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 123 static CompileCommand findCompileArgsInJsonDatabase(StringRef FileName, 124 StringRef JSONDatabase, 125 std::string &ErrorMessage) { 126 std::unique_ptr<CompilationDatabase> Database( 127 JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage)); 128 if (!Database) 129 return CompileCommand(); 130 std::vector<CompileCommand> Commands = Database->getCompileCommands(FileName); 131 EXPECT_LE(Commands.size(), 1u); 132 if (Commands.empty()) 133 return CompileCommand(); 134 return Commands[0]; 135 } 136 137 TEST(JSONCompilationDatabase, ArgumentsPreferredOverCommand) { 138 StringRef Directory("//net/dir"); 139 StringRef FileName("//net/dir/filename"); 140 StringRef Command("command"); 141 StringRef Arguments = "arguments"; 142 Twine ArgumentsAccumulate; 143 std::string ErrorMessage; 144 CompileCommand FoundCommand = findCompileArgsInJsonDatabase( 145 FileName, 146 ("[{\"directory\":\"" + Directory + "\"," 147 "\"arguments\":[\"" + Arguments + "\"]," 148 "\"command\":\"" + Command + "\"," 149 "\"file\":\"" + FileName + "\"}]").str(), 150 ErrorMessage); 151 EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage; 152 EXPECT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage; 153 EXPECT_EQ(Arguments, FoundCommand.CommandLine[0]) << ErrorMessage; 154 } 155 156 struct FakeComparator : public PathComparator { 157 ~FakeComparator() override {} 158 bool equivalent(StringRef FileA, StringRef FileB) const override { 159 return FileA.equals_lower(FileB); 160 } 161 }; 162 163 class FileMatchTrieTest : public ::testing::Test { 164 protected: 165 FileMatchTrieTest() : Trie(new FakeComparator()) {} 166 167 StringRef find(StringRef Path) { 168 llvm::raw_string_ostream ES(Error); 169 return Trie.findEquivalent(Path, ES); 170 } 171 172 FileMatchTrie Trie; 173 std::string Error; 174 }; 175 176 TEST_F(FileMatchTrieTest, InsertingRelativePath) { 177 Trie.insert("//net/path/file.cc"); 178 Trie.insert("file.cc"); 179 EXPECT_EQ("//net/path/file.cc", find("//net/path/file.cc")); 180 } 181 182 TEST_F(FileMatchTrieTest, MatchingRelativePath) { 183 EXPECT_EQ("", find("file.cc")); 184 } 185 186 TEST_F(FileMatchTrieTest, ReturnsBestResults) { 187 Trie.insert("//net/d/c/b.cc"); 188 Trie.insert("//net/d/b/b.cc"); 189 EXPECT_EQ("//net/d/b/b.cc", find("//net/d/b/b.cc")); 190 } 191 192 TEST_F(FileMatchTrieTest, HandlesSymlinks) { 193 Trie.insert("//net/AA/file.cc"); 194 EXPECT_EQ("//net/AA/file.cc", find("//net/aa/file.cc")); 195 } 196 197 TEST_F(FileMatchTrieTest, ReportsSymlinkAmbiguity) { 198 Trie.insert("//net/Aa/file.cc"); 199 Trie.insert("//net/aA/file.cc"); 200 EXPECT_TRUE(find("//net/aa/file.cc").empty()); 201 EXPECT_EQ("Path is ambiguous", Error); 202 } 203 204 TEST_F(FileMatchTrieTest, LongerMatchingSuffixPreferred) { 205 Trie.insert("//net/src/Aa/file.cc"); 206 Trie.insert("//net/src/aA/file.cc"); 207 Trie.insert("//net/SRC/aa/file.cc"); 208 EXPECT_EQ("//net/SRC/aa/file.cc", find("//net/src/aa/file.cc")); 209 } 210 211 TEST_F(FileMatchTrieTest, EmptyTrie) { 212 EXPECT_TRUE(find("//net/some/path").empty()); 213 } 214 215 TEST_F(FileMatchTrieTest, NoResult) { 216 Trie.insert("//net/somepath/otherfile.cc"); 217 Trie.insert("//net/otherpath/somefile.cc"); 218 EXPECT_EQ("", find("//net/somepath/somefile.cc")); 219 } 220 221 TEST_F(FileMatchTrieTest, RootElementDifferent) { 222 Trie.insert("//net/path/file.cc"); 223 Trie.insert("//net/otherpath/file.cc"); 224 EXPECT_EQ("//net/path/file.cc", find("//net/path/file.cc")); 225 } 226 227 TEST_F(FileMatchTrieTest, CannotResolveRelativePath) { 228 EXPECT_EQ("", find("relative-path.cc")); 229 EXPECT_EQ("Cannot resolve relative paths", Error); 230 } 231 232 TEST(findCompileArgsInJsonDatabase, FindsNothingIfEmpty) { 233 std::string ErrorMessage; 234 CompileCommand NotFound = findCompileArgsInJsonDatabase( 235 "a-file.cpp", "", ErrorMessage); 236 EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage; 237 EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage; 238 } 239 240 TEST(findCompileArgsInJsonDatabase, ReadsSingleEntry) { 241 StringRef Directory("//net/some/directory"); 242 StringRef FileName("//net/path/to/a-file.cpp"); 243 StringRef Command("//net/path/to/compiler and some arguments"); 244 std::string ErrorMessage; 245 CompileCommand FoundCommand = findCompileArgsInJsonDatabase( 246 FileName, 247 ("[{\"directory\":\"" + Directory + "\"," + 248 "\"command\":\"" + Command + "\"," 249 "\"file\":\"" + FileName + "\"}]").str(), 250 ErrorMessage); 251 EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage; 252 ASSERT_EQ(4u, FoundCommand.CommandLine.size()) << ErrorMessage; 253 EXPECT_EQ("//net/path/to/compiler", 254 FoundCommand.CommandLine[0]) << ErrorMessage; 255 EXPECT_EQ("and", FoundCommand.CommandLine[1]) << ErrorMessage; 256 EXPECT_EQ("some", FoundCommand.CommandLine[2]) << ErrorMessage; 257 EXPECT_EQ("arguments", FoundCommand.CommandLine[3]) << ErrorMessage; 258 259 CompileCommand NotFound = findCompileArgsInJsonDatabase( 260 "a-file.cpp", 261 ("[{\"directory\":\"" + Directory + "\"," + 262 "\"command\":\"" + Command + "\"," 263 "\"file\":\"" + FileName + "\"}]").str(), 264 ErrorMessage); 265 EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage; 266 EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage; 267 } 268 269 TEST(findCompileArgsInJsonDatabase, ReadsCompileCommandLinesWithSpaces) { 270 StringRef Directory("//net/some/directory"); 271 StringRef FileName("//net/path/to/a-file.cpp"); 272 StringRef Command("\\\"//net/path to compiler\\\" \\\"and an argument\\\""); 273 std::string ErrorMessage; 274 CompileCommand FoundCommand = findCompileArgsInJsonDatabase( 275 FileName, 276 ("[{\"directory\":\"" + Directory + "\"," + 277 "\"command\":\"" + Command + "\"," 278 "\"file\":\"" + FileName + "\"}]").str(), 279 ErrorMessage); 280 ASSERT_EQ(2u, FoundCommand.CommandLine.size()); 281 EXPECT_EQ("//net/path to compiler", 282 FoundCommand.CommandLine[0]) << ErrorMessage; 283 EXPECT_EQ("and an argument", FoundCommand.CommandLine[1]) << ErrorMessage; 284 } 285 286 TEST(findCompileArgsInJsonDatabase, ReadsDirectoryWithSpaces) { 287 StringRef Directory("//net/some directory / with spaces"); 288 StringRef FileName("//net/path/to/a-file.cpp"); 289 StringRef Command("a command"); 290 std::string ErrorMessage; 291 CompileCommand FoundCommand = findCompileArgsInJsonDatabase( 292 FileName, 293 ("[{\"directory\":\"" + Directory + "\"," + 294 "\"command\":\"" + Command + "\"," 295 "\"file\":\"" + FileName + "\"}]").str(), 296 ErrorMessage); 297 EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage; 298 } 299 300 TEST(findCompileArgsInJsonDatabase, FindsEntry) { 301 StringRef Directory("//net/directory"); 302 StringRef FileName("file"); 303 StringRef Command("command"); 304 std::string JsonDatabase = "["; 305 for (int I = 0; I < 10; ++I) { 306 if (I > 0) JsonDatabase += ","; 307 JsonDatabase += 308 ("{\"directory\":\"" + Directory + Twine(I) + "\"," + 309 "\"command\":\"" + Command + Twine(I) + "\"," 310 "\"file\":\"" + FileName + Twine(I) + "\"}").str(); 311 } 312 JsonDatabase += "]"; 313 std::string ErrorMessage; 314 CompileCommand FoundCommand = findCompileArgsInJsonDatabase( 315 "//net/directory4/file4", JsonDatabase, ErrorMessage); 316 EXPECT_EQ("//net/directory4", FoundCommand.Directory) << ErrorMessage; 317 ASSERT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage; 318 EXPECT_EQ("command4", FoundCommand.CommandLine[0]) << ErrorMessage; 319 } 320 321 static std::vector<std::string> unescapeJsonCommandLine(StringRef Command) { 322 std::string JsonDatabase = 323 ("[{\"directory\":\"//net/root\", \"file\":\"test\", \"command\": \"" + 324 Command + "\"}]").str(); 325 std::string ErrorMessage; 326 CompileCommand FoundCommand = findCompileArgsInJsonDatabase( 327 "//net/root/test", JsonDatabase, ErrorMessage); 328 EXPECT_TRUE(ErrorMessage.empty()) << ErrorMessage; 329 return FoundCommand.CommandLine; 330 } 331 332 TEST(unescapeJsonCommandLine, ReturnsEmptyArrayOnEmptyString) { 333 std::vector<std::string> Result = unescapeJsonCommandLine(""); 334 EXPECT_TRUE(Result.empty()); 335 } 336 337 TEST(unescapeJsonCommandLine, SplitsOnSpaces) { 338 std::vector<std::string> Result = unescapeJsonCommandLine("a b c"); 339 ASSERT_EQ(3ul, Result.size()); 340 EXPECT_EQ("a", Result[0]); 341 EXPECT_EQ("b", Result[1]); 342 EXPECT_EQ("c", Result[2]); 343 } 344 345 TEST(unescapeJsonCommandLine, MungesMultipleSpaces) { 346 std::vector<std::string> Result = unescapeJsonCommandLine(" a b "); 347 ASSERT_EQ(2ul, Result.size()); 348 EXPECT_EQ("a", Result[0]); 349 EXPECT_EQ("b", Result[1]); 350 } 351 352 TEST(unescapeJsonCommandLine, UnescapesBackslashCharacters) { 353 std::vector<std::string> Backslash = unescapeJsonCommandLine("a\\\\\\\\"); 354 ASSERT_EQ(1ul, Backslash.size()); 355 EXPECT_EQ("a\\", Backslash[0]); 356 std::vector<std::string> Quote = unescapeJsonCommandLine("a\\\\\\\""); 357 ASSERT_EQ(1ul, Quote.size()); 358 EXPECT_EQ("a\"", Quote[0]); 359 } 360 361 TEST(unescapeJsonCommandLine, DoesNotMungeSpacesBetweenQuotes) { 362 std::vector<std::string> Result = unescapeJsonCommandLine("\\\" a b \\\""); 363 ASSERT_EQ(1ul, Result.size()); 364 EXPECT_EQ(" a b ", Result[0]); 365 } 366 367 TEST(unescapeJsonCommandLine, AllowsMultipleQuotedArguments) { 368 std::vector<std::string> Result = unescapeJsonCommandLine( 369 " \\\" a \\\" \\\" b \\\" "); 370 ASSERT_EQ(2ul, Result.size()); 371 EXPECT_EQ(" a ", Result[0]); 372 EXPECT_EQ(" b ", Result[1]); 373 } 374 375 TEST(unescapeJsonCommandLine, AllowsEmptyArgumentsInQuotes) { 376 std::vector<std::string> Result = unescapeJsonCommandLine( 377 "\\\"\\\"\\\"\\\""); 378 ASSERT_EQ(1ul, Result.size()); 379 EXPECT_TRUE(Result[0].empty()) << Result[0]; 380 } 381 382 TEST(unescapeJsonCommandLine, ParsesEscapedQuotesInQuotedStrings) { 383 std::vector<std::string> Result = unescapeJsonCommandLine( 384 "\\\"\\\\\\\"\\\""); 385 ASSERT_EQ(1ul, Result.size()); 386 EXPECT_EQ("\"", Result[0]); 387 } 388 389 TEST(unescapeJsonCommandLine, ParsesMultipleArgumentsWithEscapedCharacters) { 390 std::vector<std::string> Result = unescapeJsonCommandLine( 391 " \\\\\\\" \\\"a \\\\\\\" b \\\" \\\"and\\\\\\\\c\\\" \\\\\\\""); 392 ASSERT_EQ(4ul, Result.size()); 393 EXPECT_EQ("\"", Result[0]); 394 EXPECT_EQ("a \" b ", Result[1]); 395 EXPECT_EQ("and\\c", Result[2]); 396 EXPECT_EQ("\"", Result[3]); 397 } 398 399 TEST(unescapeJsonCommandLine, ParsesStringsWithoutSpacesIntoSingleArgument) { 400 std::vector<std::string> QuotedNoSpaces = unescapeJsonCommandLine( 401 "\\\"a\\\"\\\"b\\\""); 402 ASSERT_EQ(1ul, QuotedNoSpaces.size()); 403 EXPECT_EQ("ab", QuotedNoSpaces[0]); 404 405 std::vector<std::string> MixedNoSpaces = unescapeJsonCommandLine( 406 "\\\"a\\\"bcd\\\"ef\\\"\\\"\\\"\\\"g\\\""); 407 ASSERT_EQ(1ul, MixedNoSpaces.size()); 408 EXPECT_EQ("abcdefg", MixedNoSpaces[0]); 409 } 410 411 TEST(unescapeJsonCommandLine, ParsesQuotedStringWithoutClosingQuote) { 412 std::vector<std::string> Unclosed = unescapeJsonCommandLine("\\\"abc"); 413 ASSERT_EQ(1ul, Unclosed.size()); 414 EXPECT_EQ("abc", Unclosed[0]); 415 416 std::vector<std::string> Empty = unescapeJsonCommandLine("\\\""); 417 ASSERT_EQ(1ul, Empty.size()); 418 EXPECT_EQ("", Empty[0]); 419 } 420 421 TEST(unescapeJsonCommandLine, ParsesSingleQuotedString) { 422 std::vector<std::string> Args = unescapeJsonCommandLine("a'\\\\b \\\"c\\\"'"); 423 ASSERT_EQ(1ul, Args.size()); 424 EXPECT_EQ("a\\b \"c\"", Args[0]); 425 } 426 427 TEST(FixedCompilationDatabase, ReturnsFixedCommandLine) { 428 std::vector<std::string> CommandLine; 429 CommandLine.push_back("one"); 430 CommandLine.push_back("two"); 431 FixedCompilationDatabase Database(".", CommandLine); 432 StringRef FileName("source"); 433 std::vector<CompileCommand> Result = 434 Database.getCompileCommands(FileName); 435 ASSERT_EQ(1ul, Result.size()); 436 std::vector<std::string> ExpectedCommandLine(1, "clang-tool"); 437 ExpectedCommandLine.insert(ExpectedCommandLine.end(), 438 CommandLine.begin(), CommandLine.end()); 439 ExpectedCommandLine.push_back("source"); 440 EXPECT_EQ(".", Result[0].Directory); 441 EXPECT_EQ(FileName, Result[0].Filename); 442 EXPECT_EQ(ExpectedCommandLine, Result[0].CommandLine); 443 } 444 445 TEST(FixedCompilationDatabase, GetAllFiles) { 446 std::vector<std::string> CommandLine; 447 CommandLine.push_back("one"); 448 CommandLine.push_back("two"); 449 FixedCompilationDatabase Database(".", CommandLine); 450 451 EXPECT_EQ(0ul, Database.getAllFiles().size()); 452 } 453 454 TEST(FixedCompilationDatabase, GetAllCompileCommands) { 455 std::vector<std::string> CommandLine; 456 CommandLine.push_back("one"); 457 CommandLine.push_back("two"); 458 FixedCompilationDatabase Database(".", CommandLine); 459 460 EXPECT_EQ(0ul, Database.getAllCompileCommands().size()); 461 } 462 463 TEST(ParseFixedCompilationDatabase, ReturnsNullOnEmptyArgumentList) { 464 int Argc = 0; 465 std::unique_ptr<FixedCompilationDatabase> Database( 466 FixedCompilationDatabase::loadFromCommandLine(Argc, nullptr)); 467 EXPECT_FALSE(Database); 468 EXPECT_EQ(0, Argc); 469 } 470 471 TEST(ParseFixedCompilationDatabase, ReturnsNullWithoutDoubleDash) { 472 int Argc = 2; 473 const char *Argv[] = { "1", "2" }; 474 std::unique_ptr<FixedCompilationDatabase> Database( 475 FixedCompilationDatabase::loadFromCommandLine(Argc, Argv)); 476 EXPECT_FALSE(Database); 477 EXPECT_EQ(2, Argc); 478 } 479 480 TEST(ParseFixedCompilationDatabase, ReturnsArgumentsAfterDoubleDash) { 481 int Argc = 5; 482 const char *Argv[] = { 483 "1", "2", "--\0no-constant-folding", "-DDEF3", "-DDEF4" 484 }; 485 std::unique_ptr<FixedCompilationDatabase> Database( 486 FixedCompilationDatabase::loadFromCommandLine(Argc, Argv)); 487 ASSERT_TRUE((bool)Database); 488 std::vector<CompileCommand> Result = 489 Database->getCompileCommands("source"); 490 ASSERT_EQ(1ul, Result.size()); 491 ASSERT_EQ(".", Result[0].Directory); 492 std::vector<std::string> CommandLine; 493 CommandLine.push_back("clang-tool"); 494 CommandLine.push_back("-DDEF3"); 495 CommandLine.push_back("-DDEF4"); 496 CommandLine.push_back("source"); 497 ASSERT_EQ(CommandLine, Result[0].CommandLine); 498 EXPECT_EQ(2, Argc); 499 } 500 501 TEST(ParseFixedCompilationDatabase, ReturnsEmptyCommandLine) { 502 int Argc = 3; 503 const char *Argv[] = { "1", "2", "--\0no-constant-folding" }; 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("source"); 514 ASSERT_EQ(CommandLine, Result[0].CommandLine); 515 EXPECT_EQ(2, Argc); 516 } 517 518 TEST(ParseFixedCompilationDatabase, HandlesPositionalArgs) { 519 const char *Argv[] = {"1", "2", "--", "-c", "somefile.cpp", "-DDEF3"}; 520 int Argc = sizeof(Argv) / sizeof(char*); 521 std::unique_ptr<FixedCompilationDatabase> Database( 522 FixedCompilationDatabase::loadFromCommandLine(Argc, Argv)); 523 ASSERT_TRUE((bool)Database); 524 std::vector<CompileCommand> Result = 525 Database->getCompileCommands("source"); 526 ASSERT_EQ(1ul, Result.size()); 527 ASSERT_EQ(".", Result[0].Directory); 528 std::vector<std::string> Expected; 529 Expected.push_back("clang-tool"); 530 Expected.push_back("-c"); 531 Expected.push_back("-DDEF3"); 532 Expected.push_back("source"); 533 ASSERT_EQ(Expected, Result[0].CommandLine); 534 EXPECT_EQ(2, Argc); 535 } 536 537 TEST(ParseFixedCompilationDatabase, HandlesArgv0) { 538 const char *Argv[] = {"1", "2", "--", "mytool", "somefile.cpp"}; 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("source"); 550 ASSERT_EQ(Expected, Result[0].CommandLine); 551 EXPECT_EQ(2, Argc); 552 } 553 554 } // end namespace tooling 555 } // end namespace clang 556