diff --git a/server/src/printers/Printer.cpp b/server/src/printers/Printer.cpp index 1b1bf6cbc..700a5c81d 100644 --- a/server/src/printers/Printer.cpp +++ b/server/src/printers/Printer.cpp @@ -393,9 +393,9 @@ namespace printer { auto methodCopy = method; methodCopy.name = method.name; - std::string stubSymbolicVarName = getStubSymbolicVarName(nameForStub); + std::string stubSymbolicVarName = StubsUtils::getStubSymbolicVarName(nameForStub); if (!types::TypesHandler::omitMakeSymbolic(method.returnType)) { - stubSymbolicVarName = getStubSymbolicVarName(methodName + "_" + nameForStub); + stubSymbolicVarName = StubsUtils::getStubSymbolicVarName(methodName + "_" + nameForStub); strDeclareArrayVar(types::Type::createArray(method.returnType), stubSymbolicVarName, types::PointerUsage::PARAMETER); } @@ -447,10 +447,6 @@ namespace printer { return ss; } - std::string Printer::getStubSymbolicVarName(const std::string &methodName) { - return methodName + PrinterUtils::KLEE_SYMBOLIC_SUFFIX; - } - Printer::Stream Printer::strKleeMakeSymbolic(const std::string &varName, bool needAmpersand, SRef pseudoName) { auto pointer = (needAmpersand ? "&" : "") + varName; auto size = "sizeof(" + varName + ")"; diff --git a/server/src/printers/Printer.h b/server/src/printers/Printer.h index b677bcb8a..6ff140842 100644 --- a/server/src/printers/Printer.h +++ b/server/src/printers/Printer.h @@ -182,8 +182,6 @@ namespace printer { const std::string &nameForStub, bool makeStatic = false); - static std::string getStubSymbolicVarName(const std::string &methodName); - Stream strKleeMakeSymbolic(SRef varName, bool needAmpersand, SRef pseudoName); static inline std::string getTypedefFunctionPointer(const std::string &parentFunctionName, diff --git a/server/src/printers/StubsPrinter.cpp b/server/src/printers/StubsPrinter.cpp index 9da64b35b..32f5f2d4b 100644 --- a/server/src/printers/StubsPrinter.cpp +++ b/server/src/printers/StubsPrinter.cpp @@ -53,7 +53,7 @@ Stubs printer::StubsPrinter::genStubFile(const tests::Tests &tests, } if (!typesHandler.omitMakeSymbolic(methodCopy.returnType)) { - std::string stubSymbolicVarName = getStubSymbolicVarName(method.name); + std::string stubSymbolicVarName = StubsUtils::getStubSymbolicVarName(method.name); strDeclareArrayVar(types::Type::createArray(method.returnType), stubSymbolicVarName, types::PointerUsage::PARAMETER); } diff --git a/server/src/printers/StubsPrinter.h b/server/src/printers/StubsPrinter.h index d192a7ed2..4a1521c63 100644 --- a/server/src/printers/StubsPrinter.h +++ b/server/src/printers/StubsPrinter.h @@ -5,6 +5,7 @@ #include "ProjectContext.h" #include "stubs/Stubs.h" #include "types/Types.h" +#include "utils/StubsUtils.h" namespace printer { class StubsPrinter : Printer { diff --git a/server/src/printers/TestsPrinter.cpp b/server/src/printers/TestsPrinter.cpp index 2f6780f62..a623bc18e 100644 --- a/server/src/printers/TestsPrinter.cpp +++ b/server/src/printers/TestsPrinter.cpp @@ -194,7 +194,7 @@ void TestsPrinter::genCode(Tests::MethodDescription &methodDescription, static std::string getTestName(const Tests::MethodDescription &methodDescription, int testNum) { std::string renamedMethodDescription = KleeUtils::getRenamedOperator(methodDescription.name); - StringUtils::replaceAll(renamedMethodDescription, ':', '_'); + StringUtils::replaceColon(renamedMethodDescription); std::string testBaseName = methodDescription.isClassMethod() ? StringUtils::stringFormat("%s_%s", methodDescription.classObj->type.typeName(), diff --git a/server/src/types/TypesResolver.cpp b/server/src/types/TypesResolver.cpp index 3d1dcb174..3f2ff4f9b 100644 --- a/server/src/types/TypesResolver.cpp +++ b/server/src/types/TypesResolver.cpp @@ -75,7 +75,7 @@ std::string TypesResolver::getFullname(const clang::TagDecl *TD, const clang::Qu if (!fullname[parentID].empty()) { fullname[id] = fullname[parentID] + "::" + fullname[id]; if (typeDeclNeeded) { - StringUtils::replaceAll(fullname[id], "::", "_"); + StringUtils::replaceColon(fullname[id]); } } } diff --git a/server/src/utils/KleeUtils.cpp b/server/src/utils/KleeUtils.cpp index befd88de8..6a39b732d 100644 --- a/server/src/utils/KleeUtils.cpp +++ b/server/src/utils/KleeUtils.cpp @@ -84,7 +84,7 @@ namespace KleeUtils { bool needToMangle, bool isWrapped) { std::string methodNewName = methodName; - StringUtils::replaceAll(methodNewName, ':', '_'); + StringUtils::replaceColon(methodNewName); methodNewName = getRenamedOperator(methodNewName); if (isWrapped) { methodNewName += PrinterUtils::WRAPPED_SUFFIX; diff --git a/server/src/utils/StringUtils.cpp b/server/src/utils/StringUtils.cpp index 944beafe6..98d0c405a 100644 --- a/server/src/utils/StringUtils.cpp +++ b/server/src/utils/StringUtils.cpp @@ -84,6 +84,10 @@ namespace StringUtils { } } + void replaceColon(std::string &str) { + replaceAll(str, "::", "_"); + } + bool isPrintable(int code) { if (std::numeric_limits::is_signed && code < 0) { code += 256; diff --git a/server/src/utils/StringUtils.h b/server/src/utils/StringUtils.h index 1503a0b9c..58fea6e26 100644 --- a/server/src/utils/StringUtils.h +++ b/server/src/utils/StringUtils.h @@ -53,6 +53,8 @@ namespace StringUtils { void replaceAll(std::string &str, const std::string &from, const std::string &to); + void replaceColon(std::string &str); + /** * Returns true if char literal can be printed to .cpp file as is, false otherwise. * @param value - given character code diff --git a/server/src/utils/StubsUtils.cpp b/server/src/utils/StubsUtils.cpp index 0765ef99a..5a8f86a02 100644 --- a/server/src/utils/StubsUtils.cpp +++ b/server/src/utils/StubsUtils.cpp @@ -16,7 +16,9 @@ namespace StubsUtils { } std::string getStubSymbolicVarName(const std::string &methodName) { - return methodName + PrinterUtils::KLEE_SYMBOLIC_SUFFIX; + std::string stubName = methodName + PrinterUtils::KLEE_SYMBOLIC_SUFFIX; + StringUtils::replaceColon(stubName); + return stubName; } std::string getFunctionPointerAsStructFieldStubName(const std::string &structName, @@ -28,6 +30,7 @@ namespace StubsUtils { } else { stubName = stubName.substr(1); } + StringUtils::replaceColon(stubName); return stubName; } } diff --git a/server/test/framework/Server_Tests.cpp b/server/test/framework/Server_Tests.cpp index d24d86e61..8107d8159 100644 --- a/server/test/framework/Server_Tests.cpp +++ b/server/test/framework/Server_Tests.cpp @@ -1986,6 +1986,44 @@ namespace { testUtils::checkStatusesCount(resultMap, tests, expectedStatusCountMap); } + TEST_F(Server_Test, Run_Tests_For_Complex_Structs) { + fs::path complex_structs_c = getTestFilePath("complex_structs.c"); + auto request = testUtils::createFileRequest(projectName, suitePath, buildDirRelativePath, + srcPaths, complex_structs_c, + GrpcUtils::UTBOT_AUTO_TARGET_PATH, true, false); + auto testGen = FileTestGen(*request, writer.get(), TESTMODE); + Status status = Server::TestsGenServiceImpl::ProcessBaseTestRequest(testGen, writer.get()); + ASSERT_TRUE(status.ok()) << status.error_message(); + EXPECT_GE(testUtils::getNumberOfTests(testGen.tests), 12); + + fs::path testsDirPath = getTestFilePath("tests"); + + fs::path complex_structs_test_cpp = Paths::sourcePathToTestPath( + utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath), + complex_structs_c); + auto testFilter = GrpcUtils::createTestFilterForFile(complex_structs_test_cpp); + auto runRequest = testUtils::createCoverageAndResultsRequest( + projectName, suitePath, testsDirPath, buildDirRelativePath, std::move(testFilter)); + + static auto coverageAndResultsWriter = + std::make_unique(nullptr); + CoverageAndResultsGenerator coverageGenerator{ runRequest.get(), + coverageAndResultsWriter.get() }; + utbot::SettingsContext settingsContext{ + true, false, 45, 0, false, false, ErrorMode::FAILING, false + }; + coverageGenerator.generate(false, settingsContext); + + EXPECT_FALSE(coverageGenerator.hasExceptions()); + ASSERT_TRUE(coverageGenerator.getCoverageMap().empty()); + + auto resultsMap = coverageGenerator.getTestResultMap(); + auto tests = coverageGenerator.getTestsToLaunch(); + + StatusCountMap expectedStatusCountMap{ { testsgen::TEST_PASSED, 12 } }; + testUtils::checkStatuses(resultsMap, tests); + } + TEST_F(Server_Test, Run_Tests_For_Input_Output_C) { fs::path input_output_c = getTestFilePath("input_output.c"); auto request = testUtils::createFileRequest(projectName, suitePath, buildDirRelativePath, diff --git a/server/test/suites/server/complex_structs.c b/server/test/suites/server/complex_structs.c index e23011d10..f0f362256 100644 --- a/server/test/suites/server/complex_structs.c +++ b/server/test/suites/server/complex_structs.c @@ -41,3 +41,7 @@ struct One alphabet(int a) { struct One res = {1, {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'}}; return res; } + +int st_access_s(struct StructWithFunctionPointer st) { + return st.s; +} diff --git a/server/test/suites/server/complex_structs.h b/server/test/suites/server/complex_structs.h index 0dd6fcf75..8c1b8e45a 100644 --- a/server/test/suites/server/complex_structs.h +++ b/server/test/suites/server/complex_structs.h @@ -6,6 +6,13 @@ struct StructWithArrays { int a[10]; }; +struct StructWithFunctionPointer { + int s; + struct FunctionPointer { + void *(*plain) (int); + } fptr; +}; + struct One { int a; char str[12]; @@ -23,8 +30,10 @@ struct Three { int struct_has_alphabet(struct One st); - char arrays_in_inner_structs(struct Three st); struct One alphabet(int a); + +int st_access_s(struct StructWithFunctionPointer st); + #endif // SIMPLE_TEST_PROJECT_COMPLEX_STRUCTS_H