CompilationDatabaseTest.cpp 19 KB

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