1 #include "ClangTidyTest.h" 2 #include "google/ExplicitConstructorCheck.h" 3 #include "google/GlobalNamesInHeadersCheck.h" 4 #include "gtest/gtest.h" 5 6 using namespace clang::tidy::google; 7 8 namespace clang { 9 namespace tidy { 10 namespace test { 11 12 TEST(ExplicitConstructorCheckTest, SingleArgumentConstructorsOnly) { 13 EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(); };"); 14 EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(int i, int j); };"); 15 EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(const C&); };"); 16 EXPECT_NO_CHANGES(ExplicitConstructorCheck, "class C { C(C&&); };"); 17 EXPECT_NO_CHANGES(ExplicitConstructorCheck, 18 "class C { C(const C&) = delete; };"); 19 EXPECT_NO_CHANGES(ExplicitConstructorCheck, 20 "class C { C(int) = delete; };"); 21 } 22 23 TEST(ExplicitConstructorCheckTest, Basic) { 24 EXPECT_EQ("class C { explicit C(int i); };", 25 runCheckOnCode<ExplicitConstructorCheck>("class C { C(int i); };")); 26 } 27 28 TEST(ExplicitConstructorCheckTest, DefaultParameters) { 29 EXPECT_EQ("class C { explicit C(int i, int j = 0); };", 30 runCheckOnCode<ExplicitConstructorCheck>( 31 "class C { C(int i, int j = 0); };")); 32 } 33 34 TEST(ExplicitConstructorCheckTest, OutOfLineDefinitions) { 35 EXPECT_EQ("class C { explicit C(int i); }; C::C(int i) {}", 36 runCheckOnCode<ExplicitConstructorCheck>( 37 "class C { C(int i); }; C::C(int i) {}")); 38 } 39 40 TEST(ExplicitConstructorCheckTest, RemoveExplicit) { 41 EXPECT_EQ("class A { A(const A&); };\n" 42 "class B { /*asdf*/ B(B&&); };\n" 43 "class C { /*asdf*/ C(const C&, int i = 0); };", 44 runCheckOnCode<ExplicitConstructorCheck>( 45 "class A { explicit A(const A&); };\n" 46 "class B { explicit /*asdf*/ B(B&&); };\n" 47 "class C { explicit/*asdf*/ C(const C&, int i = 0); };")); 48 } 49 50 TEST(ExplicitConstructorCheckTest, RemoveExplicitWithMacros) { 51 EXPECT_EQ( 52 "#define A(T) class T##Bar { explicit T##Bar(const T##Bar &b) {} };\n" 53 "A(Foo);", 54 runCheckOnCode<ExplicitConstructorCheck>( 55 "#define A(T) class T##Bar { explicit T##Bar(const T##Bar &b) {} };\n" 56 "A(Foo);")); 57 } 58 59 class GlobalNamesInHeadersCheckTest : public ::testing::Test { 60 protected: 61 bool runCheckOnCode(const std::string &Code, const std::string &Filename) { 62 static const char *const Header = "namespace std {\n" 63 "class string {};\n" 64 "} // namespace std\n" 65 "\n" 66 "#define SOME_MACRO(x) using x\n"; 67 std::vector<ClangTidyError> Errors; 68 std::vector<std::string> Args; 69 if (!StringRef(Filename).endswith(".cpp")) { 70 Args.emplace_back("-xc++-header"); 71 } 72 test::runCheckOnCode<readability::GlobalNamesInHeadersCheck>( 73 Header + Code, &Errors, Filename, Args); 74 if (Errors.empty()) 75 return false; 76 assert(Errors.size() == 1); 77 assert( 78 Errors[0].Message.Message == 79 "using declarations in the global namespace in headers are prohibited"); 80 return true; 81 } 82 }; 83 84 TEST_F(GlobalNamesInHeadersCheckTest, UsingDeclarations) { 85 EXPECT_TRUE(runCheckOnCode("using std::string;", "foo.h")); 86 EXPECT_FALSE(runCheckOnCode("using std::string;", "foo.cpp")); 87 EXPECT_FALSE(runCheckOnCode("namespace my_namespace {\n" 88 "using std::string;\n" 89 "} // my_namespace\n", 90 "foo.h")); 91 EXPECT_FALSE(runCheckOnCode("SOME_MACRO(std::string);", "foo.h")); 92 } 93 94 TEST_F(GlobalNamesInHeadersCheckTest, UsingDirectives) { 95 EXPECT_TRUE(runCheckOnCode("using namespace std;", "foo.h")); 96 EXPECT_FALSE(runCheckOnCode("using namespace std;", "foo.cpp")); 97 EXPECT_FALSE(runCheckOnCode("namespace my_namespace {\n" 98 "using namespace std;\n" 99 "} // my_namespace\n", 100 "foo.h")); 101 EXPECT_FALSE(runCheckOnCode("SOME_MACRO(namespace std);", "foo.h")); 102 } 103 104 TEST_F(GlobalNamesInHeadersCheckTest, RegressionAnonymousNamespace) { 105 EXPECT_FALSE(runCheckOnCode("namespace {}", "foo.h")); 106 } 107 108 } // namespace test 109 } // namespace tidy 110 } // namespace clang 111