1 //===- unittests/Tooling/DiagnosticsYamlTest.cpp - Serialization tests ---===// 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 // Tests for serialization of Diagnostics. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Tooling/DiagnosticsYaml.h" 15 #include "clang/Tooling/Core/Diagnostic.h" 16 #include "clang/Tooling/ReplacementsYaml.h" 17 #include "gtest/gtest.h" 18 19 using namespace llvm; 20 using namespace clang::tooling; 21 using clang::tooling::Diagnostic; 22 23 static DiagnosticMessage makeMessage(const std::string &Message, int FileOffset, 24 const std::string &FilePath) { 25 DiagnosticMessage DiagMessage; 26 DiagMessage.Message = Message; 27 DiagMessage.FileOffset = FileOffset; 28 DiagMessage.FilePath = FilePath; 29 return DiagMessage; 30 } 31 32 static Diagnostic makeDiagnostic(StringRef DiagnosticName, 33 const std::string &Message, int FileOffset, 34 const std::string &FilePath, 35 const StringMap<Replacements> &Fix) { 36 return Diagnostic(DiagnosticName, makeMessage(Message, FileOffset, FilePath), 37 Fix, {}, Diagnostic::Warning, "path/to/build/directory"); 38 } 39 40 TEST(DiagnosticsYamlTest, serializesDiagnostics) { 41 TranslationUnitDiagnostics TUD; 42 TUD.MainSourceFile = "path/to/source.cpp"; 43 44 StringMap<Replacements> Fix1 = { 45 {"path/to/source.cpp", 46 Replacements({"path/to/source.cpp", 100, 12, "replacement #1"})}}; 47 TUD.Diagnostics.push_back(makeDiagnostic("diagnostic#1", "message #1", 55, 48 "path/to/source.cpp", Fix1)); 49 50 StringMap<Replacements> Fix2 = { 51 {"path/to/header.h", 52 Replacements({"path/to/header.h", 62, 2, "replacement #2"})}}; 53 TUD.Diagnostics.push_back(makeDiagnostic("diagnostic#2", "message #2", 60, 54 "path/to/header.h", Fix2)); 55 56 TUD.Diagnostics.push_back(makeDiagnostic("diagnostic#3", "message #3", 72, 57 "path/to/source2.cpp", {})); 58 TUD.Diagnostics.back().Notes.push_back( 59 makeMessage("Note1", 88, "path/to/note1.cpp")); 60 TUD.Diagnostics.back().Notes.push_back( 61 makeMessage("Note2", 99, "path/to/note2.cpp")); 62 63 std::string YamlContent; 64 raw_string_ostream YamlContentStream(YamlContent); 65 66 yaml::Output YAML(YamlContentStream); 67 YAML << TUD; 68 69 EXPECT_EQ("---\n" 70 "MainSourceFile: 'path/to/source.cpp'\n" 71 "Diagnostics: \n" 72 " - DiagnosticName: 'diagnostic#1\'\n" 73 " Message: 'message #1'\n" 74 " FileOffset: 55\n" 75 " FilePath: 'path/to/source.cpp'\n" 76 " Replacements: \n" 77 " - FilePath: 'path/to/source.cpp'\n" 78 " Offset: 100\n" 79 " Length: 12\n" 80 " ReplacementText: 'replacement #1'\n" 81 " - DiagnosticName: 'diagnostic#2'\n" 82 " Message: 'message #2'\n" 83 " FileOffset: 60\n" 84 " FilePath: 'path/to/header.h'\n" 85 " Replacements: \n" 86 " - FilePath: 'path/to/header.h'\n" 87 " Offset: 62\n" 88 " Length: 2\n" 89 " ReplacementText: 'replacement #2'\n" 90 " - DiagnosticName: 'diagnostic#3'\n" 91 " Message: 'message #3'\n" 92 " FileOffset: 72\n" 93 " FilePath: 'path/to/source2.cpp'\n" 94 " Notes: \n" 95 " - Message: Note1\n" 96 " FilePath: 'path/to/note1.cpp'\n" 97 " FileOffset: 88\n" 98 " - Message: Note2\n" 99 " FilePath: 'path/to/note2.cpp'\n" 100 " FileOffset: 99\n" 101 " Replacements: []\n" 102 "...\n", 103 YamlContentStream.str()); 104 } 105 106 TEST(DiagnosticsYamlTest, deserializesDiagnostics) { 107 std::string YamlContent = "---\n" 108 "MainSourceFile: path/to/source.cpp\n" 109 "Diagnostics: \n" 110 " - DiagnosticName: 'diagnostic#1'\n" 111 " Message: 'message #1'\n" 112 " FileOffset: 55\n" 113 " FilePath: path/to/source.cpp\n" 114 " Replacements: \n" 115 " - FilePath: path/to/source.cpp\n" 116 " Offset: 100\n" 117 " Length: 12\n" 118 " ReplacementText: 'replacement #1'\n" 119 " - DiagnosticName: 'diagnostic#2'\n" 120 " Message: 'message #2'\n" 121 " FileOffset: 60\n" 122 " FilePath: path/to/header.h\n" 123 " Replacements: \n" 124 " - FilePath: path/to/header.h\n" 125 " Offset: 62\n" 126 " Length: 2\n" 127 " ReplacementText: 'replacement #2'\n" 128 " - DiagnosticName: 'diagnostic#3'\n" 129 " Message: 'message #3'\n" 130 " FileOffset: 98\n" 131 " FilePath: path/to/source.cpp\n" 132 " Notes:\n" 133 " - Message: Note1\n" 134 " FilePath: 'path/to/note1.cpp'\n" 135 " FileOffset: 66\n" 136 " - Message: Note2\n" 137 " FilePath: 'path/to/note2.cpp'\n" 138 " FileOffset: 77\n" 139 " Replacements: []\n" 140 "...\n"; 141 TranslationUnitDiagnostics TUDActual; 142 yaml::Input YAML(YamlContent); 143 YAML >> TUDActual; 144 145 ASSERT_FALSE(YAML.error()); 146 ASSERT_EQ(3u, TUDActual.Diagnostics.size()); 147 EXPECT_EQ("path/to/source.cpp", TUDActual.MainSourceFile); 148 149 auto getFixes = [](const StringMap<Replacements> &Fix) { 150 std::vector<Replacement> Fixes; 151 for (auto &Replacements : Fix) { 152 for (auto &Replacement : Replacements.second) { 153 Fixes.push_back(Replacement); 154 } 155 } 156 return Fixes; 157 }; 158 159 Diagnostic D1 = TUDActual.Diagnostics[0]; 160 EXPECT_EQ("diagnostic#1", D1.DiagnosticName); 161 EXPECT_EQ("message #1", D1.Message.Message); 162 EXPECT_EQ(55u, D1.Message.FileOffset); 163 EXPECT_EQ("path/to/source.cpp", D1.Message.FilePath); 164 std::vector<Replacement> Fixes1 = getFixes(D1.Fix); 165 ASSERT_EQ(1u, Fixes1.size()); 166 EXPECT_EQ("path/to/source.cpp", Fixes1[0].getFilePath()); 167 EXPECT_EQ(100u, Fixes1[0].getOffset()); 168 EXPECT_EQ(12u, Fixes1[0].getLength()); 169 EXPECT_EQ("replacement #1", Fixes1[0].getReplacementText()); 170 171 Diagnostic D2 = TUDActual.Diagnostics[1]; 172 EXPECT_EQ("diagnostic#2", D2.DiagnosticName); 173 EXPECT_EQ("message #2", D2.Message.Message); 174 EXPECT_EQ(60u, D2.Message.FileOffset); 175 EXPECT_EQ("path/to/header.h", D2.Message.FilePath); 176 std::vector<Replacement> Fixes2 = getFixes(D2.Fix); 177 ASSERT_EQ(1u, Fixes2.size()); 178 EXPECT_EQ("path/to/header.h", Fixes2[0].getFilePath()); 179 EXPECT_EQ(62u, Fixes2[0].getOffset()); 180 EXPECT_EQ(2u, Fixes2[0].getLength()); 181 EXPECT_EQ("replacement #2", Fixes2[0].getReplacementText()); 182 183 Diagnostic D3 = TUDActual.Diagnostics[2]; 184 EXPECT_EQ("diagnostic#3", D3.DiagnosticName); 185 EXPECT_EQ("message #3", D3.Message.Message); 186 EXPECT_EQ(98u, D3.Message.FileOffset); 187 EXPECT_EQ("path/to/source.cpp", D3.Message.FilePath); 188 EXPECT_EQ(2u, D3.Notes.size()); 189 EXPECT_EQ("Note1", D3.Notes[0].Message); 190 EXPECT_EQ(66u, D3.Notes[0].FileOffset); 191 EXPECT_EQ("path/to/note1.cpp", D3.Notes[0].FilePath); 192 EXPECT_EQ("Note2", D3.Notes[1].Message); 193 EXPECT_EQ(77u, D3.Notes[1].FileOffset); 194 EXPECT_EQ("path/to/note2.cpp", D3.Notes[1].FilePath); 195 std::vector<Replacement> Fixes3 = getFixes(D3.Fix); 196 EXPECT_TRUE(Fixes3.empty()); 197 } 198