diff --git a/.github/workflows/matrix.json b/.github/workflows/matrix.json index c5c9727f6..08a8be0b9 100644 --- a/.github/workflows/matrix.json +++ b/.github/workflows/matrix.json @@ -1,7 +1,7 @@ { "include": [ { - "DOCKER_TAG": "2022.10.0", + "DOCKER_TAG": "2023.10.0", "OPERATING_SYSTEM_TAG": "18.04", "LLVM_VERSION_MAJOR": "10" } diff --git a/build.sh b/build.sh index 8bca474ea..89b051303 100755 --- a/build.sh +++ b/build.sh @@ -2,7 +2,7 @@ set -e set -o pipefail pwd=$PWD -chmod +x $pwd/submodules/klee/build.sh $pwd/submodules/Bear/build.sh $pwd/server/build.sh -cd $pwd/submodules/klee && ./build.sh +chmod +x $pwd/submodules/build-klee.sh $pwd/submodules/Bear/build.sh $pwd/server/build.sh +cd $pwd/submodules && ./build-klee.sh cd $pwd/submodules/Bear && ./build.sh cd $pwd/server && ./build.sh diff --git a/docker/Dockerfile_base b/docker/Dockerfile_base index a0773df12..57b047184 100644 --- a/docker/Dockerfile_base +++ b/docker/Dockerfile_base @@ -74,7 +74,7 @@ RUN git clone --single-branch --branch "release/${LLVM_VERSION_MAJOR}.x" --depth WORKDIR $UTBOT_ALL/llvm-project RUN mkdir build && cd build \ && $UTBOT_CMAKE_BINARY \ - -DCMAKE_BUILD_TYPE="Release" \ + -DCMAKE_BUILD_TYPE=MinSizeRel \ -DCMAKE_INSTALL_PREFIX=$UTBOT_INSTALL_DIR \ -DLLVM_INCLUDE_TESTS=OFF \ -DLLVM_BINUTILS_INCDIR=$UTBOT_ALL/llvm_gold_plugin \ @@ -125,7 +125,7 @@ RUN cd $UTBOT_ALL/grpc && git submodule update --init RUN cd $UTBOT_ALL/grpc \ && mkdir -p cmake/build \ && cd cmake/build \ - && $UTBOT_CMAKE_BINARY -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX=$UTBOT_INSTALL_DIR ../.. \ + && $UTBOT_CMAKE_BINARY -DgRPC_INSTALL=ON -DgRPC_BUILD_TESTS=OFF -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_INSTALL_PREFIX=$UTBOT_INSTALL_DIR ../.. \ && make -j`nproc` \ && make install \ && cd $UTBOT_ALL \ @@ -142,9 +142,9 @@ USER utbot # Install z3 USER root -RUN git clone --single-branch -b z3-4.8.7 --depth=1 https://github.com/Z3Prover/z3.git $UTBOT_ALL/z3-src +RUN git clone --single-branch -b z3-4.8.17 --depth=1 https://github.com/Z3Prover/z3.git $UTBOT_ALL/z3-src RUN cd $UTBOT_ALL/z3-src && mkdir build && cd build && \ - $UTBOT_CMAKE_BINARY -G "Ninja" -DCMAKE_INSTALL_PREFIX=$UTBOT_INSTALL_DIR .. && \ + $UTBOT_CMAKE_BINARY -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$UTBOT_INSTALL_DIR .. && \ $UTBOT_CMAKE_BINARY --build . --target install && \ cd $UTBOT_ALL && \ rm -rf $UTBOT_ALL/z3-src @@ -171,7 +171,7 @@ RUN npm config set strict-ssl false RUN npm cache clean -f RUN sudo -E npm install -g n RUN echo insecure > ~/.curlrc -RUN sudo -E n stable +RUN sudo -E n 16 RUN sudo -E apt remove -y --purge nodejs npm # Install cmake which can generate link_commands.json. Installing cmake the second time in order to build base image faster since this cmake may be changed frequently. diff --git a/docs/contributor-guides/advanced/symbolic-stdin.md b/docs/contributor-guides/advanced/symbolic-stdin.md index 2f739b98d..0cab28cf2 100644 --- a/docs/contributor-guides/advanced/symbolic-stdin.md +++ b/docs/contributor-guides/advanced/symbolic-stdin.md @@ -249,7 +249,7 @@ TEST(regression, check_password_test_10) In the previous version, UnitTestBot didn't preprocess functions that were using `stdin` before sending the bitcode to KLEE. Having added the interactive mode, we faced difficulties: KLEE couldn't work with multiple entry points that used `stdin` in one launch. The fact is that KLEE substitutes the original entry point to POSIX wrapper, which -initializes environment and adds the `stdin`, `stdin-stat`, `stdin-read`, and `model-version` symbolic variables. +initializes environment and adds the `stdin`, `stdin_stat`, `stdin_read`, and `model_version` symbolic variables. Then KLEE launches this wrapper as if the wrapper was the initial entry point. UnitTestBot doesn't use these KLEE wrappers now. Instead, UnitTestBot creates the POSIX wrapper for every @@ -304,4 +304,4 @@ TEST(regression, file_fgetc_test_1) int actual = file_fgetc(fA, fB, fC); EXPECT_EQ(4, actual); } -``` \ No newline at end of file +``` diff --git a/server/build.sh b/server/build.sh index 07888a844..b92a4bfbd 100755 --- a/server/build.sh +++ b/server/build.sh @@ -3,6 +3,6 @@ mkdir -p build cd build -$UTBOT_CMAKE_BINARY -G "Ninja" -DCMAKE_INSTALL_PREFIX=$UTBOT_ALL/server-install .. +$UTBOT_CMAKE_BINARY -G "Ninja" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=$UTBOT_ALL/server-install .. $UTBOT_CMAKE_BINARY --build . $UTBOT_CMAKE_BINARY --install . diff --git a/server/src/KleeRunner.cpp b/server/src/KleeRunner.cpp index a9b943ac8..b22e0c061 100644 --- a/server/src/KleeRunner.cpp +++ b/server/src/KleeRunner.cpp @@ -222,7 +222,7 @@ KleeRunner::createKleeParams(const tests::TestMethod &testMethod, "--utbot", "--posix-runtime", "--skip-not-lazy-initialized", - "--type-system=CXX", + "--min-number-elements-li=1", "--fp-runtime", "--only-output-states-covering-new", "--allocate-determ", @@ -235,10 +235,12 @@ KleeRunner::createKleeParams(const tests::TestMethod &testMethod, "--check-overshift=false", "--skip-not-symbolic-objects", "--use-tbaa", + "--ubsan-runtime", "--output-dir=" + kleeOut.string() }; if (Paths::isCXXFile(testMethod.sourceFilePath)) { - argvData.emplace_back("--libcxx=true"); + argvData.emplace_back("--use-advanced-type-system=true"); +// argvData.emplace_back("--libcxx=true"); } if (settingsContext.useDeterministicSearcher) { argvData.emplace_back("--search=dfs"); diff --git a/server/src/SARIFGenerator.cpp b/server/src/SARIFGenerator.cpp index 548c9f5b4..050205047 100644 --- a/server/src/SARIFGenerator.cpp +++ b/server/src/SARIFGenerator.cpp @@ -66,9 +66,9 @@ namespace sarif { if (lineInDescriptor.empty() || lineInDescriptor[0] == '#') continue; if (isspace(lineInDescriptor[0])) { - if (key == "Stack") { + if (key == "ExecutionStack") { const std::regex stack_regex( - R"regex(\s+#(.*) in ([^ ]*) [(][^)]*[)] at ([^:]*):(\d+))regex"); + R"regex(\s+#(.*) in ([^ ]*)[(][^)]*[)] at ([^:]*):(\d+))regex"); std::smatch stack_match; if (!std::regex_match(lineInDescriptor, stack_match, stack_regex)) { LOG_S(ERROR) << "wrong `Stack` line: " << lineInDescriptor; @@ -129,10 +129,10 @@ namespace sarif { if (pos == std::string::npos) { LOG_S(ERROR) << "no key:" << lineInDescriptor; } else { - if (key == "Stack") { + if (key == "ExecutionStack") { // Check stack validity if (firstCallInStack) { - LOG_S(ERROR) << "no visible stack in descriptor:" << descriptor; + LOG_S(ERROR) << "no visible ExecutionStack in descriptor:" << descriptor; } else { canAddThisTestToSARIF = true; } @@ -147,7 +147,7 @@ namespace sarif { result["kind"] = "fail"; } else if (key == ERROR_ID_KEY) { result["ruleId"] = value; - } else if (key == "Stack") { + } else if (key == "ExecutionStack") { stackLocations = json(); codeFlowsLocations = json(); } else if (key == TEST_FILE_KEY) { diff --git a/server/src/Tests.cpp b/server/src/Tests.cpp index add9c5f5b..f2d2327bc 100644 --- a/server/src/Tests.cpp +++ b/server/src/Tests.cpp @@ -675,7 +675,7 @@ void KTestObjectParser::assignTypeUnnamedVar( curType.paramValue.lazyValues.emplace_back(name, std::nullopt, testParamView); } - for (auto const &[offset, indObj, indexOffset] : testCase.objects[curType.jsonInd].pointers) { + for (auto const &[offset, indObj, indexOffset]: testCase.objects[curType.jsonInd].pointers) { if (indexOffset != 0) { continue; } @@ -1065,12 +1065,12 @@ void KTestObjectParser::processGlobalParamPreValue(Tests::TestCaseDescription &t void KTestObjectParser::processSymbolicStdin(Tests::TestCaseDescription &testCaseDescription, const std::vector &rawKleeParams) { - auto &&read = getKleeParamOrThrow(rawKleeParams, "stdin-read"); + auto &&read = getKleeParamOrThrow(rawKleeParams, KleeUtils::STDIN_READ_NAME); std::string &&view = - testParameterView(read, { types::Type::longlongType(), "stdin-read" }, - types::PointerUsage::PARAMETER, testCaseDescription.objects, - testCaseDescription.lazyReferences) - ->getEntryValue(nullptr); + testParameterView(read, {types::Type::longlongType(), KleeUtils::STDIN_READ_NAME}, + types::PointerUsage::PARAMETER, testCaseDescription.objects, + testCaseDescription.lazyReferences) + ->getEntryValue(nullptr); if (view == "0LL") { return; } else { @@ -1080,7 +1080,7 @@ void KTestObjectParser::processSymbolicStdin(Tests::TestCaseDescription &testCas LOG_S(ERROR) << message; throw UnImplementedException(message); } - auto &&stdinBuffer = getKleeParamOrThrow(rawKleeParams, "stdin"); + auto &&stdinBuffer = getKleeParamOrThrow(rawKleeParams, KleeUtils::STDIN_NAME); auto &&testParamView = stringLiteralView(stdinBuffer.rawData, usedStdinBytesCount); testCaseDescription.stdinValue = Tests::TestCaseParamValue(types::Type::getStdinParamName(), std::nullopt, testParamView); diff --git a/server/src/Tests.h b/server/src/Tests.h index c7706359c..3c828aea0 100644 --- a/server/src/Tests.h +++ b/server/src/Tests.h @@ -888,8 +888,7 @@ namespace tests { std::enable_if_t::value, std::string> primitiveValueToString(T value) { std::stringstream ss; - ss << std::scientific; - ss << value; + ss << std::scientific << value; return ss.str(); } diff --git a/server/src/fetchers/FunctionDeclsMatchCallback.cpp b/server/src/fetchers/FunctionDeclsMatchCallback.cpp index b28267840..34c2d7f4d 100644 --- a/server/src/fetchers/FunctionDeclsMatchCallback.cpp +++ b/server/src/fetchers/FunctionDeclsMatchCallback.cpp @@ -22,6 +22,9 @@ FunctionDeclsMatchCallback::FunctionDeclsMatchCallback(const Fetcher *parent, void FunctionDeclsMatchCallback::run(const MatchFinder::MatchResult &Result) { ExecUtils::throwIfCancelled(); if (const FunctionDecl *FS = ClangUtils::getFunctionOrConstructor(Result)) { + if (FS->isTemplated()) { + return; + } ExecUtils::throwIfCancelled(); SourceManager &sourceManager = Result.Context->getSourceManager(); fs::path sourceFilePath = ClangUtils::getSourceFilePath(sourceManager); diff --git a/server/src/types/Types.cpp b/server/src/types/Types.cpp index 6c2fc2f4e..b6bda0edd 100644 --- a/server/src/types/Types.cpp +++ b/server/src/types/Types.cpp @@ -114,7 +114,7 @@ types::Type types::Type::baseTypeObj(size_t depth) const { type.mKinds.erase(type.mKinds.begin(), type.mKinds.begin() + depth); type.dimension = type.getDimension(); type.mTypeId = mBaseTypeId; - type.mBaseTypeId = {}; + type.mBaseTypeId = mBaseTypeId; return type; } diff --git a/server/src/utils/KleeUtils.h b/server/src/utils/KleeUtils.h index bddf63f9b..55fd2c790 100644 --- a/server/src/utils/KleeUtils.h +++ b/server/src/utils/KleeUtils.h @@ -12,6 +12,9 @@ namespace KleeUtils { static inline const std::string RESULT_VARIABLE_NAME = "utbot_result"; static inline const std::string NOT_NULL_VARIABLE_NAME = "utbot_return_not_null"; + static inline const std::string STDIN_READ_NAME = "stdin_read"; + static inline const std::string STDIN_NAME = "stdin"; + std::string getRenamedOperator(std::string_view methodName); std::string entryPointFunction(const tests::Tests &tests, diff --git a/server/src/utils/PrinterUtils.cpp b/server/src/utils/PrinterUtils.cpp index e9b96ae62..1e4c265e9 100644 --- a/server/src/utils/PrinterUtils.cpp +++ b/server/src/utils/PrinterUtils.cpp @@ -161,15 +161,15 @@ namespace PrinterUtils { } std::string getFileParamKTestJSON(char fileName) { - return StringUtils::stringFormat("%c-data", fileName); + return StringUtils::stringFormat("%c_data", fileName); } std::string getFileReadBytesParamKTestJSON(char fileName) { - return StringUtils::stringFormat("%c-data-read", fileName); + return StringUtils::stringFormat("%c_data_read", fileName); } std::string getFileWriteBytesParamKTestJSON(char fileName) { - return StringUtils::stringFormat("%c-data-write", fileName); + return StringUtils::stringFormat("%c_data_write", fileName); } void removeThreadLocalQualifiers(std::string &decl) { diff --git a/server/test/framework/Server_Tests.cpp b/server/test/framework/Server_Tests.cpp index 2ae7f7177..a430ae853 100644 --- a/server/test/framework/Server_Tests.cpp +++ b/server/test/framework/Server_Tests.cpp @@ -142,66 +142,55 @@ namespace { } void checkDifferentVariables_C(BaseTestGen &testGen, bool differentVariables) { - for (const auto &[methodName, methodDescription] : - testGen.tests.at(different_variables_c).methods) { + for (const auto &[methodName, methodDescription]: + testGen.tests.at(different_variables_c).methods) { if (methodName == "swap_two_int_pointers") { checkTestCasePredicates( - methodDescription.testCases, - std::vector( - { [differentVariables](tests::Tests::MethodTestCase const &testCase) { - return (differentVariables ^ - checkEquals(testCase.paramValues[0], - testCase.paramValues[1])) && - checkEquals(testCase.paramPostValues[0], - testCase.paramValues[1]) && - checkEquals(testCase.paramPostValues[1], - testCase.paramValues[0]) && - testCase.stdinValue == std::nullopt; - } }), - methodName); + methodDescription.testCases, + std::vector( + {[differentVariables](tests::Tests::MethodTestCase const &testCase) { + return (differentVariables ^ + checkEquals(testCase.paramValues[0], + testCase.paramValues[1])) && + checkEquals(testCase.paramPostValues[0], + testCase.paramValues[1]) && + checkEquals(testCase.paramPostValues[1], + testCase.paramValues[0]) && + testCase.stdinValue == std::nullopt; + }}), + methodName); } else if (methodName == "max_of_two_float") { checkTestCasePredicates( - methodDescription.testCases, - std::vector( - { [differentVariables](tests::Tests::MethodTestCase const &testCase) { - return ((stod(testCase.paramValues[0].view->getEntryValue( - nullptr)) == - stod(testCase.paramValues[1].view->getEntryValue( - nullptr))) ^ - differentVariables) && - stod(testCase.returnValue.view->getEntryValue(nullptr)) == - std::max( - stod(testCase.paramValues[0].view->getEntryValue( - nullptr)), - stod(testCase.paramValues[1].view->getEntryValue( - nullptr))) && - testCase.stdinValue == std::nullopt; - }, - [](tests::Tests::MethodTestCase const &testCase) { - return stod(testCase.paramValues[0].view->getEntryValue( - nullptr)) != - stod(testCase.paramValues[1].view->getEntryValue( - nullptr)) && - stod(testCase.returnValue.view->getEntryValue(nullptr)) == - std::max( - stod(testCase.paramValues[0].view->getEntryValue( - nullptr)), - stod(testCase.paramValues[1].view->getEntryValue( - nullptr))) && - testCase.stdinValue == std::nullopt; - } }), - methodName); + methodDescription.testCases, + std::vector( + {[differentVariables](tests::Tests::MethodTestCase const &testCase) { + double param0 = stod(testCase.paramValues[0].view->getEntryValue(nullptr)); + double param1 = stod(testCase.paramValues[1].view->getEntryValue(nullptr)); + double ret = stod(testCase.returnValue.view->getEntryValue(nullptr)); + return (param0 != param1 || differentVariables) && + ret == std::max(param0, param1) && + testCase.stdinValue == std::nullopt; + }, + [](tests::Tests::MethodTestCase const &testCase) { + double param0 = stod(testCase.paramValues[0].view->getEntryValue(nullptr)); + double param1 = stod(testCase.paramValues[1].view->getEntryValue(nullptr)); + double ret = stod(testCase.returnValue.view->getEntryValue(nullptr)); + return param0 != param1 && + ret == std::max(param0, param1) && + testCase.stdinValue == std::nullopt; + }}), + methodName); } else if (methodName == "struct_test") { checkTestCasePredicates( - methodDescription.testCases, - std::vector( - { [](tests::Tests::MethodTestCase const &testCase) { - return testCase.returnValue.view->getEntryValue(nullptr) == "-1"; - }, - [](tests::Tests::MethodTestCase const &testCase) { - return testCase.returnValue.view->getEntryValue(nullptr) == "1"; - } }), - methodName); + methodDescription.testCases, + std::vector( + {[](tests::Tests::MethodTestCase const &testCase) { + return testCase.returnValue.view->getEntryValue(nullptr) == "-1"; + }, + [](tests::Tests::MethodTestCase const &testCase) { + return testCase.returnValue.view->getEntryValue(nullptr) == "1"; + }}), + methodName); } } } @@ -1566,11 +1555,11 @@ namespace { auto tests = coverageGenerator.getTestsToLaunch(); ASSERT_FALSE(resultMap.empty()); - EXPECT_GT(resultMap.getNumberOfTests(), 2); + EXPECT_GE(resultMap.getNumberOfTests(), 3); testUtils::checkStatuses(resultMap, tests); - StatusCountMap expectedStatusCountMap{{testsgen::TEST_PASSED, 7}}; + StatusCountMap expectedStatusCountMap{{testsgen::TEST_PASSED, 3}}; testUtils::checkStatusesCount(resultMap, tests, expectedStatusCountMap); } @@ -1962,7 +1951,7 @@ namespace { 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), 2); + EXPECT_GE(testUtils::getNumberOfTests(testGen.tests), 5); fs::path testsDirPath = getTestFilePath("tests"); @@ -1990,7 +1979,7 @@ namespace { testUtils::checkStatuses(resultMap, tests); - StatusCountMap expectedStatusCountMap{ { testsgen::TEST_PASSED, 6 } }; + StatusCountMap expectedStatusCountMap{{testsgen::TEST_PASSED, 5}}; testUtils::checkStatusesCount(resultMap, tests, expectedStatusCountMap); } @@ -2002,7 +1991,7 @@ namespace { 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); + EXPECT_GE(testUtils::getNumberOfTests(testGen.tests), 11); fs::path testsDirPath = getTestFilePath("tests"); @@ -2041,14 +2030,27 @@ namespace { testGen.setTargetForSource(input_output_c); Status status = Server::TestsGenServiceImpl::ProcessBaseTestRequest(testGen, writer.get()); ASSERT_TRUE(status.ok()) << status.error_message(); - EXPECT_EQ(testUtils::getNumberOfTests(testGen.tests), - 63); // 61 regression tests and 2 error + + TestCountMap expectedTestCountMap = {{"simple_getc", 11}, + {"simple_fgetc", 5}, + {"simple_fread", 3}, + {"simple_fgets", 2}, + {"simple_getchar", 3}, + {"simple_gets", 6}, + {"simple_putc", 3}, + {"simple_fputc", 3}, + {"simple_fwrite", 3}, + {"simple_fputs", 2}, + {"simple_putchar", 3}, + {"simple_puts", 2}}; + + checkMinNumberOfTests(testGen.tests, expectedTestCountMap); fs::path testsDirPath = getTestFilePath("tests"); fs::path input_output_test_cpp = Paths::sourcePathToTestPath( - utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath), - input_output_c); + utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath), + input_output_c); auto testFilter = GrpcUtils::createTestFilterForFile(input_output_test_cpp); auto runRequest = testUtils::createCoverageAndResultsRequest( projectName, suitePath, testsDirPath, buildDirRelativePath, std::move(testFilter)); @@ -2068,8 +2070,7 @@ namespace { auto resultMap = coverageGenerator.getTestResultMap(); auto tests = coverageGenerator.getTestsToLaunch(); - StatusCountMap expectedStatusCountMap{ { testsgen::TEST_PASSED, 61 } }; - testUtils::checkStatusesCount(resultMap, tests, expectedStatusCountMap); + testUtils::checkStatuses(resultMap, tests, ErrorMode::FAILING); } TEST_F(Server_Test, Run_Tests_For_File_C) { diff --git a/server/test/framework/Syntax_Tests.cpp b/server/test/framework/Syntax_Tests.cpp index 7a5a5850b..98023abbd 100644 --- a/server/test/framework/Syntax_Tests.cpp +++ b/server/test/framework/Syntax_Tests.cpp @@ -264,15 +264,15 @@ namespace { {[](const tests::Tests::MethodTestCase& testCase) { std::cout << testCase.paramValues[0].view->getEntryValue(nullptr) << std::endl; return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 1 - && testCase.paramValues[0].view->getEntryValue(nullptr).find("{{'\\0', ") == 0; + && testCase.paramValues[0].view->getEntryValue(nullptr).find(", 'a'") != std::string::npos; }, [](const tests::Tests::MethodTestCase& testCase) { return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 0 - && testCase.paramValues[0].view->getEntryValue(nullptr).find("{{'\\0', ") == std::string::npos; + && testCase.paramValues[0].view->getEntryValue(nullptr).find("{{'a', ") == 0; }, [](const tests::Tests::MethodTestCase& testCase) { return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == -1 - && testCase.paramValues[0].view->getEntryValue(nullptr).find("{{'\\0', ") == 0; + && testCase.paramValues[0].view->getEntryValue(nullptr).find("'a'") == std::string::npos; } }), "extract_bit"); @@ -512,17 +512,19 @@ namespace { ASSERT_TRUE(status.ok()) << status.error_message(); checkTestCasePredicates( - testGen.tests.at(complex_structs_c).methods.begin().value().testCases, - std::vector( - {[] (const tests::Tests::MethodTestCase& testCase) { - std::string expectedString = StringUtils::stringFormat("{%s, {%s, %s}, 0}", - PrinterUtils::C_NULL, PrinterUtils::C_NULL, PrinterUtils::C_NULL); - return testCase.returnValue.view->getEntryValue(nullptr) == expectedString && - testCase.paramValues[0].view->getEntryValue(nullptr) == expectedString && - testCase.globalPostValues[0].view->getEntryValue(nullptr) == expectedString; - } - }), - "check_double_pointer"); + testGen.tests.at(complex_structs_c).methods.begin().value().testCases, + std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + std::string expectedString = StringUtils::stringFormat("{%s, {%s, %s}", + PrinterUtils::C_NULL, + PrinterUtils::C_NULL, + PrinterUtils::C_NULL); + return testCase.paramValues[0].view->getEntryValue(nullptr).find(expectedString) == 0 && + testCase.globalPostValues[0].view->getEntryValue(nullptr) == + testCase.returnValue.view->getEntryValue(nullptr); + } + }), + "check_double_pointer"); } TEST_F(Syntax_Test, Booleans_as_Parameters_Test) { @@ -599,13 +601,13 @@ namespace { ASSERT_TRUE(status.ok()) << status.error_message(); checkTestCasePredicates( - testGen.tests.at(pointer_parameters_c).methods.begin().value().testCases, - std::vector( - {[] (const tests::Tests::MethodTestCase& testCase) { - return testCase.paramValues[0].view->getEntryValue(nullptr) == "0" && stoll(testCase.returnValue.view->getEntryValue(nullptr)) == 0; - } - }), - "void_pointer_int_usage"); + testGen.tests.at(pointer_parameters_c).methods.begin().value().testCases, + std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + return testCase.isError(); + } + }), + "void_pointer_int_usage"); } TEST_F(Syntax_Test, Enum_Pointer_as_Parameter_Test) { @@ -1112,15 +1114,17 @@ namespace { ASSERT_TRUE(status.ok()) << status.error_message(); checkTestCasePredicates( - testGen.tests.at(pointer_return_c).methods.begin().value().testCases, - std::vector( - {[] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) == 0 && testUtils::cmpChars(testCase.returnValue.view->getEntryValue(nullptr), 'a'); - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) != 0 && testUtils::cmpChars(testCase.returnValue.view->getEntryValue(nullptr), 'b'); - } - }) + testGen.tests.at(pointer_return_c).methods.begin().value().testCases, + std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) == 0 && + testUtils::cmpChars(testCase.returnValue.view->getEntryValue(nullptr), 'a'); + }, + [](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) != 0 && + testUtils::cmpChars(testCase.returnValue.view->getEntryValue(nullptr), 'b'); + } + }) ); } @@ -1130,17 +1134,21 @@ namespace { ASSERT_TRUE(status.ok()) << status.error_message(); checkTestCasePredicates( - testGen.tests.at(pointer_return_c).methods.begin().value().testCases, - std::vector( - {[] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) < stoi(testCase.paramValues[1].view->getEntryValue(nullptr)) && - stoi(testCase.returnValue.view->getSubViews()[0]->getEntryValue(nullptr)) < stoi(testCase.returnValue.view->getSubViews()[1]->getEntryValue(nullptr)); - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) >= stoi(testCase.paramValues[1].view->getEntryValue(nullptr)) && - stoi(testCase.returnValue.view->getSubViews()[0]->getEntryValue(nullptr)) >= stoi(testCase.returnValue.view->getSubViews()[1]->getEntryValue(nullptr)); - } - }) + testGen.tests.at(pointer_return_c).methods.begin().value().testCases, + std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) < + stoi(testCase.paramValues[1].view->getEntryValue(nullptr)) && + stoi(testCase.returnValue.view->getSubViews()[0]->getEntryValue(nullptr)) < + stoi(testCase.returnValue.view->getSubViews()[1]->getEntryValue(nullptr)); + }, + [](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) >= + stoi(testCase.paramValues[1].view->getEntryValue(nullptr)) && + stoi(testCase.returnValue.view->getSubViews()[0]->getEntryValue(nullptr)) < + stoi(testCase.returnValue.view->getSubViews()[1]->getEntryValue(nullptr)); + } + }) ); } @@ -1447,18 +1455,27 @@ namespace { ASSERT_TRUE(status.ok()) << status.error_message(); checkTestCasePredicates( - testGen.tests.at(functions_as_params_c).methods.begin().value().testCases, - std::vector( - {[] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 0; - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 8; - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == -1; - } - }) + testGen.tests.at(functions_as_params_c).methods.begin().value().testCases, + std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + return testCase.stubParamValues.size() && + testCase.paramValues[1].view->getEntryValue(nullptr) == "'a'" && + stoi(testCase.stubParamValues.front().view->getSubViews().front()->getEntryValue( + nullptr)) == + stoi(testCase.returnValue.view->getEntryValue(nullptr)); + }, + [](const tests::Tests::MethodTestCase &testCase) { + return testCase.stubParamValues.size() && + testCase.paramValues[1].view->getEntryValue(nullptr) == "'b'" && + stoi(testCase.stubParamValues.front().view->getSubViews().front()->getEntryValue( + nullptr)) + 8 == + stoi(testCase.returnValue.view->getEntryValue(nullptr)); + }, + [](const tests::Tests::MethodTestCase &testCase) { + return testCase.stubParamValues.empty() && + stoi(testCase.returnValue.view->getEntryValue(nullptr)) == -1; + } + }) ); } @@ -1467,15 +1484,15 @@ namespace { ASSERT_TRUE(status.ok()) << status.error_message(); checkTestCasePredicates( - testGen.tests.at(functions_as_params_c).methods.begin().value().testCases, - std::vector( - {[] (const tests::Tests::MethodTestCase& testCase) { - return testCase.returnValue.view->getEntryValue(nullptr) == "'\\0'"; - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return testCase.returnValue.view->getEntryValue(nullptr) == "'\\0'"; - } - }) + testGen.tests.at(functions_as_params_c).methods.begin().value().testCases, + std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + return testCase.returnValue.view->getEntryValue(nullptr) == "'\\0'"; + }, + [](const tests::Tests::MethodTestCase &testCase) { + return testCase.returnValue.view->getEntryValue(nullptr) == "'\\0'"; + } + }) ); } @@ -1484,18 +1501,38 @@ namespace { ASSERT_TRUE(status.ok()) << status.error_message(); checkTestCasePredicates( - testGen.tests.at(functions_as_params_c).methods.begin().value().testCases, - std::vector( - {[] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 0; - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 6; - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 0; - } - }) + testGen.tests.at(functions_as_params_c).methods.begin().value().testCases, + std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + return testCase.stubParamValues.size() && + testCase.paramValues[1].view->getSubViews().size() >= 1 && + testCase.paramValues[1].view->getSubViews()[0]->getEntryValue(nullptr) == "'z'" && + stoi(testCase.stubParamValues.front().view->getSubViews().front()->getEntryValue( + nullptr)) == + stoi(testCase.returnValue.view->getEntryValue(nullptr)); + }, + [](const tests::Tests::MethodTestCase &testCase) { + return testCase.stubParamValues.size() && + testCase.paramValues[1].view->getSubViews().size() >= 1 && + testCase.paramValues[1].view->getSubViews()[0]->getEntryValue(nullptr) == "'a'" && + stoi(testCase.stubParamValues.front().view->getSubViews().front()->getEntryValue( + nullptr)) + 6 == + stoi(testCase.returnValue.view->getEntryValue(nullptr)); + }, + [](const tests::Tests::MethodTestCase &testCase) { + if (testCase.paramValues[1].view->getSubViews().empty()) { + return false; + } + std::string param1 = testCase.paramValues[1].view->getSubViews()[0]->getEntryValue( + nullptr); + int stubRes = stoi( + testCase.stubParamValues.front().view->getSubViews().front()->getEntryValue( + nullptr)); + return testCase.stubParamValues.size() && + param1 != "'a'" && param1 != "'z'" && + stubRes * stubRes == stoi(testCase.returnValue.view->getEntryValue(nullptr)); + } + }) ); } @@ -1504,18 +1541,35 @@ namespace { ASSERT_TRUE(status.ok()) << status.error_message(); checkTestCasePredicates( - testGen.tests.at(functions_as_params_c).methods.begin().value().testCases, - std::vector( - {[] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 12; - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 1; - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.returnValue.view->getEntryValue(nullptr)) == 0; - } - }) + testGen.tests.at(functions_as_params_c).methods.begin().value().testCases, + std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + return testCase.stubParamValues.size() && + testCase.paramValues[1].view->getSubViews().size() >= 1 && + testCase.paramValues[1].view->getSubViews()[0]->getEntryValue(nullptr) == "1" && + stoi(testCase.stubParamValues.front().view->getSubViews().front()->getEntryValue( + nullptr)) + 12 == + stoi(testCase.returnValue.view->getEntryValue(nullptr)); + }, + [](const tests::Tests::MethodTestCase &testCase) { + return testCase.stubParamValues.size() && + testCase.paramValues[1].view->getSubViews().size() >= 2 && + testCase.paramValues[1].view->getSubViews()[0]->getEntryValue(nullptr) != "1" && + testCase.paramValues[1].view->getSubViews()[1]->getEntryValue(nullptr) == "34" && + stoi(testCase.stubParamValues.front().view->getSubViews().front()->getEntryValue( + nullptr)) + 1 == + stoi(testCase.returnValue.view->getEntryValue(nullptr)); + }, + [](const tests::Tests::MethodTestCase &testCase) { + return testCase.stubParamValues.size() && + testCase.paramValues[1].view->getSubViews().size() >= 2 && + testCase.paramValues[1].view->getSubViews()[0]->getEntryValue(nullptr) != "1" && + testCase.paramValues[1].view->getSubViews()[1]->getEntryValue(nullptr) != "34" && + stoi(testCase.stubParamValues.front().view->getSubViews().front()->getEntryValue( + nullptr)) == + stoi(testCase.returnValue.view->getEntryValue(nullptr)); + } + }) ); } @@ -1740,7 +1794,8 @@ namespace { testGen.tests.at(floats_special_c).methods.begin().value().testCases, std::vector( {[](const tests::Tests::MethodTestCase &testCase) { - return testCase.paramValues[0].view->getEntryValue(nullptr) == "NAN"; + return testCase.paramValues[0].view->getEntryValue(nullptr).find("NAN") != + std::string::npos; }})); } @@ -1752,15 +1807,21 @@ namespace { printer::TestsPrinter testsPrinter(testGen.projectContext, nullptr, utbot::Language::C); const auto &tests = testGen.tests.at(floats_special_c) - .methods.begin().value().testCases; + .methods.begin().value().testCases; checkTestCasePredicates( - tests, std::vector( - { [](const tests::Tests::MethodTestCase &testCase) { - return testCase.paramValues[0].view->getEntryValue(nullptr) == "NAN"; - }, + tests, std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + return testCase.paramValues[0].view->getEntryValue(nullptr).find("NAN") != + std::string::npos; + }, [](const tests::Tests::MethodTestCase &testCase) { - return testCase.paramValues[0].view->getEntryValue(nullptr) == "0.000000e+00L"; - } })); + return testCase.paramValues[0].view->getEntryValue(nullptr).find("NAN") == + std::string::npos && + testCase.paramValues[0].view->getEntryValue(nullptr).find("INFINITY") == + std::string::npos && + testCase.paramValues[0].view->getEntryValue(nullptr).find("e") != + std::string::npos; + }})); } TEST_F(Syntax_Test, Floats_Special_Values_Inf) { @@ -2463,36 +2524,49 @@ namespace { ASSERT_TRUE(status.ok()) << status.error_message(); printer::TestsPrinter testsPrinter(testGen.projectContext, nullptr, utbot::Language::CXX); const auto &tests = testGen.tests.at(simple_class_cpp) - .methods.begin().value().testCases; + .methods.begin().value().testCases; testUtils::checkRegexp(tests[0].paramValues[0].view->getEntryValue(&testsPrinter), "[{]" "\n /[*][.]x = [*]/.+," "\n /[*][.]y = [*]/.+" "\n[}]"); - testUtils::checkMinNumberOfTests(testGen.tests.at(simple_class_cpp).methods.begin().value().testCases, 5); + testUtils::checkMinNumberOfTests(testGen.tests.at(simple_class_cpp).methods.begin().value().testCases, 4); checkTestCasePredicates( - tests, - std::vector( - {[] (const tests::Tests::MethodTestCase& testCase) { - return testCase.paramPostValues.front().view->getSubViews()[0]->getEntryValue(nullptr) == "0" && - testCase.paramPostValues.front().view->getSubViews()[1]->getEntryValue(nullptr) == "0"; - }, [] (const tests::Tests::MethodTestCase& testCase) { - return testCase.paramPostValues.front().view->getSubViews()[0]->getEntryValue(nullptr) == "0" && - testCase.paramPostValues.front().view->getSubViews()[1]->getEntryValue(nullptr) == "0"; - }, [] (const tests::Tests::MethodTestCase& testCase) { - return testCase.paramPostValues.front().view->getSubViews()[0]->getEntryValue(nullptr) == "0" && - testCase.paramPostValues.front().view->getSubViews()[1]->getEntryValue(nullptr) == "0"; - }, [] (const tests::Tests::MethodTestCase& testCase) { - return testCase.paramPostValues.front().view->getSubViews()[0]->getEntryValue(nullptr) == "0" && - testCase.paramPostValues.front().view->getSubViews()[1]->getEntryValue(nullptr) == "0"; - }, [] (const tests::Tests::MethodTestCase& testCase) { - return testCase.paramPostValues.front().view->getSubViews()[0]->getEntryValue(nullptr) == "0" && - testCase.paramPostValues.front().view->getSubViews()[1]->getEntryValue(nullptr) == "0"; - } - }), - "change_class_by_ref_cpp"); + tests, + std::vector( + {[](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues.front().view->getSubViews()[0]->getEntryValue(nullptr)) < + 0 && + testCase.paramPostValues.front().view->getSubViews()[0]->getEntryValue(nullptr) == + "0" && + testCase.paramPostValues.front().view->getSubViews()[1]->getEntryValue(nullptr) == + "0"; + }, [](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues.front().view->getSubViews()[0]->getEntryValue(nullptr)) > + 0 && + testCase.paramPostValues.front().view->getSubViews()[0]->getEntryValue(nullptr) == + "0" && + testCase.paramPostValues.front().view->getSubViews()[1]->getEntryValue(nullptr) == + "0"; + }, [](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues.front().view->getSubViews()[1]->getEntryValue(nullptr)) < + 0 && + testCase.paramPostValues.front().view->getSubViews()[0]->getEntryValue(nullptr) == + "0" && + testCase.paramPostValues.front().view->getSubViews()[1]->getEntryValue(nullptr) == + "0"; + }, [](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues.front().view->getSubViews()[1]->getEntryValue(nullptr)) < + 0 && + testCase.paramPostValues.front().view->getSubViews()[0]->getEntryValue(nullptr) == + "0" && + testCase.paramPostValues.front().view->getSubViews()[1]->getEntryValue(nullptr) == + "0"; + } + }), + "change_class_by_ref_cpp"); } TEST_F(Syntax_Test, Change_class_by_ref_2_cpp) { @@ -2922,7 +2996,7 @@ namespace { ); } - TEST_F(Syntax_Test, return_and_get_params_cpp) { + TEST_F(Syntax_Test, rvalue_params_cpp) { auto [testGen, status] = createTestForFunction(rvalue_reference_cpp, 28); ASSERT_TRUE(status.ok()) << status.error_message(); @@ -2930,35 +3004,42 @@ namespace { testUtils::checkMinNumberOfTests(testGen.tests.at(rvalue_reference_cpp).methods.begin().value().testCases, 3); checkTestCasePredicates( - testGen.tests.at(rvalue_reference_cpp).methods.begin().value().testCases, - std::vector( - { - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) % 5 == 0; - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.paramValues[1].view->getEntryValue(nullptr)) % 5 == 0; - } - }) + testGen.tests.at(rvalue_reference_cpp).methods.begin().value().testCases, + std::vector( + { + [](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) % 5 == 0 && + testCase.returnValue.view->getEntryValue(nullptr) == "1"; + }, + [](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues[1].view->getEntryValue(nullptr)) % 5 == 0 && + testCase.returnValue.view->getEntryValue(nullptr) == "2"; + }, + [](const tests::Tests::MethodTestCase &testCase) { + return stoi(testCase.paramValues[1].view->getEntryValue(nullptr)) % 5 != 0 && + stoi(testCase.paramValues[1].view->getEntryValue(nullptr)) % 5 != 0 && + testCase.returnValue.view->getEntryValue(nullptr) == "0"; + } + }) ); + } + + TEST_F(Syntax_Test, return_rvalue_cpp) { + auto [testGen, status] = createTestForFunction(rvalue_reference_cpp, 62); + + ASSERT_TRUE(status.ok()) << status.error_message(); + + testUtils::checkMinNumberOfTests(testGen.tests.at(rvalue_reference_cpp).methods.begin().value().testCases, 1); checkTestCasePredicates( - testGen.tests.at(rvalue_reference_cpp).methods.begin().value().testCases, - std::vector( - { - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) == - stoi(testCase.returnValue.view->getEntryValue(nullptr)); - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.paramValues[1].view->getEntryValue(nullptr)) == - stoi(testCase.returnValue.view->getEntryValue(nullptr)); - }, - [] (const tests::Tests::MethodTestCase& testCase) { - return stoi(testCase.paramValues[0].view->getEntryValue(nullptr)) + stoi(testCase.paramValues[1].view->getEntryValue(nullptr))== - stoi(testCase.returnValue.view->getEntryValue(nullptr)); - } - }) + testGen.tests.at(rvalue_reference_cpp).methods.begin().value().testCases, + std::vector({ + [](const tests::Tests::MethodTestCase &testCase) { + return testCase.classPreValues.value().view->getSubViews()[4]->getEntryValue( + nullptr) == + testCase.returnValue.view->getEntryValue(nullptr); + } + }) ); } diff --git a/server/test/framework/TestUtils.cpp b/server/test/framework/TestUtils.cpp index d6c9a22bc..6f1da86f9 100644 --- a/server/test/framework/TestUtils.cpp +++ b/server/test/framework/TestUtils.cpp @@ -9,21 +9,23 @@ namespace testUtils { static std::string getMessageForTestCaseNotMatching( - size_t predicateNumber, - const std::string &functionName, - const std::vector>> ¶meters, - const std::vector> &returnValues) { + size_t predicateNumber, + const std::string &functionName, + const std::vector &testCases, + const std::vector &mask) { std::stringstream ss; ss << "Predicates don't match test cases:\n"; ss << "\tNot found test case for predicate at position:" << predicateNumber << "\n"; ss << "\tFunction name: " << functionName << "\n"; ss << "\tRemaining non-matched test cases:\n"; - for (size_t i = 0; i < parameters.size(); i++) { - ss << "\t\tParameters values: "; - for (const auto ¶m : parameters[i]) { - ss << param->getEntryValue(nullptr) << " "; + for (size_t i = 0; i < mask.size(); i++) { + if (mask[i]) { + ss << "\t\tParameters values: "; + for (const auto ¶m: testCases[i].paramValues) { + ss << param.view->getEntryValue(nullptr) << " "; + } + ss << "\n\t\tReturn value: " << testCases[i].returnValue.view->getEntryValue(nullptr) << "\n"; } - ss << "\n\t\tReturn value: " << returnValues[i]->getEntryValue(nullptr) << "\n"; } return ss.str(); } @@ -32,35 +34,22 @@ namespace testUtils { const std::vector &predicates, const std::string &functionName) { EXPECT_GE(testCases.size(), predicates.size()) - << " Number of test cases (" << testCases.size() - << ") less than" - " number of predicates (" - << predicates.size() << ") for function " << functionName << "."; - std::vector>> params; - std::vector> returnValues; - for (const auto &testCase : testCases) { - params.emplace_back(); - for (const auto &p : testCase.paramValues) { - params.back().push_back(p.view); - } - returnValues.push_back(testCase.returnValue.view); - } + << " Number of test cases (" << testCases.size() + << ") less than" + " number of predicates (" + << predicates.size() << ") for function " << functionName << "."; + std::vector mask(testCases.size(), true); for (size_t p_i = 0; p_i < predicates.size(); p_i++) { const auto &predicate = predicates[p_i]; - int ind = -1; + bool flag = false; for (size_t i = 0; i < testCases.size(); i++) { if (predicate(testCases[i])) { - ind = i; + flag = true; + mask[i] = false; break; } } - EXPECT_NE(-1, ind) << getMessageForTestCaseNotMatching(p_i, functionName, params, - returnValues); - if (ind == -1) { - return; - } - params.erase(params.begin() + ind); - returnValues.erase(returnValues.begin() + ind); + EXPECT_TRUE(flag) << getMessageForTestCaseNotMatching(p_i, functionName, testCases, mask); } } @@ -205,13 +194,32 @@ namespace testUtils { << "Number of test cases in \"" << fileName << "\" not equal to predicate"; } - void - checkMinNumberOfTestsInFile(const BaseTestGen &testGen, std::string fileName, size_t number) { + void checkMinNumberOfTestsInFile(const BaseTestGen &testGen, std::string fileName, size_t number) { size_t testCounter = getNumberOfTestsForFile(testGen, fileName); EXPECT_LE(number, testCounter) << "Number of test cases in \"" << fileName << "\" not equal to predicate"; } + void checkMinNumberOfTests(const tests::TestsMap &tests, const TestCountMap &expectedTestCountMap) { + TestCountMap actualTestCountMap; + + for (const auto &[filename, cases]: tests) { + for (const auto &[methodName, methodDescription]: cases.methods) { + auto it = actualTestCountMap.find(methodName); + if (it == actualTestCountMap.end()) { + actualTestCountMap.insert({methodName, 1}); + } else { + it->second += 1; + } + } + } + for (const auto &[methodName, count]: expectedTestCountMap) { + auto it = actualTestCountMap.find(methodName); + ASSERT_TRUE(it != actualTestCountMap.end()); + ASSERT_GE(count, it->second); + } + } + std::unique_ptr createProjectRequest(const std::string &projectName, const fs::path &projectPath, const std::string &buildDirRelativePath, diff --git a/server/test/framework/TestUtils.h b/server/test/framework/TestUtils.h index 872e52286..66a79e4ee 100644 --- a/server/test/framework/TestUtils.h +++ b/server/test/framework/TestUtils.h @@ -20,6 +20,7 @@ using ReturnValue = const std::shared_ptr &; using TestCasePredicate = std::function; using CoverageLines = CollectionUtils::MapFileTo>; using StatusCountMap = std::unordered_map; +using TestCountMap = std::map; namespace testUtils { enum BuildCommandsTool { @@ -59,8 +60,9 @@ namespace testUtils { void checkNumberOfTestsInFile(const BaseTestGen &testGen, std::string fileName, size_t number); - void - checkMinNumberOfTestsInFile(const BaseTestGen &testGen, std::string fileName, size_t number); + void checkMinNumberOfTestsInFile(const BaseTestGen &testGen, std::string fileName, size_t number); + + void checkMinNumberOfTests(const tests::TestsMap &tests, const TestCountMap &expectedTestCountMap); std::unique_ptr createSnippetRequest(const std::string &projectName, const fs::path &projectPath, diff --git a/server/test/suites/syntax/function_with_rvalue_params.cpp b/server/test/suites/syntax/function_with_rvalue_params.cpp index f5d681721..844f0c0e8 100644 --- a/server/test/suites/syntax/function_with_rvalue_params.cpp +++ b/server/test/suites/syntax/function_with_rvalue_params.cpp @@ -19,13 +19,13 @@ int remainder(const int &&value) { } } -int &&return_and_get_rvalue_reference(int &&first, int &&second) { +int get_rvalue_reference(int &&first, int &&second) { if (first % 5 == 0) { - return std::move(first); + return 1; } else if (second % 5 == 0) { - return std::move(second); + return 2; } else { - return std::move(first + second); + return 0; } } @@ -44,16 +44,20 @@ int get_rvalue_custom_struct_as_param(Box &&box) { } } -Box::Box() { +Box::Box() : count(1) { length = 1.5; width = 0.5; height = 2.5; volume = height * width * length; } -Box::Box(double length_, double width_, double height_, double volume_) { +Box::Box(double length_, double width_, double height_, double volume_, int count_) : count(count_) { length = length_; width = width_; height = height_; volume = volume_; } + +int &&Box::return_rvalue_reference() { + return std::move(count); +} diff --git a/server/test/suites/syntax/function_with_rvalue_params.h b/server/test/suites/syntax/function_with_rvalue_params.h index c553f80f2..5dd60d3dd 100644 --- a/server/test/suites/syntax/function_with_rvalue_params.h +++ b/server/test/suites/syntax/function_with_rvalue_params.h @@ -6,10 +6,13 @@ struct Box { double width; double height; double volume; + int count; Box(); - Box(double length_, double width_, double height_, double volume_); + Box(double length_, double width_, double height_, double volume_, int count); + + int &&return_rvalue_reference(); }; #endif // UNITTESTBOT_FUNCTION_WITH_RVALUE_PARAMS_H diff --git a/server/test/suites/syntax/simple_unions.c b/server/test/suites/syntax/simple_unions.c index 3d8b4cd62..423df6e84 100644 --- a/server/test/suites/syntax/simple_unions.c +++ b/server/test/suites/syntax/simple_unions.c @@ -13,10 +13,10 @@ int get_sign_union(union IntBytesUnion st) { } int extract_bit(union ShortBytesUnion x) { - if (x.bytes[0] > 0) { + if (x.bytes[0] == 'a') { return 0; } - if (x.bytes[1] > 0) { + if (x.bytes[1] == 'a') { return 1; } return -1; diff --git a/submodules/build-klee.sh b/submodules/build-klee.sh new file mode 100644 index 000000000..84cc8acc9 --- /dev/null +++ b/submodules/build-klee.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# This script is used to build KLEE as UTBot backend + +set -e +set -o pipefail +cd klee +mkdir -p build +cd build + +$UTBOT_CMAKE_BINARY -G Ninja \ + -DCMAKE_PREFIX_PATH=$UTBOT_INSTALL_DIR/lib/cmake/z3 \ + -DCMAKE_LIBRARY_PATH=$UTBOT_INSTALL_DIR/lib \ + -DCMAKE_INCLUDE_PATH=$UTBOT_INSTALL_DIR/include \ + -DENABLE_SOLVER_Z3=TRUE \ + -DENABLE_POSIX_RUNTIME=TRUE \ + -DENABLE_FLOATING_POINT=TRUE \ + -DENABLE_FP_RUNTIME=TRUE \ + -DLLVM_CONFIG_BINARY=$UTBOT_INSTALL_DIR/bin/llvm-config \ + -DLLVMCC=/utbot_distr/install/bin/clang \ + -DLLVMCXX=/utbot_distr/install/bin/clang++ \ + -DENABLE_UNIT_TESTS=TRUE \ + -DENABLE_SYSTEM_TESTS=TRUE \ + -DGTEST_SRC_DIR=$UTBOT_ALL/gtest \ + -DGTEST_INCLUDE_DIR=$UTBOT_ALL/gtest/googletest/include \ + -DCMAKE_INSTALL_PREFIX=$UTBOT_ALL/klee \ + -DENABLE_KLEE_LIBCXX=TRUE \ + -DKLEE_LIBCXX_DIR=$UTBOT_ALL/libcxx/install \ + -DKLEE_LIBCXX_INCLUDE_DIR=$UTBOT_ALL/libcxx/install/include/c++/v1 \ + -DENABLE_KLEE_EH_CXX=TRUE \ + -DKLEE_LIBCXXABI_SRC_DIR=$UTBOT_ALL/libcxx/libcxxabi \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + .. + +$UTBOT_CMAKE_BINARY --build . +$UTBOT_CMAKE_BINARY --install . diff --git a/submodules/klee b/submodules/klee index 5df54da3f..1e1e8f8cb 160000 --- a/submodules/klee +++ b/submodules/klee @@ -1 +1 @@ -Subproject commit 5df54da3f708441ce256a051d74adc02b411ab82 +Subproject commit 1e1e8f8cb6e0529816caeff9708465ac433ab893