1f4a2713aSLionel Sambuc //===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc
10f4a2713aSLionel Sambuc #include "clang/AST/ASTConsumer.h"
11f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
12f4a2713aSLionel Sambuc #include "clang/AST/DeclGroup.h"
13f4a2713aSLionel Sambuc #include "clang/Frontend/ASTUnit.h"
14f4a2713aSLionel Sambuc #include "clang/Frontend/CompilerInstance.h"
15f4a2713aSLionel Sambuc #include "clang/Frontend/FrontendAction.h"
16f4a2713aSLionel Sambuc #include "clang/Frontend/FrontendActions.h"
17f4a2713aSLionel Sambuc #include "clang/Tooling/CompilationDatabase.h"
18f4a2713aSLionel Sambuc #include "clang/Tooling/Tooling.h"
19f4a2713aSLionel Sambuc #include "llvm/ADT/STLExtras.h"
20*0a6a1f1dSLionel Sambuc #include "llvm/Config/llvm-config.h"
21*0a6a1f1dSLionel Sambuc #include "gtest/gtest.h"
22*0a6a1f1dSLionel Sambuc #include <algorithm>
23f4a2713aSLionel Sambuc #include <string>
24f4a2713aSLionel Sambuc
25f4a2713aSLionel Sambuc namespace clang {
26f4a2713aSLionel Sambuc namespace tooling {
27f4a2713aSLionel Sambuc
28f4a2713aSLionel Sambuc namespace {
29f4a2713aSLionel Sambuc /// Takes an ast consumer and returns it from CreateASTConsumer. This only
30f4a2713aSLionel Sambuc /// works with single translation unit compilations.
31f4a2713aSLionel Sambuc class TestAction : public clang::ASTFrontendAction {
32f4a2713aSLionel Sambuc public:
33f4a2713aSLionel Sambuc /// Takes ownership of TestConsumer.
TestAction(std::unique_ptr<clang::ASTConsumer> TestConsumer)34*0a6a1f1dSLionel Sambuc explicit TestAction(std::unique_ptr<clang::ASTConsumer> TestConsumer)
35*0a6a1f1dSLionel Sambuc : TestConsumer(std::move(TestConsumer)) {}
36f4a2713aSLionel Sambuc
37f4a2713aSLionel Sambuc protected:
38*0a6a1f1dSLionel Sambuc virtual std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance & compiler,StringRef dummy)39*0a6a1f1dSLionel Sambuc CreateASTConsumer(clang::CompilerInstance &compiler, StringRef dummy) {
40f4a2713aSLionel Sambuc /// TestConsumer will be deleted by the framework calling us.
41*0a6a1f1dSLionel Sambuc return std::move(TestConsumer);
42f4a2713aSLionel Sambuc }
43f4a2713aSLionel Sambuc
44f4a2713aSLionel Sambuc private:
45*0a6a1f1dSLionel Sambuc std::unique_ptr<clang::ASTConsumer> TestConsumer;
46f4a2713aSLionel Sambuc };
47f4a2713aSLionel Sambuc
48f4a2713aSLionel Sambuc class FindTopLevelDeclConsumer : public clang::ASTConsumer {
49f4a2713aSLionel Sambuc public:
FindTopLevelDeclConsumer(bool * FoundTopLevelDecl)50f4a2713aSLionel Sambuc explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
51f4a2713aSLionel Sambuc : FoundTopLevelDecl(FoundTopLevelDecl) {}
HandleTopLevelDecl(clang::DeclGroupRef DeclGroup)52f4a2713aSLionel Sambuc virtual bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) {
53f4a2713aSLionel Sambuc *FoundTopLevelDecl = true;
54f4a2713aSLionel Sambuc return true;
55f4a2713aSLionel Sambuc }
56f4a2713aSLionel Sambuc private:
57f4a2713aSLionel Sambuc bool * const FoundTopLevelDecl;
58f4a2713aSLionel Sambuc };
59f4a2713aSLionel Sambuc } // end namespace
60f4a2713aSLionel Sambuc
TEST(runToolOnCode,FindsNoTopLevelDeclOnEmptyCode)61f4a2713aSLionel Sambuc TEST(runToolOnCode, FindsNoTopLevelDeclOnEmptyCode) {
62f4a2713aSLionel Sambuc bool FoundTopLevelDecl = false;
63*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
64*0a6a1f1dSLionel Sambuc runToolOnCode(new TestAction(llvm::make_unique<FindTopLevelDeclConsumer>(
65*0a6a1f1dSLionel Sambuc &FoundTopLevelDecl)),
66*0a6a1f1dSLionel Sambuc ""));
67f4a2713aSLionel Sambuc EXPECT_FALSE(FoundTopLevelDecl);
68f4a2713aSLionel Sambuc }
69f4a2713aSLionel Sambuc
70f4a2713aSLionel Sambuc namespace {
71f4a2713aSLionel Sambuc class FindClassDeclXConsumer : public clang::ASTConsumer {
72f4a2713aSLionel Sambuc public:
FindClassDeclXConsumer(bool * FoundClassDeclX)73f4a2713aSLionel Sambuc FindClassDeclXConsumer(bool *FoundClassDeclX)
74f4a2713aSLionel Sambuc : FoundClassDeclX(FoundClassDeclX) {}
HandleTopLevelDecl(clang::DeclGroupRef GroupRef)75f4a2713aSLionel Sambuc virtual bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) {
76f4a2713aSLionel Sambuc if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
77f4a2713aSLionel Sambuc *GroupRef.begin())) {
78f4a2713aSLionel Sambuc if (Record->getName() == "X") {
79f4a2713aSLionel Sambuc *FoundClassDeclX = true;
80f4a2713aSLionel Sambuc }
81f4a2713aSLionel Sambuc }
82f4a2713aSLionel Sambuc return true;
83f4a2713aSLionel Sambuc }
84f4a2713aSLionel Sambuc private:
85f4a2713aSLionel Sambuc bool *FoundClassDeclX;
86f4a2713aSLionel Sambuc };
FindClassDeclX(ASTUnit * AST)87f4a2713aSLionel Sambuc bool FindClassDeclX(ASTUnit *AST) {
88f4a2713aSLionel Sambuc for (std::vector<Decl *>::iterator i = AST->top_level_begin(),
89f4a2713aSLionel Sambuc e = AST->top_level_end();
90f4a2713aSLionel Sambuc i != e; ++i) {
91f4a2713aSLionel Sambuc if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(*i)) {
92f4a2713aSLionel Sambuc if (Record->getName() == "X") {
93f4a2713aSLionel Sambuc return true;
94f4a2713aSLionel Sambuc }
95f4a2713aSLionel Sambuc }
96f4a2713aSLionel Sambuc }
97f4a2713aSLionel Sambuc return false;
98f4a2713aSLionel Sambuc }
99f4a2713aSLionel Sambuc } // end namespace
100f4a2713aSLionel Sambuc
TEST(runToolOnCode,FindsClassDecl)101f4a2713aSLionel Sambuc TEST(runToolOnCode, FindsClassDecl) {
102f4a2713aSLionel Sambuc bool FoundClassDeclX = false;
103*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
104*0a6a1f1dSLionel Sambuc runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>(
105*0a6a1f1dSLionel Sambuc &FoundClassDeclX)),
106*0a6a1f1dSLionel Sambuc "class X;"));
107f4a2713aSLionel Sambuc EXPECT_TRUE(FoundClassDeclX);
108f4a2713aSLionel Sambuc
109f4a2713aSLionel Sambuc FoundClassDeclX = false;
110*0a6a1f1dSLionel Sambuc EXPECT_TRUE(
111*0a6a1f1dSLionel Sambuc runToolOnCode(new TestAction(llvm::make_unique<FindClassDeclXConsumer>(
112*0a6a1f1dSLionel Sambuc &FoundClassDeclX)),
113*0a6a1f1dSLionel Sambuc "class Y;"));
114f4a2713aSLionel Sambuc EXPECT_FALSE(FoundClassDeclX);
115f4a2713aSLionel Sambuc }
116f4a2713aSLionel Sambuc
TEST(buildASTFromCode,FindsClassDecl)117f4a2713aSLionel Sambuc TEST(buildASTFromCode, FindsClassDecl) {
118*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTUnit> AST = buildASTFromCode("class X;");
119f4a2713aSLionel Sambuc ASSERT_TRUE(AST.get());
120f4a2713aSLionel Sambuc EXPECT_TRUE(FindClassDeclX(AST.get()));
121f4a2713aSLionel Sambuc
122*0a6a1f1dSLionel Sambuc AST = buildASTFromCode("class Y;");
123f4a2713aSLionel Sambuc ASSERT_TRUE(AST.get());
124f4a2713aSLionel Sambuc EXPECT_FALSE(FindClassDeclX(AST.get()));
125f4a2713aSLionel Sambuc }
126f4a2713aSLionel Sambuc
TEST(newFrontendActionFactory,CreatesFrontendActionFactoryFromType)127f4a2713aSLionel Sambuc TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {
128*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendActionFactory> Factory(
129f4a2713aSLionel Sambuc newFrontendActionFactory<SyntaxOnlyAction>());
130*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendAction> Action(Factory->create());
131*0a6a1f1dSLionel Sambuc EXPECT_TRUE(Action.get() != nullptr);
132f4a2713aSLionel Sambuc }
133f4a2713aSLionel Sambuc
134f4a2713aSLionel Sambuc struct IndependentFrontendActionCreator {
newASTConsumerclang::tooling::IndependentFrontendActionCreator135*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> newASTConsumer() {
136*0a6a1f1dSLionel Sambuc return llvm::make_unique<FindTopLevelDeclConsumer>(nullptr);
137f4a2713aSLionel Sambuc }
138f4a2713aSLionel Sambuc };
139f4a2713aSLionel Sambuc
TEST(newFrontendActionFactory,CreatesFrontendActionFactoryFromFactoryType)140f4a2713aSLionel Sambuc TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
141f4a2713aSLionel Sambuc IndependentFrontendActionCreator Creator;
142*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendActionFactory> Factory(
143f4a2713aSLionel Sambuc newFrontendActionFactory(&Creator));
144*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendAction> Action(Factory->create());
145*0a6a1f1dSLionel Sambuc EXPECT_TRUE(Action.get() != nullptr);
146f4a2713aSLionel Sambuc }
147f4a2713aSLionel Sambuc
TEST(ToolInvocation,TestMapVirtualFile)148f4a2713aSLionel Sambuc TEST(ToolInvocation, TestMapVirtualFile) {
149f4a2713aSLionel Sambuc IntrusiveRefCntPtr<clang::FileManager> Files(
150f4a2713aSLionel Sambuc new clang::FileManager(clang::FileSystemOptions()));
151f4a2713aSLionel Sambuc std::vector<std::string> Args;
152f4a2713aSLionel Sambuc Args.push_back("tool-executable");
153f4a2713aSLionel Sambuc Args.push_back("-Idef");
154f4a2713aSLionel Sambuc Args.push_back("-fsyntax-only");
155f4a2713aSLionel Sambuc Args.push_back("test.cpp");
156f4a2713aSLionel Sambuc clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
157*0a6a1f1dSLionel Sambuc Files.get());
158f4a2713aSLionel Sambuc Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");
159f4a2713aSLionel Sambuc Invocation.mapVirtualFile("def/abc", "\n");
160f4a2713aSLionel Sambuc EXPECT_TRUE(Invocation.run());
161f4a2713aSLionel Sambuc }
162f4a2713aSLionel Sambuc
TEST(ToolInvocation,TestVirtualModulesCompilation)163f4a2713aSLionel Sambuc TEST(ToolInvocation, TestVirtualModulesCompilation) {
164f4a2713aSLionel Sambuc // FIXME: Currently, this only tests that we don't exit with an error if a
165f4a2713aSLionel Sambuc // mapped module.map is found on the include path. In the future, expand this
166f4a2713aSLionel Sambuc // test to run a full modules enabled compilation, so we make sure we can
167f4a2713aSLionel Sambuc // rerun modules compilations with a virtual file system.
168f4a2713aSLionel Sambuc IntrusiveRefCntPtr<clang::FileManager> Files(
169f4a2713aSLionel Sambuc new clang::FileManager(clang::FileSystemOptions()));
170f4a2713aSLionel Sambuc std::vector<std::string> Args;
171f4a2713aSLionel Sambuc Args.push_back("tool-executable");
172f4a2713aSLionel Sambuc Args.push_back("-Idef");
173f4a2713aSLionel Sambuc Args.push_back("-fsyntax-only");
174f4a2713aSLionel Sambuc Args.push_back("test.cpp");
175f4a2713aSLionel Sambuc clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction,
176*0a6a1f1dSLionel Sambuc Files.get());
177f4a2713aSLionel Sambuc Invocation.mapVirtualFile("test.cpp", "#include <abc>\n");
178f4a2713aSLionel Sambuc Invocation.mapVirtualFile("def/abc", "\n");
179f4a2713aSLionel Sambuc // Add a module.map file in the include directory of our header, so we trigger
180f4a2713aSLionel Sambuc // the module.map header search logic.
181f4a2713aSLionel Sambuc Invocation.mapVirtualFile("def/module.map", "\n");
182f4a2713aSLionel Sambuc EXPECT_TRUE(Invocation.run());
183f4a2713aSLionel Sambuc }
184f4a2713aSLionel Sambuc
185f4a2713aSLionel Sambuc struct VerifyEndCallback : public SourceFileCallbacks {
VerifyEndCallbackclang::tooling::VerifyEndCallback186f4a2713aSLionel Sambuc VerifyEndCallback() : BeginCalled(0), EndCalled(0), Matched(false) {}
handleBeginSourceclang::tooling::VerifyEndCallback187f4a2713aSLionel Sambuc virtual bool handleBeginSource(CompilerInstance &CI,
188*0a6a1f1dSLionel Sambuc StringRef Filename) override {
189f4a2713aSLionel Sambuc ++BeginCalled;
190f4a2713aSLionel Sambuc return true;
191f4a2713aSLionel Sambuc }
handleEndSourceclang::tooling::VerifyEndCallback192*0a6a1f1dSLionel Sambuc virtual void handleEndSource() override {
193f4a2713aSLionel Sambuc ++EndCalled;
194f4a2713aSLionel Sambuc }
newASTConsumerclang::tooling::VerifyEndCallback195*0a6a1f1dSLionel Sambuc std::unique_ptr<ASTConsumer> newASTConsumer() {
196*0a6a1f1dSLionel Sambuc return llvm::make_unique<FindTopLevelDeclConsumer>(&Matched);
197f4a2713aSLionel Sambuc }
198f4a2713aSLionel Sambuc unsigned BeginCalled;
199f4a2713aSLionel Sambuc unsigned EndCalled;
200f4a2713aSLionel Sambuc bool Matched;
201f4a2713aSLionel Sambuc };
202f4a2713aSLionel Sambuc
203*0a6a1f1dSLionel Sambuc #if !defined(LLVM_ON_WIN32)
TEST(newFrontendActionFactory,InjectsSourceFileCallbacks)204f4a2713aSLionel Sambuc TEST(newFrontendActionFactory, InjectsSourceFileCallbacks) {
205f4a2713aSLionel Sambuc VerifyEndCallback EndCallback;
206f4a2713aSLionel Sambuc
207f4a2713aSLionel Sambuc FixedCompilationDatabase Compilations("/", std::vector<std::string>());
208f4a2713aSLionel Sambuc std::vector<std::string> Sources;
209f4a2713aSLionel Sambuc Sources.push_back("/a.cc");
210f4a2713aSLionel Sambuc Sources.push_back("/b.cc");
211f4a2713aSLionel Sambuc ClangTool Tool(Compilations, Sources);
212f4a2713aSLionel Sambuc
213f4a2713aSLionel Sambuc Tool.mapVirtualFile("/a.cc", "void a() {}");
214f4a2713aSLionel Sambuc Tool.mapVirtualFile("/b.cc", "void b() {}");
215f4a2713aSLionel Sambuc
216*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendActionFactory> Action(
217*0a6a1f1dSLionel Sambuc newFrontendActionFactory(&EndCallback, &EndCallback));
218*0a6a1f1dSLionel Sambuc Tool.run(Action.get());
219f4a2713aSLionel Sambuc
220f4a2713aSLionel Sambuc EXPECT_TRUE(EndCallback.Matched);
221f4a2713aSLionel Sambuc EXPECT_EQ(2u, EndCallback.BeginCalled);
222f4a2713aSLionel Sambuc EXPECT_EQ(2u, EndCallback.EndCalled);
223f4a2713aSLionel Sambuc }
224f4a2713aSLionel Sambuc #endif
225f4a2713aSLionel Sambuc
226f4a2713aSLionel Sambuc struct SkipBodyConsumer : public clang::ASTConsumer {
227f4a2713aSLionel Sambuc /// Skip the 'skipMe' function.
shouldSkipFunctionBodyclang::tooling::SkipBodyConsumer228f4a2713aSLionel Sambuc virtual bool shouldSkipFunctionBody(Decl *D) {
229f4a2713aSLionel Sambuc FunctionDecl *F = dyn_cast<FunctionDecl>(D);
230f4a2713aSLionel Sambuc return F && F->getNameAsString() == "skipMe";
231f4a2713aSLionel Sambuc }
232f4a2713aSLionel Sambuc };
233f4a2713aSLionel Sambuc
234f4a2713aSLionel Sambuc struct SkipBodyAction : public clang::ASTFrontendAction {
235*0a6a1f1dSLionel Sambuc virtual std::unique_ptr<ASTConsumer>
CreateASTConsumerclang::tooling::SkipBodyAction236*0a6a1f1dSLionel Sambuc CreateASTConsumer(CompilerInstance &Compiler, StringRef) {
237f4a2713aSLionel Sambuc Compiler.getFrontendOpts().SkipFunctionBodies = true;
238*0a6a1f1dSLionel Sambuc return llvm::make_unique<SkipBodyConsumer>();
239f4a2713aSLionel Sambuc }
240f4a2713aSLionel Sambuc };
241f4a2713aSLionel Sambuc
TEST(runToolOnCode,TestSkipFunctionBody)242f4a2713aSLionel Sambuc TEST(runToolOnCode, TestSkipFunctionBody) {
243f4a2713aSLionel Sambuc EXPECT_TRUE(runToolOnCode(new SkipBodyAction,
244f4a2713aSLionel Sambuc "int skipMe() { an_error_here }"));
245f4a2713aSLionel Sambuc EXPECT_FALSE(runToolOnCode(new SkipBodyAction,
246f4a2713aSLionel Sambuc "int skipMeNot() { an_error_here }"));
247f4a2713aSLionel Sambuc }
248f4a2713aSLionel Sambuc
TEST(runToolOnCodeWithArgs,TestNoDepFile)249*0a6a1f1dSLionel Sambuc TEST(runToolOnCodeWithArgs, TestNoDepFile) {
250*0a6a1f1dSLionel Sambuc llvm::SmallString<32> DepFilePath;
251*0a6a1f1dSLionel Sambuc ASSERT_FALSE(
252*0a6a1f1dSLionel Sambuc llvm::sys::fs::createTemporaryFile("depfile", "d", DepFilePath));
253*0a6a1f1dSLionel Sambuc std::vector<std::string> Args;
254*0a6a1f1dSLionel Sambuc Args.push_back("-MMD");
255*0a6a1f1dSLionel Sambuc Args.push_back("-MT");
256*0a6a1f1dSLionel Sambuc Args.push_back(DepFilePath.str());
257*0a6a1f1dSLionel Sambuc Args.push_back("-MF");
258*0a6a1f1dSLionel Sambuc Args.push_back(DepFilePath.str());
259*0a6a1f1dSLionel Sambuc EXPECT_TRUE(runToolOnCodeWithArgs(new SkipBodyAction, "", Args));
260*0a6a1f1dSLionel Sambuc EXPECT_FALSE(llvm::sys::fs::exists(DepFilePath.str()));
261*0a6a1f1dSLionel Sambuc EXPECT_FALSE(llvm::sys::fs::remove(DepFilePath.str()));
262f4a2713aSLionel Sambuc }
263f4a2713aSLionel Sambuc
TEST(ClangToolTest,ArgumentAdjusters)264f4a2713aSLionel Sambuc TEST(ClangToolTest, ArgumentAdjusters) {
265f4a2713aSLionel Sambuc FixedCompilationDatabase Compilations("/", std::vector<std::string>());
266f4a2713aSLionel Sambuc
267f4a2713aSLionel Sambuc ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
268f4a2713aSLionel Sambuc Tool.mapVirtualFile("/a.cc", "void a() {}");
269f4a2713aSLionel Sambuc
270*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendActionFactory> Action(
271*0a6a1f1dSLionel Sambuc newFrontendActionFactory<SyntaxOnlyAction>());
272*0a6a1f1dSLionel Sambuc
273f4a2713aSLionel Sambuc bool Found = false;
274f4a2713aSLionel Sambuc bool Ran = false;
275*0a6a1f1dSLionel Sambuc ArgumentsAdjuster CheckSyntaxOnlyAdjuster =
276*0a6a1f1dSLionel Sambuc [&Found, &Ran](const CommandLineArguments &Args) {
277*0a6a1f1dSLionel Sambuc Ran = true;
278*0a6a1f1dSLionel Sambuc if (std::find(Args.begin(), Args.end(), "-fsyntax-only") != Args.end())
279*0a6a1f1dSLionel Sambuc Found = true;
280*0a6a1f1dSLionel Sambuc return Args;
281*0a6a1f1dSLionel Sambuc };
282*0a6a1f1dSLionel Sambuc Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster);
283*0a6a1f1dSLionel Sambuc Tool.run(Action.get());
284f4a2713aSLionel Sambuc EXPECT_TRUE(Ran);
285f4a2713aSLionel Sambuc EXPECT_TRUE(Found);
286f4a2713aSLionel Sambuc
287f4a2713aSLionel Sambuc Ran = Found = false;
288f4a2713aSLionel Sambuc Tool.clearArgumentsAdjusters();
289*0a6a1f1dSLionel Sambuc Tool.appendArgumentsAdjuster(CheckSyntaxOnlyAdjuster);
290*0a6a1f1dSLionel Sambuc Tool.appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
291*0a6a1f1dSLionel Sambuc Tool.run(Action.get());
292f4a2713aSLionel Sambuc EXPECT_TRUE(Ran);
293f4a2713aSLionel Sambuc EXPECT_FALSE(Found);
294f4a2713aSLionel Sambuc }
295f4a2713aSLionel Sambuc
296*0a6a1f1dSLionel Sambuc #ifndef LLVM_ON_WIN32
TEST(ClangToolTest,BuildASTs)297f4a2713aSLionel Sambuc TEST(ClangToolTest, BuildASTs) {
298f4a2713aSLionel Sambuc FixedCompilationDatabase Compilations("/", std::vector<std::string>());
299f4a2713aSLionel Sambuc
300f4a2713aSLionel Sambuc std::vector<std::string> Sources;
301f4a2713aSLionel Sambuc Sources.push_back("/a.cc");
302f4a2713aSLionel Sambuc Sources.push_back("/b.cc");
303f4a2713aSLionel Sambuc ClangTool Tool(Compilations, Sources);
304f4a2713aSLionel Sambuc
305f4a2713aSLionel Sambuc Tool.mapVirtualFile("/a.cc", "void a() {}");
306f4a2713aSLionel Sambuc Tool.mapVirtualFile("/b.cc", "void b() {}");
307f4a2713aSLionel Sambuc
308*0a6a1f1dSLionel Sambuc std::vector<std::unique_ptr<ASTUnit>> ASTs;
309f4a2713aSLionel Sambuc EXPECT_EQ(0, Tool.buildASTs(ASTs));
310f4a2713aSLionel Sambuc EXPECT_EQ(2u, ASTs.size());
311f4a2713aSLionel Sambuc }
312f4a2713aSLionel Sambuc
313f4a2713aSLionel Sambuc struct TestDiagnosticConsumer : public DiagnosticConsumer {
TestDiagnosticConsumerclang::tooling::TestDiagnosticConsumer314f4a2713aSLionel Sambuc TestDiagnosticConsumer() : NumDiagnosticsSeen(0) {}
HandleDiagnosticclang::tooling::TestDiagnosticConsumer315f4a2713aSLionel Sambuc virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
316f4a2713aSLionel Sambuc const Diagnostic &Info) {
317f4a2713aSLionel Sambuc ++NumDiagnosticsSeen;
318f4a2713aSLionel Sambuc }
319f4a2713aSLionel Sambuc unsigned NumDiagnosticsSeen;
320f4a2713aSLionel Sambuc };
321f4a2713aSLionel Sambuc
TEST(ClangToolTest,InjectDiagnosticConsumer)322f4a2713aSLionel Sambuc TEST(ClangToolTest, InjectDiagnosticConsumer) {
323f4a2713aSLionel Sambuc FixedCompilationDatabase Compilations("/", std::vector<std::string>());
324f4a2713aSLionel Sambuc ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
325f4a2713aSLionel Sambuc Tool.mapVirtualFile("/a.cc", "int x = undeclared;");
326f4a2713aSLionel Sambuc TestDiagnosticConsumer Consumer;
327f4a2713aSLionel Sambuc Tool.setDiagnosticConsumer(&Consumer);
328*0a6a1f1dSLionel Sambuc std::unique_ptr<FrontendActionFactory> Action(
329*0a6a1f1dSLionel Sambuc newFrontendActionFactory<SyntaxOnlyAction>());
330*0a6a1f1dSLionel Sambuc Tool.run(Action.get());
331f4a2713aSLionel Sambuc EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen);
332f4a2713aSLionel Sambuc }
333f4a2713aSLionel Sambuc
TEST(ClangToolTest,InjectDiagnosticConsumerInBuildASTs)334f4a2713aSLionel Sambuc TEST(ClangToolTest, InjectDiagnosticConsumerInBuildASTs) {
335f4a2713aSLionel Sambuc FixedCompilationDatabase Compilations("/", std::vector<std::string>());
336f4a2713aSLionel Sambuc ClangTool Tool(Compilations, std::vector<std::string>(1, "/a.cc"));
337f4a2713aSLionel Sambuc Tool.mapVirtualFile("/a.cc", "int x = undeclared;");
338f4a2713aSLionel Sambuc TestDiagnosticConsumer Consumer;
339f4a2713aSLionel Sambuc Tool.setDiagnosticConsumer(&Consumer);
340*0a6a1f1dSLionel Sambuc std::vector<std::unique_ptr<ASTUnit>> ASTs;
341f4a2713aSLionel Sambuc Tool.buildASTs(ASTs);
342f4a2713aSLionel Sambuc EXPECT_EQ(1u, ASTs.size());
343f4a2713aSLionel Sambuc EXPECT_EQ(1u, Consumer.NumDiagnosticsSeen);
344f4a2713aSLionel Sambuc }
345f4a2713aSLionel Sambuc #endif
346f4a2713aSLionel Sambuc
347f4a2713aSLionel Sambuc } // end namespace tooling
348f4a2713aSLionel Sambuc } // end namespace clang
349