1
1
#include < utils/stats/TestsExecutionStats.h>
2
+ #include < utils/KleeUtils.h>
2
3
#include " TestRunner.h"
3
4
4
5
#include " printers/DefaultMakefilePrinter.h"
@@ -18,33 +19,37 @@ TestRunner::TestRunner(utbot::ProjectContext projectContext,
18
19
std::string testFilePath,
19
20
std::string testSuite,
20
21
std::string testName,
22
+ std::string functionName,
21
23
ProgressWriter const *progressWriter)
22
- : projectContext(std::move(projectContext)),
23
- testFilePath(testFilePath.empty() ? std::nullopt : std::make_optional(testFilePath)),
24
- testSuite(std::move(testSuite)), testName(std::move(testName)),
25
- progressWriter(progressWriter) {
24
+ : projectContext(std::move(projectContext)),
25
+ testFilePath(testFilePath.empty() ? std::nullopt : std::make_optional(testFilePath)),
26
+ testSuite(std::move(testSuite)), testName(std::move(testName)), functionName(std::move(functionName )),
27
+ progressWriter(progressWriter) {
26
28
}
27
29
28
30
TestRunner::TestRunner (
29
- const testsgen::CoverageAndResultsRequest *coverageAndResultsRequest,
30
- grpc::ServerWriter<testsgen::CoverageAndResultsResponse> *coverageAndResultsWriter,
31
- std::string testFilename,
32
- std::string testSuite,
33
- std::string testName)
34
- : TestRunner(utbot::ProjectContext(coverageAndResultsRequest->projectcontext ()),
35
- std::move(testFilename),
36
- std::move(testSuite),
37
- std::move(testName),
38
- &writer) {
31
+ const testsgen::CoverageAndResultsRequest *coverageAndResultsRequest,
32
+ grpc::ServerWriter<testsgen::CoverageAndResultsResponse> *coverageAndResultsWriter,
33
+ std::string testFilename,
34
+ std::string testSuite,
35
+ std::string testName,
36
+ std::string functionName)
37
+ : TestRunner(utbot::ProjectContext(coverageAndResultsRequest->projectcontext ()),
38
+ std::move(testFilename),
39
+ std::move(testSuite),
40
+ std::move(testName),
41
+ std::move(functionName),
42
+ &writer) {
39
43
writer = ServerCoverageAndResultsWriter (coverageAndResultsWriter);
40
44
}
41
45
42
46
std::vector<UnitTest> TestRunner::getTestsFromMakefile (const fs::path &makefile,
43
- const fs::path &testFilePath) {
47
+ const fs::path &testFilePath,
48
+ const std::string &filter) {
44
49
auto cmdGetAllTests = MakefileUtils::MakefileCommand (projectContext, makefile,
45
50
printer::DefaultMakefilePrinter::TARGET_RUN,
46
- " --gtest_list_tests" , {" GTEST_FILTER=* " });
47
- auto [out, status, _] = cmdGetAllTests.run (projectContext.getBuildDirAbsPath (), false );
51
+ " --gtest_list_tests" , {" GTEST_FILTER=" + filter });
52
+ auto [out, status, _] = cmdGetAllTests.run (projectContext.getBuildDirAbsPath (), false );
48
53
if (status != 0 ) {
49
54
auto [err, _, logFilePath] = cmdGetAllTests.run (projectContext.getBuildDirAbsPath (), true );
50
55
progressWriter->writeProgress (StringUtils::stringFormat (" command %s failed.\n "
@@ -55,12 +60,14 @@ std::vector<UnitTest> TestRunner::getTestsFromMakefile(const fs::path &makefile,
55
60
throw ExecutionProcessException (err, logFilePath.value ());
56
61
}
57
62
if (out.empty ()) {
58
- LOG_S (WARNING) << " Running gtest with flag --gtest_list_tests returns empty output. Does file contain main function?" ;
63
+ LOG_S (WARNING)
64
+ << " Running gtest with flag --gtest_list_tests returns empty output. Does file contain main function?" ;
59
65
return {};
60
66
}
61
67
std::vector<std::string> gtestListTestsOutput = StringUtils::split (out, ' \n ' );
62
- gtestListTestsOutput.erase (gtestListTestsOutput.begin ()); // GTEST prints "Running main() from /opt/gtest/googletest/src/gtest_main.cc"
63
- for (std::string &s : gtestListTestsOutput) {
68
+ gtestListTestsOutput.erase (
69
+ gtestListTestsOutput.begin ()); // GTEST prints "Running main() from /opt/gtest/googletest/src/gtest_main.cc"
70
+ for (std::string &s: gtestListTestsOutput) {
64
71
StringUtils::trim (s);
65
72
}
66
73
std::string testSuite;
@@ -84,50 +91,65 @@ std::vector<UnitTest> TestRunner::getTestsToLaunch() {
84
91
if (fs::exists (projectContext.getTestDirAbsPath ())) {
85
92
FileSystemUtils::RecursiveDirectoryIterator directoryIterator (projectContext.getTestDirAbsPath ());
86
93
ExecUtils::doWorkWithProgress (
87
- directoryIterator, progressWriter, " Building tests" ,
88
- [this , &result](fs::directory_entry const &directoryEntry) {
89
- if (!directoryEntry.is_regular_file ()) {
90
- return ;
91
- }
92
- const auto &testFilePath = directoryEntry.path ();
93
- if (testFilePath.extension () == Paths::CXX_EXTENSION &&
94
- StringUtils::endsWith (testFilePath.stem ().c_str (), Paths::TEST_SUFFIX)) {
95
- fs::path sourcePath = Paths::testPathToSourcePath (projectContext, testFilePath);
96
- fs::path makefile =
97
- Paths::getMakefilePathFromSourceFilePath (projectContext, sourcePath);
98
- if (fs::exists (makefile)) {
99
- try {
100
- auto tests = getTestsFromMakefile (makefile, testFilePath);
101
- CollectionUtils::extend (result, tests);
102
- } catch (ExecutionProcessException const &e) {
103
- exceptions.push_back (e);
94
+ directoryIterator, progressWriter, " Building tests" ,
95
+ [this , &result](fs::directory_entry const &directoryEntry) {
96
+ if (!directoryEntry.is_regular_file ()) {
97
+ return ;
98
+ }
99
+ const auto &testFilePath = directoryEntry.path ();
100
+ if (testFilePath.extension () == Paths::CXX_EXTENSION &&
101
+ StringUtils::endsWith (testFilePath.stem ().c_str (), Paths::TEST_SUFFIX)) {
102
+ fs::path sourcePath = Paths::testPathToSourcePath (projectContext, testFilePath);
103
+ fs::path makefile =
104
+ Paths::getMakefilePathFromSourceFilePath (projectContext, sourcePath);
105
+ if (fs::exists (makefile)) {
106
+ try {
107
+ auto tests = getTestsFromMakefile (makefile, testFilePath);
108
+ CollectionUtils::extend (result, tests);
109
+ } catch (ExecutionProcessException const &e) {
110
+ exceptions.push_back (e);
111
+ }
112
+ } else {
113
+ LOG_S (WARNING) << StringUtils::stringFormat (
114
+ " Makefile for %s not found, candidate: %s" , testFilePath, makefile);
104
115
}
105
116
} else {
106
- LOG_S (WARNING) << StringUtils::stringFormat (
107
- " Makefile for %s not found, candidate: %s" , testFilePath, makefile);
108
- }
109
- } else {
110
- if (!StringUtils::endsWith (testFilePath.stem ().c_str (), Paths::TEST_SUFFIX) &&
111
- !StringUtils::endsWith (testFilePath.stem ().c_str (), Paths::STUB_SUFFIX) &&
112
- !StringUtils::endsWith (testFilePath.stem ().c_str (), Paths::MAKE_WRAPPER_SUFFIX) &&
113
- !StringUtils::endsWith (testFilePath.c_str (), Paths::MAKEFILE_EXTENSION)) {
114
- LOG_S (WARNING) << " Found extra file in test directory: " << testFilePath;
117
+ if (!StringUtils::endsWith (testFilePath.stem ().c_str (), Paths::TEST_SUFFIX) &&
118
+ !StringUtils::endsWith (testFilePath.stem ().c_str (), Paths::STUB_SUFFIX) &&
119
+ !StringUtils::endsWith (testFilePath.stem ().c_str (), Paths::MAKE_WRAPPER_SUFFIX) &&
120
+ !StringUtils::endsWith (testFilePath.c_str (), Paths::MAKEFILE_EXTENSION)) {
121
+ LOG_S (WARNING) << " Found extra file in test directory: " << testFilePath;
122
+ }
115
123
}
116
- }
117
- });
124
+ });
118
125
} else {
119
126
LOG_S (WARNING) << " Test folder doesn't exist: " << projectContext.getTestDirAbsPath ();
120
127
}
121
128
return result;
122
129
}
123
- if (testName.empty ()) {
130
+
131
+ if (testName.empty () && functionName.empty ()) {
124
132
// for file
125
133
fs::path sourcePath = Paths::testPathToSourcePath (projectContext, testFilePath.value ());
126
134
fs::path makefile = Paths::getMakefilePathFromSourceFilePath (projectContext, sourcePath);
127
135
return getTestsFromMakefile (makefile, testFilePath.value ());
128
136
}
137
+
138
+ if (testName.empty ()) {
139
+ // for function
140
+ fs::path sourcePath = Paths::testPathToSourcePath (projectContext, testFilePath.value ());
141
+ fs::path makefile = Paths::getMakefilePathFromSourceFilePath (projectContext, sourcePath);
142
+
143
+
144
+ std::string renamedMethodDescription = KleeUtils::getRenamedOperator (functionName);
145
+ StringUtils::replaceColon (renamedMethodDescription);
146
+
147
+ std::string filter = " *." + renamedMethodDescription + Paths::TEST_SUFFIX + " *" ;
148
+
149
+ return getTestsFromMakefile (makefile, testFilePath.value (), filter);
150
+ }
129
151
// for single test
130
- return { UnitTest{ testFilePath.value (), testSuite, testName } };
152
+ return {UnitTest{testFilePath.value (), testSuite, testName} };
131
153
}
132
154
133
155
grpc::Status TestRunner::runTests (bool withCoverage, const std::optional<std::chrono::seconds> &testTimeout) {
@@ -136,22 +158,22 @@ grpc::Status TestRunner::runTests(bool withCoverage, const std::optional<std::ch
136
158
137
159
const auto buildRunCommands = coverageTool->getBuildRunCommands (testsToLaunch, withCoverage);
138
160
ExecUtils::doWorkWithProgress (buildRunCommands, progressWriter, " Running tests" ,
139
- [this , testTimeout] (BuildRunCommand const &buildRunCommand) {
140
- auto const &[unitTest, buildCommand, runCommand] =
141
- buildRunCommand;
142
- try {
143
- auto status = runTest (buildRunCommand, testTimeout);
144
- testResultMap[unitTest.testFilePath ][unitTest.testname ] = status;
145
- ExecUtils::throwIfCancelled ();
146
- } catch (ExecutionProcessException const &e) {
147
- testsgen::TestResultObject testRes;
148
- testRes.set_testfilepath (unitTest.testFilePath );
149
- testRes.set_testname (unitTest.testname );
150
- testRes.set_status (testsgen::TEST_FAILED);
151
- testResultMap[unitTest.testFilePath ][unitTest.testname ] = testRes;
152
- exceptions.emplace_back (e);
153
- }
154
- });
161
+ [this , testTimeout](BuildRunCommand const &buildRunCommand) {
162
+ auto const &[unitTest, buildCommand, runCommand] =
163
+ buildRunCommand;
164
+ try {
165
+ auto status = runTest (buildRunCommand, testTimeout);
166
+ testResultMap[unitTest.testFilePath ][unitTest.testname ] = status;
167
+ ExecUtils::throwIfCancelled ();
168
+ } catch (ExecutionProcessException const &e) {
169
+ testsgen::TestResultObject testRes;
170
+ testRes.set_testfilepath (unitTest.testFilePath );
171
+ testRes.set_testname (unitTest.testname );
172
+ testRes.set_status (testsgen::TEST_FAILED);
173
+ testResultMap[unitTest.testFilePath ][unitTest.testname ] = testRes;
174
+ exceptions.emplace_back (e);
175
+ }
176
+ });
155
177
LOG_S (DEBUG) << " All run commands were executed" ;
156
178
return Status::OK;
157
179
}
@@ -169,14 +191,14 @@ void TestRunner::init(bool withCoverage) {
169
191
}
170
192
}
171
193
172
- bool TestRunner::buildTest (const utbot::ProjectContext& projectContext, const fs::path& sourcePath) {
194
+ bool TestRunner::buildTest (const utbot::ProjectContext & projectContext, const fs::path & sourcePath) {
173
195
ExecUtils::throwIfCancelled ();
174
196
fs::path makefile = Paths::getMakefilePathFromSourceFilePath (projectContext, sourcePath);
175
197
if (fs::exists (makefile)) {
176
198
auto command = MakefileUtils::MakefileCommand (projectContext, makefile,
177
199
printer::DefaultMakefilePrinter::TARGET_BUILD, " " , {});
178
200
LOG_S (DEBUG) << " Try compile tests for: " << sourcePath.string ();
179
- auto [out, status, logFilePath] = command.run (projectContext.getBuildDirAbsPath (), true );
201
+ auto [out, status, logFilePath] = command.run (projectContext.getBuildDirAbsPath (), true );
180
202
if (status != 0 ) {
181
203
return false ;
182
204
}
@@ -185,18 +207,18 @@ bool TestRunner::buildTest(const utbot::ProjectContext& projectContext, const fs
185
207
return false ;
186
208
}
187
209
188
- size_t TestRunner::buildTests (const utbot::ProjectContext& projectContext, const tests::TestsMap& tests) {
210
+ size_t TestRunner::buildTests (const utbot::ProjectContext & projectContext, const tests::TestsMap & tests) {
189
211
size_t fail_count = 0 ;
190
212
for (const auto &[file, _]: tests) {
191
- if (!TestRunner::buildTest (projectContext, file)) {
213
+ if (!TestRunner::buildTest (projectContext, file)) {
192
214
fail_count++;
193
215
}
194
216
}
195
217
return fail_count;
196
218
}
197
219
198
220
testsgen::TestResultObject TestRunner::runTest (const BuildRunCommand &command,
199
- const std::optional <std::chrono::seconds> &testTimeout) {
221
+ const std::optional<std::chrono::seconds> &testTimeout) {
200
222
fs::remove (Paths::getGTestResultsJsonPath (projectContext));
201
223
auto res = command.runCommand .run (projectContext.getBuildDirAbsPath (), true , true , testTimeout);
202
224
GTestLogger::log (res.output );
0 commit comments