summaryrefslogtreecommitdiffstats
path: root/unittests
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2011-04-27 16:39:14 +0000
committerManuel Klimek <klimek@google.com>2011-04-27 16:39:14 +0000
commit9a05fa97df4d5e64f740848a7759ecae5e1ed162 (patch)
tree70f5f56fcbe1bd6d3ff66ee1af96fa793fc01923 /unittests
parent4d8d803b06804defe25346871c7beb6096540c4a (diff)
This is the next step in building the standalone tools infrastructure:
This patch simplifies writing of standalone Clang tools. As an example, we add clang-check, a tool that runs a syntax only frontend action over a .cc file. When you integrate this into your favorite editor, you get much faster feedback on your compilation errors, thus reducing your feedback cycle especially when writing new code. The tool depends on integration of an outstanding patch to CMake to work which allows you to always have a current compile command database in your cmake output directory when you set CMAKE_EXPORT_COMPILE_COMMANDS. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130306 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests')
-rw-r--r--unittests/CMakeLists.txt5
-rw-r--r--unittests/Tooling/JsonCompileCommandLineDatabaseTest.cpp232
-rw-r--r--unittests/Tooling/ToolingTest.cpp84
3 files changed, 321 insertions, 0 deletions
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index dd6bad5fa9..f7f495ee9d 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -64,3 +64,8 @@ add_clang_unittest(Tooling
Tooling/ToolingTest.cpp
USED_LIBS gtest gtest_main clangTooling
)
+
+add_clang_unittest(JsonCompileCommandLineDatabase
+ Tooling/JsonCompileCommandLineDatabaseTest.cpp
+ USED_LIBS gtest gtest_main clangTooling
+ )
diff --git a/unittests/Tooling/JsonCompileCommandLineDatabaseTest.cpp b/unittests/Tooling/JsonCompileCommandLineDatabaseTest.cpp
new file mode 100644
index 0000000000..d875293e5d
--- /dev/null
+++ b/unittests/Tooling/JsonCompileCommandLineDatabaseTest.cpp
@@ -0,0 +1,232 @@
+//===- unittest/Tooling/JsonCompileCommandLineDatabaseTest ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../lib/Tooling/JsonCompileCommandLineDatabase.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tooling {
+
+TEST(UnescapeJsonCommandLine, ReturnsEmptyArrayOnEmptyString) {
+ std::vector<std::string> Result = UnescapeJsonCommandLine("");
+ EXPECT_TRUE(Result.empty());
+}
+
+TEST(UnescapeJsonCommandLine, SplitsOnSpaces) {
+ std::vector<std::string> Result = UnescapeJsonCommandLine("a b c");
+ ASSERT_EQ(3ul, Result.size());
+ EXPECT_EQ("a", Result[0]);
+ EXPECT_EQ("b", Result[1]);
+ EXPECT_EQ("c", Result[2]);
+}
+
+TEST(UnescapeJsonCommandLine, MungesMultipleSpaces) {
+ std::vector<std::string> Result = UnescapeJsonCommandLine(" a b ");
+ ASSERT_EQ(2ul, Result.size());
+ EXPECT_EQ("a", Result[0]);
+ EXPECT_EQ("b", Result[1]);
+}
+
+TEST(UnescapeJsonCommandLine, UnescapesBackslashCharacters) {
+ std::vector<std::string> Backslash = UnescapeJsonCommandLine("a\\\\\\\\");
+ ASSERT_EQ(1ul, Backslash.size());
+ EXPECT_EQ("a\\", Backslash[0]);
+ std::vector<std::string> Quote = UnescapeJsonCommandLine("a\\\\\\\"");
+ ASSERT_EQ(1ul, Quote.size());
+ EXPECT_EQ("a\"", Quote[0]);
+}
+
+TEST(UnescapeJsonCommandLine, DoesNotMungeSpacesBetweenQuotes) {
+ std::vector<std::string> Result = UnescapeJsonCommandLine("\\\" a b \\\"");
+ ASSERT_EQ(1ul, Result.size());
+ EXPECT_EQ(" a b ", Result[0]);
+}
+
+TEST(UnescapeJsonCommandLine, AllowsMultipleQuotedArguments) {
+ std::vector<std::string> Result = UnescapeJsonCommandLine(
+ " \\\" a \\\" \\\" b \\\" ");
+ ASSERT_EQ(2ul, Result.size());
+ EXPECT_EQ(" a ", Result[0]);
+ EXPECT_EQ(" b ", Result[1]);
+}
+
+TEST(UnescapeJsonCommandLine, AllowsEmptyArgumentsInQuotes) {
+ std::vector<std::string> Result = UnescapeJsonCommandLine(
+ "\\\"\\\"\\\"\\\"");
+ ASSERT_EQ(1ul, Result.size());
+ EXPECT_TRUE(Result[0].empty()) << Result[0];
+}
+
+TEST(UnescapeJsonCommandLine, ParsesEscapedQuotesInQuotedStrings) {
+ std::vector<std::string> Result = UnescapeJsonCommandLine(
+ "\\\"\\\\\\\"\\\"");
+ ASSERT_EQ(1ul, Result.size());
+ EXPECT_EQ("\"", Result[0]);
+}
+
+TEST(UnescapeJsonCommandLine, ParsesMultipleArgumentsWithEscapedCharacters) {
+ std::vector<std::string> Result = UnescapeJsonCommandLine(
+ " \\\\\\\" \\\"a \\\\\\\" b \\\" \\\"and\\\\\\\\c\\\" \\\\\\\"");
+ ASSERT_EQ(4ul, Result.size());
+ EXPECT_EQ("\"", Result[0]);
+ EXPECT_EQ("a \" b ", Result[1]);
+ EXPECT_EQ("and\\c", Result[2]);
+ EXPECT_EQ("\"", Result[3]);
+}
+
+TEST(UnescapeJsonCommandLine, ParsesStringsWithoutSpacesIntoSingleArgument) {
+ std::vector<std::string> QuotedNoSpaces = UnescapeJsonCommandLine(
+ "\\\"a\\\"\\\"b\\\"");
+ ASSERT_EQ(1ul, QuotedNoSpaces.size());
+ EXPECT_EQ("ab", QuotedNoSpaces[0]);
+
+ std::vector<std::string> MixedNoSpaces = UnescapeJsonCommandLine(
+ "\\\"a\\\"bcd\\\"ef\\\"\\\"\\\"\\\"g\\\"");
+ ASSERT_EQ(1ul, MixedNoSpaces.size());
+ EXPECT_EQ("abcdefg", MixedNoSpaces[0]);
+}
+
+TEST(JsonCompileCommandLineParser, FailsOnEmptyString) {
+ JsonCompileCommandLineParser Parser("", NULL);
+ EXPECT_FALSE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, DoesNotReadAfterInput) {
+ JsonCompileCommandLineParser Parser(llvm::StringRef(NULL, 0), NULL);
+ EXPECT_FALSE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, ParsesEmptyArray) {
+ JsonCompileCommandLineParser Parser("[]", NULL);
+ EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, FailsIfNotClosingArray) {
+ JsonCompileCommandLineParser JustOpening("[", NULL);
+ EXPECT_FALSE(JustOpening.Parse()) << JustOpening.GetErrorMessage();
+ JsonCompileCommandLineParser WithSpaces(" [ ", NULL);
+ EXPECT_FALSE(WithSpaces.Parse()) << WithSpaces.GetErrorMessage();
+ JsonCompileCommandLineParser WithGarbage(" [x", NULL);
+ EXPECT_FALSE(WithGarbage.Parse()) << WithGarbage.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, ParsesEmptyArrayWithWhitespace) {
+ JsonCompileCommandLineParser Spaces(" [ ] ", NULL);
+ EXPECT_TRUE(Spaces.Parse()) << Spaces.GetErrorMessage();
+ JsonCompileCommandLineParser AllWhites("\t\r\n[\t\n \t\r ]\t\r \n\n", NULL);
+ EXPECT_TRUE(AllWhites.Parse()) << AllWhites.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, FailsIfNotStartingArray) {
+ JsonCompileCommandLineParser ObjectStart("{", NULL);
+ EXPECT_FALSE(ObjectStart.Parse()) << ObjectStart.GetErrorMessage();
+ // We don't implement a full JSON parser, and thus parse only a subset
+ // of valid JSON.
+ JsonCompileCommandLineParser Object("{}", NULL);
+ EXPECT_FALSE(Object.Parse()) << Object.GetErrorMessage();
+ JsonCompileCommandLineParser Character("x", NULL);
+ EXPECT_FALSE(Character.Parse()) << Character.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, ParsesEmptyObject) {
+ JsonCompileCommandLineParser Parser("[{}]", NULL);
+ EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, ParsesObject) {
+ JsonCompileCommandLineParser Parser("[{\"a\":\"/b\"}]", NULL);
+ EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, ParsesMultipleKeyValuePairsInObject) {
+ JsonCompileCommandLineParser Parser(
+ "[{\"a\":\"/b\",\"c\":\"d\",\"e\":\"f\"}]", NULL);
+ EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, FailsIfNotClosingObject) {
+ JsonCompileCommandLineParser MissingCloseOnEmpty("[{]", NULL);
+ EXPECT_FALSE(MissingCloseOnEmpty.Parse())
+ << MissingCloseOnEmpty.GetErrorMessage();
+ JsonCompileCommandLineParser MissingCloseAfterPair("[{\"a\":\"b\"]", NULL);
+ EXPECT_FALSE(MissingCloseAfterPair.Parse())
+ << MissingCloseAfterPair.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, FailsIfMissingColon) {
+ JsonCompileCommandLineParser StringString("[{\"a\"\"/b\"}]", NULL);
+ EXPECT_FALSE(StringString.Parse()) << StringString.GetErrorMessage();
+ JsonCompileCommandLineParser StringSpaceString("[{\"a\" \"b\"}]", NULL);
+ EXPECT_FALSE(StringSpaceString.Parse())
+ << StringSpaceString.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, FailsOnMissingQuote) {
+ JsonCompileCommandLineParser OpenQuote("[{a\":\"b\"}]", NULL);
+ EXPECT_FALSE(OpenQuote.Parse()) << OpenQuote.GetErrorMessage();
+ JsonCompileCommandLineParser CloseQuote("[{\"a\":\"b}]", NULL);
+ EXPECT_FALSE(CloseQuote.Parse()) << CloseQuote.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, ParsesEscapedQuotes) {
+ JsonCompileCommandLineParser Parser(
+ "[{\"a\":\"\\\"b\\\" \\\" \\\"\"}]", NULL);
+ EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, ParsesEmptyString) {
+ JsonCompileCommandLineParser Parser("[{\"a\":\"\"}]", NULL);
+ EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, FailsOnMissingString) {
+ JsonCompileCommandLineParser MissingValue("[{\"a\":}]", NULL);
+ EXPECT_FALSE(MissingValue.Parse()) << MissingValue.GetErrorMessage();
+ JsonCompileCommandLineParser MissingKey("[{:\"b\"}]", NULL);
+ EXPECT_FALSE(MissingKey.Parse()) << MissingKey.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, ParsesMultipleObjects) {
+ JsonCompileCommandLineParser Parser(
+ "["
+ " { \"a\" : \"b\" },"
+ " { \"a\" : \"b\" },"
+ " { \"a\" : \"b\" }"
+ "]", NULL);
+ EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, FailsOnMissingComma) {
+ JsonCompileCommandLineParser Parser(
+ "["
+ " { \"a\" : \"b\" }"
+ " { \"a\" : \"b\" }"
+ "]", NULL);
+ EXPECT_FALSE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, FailsOnSuperfluousComma) {
+ JsonCompileCommandLineParser Parser(
+ "[ { \"a\" : \"b\" }, ]", NULL);
+ EXPECT_FALSE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+TEST(JsonCompileCommandLineParser, ParsesSpacesInBetweenTokens) {
+ JsonCompileCommandLineParser Parser(
+ " \t \n\n \r [ \t \n\n \r"
+ " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :"
+ " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r,\t \n\n \r"
+ " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :"
+ " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r]\t \n\n \r",
+ NULL);
+ EXPECT_TRUE(Parser.Parse()) << Parser.GetErrorMessage();
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp
index da89c0ba10..6e5bc6b613 100644
--- a/unittests/Tooling/ToolingTest.cpp
+++ b/unittests/Tooling/ToolingTest.cpp
@@ -7,6 +7,7 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/Twine.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
@@ -86,6 +87,89 @@ TEST(RunSyntaxOnlyToolOnCode, FindsClassDecl) {
EXPECT_FALSE(FoundClassDeclX);
}
+TEST(FindCompileArgsInJsonDatabase, FindsNothingIfEmpty) {
+ std::string ErrorMessage;
+ CompileCommand NotFound = FindCompileArgsInJsonDatabase(
+ "a-file.cpp", "", ErrorMessage);
+ EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
+ EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
+}
+
+TEST(FindCompileArgsInJsonDatabase, ReadsSingleEntry) {
+ llvm::StringRef Directory("/some/directory");
+ llvm::StringRef FileName("/path/to/a-file.cpp");
+ llvm::StringRef Command("/path/to/compiler and some arguments");
+ std::string ErrorMessage;
+ CompileCommand FoundCommand = FindCompileArgsInJsonDatabase(
+ FileName,
+ (llvm::Twine("[{\"directory\":\"") + Directory + "\"," +
+ "\"command\":\"" + Command + "\","
+ "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage);
+ EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
+ ASSERT_EQ(4u, FoundCommand.CommandLine.size()) << ErrorMessage;
+ EXPECT_EQ("/path/to/compiler", FoundCommand.CommandLine[0]) << ErrorMessage;
+ EXPECT_EQ("and", FoundCommand.CommandLine[1]) << ErrorMessage;
+ EXPECT_EQ("some", FoundCommand.CommandLine[2]) << ErrorMessage;
+ EXPECT_EQ("arguments", FoundCommand.CommandLine[3]) << ErrorMessage;
+
+ CompileCommand NotFound = FindCompileArgsInJsonDatabase(
+ "a-file.cpp",
+ (llvm::Twine("[{\"directory\":\"") + Directory + "\"," +
+ "\"command\":\"" + Command + "\","
+ "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage);
+ EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
+ EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
+}
+
+TEST(FindCompileArgsInJsonDatabase, ReadsCompileCommandLinesWithSpaces) {
+ llvm::StringRef Directory("/some/directory");
+ llvm::StringRef FileName("/path/to/a-file.cpp");
+ llvm::StringRef Command("\\\"/path to compiler\\\" \\\"and an argument\\\"");
+ std::string ErrorMessage;
+ CompileCommand FoundCommand = FindCompileArgsInJsonDatabase(
+ FileName,
+ (llvm::Twine("[{\"directory\":\"") + Directory + "\"," +
+ "\"command\":\"" + Command + "\","
+ "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage);
+ ASSERT_EQ(2u, FoundCommand.CommandLine.size());
+ EXPECT_EQ("/path to compiler", FoundCommand.CommandLine[0]) << ErrorMessage;
+ EXPECT_EQ("and an argument", FoundCommand.CommandLine[1]) << ErrorMessage;
+}
+
+TEST(FindCompileArgsInJsonDatabase, ReadsDirectoryWithSpaces) {
+ llvm::StringRef Directory("/some directory / with spaces");
+ llvm::StringRef FileName("/path/to/a-file.cpp");
+ llvm::StringRef Command("a command");
+ std::string ErrorMessage;
+ CompileCommand FoundCommand = FindCompileArgsInJsonDatabase(
+ FileName,
+ (llvm::Twine("[{\"directory\":\"") + Directory + "\"," +
+ "\"command\":\"" + Command + "\","
+ "\"file\":\"" + FileName + "\"}]").str(), ErrorMessage);
+ EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
+}
+
+TEST(FindCompileArgsInJsonDatabase, FindsEntry) {
+ llvm::StringRef Directory("directory");
+ llvm::StringRef FileName("file");
+ llvm::StringRef Command("command");
+ std::string JsonDatabase = "[";
+ for (int I = 0; I < 10; ++I) {
+ if (I > 0) JsonDatabase += ",";
+ JsonDatabase += (llvm::Twine(
+ "{\"directory\":\"") + Directory + llvm::Twine(I) + "\"," +
+ "\"command\":\"" + Command + llvm::Twine(I) + "\","
+ "\"file\":\"" + FileName + llvm::Twine(I) + "\"}").str();
+ }
+ JsonDatabase += "]";
+ std::string ErrorMessage;
+ CompileCommand FoundCommand = FindCompileArgsInJsonDatabase(
+ "file4", JsonDatabase, ErrorMessage);
+ EXPECT_EQ("directory4", FoundCommand.Directory) << ErrorMessage;
+ ASSERT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage;
+ EXPECT_EQ("command4", FoundCommand.CommandLine[0]) << ErrorMessage;
+}
+
} // end namespace tooling
} // end namespace clang