1
1
#include " KleeRunner.h"
2
2
3
3
#include " Paths.h"
4
+ #include " TimeExecStatistics.h"
4
5
#include " exceptions/FileNotPresentedInArtifactException.h"
5
6
#include " exceptions/FileNotPresentedInCommandsException.h"
6
7
#include " tasks/RunKleeTask.h"
7
8
#include " utils/ExecUtils.h"
8
9
#include " utils/FileSystemUtils.h"
9
10
#include " utils/KleeUtils.h"
10
11
#include " utils/LogUtils.h"
11
- #include " TimeExecStatistics.h"
12
12
13
13
#include " loguru.h"
14
14
15
+ #include < fstream>
15
16
#include < utility>
16
17
17
18
using namespace tests ;
@@ -92,13 +93,6 @@ void KleeRunner::runKlee(const std::vector<tests::TestMethod> &testMethods,
92
93
std::move (writeFunctor));
93
94
}
94
95
95
- fs::path KleeRunner::getKleeMethodOutFile (const TestMethod &method) {
96
- fs::path kleeOutDir = Paths::getKleeOutDir (projectTmpPath);
97
- fs::path relative =
98
- Paths::removeExtension (fs::relative (method.sourceFilePath , projectContext.projectPath ));
99
- return kleeOutDir / relative / (" klee_out_" + method.methodName );
100
- }
101
-
102
96
namespace {
103
97
void clearUnusedData (const fs::path &kleeDir) {
104
98
fs::remove (kleeDir / " assembly.ll" );
@@ -119,56 +113,10 @@ namespace {
119
113
}
120
114
}
121
115
122
- void KleeRunner::processBatchWithoutInteractive (MethodKtests &ktestChunk,
123
- const TestMethod &testMethod,
124
- Tests &tests) {
125
- if (!tests.isFilePresentedInArtifact ) {
126
- return ;
127
- }
128
- if (testMethod.sourceFilePath != tests.sourceFilePath ) {
129
- std::string message = StringUtils::stringFormat (
130
- " While generating tests for source file: %s tried to generate tests for method %s "
131
- " from another source file: %s. This can cause invalid generation.\n " ,
132
- tests.sourceFilePath , testMethod.methodName , testMethod.sourceFilePath );
133
- LOG_S (WARNING) << message;
134
- }
135
-
136
- std::string entryPoint = KleeUtils::entryPointFunction (tests, testMethod.methodName , true );
137
- std::string entryPointFlag = StringUtils::stringFormat (" --entry-point=%s" , entryPoint);
138
- auto kleeOut = getKleeMethodOutFile (testMethod);
139
- fs::create_directories (kleeOut.parent_path ());
140
- std::string outputDir = " --output-dir=" + kleeOut.string ();
141
- std::vector<std::string> argvData = { " klee" ,
142
- entryPointFlag,
143
- " --libc=klee" ,
144
- " --posix-runtime" ,
145
- " --fp-runtime" ,
146
- " --only-output-states-covering-new" ,
147
- " --allocate-determ" ,
148
- " --external-calls=all" ,
149
- " --timer-interval=1000ms" ,
150
- " --bcov-check-interval=6s" ,
151
- " -istats-write-interval=5s" ,
152
- " --disable-verify" ,
153
- " --check-div-zero=false" ,
154
- " --check-overshift=false" ,
155
- " --skip-not-lazy-and-symbolic-pointers" ,
156
- outputDir };
157
- if (settingsContext.useDeterministicSearcher ) {
158
- argvData.emplace_back (" --search=dfs" );
159
- }
160
- argvData.push_back (testMethod.bitcodeFilePath );
161
- argvData.emplace_back (" --sym-stdin" );
162
- argvData.emplace_back (std::to_string (types::Type::symStdinSize));
163
- std::vector<char *> cargv, cenvp;
164
- std::vector<std::string> tmp;
165
- ExecUtils::toCArgumentsPtr (argvData, tmp, cargv, cenvp, false );
166
- LOG_S (DEBUG) << " Klee command :: " + StringUtils::joinWith (argvData, " " );
167
- MEASURE_FUNCTION_EXECUTION_TIME
168
- RunKleeTask task (cargv.size (), cargv.data (), settingsContext.timeoutPerFunction );
169
- ExecUtils::ExecutionResult result __attribute__ ((unused)) = task.run ();
170
- ExecUtils::throwIfCancelled ();
171
-
116
+ static void processMethod (MethodKtests &ktestChunk,
117
+ tests::Tests &tests,
118
+ const fs::path &kleeOut,
119
+ const tests::TestMethod &method) {
172
120
if (fs::exists (kleeOut)) {
173
121
clearUnusedData (kleeOut);
174
122
bool hasTimeout = false ;
@@ -198,32 +146,90 @@ void KleeRunner::processBatchWithoutInteractive(MethodKtests &ktestChunk,
198
146
return UTBotKTestObject{ kTestObject };
199
147
});
200
148
201
- ktestChunk[testMethod ].emplace_back (objects, status);
149
+ ktestChunk[method ].emplace_back (objects, status);
202
150
}
203
151
}
204
152
}
205
153
if (hasTimeout) {
206
154
std::string message = StringUtils::stringFormat (
207
155
" Some tests for function '%s' were skipped, as execution of function is "
208
156
" out of timeout." ,
209
- testMethod .methodName );
157
+ method .methodName );
210
158
tests.commentBlocks .emplace_back (std::move (message));
211
159
}
212
160
if (hasError) {
213
161
std::string message = StringUtils::stringFormat (
214
162
" Some tests for function '%s' were skipped, as execution of function leads "
215
163
" KLEE to the internal error. See console log for more details." ,
216
- testMethod .methodName );
164
+ method .methodName );
217
165
tests.commentBlocks .emplace_back (std::move (message));
218
166
}
167
+
219
168
writeKleeStats (kleeOut);
169
+
170
+ if (!CollectionUtils::containsKey (ktestChunk, method) || ktestChunk.at (method).empty ()) {
171
+ tests.commentBlocks .emplace_back (StringUtils::stringFormat (
172
+ " Tests for %s were not generated. Maybe the function is too complex." ,
173
+ method.methodName ));
174
+ }
220
175
}
176
+ }
221
177
222
- if (!CollectionUtils::containsKey (ktestChunk, testMethod) ||
223
- ktestChunk.at (testMethod).empty ()) {
224
- tests.commentBlocks .emplace_back (StringUtils::stringFormat (
225
- " Tests for %s were not generated. Maybe the function is too complex." ,
226
- testMethod.methodName ));
178
+ void KleeRunner::processBatchWithoutInteractive (MethodKtests &ktestChunk,
179
+ const TestMethod &testMethod,
180
+ Tests &tests) {
181
+ if (!tests.isFilePresentedInArtifact ) {
182
+ return ;
183
+ }
184
+ if (testMethod.sourceFilePath != tests.sourceFilePath ) {
185
+ std::string message = StringUtils::stringFormat (
186
+ " While generating tests for source file: %s tried to generate tests for method %s "
187
+ " from another source file: %s. This can cause invalid generation.\n " ,
188
+ tests.sourceFilePath , testMethod.methodName , testMethod.sourceFilePath );
189
+ LOG_S (WARNING) << message;
190
+ }
191
+
192
+ std::string entryPoint = KleeUtils::entryPointFunction (tests, testMethod.methodName , true );
193
+ std::string entryPointFlag = StringUtils::stringFormat (" --entry-point=%s" , entryPoint);
194
+ auto kleeOut = Paths::kleeOutDirForEntrypoints (projectContext, projectTmpPath, testMethod.sourceFilePath ,
195
+ testMethod.methodName );
196
+ fs::create_directories (kleeOut.parent_path ());
197
+ std::string outputDir = " --output-dir=" + kleeOut.string ();
198
+ std::vector<std::string> argvData = { " klee" ,
199
+ entryPointFlag,
200
+ " --libc=klee" ,
201
+ " --posix-runtime" ,
202
+ " --fp-runtime" ,
203
+ " --only-output-states-covering-new" ,
204
+ " --allocate-determ" ,
205
+ " --external-calls=all" ,
206
+ " --timer-interval=1000ms" ,
207
+ " --bcov-check-interval=6s" ,
208
+ " -istats-write-interval=5s" ,
209
+ " --disable-verify" ,
210
+ " --check-div-zero=false" ,
211
+ " --check-overshift=false" ,
212
+ " --skip-not-lazy-and-symbolic-pointers" ,
213
+ outputDir };
214
+ if (settingsContext.useDeterministicSearcher ) {
215
+ argvData.emplace_back (" --search=dfs" );
216
+ }
217
+ argvData.push_back (testMethod.bitcodeFilePath );
218
+ argvData.emplace_back (" --sym-stdin" );
219
+ argvData.emplace_back (std::to_string (types::Type::symStdinSize));
220
+
221
+ {
222
+ std::vector<char *> cargv, cenvp;
223
+ std::vector<std::string> tmp;
224
+ ExecUtils::toCArgumentsPtr (argvData, tmp, cargv, cenvp, false );
225
+ LOG_S (DEBUG) << " Klee command :: " + StringUtils::joinWith (argvData, " " );
226
+ MEASURE_FUNCTION_EXECUTION_TIME
227
+
228
+ RunKleeTask task (cargv.size (), cargv.data (), settingsContext.timeoutPerFunction );
229
+ ExecUtils::ExecutionResult result __attribute__ ((unused)) = task.run ();
230
+ ExecUtils::throwIfCancelled ();
231
+
232
+ processMethod (ktestChunk, tests, kleeOut, testMethod);
227
233
}
228
234
}
229
235
@@ -238,7 +244,7 @@ void KleeRunner::processBatchWithInteractive(const std::vector<tests::TestMethod
238
244
if (method.sourceFilePath != tests.sourceFilePath ) {
239
245
std::string message = StringUtils::stringFormat (
240
246
" While generating tests for source file: %s tried to generate tests for method %s "
241
- " from another source file: %s. This can cause invalid generation.\n " ,
247
+ " from another source file: %s. This can cause invalid generation.\n " ,
242
248
tests.sourceFilePath , method.methodName , method.sourceFilePath );
243
249
LOG_S (WARNING) << message;
244
250
}
@@ -247,7 +253,7 @@ void KleeRunner::processBatchWithInteractive(const std::vector<tests::TestMethod
247
253
TestMethod testMethod = testMethods[0 ];
248
254
std::string entryPoint = KleeUtils::entryPointFunction (tests, testMethod.methodName , true );
249
255
std::string entryPointFlag = StringUtils::stringFormat (" --entry-point=%s" , entryPoint);
250
- auto kleeOut = getKleeMethodOutFile (testMethod );
256
+ auto kleeOut = Paths::kleeOutDirForEntrypoints (projectContext, projectTmpPath, tests. sourceFilePath );
251
257
fs::create_directories (kleeOut.parent_path ());
252
258
253
259
fs::path entrypoints = kleeOut.parent_path () / " entrypoints.txt" ;
@@ -287,86 +293,31 @@ void KleeRunner::processBatchWithInteractive(const std::vector<tests::TestMethod
287
293
argvData.push_back (testMethod.bitcodeFilePath );
288
294
argvData.emplace_back (" --sym-stdin" );
289
295
argvData.emplace_back (std::to_string (types::Type::symStdinSize));
290
- std::vector<char *> cargv, cenvp;
291
- std::vector<std::string> tmp;
292
- ExecUtils::toCArgumentsPtr (argvData, tmp, cargv, cenvp, false );
293
-
294
- LOG_S (DEBUG) << " Klee command :: " + StringUtils::joinWith (argvData, " " );
295
- MEASURE_FUNCTION_EXECUTION_TIME
296
- if (settingsContext.timeoutPerFunction .has_value ()) {
297
- RunKleeTask task (cargv.size (), cargv.data (), settingsContext.timeoutPerFunction .value () * testMethods.size ());
298
- ExecUtils::ExecutionResult result __attribute__ ((unused)) = task.run ();
299
- } else {
300
- RunKleeTask task (cargv.size (), cargv.data (), settingsContext.timeoutPerFunction );
301
- ExecUtils::ExecutionResult result __attribute__ ((unused)) = task.run ();
302
- }
303
-
304
- ExecUtils::throwIfCancelled ();
305
296
306
- for (const auto &method : testMethods) {
307
- std::string kleeMethodName = KleeUtils::entryPointFunction (tests, method.methodName , true );
308
- fs::path newKleeOut = kleeOut / kleeMethodName;
309
- MethodKtests ktestChunk;
310
- if (fs::exists (newKleeOut)) {
311
- clearUnusedData (newKleeOut);
312
- bool hasTimeout = false ;
313
- bool hasError = false ;
314
- for (auto const &entry : fs::directory_iterator (newKleeOut)) {
315
- auto const &path = entry.path ();
316
- if (Paths::isKtestJson (path)) {
317
- if (Paths::hasEarly (path)) {
318
- hasTimeout = true ;
319
- } else if (Paths::hasInternalError (path)) {
320
- hasError = true ;
321
- } else {
322
- std::unique_ptr<TestCase, decltype (&TestCase_free)> ktestData{
323
- TC_fromFile (path.c_str ()), TestCase_free
324
- };
325
- if (ktestData == nullptr ) {
326
- LOG_S (WARNING) << " Unable to open .ktestjson file" ;
327
- continue ;
328
- }
329
- UTBotKTest::Status status = Paths::hasError (path)
330
- ? UTBotKTest::Status::FAILED
331
- : UTBotKTest::Status::SUCCESS;
332
- std::vector<ConcretizedObject> kTestObjects (
333
- ktestData->objects , ktestData->objects + ktestData->n_objects );
297
+ {
298
+ std::vector<char *> cargv, cenvp;
299
+ std::vector<std::string> tmp;
300
+ ExecUtils::toCArgumentsPtr (argvData, tmp, cargv, cenvp, false );
334
301
335
- std::vector<UTBotKTestObject> objects = CollectionUtils::transform (
336
- kTestObjects , [](const ConcretizedObject &kTestObject ) {
337
- return UTBotKTestObject{ kTestObject };
338
- });
302
+ LOG_S (DEBUG) << " Klee command :: " + StringUtils::joinWith (argvData, " " );
303
+ MEASURE_FUNCTION_EXECUTION_TIME
339
304
340
- ktestChunk[method].emplace_back (objects, status);
341
- }
342
- }
343
- }
344
- if (hasTimeout) {
345
- std::string message = StringUtils::stringFormat (
346
- " Some tests for function '%s' were skipped, as execution of function is "
347
- " out of timeout." ,
348
- method.methodName );
349
- tests.commentBlocks .emplace_back (std::move (message));
350
- }
351
- if (hasError) {
352
- std::string message = StringUtils::stringFormat (
353
- " Some tests for function '%s' were skipped, as execution of function leads "
354
- " KLEE to the internal error. See console log for more details." ,
355
- method.methodName );
356
- tests.commentBlocks .emplace_back (std::move (message));
357
- }
358
- }
305
+ RunKleeTask task (cargv.size (),
306
+ cargv.data (),
307
+ settingsContext.timeoutPerFunction .has_value ()
308
+ ? settingsContext.timeoutPerFunction .value () * testMethods.size ()
309
+ : settingsContext.timeoutPerFunction );
310
+ ExecUtils::ExecutionResult result __attribute__ ((unused)) = task.run ();
359
311
360
- if (fs::exists (kleeOut)) {
361
- writeKleeStats (kleeOut);
362
- }
312
+ ExecUtils::throwIfCancelled ();
363
313
364
- if (!CollectionUtils::containsKey (ktestChunk, method) ||
365
- ktestChunk.at (method).empty ()) {
366
- tests.commentBlocks .emplace_back (StringUtils::stringFormat (
367
- " Tests for %s were not generated. Maybe the function is too complex." ,
368
- method.methodName ));
314
+ for (const auto &method : testMethods) {
315
+ std::string kleeMethodName =
316
+ KleeUtils::entryPointFunction (tests, method.methodName , true );
317
+ fs::path newKleeOut = kleeOut / kleeMethodName;
318
+ MethodKtests ktestChunk;
319
+ processMethod (ktestChunk, tests, newKleeOut, method);
320
+ ktests.push_back (ktestChunk);
369
321
}
370
- ktests.push_back (ktestChunk);
371
322
}
372
323
}
0 commit comments