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