Skip to content

Commit 2b0fccd

Browse files
committed
Fixes for CPP projects
1 parent 7700689 commit 2b0fccd

19 files changed

+203
-41
lines changed

server/src/FeaturesFilter.cpp

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

17+
bool has_private_array(const types::Type &type, const types::TypesHandler &typesHandler) {
18+
switch (typesHandler.getTypeKind(type)) {
19+
case types::TypeKind::STRUCT:
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 has_private_array(field.type, typesHandler);
25+
}
26+
break;
27+
case types::TypeKind::UNION:
28+
for (const auto &field: typesHandler.getUnionInfo(type).fields) {
29+
if (field.type.isArray() && field.accessSpecifier != types::AccessSpecifier::AS_pubic) {
30+
return true;
31+
}
32+
return has_private_array(field.type, typesHandler);
33+
}
34+
break;
35+
case types::TypeKind::OBJECT_POINTER:
36+
return has_private_array(type.baseTypeObj(), typesHandler);
37+
case types::TypeKind::ARRAY:
38+
return has_private_array(type.baseTypeObj(), typesHandler);
39+
case types::TypeKind::PRIMITIVE:
40+
case types::TypeKind::ENUM:
41+
case types::TypeKind::UNKNOWN:
42+
default:
43+
return false;
44+
}
45+
return false;
46+
}
47+
1748
void FeaturesFilter::filter(utbot::SettingsContext const &settingsContext,
1849
const types::TypesHandler &typesHandler,
1950
tests::TestsMap &testsMap,
@@ -80,6 +111,76 @@ void FeaturesFilter::filter(utbot::SettingsContext const &settingsContext,
80111
tests.commentBlocks.push_back(message.str());
81112
return true;
82113
}
114+
115+
if (method.isClassMethod() && !typesHandler.getStructInfo(method.classObj->type).canBeConstruct) {
116+
std::stringstream message;
117+
message
118+
<< "Method '" << method.name
119+
<< "' was skipped, as class '" << method.getClassTypeName().value()
120+
<< "' can't be construct in current version";
121+
LOG_S(DEBUG) << message.str();
122+
tests.commentBlocks.push_back(message.str());
123+
return true;
124+
}
125+
126+
for (const auto &param: method.params) {
127+
if (typesHandler.isStruct(param.type)) {
128+
for (const auto &field: typesHandler.getStructInfo(param.type).fields) {
129+
if (field.type.isArray() && field.accessSpecifier != types::AccessSpecifier::AS_pubic) {
130+
std::stringstream message;
131+
message
132+
<< "Method '" << method.name
133+
<< "' was skipped, as class '" << param.type.typeName()
134+
<< "' has private array member '" << field.name << "'";
135+
LOG_S(DEBUG) << message.str();
136+
tests.commentBlocks.push_back(message.str());
137+
return true;
138+
}
139+
}
140+
}
141+
}
142+
143+
if (typesHandler.isStruct(method.returnType)) {
144+
for (const auto &field: typesHandler.getStructInfo(method.returnType).fields) {
145+
if (field.type.isArray() && field.accessSpecifier != types::AccessSpecifier::AS_pubic) {
146+
std::stringstream message;
147+
message
148+
<< "Method '" << method.name
149+
<< "' was skipped, as class '" << method.returnType.typeName()
150+
<< "' has private array member '" << field.name << "'";
151+
LOG_S(DEBUG) << message.str();
152+
tests.commentBlocks.push_back(message.str());
153+
return true;
154+
}
155+
}
156+
}
157+
158+
if (method.isClassMethod()) {
159+
for (const auto &field : typesHandler.getStructInfo(method.classObj->type).fields) {
160+
if (field.type.isArray() && field.accessSpecifier != types::AccessSpecifier::AS_pubic) {
161+
std::stringstream message;
162+
message
163+
<< "Method '" << method.name
164+
<< "' was skipped, as class '" << method.getClassTypeName().value()
165+
<< "' has private array member '" << field.name << "'";
166+
LOG_S(DEBUG) << message.str();
167+
tests.commentBlocks.push_back(message.str());
168+
return true;
169+
}
170+
}
171+
}
172+
173+
if (method.accessSpecifier != types::AS_pubic) {
174+
std::stringstream message;
175+
message
176+
<< "Method '" << method.name
177+
<< "' from class '" << method.getClassTypeName().value_or("")
178+
<< "' was skipped, as private";
179+
LOG_S(DEBUG) << message.str();
180+
tests.commentBlocks.push_back(message.str());
181+
return true;
182+
}
183+
83184
unsupportedStatistics["passed features filter"]++;
84185

85186
return false;

server/src/Paths.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ namespace Paths {
112112
fs::path getCCJsonFileFullPath(const std::string &filename, const fs::path &directory) {
113113
fs::path path1 = fs::path(filename);
114114
fs::path path2 = fs::weakly_canonical(directory / path1);
115-
return fs::exists(path2) ? path2 : path1;
115+
return fs::exists(path2.parent_path()) ? path2 : path1;
116116
}
117117

118118
bool isPath(const std::string &possibleFilePath) noexcept {

server/src/Server.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,7 @@ 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, "Failed to find compile_commands.json:\n" + std::string(e.what())};
567566
}
568567

569568
Status Server::TestsGenServiceImpl::PrintModulesContent(ServerContext *context,
@@ -658,6 +657,7 @@ Status Server::TestsGenServiceImpl::GetProjectTargets(ServerContext *context,
658657
ProjectTargetsWriter targetsWriter(response);
659658
targetsWriter.writeResponse(projectContext, targets);
660659
} catch (CompilationDatabaseException const &e) {
660+
LOG_S(ERROR) << "Compilation database error: " << e.what();
661661
return failedToLoadCDbStatus(e);
662662
}
663663
return Status::OK;

server/src/Tests.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ namespace tests {
467467
FileInfo getFileByName(char fileName) const {
468468
return filesValues.value()[fileName - 'A'];
469469
}
470-
470+
471471
std::string getError() const {
472472
if (!errorDescriptors.empty()) {
473473
return errorDescriptors[0].substr(0, errorDescriptors[0].find('\n'));
@@ -513,6 +513,7 @@ namespace tests {
513513
std::vector<MethodTestCase> testCases;
514514
typedef std::unordered_map<std::string, std::vector<int>> SuiteNameToTestCasesMap;
515515
SuiteNameToTestCasesMap suiteTestCases;
516+
types::AccessSpecifier accessSpecifier;
516517

517518
ConstructorInfo constructorInfo = ConstructorInfo::NOT_A_CONSTRUCTOR;
518519

server/src/building/IRParser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ bool IRParser::parseModule(const fs::path &rootBitcode, tests::TestsMap &tests)
2424
for (auto it = tests.begin(); it != tests.end(); it++) {
2525
fs::path const &sourceFile = it.key();
2626
tests::Tests &test = it.value();
27-
test.isFilePresentedInArtifact = true;
27+
test.isFilePresentedInArtifact = false;
2828
for (const auto &[methodName, methodDescription] : test.methods) {
2929
std::string entryPointFunction = KleeUtils::entryPointFunction(test, methodName, true);
3030
std::string methodDebugInfo =
3131
StringUtils::stringFormat("Method: '%s', file: '%s'", methodName, sourceFile);
3232
if (llvm::Function *pFunction = module->getFunction(entryPointFunction)) {
33+
test.isFilePresentedInArtifact = true;
3334
continue;
3435
} else {
3536
LOG_S(DEBUG) << "llvm::Function is null: " << methodDebugInfo;
36-
test.isFilePresentedInArtifact = false;
3737
}
3838
}
3939
}

server/src/building/UserProjectConfiguration.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ UserProjectConfiguration::RunProjectConfigurationCommands(const fs::path &buildD
9494
cmakeOptionsWithMandatory);
9595
ShellExecTask::ExecutionParameters bearMakeParams(
9696
Paths::getBear(),
97-
{ Paths::getMake(), MakefileUtils::threadFlag() });
97+
{ Paths::getMake(), MakefileUtils::threadFlag() , "--always-make"});
9898

9999
fs::path cmakeListsPath = getCmakeListsPath(buildDirPath);
100100
if (fs::exists(cmakeListsPath)) {

server/src/fetchers/FetcherUtils.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,16 @@ void ClangToolRunner::setResourceDirOption(clang::tooling::ClangTool *clangTool)
109109
clangTool->appendArgumentsAdjuster(resourceDirAdjuster);
110110
}
111111
}
112+
113+
types::AccessSpecifier getAS(const clang::Decl *D) {
114+
switch (D->getAccess()) {
115+
case clang::AS_private :
116+
return types::AS_private;
117+
case clang::AS_protected :
118+
return types::AS_protected;
119+
case clang::AS_public :
120+
return types::AS_pubic;
121+
case clang::AS_none :
122+
return types::AS_none;
123+
}
124+
}

server/src/fetchers/FetcherUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,6 @@ template <typename StatementType> bool canBeMissed(StatementType const& statemen
6060
llvm::isa<clang::ParenExpr>(statement) || llvm::isa<clang::CStyleCastExpr>(statement);
6161
}
6262

63+
types::AccessSpecifier getAS(const clang::Decl *D);
64+
6365
#endif //UNITTESTBOT_FETCHERUTILS_H

server/src/fetchers/FunctionDeclsMatchCallback.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ void FunctionDeclsMatchCallback::run(const MatchFinder::MatchResult &Result) {
4545
}
4646
clang::QualType realReturnType = ClangUtils::getReturnType(FS, Result);
4747
methodDescription.returnType = ParamsHandler::getType(realReturnType, realReturnType, sourceManager);
48+
methodDescription.accessSpecifier = types::AS_pubic;
4849
if (onlyReturnTypes) {
4950
addMethod(sourceFilePath, methodDescription);
5051
return;
@@ -71,6 +72,7 @@ void FunctionDeclsMatchCallback::run(const MatchFinder::MatchResult &Result) {
7172
methodDescription.classObj = {classType,
7273
classType.typeName() + "_obj",
7374
std::nullopt};
75+
methodDescription.accessSpecifier = getAS(FS);
7476
}
7577
methodDescription.returnType = ParamsHandler::getType(realReturnType, realReturnType, sourceManager);
7678
methodDescription.hasIncompleteReturnType = ClangUtils::isIncomplete(realReturnType);

server/src/printers/KleePrinter.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,11 @@ fs::path KleePrinter::writeTmpKleeFile(
143143
strInclude("klee/klee.h") << NL;
144144
ss << CALLOC_DECLARATION << NL;
145145
writeStubsForStructureFields(tests);
146-
147-
writeAccessPrivateMacros(typesHandler, tests, false);
146+
writeAccessPrivateMacros(typesHandler, tests, false, [methodFilter, onlyForOneClass, onlyForOneFunction, testedMethod, testedClass] (
147+
tests::Tests::MethodDescription const &testMethod) {
148+
return methodFilter(testMethod) && !((onlyForOneFunction && testMethod.name != testedMethod) ||
149+
(onlyForOneClass && testMethod.isClassMethod() && testMethod.classObj->type.typeName() != testedClass));
150+
});
148151

149152
strDeclareSetOfVars(tests.externVariables);
150153
ss << NL;

server/src/printers/Printer.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -583,18 +583,22 @@ namespace printer {
583583
stubName, "stub", methodName, fInfo->name, makeStatic);
584584
}
585585

586-
void Printer::writeAccessPrivateMacros(types::TypesHandler const *typesHandler, const Tests &tests, bool onlyChangeable) {
586+
void Printer::writeAccessPrivateMacros(types::TypesHandler const *typesHandler, const Tests &tests, bool onlyChangeable,
587+
const std::function<bool(tests::Tests::MethodDescription const &)> &methodFilter) {
587588
if (srcLanguage == utbot::Language::CXX) {
588589
ss << NL;
589590
strInclude("access_private.hpp");
590591
ss << NL;
591592
std::unordered_set<uint64_t> checkedOnPrivate;
592-
for (const auto &[methodName, testMethod] : tests.methods) {
593+
for (const auto &[methodName, testMethod]: tests.methods) {
594+
if (!methodFilter(testMethod)) {
595+
continue;
596+
}
593597
addAccessor(typesHandler, testMethod.returnType, checkedOnPrivate);
594598
if (testMethod.isClassMethod()) {
595599
addAccessor(typesHandler, testMethod.classObj->type, checkedOnPrivate);
596600
}
597-
for (const auto& param : testMethod.params) {
601+
for (const auto &param: testMethod.params) {
598602
if (!onlyChangeable || param.isChangeable()) {
599603
addAccessor(typesHandler, param.type, checkedOnPrivate);
600604
}
@@ -604,12 +608,18 @@ namespace printer {
604608
}
605609
}
606610

611+
void Printer::writeAccessPrivateMacros(types::TypesHandler const *typesHandler,
612+
const Tests &tests, bool onlyChangeable) {
613+
writeAccessPrivateMacros(typesHandler, tests, onlyChangeable,
614+
[](tests::Tests::MethodDescription const &val) { return true; });
615+
}
616+
607617
void Printer::addAccessor(const types::TypesHandler *typesHandler, const types::Type &type,
608618
std::unordered_set<uint64_t> &checkedOnPrivate) {
609619
if (!checkedOnPrivate.count(type.getId()) && typesHandler->isStructLike(type)) {
610620
checkedOnPrivate.insert(type.getId());
611621
for (const auto& field : typesHandler->getStructInfo(type).fields) {
612-
if (field.accessSpecifier != types::Field::AS_pubic) {
622+
if (field.accessSpecifier != types::AccessSpecifier::AS_pubic && !field.type.isArray()) {
613623
ss << StringUtils::stringFormat("ACCESS_PRIVATE_FIELD(%s, %s, %s)",
614624
type.typeName(),
615625
field.type.typeName(),

server/src/printers/Printer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ namespace printer {
220220
const std::string &methodName,
221221
const std::string &stubName, bool needToTypedef, bool makeStatic);
222222

223+
void writeAccessPrivateMacros(types::TypesHandler const *typesHandler, const Tests &tests, bool onlyChangeable,
224+
const std::function<bool(tests::Tests::MethodDescription const &)> &methodFilter);
225+
223226
void writeAccessPrivateMacros(types::TypesHandler const *typesHandler, const Tests &tests, bool onlyChangeable);
224227

225228
void genStubForStructFunctionPointer(const std::string &structName,

server/src/printers/TestsPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,9 @@ void printer::TestsPrinter::printClassObject(const Tests::MethodDescription &met
529529
if (methodDescription.isClassMethod()) {
530530
const auto &param = methodDescription.classObj.value();
531531
const auto &value = testCase.classPreValues.value();
532+
if (!typesHandler->getStructInfo(param.type).isCLike) {
533+
strComment("struct/class maybe can't be construct");
534+
}
532535
verboseParameter(methodDescription, param, value, true);
533536
}
534537
}

server/src/stubs/StubSourcesFinder.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ std::vector<fs::path> StubSourcesFinder::excludeFind(const fs::path &testedFileP
2727
continue;
2828
fs::path sourcePath =
2929
buildDatabase->getClientCompilationUnitInfo(bitcodeFile)->getSourcePath();
30+
// TODO Support stubs for c++ code
31+
if (Paths::isCXXFile(sourcePath)) {
32+
LOG_S(DEBUG) << "CXX stubs not supported now, file: " << sourcePath;
33+
continue;
34+
}
3035
stubSources.emplace_back(std::move(sourcePath));
3136
}
3237
return stubSources;

server/src/types/Types.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ namespace types {
2626
enum class PointerUsage;
2727
enum class ReferenceType;
2828

29+
enum AccessSpecifier {
30+
AS_pubic,
31+
AS_protected,
32+
AS_private,
33+
AS_none
34+
};
35+
2936
class Type {
3037
public:
3138
Type() = default;
@@ -274,12 +281,6 @@ namespace types {
274281
size_t size;
275282
/// offset in @b bits, reassigned in structFields
276283
size_t offset = 0;
277-
enum AccessSpecifier {
278-
AS_pubic,
279-
AS_protected,
280-
AS_private,
281-
AS_none
282-
};
283284
AccessSpecifier accessSpecifier = AS_pubic;
284285
};
285286

@@ -306,6 +307,15 @@ namespace types {
306307
bool hasAnonymousStructOrUnion;
307308
bool isCLike;
308309
SubType subType;
310+
bool hasUnnamedFields;
311+
//TODO delete then can construct without initializer list
312+
bool canBeConstruct;
313+
bool isCLike;
314+
};
315+
316+
struct UnionInfo: TypeInfo {
317+
std::vector<Field> fields{};
318+
bool hasUnnamedFields;
309319
};
310320

311321
struct EnumInfo: TypeInfo {
@@ -677,7 +687,6 @@ namespace types {
677687
};
678688
std::vector<FunctionParamInfo> params;
679689
};
680-
681690
}
682691

683692
#endif //UNITTESTBOT_TYPES_H

0 commit comments

Comments
 (0)