Skip to content

Commit 38de4ee

Browse files
authored
Use stubs instead of wrappers in generated test headers when needed (#615)
* Use stubs instead of wrappers in generated test headers when needed
1 parent 90d9f40 commit 38de4ee

File tree

11 files changed

+70
-29
lines changed

11 files changed

+70
-29
lines changed

server/src/Server.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,9 +204,6 @@ Status Server::TestsGenServiceImpl::ProcessBaseTestRequest(BaseTestGen &testGen,
204204
testGen.compileCommandsJsonPath, false);
205205
fetcher.fetchWithProgress(testGen.progressWriter, logMessage);
206206
types::TypesHandler typesHandler{testGen.types, sizeContext};
207-
SourceToHeaderRewriter(testGen.projectContext, testGen.getTargetBuildDatabase()->compilationDatabase,
208-
fetcher.getStructsToDeclare(), testGen.serverBuildDir, typesHandler)
209-
.generateTestHeaders(testGen.tests, testGen.progressWriter);
210207
testGen.progressWriter->writeProgress("Generating stub files", 0.0);
211208
StubGen stubGen(testGen);
212209

@@ -265,6 +262,10 @@ Status Server::TestsGenServiceImpl::ProcessBaseTestRequest(BaseTestGen &testGen,
265262
Linker linker{testGen, stubGen, lineInfo, generator};
266263
linker.prepareArtifacts();
267264
auto testMethods = linker.getTestMethods();
265+
auto selectedTargets = linker.getSelectedTargets();
266+
SourceToHeaderRewriter(testGen.projectContext, testGen.getTargetBuildDatabase()->compilationDatabase,
267+
fetcher.getStructsToDeclare(), testGen.serverBuildDir, typesHandler)
268+
.generateTestHeaders(testGen.tests, stubGen, selectedTargets, testGen.progressWriter);
268269
KleeRunner kleeRunner{testGen.projectContext, testGen.settingsContext};
269270
bool interactiveMode = (dynamic_cast<ProjectTestGen *>(&testGen) != nullptr);
270271
auto generationStartTime = std::chrono::steady_clock::now();

server/src/building/Linker.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ void Linker::linkForOneFile(const fs::path &sourceFilePath) {
106106
auto [targetBitcode, stubsSet, _] = result.getOpt().value();
107107
addToGenerated({ objectFile }, targetBitcode);
108108
auto&& targetUnitInfo = testGen.getTargetBuildDatabase()->getClientLinkUnitInfo(target);
109+
selectedTargets[sourceFilePath] = target;
109110
return;
110111
} else {
111112
LOG_S(DEBUG) << "Linkage for target " << target.filename() << " failed: " << result.getError()->c_str();
@@ -193,6 +194,7 @@ void Linker::linkForProject() {
193194
return compilationUnitInfo->getOutputFile();
194195
});
195196
addToGenerated(objectFiles, linkres.bitcodeOutput);
197+
selectedTargets[sourceFile] = target;
196198
break;
197199
} else {
198200
std::stringstream ss;
@@ -311,6 +313,10 @@ std::vector<tests::TestMethod> Linker::getTestMethods() {
311313
return testMethods;
312314
}
313315

316+
CollectionUtils::MapFileTo<fs::path> Linker::getSelectedTargets() {
317+
return selectedTargets;
318+
}
319+
314320
Linker::Linker(BaseTestGen &testGen,
315321
StubGen stubGen,
316322
std::shared_ptr<LineInfo> lineInfo,

server/src/building/Linker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class Linker {
3131

3232
std::vector<tests::TestMethod> getTestMethods();
3333

34+
CollectionUtils::MapFileTo<fs::path> getSelectedTargets();
35+
3436
BuildResult
3537
addLinkTargetRecursively(const fs::path &fileToBuild,
3638
printer::DefaultMakefilePrinter &bitcodeLinkMakefilePrinter,
@@ -54,6 +56,7 @@ class Linker {
5456

5557
CollectionUtils::FileSet testedFiles;
5658
CollectionUtils::MapFileTo<fs::path> bitcodeFileName;
59+
CollectionUtils::MapFileTo<fs::path> selectedTargets;
5760
CollectionUtils::FileSet brokenLinkFiles;
5861

5962
IRParser irParser;

server/src/clang-utils/SourceToHeaderMatchCallback.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ SourceToHeaderMatchCallback::SourceToHeaderMatchCallback(utbot::ProjectContext p
2222
raw_ostream *unnamedTypeDeclsStream,
2323
raw_ostream *wrapperStream,
2424
const types::TypesHandler &typesHandler,
25-
bool forStubHeader)
25+
bool forStubHeader,
26+
bool externFromStub)
2627
: projectContext(std::move(projectContext)),
2728
sourceFilePath(std::move(sourceFilePath)), externalStream(externalStream),
2829
internalStream(internalStream), unnamedTypeDeclsStream(unnamedTypeDeclsStream),
29-
wrapperStream(wrapperStream), typesHandler(typesHandler), forStubHeader(forStubHeader) {
30+
wrapperStream(wrapperStream), typesHandler(typesHandler), forStubHeader(forStubHeader),
31+
externFromStub(externFromStub) {
3032
}
3133

3234
void SourceToHeaderMatchCallback::run(const ast_matchers::MatchFinder::MatchResult &Result) {
@@ -222,14 +224,18 @@ void SourceToHeaderMatchCallback::generateInternal(const FunctionDecl *decl) con
222224
renameAnonymousReturnTypeDecl(tagDecl, name);
223225
}
224226

225-
*internalStream << "extern \"C\" " << wrapperDecl << ";\n";
226-
*internalStream << "static " << curDecl << " {\n";
227-
printReturn(decl, wrapperName, internalStream);
228-
*internalStream << "}\n";
227+
if (externFromStub) {
228+
*internalStream << "extern \"C\" " << curDecl << ";\n";
229+
} else {
230+
*internalStream << "extern \"C\" " << wrapperDecl << ";\n";
231+
*internalStream << "static " << curDecl << " {\n";
232+
printReturn(decl, wrapperName, internalStream);
233+
*internalStream << "}\n";
234+
}
229235
}
230236

231237
void SourceToHeaderMatchCallback::generateInternal(const VarDecl *decl) const {
232-
if (internalStream == nullptr) {
238+
if (internalStream == nullptr || externFromStub) {
233239
return;
234240
}
235241
auto policy = getDefaultPrintingPolicy(decl, true);

server/src/clang-utils/SourceToHeaderMatchCallback.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class SourceToHeaderMatchCallback : public clang::ast_matchers::MatchFinder::Mat
2929
const types::TypesHandler &typesHandler;
3030

3131
bool forStubHeader;
32+
bool externFromStub;
3233
public:
3334
SourceToHeaderMatchCallback(
3435
utbot::ProjectContext projectContext,
@@ -38,7 +39,8 @@ class SourceToHeaderMatchCallback : public clang::ast_matchers::MatchFinder::Mat
3839
llvm::raw_ostream *unnamedTypeDeclsStream,
3940
llvm::raw_ostream *wrapperStream,
4041
const types::TypesHandler &typesHandler,
41-
bool forStubHeader);
42+
bool forStubHeader,
43+
bool externFromStub);
4244

4345
void run(const MatchFinder::MatchResult &Result) override;
4446
private:

server/src/clang-utils/SourceToHeaderRewriter.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,30 @@ SourceToHeaderRewriter::createFactory(llvm::raw_ostream *externalStream,
2828
llvm::raw_ostream *unnamedTypeDeclsStream,
2929
llvm::raw_ostream *wrapperStream,
3030
fs::path sourceFilePath,
31-
bool forStubHeader) {
31+
bool forStubHeader,
32+
bool externFromStub) {
3233
if (Paths::isCXXFile(sourceFilePath)) {
3334
externalStream = nullptr;
3435
internalStream = nullptr;
3536
}
3637
fetcherInstance = std::make_unique<SourceToHeaderMatchCallback>(
37-
projectContext, sourceFilePath, externalStream, internalStream, unnamedTypeDeclsStream, wrapperStream, typesHandler, forStubHeader);
38+
projectContext, sourceFilePath, externalStream, internalStream, unnamedTypeDeclsStream, wrapperStream,
39+
typesHandler, forStubHeader, externFromStub);
3840
finder = std::make_unique<clang::ast_matchers::MatchFinder>();
3941
finder->addMatcher(Matchers::anyToplevelDeclarationMatcher, fetcherInstance.get());
4042
return clang::tooling::newFrontendActionFactory(finder.get());
4143
}
4244

4345
SourceToHeaderRewriter::SourceDeclarations
44-
SourceToHeaderRewriter::generateSourceDeclarations(const fs::path &sourceFilePath, bool forStubHeader) {
46+
SourceToHeaderRewriter::generateSourceDeclarations(const fs::path &sourceFilePath, bool forStubHeader, bool externFromStub) {
4547
std::string externalDeclarations;
4648
llvm::raw_string_ostream externalStream(externalDeclarations);
4749
std::string internalDeclarations;
4850
llvm::raw_string_ostream internalStream(internalDeclarations);
4951
std::string unnamedTypeDeclarations;
5052
llvm::raw_string_ostream unnamedTypeDeclsStream(unnamedTypeDeclarations);
5153

52-
auto factory = createFactory(&externalStream, &internalStream, &unnamedTypeDeclsStream, nullptr, sourceFilePath, forStubHeader);
54+
auto factory = createFactory(&externalStream, &internalStream, &unnamedTypeDeclsStream, nullptr, sourceFilePath, forStubHeader, externFromStub);
5355

5456
if (CollectionUtils::containsKey(*structsToDeclare, sourceFilePath)) {
5557
std::stringstream newContentStream;
@@ -72,9 +74,10 @@ SourceToHeaderRewriter::generateSourceDeclarations(const fs::path &sourceFilePat
7274

7375

7476
std::string SourceToHeaderRewriter::generateTestHeader(const fs::path &sourceFilePath,
75-
const Tests &test) {
77+
const Tests &test,
78+
bool externFromStub) {
7679
MEASURE_FUNCTION_EXECUTION_TIME
77-
auto sourceDeclarations = generateSourceDeclarations(sourceFilePath, false);
80+
auto sourceDeclarations = generateSourceDeclarations(sourceFilePath, false, externFromStub);
7881

7982
if (Paths::isCXXFile(sourceFilePath)) {
8083
auto sourceFileToInclude = sourceFilePath;
@@ -112,7 +115,7 @@ std::string SourceToHeaderRewriter::generateStubHeader(const fs::path &sourceFil
112115
MEASURE_FUNCTION_EXECUTION_TIME
113116
LOG_IF_S(WARNING, Paths::isCXXFile(sourceFilePath))
114117
<< "Stubs feature for C++ sources has not been tested thoroughly; some problems may occur";
115-
auto sourceDeclarations = generateSourceDeclarations(sourceFilePath, true);
118+
auto sourceDeclarations = generateSourceDeclarations(sourceFilePath, true, false);
116119
long long creationTime = TimeUtils::convertFileToSystemClock(fs::file_time_type::clock::now())
117120
.time_since_epoch()
118121
.count();
@@ -133,19 +136,28 @@ std::string SourceToHeaderRewriter::generateWrapper(const fs::path &sourceFilePa
133136
}
134137
std::string result;
135138
llvm::raw_string_ostream wrapperStream(result);
136-
auto factory = createFactory(nullptr, nullptr, nullptr, &wrapperStream, sourceFilePath, false);
139+
auto factory = createFactory(
140+
nullptr, nullptr, nullptr, &wrapperStream,
141+
sourceFilePath, false, false);
137142
clangToolRunner.run(sourceFilePath, factory.get());
138143
wrapperStream.flush();
139144
return result;
140145
}
141146

142147
void SourceToHeaderRewriter::generateTestHeaders(tests::TestsMap &tests,
143-
ProgressWriter const *progressWriter) {
148+
const StubGen &stubGen,
149+
const CollectionUtils::MapFileTo<fs::path> &selectedTargets,
150+
ProgressWriter const *progressWriter) {
144151
std::string logMessage = "Generating headers for tests";
145152
LOG_S(DEBUG) << logMessage;
146-
ExecUtils::doWorkWithProgress(tests, progressWriter, logMessage, [this](auto &it) {
153+
ExecUtils::doWorkWithProgress(tests, progressWriter, logMessage,
154+
[this, &stubGen, &selectedTargets](auto &it) {
147155
fs::path const &sourceFilePath = it.first;
148-
tests::Tests &test = const_cast<tests::Tests &>(it.second);
149-
test.headerCode = generateTestHeader(sourceFilePath, test);
156+
auto &test = const_cast<tests::Tests &>(it.second);
157+
auto iterator = selectedTargets.find(sourceFilePath);
158+
bool externFromStub =
159+
iterator != selectedTargets.end() &&
160+
CollectionUtils::contains(stubGen.getStubSources(iterator->second), sourceFilePath);
161+
test.headerCode = generateTestHeader(sourceFilePath, test, externFromStub);
150162
});
151163
}

server/src/clang-utils/SourceToHeaderRewriter.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "building/BuildDatabase.h"
99
#include "fetchers/Fetcher.h"
1010
#include "fetchers/FetcherUtils.h"
11+
#include "stubs/StubGen.h"
1112
#include "utils/FileSystemUtils.h"
1213

1314
#include <clang/AST/RecursiveASTVisitor.h>
@@ -35,7 +36,8 @@ class SourceToHeaderRewriter {
3536
llvm::raw_ostream *unnamedTypeDeclsStream,
3637
llvm::raw_ostream *wrapperStream,
3738
fs::path sourceFilePath,
38-
bool forStubHeader);
39+
bool forStubHeader,
40+
bool externFromStub);
3941

4042
public:
4143
struct SourceDeclarations {
@@ -53,15 +55,18 @@ class SourceToHeaderRewriter {
5355
fs::path serverBuildDir,
5456
const types::TypesHandler &typesHandler);
5557

56-
SourceDeclarations generateSourceDeclarations(const fs::path &sourceFilePath, bool forStubHeader);
58+
SourceDeclarations generateSourceDeclarations(const fs::path &sourceFilePath, bool forStubHeader, bool externFromStub);
5759

58-
std::string generateTestHeader(const fs::path &sourceFilePath, const Tests &test);
60+
std::string generateTestHeader(const fs::path &sourceFilePath, const Tests &test, bool externFromStub);
5961

6062
std::string generateStubHeader(const fs::path &sourceFilePath);
6163

6264
std::string generateWrapper(const fs::path &sourceFilePath);
6365

64-
void generateTestHeaders(tests::TestsMap &tests, ProgressWriter const *progressWriter);
66+
void generateTestHeaders(tests::TestsMap &tests,
67+
const StubGen &stubGen,
68+
const CollectionUtils::MapFileTo<fs::path> &selectedTargets,
69+
ProgressWriter const *progressWriter);
6570
};
6671

6772

server/src/printers/SourceWrapperPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ namespace printer {
2424

2525
strInclude(Include(false, projectDirRelativeToWrapperFile / sourcePathRelativeToProjectDir));
2626

27+
ss << "#pragma GCC visibility push (default)" << NL;
28+
2729
ss << wrapperDefinitions;
2830

31+
ss << "#pragma GCC visibility pop" << NL;
32+
2933
FileSystemUtils::writeToFile(wrapperFilePath, ss.str());
3034
}
3135
}

server/src/printers/StubsPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Stubs printer::StubsPrinter::genStubFile(const tests::Tests &tests,
2525
ss << "#endif" << NL;
2626
strInclude(Paths::sourcePathToHeaderInclude(tests.sourceFilePath));
2727
ss << NL;
28+
ss << "#pragma GCC visibility push (default)" << NL;
2829
strDefine(PrinterUtils::C_NULL, "((void*)0)") << NL;
2930
for (const auto &[_, method] : tests.methods) {
3031
auto methodCopy = method;
@@ -66,6 +67,7 @@ Stubs printer::StubsPrinter::genStubFile(const tests::Tests &tests,
6667
};
6768
ss << NL;
6869
}
70+
ss << "#pragma GCC visibility pop" << NL;
6971
stubFile.code = ss.str();
7072
return stubFile;
7173
}

server/src/stubs/StubGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
StubGen::StubGen(BaseTestGen &testGen) : testGen(testGen) {
1515
}
1616

17-
CollectionUtils::FileSet StubGen::getStubSources(const fs::path &target) {
17+
CollectionUtils::FileSet StubGen::getStubSources(const fs::path &target) const {
1818
if (!testGen.needToBeMocked() || !testGen.settingsContext.useStubs) {
1919
return {};
2020
}

0 commit comments

Comments
 (0)