]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - unittests/Tooling/CompilationDatabaseTest.cpp
Vendor import of clang trunk r290819:
[FreeBSD/FreeBSD.git] / unittests / Tooling / CompilationDatabaseTest.cpp
1 //===- unittest/Tooling/CompilationDatabaseTest.cpp -----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "clang/AST/DeclCXX.h"
11 #include "clang/AST/DeclGroup.h"
12 #include "clang/Frontend/FrontendAction.h"
13 #include "clang/Tooling/FileMatchTrie.h"
14 #include "clang/Tooling/JSONCompilationDatabase.h"
15 #include "clang/Tooling/Tooling.h"
16 #include "llvm/Support/Path.h"
17 #include "gtest/gtest.h"
18
19 namespace clang {
20 namespace tooling {
21
22 static void expectFailure(StringRef JSONDatabase, StringRef Explanation) {
23   std::string ErrorMessage;
24   EXPECT_EQ(nullptr,
25             JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
26                                                     JSONCommandLineSyntax::Gnu))
27       << "Expected an error because of: " << Explanation.str();
28 }
29
30 TEST(JSONCompilationDatabase, ErrsOnInvalidFormat) {
31   expectFailure("", "Empty database");
32   expectFailure("{", "Invalid JSON");
33   expectFailure("[[]]", "Array instead of object");
34   expectFailure("[{\"a\":[]}]", "Array instead of value");
35   expectFailure("[{\"a\":\"b\"}]", "Unknown key");
36   expectFailure("[{[]:\"\"}]", "Incorrectly typed entry");
37   expectFailure("[{}]", "Empty entry");
38   expectFailure("[{\"directory\":\"\",\"command\":\"\"}]", "Missing file");
39   expectFailure("[{\"directory\":\"\",\"file\":\"\"}]", "Missing command or arguments");
40   expectFailure("[{\"command\":\"\",\"file\":\"\"}]", "Missing directory");
41   expectFailure("[{\"directory\":\"\",\"arguments\":[]}]", "Missing file");
42   expectFailure("[{\"arguments\":\"\",\"file\":\"\"}]", "Missing directory");
43   expectFailure("[{\"directory\":\"\",\"arguments\":\"\",\"file\":\"\"}]", "Arguments not array");
44   expectFailure("[{\"directory\":\"\",\"command\":[],\"file\":\"\"}]", "Command not string");
45   expectFailure("[{\"directory\":\"\",\"arguments\":[[]],\"file\":\"\"}]",
46                 "Arguments contain non-string");
47   expectFailure("[{\"output\":[]}]", "Expected strings as value.");
48 }
49
50 static std::vector<std::string> getAllFiles(StringRef JSONDatabase,
51                                             std::string &ErrorMessage,
52                                             JSONCommandLineSyntax Syntax) {
53   std::unique_ptr<CompilationDatabase> Database(
54       JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
55                                               Syntax));
56   if (!Database) {
57     ADD_FAILURE() << ErrorMessage;
58     return std::vector<std::string>();
59   }
60   return Database->getAllFiles();
61 }
62
63 static std::vector<CompileCommand>
64 getAllCompileCommands(JSONCommandLineSyntax Syntax, StringRef JSONDatabase,
65                       std::string &ErrorMessage) {
66   std::unique_ptr<CompilationDatabase> Database(
67       JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
68                                               Syntax));
69   if (!Database) {
70     ADD_FAILURE() << ErrorMessage;
71     return std::vector<CompileCommand>();
72   }
73   return Database->getAllCompileCommands();
74 }
75
76 TEST(JSONCompilationDatabase, GetAllFiles) {
77   std::string ErrorMessage;
78   EXPECT_EQ(std::vector<std::string>(),
79             getAllFiles("[]", ErrorMessage, JSONCommandLineSyntax::Gnu))
80       << ErrorMessage;
81
82   std::vector<std::string> expected_files;
83   SmallString<16> PathStorage;
84   llvm::sys::path::native("//net/dir/file1", PathStorage);
85   expected_files.push_back(PathStorage.str());
86   llvm::sys::path::native("//net/dir/file2", PathStorage);
87   expected_files.push_back(PathStorage.str());
88   EXPECT_EQ(expected_files,
89             getAllFiles("[{\"directory\":\"//net/dir\","
90                         "\"command\":\"command\","
91                         "\"file\":\"file1\"},"
92                         " {\"directory\":\"//net/dir\","
93                         "\"command\":\"command\","
94                         "\"file\":\"file2\"}]",
95                         ErrorMessage, JSONCommandLineSyntax::Gnu))
96       << ErrorMessage;
97 }
98
99 TEST(JSONCompilationDatabase, GetAllCompileCommands) {
100   std::string ErrorMessage;
101   EXPECT_EQ(
102       0u, getAllCompileCommands(JSONCommandLineSyntax::Gnu, "[]", ErrorMessage)
103               .size())
104       << ErrorMessage;
105
106   StringRef Directory1("//net/dir1");
107   StringRef FileName1("file1");
108   StringRef Command1("command1");
109   StringRef Output1("file1.o");
110   StringRef Directory2("//net/dir2");
111   StringRef FileName2("file2");
112   StringRef Command2("command2");
113   StringRef Output2("");
114
115   std::vector<CompileCommand> Commands = getAllCompileCommands(
116       JSONCommandLineSyntax::Gnu,
117       ("[{\"directory\":\"" + Directory1 + "\"," + "\"command\":\"" + Command1 +
118        "\","
119        "\"file\":\"" +
120        FileName1 + "\", \"output\":\"" +
121        Output1 + "\"},"
122                    " {\"directory\":\"" +
123        Directory2 + "\"," + "\"command\":\"" + Command2 + "\","
124                                                           "\"file\":\"" +
125        FileName2 + "\"}]")
126           .str(),
127       ErrorMessage);
128   EXPECT_EQ(2U, Commands.size()) << ErrorMessage;
129   EXPECT_EQ(Directory1, Commands[0].Directory) << ErrorMessage;
130   EXPECT_EQ(FileName1, Commands[0].Filename) << ErrorMessage;
131   EXPECT_EQ(Output1, Commands[0].Output) << ErrorMessage;
132   ASSERT_EQ(1u, Commands[0].CommandLine.size());
133   EXPECT_EQ(Command1, Commands[0].CommandLine[0]) << ErrorMessage;
134   EXPECT_EQ(Directory2, Commands[1].Directory) << ErrorMessage;
135   EXPECT_EQ(FileName2, Commands[1].Filename) << ErrorMessage;
136   EXPECT_EQ(Output2, Commands[1].Output) << ErrorMessage;
137   ASSERT_EQ(1u, Commands[1].CommandLine.size());
138   EXPECT_EQ(Command2, Commands[1].CommandLine[0]) << ErrorMessage;
139
140   // Check that order is preserved.
141   Commands = getAllCompileCommands(
142       JSONCommandLineSyntax::Gnu,
143       ("[{\"directory\":\"" + Directory2 + "\"," + "\"command\":\"" + Command2 +
144        "\","
145        "\"file\":\"" +
146        FileName2 + "\"},"
147                    " {\"directory\":\"" +
148        Directory1 + "\"," + "\"command\":\"" + Command1 + "\","
149                                                           "\"file\":\"" +
150        FileName1 + "\"}]")
151           .str(),
152       ErrorMessage);
153   EXPECT_EQ(2U, Commands.size()) << ErrorMessage;
154   EXPECT_EQ(Directory2, Commands[0].Directory) << ErrorMessage;
155   EXPECT_EQ(FileName2, Commands[0].Filename) << ErrorMessage;
156   ASSERT_EQ(1u, Commands[0].CommandLine.size());
157   EXPECT_EQ(Command2, Commands[0].CommandLine[0]) << ErrorMessage;
158   EXPECT_EQ(Directory1, Commands[1].Directory) << ErrorMessage;
159   EXPECT_EQ(FileName1, Commands[1].Filename) << ErrorMessage;
160   ASSERT_EQ(1u, Commands[1].CommandLine.size());
161   EXPECT_EQ(Command1, Commands[1].CommandLine[0]) << ErrorMessage;
162 }
163
164 static CompileCommand findCompileArgsInJsonDatabase(StringRef FileName,
165                                                     StringRef JSONDatabase,
166                                                     std::string &ErrorMessage) {
167   std::unique_ptr<CompilationDatabase> Database(
168       JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage,
169                                               JSONCommandLineSyntax::Gnu));
170   if (!Database)
171     return CompileCommand();
172   std::vector<CompileCommand> Commands = Database->getCompileCommands(FileName);
173   EXPECT_LE(Commands.size(), 1u);
174   if (Commands.empty())
175     return CompileCommand();
176   return Commands[0];
177 }
178
179 TEST(JSONCompilationDatabase, ArgumentsPreferredOverCommand) {
180    StringRef Directory("//net/dir");
181    StringRef FileName("//net/dir/filename");
182    StringRef Command("command");
183    StringRef Arguments = "arguments";
184    Twine ArgumentsAccumulate;
185    std::string ErrorMessage;
186    CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
187       FileName,
188       ("[{\"directory\":\"" + Directory + "\","
189          "\"arguments\":[\"" + Arguments + "\"],"
190          "\"command\":\"" + Command + "\","
191          "\"file\":\"" + FileName + "\"}]").str(),
192       ErrorMessage);
193    EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
194    EXPECT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage;
195    EXPECT_EQ(Arguments, FoundCommand.CommandLine[0]) << ErrorMessage;
196 }
197
198 struct FakeComparator : public PathComparator {
199   ~FakeComparator() override {}
200   bool equivalent(StringRef FileA, StringRef FileB) const override {
201     return FileA.equals_lower(FileB);
202   }
203 };
204
205 class FileMatchTrieTest : public ::testing::Test {
206 protected:
207   FileMatchTrieTest() : Trie(new FakeComparator()) {}
208
209   StringRef find(StringRef Path) {
210     llvm::raw_string_ostream ES(Error);
211     return Trie.findEquivalent(Path, ES);
212   }
213
214   FileMatchTrie Trie;
215   std::string Error;
216 };
217
218 TEST_F(FileMatchTrieTest, InsertingRelativePath) {
219   Trie.insert("//net/path/file.cc");
220   Trie.insert("file.cc");
221   EXPECT_EQ("//net/path/file.cc", find("//net/path/file.cc"));
222 }
223
224 TEST_F(FileMatchTrieTest, MatchingRelativePath) {
225   EXPECT_EQ("", find("file.cc"));
226 }
227
228 TEST_F(FileMatchTrieTest, ReturnsBestResults) {
229   Trie.insert("//net/d/c/b.cc");
230   Trie.insert("//net/d/b/b.cc");
231   EXPECT_EQ("//net/d/b/b.cc", find("//net/d/b/b.cc"));
232 }
233
234 TEST_F(FileMatchTrieTest, HandlesSymlinks) {
235   Trie.insert("//net/AA/file.cc");
236   EXPECT_EQ("//net/AA/file.cc", find("//net/aa/file.cc"));
237 }
238
239 TEST_F(FileMatchTrieTest, ReportsSymlinkAmbiguity) {
240   Trie.insert("//net/Aa/file.cc");
241   Trie.insert("//net/aA/file.cc");
242   EXPECT_TRUE(find("//net/aa/file.cc").empty());
243   EXPECT_EQ("Path is ambiguous", Error);
244 }
245
246 TEST_F(FileMatchTrieTest, LongerMatchingSuffixPreferred) {
247   Trie.insert("//net/src/Aa/file.cc");
248   Trie.insert("//net/src/aA/file.cc");
249   Trie.insert("//net/SRC/aa/file.cc");
250   EXPECT_EQ("//net/SRC/aa/file.cc", find("//net/src/aa/file.cc"));
251 }
252
253 TEST_F(FileMatchTrieTest, EmptyTrie) {
254   EXPECT_TRUE(find("//net/some/path").empty());
255 }
256
257 TEST_F(FileMatchTrieTest, NoResult) {
258   Trie.insert("//net/somepath/otherfile.cc");
259   Trie.insert("//net/otherpath/somefile.cc");
260   EXPECT_EQ("", find("//net/somepath/somefile.cc"));
261 }
262
263 TEST_F(FileMatchTrieTest, RootElementDifferent) {
264   Trie.insert("//net/path/file.cc");
265   Trie.insert("//net/otherpath/file.cc");
266   EXPECT_EQ("//net/path/file.cc", find("//net/path/file.cc"));
267 }
268
269 TEST_F(FileMatchTrieTest, CannotResolveRelativePath) {
270   EXPECT_EQ("", find("relative-path.cc"));
271   EXPECT_EQ("Cannot resolve relative paths", Error);
272 }
273
274 TEST(findCompileArgsInJsonDatabase, FindsNothingIfEmpty) {
275   std::string ErrorMessage;
276   CompileCommand NotFound = findCompileArgsInJsonDatabase(
277     "a-file.cpp", "", ErrorMessage);
278   EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
279   EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
280 }
281
282 TEST(findCompileArgsInJsonDatabase, ReadsSingleEntry) {
283   StringRef Directory("//net/some/directory");
284   StringRef FileName("//net/path/to/a-file.cpp");
285   StringRef Command("//net/path/to/compiler and some arguments");
286   std::string ErrorMessage;
287   CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
288     FileName,
289     ("[{\"directory\":\"" + Directory + "\"," +
290        "\"command\":\"" + Command + "\","
291        "\"file\":\"" + FileName + "\"}]").str(),
292     ErrorMessage);
293   EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
294   ASSERT_EQ(4u, FoundCommand.CommandLine.size()) << ErrorMessage;
295   EXPECT_EQ("//net/path/to/compiler",
296             FoundCommand.CommandLine[0]) << ErrorMessage;
297   EXPECT_EQ("and", FoundCommand.CommandLine[1]) << ErrorMessage;
298   EXPECT_EQ("some", FoundCommand.CommandLine[2]) << ErrorMessage;
299   EXPECT_EQ("arguments", FoundCommand.CommandLine[3]) << ErrorMessage;
300
301   CompileCommand NotFound = findCompileArgsInJsonDatabase(
302     "a-file.cpp",
303     ("[{\"directory\":\"" + Directory + "\"," +
304        "\"command\":\"" + Command + "\","
305        "\"file\":\"" + FileName + "\"}]").str(),
306     ErrorMessage);
307   EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
308   EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
309 }
310
311 TEST(findCompileArgsInJsonDatabase, ReadsCompileCommandLinesWithSpaces) {
312   StringRef Directory("//net/some/directory");
313   StringRef FileName("//net/path/to/a-file.cpp");
314   StringRef Command("\\\"//net/path to compiler\\\" \\\"and an argument\\\"");
315   std::string ErrorMessage;
316   CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
317     FileName,
318     ("[{\"directory\":\"" + Directory + "\"," +
319        "\"command\":\"" + Command + "\","
320        "\"file\":\"" + FileName + "\"}]").str(),
321     ErrorMessage);
322   ASSERT_EQ(2u, FoundCommand.CommandLine.size());
323   EXPECT_EQ("//net/path to compiler",
324             FoundCommand.CommandLine[0]) << ErrorMessage;
325   EXPECT_EQ("and an argument", FoundCommand.CommandLine[1]) << ErrorMessage;
326 }
327
328 TEST(findCompileArgsInJsonDatabase, ReadsDirectoryWithSpaces) {
329   StringRef Directory("//net/some directory / with spaces");
330   StringRef FileName("//net/path/to/a-file.cpp");
331   StringRef Command("a command");
332   std::string ErrorMessage;
333   CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
334     FileName,
335     ("[{\"directory\":\"" + Directory + "\"," +
336        "\"command\":\"" + Command + "\","
337        "\"file\":\"" + FileName + "\"}]").str(),
338     ErrorMessage);
339   EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
340 }
341
342 TEST(findCompileArgsInJsonDatabase, FindsEntry) {
343   StringRef Directory("//net/directory");
344   StringRef FileName("file");
345   StringRef Command("command");
346   std::string JsonDatabase = "[";
347   for (int I = 0; I < 10; ++I) {
348     if (I > 0) JsonDatabase += ",";
349     JsonDatabase +=
350       ("{\"directory\":\"" + Directory + Twine(I) + "\"," +
351         "\"command\":\"" + Command + Twine(I) + "\","
352         "\"file\":\"" + FileName + Twine(I) + "\"}").str();
353   }
354   JsonDatabase += "]";
355   std::string ErrorMessage;
356   CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
357     "//net/directory4/file4", JsonDatabase, ErrorMessage);
358   EXPECT_EQ("//net/directory4", FoundCommand.Directory) << ErrorMessage;
359   ASSERT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage;
360   EXPECT_EQ("command4", FoundCommand.CommandLine[0]) << ErrorMessage;
361 }
362
363 static std::vector<std::string> unescapeJsonCommandLine(StringRef Command) {
364   std::string JsonDatabase =
365     ("[{\"directory\":\"//net/root\", \"file\":\"test\", \"command\": \"" +
366      Command + "\"}]").str();
367   std::string ErrorMessage;
368   CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
369     "//net/root/test", JsonDatabase, ErrorMessage);
370   EXPECT_TRUE(ErrorMessage.empty()) << ErrorMessage;
371   return FoundCommand.CommandLine;
372 }
373
374 TEST(unescapeJsonCommandLine, ReturnsEmptyArrayOnEmptyString) {
375   std::vector<std::string> Result = unescapeJsonCommandLine("");
376   EXPECT_TRUE(Result.empty());
377 }
378
379 TEST(unescapeJsonCommandLine, SplitsOnSpaces) {
380   std::vector<std::string> Result = unescapeJsonCommandLine("a b c");
381   ASSERT_EQ(3ul, Result.size());
382   EXPECT_EQ("a", Result[0]);
383   EXPECT_EQ("b", Result[1]);
384   EXPECT_EQ("c", Result[2]);
385 }
386
387 TEST(unescapeJsonCommandLine, MungesMultipleSpaces) {
388   std::vector<std::string> Result = unescapeJsonCommandLine("   a   b   ");
389   ASSERT_EQ(2ul, Result.size());
390   EXPECT_EQ("a", Result[0]);
391   EXPECT_EQ("b", Result[1]);
392 }
393
394 TEST(unescapeJsonCommandLine, UnescapesBackslashCharacters) {
395   std::vector<std::string> Backslash = unescapeJsonCommandLine("a\\\\\\\\");
396   ASSERT_EQ(1ul, Backslash.size());
397   EXPECT_EQ("a\\", Backslash[0]);
398   std::vector<std::string> Quote = unescapeJsonCommandLine("a\\\\\\\"");
399   ASSERT_EQ(1ul, Quote.size());
400   EXPECT_EQ("a\"", Quote[0]);
401 }
402
403 TEST(unescapeJsonCommandLine, DoesNotMungeSpacesBetweenQuotes) {
404   std::vector<std::string> Result = unescapeJsonCommandLine("\\\"  a  b  \\\"");
405   ASSERT_EQ(1ul, Result.size());
406   EXPECT_EQ("  a  b  ", Result[0]);
407 }
408
409 TEST(unescapeJsonCommandLine, AllowsMultipleQuotedArguments) {
410   std::vector<std::string> Result = unescapeJsonCommandLine(
411       "  \\\" a \\\"  \\\" b \\\"  ");
412   ASSERT_EQ(2ul, Result.size());
413   EXPECT_EQ(" a ", Result[0]);
414   EXPECT_EQ(" b ", Result[1]);
415 }
416
417 TEST(unescapeJsonCommandLine, AllowsEmptyArgumentsInQuotes) {
418   std::vector<std::string> Result = unescapeJsonCommandLine(
419       "\\\"\\\"\\\"\\\"");
420   ASSERT_EQ(1ul, Result.size());
421   EXPECT_TRUE(Result[0].empty()) << Result[0];
422 }
423
424 TEST(unescapeJsonCommandLine, ParsesEscapedQuotesInQuotedStrings) {
425   std::vector<std::string> Result = unescapeJsonCommandLine(
426       "\\\"\\\\\\\"\\\"");
427   ASSERT_EQ(1ul, Result.size());
428   EXPECT_EQ("\"", Result[0]);
429 }
430
431 TEST(unescapeJsonCommandLine, ParsesMultipleArgumentsWithEscapedCharacters) {
432   std::vector<std::string> Result = unescapeJsonCommandLine(
433       "  \\\\\\\"  \\\"a \\\\\\\" b \\\"     \\\"and\\\\\\\\c\\\"   \\\\\\\"");
434   ASSERT_EQ(4ul, Result.size());
435   EXPECT_EQ("\"", Result[0]);
436   EXPECT_EQ("a \" b ", Result[1]);
437   EXPECT_EQ("and\\c", Result[2]);
438   EXPECT_EQ("\"", Result[3]);
439 }
440
441 TEST(unescapeJsonCommandLine, ParsesStringsWithoutSpacesIntoSingleArgument) {
442   std::vector<std::string> QuotedNoSpaces = unescapeJsonCommandLine(
443       "\\\"a\\\"\\\"b\\\"");
444   ASSERT_EQ(1ul, QuotedNoSpaces.size());
445   EXPECT_EQ("ab", QuotedNoSpaces[0]);
446
447   std::vector<std::string> MixedNoSpaces = unescapeJsonCommandLine(
448       "\\\"a\\\"bcd\\\"ef\\\"\\\"\\\"\\\"g\\\"");
449   ASSERT_EQ(1ul, MixedNoSpaces.size());
450   EXPECT_EQ("abcdefg", MixedNoSpaces[0]);
451 }
452
453 TEST(unescapeJsonCommandLine, ParsesQuotedStringWithoutClosingQuote) {
454   std::vector<std::string> Unclosed = unescapeJsonCommandLine("\\\"abc");
455   ASSERT_EQ(1ul, Unclosed.size());
456   EXPECT_EQ("abc", Unclosed[0]);
457
458   std::vector<std::string> Empty = unescapeJsonCommandLine("\\\"");
459   ASSERT_EQ(1ul, Empty.size());
460   EXPECT_EQ("", Empty[0]);
461 }
462
463 TEST(unescapeJsonCommandLine, ParsesSingleQuotedString) {
464   std::vector<std::string> Args = unescapeJsonCommandLine("a'\\\\b \\\"c\\\"'");
465   ASSERT_EQ(1ul, Args.size());
466   EXPECT_EQ("a\\b \"c\"", Args[0]);
467 }
468
469 TEST(FixedCompilationDatabase, ReturnsFixedCommandLine) {
470   std::vector<std::string> CommandLine;
471   CommandLine.push_back("one");
472   CommandLine.push_back("two");
473   FixedCompilationDatabase Database(".", CommandLine);
474   StringRef FileName("source");
475   std::vector<CompileCommand> Result =
476     Database.getCompileCommands(FileName);
477   ASSERT_EQ(1ul, Result.size());
478   std::vector<std::string> ExpectedCommandLine(1, "clang-tool");
479   ExpectedCommandLine.insert(ExpectedCommandLine.end(),
480                              CommandLine.begin(), CommandLine.end());
481   ExpectedCommandLine.push_back("source");
482   EXPECT_EQ(".", Result[0].Directory);
483   EXPECT_EQ(FileName, Result[0].Filename);
484   EXPECT_EQ(ExpectedCommandLine, Result[0].CommandLine);
485 }
486
487 TEST(FixedCompilationDatabase, GetAllFiles) {
488   std::vector<std::string> CommandLine;
489   CommandLine.push_back("one");
490   CommandLine.push_back("two");
491   FixedCompilationDatabase Database(".", CommandLine);
492
493   EXPECT_EQ(0ul, Database.getAllFiles().size());
494 }
495
496 TEST(FixedCompilationDatabase, GetAllCompileCommands) {
497   std::vector<std::string> CommandLine;
498   CommandLine.push_back("one");
499   CommandLine.push_back("two");
500   FixedCompilationDatabase Database(".", CommandLine);
501
502   EXPECT_EQ(0ul, Database.getAllCompileCommands().size());
503 }
504
505 TEST(ParseFixedCompilationDatabase, ReturnsNullOnEmptyArgumentList) {
506   int Argc = 0;
507   std::unique_ptr<FixedCompilationDatabase> Database(
508       FixedCompilationDatabase::loadFromCommandLine(Argc, nullptr));
509   EXPECT_FALSE(Database);
510   EXPECT_EQ(0, Argc);
511 }
512
513 TEST(ParseFixedCompilationDatabase, ReturnsNullWithoutDoubleDash) {
514   int Argc = 2;
515   const char *Argv[] = { "1", "2" };
516   std::unique_ptr<FixedCompilationDatabase> Database(
517       FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
518   EXPECT_FALSE(Database);
519   EXPECT_EQ(2, Argc);
520 }
521
522 TEST(ParseFixedCompilationDatabase, ReturnsArgumentsAfterDoubleDash) {
523   int Argc = 5;
524   const char *Argv[] = {
525     "1", "2", "--\0no-constant-folding", "-DDEF3", "-DDEF4"
526   };
527   std::unique_ptr<FixedCompilationDatabase> Database(
528       FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
529   ASSERT_TRUE((bool)Database);
530   std::vector<CompileCommand> Result =
531     Database->getCompileCommands("source");
532   ASSERT_EQ(1ul, Result.size());
533   ASSERT_EQ(".", Result[0].Directory);
534   std::vector<std::string> CommandLine;
535   CommandLine.push_back("clang-tool");
536   CommandLine.push_back("-DDEF3");
537   CommandLine.push_back("-DDEF4");
538   CommandLine.push_back("source");
539   ASSERT_EQ(CommandLine, Result[0].CommandLine);
540   EXPECT_EQ(2, Argc);
541 }
542
543 TEST(ParseFixedCompilationDatabase, ReturnsEmptyCommandLine) {
544   int Argc = 3;
545   const char *Argv[] = { "1", "2", "--\0no-constant-folding" };
546   std::unique_ptr<FixedCompilationDatabase> Database(
547       FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
548   ASSERT_TRUE((bool)Database);
549   std::vector<CompileCommand> Result =
550     Database->getCompileCommands("source");
551   ASSERT_EQ(1ul, Result.size());
552   ASSERT_EQ(".", Result[0].Directory);
553   std::vector<std::string> CommandLine;
554   CommandLine.push_back("clang-tool");
555   CommandLine.push_back("source");
556   ASSERT_EQ(CommandLine, Result[0].CommandLine);
557   EXPECT_EQ(2, Argc);
558 }
559
560 TEST(ParseFixedCompilationDatabase, HandlesPositionalArgs) {
561   const char *Argv[] = {"1", "2", "--", "-c", "somefile.cpp", "-DDEF3"};
562   int Argc = sizeof(Argv) / sizeof(char*);
563   std::unique_ptr<FixedCompilationDatabase> Database(
564       FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
565   ASSERT_TRUE((bool)Database);
566   std::vector<CompileCommand> Result =
567     Database->getCompileCommands("source");
568   ASSERT_EQ(1ul, Result.size());
569   ASSERT_EQ(".", Result[0].Directory);
570   std::vector<std::string> Expected;
571   Expected.push_back("clang-tool");
572   Expected.push_back("-c");
573   Expected.push_back("-DDEF3");
574   Expected.push_back("source");
575   ASSERT_EQ(Expected, Result[0].CommandLine);
576   EXPECT_EQ(2, Argc);
577 }
578
579 TEST(ParseFixedCompilationDatabase, HandlesArgv0) {
580   const char *Argv[] = {"1", "2", "--", "mytool", "somefile.cpp"};
581   int Argc = sizeof(Argv) / sizeof(char*);
582   std::unique_ptr<FixedCompilationDatabase> Database(
583       FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
584   ASSERT_TRUE((bool)Database);
585   std::vector<CompileCommand> Result =
586     Database->getCompileCommands("source");
587   ASSERT_EQ(1ul, Result.size());
588   ASSERT_EQ(".", Result[0].Directory);
589   std::vector<std::string> Expected;
590   Expected.push_back("clang-tool");
591   Expected.push_back("source");
592   ASSERT_EQ(Expected, Result[0].CommandLine);
593   EXPECT_EQ(2, Argc);
594 }
595
596 } // end namespace tooling
597 } // end namespace clang