testtools/micromock/tools/micromockgenerator/micromockgenerator.cpp (361 lines of code) (raw):

// Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. #include "stdafx.h" #include "string" #include "sstream" #include "fstream" namespace std { typedef std::basic_string<TCHAR> tstring; typedef std::basic_ostringstream<TCHAR> tostringstream; } using namespace std; const TCHAR* fileHeader = _T("// Copyright (c) Microsoft. All rights reserved.\n") _T("// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n") _T("\n") _T("// THIS FILE IS AUTOGENERATED!\n") _T("// DO NOT EDIT!\n") _T("//\n") _T("\n") _T("#ifndef MICROMOCKCALLMACROS_H\n") _T("#define MICROMOCKCALLMACROS_H\n") _T("\n") _T("#pragma once\n") _T("\n"); void GenerateMockCallMacros(_In_ size_t supportedArgCount) { FILE* outFile = NULL; _tfopen_s(&outFile, _T("micromockcallmacros.h"), _T("wt")); if (NULL != outFile) { _ftprintf(outFile, fileHeader); for (UINT currentArgCount = 0; currentArgCount <= supportedArgCount; currentArgCount++) { tostringstream argsWithValuesSignatureStream; tostringstream argAndValuesMacroStream; tstring argsWithValuesSignature; tstring argAndValuesMacroString; for (UINT i = 1; i <= currentArgCount; i++) { if (i > 1) { argsWithValuesSignatureStream << _T(", "); } argsWithValuesSignatureStream << _T("arg") << i << _T("Type arg") << i << _T("Value"); argAndValuesMacroStream << _T(", arg") << i << _T("Type, arg") << i << _T("Value"); } argsWithValuesSignature = argsWithValuesSignatureStream.str(); argAndValuesMacroString = argAndValuesMacroStream.str(); _ftprintf(outFile, _T("#define MOCK_ANY_METHOD_%u(static_, STATIC_, prefix, resultType, name%s) \\\n"), currentArgCount, argAndValuesMacroString.c_str()); _ftprintf(outFile, _T("static_ CMockMethodCall<resultType>& prefix Expected_##name(%s) \\\n"), argsWithValuesSignature.c_str()); _ftprintf(outFile, _T("{ \\\n")); if (currentArgCount > 0) { _ftprintf(outFile, _T(" CMockCallArgumentBase* args[%u]; \\\n"), currentArgCount); } for (UINT i = 1; i <= currentArgCount; i++) { _ftprintf(outFile, _T(" args[%u] = new CMockCallArgument<arg%uType>(arg%uValue); \\\n"), i - 1, i, i); } _ftprintf(outFile, _T(" CMockMethodCall<resultType>* mockMethodCall = \\\n")); _ftprintf(outFile, _T(" new CMockMethodCall<resultType>(_T(#name), %u, %s); \\\n"), currentArgCount, (currentArgCount > 0) ? _T("args") : _T("NULL")); _ftprintf(outFile, _T(" RECORD_EXPECTED_##STATIC_##MOCK_CALL(mockMethodCall); \\\n")); _ftprintf(outFile, _T(" return *mockMethodCall; \\\n")); _ftprintf(outFile, _T("} \\\n")); _ftprintf(outFile, _T("static_ resultType prefix name(%s) \\\n"), argsWithValuesSignature.c_str()); _ftprintf(outFile, _T("{ \\\n")); if (currentArgCount > 0) { _ftprintf(outFile, _T(" CMockCallArgumentBase* args[%u]; \\\n"), currentArgCount); } for (UINT i = 1; i <= currentArgCount; i++) { _ftprintf(outFile, _T(" args[%u] = new CMockCallArgument<arg%uType>(arg%uValue); \\\n"), i - 1, i, i); } _ftprintf(outFile, _T(" CMockMethodCallBase* mockMethodCall = \\\n")); _ftprintf(outFile, _T(" new CMockMethodCall<resultType>(_T(#name), %u, %s); \\\n"), currentArgCount, (currentArgCount > 0) ? _T("args") : _T("NULL")); _ftprintf(outFile, _T(" bool failed=false; \\\n")); _ftprintf(outFile, _T(" CMockValueBase* result = RECORD_ACTUAL_##STATIC_##MOCK_CALL(mockMethodCall, &failed); \\\n")); _ftprintf(outFile, _T(" if((result!=NULL)&&(failed)) return dynamic_cast<CMockValue<resultType>*>(result)->GetValue();\n")); _ftprintf(outFile, _T("\n")); // regular member function mock _ftprintf(outFile, _T("#define MOCK_METHOD_%u(prefix, resultType, name%s) \\\n"), currentArgCount, argAndValuesMacroString.c_str()); _ftprintf(outFile, _T("MOCK_ANY_METHOD_%u(,,prefix, resultType, name%s) \n"), currentArgCount, argAndValuesMacroString.c_str()); _ftprintf(outFile, _T("\n")); // static function mock _ftprintf(outFile, _T("#define MOCK_STATIC_METHOD_%u(prefix, resultType, name%s) \\\n"), currentArgCount, argAndValuesMacroString.c_str()); _ftprintf(outFile, _T("MOCK_ANY_METHOD_%u(static, STATIC_, prefix, resultType, name%s) \n"), currentArgCount, argAndValuesMacroString.c_str()); _ftprintf(outFile, _T("\n")); // global mock declaration _ftprintf(outFile, _T("#define DECLARE_GLOBAL_MOCK_METHOD_%u(mockClass, prefix, resultType, name%s) \\\n"), currentArgCount, argAndValuesMacroString.c_str()); _ftprintf(outFile, _T("prefix resultType name(%s) \\\n"), argsWithValuesSignature.c_str()); _ftprintf(outFile, _T("{ \\\n")); _ftprintf(outFile, _T(" return mockClass::name(")); for (UINT i = 1; i <= currentArgCount; i++) { if (i > 1) { _ftprintf(outFile, _T(",")); } _ftprintf(outFile, _T("arg%uValue"), i); } _ftprintf(outFile, _T(");\\\n")); _ftprintf(outFile, _T("} \\\n")); _ftprintf(outFile, _T("\n")); } _ftprintf(outFile, _T("#endif // MICROMOCKCALLMACROS_H\n")); _ftprintf(outFile, _T("\n")); fclose(outFile); } } const char* CfileHeader = "// Copyright (c) Microsoft. All rights reserved.\n" "// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n" "\n" "\n" "// THIS FILE IS AUTOGENERATED!\n" "// DO NOT EDIT!\n" "\n" "\n" "#ifndef TIMEDISCRETEMICROMOCKCALLMACROS_H\n" "#define TIMEDISCRETEMICROMOCKCALLMACROS_H\n" "\n" "#pragma once\n" "\n"; #define tab (char)(9) void GenerateTimeDiscreteMockCallMacros(_In_ size_t supportedArgCount) { unsigned int i,j; /*intended as ANSI, non TCHAR, since it produces C++ source code*/ ofstream fout("timediscretemicromockcallmacros.h"); fout<<CfileHeader<<endl; for(i=0;i<supportedArgCount;i++) { fout<<"#define MOCK_TD_METHOD_"<<i<<"(prefix, resultType, name"; //write the argument list... for(j=1;j<=i;j++) { fout<<", arg"<<j<<"Type, arg"<<j<<"Value"; } //close the argument list fout<<") \\"<<endl; //MOCK_METHOD1... same thing fout<<tab<<"MOCK_METHOD_"<<i<<"(prefix, resultType, name"; for(j=1;j<=i;j++) { fout<<", arg"<<j<<"Type, arg"<<j<<"Value"; } fout<<")\\"<<endl; fout<<tab<<"mockMethodCall->AddExtraCallArgument(new CMockCallArgument<UINT32>(MOCK_TIMEPROVIDER(__FUNCTION__)));\\"<<endl; fout<<tab<<"result = REMATCH_ACTUAL_STATIC_MOCK_CALL(mockMethodCall);\\"<<endl; fout<<endl; fout << "#define MOCK_STATIC_TD_METHOD_" << i << "(prefix, resultType, name"; //write the argument list... for (j = 1; j <= i; j++) { fout << ", arg" << j << "Type, arg" << j << "Value"; } //close the argument list fout << ") \\" << endl; //MOCK_METHOD_n ... same thing fout << tab << "MOCK_STATIC_METHOD_" << i << "(prefix, resultType, name"; for (j = 1; j <= i; j++) { fout << ", arg" << j << "Type, arg" << j << "Value"; } fout << ")\\" << endl; fout << tab << "mockMethodCall->AddExtraCallArgument(new CMockCallArgument<UINT32>(MOCK_TIMEPROVIDER(__FUNCTION__)));\\" << endl; fout << tab << "result = REMATCH_ACTUAL_STATIC_MOCK_CALL(mockMethodCall);\\" << endl; fout << endl; } fout<<"#define STIM_CALL_AT(var, time, ...) var.__VA_ARGS__.SetTime(time, var.getAndIncOrder(time))"<<endl; fout<<endl; for(i=0;i<supportedArgCount;i++) { fout<<"#define DECLARE_STIM_STATIC_TD_METHOD_"<<i<<"(prefix, resultType, name"; for(j=1;j<=i;j++) { fout<<", arg"<<j<<"Type, arg"<<j<<"Value"; } fout<<")\\"<<endl; fout<<"class pFunctionCall_Wrapper_##name \\"<<endl; fout<<"{\\"<<endl; fout<<tab<<"public:\\"<<endl; fout<<tab<<"typedef resultType (*pRealFunctionType)("; for(j=1;j<=i;j++) { fout<<"arg"<<j<<"Type arg"<<j<<"Value"; if((i>0) &&(j<i))fout<<", "; } fout<<");\\"<<endl; fout<<tab<<"static pRealFunctionType realFunction;\\"<<endl; fout<<"};\\"<<endl; fout<<"pFunctionCall_Wrapper_##name::pRealFunctionType pFunctionCall_Wrapper_##name::realFunction = ::name; /*so this never can go to a header*/"<<endl; fout<<endl; fout<<"#define STIM_STATIC_TD_METHOD_"<<i<<"(prefix, resultType, name "; for(j=1;j<=i;j++) { fout<<", arg"<<j<<"Type, arg"<<j<<"Value"; } fout<<") call"<<i<<"Arg<resultType, "; for(j=1;j<=i;j++) { fout<<"arg"<<j<<"Type, "; } fout<<"pFunctionCall_Wrapper_##name > name;"<<endl; fout<<endl; } for(i=0;i<supportedArgCount;i++) { fout<<"template<typename resultType,"; for(j=1;j<=i;j++) { fout<<"typename arg"<<j<<"Type, "; } fout<<"class C>"; fout<<"class call"<<i<<"Arg : public canPlay"<<endl; fout<<"{"<<endl; fout<<"private:"<<endl; fout<<tab<<"class timeS"<<endl; fout<<tab<<"{"<<endl; fout<<tab<<"public:"<<endl; fout<<tab<<tab<<"timeS("; for(j=1;j<=i;j++) { fout<<"arg"<<j<<"Type arg"<<j<<"Value"; if((i>0) && (j<i)) fout<<", "; } fout<<"): "<<endl; fout<<tab<<tab<<"time(0), order(0)"; for(j=1;j<=i;j++) { fout<<", arg"<<j<<"(arg"<<j<<"Value)"; } fout<<endl; fout<<tab<<tab<<"{"<<endl; fout<<tab<<tab<<"}"<<endl; fout<<tab<<tab<<"UINT32 time;"<<endl; fout<<tab<<tab<<"UINT32 order;"<<endl; for(j=1;j<=i;j++) { fout<<tab<<tab<<"valueHolder<arg"<<j<<"Type> arg"<<j<<";"<<endl; } fout<<tab<<"};"<<endl; fout<<tab<<"std::vector<timeS> allCalls;"<<endl; fout<<"public:"<<endl; fout<<tab<<"call"<<i<<"Arg()"<<endl; fout<<tab<<"{"<<endl; fout<<tab<<tab<<"stims_base::registerCallXArg(this);"<<endl; fout<<tab<<"}"<<endl; fout<<endl; fout<<tab<<"virtual ~call"<<i<<"Arg<resultType, "; for(j=1;j<=i;j++) { fout<<"arg"<<j<<"Type, "; } fout<<" C>()"<<endl; fout<<tab<<"{"<<endl; fout<<tab<<"}"<<endl; fout<<tab<<"virtual void PlayTick(_In_ UINT32 tick, _In_ UINT32 order)"<<endl; fout<<tab<<"{"<<endl; fout<<tab<<tab<<"for(UINT32 i=0; i<allCalls.size();i++)"<<endl; fout<<tab<<tab<<"{"<<endl; fout<<tab<<tab<<tab<<"if((allCalls[i].time==tick)&&(allCalls[i].order==order))"<<endl; fout<<tab<<tab<<tab<<"{"<<endl; fout<<tab<<tab<<tab<<tab<<"C::realFunction("; for(j=1;j<=i;j++) { fout<<"allCalls[i].arg"<<j; if((i>0)&&(j<i)) fout<<", "; } fout<<");"<<endl; fout<<tab<<tab<<tab<<"}"<<endl; fout<<tab<<tab<<"}"<<endl; fout<<tab<<"}"<<endl; fout<<endl; fout<<tab<<"call"<<i<<"Arg<resultType, "; for(j=1;j<=i;j++) { fout<<"arg"<<j<<"Type, "; } fout<<"C>& SetTime(_In_ UINT32 time, _In_ UINT32 order)"<<endl; fout<<tab<<"{"<<endl; fout<<tab<<tab<<"if(allCalls.size()==0)"<<endl; fout<<tab<<tab<<"{"<<endl; fout<<tab<<tab<<tab<<"throw CMicroMockException(MICROMOCK_EXCEPTION_SET_TIME_BEFORE_CALL, _T(\"using SetTime before the call has been defined usually indicates an error in test code\"));"<<endl; fout<<tab<<tab<<"}"<<endl; fout<<tab<<tab<<"else"<<endl; fout<<tab<<tab<<"{"<<endl; fout<<tab<<tab<<tab<<"allCalls[allCalls.size()-1].time=time;"<<endl; fout<<tab<<tab<<tab<<"allCalls[allCalls.size()-1].order=order;"<<endl; fout<<tab<<tab<<"}"<<endl; fout<<tab<<tab<<"return *this;"<<endl; fout<<tab<<"}"<<endl; fout<<endl; fout<<tab<<"call"<<i<<"Arg<resultType, "; for(j=1;j<=i;j++) { fout<<"arg"<<j<<"Type, "; } fout<<" C>& operator()("; for(j=1;j<=i;j++) { fout<<"arg"<<j<<"Type arg"<<j; if((i>0)&&(j<i)) fout<<","; } fout<<")"<<endl; fout<<tab<<"{"<<endl; fout<<tab<<tab<<"timeS s"<<((i==0)?"":"("); for(j=1;j<=i;j++) { fout<<"arg"<<j; if((i>0)&&(j<i)) fout<<", "; } fout<<((i==0)?"":")")<<";"<<endl; fout<<tab<<tab<<"allCalls.push_back(s); /*time is updated \"later\" by chaining*/"<<endl; fout<<tab<<tab<<"return *this;"<<endl; fout<<tab<<"}"<<endl; fout<<endl; if(i>0) { fout<<tab<<"call"<<i<<"Arg<resultType, "; for(j=1;j<=i;j++) { fout<<"arg"<<j<<"Type, "; } fout<<" C>& setArraySize(_In_ UINT32 parameter, _In_ size_t nElements)"<<endl; fout<<tab<<"{"<<endl; fout<<tab<<tab<<"if(allCalls.size()==0)"<<endl; fout<<tab<<tab<<"{"<<endl; fout<<tab<<tab<<tab<<"throw CMicroMockException(MICROMOCK_EXCEPTION_SET_ARRAY_SIZE_BEFORE_CALL, _T(\"using setArraySize before the call has been defined usually indicates an error in test code\"));"<<endl; fout<<tab<<tab<<"}"<<endl; fout<<tab<<tab<<"else"<<endl; fout<<tab<<tab<<"{"<<endl; fout<<tab<<tab<<tab<<"timeS& s = allCalls[allCalls.size()-1]; /*get the last element*/"<<endl; fout<<tab<<tab<<tab<<"switch(parameter)"<<endl; fout<<tab<<tab<<tab<<"{"<<endl; for(j=1;j<=i;j++) { fout<<tab<<tab<<tab<<tab<<"case "<<j<<":"<<endl; fout<<tab<<tab<<tab<<tab<<"{"<<endl; fout<<tab<<tab<<tab<<tab<<tab<<"s.arg"<<j<<".setArraySize(nElements);"<<endl; fout<<tab<<tab<<tab<<tab<<tab<<"break;"<<endl; fout<<tab<<tab<<tab<<tab<<"}"<<endl; } fout<<tab<<tab<<tab<<tab<<"default:"<<endl; fout<<tab<<tab<<tab<<tab<<"{"<<endl; fout<<tab<<tab<<tab<<tab<<tab<<"ASSERT_FAIL(_T(\"there are no parameters so big\"));"<<endl; fout<<tab<<tab<<tab<<tab<<"}"<<endl; fout<<tab<<tab<<tab<<"}"<<endl; fout<<tab<<tab<<tab<<"return *this;"<<endl; fout<<tab<<tab<<"}"<<endl; fout<<tab<<"}"<<endl; } fout<<"};"<<endl; fout<<endl; } fout<<"#endif // TIMEDISCRETEMICROMOCKCALLMACROS_H"<<endl; fout<<endl; fout.close(); } int __cdecl _tmain(const int argc, const _TCHAR* argv[]) { UNREFERENCED_PARAMETER(argc); UNREFERENCED_PARAMETER(argv); size_t supportedArgCount = 16; _tprintf(_T("MicroMock code generator.\n")); _tprintf(_T("GENERATED OUTPUT HAS TO BE HAND COPIED TO THE DESTINATION!!! (because building out of source tree).\n")); _tprintf(_T("Generating MicroMock call macros...\n")); GenerateMockCallMacros(supportedArgCount); _tprintf(_T("Generating TimeDiscreteMicroMock call macros...\n")); GenerateTimeDiscreteMockCallMacros(supportedArgCount); _tprintf(_T("Done.\n")); return 0; }