Skip to content

Commit c706e17

Browse files
committed
fix PR comments
1 parent 63f4b30 commit c706e17

19 files changed

+62
-66
lines changed

server/proto/testgen.proto

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ syntax = "proto3";
33
package testsgen;
44

55
import "util.proto";
6+
import "google/protobuf/duration.proto";
67

78
service TestsGenService {
89
rpc Handshake(DummyRequest) returns(DummyResponse) {}
@@ -188,7 +189,7 @@ message TestResultObject {
188189
string testname = 2;
189190
TestStatus status = 3;
190191
string output = 4;
191-
uint32 executionTimeMs = 5;
192+
google.protobuf.Duration executionTime = 5;
192193
}
193194

194195
message CoverageAndResultsResponse {

server/src/KleeGenerator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ KleeGenerator::buildByCDb(const CollectionUtils::MapFileTo<fs::path> &filesToBui
5757
fs::path makefile = projectTmpPath / "GenerationCompileMakefile.mk";
5858
FileSystemUtils::writeToFile(makefile, makefilePrinter.ss.str());
5959

60-
auto command = MakefileUtils::makefileCommand(projectContext, makefile, "all");
60+
auto command = MakefileUtils::MakefileCommand(projectContext, makefile, "all");
6161
ExecUtils::ExecutionResult res = command.run();
6262
if (res.status != 0) {
6363
LOG_S(ERROR) << StringUtils::stringFormat("Make for \"%s\" failed.\nCommand: \"%s\"\n%s\n",

server/src/Paths.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ namespace Paths {
183183
fs::path getArtifactsRootDir(const utbot::ProjectContext &projectContext) {
184184
return projectContext.buildDir / "utbot";
185185
}
186+
fs::path getGTestResultsJsonPath(const utbot::ProjectContext &projectContext) {
187+
return getArtifactsRootDir(projectContext) / "gtest-results.json";
188+
}
186189
fs::path getFlagsDir(const utbot::ProjectContext &projectContext) {
187190
return getArtifactsRootDir(projectContext) / "flags";
188191
}

server/src/Paths.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ namespace Paths {
273273

274274
fs::path getArtifactsRootDir(const utbot::ProjectContext &projectContext);
275275

276+
fs::path getGTestResultsJsonPath(const utbot::ProjectContext &projectContext);
277+
276278
fs::path getFlagsDir(const utbot::ProjectContext &projectContext);
277279

278280
fs::path getTestExecDir(const utbot::ProjectContext &projectContext);

server/src/building/Linker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ Result<Linker::LinkResult> Linker::link(const CollectionUtils::MapFileTo<fs::pat
364364
FileSystemUtils::writeToFile(linkMakefile, bitcodeLinkMakefilePrinter.ss.str());
365365

366366
auto command =
367-
MakefileUtils::makefileCommand(testGen.projectContext, linkMakefile, targetBitcode);
367+
MakefileUtils::MakefileCommand(testGen.projectContext, linkMakefile, targetBitcode);
368368
auto [out, status, logFilePath] = command.run(testGen.serverBuildDir);
369369
if (status != 0) {
370370
std::string errorMessage =
@@ -477,7 +477,7 @@ Result<utbot::Void> Linker::linkWithStubsIfNeeded(const fs::path &linkMakefile,
477477
return errorMessage;
478478
}
479479

480-
auto command = MakefileUtils::makefileCommand(testGen.projectContext, linkMakefile, "all");
480+
auto command = MakefileUtils::MakefileCommand(testGen.projectContext, linkMakefile, "all");
481481
auto [out, status, _] = command.run(testGen.serverBuildDir);
482482
if (status != 0) {
483483
std::string errorMessage =

server/src/coverage/Coverage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "utils/CollectionUtils.h"
55

66
#include <protobuf/testgen.grpc.pb.h>
7+
#include <google/protobuf/util/time_util.h>
78

89
#include <unordered_map>
910
#include <vector>

server/src/coverage/CoverageAndResultsGenerator.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,19 @@ grpc::Status CoverageAndResultsGenerator::generate(bool withCoverage,
3737
}
3838
} catch (CoverageGenerationException &e) {
3939
showErrors();
40+
fs::remove(Paths::getGTestResultsJsonPath(projectContext));
4041
return Status(StatusCode::FAILED_PRECONDITION, e.what());
4142
} catch (ExecutionProcessException &e) {
4243
exceptions.emplace_back(e);
4344
showErrors();
45+
fs::remove(Paths::getGTestResultsJsonPath(projectContext));
4446
return Status(StatusCode::FAILED_PRECONDITION, e.what());
4547
} catch (CancellationException &e) {
48+
fs::remove(Paths::getGTestResultsJsonPath(projectContext));
4649
return Status::CANCELLED;
4750
}
48-
4951
showErrors();
52+
fs::remove(Paths::getGTestResultsJsonPath(projectContext));
5053
return Status::OK;
5154
}
5255

server/src/coverage/CoverageTool.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88

99
using namespace CompilationUtils;
1010

11-
CoverageTool::CoverageTool(ProgressWriter const *progressWriter) : progressWriter(progressWriter) {
11+
CoverageTool::CoverageTool(utbot::ProjectContext projectContext, ProgressWriter const *progressWriter) :
12+
projectContext(std::move(projectContext)), progressWriter(progressWriter) {
1213
}
1314

1415
std::unique_ptr<CoverageTool> getCoverageTool(const std::string &compileCommandsJsonPath,
@@ -29,6 +30,10 @@ std::unique_ptr<CoverageTool> getCoverageTool(const std::string &compileCommands
2930
}
3031
}
3132

32-
std::string CoverageTool::getTestFilter(const UnitTest &unitTest) const {
33-
return StringUtils::stringFormat("--gtest_filter=*.%s", unitTest.testname);
33+
std::string CoverageTool::getGTestFlags(const UnitTest &unitTest) const {
34+
std::string gtestFilterFlag = StringUtils::stringFormat("\"--gtest_filter=*.%s\"", unitTest.testname);
35+
std::string gtestOutputFlag = StringUtils::stringFormat("\"--gtest_output=json:%s\"",
36+
Paths::getGTestResultsJsonPath(projectContext));
37+
std::vector<std::string> gtestFlagsList = { gtestFilterFlag, gtestOutputFlag };
38+
return StringUtils::joinWith(gtestFlagsList, " ");
3439
}

server/src/coverage/CoverageTool.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ struct BuildRunCommand {
2020
class CoverageTool {
2121
protected:
2222
ProgressWriter const *progressWriter;
23+
const utbot::ProjectContext projectContext;
2324

24-
[[nodiscard]] std::string getTestFilter(UnitTest const &unitTest) const;
25+
[[nodiscard]] std::string getGTestFlags(const UnitTest &unitTest) const;
2526

2627
public:
27-
explicit CoverageTool(ProgressWriter const *progressWriter);
28+
CoverageTool(utbot::ProjectContext projectContext, ProgressWriter const *progressWriter);
2829

2930
[[nodiscard]] virtual std::vector<BuildRunCommand>
3031
getBuildRunCommands(const std::vector<UnitTest> &testsToLaunch, bool withCoverage) = 0;

server/src/coverage/GcovCoverageTool.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ using Coverage::FileCoverage;
2424

2525
GcovCoverageTool::GcovCoverageTool(utbot::ProjectContext projectContext,
2626
ProgressWriter const *progressWriter)
27-
: CoverageTool(progressWriter), projectContext(std::move(projectContext)) {
27+
: CoverageTool(std::move(projectContext), progressWriter) {
2828
}
2929

3030
std::vector<BuildRunCommand>
@@ -38,11 +38,11 @@ GcovCoverageTool::getBuildRunCommands(const std::vector<UnitTest> &testsToLaunch
3838
auto makefile = Paths::getMakefilePathFromSourceFilePath(
3939
projectContext,
4040
Paths::testPathToSourcePath(projectContext, testToLaunch.testFilePath));
41-
auto gtestFlags = getTestFilter(testToLaunch);
41+
auto gtestFlags = getGTestFlags(testToLaunch);
4242
auto buildCommand =
43-
MakefileUtils::makefileCommand(projectContext, makefile, "build", gtestFlags);
43+
MakefileUtils::MakefileCommand(projectContext, makefile, "build", gtestFlags);
4444
auto runCommand =
45-
MakefileUtils::makefileCommand(projectContext, makefile, "run", gtestFlags);
45+
MakefileUtils::MakefileCommand(projectContext, makefile, "run", gtestFlags);
4646
result.push_back({ testToLaunch, buildCommand, runCommand });
4747
});
4848
return result;

server/src/coverage/GcovCoverageTool.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ class GcovCoverageTool : public CoverageTool {
2323
void cleanCoverage() const override;
2424

2525
private:
26-
const utbot::ProjectContext projectContext;
27-
2826
std::vector<fs::path> getGcdaFiles() const;
2927
};
3028

server/src/coverage/LlvmCoverageTool.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "LlvmCoverageTool.h"
22

3+
#include <utility>
4+
35
#include "Coverage.h"
46
#include "Paths.h"
57
#include "TimeExecStatistics.h"
@@ -20,7 +22,7 @@ using Coverage::FileCoverage;
2022

2123
LlvmCoverageTool::LlvmCoverageTool(utbot::ProjectContext projectContext,
2224
ProgressWriter const *progressWriter)
23-
: CoverageTool(progressWriter), projectContext(projectContext) {
25+
: CoverageTool(std::move(projectContext), progressWriter) {
2426
}
2527

2628
std::vector<BuildRunCommand>
@@ -30,15 +32,15 @@ LlvmCoverageTool::getBuildRunCommands(const std::vector<UnitTest> &testsToLaunch
3032
Paths::testPathToSourcePath(projectContext, testToLaunch.testFilePath);
3133
auto makefilePath = Paths::getMakefilePathFromSourceFilePath(projectContext, sourcePath);
3234
auto testName = testToLaunch.testname;
33-
auto gtestFlags = getTestFilter(testToLaunch);
35+
auto gtestFlags = getGTestFlags(testToLaunch);
3436
std::vector<std::string> profileEnv;
3537
if (withCoverage) {
3638
auto profrawFilePath = Paths::getProfrawFilePath(projectContext, testName);
3739
profileEnv = { StringUtils::stringFormat("LLVM_PROFILE_FILE=%s", profrawFilePath) };
3840
}
39-
auto buildCommand = MakefileUtils::makefileCommand(projectContext, makefilePath, "build",
41+
auto buildCommand = MakefileUtils::MakefileCommand(projectContext, makefilePath, "build",
4042
gtestFlags, profileEnv);
41-
auto runCommand = MakefileUtils::makefileCommand(projectContext, makefilePath, "run",
43+
auto runCommand = MakefileUtils::MakefileCommand(projectContext, makefilePath, "run",
4244
gtestFlags, profileEnv);
4345
return BuildRunCommand{ testToLaunch, buildCommand, runCommand };
4446
});
@@ -73,7 +75,7 @@ LlvmCoverageTool::getCoverageCommands(const std::vector<UnitTest> &testsToLaunch
7375
fs::path sourcePath = Paths::testPathToSourcePath(projectContext, testFilePath);
7476
fs::path makefile =
7577
Paths::getMakefilePathFromSourceFilePath(projectContext, sourcePath);
76-
auto makefileCommand = MakefileUtils::makefileCommand(projectContext, makefile, "bin");
78+
auto makefileCommand = MakefileUtils::MakefileCommand(projectContext, makefile, "bin");
7779
auto res = makefileCommand.run();
7880
if (res.status == 0) {
7981
if (res.output.empty()) {

server/src/coverage/LlvmCoverageTool.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ class LlvmCoverageTool : public CoverageTool {
1717
[[nodiscard]] nlohmann::json getTotals() const override;
1818
void cleanCoverage() const override;
1919
private:
20-
const utbot::ProjectContext projectContext;
2120
void countLineCoverage(Coverage::CoverageMap& coverageMap, const std::string& filename) const;
2221
void checkLineForPartial(Coverage::FileCoverage::SourceLine line, Coverage::FileCoverage& fileCoverage) const;
2322
};

server/src/coverage/TestRunner.cpp

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
#include "Paths.h"
55
#include "TimeExecStatistics.h"
66
#include "utils/FileSystemUtils.h"
7+
#include "utils/JsonUtils.h"
78
#include "utils/StringUtils.h"
89

910
#include "loguru.h"
10-
#include <regex>
1111

1212
using grpc::ServerWriter;
1313
using grpc::Status;
@@ -39,7 +39,7 @@ TestRunner::TestRunner(
3939

4040
std::vector<UnitTest> TestRunner::getTestsFromMakefile(const fs::path &makefile,
4141
const fs::path &testFilePath) {
42-
auto cmdGetAllTests = MakefileUtils::makefileCommand(projectContext, makefile, "run", "--gtest_list_tests", {"GTEST_FILTER=*"});
42+
auto cmdGetAllTests = MakefileUtils::MakefileCommand(projectContext, makefile, "run", "--gtest_list_tests", {"GTEST_FILTER=*"});
4343
auto [out, status, _] = cmdGetAllTests.run(projectContext.buildDir, false);
4444
if (status != 0) {
4545
auto [err, _, logFilePath] = cmdGetAllTests.run(projectContext.buildDir, true);
@@ -148,7 +148,6 @@ grpc::Status TestRunner::runTests(bool withCoverage, const std::optional<std::ch
148148
exceptions.emplace_back(e);
149149
}
150150
});
151-
152151
LOG_S(DEBUG) << "All run commands were executed";
153152
return Status::OK;
154153
}
@@ -171,7 +170,7 @@ bool TestRunner::buildTest(const utbot::ProjectContext& projectContext, const fs
171170
ExecUtils::throwIfCancelled();
172171
fs::path makefile = Paths::getMakefilePathFromSourceFilePath(projectContext, sourcePath);
173172
if (fs::exists(makefile)) {
174-
auto command = MakefileUtils::makefileCommand(projectContext, makefile, "build", "", {});
173+
auto command = MakefileUtils::MakefileCommand(projectContext, makefile, "build", "", {});
175174
LOG_S(DEBUG) << "Try compile tests for: " << sourcePath.string();
176175
auto[out, status, logFilePath] = command.run(projectContext.buildDir, true);
177176
if (status != 0) {
@@ -196,20 +195,16 @@ testsgen::TestResultObject TestRunner::runTest(const BuildRunCommand &command, c
196195
auto res = command.runCommand.run(projectContext.buildDir, true, true, testTimeout);
197196
GTestLogger::log(res.output);
198197

199-
std::smatch match;
200-
std::regex expr(R"(\[==========\] 1 test from 1 test suite ran. \(\d+ ms total\))");
201-
std::regex_search(res.output, match, expr);
202-
uint32_t executionTimeMs = 0;
203-
if (!match.empty()) {
204-
std::string strMatch = res.output.substr(match.position(0), match.length(0));
205-
std::string strExecutionTime = StringUtils::splitByWhitespaces(strMatch)[8];
206-
executionTimeMs = std::stoul(strExecutionTime.substr(1));
198+
nlohmann::json gtestResultsJson = JsonUtils::getJsonFromFile(Paths::getGTestResultsJsonPath(projectContext));
199+
auto executionTime = new google::protobuf::Duration;
200+
if (!google::protobuf::util::TimeUtil::FromString(gtestResultsJson["time"], executionTime)) {
201+
LOG_S(WARNING) << "Cannot parse duration of test execution";
207202
}
208203

209204
testsgen::TestResultObject testRes;
210205
testRes.set_testfilepath(command.unitTest.testFilePath);
211206
testRes.set_testname(command.unitTest.testname);
212-
testRes.set_executiontimems(executionTimeMs);
207+
testRes.set_allocated_executiontime(executionTime);
213208
if (StringUtils::contains(res.output, "[ PASSED ] 1 test")) {
214209
testRes.set_status(testsgen::TEST_PASSED);
215210
return testRes;

server/src/printers/CoverageAndResultsStatisticsPrinter.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
#include "utils/StringUtils.h"
55
#include "utils/CollectionUtils.h"
66
#include "Paths.h"
7+
#include <google/protobuf/util/time_util.h>
78

89
namespace printer {
910
std::ostream &operator<<(std::ostream &os, const FileCoverageAndResultsStatistics &statistics) {
1011
// total tests execution file
11-
os << statistics.totalExecutionTimeMs << ',';
12+
std::string totalExecutionTimeStr = google::protobuf::util::TimeUtil::ToString(statistics.totalExecutionTime);
13+
os << totalExecutionTimeStr.substr(0, totalExecutionTimeStr.size() - 1) << ',';
1214
// total number of tests
1315
os << statistics.totalTestsNum << ",";
1416
// number of passed tests
@@ -47,7 +49,7 @@ namespace printer {
4749
insert({sourcePath, FileCoverageAndResultsStatistics(testsResult, fileCoverage)});
4850
}
4951
std::vector<std::string> metricNames = {
50-
"filename", "executionTime (ms)",
52+
"filename", "executionTime (s)",
5153
"totalTestsNumber", "passedTestsNumber", "failedTestsNumber", "deathTestsNumber",
5254
"interruptedTestsNumber",
5355
"totalLinesNumber", "coveredLinesNumber", "lineCoverageRatio (%)"
@@ -62,9 +64,8 @@ namespace printer {
6264
ss << fs::relative(sourcePath, projectContext.projectPath).string() << ",";
6365
ss << statistics << '\n';
6466
}
65-
ss << "Total,";
66-
ss << total << '\n';
67-
fs::path resultsFilePath = resultsDirectory / "coverage-and-results-stats.csv";
67+
ss << "Total," << total << '\n';
68+
fs::path resultsFilePath = resultsDirectory / "coverage-and-results.csv";
6869
FileSystemUtils::writeToFile(resultsFilePath, ss.str());
6970
LOG_S(INFO) << StringUtils::stringFormat("See statistics info here: %s", resultsFilePath);
7071
}
@@ -73,11 +74,11 @@ namespace printer {
7374
const Coverage::FileTestsResult &testsResult,
7475
const Coverage::FileCoverage &fileCoverage) {
7576
totalTestsNum = 0;
76-
totalExecutionTimeMs = 0;
77+
totalExecutionTime = google::protobuf::Duration();
7778
for (const auto &[_, testResult]: testsResult) {
7879
totalTestsNum++;
7980
testsWithStatusNum[testResult.status()]++;
80-
totalExecutionTimeMs += testResult.executiontimems();
81+
totalExecutionTime += testResult.executiontime();
8182
}
8283
fullCoverageLinesNum = fileCoverage.fullCoverageLines.size();
8384
partialCoverageLinesNum = fileCoverage.partialCoverageLines.size();
@@ -86,7 +87,7 @@ namespace printer {
8687

8788
FileCoverageAndResultsStatistics &
8889
FileCoverageAndResultsStatistics::operator+=(const FileCoverageAndResultsStatistics &other) {
89-
totalExecutionTimeMs += other.totalExecutionTimeMs;
90+
totalExecutionTime += other.totalExecutionTime;
9091
totalTestsNum += other.totalTestsNum;
9192
for (auto &[status, testsNum]: testsWithStatusNum) {
9293
testsNum += CollectionUtils::getOrDefault(other.testsWithStatusNum, status, 0u);

server/src/printers/CoverageAndResultsStatisticsPrinter.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace printer {
1616
FileCoverageAndResultsStatistics(const Coverage::FileTestsResult &testsResult, const Coverage::FileCoverage &coverage);
1717

1818
// Time statistics
19-
uint32_t totalExecutionTimeMs = 0;
19+
google::protobuf::Duration totalExecutionTime;
2020

2121
// Test runs statistics
2222
uint32_t totalTestsNum = 0;
@@ -36,8 +36,8 @@ namespace printer {
3636

3737
class CoverageAndResultsStatisticsPrinter : CollectionUtils::MapFileTo<FileCoverageAndResultsStatistics> {
3838
public:
39-
explicit CoverageAndResultsStatisticsPrinter(fs::path resultsDirectory) : resultsDirectory(
40-
std::move(resultsDirectory)) {};
39+
explicit CoverageAndResultsStatisticsPrinter(fs::path resultsDirectory) :
40+
resultsDirectory(std::move(resultsDirectory)) {};
4141
void write(const utbot::ProjectContext &, const Coverage::TestResultMap &, const Coverage::CoverageMap &);
4242

4343
private:

server/src/streams/coverage/CLICoverageAndResultsWriter.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ void CLICoverageAndResultsWriter::writeResponse(const utbot::ProjectContext &pro
5757
fs::path resultsFilePath = resultsDirectory / (TimeUtils::getDate() + ".log");
5858
FileSystemUtils::writeToFile(resultsFilePath, ss.str());
5959
LOG_S(INFO) << ss.str();
60-
printer::CoverageAndResultsStatisticsPrinter statsPrinter = printer::CoverageAndResultsStatisticsPrinter(
61-
resultsDirectory);
60+
printer::CoverageAndResultsStatisticsPrinter statsPrinter = printer::CoverageAndResultsStatisticsPrinter(resultsDirectory);
6261
statsPrinter.write(projectContext, testsResultMap, coverageMap);
6362
}

server/src/utils/MakefileUtils.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ namespace MakefileUtils {
3737
: makefile(std::move(makefile)), target(std::move(target)),
3838
projectName(projectContext.projectName) {
3939
this->makefile = this->makefile.lexically_normal();
40+
this->makefile = this->makefile.lexically_normal();
4041
fs::path logDir = Paths::getLogDir(projectContext.projectName);
4142
logFile = logDir / "makefile.log";
4243
fs::create_directories(logDir);
4344
std::vector<std::string> argv = std::move(env);
44-
argv.emplace_back(std::string("GTEST_FLAGS=\"") + gtestFlags + "\"");
45+
argv.emplace_back(std::string("GTEST_FLAGS=") + gtestFlags);
4546
std::vector<std::string> makeCommand = getMakeCommand(this->makefile, this->target, false);
4647
argv.insert(argv.begin(), makeCommand.begin(), makeCommand.end());
4748
runCommand = ShellExecTask::ExecutionParameters("env", argv);
@@ -83,15 +84,6 @@ namespace MakefileUtils {
8384
}
8485
}
8586

86-
87-
MakefileCommand makefileCommand(utbot::ProjectContext const &projectContext,
88-
const fs::path &makefile,
89-
const std::string &target,
90-
const std::string &gtestFlags,
91-
const std::vector<std::string> &env) {
92-
return MakefileCommand(projectContext, makefile, target, gtestFlags, env);
93-
}
94-
9587
std::string threadFlag() {
9688
if (Commands::threadsPerUser != 0) {
9789
return "-j" + std::to_string(Commands::threadsPerUser);

0 commit comments

Comments
 (0)