13 #include "clang/Tooling/CompilationDatabase.h" 14 #include "llvm/ADT/Optional.h" 15 #include "llvm/ADT/SmallString.h" 16 #include "llvm/ADT/StringExtras.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/Support/FileSystem.h" 19 #include "llvm/Support/FormatVariadic.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/Path.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include "gmock/gmock.h" 24 #include "gtest/gtest.h" 31 using ::testing::AllOf;
32 using ::testing::Contains;
33 using ::testing::ElementsAre;
34 using ::testing::EndsWith;
35 using ::testing::HasSubstr;
36 using ::testing::IsEmpty;
38 using ::testing::StartsWith;
39 using ::testing::UnorderedElementsAre;
41 TEST(GlobalCompilationDatabaseTest, FallbackCommand) {
42 DirectoryBasedGlobalCompilationDatabase DB(None);
43 auto Cmd = DB.getFallbackCommand(
testPath(
"foo/bar.cc"));
44 EXPECT_EQ(Cmd.Directory,
testPath(
"foo"));
45 EXPECT_THAT(Cmd.CommandLine, ElementsAre(
"clang",
testPath(
"foo/bar.cc")));
46 EXPECT_EQ(Cmd.Output,
"");
49 Cmd = DB.getFallbackCommand(
testPath(
"foo/bar.h"));
50 EXPECT_THAT(Cmd.CommandLine, ElementsAre(
"clang",
"-xobjective-c++-header",
52 Cmd = DB.getFallbackCommand(
testPath(
"foo/bar"));
53 EXPECT_THAT(Cmd.CommandLine, ElementsAre(
"clang",
"-xobjective-c++-header",
57 static tooling::CompileCommand cmd(llvm::StringRef File, llvm::StringRef Arg) {
58 return tooling::CompileCommand(
testRoot(), File, {
"clang", Arg, File},
"");
61 class OverlayCDBTest :
public ::testing::Test {
62 class BaseCDB :
public GlobalCompilationDatabase {
64 llvm::Optional<tooling::CompileCommand>
65 getCompileCommand(llvm::StringRef File)
const override {
67 return cmd(File,
"-DA=1");
71 tooling::CompileCommand
72 getFallbackCommand(llvm::StringRef File)
const override {
73 return cmd(File,
"-DA=2");
76 llvm::Optional<ProjectInfo> getProjectInfo(
PathRef File)
const override {
82 OverlayCDBTest() :
Base(std::make_unique<BaseCDB>()) {}
83 std::unique_ptr<GlobalCompilationDatabase>
Base;
86 TEST_F(OverlayCDBTest, GetCompileCommand) {
87 OverlayCDB CDB(
Base.get());
88 EXPECT_THAT(CDB.getCompileCommand(
testPath(
"foo.cc"))->CommandLine,
89 AllOf(Contains(
testPath(
"foo.cc")), Contains(
"-DA=1")));
92 auto Override = cmd(
testPath(
"foo.cc"),
"-DA=3");
93 CDB.setCompileCommand(
testPath(
"foo.cc"), Override);
94 EXPECT_THAT(CDB.getCompileCommand(
testPath(
"foo.cc"))->CommandLine,
97 CDB.setCompileCommand(
testPath(
"missing.cc"), Override);
98 EXPECT_THAT(CDB.getCompileCommand(
testPath(
"missing.cc"))->CommandLine,
102 TEST_F(OverlayCDBTest, GetFallbackCommand) {
103 OverlayCDB CDB(
Base.get(), {
"-DA=4"});
104 EXPECT_THAT(CDB.getFallbackCommand(
testPath(
"bar.cc")).CommandLine,
105 ElementsAre(
"clang",
"-DA=2",
testPath(
"bar.cc"),
"-DA=4"));
108 TEST_F(OverlayCDBTest, NoBase) {
109 OverlayCDB CDB(
nullptr, {
"-DA=6"});
110 EXPECT_EQ(CDB.getCompileCommand(
testPath(
"bar.cc")),
None);
111 auto Override = cmd(
testPath(
"bar.cc"),
"-DA=5");
112 CDB.setCompileCommand(
testPath(
"bar.cc"), Override);
113 EXPECT_THAT(CDB.getCompileCommand(
testPath(
"bar.cc"))->CommandLine,
116 EXPECT_THAT(CDB.getFallbackCommand(
testPath(
"foo.cc")).CommandLine,
117 ElementsAre(
"clang",
testPath(
"foo.cc"),
"-DA=6"));
120 TEST_F(OverlayCDBTest, Watch) {
121 OverlayCDB Inner(
nullptr);
122 OverlayCDB Outer(&Inner);
124 std::vector<std::vector<std::string>>
Changes;
125 auto Sub = Outer.watch([&](
const std::vector<std::string> &ChangedFiles) {
126 Changes.push_back(ChangedFiles);
129 Inner.setCompileCommand(
"A.cpp", tooling::CompileCommand());
130 Outer.setCompileCommand(
"B.cpp", tooling::CompileCommand());
133 EXPECT_THAT(Changes, ElementsAre(ElementsAre(
"A.cpp"), ElementsAre(
"B.cpp"),
134 ElementsAre(
"A.cpp"), ElementsAre(
"C.cpp")));
137 TEST_F(OverlayCDBTest, Adjustments) {
138 OverlayCDB CDB(
Base.get(), {
"-DFallback"},
139 [](
const std::vector<std::string> &Cmd, llvm::StringRef
File) {
142 (
"-DAdjust_" + llvm::sys::path::filename(File)).str());
146 auto Cmd = CDB.getCompileCommand(
testPath(
"foo.cc")).getValue();
147 EXPECT_THAT(Cmd.CommandLine, ElementsAre(
"clang",
"-DA=1",
testPath(
"foo.cc"),
151 tooling::CompileCommand BarCommand;
152 BarCommand.Filename =
testPath(
"bar.cc");
153 BarCommand.CommandLine = {
"clang++",
"-DB=1",
testPath(
"bar.cc")};
154 CDB.setCompileCommand(
testPath(
"bar.cc"), BarCommand);
155 Cmd = CDB.getCompileCommand(
testPath(
"bar.cc")).getValue();
158 ElementsAre(
"clang++",
"-DB=1",
testPath(
"bar.cc"),
"-DAdjust_bar.cc"));
161 Cmd = CDB.getFallbackCommand(
"baz.cc");
162 EXPECT_THAT(Cmd.CommandLine, ElementsAre(
"clang",
"-DA=2",
"baz.cc",
163 "-DFallback",
"-DAdjust_baz.cc"));
166 TEST(GlobalCompilationDatabaseTest, DiscoveryWithNestedCDBs) {
167 const char *
const CDBOuter =
176 "file": "build/gen.cc", 181 "file": "build/gen2.cc", 187 const char *
const CDBInner =
193 "directory": "{0}/build", 199 llvm::SmallString<128> Root;
203 llvm::sys::fs::createUniqueDirectory(
"clangd-cdb-test", Root))
204 <<
"Failed to create unique directory";
208 EXPECT_FALSE(llvm::sys::fs::remove_directories(Root))
209 <<
"Failed to cleanup " << Root;
213 llvm::SmallString<128> AbsPath(Root);
214 llvm::sys::path::append(AbsPath, RelativePath);
216 EXPECT_FALSE(llvm::sys::fs::create_directories(
217 llvm::sys::path::parent_path(AbsPath)))
218 <<
"Failed to create directories for: " << AbsPath;
221 llvm::raw_fd_ostream OS(AbsPath, EC);
222 EXPECT_FALSE(EC) <<
"Failed to open " << AbsPath <<
" for writing";
223 OS << llvm::formatv(Contents.data(),
224 llvm::sys::path::convert_to_slash(Root));
227 EXPECT_FALSE(OS.has_error());
232 FS.registerFile(
"compile_commands.json", CDBOuter);
233 FS.registerFile(
"build/compile_commands.json", CDBInner);
234 llvm::SmallString<128>
File;
239 DirectoryBasedGlobalCompilationDatabase DB(
llvm::None);
240 std::vector<std::string> DiscoveredFiles;
242 DB.watch([&DiscoveredFiles](
const std::vector<std::string>
Changes) {
247 llvm::sys::path::append(File,
"build",
"..",
"a.cc");
248 DB.getCompileCommand(File.str());
249 EXPECT_THAT(DiscoveredFiles, UnorderedElementsAre(AllOf(
250 EndsWith(
"a.cc"), Not(HasSubstr(
"..")))));
251 DiscoveredFiles.clear();
254 llvm::sys::path::append(File,
"build",
"gen.cc");
255 DB.getCompileCommand(File.str());
256 EXPECT_THAT(DiscoveredFiles, UnorderedElementsAre(EndsWith(
"gen.cc")));
261 DirectoryBasedGlobalCompilationDatabase DB(FS.Root.str().str());
262 std::vector<std::string> DiscoveredFiles;
264 DB.watch([&DiscoveredFiles](
const std::vector<std::string>
Changes) {
269 llvm::sys::path::append(File,
"a.cc");
270 DB.getCompileCommand(File.str());
271 EXPECT_THAT(DiscoveredFiles,
272 UnorderedElementsAre(EndsWith(
"a.cc"), EndsWith(
"gen.cc"),
273 EndsWith(
"gen2.cc")));
274 DiscoveredFiles.clear();
277 llvm::sys::path::append(File,
"build",
"gen.cc");
278 DB.getCompileCommand(File.str());
279 EXPECT_THAT(DiscoveredFiles, IsEmpty());
283 TEST(GlobalCompilationDatabaseTest, NonCanonicalFilenames) {
284 OverlayCDB DB(
nullptr);
285 std::vector<std::string> DiscoveredFiles;
287 DB.watch([&DiscoveredFiles](
const std::vector<std::string>
Changes) {
291 llvm::SmallString<128> Root(
testRoot());
292 llvm::sys::path::append(Root,
"build",
"..",
"a.cc");
293 DB.setCompileCommand(Root.str(), tooling::CompileCommand());
294 EXPECT_THAT(DiscoveredFiles, UnorderedElementsAre(
testPath(
"a.cc")));
295 DiscoveredFiles.clear();
298 llvm::sys::path::append(File,
"blabla",
"..",
"a.cc");
300 EXPECT_TRUE(DB.getCompileCommand(File));
301 EXPECT_TRUE(DB.getProjectInfo(File));
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Documents should not be synced at all.
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
TEST(BackgroundQueueTest, Priority)
std::string testPath(PathRef File)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::unique_ptr< GlobalCompilationDatabase > Base