1 //===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "clang/AST/ASTConsumer.h" 11 #include "clang/AST/DeclCXX.h" 12 #include "clang/AST/DeclGroup.h" 13 #include "clang/Frontend/FrontendAction.h" 14 #include "clang/Frontend/FrontendActions.h" 15 #include "clang/Tooling/CompilationDatabase.h" 16 #include "clang/Tooling/Tooling.h" 17 #include "gtest/gtest.h" 18 #include <string> 19 20 namespace clang { 21 namespace tooling { 22 23 namespace { 24 /// Takes an ast consumer and returns it from CreateASTConsumer. This only 25 /// works with single translation unit compilations. 26 class TestAction : public clang::ASTFrontendAction { 27 public: 28 /// Takes ownership of TestConsumer. 29 explicit TestAction(clang::ASTConsumer *TestConsumer) 30 : TestConsumer(TestConsumer) {} 31 32 protected: 33 virtual clang::ASTConsumer* CreateASTConsumer( 34 clang::CompilerInstance& compiler, StringRef dummy) { 35 /// TestConsumer will be deleted by the framework calling us. 36 return TestConsumer; 37 } 38 39 private: 40 clang::ASTConsumer * const TestConsumer; 41 }; 42 43 class FindTopLevelDeclConsumer : public clang::ASTConsumer { 44 public: 45 explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl) 46 : FoundTopLevelDecl(FoundTopLevelDecl) {} 47 virtual bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) { 48 *FoundTopLevelDecl = true; 49 return true; 50 } 51 private: 52 bool * const FoundTopLevelDecl; 53 }; 54 } // end namespace 55 56 TEST(runToolOnCode, FindsNoTopLevelDeclOnEmptyCode) { 57 bool FoundTopLevelDecl = false; 58 EXPECT_TRUE(runToolOnCode( 59 new TestAction(new FindTopLevelDeclConsumer(&FoundTopLevelDecl)), "")); 60 #if !defined(_MSC_VER) 61 EXPECT_FALSE(FoundTopLevelDecl); 62 #else 63 // FIXME: LangOpts.MicrosoftExt appends "class type_info;" 64 EXPECT_TRUE(FoundTopLevelDecl); 65 #endif 66 } 67 68 namespace { 69 class FindClassDeclXConsumer : public clang::ASTConsumer { 70 public: 71 FindClassDeclXConsumer(bool *FoundClassDeclX) 72 : FoundClassDeclX(FoundClassDeclX) {} 73 virtual bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) { 74 if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>( 75 *GroupRef.begin())) { 76 if (Record->getName() == "X") { 77 *FoundClassDeclX = true; 78 } 79 } 80 return true; 81 } 82 private: 83 bool *FoundClassDeclX; 84 }; 85 } // end namespace 86 87 TEST(runToolOnCode, FindsClassDecl) { 88 bool FoundClassDeclX = false; 89 EXPECT_TRUE(runToolOnCode(new TestAction( 90 new FindClassDeclXConsumer(&FoundClassDeclX)), "class X;")); 91 EXPECT_TRUE(FoundClassDeclX); 92 93 FoundClassDeclX = false; 94 EXPECT_TRUE(runToolOnCode(new TestAction( 95 new FindClassDeclXConsumer(&FoundClassDeclX)), "class Y;")); 96 EXPECT_FALSE(FoundClassDeclX); 97 } 98 99 TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) { 100 llvm::OwningPtr<FrontendActionFactory> Factory( 101 newFrontendActionFactory<SyntaxOnlyAction>()); 102 llvm::OwningPtr<FrontendAction> Action(Factory->create()); 103 EXPECT_TRUE(Action.get() != NULL); 104 } 105 106 struct IndependentFrontendActionCreator { 107 ASTConsumer *newASTConsumer() { 108 return new FindTopLevelDeclConsumer(NULL); 109 } 110 }; 111 112 TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) { 113 IndependentFrontendActionCreator Creator; 114 llvm::OwningPtr<FrontendActionFactory> Factory( 115 newFrontendActionFactory(&Creator)); 116 llvm::OwningPtr<FrontendAction> Action(Factory->create()); 117 EXPECT_TRUE(Action.get() != NULL); 118 } 119 120 TEST(ToolInvocation, TestMapVirtualFile) { 121 clang::FileManager Files((clang::FileSystemOptions())); 122 std::vector<std::string> Args; 123 Args.push_back("tool-executable"); 124 Args.push_back("-Idef"); 125 Args.push_back("-fsyntax-only"); 126 Args.push_back("test.cpp"); 127 clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction, &Files); 128 Invocation.mapVirtualFile("test.cpp", "#include <abc>\n"); 129 Invocation.mapVirtualFile("def/abc", "\n"); 130 EXPECT_TRUE(Invocation.run()); 131 } 132 133 } // end namespace tooling 134 } // end namespace clang 135