Skip to content

Commit ef3ce99

Browse files
Samatantipeon
authored andcommitted
fix: detect source paths from compile_commands.json by default
1 parent 6124a9e commit ef3ce99

File tree

10 files changed

+119
-49
lines changed

10 files changed

+119
-49
lines changed

server/src/Paths.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@ namespace Paths {
2424

2525
vector<fs::path> filterPathsByDirNames(const vector<fs::path> &paths,
2626
const vector<fs::path> &dirPaths,
27-
const vector<string> &allowedExt) {
27+
const std::function<bool(const fs::path &path)> &filter) {
2828
std::vector<fs::path> filtered;
2929
std::copy_if(paths.begin(), paths.end(), std::back_inserter(filtered),
30-
[&dirPaths, &allowedExt](const fs::path &path) {
30+
[&dirPaths, &filter](const fs::path &path) {
3131
return std::any_of(
3232
dirPaths.begin(), dirPaths.end(), [&](const auto &dirPath) {
3333
return path.parent_path() == dirPath && fs::exists(path) &&
34-
CollectionUtils::contains(allowedExt, path.extension());
34+
filter(path);
3535
});
3636
});
3737
return filtered;
@@ -320,9 +320,8 @@ namespace Paths {
320320
}
321321

322322
std::optional<fs::path> headerPathToSourcePath(const fs::path &source) {
323-
std::vector<std::string> sourceExtensions({".cc", ".cp", ".cpp", ".c++", ".cxx"});
324323
if (Paths::isHeaderFile(source)) {
325-
for (const std::string &extension : sourceExtensions) {
324+
for (const std::string &extension : CXXFileExtensions) {
326325
fs::path sourceFilePath = replaceExtension(source, extension);
327326
if (fs::exists(sourceFilePath)) {
328327
return {sourceFilePath};
@@ -355,4 +354,9 @@ namespace Paths {
355354

356355
//endregion
357356

357+
const std::vector<std::string> CXXFileExtensions({".cc", ".cp", ".cpp", ".c++", ".cxx"});
358+
const std::vector<std::string> HPPFileExtensions({".hh", ".hpp", ".hxx"});
359+
const std::vector<std::string> CFileSourceExtensions({".c"});
360+
const std::vector<std::string> CFileHeaderExtensions({".h"});
361+
358362
}

server/src/Paths.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ namespace Paths {
3939
*/
4040
vector<fs::path> filterPathsByDirNames(const vector<fs::path> &path,
4141
const vector<fs::path> &dirNames,
42-
const vector<string> &allowedExt);
42+
const std::function<bool(const fs::path &path)> &filter);
4343

4444
static inline void setOptPath(fs::path &path, const string &value) {
4545
path = fs::path(value);
@@ -211,23 +211,24 @@ namespace Paths {
211211
//endregion
212212

213213
//region extensions
214+
extern const std::vector<std::string> CFileHeaderExtensions;
214215
static inline bool isHFile(const fs::path &path) {
215-
return path.extension() == ".h";
216+
return CollectionUtils::contains(CFileHeaderExtensions, path.extension());
216217
}
217218

219+
extern const std::vector<std::string> CFileSourceExtensions;
218220
static inline bool isCFile(const fs::path &path) {
219-
return path.extension() == ".c";
221+
return CollectionUtils::contains(CFileSourceExtensions, path.extension());
220222
}
221223

224+
extern const std::vector<std::string> CXXFileExtensions;
222225
static inline bool isCXXFile(const fs::path &path) {
223-
return path.extension() == ".cc" || path.extension() == ".cp" ||
224-
path.extension() == ".cpp" || path.extension() == ".c++" ||
225-
path.extension() == ".cxx";
226+
return CollectionUtils::contains(CXXFileExtensions, path.extension());
226227
}
227228

229+
extern const std::vector<std::string> HPPFileExtensions;
228230
static inline bool isHppFile(const fs::path &path) {
229-
return path.extension() == ".hh" || path.extension() == ".hpp" ||
230-
path.extension() == ".hxx";
231+
return CollectionUtils::contains(HPPFileExtensions, path.extension());
231232
}
232233

233234
static inline bool isHeaderFile(const fs::path &path) {

server/src/building/Linker.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ Result<Linker::LinkResult> Linker::linkForTarget(const fs::path &target, const f
6464
testGen.setTargetPath(target);
6565

6666
auto siblings = testGen.buildDatabase->getArchiveObjectFiles(target);
67-
checkSiblingsExist(siblings);
6867
auto stubSources = stubGen.getStubSources(target);
6968

7069
CollectionUtils::MapFileTo<fs::path> filesToLink;
@@ -143,7 +142,6 @@ Result<Linker::LinkResult> Linker::linkWholeTarget(const fs::path &target) {
143142
auto targetUnitInfo = testGen.buildDatabase->getClientLinkUnitInfo(target);
144143
auto siblings = testGen.buildDatabase->getArchiveObjectFiles(target);
145144

146-
checkSiblingsExist(siblings);
147145
auto stubSources = stubGen.getStubSources(target);
148146

149147
CollectionUtils::MapFileTo<fs::path> filesToLink;
@@ -242,20 +240,6 @@ void Linker::addToGenerated(const CollectionUtils::FileSet &objectFiles, const f
242240
}
243241
}
244242

245-
void Linker::checkSiblingsExist(const CollectionUtils::FileSet &archivedFiles) const {
246-
for (const auto &objectFile : archivedFiles) {
247-
auto objectInfo = testGen.buildDatabase->getClientCompilationUnitInfo(objectFile);
248-
const fs::path &sourcePath = objectInfo->getSourcePath();
249-
if (!CollectionUtils::contains(testGen.sourcePaths, sourcePath)) {
250-
throw CompilationDatabaseException(
251-
"Source file is not registered: " + sourcePath.string() +
252-
"\nPlease check if directory is in source directories in UTBot extension "
253-
"settings: " +
254-
sourcePath.parent_path().string());
255-
}
256-
}
257-
}
258-
259243
void Linker::prepareArtifacts() {
260244
if (isForOneFile()) {
261245
fs::path sourceFilePath = getSourceFilePath();

server/src/testgens/FileTestGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
FileTestGen::FileTestGen(const testsgen::FileRequest &request,
1010
ProgressWriter *progressWriter,
1111
bool testMode)
12-
: ProjectTestGen(request.projectrequest(), progressWriter, testMode),
12+
: ProjectTestGen(request.projectrequest(), progressWriter, testMode, false),
1313
filepath(request.filepath()) {
1414
testingMethodsSourcePaths = { filepath };
1515
setInitializedTestsMap();

server/src/testgens/FolderTestGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
FolderTestGen::FolderTestGen(const testsgen::FolderRequest &request,
1010
ProgressWriter *progressWriter,
1111
bool testMode)
12-
: ProjectTestGen(request.projectrequest(), progressWriter, testMode),
12+
: ProjectTestGen(request.projectrequest(), progressWriter, testMode, false),
1313
folderPath(request.folderpath()) {
1414
testingMethodsSourcePaths = {};
1515
std::copy_if(sourcePaths.begin(), sourcePaths.end(),

server/src/testgens/LineTestGen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
LineTestGen::LineTestGen(const testsgen::LineRequest &request,
88
ProgressWriter *progressWriter,
99
bool testMode, bool forHeader)
10-
: ProjectTestGen(request.projectrequest(), progressWriter, testMode) {
10+
: ProjectTestGen(request.projectrequest(), progressWriter, testMode, false) {
1111
filePath = request.sourceinfo().filepath();
1212
line = request.sourceinfo().line();
13-
std::optional sourcePath = Paths::headerPathToSourcePath(filePath);
13+
std::optional<fs::path> sourcePath = Paths::headerPathToSourcePath(filePath);
1414
if (forHeader && sourcePath.has_value()) {
1515
testingMethodsSourcePaths = {sourcePath.value()};
1616
} else {

server/src/testgens/ProjectTestGen.cpp

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
ProjectTestGen::ProjectTestGen(const testsgen::ProjectRequest &request,
1313
ProgressWriter *progressWriter,
14-
bool testMode)
14+
bool testMode,
15+
bool autoDetect)
1516
: BaseTestGen(request.projectcontext(),
1617
request.settingscontext(),
1718
progressWriter,
@@ -22,20 +23,12 @@ ProjectTestGen::ProjectTestGen(const testsgen::ProjectRequest &request,
2223
buildDatabase =
2324
std::make_shared<BuildDatabase>(compileCommandsJsonPath, serverBuildDir, projectContext);
2425
compilationDatabase = CompilationUtils::getCompilationDatabase(compileCommandsJsonPath);
25-
vector<fs::path> sourcePathsCandidates;
26-
for (const auto &compileCommand : compilationDatabase->getAllCompileCommands()) {
27-
try {
28-
fs::path path = Paths::getCCJsonFileFullPath(compileCommand.Filename, compileCommand.Directory);
29-
sourcePathsCandidates.push_back(path);
30-
} catch (...) {
31-
throw CompilationDatabaseException("Cannot detect file: " + compileCommand.Filename +
32-
". Maybe you need to rebuild the project.");
33-
}
26+
if (autoDetect) {
27+
autoDetectSourcePathsIfNotEmpty();
28+
} else {
29+
vector<fs::path> sourcePathsCandidates = getSourcePathCandidates();
30+
sourcePaths = sourcePathsCandidates;
3431
}
35-
auto requestSourcePaths = CollectionUtils::transformTo<vector<fs::path>>(
36-
request.sourcepaths(), [](std::string const &sourcePath) { return fs::path(sourcePath); });
37-
sourcePaths =
38-
Paths::filterPathsByDirNames(sourcePathsCandidates, requestSourcePaths, { ".c", ".cpp", ".cc" });
3932
testingMethodsSourcePaths = sourcePaths;
4033
setInitializedTestsMap();
4134
}
@@ -55,3 +48,36 @@ void ProjectTestGen::setTargetForSource(const fs::path &sourcePath) {
5548
const testsgen::ProjectRequest *ProjectTestGen::getRequest() const {
5649
return request;
5750
}
51+
52+
vector<fs::path> ProjectTestGen::getRequestSourcePaths() const {
53+
return CollectionUtils::transformTo<vector<fs::path>>(
54+
request->sourcepaths(), [](std::string const &sourcePath) { return fs::path(sourcePath); });
55+
}
56+
57+
vector<fs::path> ProjectTestGen::getSourcePathCandidates() const {
58+
vector<fs::path> sourcePathsCandidates;
59+
for (const auto &compileCommand : compilationDatabase->getAllCompileCommands()) {
60+
try {
61+
fs::path path = Paths::getCCJsonFileFullPath(compileCommand.Filename, compileCommand.Directory);
62+
sourcePathsCandidates.push_back(path);
63+
} catch (...) {
64+
throw CompilationDatabaseException("Cannot detect file: " + compileCommand.Filename +
65+
". Maybe you need to rebuild the project.");
66+
}
67+
}
68+
return sourcePathsCandidates;
69+
}
70+
void ProjectTestGen::autoDetectSourcePathsIfNotEmpty() {
71+
// requestSourcePaths are from settings.json
72+
auto requestSourcePaths = getRequestSourcePaths();
73+
// sourcePathsCandidates are from compile_commands.json
74+
auto sourcePathsCandidates = getSourcePathCandidates();
75+
if (!requestSourcePaths.empty()) {
76+
sourcePaths =
77+
Paths::filterPathsByDirNames(sourcePathsCandidates, requestSourcePaths, Paths::isSourceFile);
78+
} else {
79+
sourcePaths = sourcePathsCandidates;
80+
}
81+
}
82+
83+

server/src/testgens/ProjectTestGen.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ class ProjectTestGen : public BaseTestGen {
1414
public:
1515
ProjectTestGen(const testsgen::ProjectRequest &request,
1616
ProgressWriter *progressWriter,
17-
bool testMode);
17+
bool testMode,
18+
bool autoDetect = true);
1819

1920
~ProjectTestGen() override = default;
2021

@@ -26,6 +27,12 @@ class ProjectTestGen : public BaseTestGen {
2627

2728
private:
2829
testsgen::ProjectRequest const *const request;
30+
31+
vector<fs::path> getSourcePathCandidates() const;
32+
33+
vector<fs::path> getRequestSourcePaths() const;
34+
35+
void autoDetectSourcePathsIfNotEmpty();
2936
};
3037

3138

server/test/framework/Server_Tests.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,54 @@ namespace {
924924
}
925925
}
926926

927+
TEST_P(Parameterized_Server_Test, Project_Test_Auto_Detect_Src_Paths) {
928+
std::string suite = "small-project";
929+
setSuite(suite);
930+
srcPaths = {};
931+
auto request = createProjectRequest(projectName, suitePath, buildDirRelativePath, srcPaths);
932+
auto testGen = ProjectTestGen(*request, writer.get(), TESTMODE);
933+
testGen.setTargetForSource(testGen.testingMethodsSourcePaths[0]);
934+
935+
Status status = Server::TestsGenServiceImpl::ProcessBaseTestRequest(testGen, writer.get());
936+
ASSERT_TRUE(status.ok()) << status.error_message();
937+
938+
auto testFilePaths = CollectionUtils::getKeys(testGen.tests);
939+
EXPECT_TRUE(!testFilePaths.empty()) << "Generated test files are missing.";
940+
941+
EXPECT_FALSE(testFilePaths.size() < 2) << "Not enough test files are generated";
942+
EXPECT_FALSE(testFilePaths.size() > 2) << "More than needed test files are generated";
943+
944+
for (const auto &test : testGen.tests) {
945+
for (const auto &[methodName, methodDescription] : test.second.methods) {
946+
testUtils::checkMinNumberOfTests(methodDescription.testCases, 2);
947+
}
948+
}
949+
}
950+
951+
TEST_P(Parameterized_Server_Test, Project_Test_Detect_Src_Paths_From_Request) {
952+
std::string suite = "small-project";
953+
setSuite(suite);
954+
srcPaths = { suitePath / "lib"};
955+
auto request = createProjectRequest(projectName, suitePath, buildDirRelativePath, srcPaths);
956+
auto testGen = ProjectTestGen(*request, writer.get(), TESTMODE);
957+
testGen.setTargetForSource(testGen.testingMethodsSourcePaths[0]);
958+
959+
Status status = Server::TestsGenServiceImpl::ProcessBaseTestRequest(testGen, writer.get());
960+
ASSERT_TRUE(status.ok()) << status.error_message();
961+
962+
auto testFilePaths = CollectionUtils::getKeys(testGen.tests);
963+
EXPECT_TRUE(!testFilePaths.empty()) << "Generated test files are missing.";
964+
965+
EXPECT_FALSE(testFilePaths.size() < 1) << "Not enough test files are generated";
966+
EXPECT_FALSE(testFilePaths.size() > 1) << "More than needed test files are generated";
967+
968+
for (const auto &test : testGen.tests) {
969+
for (const auto &[methodName, methodDescription] : test.second.methods) {
970+
testUtils::checkMinNumberOfTests(methodDescription.testCases, 2);
971+
}
972+
}
973+
}
974+
927975
TEST_P(Parameterized_Server_Test, File_Test) {
928976
auto projectRequest =
929977
createProjectRequest(projectName, suitePath, buildDirRelativePath, srcPaths);

server/test/framework/Utils_Tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ namespace {
7272
projectPath / "zzz/snippet.c"
7373
};
7474
vector<fs::path> dirNames{ projectPath };
75-
auto filteredPaths = Paths::filterPathsByDirNames(paths, dirNames, { ".c" });
75+
auto filteredPaths = Paths::filterPathsByDirNames(paths, dirNames, Paths::isCFile);
7676
EXPECT_EQ(vector<fs::path>({
7777
projectPath / "basic_functions.c",
7878
projectPath / "types.c"}),

0 commit comments

Comments
 (0)