diff options
Diffstat (limited to 'clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp')
| -rw-r--r-- | clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp | 129 |
1 files changed, 123 insertions, 6 deletions
diff --git a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp index 6823fc557ee..e6cc01b8a76 100644 --- a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp +++ b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp @@ -8,10 +8,21 @@ #include "GlobalCompilationDatabase.h" +#include "Path.h" #include "TestFS.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include <fstream> +#include <string> namespace clang { namespace clangd { @@ -20,8 +31,10 @@ using ::testing::AllOf; using ::testing::Contains; using ::testing::ElementsAre; using ::testing::EndsWith; +using ::testing::IsEmpty; using ::testing::Not; using ::testing::StartsWith; +using ::testing::UnorderedElementsAre; TEST(GlobalCompilationDatabaseTest, FallbackCommand) { DirectoryBasedGlobalCompilationDatabase DB(None); @@ -50,13 +63,9 @@ class OverlayCDBTest : public ::testing::Test { class BaseCDB : public GlobalCompilationDatabase { public: llvm::Optional<tooling::CompileCommand> - getCompileCommand(llvm::StringRef File, - ProjectInfo *Project) const override { - if (File == testPath("foo.cc")) { - if (Project) - Project->SourceRoot = testRoot(); + getCompileCommand(llvm::StringRef File) const override { + if (File == testPath("foo.cc")) return cmd(File, "-DA=1"); - } return None; } @@ -64,6 +73,10 @@ class OverlayCDBTest : public ::testing::Test { getFallbackCommand(llvm::StringRef File) const override { return cmd(File, "-DA=2"); } + + llvm::Optional<ProjectInfo> getProjectInfo(PathRef File) const override { + return ProjectInfo{testRoot()}; + } }; protected: @@ -153,6 +166,110 @@ TEST_F(OverlayCDBTest, Adjustments) { Not(Contains("random-plugin")))); } +TEST(GlobalCompilationDatabaseTest, DiscoveryWithNestedCDBs) { + const char *const CDBOuter = + R"cdb( + [ + { + "file": "a.cc", + "command": "", + "directory": "{0}", + }, + { + "file": "build/gen.cc", + "command": "", + "directory": "{0}", + }, + { + "file": "build/gen2.cc", + "command": "", + "directory": "{0}", + } + ] + )cdb"; + const char *const CDBInner = + R"cdb( + [ + { + "file": "gen.cc", + "command": "", + "directory": "{0}/build", + } + ] + )cdb"; + class CleaningFS { + public: + llvm::SmallString<128> Root; + + CleaningFS() { + EXPECT_FALSE( + llvm::sys::fs::createUniqueDirectory("clangd-cdb-test", Root)) + << "Failed to create unique directory"; + } + + ~CleaningFS() { + EXPECT_FALSE(llvm::sys::fs::remove_directories(Root)) + << "Failed to cleanup " << Root; + } + + void registerFile(PathRef RelativePath, llvm::StringRef Contents) { + llvm::SmallString<128> AbsPath(Root); + llvm::sys::path::append(AbsPath, RelativePath); + + EXPECT_FALSE(llvm::sys::fs::create_directories( + llvm::sys::path::parent_path(AbsPath))) + << "Failed to create directories for: " << AbsPath; + + std::error_code EC; + llvm::raw_fd_ostream OS(AbsPath, EC); + EXPECT_FALSE(EC) << "Failed to open " << AbsPath << " for writing"; + OS << llvm::formatv(Contents.data(), + llvm::sys::path::convert_to_slash(Root)); + OS.close(); + + EXPECT_FALSE(OS.has_error()); + } + }; + + CleaningFS FS; + FS.registerFile("compile_commands.json", CDBOuter); + FS.registerFile("build/compile_commands.json", CDBInner); + + // Note that gen2.cc goes missing with our following model, not sure this + // happens in practice though. + { + DirectoryBasedGlobalCompilationDatabase DB(llvm::None); + std::vector<std::string> DiscoveredFiles; + auto Sub = + DB.watch([&DiscoveredFiles](const std::vector<std::string> Changes) { + DiscoveredFiles = Changes; + }); + DB.getCompileCommand((FS.Root + "/a.cc").str()); + EXPECT_THAT(DiscoveredFiles, UnorderedElementsAre(EndsWith("a.cc"))); + + DB.getCompileCommand((FS.Root + "/build/gen.cc").str()); + EXPECT_THAT(DiscoveredFiles, UnorderedElementsAre(EndsWith("gen.cc"))); + } + + // With a custom compile commands dir. + { + DirectoryBasedGlobalCompilationDatabase DB(FS.Root.str().str()); + std::vector<std::string> DiscoveredFiles; + auto Sub = + DB.watch([&DiscoveredFiles](const std::vector<std::string> Changes) { + DiscoveredFiles = Changes; + }); + DB.getCompileCommand((FS.Root + "/a.cc").str()); + EXPECT_THAT(DiscoveredFiles, + UnorderedElementsAre(EndsWith("a.cc"), EndsWith("gen.cc"), + EndsWith("gen2.cc"))); + + DiscoveredFiles.clear(); + DB.getCompileCommand((FS.Root + "/build/gen.cc").str()); + EXPECT_THAT(DiscoveredFiles, IsEmpty()); + } +} + } // namespace } // namespace clangd } // namespace clang |

