|
20 | 20 | #include "clang/Testing/CommandLineArgs.h" |
21 | 21 | #include "clang/Tooling/ArgumentsAdjusters.h" |
22 | 22 | #include "clang/Tooling/CompilationDatabase.h" |
| 23 | +#include "clang/Tooling/JSONCompilationDatabase.h" |
23 | 24 | #include "llvm/ADT/STLExtras.h" |
24 | 25 | #include "llvm/ADT/StringRef.h" |
| 26 | +#include "llvm/Support/JSON.h" |
25 | 27 | #include "llvm/Support/Path.h" |
26 | 28 | #include "llvm/Support/TargetSelect.h" |
27 | 29 | #include "llvm/TargetParser/Host.h" |
@@ -1034,5 +1036,136 @@ TEST(runToolOnCode, TestResetDiagnostics) { |
1034 | 1036 | "void func() { long x; Foo f(x); }")); |
1035 | 1037 | } |
1036 | 1038 |
|
| 1039 | +namespace { |
| 1040 | +struct TestCommand { |
| 1041 | + llvm::StringRef File; |
| 1042 | + llvm::StringRef Command; |
| 1043 | +}; |
| 1044 | + |
| 1045 | +std::string runToolWithProgress(llvm::ArrayRef<TestCommand> Commands, |
| 1046 | + llvm::StringRef BaseDir) { |
| 1047 | + std::string ErrorMessage; |
| 1048 | + |
| 1049 | + llvm::json::Array Entries; |
| 1050 | + for (const auto &Cmd : Commands) { |
| 1051 | + Entries.push_back(llvm::json::Object{ |
| 1052 | + {"directory", BaseDir}, {"command", Cmd.Command}, {"file", Cmd.File}}); |
| 1053 | + } |
| 1054 | + std::string DatabaseContent; |
| 1055 | + llvm::raw_string_ostream OS(DatabaseContent); |
| 1056 | + OS << llvm::json::Value(std::move(Entries)); |
| 1057 | + |
| 1058 | + std::unique_ptr<CompilationDatabase> Database( |
| 1059 | + JSONCompilationDatabase::loadFromBuffer(DatabaseContent, ErrorMessage, |
| 1060 | + JSONCommandLineSyntax::Gnu)); |
| 1061 | + if (!Database) { |
| 1062 | + ADD_FAILURE() << "Failed to load compilation database: " << ErrorMessage; |
| 1063 | + return ""; |
| 1064 | + } |
| 1065 | + |
| 1066 | + std::vector<std::string> AbsoluteFiles; |
| 1067 | + for (const auto &Cmd : Commands) { |
| 1068 | + SmallString<32> NativeFile(BaseDir); |
| 1069 | + llvm::sys::path::append(NativeFile, Cmd.File); |
| 1070 | + llvm::sys::path::native(NativeFile); |
| 1071 | + std::string AbsPath = std::string(NativeFile); |
| 1072 | + if (AbsoluteFiles.empty() || AbsoluteFiles.back() != AbsPath) { |
| 1073 | + AbsoluteFiles.push_back(AbsPath); |
| 1074 | + } |
| 1075 | + } |
| 1076 | + |
| 1077 | + ClangTool Tool(*Database, AbsoluteFiles); |
| 1078 | + for (const auto &F : AbsoluteFiles) { |
| 1079 | + Tool.mapVirtualFile(F, "int x;"); |
| 1080 | + } |
| 1081 | + |
| 1082 | + testing::internal::CaptureStderr(); |
| 1083 | + Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get()); |
| 1084 | + return testing::internal::GetCapturedStderr(); |
| 1085 | +} |
| 1086 | +} // namespace |
| 1087 | + |
| 1088 | +TEST(ClangToolTest, ProgressReportSingleFile) { |
| 1089 | + SmallString<32> BaseDir; |
| 1090 | + llvm::sys::path::system_temp_directory(false, BaseDir); |
| 1091 | + llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix); |
| 1092 | + |
| 1093 | + EXPECT_TRUE( |
| 1094 | + runToolWithProgress({{"test.cpp", "clang++ -c test.cpp"}}, BaseDir) |
| 1095 | + .empty()); |
| 1096 | +} |
| 1097 | + |
| 1098 | +TEST(ClangToolTest, ProgressReportMultipleFiles) { |
| 1099 | + SmallString<32> BaseDir; |
| 1100 | + llvm::sys::path::system_temp_directory(false, BaseDir); |
| 1101 | + llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix); |
| 1102 | + |
| 1103 | + std::string Output = |
| 1104 | + runToolWithProgress({{"test1.cpp", "clang++ -c test1.cpp"}, |
| 1105 | + {"test2.cpp", "clang++ -c test2.cpp"}}, |
| 1106 | + BaseDir); |
| 1107 | + |
| 1108 | + SmallString<32> NativeFile1(BaseDir); |
| 1109 | + llvm::sys::path::append(NativeFile1, "test1.cpp"); |
| 1110 | + llvm::sys::path::native(NativeFile1); |
| 1111 | + SmallString<32> NativeFile2(BaseDir); |
| 1112 | + llvm::sys::path::append(NativeFile2, "test2.cpp"); |
| 1113 | + llvm::sys::path::native(NativeFile2); |
| 1114 | + |
| 1115 | + std::string Expected = "[1/2] Processing file " + std::string(NativeFile1) + |
| 1116 | + ".\n" + "[2/2] Processing file " + |
| 1117 | + std::string(NativeFile2) + ".\n"; |
| 1118 | + EXPECT_EQ(Output, Expected); |
| 1119 | +} |
| 1120 | + |
| 1121 | +TEST(ClangToolTest, ProgressReportMultipleCommands) { |
| 1122 | + SmallString<32> BaseDir; |
| 1123 | + llvm::sys::path::system_temp_directory(false, BaseDir); |
| 1124 | + llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix); |
| 1125 | + |
| 1126 | + std::string Output = |
| 1127 | + runToolWithProgress({{"test.cpp", "clang++ -c test.cpp -DCMD1"}, |
| 1128 | + {"test.cpp", "clang++ -c test.cpp -DCMD2"}}, |
| 1129 | + BaseDir); |
| 1130 | + |
| 1131 | + SmallString<32> NativeFile(BaseDir); |
| 1132 | + llvm::sys::path::append(NativeFile, "test.cpp"); |
| 1133 | + llvm::sys::path::native(NativeFile); |
| 1134 | + std::string Expected = |
| 1135 | + "[1/1] (1/2) Processing file " + std::string(NativeFile) + ".\n" + |
| 1136 | + "[1/1] (2/2) Processing file " + std::string(NativeFile) + ".\n"; |
| 1137 | + EXPECT_EQ(Output, Expected); |
| 1138 | +} |
| 1139 | + |
| 1140 | +TEST(ClangToolTest, ProgressReportMixed) { |
| 1141 | + SmallString<32> BaseDir; |
| 1142 | + llvm::sys::path::system_temp_directory(false, BaseDir); |
| 1143 | + llvm::sys::path::native(BaseDir, llvm::sys::path::Style::posix); |
| 1144 | + |
| 1145 | + std::string Output = |
| 1146 | + runToolWithProgress({{"test1.cpp", "clang++ -c test1.cpp"}, |
| 1147 | + {"test2.cpp", "clang++ -c test2.cpp -DCMD1"}, |
| 1148 | + {"test2.cpp", "clang++ -c test2.cpp -DCMD2"}, |
| 1149 | + {"test3.cpp", "clang++ -c test3.cpp"}}, |
| 1150 | + BaseDir); |
| 1151 | + |
| 1152 | + SmallString<32> NativeFile1(BaseDir); |
| 1153 | + llvm::sys::path::append(NativeFile1, "test1.cpp"); |
| 1154 | + llvm::sys::path::native(NativeFile1); |
| 1155 | + SmallString<32> NativeFile2(BaseDir); |
| 1156 | + llvm::sys::path::append(NativeFile2, "test2.cpp"); |
| 1157 | + llvm::sys::path::native(NativeFile2); |
| 1158 | + SmallString<32> NativeFile3(BaseDir); |
| 1159 | + llvm::sys::path::append(NativeFile3, "test3.cpp"); |
| 1160 | + llvm::sys::path::native(NativeFile3); |
| 1161 | + |
| 1162 | + std::string Expected = |
| 1163 | + "[1/3] Processing file " + std::string(NativeFile1) + ".\n" + |
| 1164 | + "[2/3] (1/2) Processing file " + std::string(NativeFile2) + ".\n" + |
| 1165 | + "[2/3] (2/2) Processing file " + std::string(NativeFile2) + ".\n" + |
| 1166 | + "[3/3] Processing file " + std::string(NativeFile3) + ".\n"; |
| 1167 | + EXPECT_EQ(Output, Expected); |
| 1168 | +} |
| 1169 | + |
1037 | 1170 | } // end namespace tooling |
1038 | 1171 | } // end namespace clang |
0 commit comments