123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717 |
- /**
- * Tencent is pleased to support the open source community by making Tars available.
- *
- * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
- *
- * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * https://opensource.org/licenses/BSD-3-Clause
- *
- * Unless required by applicable law or agreed to in writing, software distributed
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
- #include "tars2case.h"
- #include "util/tc_md5.h"
- #include "util/tc_file.h"
- #include "util/tc_common.h"
- #include <string>
- //////////////////////////////////////////////////////////////////////////////////
- //
- Tars2Case::Tars2Case() : _jsonCase(false), _webCase(false)
- {
- }
- string Tars2Case::toDescStr(const TypePtr &pPtr) const
- {
- BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
- if (bPtr)
- {
- switch (bPtr->kind())
- {
- case Builtin::KindByte: return bPtr->isUnsigned() ? "byte_u" : "byte"; break;
- case Builtin::KindShort: return bPtr->isUnsigned() ? "short_u" : "short"; break;
- case Builtin::KindInt: return bPtr->isUnsigned() ? "int_u" : "int"; break;
- case Builtin::KindLong: return "long"; break;
- case Builtin::KindBool: return "bool"; break;
- case Builtin::KindFloat: return "float"; break;
- case Builtin::KindDouble: return "double"; break;
- case Builtin::KindString: return "string"; break;
- default: assert(false); break;
- }
- }
- VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
- if (vPtr) return "vector";
- MapPtr mPtr = MapPtr::dynamicCast(pPtr);
- if (mPtr) return "map";
- StructPtr sPtr = StructPtr::dynamicCast(pPtr);
- if (sPtr) return "struct";
- EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
- if (ePtr) return "int";
- return "void";
- }
- string Tars2Case::toStr(const TypePtr &pPtr) const
- {
- BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
- if (bPtr) return tostrBuiltin(bPtr);
- VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
- if (vPtr) return tostrVector(vPtr);
- MapPtr mPtr = MapPtr::dynamicCast(pPtr);
- if (mPtr) return tostrMap(mPtr);
- StructPtr sPtr = StructPtr::dynamicCast(pPtr);
- if (sPtr) return tostrStruct(sPtr);
- EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
- if (ePtr) return tostrEnum(ePtr);
- if (!pPtr) return "void";
- assert(false);
- return "";
- }
- string Tars2Case::toCase(const TypePtr &pPtr, const string& varName) const
- {
- BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
- if (bPtr) return tocaseBuiltin(bPtr, varName);
- VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
- if (vPtr) return tocaseVector(vPtr, varName);
- MapPtr mPtr = MapPtr::dynamicCast(pPtr);
- if (mPtr) return tocaseMap(mPtr, varName);
- StructPtr sPtr = StructPtr::dynamicCast(pPtr);
- if (sPtr) return tocaseStruct(sPtr, varName);
- EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
- if (ePtr) return tocaseEnum(ePtr, varName);
- if (!pPtr) return "void";
- assert(false);
- return "";
- }
- /*******************************BuiltinPtr********************************/
- string Tars2Case::tostrBuiltin(const BuiltinPtr &pPtr) const
- {
- string s;
- switch (pPtr->kind())
- {
- case Builtin::KindBool:
- s = "bool";
- break;
- case Builtin::KindByte:
- s = pPtr->isUnsigned() ? "short" : "byte";
- break;
- case Builtin::KindShort:
- s = pPtr->isUnsigned() ? "int" : "short";
- break;
- case Builtin::KindInt:
- s = pPtr->isUnsigned() ? "long" : "int";
- break;
- case Builtin::KindLong:
- s = "long";
- break;
- case Builtin::KindFloat:
- s = "float";
- break;
- case Builtin::KindDouble:
- s = "double";
- break;
- case Builtin::KindString:
- s = "string";
- break;
- case Builtin::KindVector:
- s = "vector";
- break;
- case Builtin::KindMap:
- s = "map";
- break;
- default:
- assert(false);
- break;
- }
- return s;
- }
- string Tars2Case::tocaseBuiltin(const BuiltinPtr &pPtr, const string& varName) const
- {
- string s;
- switch (pPtr->kind())
- {
- case Builtin::KindBool:
- s = "true";
- break;
- case Builtin::KindByte:
- s = "0";
- break;
- case Builtin::KindShort:
- s = "0";
- break;
- case Builtin::KindInt:
- s = "0";
- break;
- case Builtin::KindLong:
- s = "0";
- break;
- case Builtin::KindFloat:
- s = "0.0";
- break;
- case Builtin::KindDouble:
- s = "0.00";
- break;
- case Builtin::KindString:
- s = "key";
- break;
- /*
- case Builtin::KindVector:
- s = "vector";
- break;
- case Builtin::KindMap:
- s = "map";
- break;
- */
- default:
- assert(false);
- break;
- }
- return s;
- }
- /*******************************VectorPtr********************************/
- string Tars2Case::tostrVector(const VectorPtr &pPtr) const
- {
- string s;
- BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
- s = "vector" + string("<") + toStr(pPtr->getTypePtr()) + ">";
- return s;
- }
- string Tars2Case::tocaseVector(const VectorPtr &pPtr, const string& varName) const
- {
- string s;
- BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
- s = string("<");
- for(int i = 0; i < 2; i++) {
- if(i != 0) {
- s += ",";
- }
- s += toCase(pPtr->getTypePtr(), varName);
- }
- s += ">";
- return s;
- }
- string Tars2Case::tostrMap(const MapPtr &pPtr, bool bNew) const
- {
- string s = "map";
- s += string("<") + toStr(pPtr->getLeftTypePtr()) + "," + toStr(pPtr->getRightTypePtr()) + ">";
- return s;
- }
- string Tars2Case::tocaseMap(const MapPtr &pPtr, const string& varName) const
- {
- string s = string("[");
- for(int i = 0; i < 2; i++) {
- if(i != 0) {
- s += ",";
- }
- s += toCase(pPtr->getLeftTypePtr(), varName) + "=" + toCase(pPtr->getRightTypePtr(), varName);
- }
- s += "]";
- return s;
- }
- string Tars2Case::tostrStruct(const StructPtr &pPtr) const
- {
- vector<TypeIdPtr>& members = pPtr->getAllMemberPtr();
- string s;
- //是否生成tag和require等信息
- bool genTag = false;
- for(size_t i = 0; i < members.size(); i++) {
- TypeIdPtr typeId = members[i];
- if(!s.empty()) {
- s += ",";
- }
- if(i == 0) {
- if(typeId->getTag() == 0) {
- genTag = false;
- }
- else {
- genTag = true;
- }
- }
- else {
- //检查tag是否连续
- if(typeId->getTag() == members[i-1]->getTag() + 1) {
- genTag = false;
- }
- else {
- genTag = true;
- }
- }
- if(genTag) {
- s+=genratePrefix(typeId) + " ";
- }
- s += toStr(typeId->getTypePtr());
- }
- return "struct<" + s + ">";
- }
- string Tars2Case::tocaseStruct(const StructPtr &pPtr, const string& varName) const
- {
- vector<TypeIdPtr>& members = pPtr->getAllMemberPtr();
- string s = string("<");
- for(size_t i = 0; i < members.size(); i++) {
- if(i != 0) {
- s += ",";
- }
- s += toCase(members[i]->getTypePtr(), varName);
- }
- s += ">";
- return s;
- }
- string Tars2Case::genratePrefix(const TypeIdPtr &ptr) const
- {
- string s = TC_Common::tostr(ptr->getTag()) + " ";
- if(ptr->isRequire()) {
- s += "require";
- }
- else {
- s += "optional";
- }
- return s;
- }
- string Tars2Case::tostrEnum(const EnumPtr &pPtr) const
- {
- return "int";
- }
- string Tars2Case::tocaseEnum(const EnumPtr &pPtr, const string& varName) const
- {
- return "19";
- }
- string Tars2Case::generateTest(const ParamDeclPtr &pPtr) const
- {
- ostringstream s;
- TypePtr typePtr = pPtr->getTypeIdPtr()->getTypePtr();
- s << toStr(typePtr);
- return s.str();
- }
- string Tars2Case::generateCase(const ParamDeclPtr &pPtr) const
- {
- ostringstream s;
- TypePtr typePtr = pPtr->getTypeIdPtr()->getTypePtr();
- string varName = pPtr->getTypeIdPtr()->getId();
- s << toCase(typePtr, varName);
- return s.str();
- }
- struct SortOperation
- {
- bool operator()(const OperationPtr &o1, const OperationPtr &o2)
- {
- return o1->getId() < o2->getId();
- }
- };
- string Tars2Case::generateTest(const InterfacePtr &pPtr, const string& outfile) const
- {
- ostringstream s;
- vector<OperationPtr>& vOperation = pPtr->getAllOperationPtr();
- std::sort(vOperation.begin(), vOperation.end(), SortOperation());
- //生成客户端接口的声明
- TC_File::makeDirRecursive(_baseDir);
- for (size_t i = 0; i < vOperation.size(); i++)
- {
- string sCase = "";
- string sInParams = "";
- string sOutParams = "";
- vector<ParamDeclPtr>& vParamDecl = vOperation[i]->getAllParamDeclPtr();
- for (size_t j = 0; j < vParamDecl.size(); j++)
- {
- if(vParamDecl[j]->isOut()) {
- sOutParams += (sOutParams.empty() ? "" : "|") + generateTest(vParamDecl[j]);
- }
- else {
- sCase += (sCase.empty() ? "" : "\r\n") + generateCase(vParamDecl[j]);
- sInParams += (sInParams.empty() ? "" : "|") + generateTest(vParamDecl[j]);
- }
- }
- ostringstream sc;
- sc << sInParams << endl << "#### 隔离符 ####" << endl << sCase << endl;
- string filecase = _baseDir + "/" + vOperation[i]->getId() + ".case";
- TC_File::save2file(filecase, sc.str());
- }
- return s.str();
- }
- JsonValuePtr Tars2Case::toJsonBuiltin(const BuiltinPtr &pPtr) const
- {
- JsonValuePtr p;
- switch (pPtr->kind())
- {
- case Builtin::KindBool:
- p = JsonOutput::writeJson(true);
- break;
- case Builtin::KindByte:
- p = JsonOutput::writeJson(8);
- break;
- case Builtin::KindShort:
- p = JsonOutput::writeJson(16);
- break;
- case Builtin::KindInt:
- p = JsonOutput::writeJson(32);
- break;
- case Builtin::KindLong:
- p = JsonOutput::writeJson(64);
- break;
- case Builtin::KindFloat:
- p = JsonOutput::writeJson(1.01);
- break;
- case Builtin::KindDouble:
- p = JsonOutput::writeJson((double)2.0000005);
- break;
- case Builtin::KindString:
- p = JsonOutput::writeJson(string("string"));
- break;
- default:
- assert(false);
- break;
- }
- return p;
- }
- JsonValuePtr Tars2Case::toJsonEnum(const EnumPtr &pPtr) const
- {
- return JsonOutput::writeJson(string("int32"));
- }
- JsonValueArrayPtr Tars2Case::toJsonVector(const VectorPtr &pPtr) const
- {
- JsonValueArrayPtr p = new JsonValueArray();
- JsonValuePtr p1 = generateJson(pPtr->getTypePtr());
- p->push_back(p1);
- p->push_back(p1);
- return p;
- }
- JsonValueObjPtr Tars2Case::toJsonMap(const MapPtr &pPtr) const
- {
- JsonValueObjPtr p = new JsonValueObj();
- BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getLeftTypePtr());
- if (bPtr)
- {
- p->value["key"] = generateJson(pPtr->getRightTypePtr());
- // p->value[tocaseBuiltin(bPtr, "")] = generateJson(pPtr->getRightTypePtr());
- }
- return p;
- }
- JsonValueObjPtr Tars2Case::toJsonStruct(const StructPtr &pPtr) const
- {
- JsonValueObjPtr p = new JsonValueObj();
- vector<TypeIdPtr>& members = pPtr->getAllMemberPtr();
- //是否生成tag和require等信息
- for(size_t i = 0; i < members.size(); i++)
- {
- TypeIdPtr typeId = members[i];
- string keyName = typeId->getId();
- p->value[keyName] = generateJson(typeId->getTypePtr());
- }
- return p;
- }
- JsonValuePtr Tars2Case::generateJson(const TypePtr &pPtr) const
- {
- BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
- if (bPtr) return toJsonBuiltin(bPtr);
- VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
- if (vPtr) return toJsonVector(vPtr);
- MapPtr mPtr = MapPtr::dynamicCast(pPtr);
- if (mPtr) return toJsonMap(mPtr);
- StructPtr sPtr = StructPtr::dynamicCast(pPtr);
- if (sPtr) return toJsonStruct(sPtr);
- EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
- if (ePtr) return toJsonEnum(ePtr);
- assert(false);
- return NULL;
- }
- JsonValuePtr Tars2Case::toJsonDescEnum(const EnumPtr &pPtr) const
- {
- return JsonOutput::writeJson(string("0"));
- }
- JsonValuePtr Tars2Case::toJsonDescVector(const VectorPtr &pPtr) const
- {
- JsonValueObjPtr p = new JsonValueObj();
- string name = "0_vector_" + toDescStr(pPtr->getTypePtr());
- p->value[name] = generateJsonDesc(pPtr->getTypePtr());
- return p;
- }
- JsonValuePtr Tars2Case::toJsonDescMap(const MapPtr &pPtr) const
- {
- string name;
- JsonValueObjPtr p = new JsonValueObj();
- name = "0_map_" + toDescStr(pPtr->getLeftTypePtr());
- p->value[name] = generateJsonDesc(pPtr->getLeftTypePtr());
- name = "1_map_" + toDescStr(pPtr->getRightTypePtr());
- p->value[name] = generateJsonDesc(pPtr->getRightTypePtr());
- return p;
- }
- JsonValuePtr Tars2Case::toJsonDescStruct(const StructPtr &pPtr) const
- {
- JsonValueObjPtr p = new JsonValueObj();
- vector<TypeIdPtr>& members = pPtr->getAllMemberPtr();
- //是否生成tag和require等信息
- for(size_t i = 0; i < members.size(); i++)
- {
- ostringstream osd;
- osd << members[i]->getTag() << "_" << members[i]->getId() << "_" << toDescStr(members[i]->getTypePtr());
- p->value[osd.str()] = generateJsonDesc(members[i]);
- }
- return p;
- }
- JsonValuePtr Tars2Case::generateJsonDesc(const TypePtr &pPtr) const
- {
- BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr);
- if (bPtr) return JsonOutput::writeJson(bPtr->def());
- VectorPtr vPtr = VectorPtr::dynamicCast(pPtr);
- if (vPtr) return toJsonDescVector(vPtr);
- MapPtr mPtr = MapPtr::dynamicCast(pPtr);
- if (mPtr) return toJsonDescMap(mPtr);
- StructPtr sPtr = StructPtr::dynamicCast(pPtr);
- if (sPtr) return toJsonDescStruct(sPtr);
- EnumPtr ePtr = EnumPtr::dynamicCast(pPtr);
- if (ePtr) return toJsonDescEnum(ePtr);
- assert(false);
- return NULL;
- }
- JsonValuePtr Tars2Case::generateJsonDesc(const TypeIdPtr &pPtr) const
- {
- BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr());
- if (bPtr) return JsonOutput::writeJson(pPtr->hasDefault() ? pPtr->def() : bPtr->def());
- return generateJsonDesc(pPtr->getTypePtr());
- }
- string Tars2Case::generateDesc(const InterfacePtr &pPtr, const string& outfile) const
- {
- ostringstream s;
- vector<OperationPtr>& vOperation = pPtr->getAllOperationPtr();
- std::sort(vOperation.begin(), vOperation.end(), SortOperation());
- //生成客户端接口的声明
- TC_File::makeDirRecursive(_baseDir);
- for (size_t i = 0; i < vOperation.size(); i++)
- {
- JsonValueObjPtr inDesc = new JsonValueObj();
- JsonValueObjPtr inParam = new JsonValueObj();
- vector<ParamDeclPtr>& vParamDecl = vOperation[i]->getAllParamDeclPtr();
- for (size_t j = 0; j < vParamDecl.size(); j++)
- {
- ostringstream osd;
- TypeIdPtr& p = vParamDecl[j]->getTypeIdPtr();
- osd << p->getTag() << "_" << p->getId() << "_" << toDescStr(p->getTypePtr());
- if(!vParamDecl[j]->isOut())
- {
- inDesc->value[osd.str()] = generateJsonDesc(p);
- inParam->value[p->getId()] = generateJson(vParamDecl[j]->getTypeIdPtr()->getTypePtr());
- }
- }
- string filedesc = _baseDir + "/" + vOperation[i]->getId() + ".desc";
- string filecase = _baseDir + "/" + vOperation[i]->getId() + ".case";
- TC_File::save2file(filedesc, TC_Json::writeValue(inDesc));
- TC_File::save2file(filecase, TC_Json::writeValue(inParam));
- }
- return s.str();
- }
- string Tars2Case::generateJson(const InterfacePtr &pPtr, const string& outfile) const
- {
- ostringstream s;
- vector<OperationPtr>& vOperation = pPtr->getAllOperationPtr();
- std::sort(vOperation.begin(), vOperation.end(), SortOperation());
- // 生成客户端接口的声明
- JsonValueObjPtr v = new JsonValueObj();
- // JsonValueArrayPtr v = new JsonValueArray();
- for (size_t i = 0; i < vOperation.size(); i++)
- {
- string intCaseValues = "";
- string intCaseParams = "";
- string outCaseParams = "";
- JsonValueObjPtr inDesc = new JsonValueObj();
- JsonValueObjPtr outDesc = new JsonValueObj();
- JsonValueObjPtr inParam = new JsonValueObj();
- JsonValueObjPtr outParam = new JsonValueObj();
- vector<ParamDeclPtr>& vParamDecl = vOperation[i]->getAllParamDeclPtr();
- for (size_t j = 0; j < vParamDecl.size(); j++)
- {
- ostringstream osd;
- TypeIdPtr& p = vParamDecl[j]->getTypeIdPtr();
- osd << p->getTag() << "_" << p->getId() << "_" << toDescStr(p->getTypePtr());
- if(vParamDecl[j]->isOut())
- {
- outCaseParams += (outCaseParams.empty() ? "" : "|") + generateTest(vParamDecl[j]);
- outDesc->value[osd.str()] = generateJsonDesc(p->getTypePtr());
- outParam->value[p->getId()] = generateJson(p->getTypePtr());
- }
- else
- {
- intCaseValues += (intCaseValues.empty() ? "" : "<br>") + generateCase(vParamDecl[j]);
- intCaseParams += (intCaseParams.empty() ? "" : "|") + generateTest(vParamDecl[j]);
- inDesc->value[osd.str()] = generateJsonDesc(p->getTypePtr());
- inParam->value[p->getId()] = generateJson(vParamDecl[j]->getTypeIdPtr()->getTypePtr());
- }
- }
- JsonValueObjPtr p = new JsonValueObj();
- p->value["funinput"] = inParam;
- p->value["funoutput"] = outParam;
- p->value["descinput"] = inDesc;
- p->value["descoutput"] = outDesc;
- p->value["rettype"] = JsonOutput::writeJson(toStr(vOperation[i]->getReturnPtr()->getTypePtr()));
- p->value["funintpara"] = JsonOutput::writeJson(intCaseParams);
- p->value["funintvals"] = JsonOutput::writeJson(intCaseValues);
- p->value["funoutpara"] = JsonOutput::writeJson(outCaseParams);
- v->value[vOperation[i]->getId()] = JsonValuePtr::dynamicCast(p);
- }
- if (_baseDir.empty())
- {
- cout << TC_Json::writeValue(v) << endl;
- }
- else
- {
- string filetest = _baseDir + "/" + (outfile.empty() ? pPtr->getId() : outfile) + ".json";
- TC_File::makeDirRecursive(_baseDir);
- TC_File::save2file(filetest, TC_Json::writeValue(v));
- }
- return TC_Json::writeValue(v);
- }
- /******************************Tars2Case***************************************/
- void Tars2Case::generateFile(const ContextPtr &pPtr, const string& outfile) const
- {
- ostringstream s;
- vector<NamespacePtr> namespaces = pPtr->getNamespaces();
- for (size_t i = 0; i < namespaces.size(); i++)
- {
- vector<InterfacePtr> &is = namespaces[i]->getAllInterfacePtr();
- for (size_t j = 0; j < is.size(); j++)
- {
- if (_webCase)
- {
- // 生成TarsWeb需要的用例
- generateJson(is[j], outfile);
- }
- else if (_jsonCase)
- {
- generateDesc(is[j], outfile);
- }
- else
- {
- // 生成Tars压测用例的文件
- generateTest(is[j], outfile);
- }
- }
- }
- }
- void Tars2Case::createFile(const string &tarsfile, const string& outfile)
- {
- std::vector<ContextPtr> contexts = g_parse->getContexts();
- for (size_t i = 0; i < contexts.size(); i++)
- {
- if (tarsfile == contexts[i]->getFileName())
- {
- generateFile(contexts[i], outfile);
- }
- }
- }
- void Tars2Case::setBaseDir(const string &dir)
- {
- _baseDir = dir;
- }
- void Tars2Case::setJsonCase(bool jsonCase)
- {
- _jsonCase = jsonCase;
- }
- void Tars2Case::setWebSupport(bool webCase)
- {
- _webCase = webCase;
- }
- string Tars2Case::getFilePath(const string &ns) const
- {
- return _baseDir + "/" + ns + "/";
- }
|