11#include  " KleeRunner.h" 
22
33#include  " Paths.h" 
4+ #include  " TimeExecStatistics.h" 
45#include  " exceptions/FileNotPresentedInArtifactException.h" 
56#include  " exceptions/FileNotPresentedInCommandsException.h" 
67#include  " tasks/RunKleeTask.h" 
78#include  " utils/ExecUtils.h" 
89#include  " utils/FileSystemUtils.h" 
910#include  " utils/KleeUtils.h" 
1011#include  " utils/LogUtils.h" 
11- #include  " TimeExecStatistics.h" 
1212
1313#include  " loguru.h" 
1414
15+ #include  < fstream> 
1516#include  < utility> 
1617
1718using  namespace  tests ; 
@@ -92,13 +93,6 @@ void KleeRunner::runKlee(const std::vector<tests::TestMethod> &testMethods,
9293                                        std::move (writeFunctor));
9394}
9495
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_" methodName );
100- }
101- 
10296namespace  {
10397    void  clearUnusedData (const  fs::path &kleeDir) {
10498        fs::remove (kleeDir / " assembly.ll" 
@@ -119,56 +113,10 @@ namespace {
119113    }
120114}
121115
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" 
138-     auto  kleeOut = getKleeMethodOutFile (testMethod);
139-     fs::create_directories (kleeOut.parent_path ());
140-     std::string outputDir = " --output-dir=" 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) {
172120    if  (fs::exists (kleeOut)) {
173121        clearUnusedData (kleeOut);
174122        bool  hasTimeout = false ;
@@ -198,32 +146,90 @@ void KleeRunner::processBatchWithoutInteractive(MethodKtests &ktestChunk,
198146                            return  UTBotKTestObject{ kTestObject  };
199147                        });
200148
201-                     ktestChunk[testMethod ].emplace_back (objects, status);
149+                     ktestChunk[method ].emplace_back (objects, status);
202150                }
203151            }
204152        }
205153        if  (hasTimeout) {
206154            std::string message = StringUtils::stringFormat (
207155                " Some tests for function '%s' were skipped, as execution of function is " 
208156                " out of timeout." 
209-                 testMethod .methodName );
157+                 method .methodName );
210158            tests.commentBlocks .emplace_back (std::move (message));
211159        }
212160        if  (hasError) {
213161            std::string message = StringUtils::stringFormat (
214162                " Some tests for function '%s' were skipped, as execution of function leads " 
215163                " KLEE to the internal error. See console log for more details." 
216-                 testMethod .methodName );
164+                 method .methodName );
217165            tests.commentBlocks .emplace_back (std::move (message));
218166        }
167+ 
219168        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+         }
220175    }
176+ }
221177
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" 
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=" 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);
227233    }
228234}
229235
@@ -238,7 +244,7 @@ void KleeRunner::processBatchWithInteractive(const std::vector<tests::TestMethod
238244        if  (method.sourceFilePath  != tests.sourceFilePath ) {
239245            std::string message = StringUtils::stringFormat (
240246                " 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 " 
242248                tests.sourceFilePath , method.methodName , method.sourceFilePath );
243249            LOG_S (WARNING) << message;
244250        }
@@ -247,7 +253,7 @@ void KleeRunner::processBatchWithInteractive(const std::vector<tests::TestMethod
247253    TestMethod testMethod = testMethods[0 ];
248254    std::string entryPoint = KleeUtils::entryPointFunction (tests, testMethod.methodName , true );
249255    std::string entryPointFlag = StringUtils::stringFormat (" --entry-point=%s" 
250-     auto  kleeOut = getKleeMethodOutFile (testMethod );
256+     auto  kleeOut = Paths::kleeOutDirForEntrypoints (projectContext, projectTmpPath, tests. sourceFilePath );
251257    fs::create_directories (kleeOut.parent_path ());
252258
253259    fs::path entrypoints = kleeOut.parent_path () / " entrypoints.txt" 
@@ -287,86 +293,31 @@ void KleeRunner::processBatchWithInteractive(const std::vector<tests::TestMethod
287293    argvData.push_back (testMethod.bitcodeFilePath );
288294    argvData.emplace_back (" --sym-stdin" 
289295    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 ();
305296
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 );
334301
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
339304
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 ();
359311
360-         if  (fs::exists (kleeOut)) {
361-             writeKleeStats (kleeOut);
362-         }
312+         ExecUtils::throwIfCancelled ();
363313
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);
369321        }
370-         ktests.push_back (ktestChunk);
371322    }
372323}
0 commit comments