xref: /llvm-project/clang/unittests/Tooling/DiagnosticsYamlTest.cpp (revision af17a3866b9bc426fefd4ca40e297d9878ed20ee)
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