114 lines · cpp
1//===- unittest/Tooling/HeaderAnalysisTest.cpp ----------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Tooling/Inclusions/HeaderAnalysis.h"10#include "clang/Lex/Preprocessor.h"11#include "clang/Testing/TestAST.h"12#include "gmock/gmock.h"13#include "gtest/gtest.h"14 15namespace clang {16namespace tooling {17namespace {18using testing::Eq;19 20TEST(HeaderAnalysisTest, IsSelfContained) {21 TestInputs Inputs;22 Inputs.Code = R"cpp(23 #include "headerguard.h"24 #include "pragmaonce.h"25 #import "imported.h"26 27 #include "bad.h"28 #include "unguarded.h"29 )cpp";30 31 Inputs.ExtraFiles["headerguard.h"] = R"cpp(32 #ifndef HEADER_H33 #define HEADER_H34 35 #endif HEADER_H36 )cpp";37 Inputs.ExtraFiles["pragmaonce.h"] = R"cpp(38 #pragma once39 )cpp";40 Inputs.ExtraFiles["imported.h"] = "";41 42 Inputs.ExtraFiles["unguarded.h"] = "";43 Inputs.ExtraFiles["bad.h"] = R"cpp(44 #pragma once45 46 #if defined(INSIDE_H)47 #error "Only ... can be included directly"48 #endif49 )cpp";50 51 TestAST AST(Inputs);52 const auto &SM = AST.sourceManager();53 auto &FM = SM.getFileManager();54 auto &HI = AST.preprocessor().getHeaderSearchInfo();55 EXPECT_TRUE(56 isSelfContainedHeader(*FM.getOptionalFileRef("headerguard.h"), SM, HI));57 EXPECT_TRUE(58 isSelfContainedHeader(*FM.getOptionalFileRef("pragmaonce.h"), SM, HI));59 EXPECT_TRUE(60 isSelfContainedHeader(*FM.getOptionalFileRef("imported.h"), SM, HI));61 EXPECT_TRUE(isSelfContainedHeader(62 *SM.getFileEntryRefForID(SM.getMainFileID()), SM, HI));63 64 EXPECT_FALSE(65 isSelfContainedHeader(*FM.getOptionalFileRef("unguarded.h"), SM, HI));66 EXPECT_FALSE(isSelfContainedHeader(*FM.getOptionalFileRef("bad.h"), SM, HI));67}68 69TEST(HeaderAnalysisTest, CodeContainsImports) {70 EXPECT_TRUE(codeContainsImports(R"cpp(71 #include "foo.h"72 #import "NSFoo.h"73 74 int main() {75 foo();76 }77 )cpp"));78 79 EXPECT_TRUE(codeContainsImports(R"cpp(80 #include "foo.h"81 82 int main() {83 foo();84 }85 86 #import "NSFoo.h"87 )cpp"));88 89 EXPECT_FALSE(codeContainsImports(R"cpp(90 #include "foo.h"91 92 int main() {93 foo();94 }95 )cpp"));96}97 98TEST(HeaderAnalysisTest, ParseIWYUPragma) {99 EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep"), Eq("keep"));100 EXPECT_THAT(parseIWYUPragma("// IWYU pragma: keep me\netc"),101 Eq("keep me"));102 EXPECT_THAT(parseIWYUPragma("/* IWYU pragma: keep */"), Eq("keep"));103 EXPECT_EQ(parseIWYUPragma("// IWYU pragma: keep"), std::nullopt)104 << "Prefix is sensitive to whitespace";105 EXPECT_EQ(parseIWYUPragma("// IWYU pragma:keep"), std::nullopt)106 << "Prefix is sensitive to whitespace";107 EXPECT_EQ(parseIWYUPragma("/\n* IWYU pragma: keep */"), std::nullopt)108 << "Must start with /* or //";109}110 111} // namespace112} // namespace tooling113} // namespace clang114