1dffb1a80SEric Liu //===- unittests/Lex/HeaderSearchTest.cpp ------ HeaderSearch tests -------===// 2dffb1a80SEric Liu // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6dffb1a80SEric Liu // 7dffb1a80SEric Liu //===----------------------------------------------------------------------===// 8dffb1a80SEric Liu 9dffb1a80SEric Liu #include "clang/Lex/HeaderSearch.h" 10178ad93eSDmitry Polukhin #include "HeaderMapTestUtils.h" 11dffb1a80SEric Liu #include "clang/Basic/Diagnostic.h" 12dffb1a80SEric Liu #include "clang/Basic/DiagnosticOptions.h" 13dffb1a80SEric Liu #include "clang/Basic/FileManager.h" 14dffb1a80SEric Liu #include "clang/Basic/LangOptions.h" 15dffb1a80SEric Liu #include "clang/Basic/SourceManager.h" 16dffb1a80SEric Liu #include "clang/Basic/TargetInfo.h" 17dffb1a80SEric Liu #include "clang/Basic/TargetOptions.h" 18dffb1a80SEric Liu #include "clang/Lex/HeaderSearchOptions.h" 198bef5cd4SDuncan P. N. Exon Smith #include "clang/Serialization/InMemoryModuleCache.h" 20395e1fe3SCyndy Ishida #include "llvm/Support/MemoryBuffer.h" 21dffb1a80SEric Liu #include "gtest/gtest.h" 22f1eae81cSDanial Klimkin #include <memory> 23f1eae81cSDanial Klimkin #include <string> 24dffb1a80SEric Liu 25dffb1a80SEric Liu namespace clang { 26dffb1a80SEric Liu namespace { 27dffb1a80SEric Liu 28dffb1a80SEric Liu // The test fixture. 29dffb1a80SEric Liu class HeaderSearchTest : public ::testing::Test { 30dffb1a80SEric Liu protected: 31dffb1a80SEric Liu HeaderSearchTest() 32fc51490bSJonas Devlieghere : VFS(new llvm::vfs::InMemoryFileSystem), FileMgr(FileMgrOpts, VFS), 33dffb1a80SEric Liu DiagID(new DiagnosticIDs()), 34dffb1a80SEric Liu Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()), 35ccd7e783SJan Svoboda SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions), 36dffb1a80SEric Liu Search(std::make_shared<HeaderSearchOptions>(), SourceMgr, Diags, 37ccd7e783SJan Svoboda LangOpts, Target.get()) { 38ccd7e783SJan Svoboda TargetOpts->Triple = "x86_64-apple-darwin11.1.0"; 39ccd7e783SJan Svoboda Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 40ccd7e783SJan Svoboda } 41dffb1a80SEric Liu 42dffb1a80SEric Liu void addSearchDir(llvm::StringRef Dir) { 43a41fbb1fSKazu Hirata VFS->addFile( 44a41fbb1fSKazu Hirata Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/std::nullopt, 45a41fbb1fSKazu Hirata /*Group=*/std::nullopt, llvm::sys::fs::file_type::directory_file); 460377ca64SAlex Lorenz auto DE = FileMgr.getOptionalDirectoryRef(Dir); 47dffb1a80SEric Liu assert(DE); 488d323d15SHarlan Haskins auto DL = DirectoryLookup(*DE, SrcMgr::C_User, /*isFramework=*/false); 49dffb1a80SEric Liu Search.AddSearchPath(DL, /*isAngled=*/false); 50dffb1a80SEric Liu } 51dffb1a80SEric Liu 529fe632baSDavid Goldman void addFrameworkSearchDir(llvm::StringRef Dir, bool IsSystem = true) { 53a41fbb1fSKazu Hirata VFS->addFile( 54a41fbb1fSKazu Hirata Dir, 0, llvm::MemoryBuffer::getMemBuffer(""), /*User=*/std::nullopt, 55a41fbb1fSKazu Hirata /*Group=*/std::nullopt, llvm::sys::fs::file_type::directory_file); 560cf7e61aSDavid Goldman auto DE = FileMgr.getOptionalDirectoryRef(Dir); 570cf7e61aSDavid Goldman assert(DE); 589fe632baSDavid Goldman auto DL = DirectoryLookup(*DE, IsSystem ? SrcMgr::C_System : SrcMgr::C_User, 599fe632baSDavid Goldman /*isFramework=*/true); 609fe632baSDavid Goldman if (IsSystem) 610cf7e61aSDavid Goldman Search.AddSystemSearchPath(DL); 629fe632baSDavid Goldman else 639fe632baSDavid Goldman Search.AddSearchPath(DL, /*isAngled=*/true); 640cf7e61aSDavid Goldman } 650cf7e61aSDavid Goldman 66178ad93eSDmitry Polukhin void addHeaderMap(llvm::StringRef Filename, 67395e1fe3SCyndy Ishida std::unique_ptr<llvm::MemoryBuffer> Buf, 68395e1fe3SCyndy Ishida bool isAngled = false) { 69a41fbb1fSKazu Hirata VFS->addFile(Filename, 0, std::move(Buf), /*User=*/std::nullopt, 70a41fbb1fSKazu Hirata /*Group=*/std::nullopt, 71178ad93eSDmitry Polukhin llvm::sys::fs::file_type::regular_file); 72f94695b6SJan Svoboda auto FE = FileMgr.getOptionalFileRef(Filename, true); 73178ad93eSDmitry Polukhin assert(FE); 74178ad93eSDmitry Polukhin 75178ad93eSDmitry Polukhin // Test class supports only one HMap at a time. 76178ad93eSDmitry Polukhin assert(!HMap); 77178ad93eSDmitry Polukhin HMap = HeaderMap::Create(*FE, FileMgr); 78*19b4f17dSJan Svoboda auto DL = DirectoryLookup(HMap.get(), SrcMgr::C_User); 79395e1fe3SCyndy Ishida Search.AddSearchPath(DL, isAngled); 80178ad93eSDmitry Polukhin } 81178ad93eSDmitry Polukhin 82fc51490bSJonas Devlieghere IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS; 83dffb1a80SEric Liu FileSystemOptions FileMgrOpts; 84dffb1a80SEric Liu FileManager FileMgr; 85dffb1a80SEric Liu IntrusiveRefCntPtr<DiagnosticIDs> DiagID; 86dffb1a80SEric Liu DiagnosticsEngine Diags; 87dffb1a80SEric Liu SourceManager SourceMgr; 88dffb1a80SEric Liu LangOptions LangOpts; 89dffb1a80SEric Liu std::shared_ptr<TargetOptions> TargetOpts; 90dffb1a80SEric Liu IntrusiveRefCntPtr<TargetInfo> Target; 91dffb1a80SEric Liu HeaderSearch Search; 92178ad93eSDmitry Polukhin std::unique_ptr<HeaderMap> HMap; 93dffb1a80SEric Liu }; 94dffb1a80SEric Liu 95dffb1a80SEric Liu TEST_F(HeaderSearchTest, NoSearchDir) { 96dffb1a80SEric Liu EXPECT_EQ(Search.search_dir_size(), 0u); 971f6d9845SKadir Cetinkaya EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/x/y/z", /*WorkingDir=*/"", 981f6d9845SKadir Cetinkaya /*MainFile=*/""), 99dffb1a80SEric Liu "/x/y/z"); 100dffb1a80SEric Liu } 101dffb1a80SEric Liu 102dffb1a80SEric Liu TEST_F(HeaderSearchTest, SimpleShorten) { 103dffb1a80SEric Liu addSearchDir("/x"); 104dffb1a80SEric Liu addSearchDir("/x/y"); 1051f6d9845SKadir Cetinkaya EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/x/y/z", /*WorkingDir=*/"", 1061f6d9845SKadir Cetinkaya /*MainFile=*/""), 107dffb1a80SEric Liu "z"); 108dffb1a80SEric Liu addSearchDir("/a/b/"); 1091f6d9845SKadir Cetinkaya EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/a/b/c", /*WorkingDir=*/"", 1101f6d9845SKadir Cetinkaya /*MainFile=*/""), 111dffb1a80SEric Liu "c"); 112dffb1a80SEric Liu } 113dffb1a80SEric Liu 114dffb1a80SEric Liu TEST_F(HeaderSearchTest, ShortenWithWorkingDir) { 115dffb1a80SEric Liu addSearchDir("x/y"); 116dffb1a80SEric Liu EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/a/b/c/x/y/z", 1171f6d9845SKadir Cetinkaya /*WorkingDir=*/"/a/b/c", 1181f6d9845SKadir Cetinkaya /*MainFile=*/""), 119dffb1a80SEric Liu "z"); 120dffb1a80SEric Liu } 121dffb1a80SEric Liu 122dffb1a80SEric Liu TEST_F(HeaderSearchTest, Dots) { 123dffb1a80SEric Liu addSearchDir("/x/./y/"); 124dffb1a80SEric Liu EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/x/y/./z", 1251f6d9845SKadir Cetinkaya /*WorkingDir=*/"", 1261f6d9845SKadir Cetinkaya /*MainFile=*/""), 127dffb1a80SEric Liu "z"); 128dffb1a80SEric Liu addSearchDir("a/.././c/"); 129dffb1a80SEric Liu EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/m/n/./c/z", 1301f6d9845SKadir Cetinkaya /*WorkingDir=*/"/m/n/", 1311f6d9845SKadir Cetinkaya /*MainFile=*/""), 132dffb1a80SEric Liu "z"); 133dffb1a80SEric Liu } 134dffb1a80SEric Liu 1358e0ba084Skadir çetinkaya TEST_F(HeaderSearchTest, RelativeDirs) { 1368e0ba084Skadir çetinkaya ASSERT_FALSE(VFS->setCurrentWorkingDirectory("/root/some/dir")); 1378e0ba084Skadir çetinkaya addSearchDir(".."); 1388e0ba084Skadir çetinkaya EXPECT_EQ( 1398e0ba084Skadir çetinkaya Search.suggestPathToFileForDiagnostics("/root/some/foo.h", 1408e0ba084Skadir çetinkaya /*WorkingDir=*/"/root/some/dir", 1418e0ba084Skadir çetinkaya /*MainFile=*/""), 1428e0ba084Skadir çetinkaya "foo.h"); 1438e0ba084Skadir çetinkaya EXPECT_EQ( 1448e0ba084Skadir çetinkaya Search.suggestPathToFileForDiagnostics("../foo.h", 1458e0ba084Skadir çetinkaya /*WorkingDir=*/"/root/some/dir", 1468e0ba084Skadir çetinkaya /*MainFile=*/""), 1478e0ba084Skadir çetinkaya "foo.h"); 1488e0ba084Skadir çetinkaya } 1498e0ba084Skadir çetinkaya 15040f8f7f9SKadir Cetinkaya #ifdef _WIN32 15140f8f7f9SKadir Cetinkaya TEST_F(HeaderSearchTest, BackSlash) { 15240f8f7f9SKadir Cetinkaya addSearchDir("C:\\x\\y\\"); 15340f8f7f9SKadir Cetinkaya EXPECT_EQ(Search.suggestPathToFileForDiagnostics("C:\\x\\y\\z\\t", 1541f6d9845SKadir Cetinkaya /*WorkingDir=*/"", 1551f6d9845SKadir Cetinkaya /*MainFile=*/""), 15640f8f7f9SKadir Cetinkaya "z/t"); 15740f8f7f9SKadir Cetinkaya } 15851f85b40SKadir Cetinkaya 15951f85b40SKadir Cetinkaya TEST_F(HeaderSearchTest, BackSlashWithDotDot) { 16051f85b40SKadir Cetinkaya addSearchDir("..\\y"); 16151f85b40SKadir Cetinkaya EXPECT_EQ(Search.suggestPathToFileForDiagnostics("C:\\x\\y\\z\\t", 1621f6d9845SKadir Cetinkaya /*WorkingDir=*/"C:/x/y/", 1631f6d9845SKadir Cetinkaya /*MainFile=*/""), 16451f85b40SKadir Cetinkaya "z/t"); 16551f85b40SKadir Cetinkaya } 16640f8f7f9SKadir Cetinkaya #endif 16740f8f7f9SKadir Cetinkaya 168936c67d3SKadir Cetinkaya TEST_F(HeaderSearchTest, DotDotsWithAbsPath) { 169936c67d3SKadir Cetinkaya addSearchDir("/x/../y/"); 170936c67d3SKadir Cetinkaya EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/y/z", 1711f6d9845SKadir Cetinkaya /*WorkingDir=*/"", 1721f6d9845SKadir Cetinkaya /*MainFile=*/""), 173936c67d3SKadir Cetinkaya "z"); 174936c67d3SKadir Cetinkaya } 175936c67d3SKadir Cetinkaya 1762c1fa734SSam McCall TEST_F(HeaderSearchTest, BothDotDots) { 1772c1fa734SSam McCall addSearchDir("/x/../y/"); 1782c1fa734SSam McCall EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/x/../y/z", 1792c1fa734SSam McCall /*WorkingDir=*/"", 1802c1fa734SSam McCall /*MainFile=*/""), 1812c1fa734SSam McCall "z"); 1822c1fa734SSam McCall } 1832c1fa734SSam McCall 1841f6d9845SKadir Cetinkaya TEST_F(HeaderSearchTest, IncludeFromSameDirectory) { 1851f6d9845SKadir Cetinkaya EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/y/z/t.h", 1861f6d9845SKadir Cetinkaya /*WorkingDir=*/"", 1871f6d9845SKadir Cetinkaya /*MainFile=*/"/y/a.cc"), 1881f6d9845SKadir Cetinkaya "z/t.h"); 1891f6d9845SKadir Cetinkaya 1901f6d9845SKadir Cetinkaya addSearchDir("/"); 1911f6d9845SKadir Cetinkaya EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/y/z/t.h", 1921f6d9845SKadir Cetinkaya /*WorkingDir=*/"", 1931f6d9845SKadir Cetinkaya /*MainFile=*/"/y/a.cc"), 1941f6d9845SKadir Cetinkaya "y/z/t.h"); 1951f6d9845SKadir Cetinkaya } 1961f6d9845SKadir Cetinkaya 1970cf7e61aSDavid Goldman TEST_F(HeaderSearchTest, SdkFramework) { 1989fe632baSDavid Goldman addFrameworkSearchDir( 1990cf7e61aSDavid Goldman "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/Frameworks/"); 2009fe632baSDavid Goldman bool IsAngled = false; 2010cf7e61aSDavid Goldman EXPECT_EQ(Search.suggestPathToFileForDiagnostics( 2020cf7e61aSDavid Goldman "/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/" 2030cf7e61aSDavid Goldman "Frameworks/AppKit.framework/Headers/NSView.h", 2040cf7e61aSDavid Goldman /*WorkingDir=*/"", 2059fe632baSDavid Goldman /*MainFile=*/"", &IsAngled), 2060cf7e61aSDavid Goldman "AppKit/NSView.h"); 2079fe632baSDavid Goldman EXPECT_TRUE(IsAngled); 2089fe632baSDavid Goldman 2099fe632baSDavid Goldman addFrameworkSearchDir("/System/Developer/Library/Framworks/", 2109fe632baSDavid Goldman /*IsSystem*/ false); 2119fe632baSDavid Goldman EXPECT_EQ(Search.suggestPathToFileForDiagnostics( 2129fe632baSDavid Goldman "/System/Developer/Library/Framworks/" 2139fe632baSDavid Goldman "Foo.framework/Headers/Foo.h", 2149fe632baSDavid Goldman /*WorkingDir=*/"", 2159fe632baSDavid Goldman /*MainFile=*/"", &IsAngled), 2169fe632baSDavid Goldman "Foo/Foo.h"); 2179fe632baSDavid Goldman // Expect to be true even though we passed false to IsSystem earlier since 2189fe632baSDavid Goldman // all frameworks should be treated as <>. 2199fe632baSDavid Goldman EXPECT_TRUE(IsAngled); 2200cf7e61aSDavid Goldman } 2210cf7e61aSDavid Goldman 2220cf7e61aSDavid Goldman TEST_F(HeaderSearchTest, NestedFramework) { 2239fe632baSDavid Goldman addFrameworkSearchDir("/Platforms/MacOSX/Frameworks"); 2240cf7e61aSDavid Goldman EXPECT_EQ(Search.suggestPathToFileForDiagnostics( 2250cf7e61aSDavid Goldman "/Platforms/MacOSX/Frameworks/AppKit.framework/Frameworks/" 2260cf7e61aSDavid Goldman "Sub.framework/Headers/Sub.h", 2270cf7e61aSDavid Goldman /*WorkingDir=*/"", 2280cf7e61aSDavid Goldman /*MainFile=*/""), 2290cf7e61aSDavid Goldman "Sub/Sub.h"); 2300cf7e61aSDavid Goldman } 2310cf7e61aSDavid Goldman 2329385ece9SDavid Goldman TEST_F(HeaderSearchTest, HeaderFrameworkLookup) { 2339385ece9SDavid Goldman std::string HeaderPath = "/tmp/Frameworks/Foo.framework/Headers/Foo.h"; 2349fe632baSDavid Goldman addFrameworkSearchDir("/tmp/Frameworks"); 235a41fbb1fSKazu Hirata VFS->addFile(HeaderPath, 0, 236a41fbb1fSKazu Hirata llvm::MemoryBuffer::getMemBufferCopy("", HeaderPath), 237a41fbb1fSKazu Hirata /*User=*/std::nullopt, /*Group=*/std::nullopt, 238a41fbb1fSKazu Hirata llvm::sys::fs::file_type::regular_file); 2399385ece9SDavid Goldman 2409385ece9SDavid Goldman bool IsFrameworkFound = false; 2419385ece9SDavid Goldman auto FoundFile = Search.LookupFile( 2429385ece9SDavid Goldman "Foo/Foo.h", SourceLocation(), /*isAngled=*/true, /*FromDir=*/nullptr, 2439385ece9SDavid Goldman /*CurDir=*/nullptr, /*Includers=*/{}, /*SearchPath=*/nullptr, 2449385ece9SDavid Goldman /*RelativePath=*/nullptr, /*RequestingModule=*/nullptr, 2459385ece9SDavid Goldman /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr, &IsFrameworkFound); 2469385ece9SDavid Goldman 24753daa177SKazu Hirata EXPECT_TRUE(FoundFile.has_value()); 2489385ece9SDavid Goldman EXPECT_TRUE(IsFrameworkFound); 2491e6adbadSFangrui Song auto &FE = *FoundFile; 2509385ece9SDavid Goldman auto FI = Search.getExistingFileInfo(FE); 2519385ece9SDavid Goldman EXPECT_TRUE(FI); 2529385ece9SDavid Goldman EXPECT_TRUE(FI->IsValid); 253b6c67c3cSCyndy Ishida EXPECT_EQ(Search.getIncludeNameForHeader(FE), "Foo/Foo.h"); 2549385ece9SDavid Goldman } 2559385ece9SDavid Goldman 256178ad93eSDmitry Polukhin // Helper struct with null terminator character to make MemoryBuffer happy. 257178ad93eSDmitry Polukhin template <class FileTy, class PaddingTy> 258178ad93eSDmitry Polukhin struct NullTerminatedFile : public FileTy { 259178ad93eSDmitry Polukhin PaddingTy Padding = 0; 260178ad93eSDmitry Polukhin }; 261178ad93eSDmitry Polukhin 262178ad93eSDmitry Polukhin TEST_F(HeaderSearchTest, HeaderMapReverseLookup) { 263178ad93eSDmitry Polukhin typedef NullTerminatedFile<test::HMapFileMock<2, 32>, char> FileTy; 264178ad93eSDmitry Polukhin FileTy File; 265178ad93eSDmitry Polukhin File.init(); 266178ad93eSDmitry Polukhin 267178ad93eSDmitry Polukhin test::HMapFileMockMaker<FileTy> Maker(File); 268178ad93eSDmitry Polukhin auto a = Maker.addString("d.h"); 269178ad93eSDmitry Polukhin auto b = Maker.addString("b/"); 270178ad93eSDmitry Polukhin auto c = Maker.addString("c.h"); 271178ad93eSDmitry Polukhin Maker.addBucket("d.h", a, b, c); 272178ad93eSDmitry Polukhin 273178ad93eSDmitry Polukhin addHeaderMap("/x/y/z.hmap", File.getBuffer()); 274178ad93eSDmitry Polukhin addSearchDir("/a"); 275178ad93eSDmitry Polukhin 276178ad93eSDmitry Polukhin EXPECT_EQ(Search.suggestPathToFileForDiagnostics("/a/b/c.h", 277178ad93eSDmitry Polukhin /*WorkingDir=*/"", 278178ad93eSDmitry Polukhin /*MainFile=*/""), 279178ad93eSDmitry Polukhin "d.h"); 280178ad93eSDmitry Polukhin } 281178ad93eSDmitry Polukhin 282395e1fe3SCyndy Ishida TEST_F(HeaderSearchTest, HeaderMapFrameworkLookup) { 283395e1fe3SCyndy Ishida typedef NullTerminatedFile<test::HMapFileMock<4, 128>, char> FileTy; 284395e1fe3SCyndy Ishida FileTy File; 285395e1fe3SCyndy Ishida File.init(); 286395e1fe3SCyndy Ishida 287395e1fe3SCyndy Ishida std::string HeaderDirName = "/tmp/Sources/Foo/Headers/"; 288395e1fe3SCyndy Ishida std::string HeaderName = "Foo.h"; 28999023627SDuncan P. N. Exon Smith if (is_style_windows(llvm::sys::path::Style::native)) { 290395e1fe3SCyndy Ishida // Force header path to be absolute on windows. 291395e1fe3SCyndy Ishida // As headermap content should represent absolute locations. 292395e1fe3SCyndy Ishida HeaderDirName = "C:" + HeaderDirName; 29399023627SDuncan P. N. Exon Smith } 294395e1fe3SCyndy Ishida 295395e1fe3SCyndy Ishida test::HMapFileMockMaker<FileTy> Maker(File); 296395e1fe3SCyndy Ishida auto a = Maker.addString("Foo/Foo.h"); 297395e1fe3SCyndy Ishida auto b = Maker.addString(HeaderDirName); 298395e1fe3SCyndy Ishida auto c = Maker.addString(HeaderName); 299395e1fe3SCyndy Ishida Maker.addBucket("Foo/Foo.h", a, b, c); 300395e1fe3SCyndy Ishida addHeaderMap("product-headers.hmap", File.getBuffer(), /*isAngled=*/true); 301395e1fe3SCyndy Ishida 302395e1fe3SCyndy Ishida VFS->addFile( 303395e1fe3SCyndy Ishida HeaderDirName + HeaderName, 0, 304395e1fe3SCyndy Ishida llvm::MemoryBuffer::getMemBufferCopy("", HeaderDirName + HeaderName), 305a41fbb1fSKazu Hirata /*User=*/std::nullopt, /*Group=*/std::nullopt, 306a41fbb1fSKazu Hirata llvm::sys::fs::file_type::regular_file); 307395e1fe3SCyndy Ishida 308395e1fe3SCyndy Ishida bool IsMapped = false; 309395e1fe3SCyndy Ishida auto FoundFile = Search.LookupFile( 310395e1fe3SCyndy Ishida "Foo/Foo.h", SourceLocation(), /*isAngled=*/true, /*FromDir=*/nullptr, 311105c9131SJan Svoboda /*CurDir=*/nullptr, /*Includers=*/{}, /*SearchPath=*/nullptr, 312395e1fe3SCyndy Ishida /*RelativePath=*/nullptr, /*RequestingModule=*/nullptr, 313395e1fe3SCyndy Ishida /*SuggestedModule=*/nullptr, &IsMapped, 314395e1fe3SCyndy Ishida /*IsFrameworkFound=*/nullptr); 315395e1fe3SCyndy Ishida 31653daa177SKazu Hirata EXPECT_TRUE(FoundFile.has_value()); 317395e1fe3SCyndy Ishida EXPECT_TRUE(IsMapped); 3181e6adbadSFangrui Song auto &FE = *FoundFile; 319395e1fe3SCyndy Ishida auto FI = Search.getExistingFileInfo(FE); 320395e1fe3SCyndy Ishida EXPECT_TRUE(FI); 321395e1fe3SCyndy Ishida EXPECT_TRUE(FI->IsValid); 322b6c67c3cSCyndy Ishida EXPECT_EQ(Search.getIncludeNameForHeader(FE), "Foo/Foo.h"); 323395e1fe3SCyndy Ishida } 324395e1fe3SCyndy Ishida 32529b0d575SIan Anderson TEST_F(HeaderSearchTest, HeaderFileInfoMerge) { 32629b0d575SIan Anderson auto AddHeader = [&](std::string HeaderPath) -> FileEntryRef { 32729b0d575SIan Anderson VFS->addFile(HeaderPath, 0, 32829b0d575SIan Anderson llvm::MemoryBuffer::getMemBufferCopy("", HeaderPath), 32929b0d575SIan Anderson /*User=*/std::nullopt, /*Group=*/std::nullopt, 33029b0d575SIan Anderson llvm::sys::fs::file_type::regular_file); 33129b0d575SIan Anderson return *FileMgr.getOptionalFileRef(HeaderPath); 33229b0d575SIan Anderson }; 33329b0d575SIan Anderson 33429b0d575SIan Anderson class MockExternalHeaderFileInfoSource : public ExternalHeaderFileInfoSource { 33529b0d575SIan Anderson HeaderFileInfo GetHeaderFileInfo(FileEntryRef FE) { 33629b0d575SIan Anderson HeaderFileInfo HFI; 33729b0d575SIan Anderson auto FileName = FE.getName(); 33829b0d575SIan Anderson if (FileName == ModularPath) 33929b0d575SIan Anderson HFI.mergeModuleMembership(ModuleMap::NormalHeader); 34029b0d575SIan Anderson else if (FileName == TextualPath) 34129b0d575SIan Anderson HFI.mergeModuleMembership(ModuleMap::TextualHeader); 34229b0d575SIan Anderson HFI.External = true; 34329b0d575SIan Anderson HFI.IsValid = true; 34429b0d575SIan Anderson return HFI; 34529b0d575SIan Anderson } 34629b0d575SIan Anderson 34729b0d575SIan Anderson public: 34829b0d575SIan Anderson std::string ModularPath = "/modular.h"; 34929b0d575SIan Anderson std::string TextualPath = "/textual.h"; 35029b0d575SIan Anderson }; 35129b0d575SIan Anderson 352f1eae81cSDanial Klimkin auto ExternalSource = std::make_unique<MockExternalHeaderFileInfoSource>(); 353f1eae81cSDanial Klimkin Search.SetExternalSource(ExternalSource.get()); 35429b0d575SIan Anderson 35529b0d575SIan Anderson // Everything should start out external. 35629b0d575SIan Anderson auto ModularFE = AddHeader(ExternalSource->ModularPath); 35729b0d575SIan Anderson auto TextualFE = AddHeader(ExternalSource->TextualPath); 35829b0d575SIan Anderson EXPECT_TRUE(Search.getExistingFileInfo(ModularFE)->External); 35929b0d575SIan Anderson EXPECT_TRUE(Search.getExistingFileInfo(TextualFE)->External); 36029b0d575SIan Anderson 36129b0d575SIan Anderson // Marking the same role should keep it external 36229b0d575SIan Anderson Search.MarkFileModuleHeader(ModularFE, ModuleMap::NormalHeader, 36329b0d575SIan Anderson /*isCompilingModuleHeader=*/false); 36429b0d575SIan Anderson Search.MarkFileModuleHeader(TextualFE, ModuleMap::TextualHeader, 36529b0d575SIan Anderson /*isCompilingModuleHeader=*/false); 36629b0d575SIan Anderson EXPECT_TRUE(Search.getExistingFileInfo(ModularFE)->External); 36729b0d575SIan Anderson EXPECT_TRUE(Search.getExistingFileInfo(TextualFE)->External); 36829b0d575SIan Anderson 36929b0d575SIan Anderson // textual -> modular should update the HFI, but modular -> textual should be 37029b0d575SIan Anderson // a no-op. 37129b0d575SIan Anderson Search.MarkFileModuleHeader(ModularFE, ModuleMap::TextualHeader, 37229b0d575SIan Anderson /*isCompilingModuleHeader=*/false); 37329b0d575SIan Anderson Search.MarkFileModuleHeader(TextualFE, ModuleMap::NormalHeader, 37429b0d575SIan Anderson /*isCompilingModuleHeader=*/false); 37529b0d575SIan Anderson auto ModularFI = Search.getExistingFileInfo(ModularFE); 37629b0d575SIan Anderson auto TextualFI = Search.getExistingFileInfo(TextualFE); 37729b0d575SIan Anderson EXPECT_TRUE(ModularFI->External); 37829b0d575SIan Anderson EXPECT_TRUE(ModularFI->isModuleHeader); 37929b0d575SIan Anderson EXPECT_FALSE(ModularFI->isTextualModuleHeader); 38029b0d575SIan Anderson EXPECT_FALSE(TextualFI->External); 38129b0d575SIan Anderson EXPECT_TRUE(TextualFI->isModuleHeader); 38229b0d575SIan Anderson EXPECT_FALSE(TextualFI->isTextualModuleHeader); 38329b0d575SIan Anderson 38429b0d575SIan Anderson // Compiling the module should make the HFI local. 38529b0d575SIan Anderson Search.MarkFileModuleHeader(ModularFE, ModuleMap::NormalHeader, 38629b0d575SIan Anderson /*isCompilingModuleHeader=*/true); 38729b0d575SIan Anderson Search.MarkFileModuleHeader(TextualFE, ModuleMap::NormalHeader, 38829b0d575SIan Anderson /*isCompilingModuleHeader=*/true); 38929b0d575SIan Anderson EXPECT_FALSE(Search.getExistingFileInfo(ModularFE)->External); 39029b0d575SIan Anderson EXPECT_FALSE(Search.getExistingFileInfo(TextualFE)->External); 39129b0d575SIan Anderson } 39229b0d575SIan Anderson 393dffb1a80SEric Liu } // namespace 394dffb1a80SEric Liu } // namespace clang 395