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

source code of llvm/unittests/Remarks/YAMLRemarksSerializerTest.cpp