Skip to content

Commit ad1c9b3

Browse files
authored
CPP ignore unsupported functions (#112)
* Fixes for CPP projects
1 parent 749a424 commit ad1c9b3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+488
-225
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include "multiple_classes.h"
2+
3+
int first_class::get1() {
4+
return 1;
5+
}
6+
7+
int second_class::get2() {
8+
return 2;
9+
}
10+
11+
int second_class::third_class::get3() {
12+
return 3;
13+
}
14+
15+
first_class::first_class() {}
16+
17+
second_class::second_class() {}
18+
19+
second_class::third_class::third_class() {}
20+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#ifndef UNITTESTBOT_MULTIPLE_CLASSES_H
2+
#define UNITTESTBOT_MULTIPLE_CLASSES_H
3+
4+
5+
class first_class {
6+
public:
7+
first_class();
8+
9+
int get1();
10+
};
11+
12+
struct second_class {
13+
public:
14+
second_class();
15+
16+
struct third_class {
17+
third_class();
18+
19+
public:
20+
int get3();
21+
};
22+
23+
int get2();
24+
};
25+
26+
27+
#endif //UNITTESTBOT_MULTIPLE_CLASSES_H

server/src/BordersFinder.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,9 @@ BordersFinder::BordersFinder(const fs::path &filePath,
2323

2424
void BordersFinder::run(const MatchFinder::MatchResult &Result) {
2525
LOG_SCOPE_FUNCTION(MAX);
26+
SourceManager &sourceManager = Result.Context->getSourceManager();
2627
if (const auto *ST = Result.Nodes.getNodeAs<clang::CXXRecordDecl>(Matchers::STRUCT_OR_CLASS_JUST_DECL)) {
27-
SourceManager &sourceManager = Result.Context->getSourceManager();
28-
fs::path path = sourceManager.getFileEntryForID(sourceManager.getMainFileID())
29-
->tryGetRealPathName()
30-
.str();
28+
fs::path path = ClangUtils::getSourceFilePath(sourceManager);
3129
auto borders = getBorders(sourceManager, ST->getSourceRange());
3230
if (!containsLine(borders) || (classBorder.has_value() && !(borders < classBorder.value()))) {
3331
return;
@@ -40,10 +38,7 @@ void BordersFinder::run(const MatchFinder::MatchResult &Result) {
4038
LOG_S(MAX) << "Class name: " << ST->getNameAsString();
4139
LOG_S(MAX) << "Class's borders: " << lineInfo.begin << ' ' << lineInfo.end;
4240
} else if (const FunctionDecl *FS = ClangUtils::getFunctionOrConstructor(Result)) {
43-
SourceManager &sourceManager = Result.Context->getSourceManager();
44-
fs::path path = sourceManager.getFileEntryForID(sourceManager.getMainFileID())
45-
->tryGetRealPathName()
46-
.str();
41+
fs::path path = ClangUtils::getSourceFilePath(sourceManager);
4742
Stmt *currentStmt = FS->getBody();
4843
if ((currentStmt == nullptr) || !containsLine(getFunctionBordersLines(sourceManager, FS))) {
4944
return;
@@ -83,7 +78,7 @@ void BordersFinder::run(const MatchFinder::MatchResult &Result) {
8378
} else {
8479
lineInfo.scopeName = path.stem().string();
8580
}
86-
lineInfo.methodName = FS->getNameAsString();
81+
lineInfo.methodName = FS->getQualifiedNameAsString();
8782
clang::QualType realReturnType = ClangUtils::getReturnType(FS, Result);
8883
lineInfo.functionReturnType = ParamsHandler::getType(realReturnType, realReturnType, sourceManager);
8984
lineInfo.initialized = true;

server/src/FeaturesFilter.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,27 @@ static void updateIfNotCompleteType(types::TypeSupport &typeSupport,
1414
}
1515
}
1616

17+
bool hasPrivateArray(const types::Type &type, const types::TypesHandler &typesHandler) {
18+
switch (typesHandler.getTypeKind(type)) {
19+
case types::TypeKind::STRUCT_LIKE:
20+
for (const auto &field: typesHandler.getStructInfo(type).fields) {
21+
if (field.type.isArray() && field.accessSpecifier != types::AccessSpecifier::AS_pubic) {
22+
return true;
23+
}
24+
return hasPrivateArray(field.type, typesHandler);
25+
}
26+
break;
27+
case types::TypeKind::OBJECT_POINTER:
28+
case types::TypeKind::ARRAY:
29+
case types::TypeKind::PRIMITIVE:
30+
case types::TypeKind::ENUM:
31+
case types::TypeKind::UNKNOWN:
32+
default:
33+
return false;
34+
}
35+
return false;
36+
}
37+
1738
void FeaturesFilter::filter(utbot::SettingsContext const &settingsContext,
1839
const types::TypesHandler &typesHandler,
1940
tests::TestsMap &testsMap,
@@ -80,6 +101,66 @@ void FeaturesFilter::filter(utbot::SettingsContext const &settingsContext,
80101
tests.commentBlocks.push_back(message.str());
81102
return true;
82103
}
104+
105+
if (method.isClassMethod() &&
106+
!typesHandler.getStructInfo(method.classObj->type).hasDefaultPublicConstructor) {
107+
std::stringstream message;
108+
message
109+
<< "Method '" << method.name
110+
<< "' was skipped, as class '" << method.getClassTypeName().value()
111+
<< "' can't be construct in current version";
112+
LOG_S(DEBUG) << message.str();
113+
tests.commentBlocks.push_back(message.str());
114+
return true;
115+
}
116+
117+
if (method.isClassMethod() &&
118+
hasPrivateArray(method.classObj->type, typesHandler)) {
119+
std::stringstream message;
120+
message
121+
<< "Method '" << method.name
122+
<< "' was skipped, as class '" << method.classObj->type.typeName()
123+
<< "' has private field";
124+
LOG_S(DEBUG) << message.str();
125+
tests.commentBlocks.push_back(message.str());
126+
return true;
127+
}
128+
129+
for (const auto &param: method.params) {
130+
if (typesHandler.isStructLike(param.type) && hasPrivateArray(param.type, typesHandler)) {
131+
std::stringstream message;
132+
message
133+
<< "Method '" << method.name
134+
<< "' was skipped, as parameter '" << param.type.typeName()
135+
<< "' has private field";
136+
LOG_S(DEBUG) << message.str();
137+
tests.commentBlocks.push_back(message.str());
138+
return true;
139+
}
140+
}
141+
142+
if (typesHandler.isStructLike(method.returnType) && hasPrivateArray(method.returnType, typesHandler)) {
143+
std::stringstream message;
144+
message
145+
<< "Method '" << method.name
146+
<< "' was skipped, as return type '" << method.returnType.typeName()
147+
<< "' has private field";
148+
LOG_S(DEBUG) << message.str();
149+
tests.commentBlocks.push_back(message.str());
150+
return true;
151+
}
152+
153+
if (method.accessSpecifier != types::AS_pubic) {
154+
std::stringstream message;
155+
message
156+
<< "Method '" << method.name
157+
<< "' from class '" << method.getClassTypeName().value_or("")
158+
<< "' was skipped, as private";
159+
LOG_S(DEBUG) << message.str();
160+
tests.commentBlocks.push_back(message.str());
161+
return true;
162+
}
163+
83164
unsupportedStatistics["passed features filter"]++;
84165

85166
return false;

server/src/KleeGenerator.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ KleeGenerator::buildByCDb(const CollectionUtils::MapFileTo<fs::path> &filesToBui
3838
auto compileCommands = getCompileCommandsForKlee(filesToBuild, stubSources);
3939
printer::DefaultMakefilePrinter makefilePrinter;
4040

41-
std::vector<fs::path> outfilePaths;
41+
std::vector<std::string> outfilePaths;
4242
for (const auto &compileCommand: compileCommands) {
4343
fs::path output = compileCommand.getOutput();
4444
outfilePaths.emplace_back(output);
@@ -47,6 +47,7 @@ KleeGenerator::buildByCDb(const CollectionUtils::MapFileTo<fs::path> &filesToBui
4747
{compileCommandWithChangingDirectory.toStringWithChangingDirectory()});
4848
}
4949

50+
outfilePaths.push_back(printer::DefaultMakefilePrinter::TARGET_FORCE);
5051
makefilePrinter.declareTarget(printer::DefaultMakefilePrinter::TARGET_ALL, outfilePaths, {});
5152
const fs::path makefile = testGen->serverBuildDir / GENERATION_COMPILE_MAKEFILE;
5253
FileSystemUtils::writeToFile(makefile, makefilePrinter.ss.str());
@@ -200,7 +201,8 @@ Result<fs::path> KleeGenerator::defaultBuild(const fs::path &hintPath,
200201
printer::DefaultMakefilePrinter makefilePrinter;
201202
auto commandWithChangingDirectory = utbot::CompileCommand(command, true);
202203
makefilePrinter.declareTarget(printer::DefaultMakefilePrinter::TARGET_BUILD,
203-
{commandWithChangingDirectory.getSourcePath()},
204+
{commandWithChangingDirectory.getSourcePath(),
205+
printer::DefaultMakefilePrinter::TARGET_FORCE},
204206
{commandWithChangingDirectory.toStringWithChangingDirectory()});
205207
fs::path makefile = testGen->serverBuildDir / GENERATION_KLEE_MAKEFILE;
206208
FileSystemUtils::writeToFile(makefile, makefilePrinter.ss.str());
@@ -300,13 +302,12 @@ std::vector<fs::path> KleeGenerator::buildKleeFiles(const tests::TestsMap &tests
300302
}
301303
kleeFilesInfo->setCorrectMethods(std::move(correctMethods));
302304

303-
auto kleeFilePath = writeKleeFile(
304-
kleePrinter, tests, lineInfo,
305-
[&kleeFilesInfo](tests::Tests::MethodDescription const &method) -> bool {
306-
return kleeFilesInfo->isCorrectMethod(method.name);
307-
});
308-
auto kleeBitcodeFile =
309-
defaultBuild(filename, kleeFilePath, buildDirPath, includeFlags);
305+
kleeFilePath = writeKleeFile(kleePrinter, tests, lineInfo,
306+
[&kleeFilesInfo](
307+
tests::Tests::MethodDescription const &method) -> bool {
308+
return kleeFilesInfo->isCorrectMethod(method.name);
309+
});
310+
kleeBitcodeFile = defaultBuild(filename, kleeFilePath, buildDirPath, includeFlags);
310311
if (kleeBitcodeFile.isSuccess()) {
311312
outFiles.emplace_back(kleeBitcodeFile.getOpt().value());
312313
} else {

server/src/KleeRunner.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,9 @@ KleeRunner::createKleeParams(const tests::TestMethod &testMethod,
235235
"--use-tbaa",
236236
"--output-dir=" + kleeOut.string()
237237
};
238+
if (Paths::isCXXFile(testMethod.sourceFilePath)) {
239+
argvData.emplace_back("--libcxx=true");
240+
}
238241
if (settingsContext.useDeterministicSearcher) {
239242
argvData.emplace_back("--search=dfs");
240243
}

server/src/Paths.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ namespace Paths {
308308
fs::path getWrapperFilePath(const utbot::ProjectContext &projectContext,
309309
const fs::path &sourceFilePath) {
310310
fs::path relative = getRelativeDirPath(projectContext, sourceFilePath);
311-
fs::path filename = addSuffix(sourceFilePath.filename(), "_wrapper");
311+
fs::path filename = addSuffix(sourceFilePath.filename(), MAKE_WRAPPER_SUFFIX);
312312
return getWrapperDirPath(projectContext) / relative / filename;
313313
}
314314

server/src/Paths.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
namespace Paths {
1717
extern fs::path logPath;
1818
const std::string MAKEFILE_EXTENSION = ".mk";
19+
const std::string CXX_EXTENSION = ".cpp";
1920
const std::string TEST_SUFFIX = "_test";
2021
const std::string STUB_SUFFIX = "_stub";
2122
const std::string DOT_SEP = "_dot_";
@@ -77,7 +78,7 @@ namespace Paths {
7778
}
7879

7980
static inline fs::path addTestSuffix(const fs::path &path) {
80-
return addSuffix(path, "_test");
81+
return addSuffix(path, Paths::TEST_SUFFIX);
8182
}
8283

8384
static inline fs::path removeSuffix(const fs::path &path, std::string const &suffix) {
@@ -381,12 +382,6 @@ namespace Paths {
381382
//endregion
382383

383384
//region transformations
384-
extern const std::string MAKEFILE_EXTENSION;
385-
extern const std::string TEST_SUFFIX;
386-
extern const std::string STUB_SUFFIX;
387-
extern const std::string DOT_SEP;
388-
extern const std::string MAKE_WRAPPER_SUFFIX;
389-
extern const char dot;
390385

391386
fs::path sourcePathToTestPath(const utbot::ProjectContext &projectContext, const fs::path &sourceFilePath);
392387

server/src/Server.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,8 @@ Status Server::TestsGenServiceImpl::ProcessProjectStubsRequest(BaseTestGen *test
562562
}
563563

564564
Status Server::TestsGenServiceImpl::failedToLoadCDbStatus(const CompilationDatabaseException &e) {
565-
return Status(StatusCode::INVALID_ARGUMENT,
566-
"Failed to find compile_commands.json:\n" + std::string(e.what()));
565+
return {StatusCode::INVALID_ARGUMENT,
566+
"Failed to find compile_commands.json:\n" + std::string(e.what())};
567567
}
568568

569569
Status Server::TestsGenServiceImpl::PrintModulesContent(ServerContext *context,
@@ -658,6 +658,7 @@ Status Server::TestsGenServiceImpl::GetProjectTargets(ServerContext *context,
658658
ProjectTargetsWriter targetsWriter(response);
659659
targetsWriter.writeResponse(projectContext, targets);
660660
} catch (CompilationDatabaseException const &e) {
661+
LOG_S(ERROR) << "Compilation database error: " << e.what();
661662
return failedToLoadCDbStatus(e);
662663
}
663664
return Status::OK;

server/src/Tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,9 +592,9 @@ void KTestObjectParser::addToOrder(const std::vector<UTBotKTestObject> &objects,
592592
if (it != objects.end()) {
593593
size_t jsonInd = it - objects.begin();
594594
visited[jsonInd] = true;
595-
Tests::MethodParam param = { paramType.isObjectPointer() ? paramType.baseTypeObj()
596-
: paramType,
597-
paramName, std::nullopt };
595+
Tests::MethodParam param = {paramType.isObjectPointer() ? paramType.baseTypeObj()
596+
: paramType,
597+
paramName, std::nullopt };
598598
order.emplace(jsonInd, param, paramValue);
599599
return;
600600
}
@@ -658,7 +658,7 @@ void KTestObjectParser::assignTypeUnnamedVar(
658658
continue;
659659
}
660660
if (!visited[indObj]) {
661-
Tests::MethodParam param = { fieldType.baseTypeObj(1), "", std::nullopt };
661+
Tests::MethodParam param = {fieldType.baseTypeObj(1), "", std::nullopt};
662662
order.emplace(indObj, param, curType.paramValue);
663663
visited[indObj] = true;
664664
}

0 commit comments

Comments
 (0)