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 Diagnostic makeDiagnostic(StringRef DiagnosticName, 24 const std::string &Message, int FileOffset, 25 const std::string &FilePath, 26 const StringMap<Replacements> &Fix) { 27 DiagnosticMessage DiagMessage; 28 DiagMessage.Message = Message; 29 DiagMessage.FileOffset = FileOffset; 30 DiagMessage.FilePath = FilePath; 31 return Diagnostic(DiagnosticName, DiagMessage, Fix, {}, Diagnostic::Warning, 32 "path/to/build/directory"); 33 } 34 35 TEST(DiagnosticsYamlTest, serializesDiagnostics) { 36 TranslationUnitDiagnostics TUD; 37 TUD.MainSourceFile = "path/to/source.cpp"; 38 39 StringMap<Replacements> Fix1 = { 40 {"path/to/source.cpp", 41 Replacements({"path/to/source.cpp", 100, 12, "replacement #1"})}}; 42 TUD.Diagnostics.push_back(makeDiagnostic("diagnostic#1", "message #1", 55, 43 "path/to/source.cpp", Fix1)); 44 45 StringMap<Replacements> Fix2 = { 46 {"path/to/header.h", 47 Replacements({"path/to/header.h", 62, 2, "replacement #2"})}}; 48 TUD.Diagnostics.push_back(makeDiagnostic("diagnostic#2", "message #2", 60, 49 "path/to/header.h", Fix2)); 50 51 TUD.Diagnostics.push_back(makeDiagnostic("diagnostic#3", "message #3", 72, 52 "path/to/source2.cpp", {})); 53 54 std::string YamlContent; 55 raw_string_ostream YamlContentStream(YamlContent); 56 57 yaml::Output YAML(YamlContentStream); 58 YAML << TUD; 59 60 EXPECT_EQ("---\n" 61 "MainSourceFile: 'path/to/source.cpp'\n" 62 "Diagnostics: \n" 63 " - DiagnosticName: 'diagnostic#1\'\n" 64 " Message: 'message #1'\n" 65 " FileOffset: 55\n" 66 " FilePath: 'path/to/source.cpp'\n" 67 " Replacements: \n" 68 " - FilePath: 'path/to/source.cpp'\n" 69 " Offset: 100\n" 70 " Length: 12\n" 71 " ReplacementText: 'replacement #1'\n" 72 " - DiagnosticName: 'diagnostic#2'\n" 73 " Message: 'message #2'\n" 74 " FileOffset: 60\n" 75 " FilePath: 'path/to/header.h'\n" 76 " Replacements: \n" 77 " - FilePath: 'path/to/header.h'\n" 78 " Offset: 62\n" 79 " Length: 2\n" 80 " ReplacementText: 'replacement #2'\n" 81 " - DiagnosticName: 'diagnostic#3'\n" 82 " Message: 'message #3'\n" 83 " FileOffset: 72\n" 84 " FilePath: 'path/to/source2.cpp'\n" 85 " Replacements: \n" 86 "...\n", 87 YamlContentStream.str()); 88 } 89 90 TEST(DiagnosticsYamlTest, deserializesDiagnostics) { 91 std::string YamlContent = "---\n" 92 "MainSourceFile: path/to/source.cpp\n" 93 "Diagnostics: \n" 94 " - DiagnosticName: 'diagnostic#1'\n" 95 " Message: 'message #1'\n" 96 " FileOffset: 55\n" 97 " FilePath: path/to/source.cpp\n" 98 " Replacements: \n" 99 " - FilePath: path/to/source.cpp\n" 100 " Offset: 100\n" 101 " Length: 12\n" 102 " ReplacementText: 'replacement #1'\n" 103 " - DiagnosticName: 'diagnostic#2'\n" 104 " Message: 'message #2'\n" 105 " FileOffset: 60\n" 106 " FilePath: path/to/header.h\n" 107 " Replacements: \n" 108 " - FilePath: path/to/header.h\n" 109 " Offset: 62\n" 110 " Length: 2\n" 111 " ReplacementText: 'replacement #2'\n" 112 " - DiagnosticName: 'diagnostic#3'\n" 113 " Message: 'message #3'\n" 114 " FileOffset: 98\n" 115 " FilePath: path/to/source.cpp\n" 116 " Replacements: \n" 117 "...\n"; 118 TranslationUnitDiagnostics TUDActual; 119 yaml::Input YAML(YamlContent); 120 YAML >> TUDActual; 121 122 ASSERT_FALSE(YAML.error()); 123 ASSERT_EQ(3u, TUDActual.Diagnostics.size()); 124 EXPECT_EQ("path/to/source.cpp", TUDActual.MainSourceFile); 125 126 auto getFixes = [](const StringMap<Replacements> &Fix) { 127 std::vector<Replacement> Fixes; 128 for (auto &Replacements : Fix) { 129 for (auto &Replacement : Replacements.second) { 130 Fixes.push_back(Replacement); 131 } 132 } 133 return Fixes; 134 }; 135 136 Diagnostic D1 = TUDActual.Diagnostics[0]; 137 EXPECT_EQ("diagnostic#1", D1.DiagnosticName); 138 EXPECT_EQ("message #1", D1.Message.Message); 139 EXPECT_EQ(55u, D1.Message.FileOffset); 140 EXPECT_EQ("path/to/source.cpp", D1.Message.FilePath); 141 std::vector<Replacement> Fixes1 = getFixes(D1.Fix); 142 ASSERT_EQ(1u, Fixes1.size()); 143 EXPECT_EQ("path/to/source.cpp", Fixes1[0].getFilePath()); 144 EXPECT_EQ(100u, Fixes1[0].getOffset()); 145 EXPECT_EQ(12u, Fixes1[0].getLength()); 146 EXPECT_EQ("replacement #1", Fixes1[0].getReplacementText()); 147 148 Diagnostic D2 = TUDActual.Diagnostics[1]; 149 EXPECT_EQ("diagnostic#2", D2.DiagnosticName); 150 EXPECT_EQ("message #2", D2.Message.Message); 151 EXPECT_EQ(60u, D2.Message.FileOffset); 152 EXPECT_EQ("path/to/header.h", D2.Message.FilePath); 153 std::vector<Replacement> Fixes2 = getFixes(D2.Fix); 154 ASSERT_EQ(1u, Fixes2.size()); 155 EXPECT_EQ("path/to/header.h", Fixes2[0].getFilePath()); 156 EXPECT_EQ(62u, Fixes2[0].getOffset()); 157 EXPECT_EQ(2u, Fixes2[0].getLength()); 158 EXPECT_EQ("replacement #2", Fixes2[0].getReplacementText()); 159 160 Diagnostic D3 = TUDActual.Diagnostics[2]; 161 EXPECT_EQ("diagnostic#3", D3.DiagnosticName); 162 EXPECT_EQ("message #3", D3.Message.Message); 163 EXPECT_EQ(98u, D3.Message.FileOffset); 164 EXPECT_EQ("path/to/source.cpp", D3.Message.FilePath); 165 std::vector<Replacement> Fixes3 = getFixes(D3.Fix); 166 EXPECT_TRUE(Fixes3.empty()); 167 } 168