Skip to content

Commit 0e59302

Browse files
committed
#318 Remove code duplicate and fix the procedure for writing statistic
1 parent 0904755 commit 0e59302

File tree

1 file changed

+92
-135
lines changed

1 file changed

+92
-135
lines changed

server/src/KleeRunner.cpp

Lines changed: 92 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
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

1718
using namespace tests;
@@ -119,56 +120,10 @@ namespace {
119120
}
120121
}
121122

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-
123+
static void processMethod(MethodKtests &ktestChunk,
124+
tests::Tests &tests,
125+
const fs::path &kleeOut,
126+
const tests::TestMethod &method) {
172127
if (fs::exists(kleeOut)) {
173128
clearUnusedData(kleeOut);
174129
bool hasTimeout = false;
@@ -198,32 +153,89 @@ void KleeRunner::processBatchWithoutInteractive(MethodKtests &ktestChunk,
198153
return UTBotKTestObject{ kTestObject };
199154
});
200155

201-
ktestChunk[testMethod].emplace_back(objects, status);
156+
ktestChunk[method].emplace_back(objects, status);
202157
}
203158
}
204159
}
205160
if (hasTimeout) {
206161
std::string message = StringUtils::stringFormat(
207162
"Some tests for function '%s' were skipped, as execution of function is "
208163
"out of timeout.",
209-
testMethod.methodName);
164+
method.methodName);
210165
tests.commentBlocks.emplace_back(std::move(message));
211166
}
212167
if (hasError) {
213168
std::string message = StringUtils::stringFormat(
214169
"Some tests for function '%s' were skipped, as execution of function leads "
215170
"KLEE to the internal error. See console log for more details.",
216-
testMethod.methodName);
171+
method.methodName);
217172
tests.commentBlocks.emplace_back(std::move(message));
218173
}
174+
219175
writeKleeStats(kleeOut);
176+
177+
if (!CollectionUtils::containsKey(ktestChunk, method) || ktestChunk.at(method).empty()) {
178+
tests.commentBlocks.emplace_back(StringUtils::stringFormat(
179+
"Tests for %s were not generated. Maybe the function is too complex.",
180+
method.methodName));
181+
}
182+
}
183+
}
184+
185+
void KleeRunner::processBatchWithoutInteractive(MethodKtests &ktestChunk,
186+
const TestMethod &testMethod,
187+
Tests &tests) {
188+
if (!tests.isFilePresentedInArtifact) {
189+
return;
190+
}
191+
if (testMethod.sourceFilePath != tests.sourceFilePath) {
192+
std::string message = StringUtils::stringFormat(
193+
"While generating tests for source file: %s tried to generate tests for method %s "
194+
"from another source file: %s. This can cause invalid generation.\n",
195+
tests.sourceFilePath, testMethod.methodName, testMethod.sourceFilePath);
196+
LOG_S(WARNING) << message;
197+
}
198+
199+
std::string entryPoint = KleeUtils::entryPointFunction(tests, testMethod.methodName, true);
200+
std::string entryPointFlag = StringUtils::stringFormat("--entry-point=%s", entryPoint);
201+
auto kleeOut = getKleeMethodOutFile(testMethod);
202+
fs::create_directories(kleeOut.parent_path());
203+
std::string outputDir = "--output-dir=" + kleeOut.string();
204+
std::vector<std::string> argvData = { "klee",
205+
entryPointFlag,
206+
"--libc=klee",
207+
"--posix-runtime",
208+
"--fp-runtime",
209+
"--only-output-states-covering-new",
210+
"--allocate-determ",
211+
"--external-calls=all",
212+
"--timer-interval=1000ms",
213+
"--bcov-check-interval=6s",
214+
"-istats-write-interval=5s",
215+
"--disable-verify",
216+
"--check-div-zero=false",
217+
"--check-overshift=false",
218+
"--skip-not-lazy-and-symbolic-pointers",
219+
outputDir };
220+
if (settingsContext.useDeterministicSearcher) {
221+
argvData.emplace_back("--search=dfs");
220222
}
223+
argvData.push_back(testMethod.bitcodeFilePath);
224+
argvData.emplace_back("--sym-stdin");
225+
argvData.emplace_back(std::to_string(types::Type::symStdinSize));
221226

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));
227+
{
228+
std::vector<char *> cargv, cenvp;
229+
std::vector<std::string> tmp;
230+
ExecUtils::toCArgumentsPtr(argvData, tmp, cargv, cenvp, false);
231+
LOG_S(DEBUG) << "Klee command :: " + StringUtils::joinWith(argvData, " ");
232+
MEASURE_FUNCTION_EXECUTION_TIME
233+
234+
RunKleeTask task(cargv.size(), cargv.data(), settingsContext.timeoutPerFunction);
235+
ExecUtils::ExecutionResult result __attribute__((unused)) = task.run();
236+
ExecUtils::throwIfCancelled();
237+
238+
processMethod(ktestChunk, tests, kleeOut, testMethod);
227239
}
228240
}
229241

@@ -238,7 +250,7 @@ void KleeRunner::processBatchWithInteractive(const std::vector<tests::TestMethod
238250
if (method.sourceFilePath != tests.sourceFilePath) {
239251
std::string message = StringUtils::stringFormat(
240252
"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",
253+
"from another source file: %s. This can cause invalid generation.\n",
242254
tests.sourceFilePath, method.methodName, method.sourceFilePath);
243255
LOG_S(WARNING) << message;
244256
}
@@ -287,86 +299,31 @@ void KleeRunner::processBatchWithInteractive(const std::vector<tests::TestMethod
287299
argvData.push_back(testMethod.bitcodeFilePath);
288300
argvData.emplace_back("--sym-stdin");
289301
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);
293302

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+
std::vector<char *> cargv, cenvp;
305+
std::vector<std::string> tmp;
306+
ExecUtils::toCArgumentsPtr(argvData, tmp, cargv, cenvp, false);
303307

304-
ExecUtils::throwIfCancelled();
308+
LOG_S(DEBUG) << "Klee command :: " + StringUtils::joinWith(argvData, " ");
309+
MEASURE_FUNCTION_EXECUTION_TIME
305310

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);
334-
335-
std::vector<UTBotKTestObject> objects = CollectionUtils::transform(
336-
kTestObjects, [](const ConcretizedObject &kTestObject) {
337-
return UTBotKTestObject{ kTestObject };
338-
});
339-
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-
}
311+
RunKleeTask task(cargv.size(),
312+
cargv.data(),
313+
settingsContext.timeoutPerFunction.has_value()
314+
? settingsContext.timeoutPerFunction.value() * testMethods.size()
315+
: settingsContext.timeoutPerFunction);
316+
ExecUtils::ExecutionResult result __attribute__((unused)) = task.run();
359317

360-
if (fs::exists(kleeOut)) {
361-
writeKleeStats(kleeOut);
362-
}
318+
ExecUtils::throwIfCancelled();
363319

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));
320+
for (const auto &method : testMethods) {
321+
std::string kleeMethodName =
322+
KleeUtils::entryPointFunction(tests, method.methodName, true);
323+
fs::path newKleeOut = kleeOut / kleeMethodName;
324+
MethodKtests ktestChunk;
325+
processMethod(ktestChunk, tests, newKleeOut, method);
326+
ktests.push_back(ktestChunk);
369327
}
370-
ktests.push_back(ktestChunk);
371328
}
372329
}

0 commit comments

Comments
 (0)