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