1 //===- unittest/Tooling/CompilationDatabaseTest.cpp -----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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/CompilationDatabase.h"
15 #include "clang/Tooling/Tooling.h"
16 #include "gtest/gtest.h"
21 static CompileCommand findCompileArgsInJsonDatabase(StringRef FileName,
22 StringRef JSONDatabase,
23 std::string &ErrorMessage) {
24 llvm::OwningPtr<CompilationDatabase> Database(
25 JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage));
27 return CompileCommand();
28 std::vector<CompileCommand> Commands = Database->getCompileCommands(FileName);
29 EXPECT_LE(Commands.size(), 1u);
31 return CompileCommand();
35 TEST(findCompileArgsInJsonDatabase, FindsNothingIfEmpty) {
36 std::string ErrorMessage;
37 CompileCommand NotFound = findCompileArgsInJsonDatabase(
38 "a-file.cpp", "", ErrorMessage);
39 EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
40 EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
43 TEST(findCompileArgsInJsonDatabase, ReadsSingleEntry) {
44 StringRef Directory("/some/directory");
45 StringRef FileName("/path/to/a-file.cpp");
46 StringRef Command("/path/to/compiler and some arguments");
47 std::string ErrorMessage;
48 CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
50 ("[{\"directory\":\"" + Directory + "\"," +
51 "\"command\":\"" + Command + "\","
52 "\"file\":\"" + FileName + "\"}]").str(),
54 EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
55 ASSERT_EQ(4u, FoundCommand.CommandLine.size()) << ErrorMessage;
56 EXPECT_EQ("/path/to/compiler", FoundCommand.CommandLine[0]) << ErrorMessage;
57 EXPECT_EQ("and", FoundCommand.CommandLine[1]) << ErrorMessage;
58 EXPECT_EQ("some", FoundCommand.CommandLine[2]) << ErrorMessage;
59 EXPECT_EQ("arguments", FoundCommand.CommandLine[3]) << ErrorMessage;
61 CompileCommand NotFound = findCompileArgsInJsonDatabase(
63 ("[{\"directory\":\"" + Directory + "\"," +
64 "\"command\":\"" + Command + "\","
65 "\"file\":\"" + FileName + "\"}]").str(),
67 EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
68 EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
71 TEST(findCompileArgsInJsonDatabase, ReadsCompileCommandLinesWithSpaces) {
72 StringRef Directory("/some/directory");
73 StringRef FileName("/path/to/a-file.cpp");
74 StringRef Command("\\\"/path to compiler\\\" \\\"and an argument\\\"");
75 std::string ErrorMessage;
76 CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
78 ("[{\"directory\":\"" + Directory + "\"," +
79 "\"command\":\"" + Command + "\","
80 "\"file\":\"" + FileName + "\"}]").str(),
82 ASSERT_EQ(2u, FoundCommand.CommandLine.size());
83 EXPECT_EQ("/path to compiler", FoundCommand.CommandLine[0]) << ErrorMessage;
84 EXPECT_EQ("and an argument", FoundCommand.CommandLine[1]) << ErrorMessage;
87 TEST(findCompileArgsInJsonDatabase, ReadsDirectoryWithSpaces) {
88 StringRef Directory("/some directory / with spaces");
89 StringRef FileName("/path/to/a-file.cpp");
90 StringRef Command("a command");
91 std::string ErrorMessage;
92 CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
94 ("[{\"directory\":\"" + Directory + "\"," +
95 "\"command\":\"" + Command + "\","
96 "\"file\":\"" + FileName + "\"}]").str(),
98 EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
101 TEST(findCompileArgsInJsonDatabase, FindsEntry) {
102 StringRef Directory("directory");
103 StringRef FileName("file");
104 StringRef Command("command");
105 std::string JsonDatabase = "[";
106 for (int I = 0; I < 10; ++I) {
107 if (I > 0) JsonDatabase += ",";
109 ("{\"directory\":\"" + Directory + Twine(I) + "\"," +
110 "\"command\":\"" + Command + Twine(I) + "\","
111 "\"file\":\"" + FileName + Twine(I) + "\"}").str();
114 std::string ErrorMessage;
115 CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
116 "file4", JsonDatabase, ErrorMessage);
117 EXPECT_EQ("directory4", FoundCommand.Directory) << ErrorMessage;
118 ASSERT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage;
119 EXPECT_EQ("command4", FoundCommand.CommandLine[0]) << ErrorMessage;
122 static std::vector<std::string> unescapeJsonCommandLine(StringRef Command) {
123 std::string JsonDatabase =
124 ("[{\"directory\":\"\", \"file\":\"test\", \"command\": \"" +
125 Command + "\"}]").str();
126 std::string ErrorMessage;
127 CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
128 "test", JsonDatabase, ErrorMessage);
129 EXPECT_TRUE(ErrorMessage.empty()) << ErrorMessage;
130 return FoundCommand.CommandLine;
133 TEST(unescapeJsonCommandLine, ReturnsEmptyArrayOnEmptyString) {
134 std::vector<std::string> Result = unescapeJsonCommandLine("");
135 EXPECT_TRUE(Result.empty());
138 TEST(unescapeJsonCommandLine, SplitsOnSpaces) {
139 std::vector<std::string> Result = unescapeJsonCommandLine("a b c");
140 ASSERT_EQ(3ul, Result.size());
141 EXPECT_EQ("a", Result[0]);
142 EXPECT_EQ("b", Result[1]);
143 EXPECT_EQ("c", Result[2]);
146 TEST(unescapeJsonCommandLine, MungesMultipleSpaces) {
147 std::vector<std::string> Result = unescapeJsonCommandLine(" a b ");
148 ASSERT_EQ(2ul, Result.size());
149 EXPECT_EQ("a", Result[0]);
150 EXPECT_EQ("b", Result[1]);
153 TEST(unescapeJsonCommandLine, UnescapesBackslashCharacters) {
154 std::vector<std::string> Backslash = unescapeJsonCommandLine("a\\\\\\\\");
155 ASSERT_EQ(1ul, Backslash.size());
156 EXPECT_EQ("a\\", Backslash[0]);
157 std::vector<std::string> Quote = unescapeJsonCommandLine("a\\\\\\\"");
158 ASSERT_EQ(1ul, Quote.size());
159 EXPECT_EQ("a\"", Quote[0]);
162 TEST(unescapeJsonCommandLine, DoesNotMungeSpacesBetweenQuotes) {
163 std::vector<std::string> Result = unescapeJsonCommandLine("\\\" a b \\\"");
164 ASSERT_EQ(1ul, Result.size());
165 EXPECT_EQ(" a b ", Result[0]);
168 TEST(unescapeJsonCommandLine, AllowsMultipleQuotedArguments) {
169 std::vector<std::string> Result = unescapeJsonCommandLine(
170 " \\\" a \\\" \\\" b \\\" ");
171 ASSERT_EQ(2ul, Result.size());
172 EXPECT_EQ(" a ", Result[0]);
173 EXPECT_EQ(" b ", Result[1]);
176 TEST(unescapeJsonCommandLine, AllowsEmptyArgumentsInQuotes) {
177 std::vector<std::string> Result = unescapeJsonCommandLine(
179 ASSERT_EQ(1ul, Result.size());
180 EXPECT_TRUE(Result[0].empty()) << Result[0];
183 TEST(unescapeJsonCommandLine, ParsesEscapedQuotesInQuotedStrings) {
184 std::vector<std::string> Result = unescapeJsonCommandLine(
186 ASSERT_EQ(1ul, Result.size());
187 EXPECT_EQ("\"", Result[0]);
190 TEST(unescapeJsonCommandLine, ParsesMultipleArgumentsWithEscapedCharacters) {
191 std::vector<std::string> Result = unescapeJsonCommandLine(
192 " \\\\\\\" \\\"a \\\\\\\" b \\\" \\\"and\\\\\\\\c\\\" \\\\\\\"");
193 ASSERT_EQ(4ul, Result.size());
194 EXPECT_EQ("\"", Result[0]);
195 EXPECT_EQ("a \" b ", Result[1]);
196 EXPECT_EQ("and\\c", Result[2]);
197 EXPECT_EQ("\"", Result[3]);
200 TEST(unescapeJsonCommandLine, ParsesStringsWithoutSpacesIntoSingleArgument) {
201 std::vector<std::string> QuotedNoSpaces = unescapeJsonCommandLine(
202 "\\\"a\\\"\\\"b\\\"");
203 ASSERT_EQ(1ul, QuotedNoSpaces.size());
204 EXPECT_EQ("ab", QuotedNoSpaces[0]);
206 std::vector<std::string> MixedNoSpaces = unescapeJsonCommandLine(
207 "\\\"a\\\"bcd\\\"ef\\\"\\\"\\\"\\\"g\\\"");
208 ASSERT_EQ(1ul, MixedNoSpaces.size());
209 EXPECT_EQ("abcdefg", MixedNoSpaces[0]);
212 TEST(unescapeJsonCommandLine, ParsesQuotedStringWithoutClosingQuote) {
213 std::vector<std::string> Unclosed = unescapeJsonCommandLine("\\\"abc");
214 ASSERT_EQ(1ul, Unclosed.size());
215 EXPECT_EQ("abc", Unclosed[0]);
217 std::vector<std::string> Empty = unescapeJsonCommandLine("\\\"");
218 ASSERT_EQ(1ul, Empty.size());
219 EXPECT_EQ("", Empty[0]);
222 } // end namespace tooling
223 } // end namespace clang