1 //===- unittest/Support/YAMLRemarksSerializerTest.cpp --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Remarks/Remark.h"
10 #include "llvm/Remarks/RemarkParser.h"
11 #include "llvm/Remarks/YAMLRemarkSerializer.h"
12 #include "llvm/Support/Error.h"
13 #include "gtest/gtest.h"
14 
15 // We need to supprt Windows paths as well. In order to have paths with the same
16 // length, use a different path according to the platform.
17 #ifdef _WIN32
18 #define EXTERNALFILETESTPATH "C:/externalfi"
19 #else
20 #define EXTERNALFILETESTPATH "/externalfile"
21 #endif
22 
23 using namespace llvm;
24 
check(remarks::Format SerializerFormat,remarks::SerializerMode Mode,ArrayRef<remarks::Remark> Rs,StringRef ExpectedR,Optional<StringRef> ExpectedMeta,Optional<remarks::StringTable> StrTab=None)25 static void check(remarks::Format SerializerFormat,
26                   remarks::SerializerMode Mode, ArrayRef<remarks::Remark> Rs,
27                   StringRef ExpectedR, Optional<StringRef> ExpectedMeta,
28                   Optional<remarks::StringTable> StrTab = None) {
29   std::string Buf;
30   raw_string_ostream OS(Buf);
31   Expected<std::unique_ptr<remarks::RemarkSerializer>> MaybeS = [&] {
32     if (StrTab)
33       return createRemarkSerializer(SerializerFormat, Mode, OS,
34                                     std::move(*StrTab));
35     else
36       return createRemarkSerializer(SerializerFormat, Mode, OS);
37   }();
38   EXPECT_FALSE(errorToBool(MaybeS.takeError()));
39   std::unique_ptr<remarks::RemarkSerializer> S = std::move(*MaybeS);
40 
41   for (const remarks::Remark &R : Rs)
42     S->emit(R);
43   EXPECT_EQ(OS.str(), ExpectedR);
44 
45   if (ExpectedMeta) {
46     Buf.clear();
47     std::unique_ptr<remarks::MetaSerializer> MS =
48         S->metaSerializer(OS, StringRef(EXTERNALFILETESTPATH));
49     MS->emit();
50     EXPECT_EQ(OS.str(), *ExpectedMeta);
51   }
52 }
53 
check(remarks::Format SerializerFormat,const remarks::Remark & R,StringRef ExpectedR,StringRef ExpectedMeta,Optional<remarks::StringTable> StrTab=None)54 static void check(remarks::Format SerializerFormat, const remarks::Remark &R,
55                   StringRef ExpectedR, StringRef ExpectedMeta,
56                   Optional<remarks::StringTable> StrTab = None) {
57   return check(SerializerFormat, remarks::SerializerMode::Separate,
58                makeArrayRef(&R, &R + 1), ExpectedR, ExpectedMeta,
59                std::move(StrTab));
60 }
61 
checkStandalone(remarks::Format SerializerFormat,const remarks::Remark & R,StringRef ExpectedR,Optional<remarks::StringTable> StrTab=None)62 static void checkStandalone(remarks::Format SerializerFormat,
63                             const remarks::Remark &R, StringRef ExpectedR,
64                             Optional<remarks::StringTable> StrTab = None) {
65   return check(SerializerFormat, remarks::SerializerMode::Standalone,
66                makeArrayRef(&R, &R + 1), ExpectedR,
67                /*ExpectedMeta=*/None, std::move(StrTab));
68 }
69 
TEST(YAMLRemarks,SerializerRemark)70 TEST(YAMLRemarks, SerializerRemark) {
71   remarks::Remark R;
72   R.RemarkType = remarks::Type::Missed;
73   R.PassName = "pass";
74   R.RemarkName = "name";
75   R.FunctionName = "func";
76   R.Loc = remarks::RemarkLocation{"path", 3, 4};
77   R.Hotness = 5;
78   R.Args.emplace_back();
79   R.Args.back().Key = "key";
80   R.Args.back().Val = "value";
81   R.Args.emplace_back();
82   R.Args.back().Key = "keydebug";
83   R.Args.back().Val = "valuedebug";
84   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
85   check(remarks::Format::YAML, R,
86         "--- !Missed\n"
87         "Pass:            pass\n"
88         "Name:            name\n"
89         "DebugLoc:        { File: path, Line: 3, Column: 4 }\n"
90         "Function:        func\n"
91         "Hotness:         5\n"
92         "Args:\n"
93         "  - key:             value\n"
94         "  - keydebug:        valuedebug\n"
95         "    DebugLoc:        { File: argpath, Line: 6, Column: 7 }\n"
96         "...\n",
97         StringRef("REMARKS\0"
98                   "\0\0\0\0\0\0\0\0"
99                   "\0\0\0\0\0\0\0\0" EXTERNALFILETESTPATH "\0",
100                   38));
101 }
102 
TEST(YAMLRemarks,SerializerRemarkStandalone)103 TEST(YAMLRemarks, SerializerRemarkStandalone) {
104   remarks::Remark R;
105   R.RemarkType = remarks::Type::Missed;
106   R.PassName = "pass";
107   R.RemarkName = "name";
108   R.FunctionName = "func";
109   R.Loc = remarks::RemarkLocation{"path", 3, 4};
110   R.Hotness = 5;
111   R.Args.emplace_back();
112   R.Args.back().Key = "key";
113   R.Args.back().Val = "value";
114   R.Args.emplace_back();
115   R.Args.back().Key = "keydebug";
116   R.Args.back().Val = "valuedebug";
117   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
118   checkStandalone(
119       remarks::Format::YAML, R,
120       StringRef("--- !Missed\n"
121                 "Pass:            pass\n"
122                 "Name:            name\n"
123                 "DebugLoc:        { File: path, Line: 3, Column: 4 }\n"
124                 "Function:        func\n"
125                 "Hotness:         5\n"
126                 "Args:\n"
127                 "  - key:             value\n"
128                 "  - keydebug:        valuedebug\n"
129                 "    DebugLoc:        { File: argpath, Line: 6, Column: 7 }\n"
130                 "...\n"));
131 }
132 
TEST(YAMLRemarks,SerializerRemarkStrTab)133 TEST(YAMLRemarks, SerializerRemarkStrTab) {
134   remarks::Remark R;
135   R.RemarkType = remarks::Type::Missed;
136   R.PassName = "pass";
137   R.RemarkName = "name";
138   R.FunctionName = "func";
139   R.Loc = remarks::RemarkLocation{"path", 3, 4};
140   R.Hotness = 5;
141   R.Args.emplace_back();
142   R.Args.back().Key = "key";
143   R.Args.back().Val = "value";
144   R.Args.emplace_back();
145   R.Args.back().Key = "keydebug";
146   R.Args.back().Val = "valuedebug";
147   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
148   check(remarks::Format::YAMLStrTab, R,
149         "--- !Missed\n"
150         "Pass:            0\n"
151         "Name:            1\n"
152         "DebugLoc:        { File: 3, Line: 3, Column: 4 }\n"
153         "Function:        2\n"
154         "Hotness:         5\n"
155         "Args:\n"
156         "  - key:             4\n"
157         "  - keydebug:        5\n"
158         "    DebugLoc:        { File: 6, Line: 6, Column: 7 }\n"
159         "...\n",
160         StringRef("REMARKS\0"
161                   "\0\0\0\0\0\0\0\0"
162                   "\x2d\0\0\0\0\0\0\0"
163                   "pass\0name\0func\0path\0value\0valuedebug\0argpath"
164                   "\0" EXTERNALFILETESTPATH "\0",
165                   83));
166 }
167 
TEST(YAMLRemarks,SerializerRemarkParsedStrTab)168 TEST(YAMLRemarks, SerializerRemarkParsedStrTab) {
169   StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45);
170   remarks::Remark R;
171   R.RemarkType = remarks::Type::Missed;
172   R.PassName = "pass";
173   R.RemarkName = "name";
174   R.FunctionName = "func";
175   R.Loc = remarks::RemarkLocation{"path", 3, 4};
176   R.Hotness = 5;
177   R.Args.emplace_back();
178   R.Args.back().Key = "key";
179   R.Args.back().Val = "value";
180   R.Args.emplace_back();
181   R.Args.back().Key = "keydebug";
182   R.Args.back().Val = "valuedebug";
183   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
184   check(remarks::Format::YAMLStrTab, R,
185         "--- !Missed\n"
186         "Pass:            0\n"
187         "Name:            1\n"
188         "DebugLoc:        { File: 3, Line: 3, Column: 4 }\n"
189         "Function:        2\n"
190         "Hotness:         5\n"
191         "Args:\n"
192         "  - key:             4\n"
193         "  - keydebug:        5\n"
194         "    DebugLoc:        { File: 6, Line: 6, Column: 7 }\n"
195         "...\n",
196         StringRef("REMARKS\0"
197                   "\0\0\0\0\0\0\0\0"
198                   "\x2d\0\0\0\0\0\0\0"
199                   "pass\0name\0func\0path\0value\0valuedebug\0argpath"
200                   "\0" EXTERNALFILETESTPATH "\0",
201                   83),
202         remarks::StringTable(remarks::ParsedStringTable(StrTab)));
203 }
204 
TEST(YAMLRemarks,SerializerRemarkParsedStrTabStandaloneNoStrTab)205 TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandaloneNoStrTab) {
206   // Check that we don't use the string table even if it was provided.
207   StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45);
208   remarks::ParsedStringTable ParsedStrTab(StrTab);
209   remarks::StringTable PreFilledStrTab(ParsedStrTab);
210   remarks::Remark R;
211   R.RemarkType = remarks::Type::Missed;
212   R.PassName = "pass";
213   R.RemarkName = "name";
214   R.FunctionName = "func";
215   R.Loc = remarks::RemarkLocation{"path", 3, 4};
216   R.Hotness = 5;
217   R.Args.emplace_back();
218   R.Args.back().Key = "key";
219   R.Args.back().Val = "value";
220   R.Args.emplace_back();
221   R.Args.back().Key = "keydebug";
222   R.Args.back().Val = "valuedebug";
223   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
224   checkStandalone(
225       remarks::Format::YAML, R,
226       StringRef("--- !Missed\n"
227                 "Pass:            pass\n"
228                 "Name:            name\n"
229                 "DebugLoc:        { File: path, Line: 3, Column: 4 }\n"
230                 "Function:        func\n"
231                 "Hotness:         5\n"
232                 "Args:\n"
233                 "  - key:             value\n"
234                 "  - keydebug:        valuedebug\n"
235                 "    DebugLoc:        { File: argpath, Line: 6, Column: 7 }\n"
236                 "...\n"),
237       std::move(PreFilledStrTab));
238 }
239 
TEST(YAMLRemarks,SerializerRemarkParsedStrTabStandalone)240 TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandalone) {
241   StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45);
242   remarks::ParsedStringTable ParsedStrTab(StrTab);
243   remarks::StringTable PreFilledStrTab(ParsedStrTab);
244   remarks::Remark R;
245   R.RemarkType = remarks::Type::Missed;
246   R.PassName = "pass";
247   R.RemarkName = "name";
248   R.FunctionName = "func";
249   R.Loc = remarks::RemarkLocation{"path", 3, 4};
250   R.Hotness = 5;
251   R.Args.emplace_back();
252   R.Args.back().Key = "key";
253   R.Args.back().Val = "value";
254   R.Args.emplace_back();
255   R.Args.back().Key = "keydebug";
256   R.Args.back().Val = "valuedebug";
257   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
258   checkStandalone(
259       remarks::Format::YAMLStrTab, R,
260       StringRef("REMARKS\0"
261                 "\0\0\0\0\0\0\0\0"
262                 "\x2d\0\0\0\0\0\0\0"
263                 "pass\0name\0func\0path\0value\0valuedebug\0argpath\0"
264                 "--- !Missed\n"
265                 "Pass:            0\n"
266                 "Name:            1\n"
267                 "DebugLoc:        { File: 3, Line: 3, Column: 4 }\n"
268                 "Function:        2\n"
269                 "Hotness:         5\n"
270                 "Args:\n"
271                 "  - key:             4\n"
272                 "  - keydebug:        5\n"
273                 "    DebugLoc:        { File: 6, Line: 6, Column: 7 }\n"
274                 "...\n",
275                 315),
276       std::move(PreFilledStrTab));
277 }
278 
TEST(YAMLRemarks,SerializerRemarkParsedStrTabStandaloneMultipleRemarks)279 TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandaloneMultipleRemarks) {
280   StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45);
281   remarks::ParsedStringTable ParsedStrTab(StrTab);
282   remarks::StringTable PreFilledStrTab(ParsedStrTab);
283   SmallVector<remarks::Remark, 2> Rs;
284   remarks::Remark R;
285   R.RemarkType = remarks::Type::Missed;
286   R.PassName = "pass";
287   R.RemarkName = "name";
288   R.FunctionName = "func";
289   R.Loc = remarks::RemarkLocation{"path", 3, 4};
290   R.Hotness = 5;
291   R.Args.emplace_back();
292   R.Args.back().Key = "key";
293   R.Args.back().Val = "value";
294   R.Args.emplace_back();
295   R.Args.back().Key = "keydebug";
296   R.Args.back().Val = "valuedebug";
297   R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7};
298   Rs.emplace_back(R.clone());
299   Rs.emplace_back(std::move(R));
300   check(remarks::Format::YAMLStrTab, remarks::SerializerMode::Standalone, Rs,
301         StringRef("REMARKS\0"
302                   "\0\0\0\0\0\0\0\0"
303                   "\x2d\0\0\0\0\0\0\0"
304                   "pass\0name\0func\0path\0value\0valuedebug\0argpath\0"
305                   "--- !Missed\n"
306                   "Pass:            0\n"
307                   "Name:            1\n"
308                   "DebugLoc:        { File: 3, Line: 3, Column: 4 }\n"
309                   "Function:        2\n"
310                   "Hotness:         5\n"
311                   "Args:\n"
312                   "  - key:             4\n"
313                   "  - keydebug:        5\n"
314                   "    DebugLoc:        { File: 6, Line: 6, Column: 7 }\n"
315                   "...\n"
316                   "--- !Missed\n"
317                   "Pass:            0\n"
318                   "Name:            1\n"
319                   "DebugLoc:        { File: 3, Line: 3, Column: 4 }\n"
320                   "Function:        2\n"
321                   "Hotness:         5\n"
322                   "Args:\n"
323                   "  - key:             4\n"
324                   "  - keydebug:        5\n"
325                   "    DebugLoc:        { File: 6, Line: 6, Column: 7 }\n"
326                   "...\n",
327                   561),
328         /*ExpectedMeta=*/None, std::move(PreFilledStrTab));
329 }
330