diff --git a/server/proto/testgen.proto b/server/proto/testgen.proto index 707b4b0e1..91b8cc86c 100644 --- a/server/proto/testgen.proto +++ b/server/proto/testgen.proto @@ -88,6 +88,7 @@ message ProjectContext { string projectPath = 2; string testDirPath = 3; string buildDirRelativePath = 4; + string clientProjectPath = 5; } enum ErrorMode { diff --git a/server/src/ProjectContext.cpp b/server/src/ProjectContext.cpp index 191cd945e..c906844fa 100644 --- a/server/src/ProjectContext.cpp +++ b/server/src/ProjectContext.cpp @@ -8,22 +8,26 @@ namespace utbot { ProjectContext::ProjectContext(std::string projectName, fs::path projectPath, fs::path testDirPath, - fs::path buildDirRelativePath) + fs::path buildDirRelativePath, + fs::path clientProjectPath) : projectName(std::move(projectName)), projectPath(std::move(projectPath)), testDirPath(std::move(testDirPath)), - buildDirRelativePath(std::move(buildDirRelativePath)) {} + buildDirRelativePath(std::move(buildDirRelativePath)), + clientProjectPath(clientProjectPath) {} ProjectContext::ProjectContext(const testsgen::ProjectContext &projectContext) : ProjectContext(projectContext.projectname(), projectContext.projectpath(), projectContext.testdirpath(), - projectContext.builddirrelativepath()) {} + projectContext.builddirrelativepath(), + projectContext.clientprojectpath()) {} ProjectContext::ProjectContext(const testsgen::SnippetRequest &request, fs::path serverBuildDir) : projectName(request.projectcontext().projectname()), projectPath(request.projectcontext().projectpath()), testDirPath(request.projectcontext().testdirpath()), - buildDirRelativePath(request.projectcontext().builddirrelativepath()) { } + buildDirRelativePath(request.projectcontext().builddirrelativepath()), + clientProjectPath(request.projectcontext().clientprojectpath()) {} fs::path ProjectContext::buildDir() const { return projectPath / buildDirRelativePath; diff --git a/server/src/ProjectContext.h b/server/src/ProjectContext.h index 4c4981d97..f3d6233b4 100644 --- a/server/src/ProjectContext.h +++ b/server/src/ProjectContext.h @@ -16,7 +16,8 @@ class ProjectContext { ProjectContext(std::string projectName, fs::path projectPath, fs::path testDirPath, - fs::path buildDirRelativePath); + fs::path buildDirRelativePath, + fs::path serverBuildDir); explicit ProjectContext(const testsgen::ProjectContext &projectContext); @@ -28,6 +29,7 @@ class ProjectContext { const fs::path projectPath; const fs::path testDirPath; const fs::path buildDirRelativePath; + const fs::path clientProjectPath; }; } diff --git a/server/src/Synchronizer.cpp b/server/src/Synchronizer.cpp index a659bea4b..e929b9f30 100644 --- a/server/src/Synchronizer.cpp +++ b/server/src/Synchronizer.cpp @@ -64,7 +64,11 @@ bool Synchronizer::isProbablyOutdatedStubs(const fs::path &srcFilePath) const { } catch (...) { return true; } - srcTimestamp = Synchronizer::getFileOutdatedTime(srcFilePath); + if (!fs::exists(srcFilePath)) { + srcTimestamp = time(nullptr); + } else { + srcTimestamp = Synchronizer::getFileOutdatedTime(srcFilePath); + } return stubTimestamp <= srcTimestamp; } @@ -75,7 +79,11 @@ bool Synchronizer::isProbablyOutdatedWrappers(const fs::path &srcFilePath) const } long long wrapperTimestamp, srcTimestamp; wrapperTimestamp = Synchronizer::getFileOutdatedTime(wrapperFilePath); - srcTimestamp = Synchronizer::getFileOutdatedTime(srcFilePath); + if (!fs::exists(srcFilePath)) { + srcTimestamp = time(nullptr); + } else { + srcTimestamp = Synchronizer::getFileOutdatedTime(srcFilePath); + } return wrapperTimestamp <= srcTimestamp; } diff --git a/server/src/building/CompileCommand.cpp b/server/src/building/CompileCommand.cpp index 84482a256..6f08d2783 100644 --- a/server/src/building/CompileCommand.cpp +++ b/server/src/building/CompileCommand.cpp @@ -114,6 +114,5 @@ namespace utbot { auto path = Paths::getCCJsonFileFullPath(Paths::replaceExtension(*this->sourcePath, ".o"), this->directory); this->output = std::next(addFlagsToBegin({"-o", path})); } - } } diff --git a/server/src/building/ProjectBuildDatabse.cpp b/server/src/building/ProjectBuildDatabse.cpp index 751f533de..17e7a18bd 100644 --- a/server/src/building/ProjectBuildDatabse.cpp +++ b/server/src/building/ProjectBuildDatabse.cpp @@ -176,12 +176,19 @@ void ProjectBuildDatabase::initInfo(const nlohmann::json &linkCommandsJson) { } targetInfo->addFile(currentFile); if (Paths::isObjectFile(currentFile)) { - if (!CollectionUtils::containsKey(objectFileInfos, currentFile)) { + if (!CollectionUtils::containsKey(objectFileInfos, currentFile) && + !CollectionUtils::containsKey(objectFileInfos, + relative(currentFile, directory))) { throw CompilationDatabaseException( - "compile_commands.json doesn't contain a command for object file " - + currentFile.string()); + "compile_commands.json doesn't contain a command for object file " + + currentFile.string()); + } + if (CollectionUtils::containsKey(objectFileInfos, currentFile)) { + objectFileInfos[currentFile]->linkUnit = output; + } else if (CollectionUtils::containsKey(objectFileInfos, + relative(currentFile, directory))) { + objectFileInfos[relative(currentFile, directory)]->linkUnit = output; } - objectFileInfos[currentFile]->linkUnit = output; } } targetInfo->commands.emplace_back(command); diff --git a/server/src/coverage/TestRunner.cpp b/server/src/coverage/TestRunner.cpp index 571ef7f97..bfab683e8 100644 --- a/server/src/coverage/TestRunner.cpp +++ b/server/src/coverage/TestRunner.cpp @@ -108,9 +108,10 @@ std::vector TestRunner::getTestsToLaunch() { } } else { if (!StringUtils::endsWith(testFilePath.c_str(), "_test.h") && - !StringUtils::endsWith(testFilePath.stem().c_str(), "_stub")) { - LOG_S(WARNING) - << "Found extra file in test directory: " << testFilePath; + !StringUtils::endsWith(testFilePath.stem().c_str(), "_stub") && + !StringUtils::endsWith(testFilePath.c_str(), "_wrapper.c") && + !StringUtils::endsWith(testFilePath.c_str(), ".mk")) { + LOG_S(WARNING) << "Found extra file in test directory: " << testFilePath; } } }); diff --git a/server/src/utils/CompilationUtils.cpp b/server/src/utils/CompilationUtils.cpp index 37cd796be..2ee86aea0 100644 --- a/server/src/utils/CompilationUtils.cpp +++ b/server/src/utils/CompilationUtils.cpp @@ -57,18 +57,16 @@ namespace CompilationUtils { } } - void substituteRemotePathToCCJsonForFile(const fs::path &projectPath, - const std::string &buildDirRelativePath, - const std::string &jsonFileName, - const fs::path &newJsonDir) { - fs::path compileCommandsJsonPath = projectPath / buildDirRelativePath / jsonFileName; - fs::create_directories(newJsonDir); + void substituteRemotePathToCCJsonForFile(const utbot::ProjectContext &projectContext, + const std::string &jsonFileName) { + fs::path compileCommandsJsonPath = projectContext.buildDir() / jsonFileName; + fs::create_directories(Paths::getUTBotBuildDir(projectContext)); if (!fs::exists(compileCommandsJsonPath)) { throw CompilationDatabaseException("Can't find " + compileCommandsJsonPath.string()); } std::ifstream ifs(compileCommandsJsonPath); json json = json::parse(ifs); - std::string projectPathStr = Paths::normalizedTrimmed(fs::absolute(projectPath)).string(); + std::string projectPathStr = Paths::normalizedTrimmed(fs::absolute(projectContext.projectPath)).string(); Paths::removeBackTrailedSlash(projectPathStr); const std::string directoryFieldName = "directory"; @@ -79,8 +77,7 @@ namespace CompilationUtils { for (auto &cmd : json) { std::string directoryField = cmd[directoryFieldName]; - std::string userSystemProjectPath = - Paths::subtractPath(directoryField, buildDirRelativePath); + std::string userSystemProjectPath = Paths::normalizedTrimmed(projectContext.clientProjectPath); Paths::removeBackTrailedSlash(userSystemProjectPath); if (cmd.contains(commandFieldName)) { @@ -106,25 +103,23 @@ namespace CompilationUtils { } else { for (auto ¤tFile : cmd[filesFieldName]) { std::string currentFileField = currentFile; - StringUtils::replaceAll(currentFileField, userSystemProjectPath, - projectPathStr); + StringUtils::replaceAll(currentFileField, userSystemProjectPath, projectPathStr); currentFile = currentFileField; } } } - fs::path newJsonPath = newJsonDir / jsonFileName; + fs::path newJsonPath = Paths::getUTBotBuildDir(projectContext) / jsonFileName; JsonUtils::writeJsonToFile(newJsonPath, json); - LOG_S(DEBUG) << jsonFileName << " for mount is written to: " << newJsonDir; + LOG_S(DEBUG) << jsonFileName << " for mount is written to: " << newJsonPath; } fs::path substituteRemotePathToCompileCommandsJsonPath(const utbot::ProjectContext &projectContext) { const std::string ccJsonFileName = "compile_commands.json"; - fs::path utbotBuildDir = Paths::getUTBotBuildDir(projectContext); - substituteRemotePathToCCJsonForFile(projectContext.projectPath, projectContext.buildDirRelativePath, - ccJsonFileName, utbotBuildDir); - substituteRemotePathToCCJsonForFile(projectContext.projectPath, projectContext.buildDirRelativePath, - "link_commands.json", utbotBuildDir); - return utbotBuildDir; + const std::string lcJsonFileName = "link_commands.json"; + + substituteRemotePathToCCJsonForFile(projectContext, ccJsonFileName); + substituteRemotePathToCCJsonForFile(projectContext, lcJsonFileName); + return Paths::getUTBotBuildDir(projectContext); } fs::path getClangCompileCommandsJsonPath(const fs::path &buildCommandsJsonPath) { diff --git a/server/src/utils/StringUtils.cpp b/server/src/utils/StringUtils.cpp index 00bd70439..944beafe6 100644 --- a/server/src/utils/StringUtils.cpp +++ b/server/src/utils/StringUtils.cpp @@ -74,6 +74,9 @@ namespace StringUtils { } void replaceAll(std::string &str, const std::string &from, const std::string &to) { + if (from.empty()) { + return; + } size_t start_pos = 0; while ((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); diff --git a/server/src/visitors/ParametrizedAssertsVisitor.cpp b/server/src/visitors/ParametrizedAssertsVisitor.cpp index 6aac02b1b..295bbda67 100644 --- a/server/src/visitors/ParametrizedAssertsVisitor.cpp +++ b/server/src/visitors/ParametrizedAssertsVisitor.cpp @@ -17,19 +17,25 @@ namespace visitor { auto returnType = methodDescription.returnType.maybeReturnArray() ? methodDescription.returnType.arrayClone(usage, pointerSize) : methodDescription.returnType; + functionCall = printer->constrVisitorFunctionCall(methodDescription, testCase, false, errorMode); - if (testCase.returnValue.view->getEntryValue(nullptr) == PrinterUtils::C_NULL) { - additionalPointersCount = methodDescription.returnType.countReturnPointers(true); - printer->writeCodeLine( - StringUtils::stringFormat("EXPECT_TRUE(%s)", - PrinterUtils::getEqualString(functionCall, PrinterUtils::C_NULL))); - return; + if (!types::TypesHandler::skipTypeInReturn(methodDescription.returnType) && !testCase.isError()) { + if (testCase.returnValue.view->getEntryValue(nullptr) == PrinterUtils::C_NULL) { + additionalPointersCount = methodDescription.returnType.countReturnPointers(true); + printer->writeCodeLine( + StringUtils::stringFormat("EXPECT_TRUE(%s)", + PrinterUtils::getEqualString(functionCall, PrinterUtils::C_NULL))); + return; + } else { + additionalPointersCount = 0; + visitAny(returnType, "", testCase.returnValue.view.get(), PrinterUtils::DEFAULT_ACCESS, 0); + functionCall = {}; + additionalPointersCount = 0; + } } else { - additionalPointersCount = 0; + printer->writeCodeLine(functionCall); + return; } - visitAny(returnType, "", testCase.returnValue.view.get(), PrinterUtils::DEFAULT_ACCESS, 0); - functionCall = {}; - additionalPointersCount = 0; } void ParametrizedAssertsVisitor::visitArray(const types::Type &type, diff --git a/server/test/framework/BaseTest.h b/server/test/framework/BaseTest.h index 73d2477e0..5da9aa570 100644 --- a/server/test/framework/BaseTest.h +++ b/server/test/framework/BaseTest.h @@ -23,6 +23,7 @@ class BaseTest : public testing::Test { CompilerName compilerName = CompilerName::CLANG; std::string buildDirRelativePath; + std::string clientProjectPath = ""; fs::path buildPath; std::vector srcPaths; diff --git a/server/test/framework/Server_Tests.cpp b/server/test/framework/Server_Tests.cpp index b7b000846..1b6f53989 100644 --- a/server/test/framework/Server_Tests.cpp +++ b/server/test/framework/Server_Tests.cpp @@ -1204,7 +1204,7 @@ namespace { testDirPath = getTestFilePath(pregeneratedTestsRelativeDir); projectContext = std::make_unique( - projectName, suitePath, testDirPath, buildDirRelativePath); + projectName, suitePath, testDirPath, buildDirRelativePath, clientProjectPath); basic_functions_c = getTestFilePath("basic_functions.c"); simple_loop_uncovered_c = getTestFilePath("simple_loop_uncovered.c"); @@ -1500,7 +1500,7 @@ namespace { testUtils::checkMinNumberOfTests(testGen.tests, 11); auto projectContext = std::make_unique(projectName, suitePath, suitePath / "tests", - buildDirRelativePath); + buildDirRelativePath, clientProjectPath); auto testFilter = GrpcUtils::createTestFilterForFile( Paths::sourcePathToTestPath(*projectContext, methods_with_asserts_cpp)); auto runRequest = createCoverageAndResultsRequest( @@ -1548,7 +1548,7 @@ namespace { testUtils::checkMinNumberOfTests(testGen.tests, 11); auto projectContext = std::make_unique(projectName, suitePath, suitePath / "tests", - buildDirRelativePath); + buildDirRelativePath, clientProjectPath); auto testFilter = GrpcUtils::createTestFilterForFile( Paths::sourcePathToTestPath(*projectContext, methods_with_asserts_cpp)); auto runRequest = createCoverageAndResultsRequest( @@ -1594,7 +1594,7 @@ namespace { testUtils::checkMinNumberOfTests(testGen.tests, 8); auto projectContext = std::make_unique(projectName, suitePath, suitePath / "tests", - buildDirRelativePath); + buildDirRelativePath, clientProjectPath); auto testFilter = GrpcUtils::createTestFilterForFile( Paths::sourcePathToTestPath(*projectContext, methods_with_exceptions_cpp)); auto runRequest = createCoverageAndResultsRequest( @@ -1640,7 +1640,7 @@ namespace { testUtils::checkMinNumberOfTests(testGen.tests, 8); auto projectContext = std::make_unique(projectName, suitePath, suitePath / "tests", - buildDirRelativePath); + buildDirRelativePath, clientProjectPath); auto testFilter = GrpcUtils::createTestFilterForFile( Paths::sourcePathToTestPath(*projectContext, methods_with_exceptions_cpp)); auto runRequest = createCoverageAndResultsRequest( @@ -1797,7 +1797,7 @@ namespace { fs::path testsDirPath = getTestFilePath("tests"); fs::path linked_list_test_cpp = Paths::sourcePathToTestPath( - utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath), + utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath), linked_list_c); auto testFilter = GrpcUtils::createTestFilterForFile(linked_list_test_cpp); auto runRequest = testUtils::createCoverageAndResultsRequest( @@ -1835,7 +1835,7 @@ namespace { fs::path testsDirPath = getTestFilePath("tests"); fs::path tree_test_cpp = Paths::sourcePathToTestPath( - utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath), + utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath), tree_c); auto testFilter = GrpcUtils::createTestFilterForFile(tree_test_cpp); auto runRequest = testUtils::createCoverageAndResultsRequest( @@ -1877,7 +1877,7 @@ namespace { fs::path testsDirPath = getTestFilePath("tests"); fs::path input_output_test_cpp = Paths::sourcePathToTestPath( - utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath), + utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath), input_output_c); auto testFilter = GrpcUtils::createTestFilterForFile(input_output_test_cpp); auto runRequest = testUtils::createCoverageAndResultsRequest( @@ -1916,7 +1916,7 @@ namespace { fs::path testsDirPath = getTestFilePath("tests"); fs::path file_test_cpp = Paths::sourcePathToTestPath( - utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath), + utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath), file_c); auto testFilter = GrpcUtils::createTestFilterForFile(file_test_cpp); auto runRequest = testUtils::createCoverageAndResultsRequest( @@ -1954,7 +1954,7 @@ namespace { fs::path testsDirPath = getTestFilePath("tests"); fs::path hard_linked_list_test_cpp = Paths::sourcePathToTestPath( - utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath), + utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath), hard_linked_list_c); auto testFilter = GrpcUtils::createTestFilterForFile(hard_linked_list_test_cpp); auto runRequest = testUtils::createCoverageAndResultsRequest( diff --git a/server/test/framework/Stub_Tests.cpp b/server/test/framework/Stub_Tests.cpp index 6d12901d1..06f2330b1 100644 --- a/server/test/framework/Stub_Tests.cpp +++ b/server/test/framework/Stub_Tests.cpp @@ -37,7 +37,7 @@ namespace { fs::path testsDirPath = getTestFilePath("tests"); utbot::ProjectContext projectContext{ projectName, suitePath, testsDirPath, - buildDirRelativePath }; + buildDirRelativePath, clientProjectPath }; fs::path sum_test_cpp = Paths::sourcePathToTestPath(projectContext, calc_sum_c); @@ -319,7 +319,8 @@ namespace { fs::path testsDirPath = getTestFilePath("tests"); fs::path function_pointers_test_cpp = Paths::sourcePathToTestPath( - utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath), function_pointers_c); + utbot::ProjectContext(projectName, suitePath, testsDirPath, buildDirRelativePath, clientProjectPath), + function_pointers_c); auto testFilter = GrpcUtils::createTestFilterForFile(function_pointers_test_cpp); auto runRequest = testUtils::createCoverageAndResultsRequest( projectName, suitePath, testsDirPath, buildDirRelativePath, std::move(testFilter)); diff --git a/vscode-plugin/src/client/client.ts b/vscode-plugin/src/client/client.ts index 98ba760fc..04148e1c0 100644 --- a/vscode-plugin/src/client/client.ts +++ b/vscode-plugin/src/client/client.ts @@ -1,6 +1,7 @@ /* eslint-disable no-async-promise-executor */ import * as grpc from 'grpc'; import * as vs from 'vscode'; +import * as vsUtils from "../utils/vscodeUtils"; import * as os from 'os'; import * as messages from '../config/notificationMessages'; import { Prefs } from '../config/prefs'; @@ -394,6 +395,7 @@ export class Client { projectContext.setProjectname(projectName); projectContext.setProjectpath(projectPath); projectContext.setBuilddirrelativepath(buildDirRelativePath); + projectContext.setClientprojectpath(vsUtils.getProjectDirByOpenedFile().fsPath) const projectConfigRequest = new ProjectConfigRequest(); projectConfigRequest.setProjectcontext(projectContext); projectConfigRequest.setConfigmode(configMode); @@ -426,6 +428,7 @@ export class Client { projectContext.setProjectpath(buildDir[0]); projectContext.setTestdirpath(Prefs.getTestsDirPath()); projectContext.setBuilddirrelativepath(buildDir[1]); + projectContext.setClientprojectpath(vsUtils.getProjectDirByOpenedFile().fsPath) rpcRequest.setProjectcontext(projectContext); rpcRequest.setSettingscontext(Prefs.getSettingsContext()); @@ -640,6 +643,7 @@ export class Client { projectContext.setProjectpath(params.projectPath); projectContext.setTestdirpath(Prefs.getTestsDirPath()); projectContext.setBuilddirrelativepath(params.buildDirRelativePath); + projectContext.setClientprojectpath(vsUtils.getProjectDirByOpenedFile().fsPath); rpcRequest.setProjectcontext(projectContext); rpcRequest.setSettingscontext(Prefs.getSettingsContext()); rpcRequest.setCoverage(true); diff --git a/vscode-plugin/src/requests/protos.ts b/vscode-plugin/src/requests/protos.ts index d43de8723..f0665b53d 100644 --- a/vscode-plugin/src/requests/protos.ts +++ b/vscode-plugin/src/requests/protos.ts @@ -11,6 +11,8 @@ import { } from "../proto-ts/testgen_pb"; import { PredicateInfo, SourceInfo, ValidationType } from "../proto-ts/util_pb"; import { RequestTestsParams } from "./params"; +import * as vsUtils from "../utils/vscodeUtils"; + export class Protos { public static projectRequestByParams(params: RequestTestsParams): ProjectRequest { @@ -37,6 +39,7 @@ export class Protos { projectContext.setProjectpath(projectPath); projectContext.setTestdirpath(Prefs.getTestsDirPath()); projectContext.setBuilddirrelativepath(buildDirRelativePath); + projectContext.setClientprojectpath(vsUtils.getProjectDirByOpenedFile().fsPath) projectInfo.setProjectcontext(projectContext); projectInfo.setSettingscontext(Prefs.getSettingsContext()); projectInfo.setSourcepathsList(srcPathsList);