[LLVM][NFC] remove unused fields
[llvm-complete.git] / unittests / Remarks / YAMLRemarksParsingTest.cpp
blobaec2e97cda8b51774395a32e0c6155e9adfa2e0d
1 //===- unittest/Support/YAMLRemarksParsingTest.cpp - OptTable tests -------===//
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 //===----------------------------------------------------------------------===//
9 #include "llvm-c/Remarks.h"
10 #include "llvm/Remarks/Remark.h"
11 #include "llvm/Remarks/RemarkParser.h"
12 #include "gtest/gtest.h"
14 using namespace llvm;
16 template <size_t N> void parseGood(const char (&Buf)[N]) {
17 Expected<std::unique_ptr<remarks::RemarkParser>> MaybeParser =
18 remarks::createRemarkParser(remarks::Format::YAML, {Buf, N - 1});
19 EXPECT_FALSE(errorToBool(MaybeParser.takeError()));
20 EXPECT_TRUE(*MaybeParser != nullptr);
22 remarks::RemarkParser &Parser = **MaybeParser;
23 Expected<std::unique_ptr<remarks::Remark>> Remark = Parser.next();
24 EXPECT_FALSE(errorToBool(Remark.takeError())); // Check for parsing errors.
25 EXPECT_TRUE(*Remark != nullptr); // At least one remark.
26 Remark = Parser.next();
27 Error E = Remark.takeError();
28 EXPECT_TRUE(E.isA<remarks::EndOfFileError>());
29 EXPECT_TRUE(errorToBool(std::move(E))); // Check for parsing errors.
32 void parseGoodMeta(StringRef Buf) {
33 Expected<std::unique_ptr<remarks::RemarkParser>> MaybeParser =
34 remarks::createRemarkParserFromMeta(remarks::Format::YAML, Buf);
35 EXPECT_FALSE(errorToBool(MaybeParser.takeError()));
36 EXPECT_TRUE(*MaybeParser != nullptr);
38 remarks::RemarkParser &Parser = **MaybeParser;
39 Expected<std::unique_ptr<remarks::Remark>> Remark = Parser.next();
40 EXPECT_FALSE(errorToBool(Remark.takeError())); // Check for parsing errors.
41 EXPECT_TRUE(*Remark != nullptr); // At least one remark.
42 Remark = Parser.next();
43 Error E = Remark.takeError();
44 EXPECT_TRUE(E.isA<remarks::EndOfFileError>());
45 EXPECT_TRUE(errorToBool(std::move(E))); // Check for parsing errors.
48 template <size_t N>
49 bool parseExpectError(const char (&Buf)[N], const char *Error) {
50 Expected<std::unique_ptr<remarks::RemarkParser>> MaybeParser =
51 remarks::createRemarkParser(remarks::Format::YAML, {Buf, N - 1});
52 EXPECT_FALSE(errorToBool(MaybeParser.takeError()));
53 EXPECT_TRUE(*MaybeParser != nullptr);
55 remarks::RemarkParser &Parser = **MaybeParser;
56 Expected<std::unique_ptr<remarks::Remark>> Remark = Parser.next();
57 EXPECT_FALSE(Remark); // Check for parsing errors.
59 std::string ErrorStr;
60 raw_string_ostream Stream(ErrorStr);
61 handleAllErrors(Remark.takeError(),
62 [&](const ErrorInfoBase &EIB) { EIB.log(Stream); });
63 return StringRef(Stream.str()).contains(Error);
66 void parseExpectErrorMeta(StringRef Buf, const char *Error) {
67 std::string ErrorStr;
68 raw_string_ostream Stream(ErrorStr);
70 Expected<std::unique_ptr<remarks::RemarkParser>> MaybeParser =
71 remarks::createRemarkParserFromMeta(remarks::Format::YAML, Buf);
72 handleAllErrors(MaybeParser.takeError(),
73 [&](const ErrorInfoBase &EIB) { EIB.log(Stream); });
75 // Use a case insensitive comparision due to case differences in error strings
76 // for different OSs.
77 EXPECT_EQ(StringRef(Stream.str()).lower(), StringRef(Error).lower());
80 TEST(YAMLRemarks, ParsingEmpty) {
81 EXPECT_TRUE(parseExpectError("\n\n", "document root is not of mapping type."));
84 TEST(YAMLRemarks, ParsingNotYAML) {
85 EXPECT_TRUE(
86 parseExpectError("\x01\x02\x03\x04\x05\x06", "Got empty plain scalar"));
89 TEST(YAMLRemarks, ParsingGood) {
90 parseGood("\n"
91 "--- !Missed\n"
92 "Pass: inline\n"
93 "Name: NoDefinition\n"
94 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
95 "Function: foo\n"
96 "Args:\n"
97 " - Callee: bar\n"
98 " - String: ' will not be inlined into '\n"
99 " - Caller: foo\n"
100 " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n"
101 " - String: ' because its definition is unavailable'\n"
102 "");
104 // No debug loc should also pass.
105 parseGood("\n"
106 "--- !Missed\n"
107 "Pass: inline\n"
108 "Name: NoDefinition\n"
109 "Function: foo\n"
110 "Args:\n"
111 " - Callee: bar\n"
112 " - String: ' will not be inlined into '\n"
113 " - Caller: foo\n"
114 " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n"
115 " - String: ' because its definition is unavailable'\n"
116 "");
118 // No args is also ok.
119 parseGood("\n"
120 "--- !Missed\n"
121 "Pass: inline\n"
122 "Name: NoDefinition\n"
123 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
124 "Function: foo\n"
125 "");
127 // Different order.
128 parseGood("\n"
129 "--- !Missed\n"
130 "DebugLoc: { Line: 3, Column: 12, File: file.c }\n"
131 "Function: foo\n"
132 "Name: NoDefinition\n"
133 "Args:\n"
134 " - Callee: bar\n"
135 " - String: ' will not be inlined into '\n"
136 " - Caller: foo\n"
137 " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n"
138 " - String: ' because its definition is unavailable'\n"
139 "Pass: inline\n"
140 "");
143 // Mandatory common part of a remark.
144 #define COMMON_REMARK "\nPass: inline\nName: NoDefinition\nFunction: foo\n\n"
145 // Test all the types.
146 TEST(YAMLRemarks, ParsingTypes) {
147 // Type: Passed
148 parseGood("--- !Passed" COMMON_REMARK);
149 // Type: Missed
150 parseGood("--- !Missed" COMMON_REMARK);
151 // Type: Analysis
152 parseGood("--- !Analysis" COMMON_REMARK);
153 // Type: AnalysisFPCommute
154 parseGood("--- !AnalysisFPCommute" COMMON_REMARK);
155 // Type: AnalysisAliasing
156 parseGood("--- !AnalysisAliasing" COMMON_REMARK);
157 // Type: Failure
158 parseGood("--- !Failure" COMMON_REMARK);
160 #undef COMMON_REMARK
162 TEST(YAMLRemarks, ParsingMissingFields) {
163 // No type.
164 EXPECT_TRUE(parseExpectError("\n"
165 "---\n"
166 "Pass: inline\n"
167 "Name: NoDefinition\n"
168 "Function: foo\n"
170 "expected a remark tag."));
171 // No pass.
172 EXPECT_TRUE(parseExpectError("\n"
173 "--- !Missed\n"
174 "Name: NoDefinition\n"
175 "Function: foo\n"
177 "Type, Pass, Name or Function missing."));
178 // No name.
179 EXPECT_TRUE(parseExpectError("\n"
180 "--- !Missed\n"
181 "Pass: inline\n"
182 "Function: foo\n"
184 "Type, Pass, Name or Function missing."));
185 // No function.
186 EXPECT_TRUE(parseExpectError("\n"
187 "--- !Missed\n"
188 "Pass: inline\n"
189 "Name: NoDefinition\n"
191 "Type, Pass, Name or Function missing."));
192 // Debug loc but no file.
193 EXPECT_TRUE(parseExpectError("\n"
194 "--- !Missed\n"
195 "Pass: inline\n"
196 "Name: NoDefinition\n"
197 "Function: foo\n"
198 "DebugLoc: { Line: 3, Column: 12 }\n"
200 "DebugLoc node incomplete."));
201 // Debug loc but no line.
202 EXPECT_TRUE(parseExpectError("\n"
203 "--- !Missed\n"
204 "Pass: inline\n"
205 "Name: NoDefinition\n"
206 "Function: foo\n"
207 "DebugLoc: { File: file.c, Column: 12 }\n"
209 "DebugLoc node incomplete."));
210 // Debug loc but no column.
211 EXPECT_TRUE(parseExpectError("\n"
212 "--- !Missed\n"
213 "Pass: inline\n"
214 "Name: NoDefinition\n"
215 "Function: foo\n"
216 "DebugLoc: { File: file.c, Line: 3 }\n"
218 "DebugLoc node incomplete."));
221 TEST(YAMLRemarks, ParsingWrongTypes) {
222 // Wrong debug loc type.
223 EXPECT_TRUE(parseExpectError("\n"
224 "--- !Missed\n"
225 "Pass: inline\n"
226 "Name: NoDefinition\n"
227 "Function: foo\n"
228 "DebugLoc: foo\n"
230 "expected a value of mapping type."));
231 // Wrong line type.
232 EXPECT_TRUE(parseExpectError("\n"
233 "--- !Missed\n"
234 "Pass: inline\n"
235 "Name: NoDefinition\n"
236 "Function: foo\n"
237 "DebugLoc: { File: file.c, Line: b, Column: 12 }\n"
239 "expected a value of integer type."));
240 // Wrong column type.
241 EXPECT_TRUE(parseExpectError("\n"
242 "--- !Missed\n"
243 "Pass: inline\n"
244 "Name: NoDefinition\n"
245 "Function: foo\n"
246 "DebugLoc: { File: file.c, Line: 3, Column: c }\n"
248 "expected a value of integer type."));
249 // Wrong args type.
250 EXPECT_TRUE(parseExpectError("\n"
251 "--- !Missed\n"
252 "Pass: inline\n"
253 "Name: NoDefinition\n"
254 "Function: foo\n"
255 "Args: foo\n"
257 "wrong value type for key."));
258 // Wrong key type.
259 EXPECT_TRUE(parseExpectError("\n"
260 "--- !Missed\n"
261 "{ A: a }: inline\n"
262 "Name: NoDefinition\n"
263 "Function: foo\n"
265 "key is not a string."));
266 // Debug loc with unknown entry.
267 EXPECT_TRUE(parseExpectError("\n"
268 "--- !Missed\n"
269 "Pass: inline\n"
270 "Name: NoDefinition\n"
271 "Function: foo\n"
272 "DebugLoc: { File: file.c, Column: 12, Unknown: 12 }\n"
274 "unknown entry in DebugLoc map."));
275 // Unknown entry.
276 EXPECT_TRUE(parseExpectError("\n"
277 "--- !Missed\n"
278 "Unknown: inline\n"
280 "unknown key."));
281 // Not a scalar.
282 EXPECT_TRUE(parseExpectError("\n"
283 "--- !Missed\n"
284 "Pass: { File: a, Line: 1, Column: 2 }\n"
285 "Name: NoDefinition\n"
286 "Function: foo\n"
288 "expected a value of scalar type."));
289 // Not a string file in debug loc.
290 EXPECT_TRUE(parseExpectError("\n"
291 "--- !Missed\n"
292 "Pass: inline\n"
293 "Name: NoDefinition\n"
294 "Function: foo\n"
295 "DebugLoc: { File: { a: b }, Column: 12, Line: 12 }\n"
297 "expected a value of scalar type."));
298 // Not a integer column in debug loc.
299 EXPECT_TRUE(parseExpectError("\n"
300 "--- !Missed\n"
301 "Pass: inline\n"
302 "Name: NoDefinition\n"
303 "Function: foo\n"
304 "DebugLoc: { File: file.c, Column: { a: b }, Line: 12 }\n"
306 "expected a value of scalar type."));
307 // Not a integer line in debug loc.
308 EXPECT_TRUE(parseExpectError("\n"
309 "--- !Missed\n"
310 "Pass: inline\n"
311 "Name: NoDefinition\n"
312 "Function: foo\n"
313 "DebugLoc: { File: file.c, Column: 12, Line: { a: b } }\n"
315 "expected a value of scalar type."));
316 // Not a mapping type value for args.
317 EXPECT_TRUE(parseExpectError("\n"
318 "--- !Missed\n"
319 "Pass: inline\n"
320 "Name: NoDefinition\n"
321 "Function: foo\n"
322 "DebugLoc: { File: file.c, Column: 12, Line: { a: b } }\n"
324 "expected a value of scalar type."));
327 TEST(YAMLRemarks, ParsingWrongArgs) {
328 // Multiple debug locs per arg.
329 EXPECT_TRUE(parseExpectError("\n"
330 "--- !Missed\n"
331 "Pass: inline\n"
332 "Name: NoDefinition\n"
333 "Function: foo\n"
334 "Args:\n"
335 " - Str: string\n"
336 " DebugLoc: { File: a, Line: 1, Column: 2 }\n"
337 " DebugLoc: { File: a, Line: 1, Column: 2 }\n"
339 "only one DebugLoc entry is allowed per argument."));
340 // Multiple strings per arg.
341 EXPECT_TRUE(parseExpectError("\n"
342 "--- !Missed\n"
343 "Pass: inline\n"
344 "Name: NoDefinition\n"
345 "Function: foo\n"
346 "Args:\n"
347 " - Str: string\n"
348 " Str2: string\n"
349 " DebugLoc: { File: a, Line: 1, Column: 2 }\n"
351 "only one string entry is allowed per argument."));
352 // No arg value.
353 EXPECT_TRUE(parseExpectError("\n"
354 "--- !Missed\n"
355 "Pass: inline\n"
356 "Name: NoDefinition\n"
357 "Function: foo\n"
358 "Args:\n"
359 " - DebugLoc: { File: a, Line: 1, Column: 2 }\n"
361 "argument key is missing."));
364 static inline StringRef checkStr(StringRef Str, unsigned ExpectedLen) {
365 const char *StrData = Str.data();
366 unsigned StrLen = Str.size();
367 EXPECT_EQ(StrLen, ExpectedLen);
368 return StringRef(StrData, StrLen);
371 TEST(YAMLRemarks, Contents) {
372 StringRef Buf = "\n"
373 "--- !Missed\n"
374 "Pass: inline\n"
375 "Name: NoDefinition\n"
376 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
377 "Function: foo\n"
378 "Hotness: 4\n"
379 "Args:\n"
380 " - Callee: bar\n"
381 " - String: ' will not be inlined into '\n"
382 " - Caller: foo\n"
383 " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n"
384 " - String: ' because its definition is unavailable'\n"
385 "\n";
387 Expected<std::unique_ptr<remarks::RemarkParser>> MaybeParser =
388 remarks::createRemarkParser(remarks::Format::YAML, Buf);
389 EXPECT_FALSE(errorToBool(MaybeParser.takeError()));
390 EXPECT_TRUE(*MaybeParser != nullptr);
392 remarks::RemarkParser &Parser = **MaybeParser;
393 Expected<std::unique_ptr<remarks::Remark>> MaybeRemark = Parser.next();
394 EXPECT_FALSE(
395 errorToBool(MaybeRemark.takeError())); // Check for parsing errors.
396 EXPECT_TRUE(*MaybeRemark != nullptr); // At least one remark.
398 const remarks::Remark &Remark = **MaybeRemark;
399 EXPECT_EQ(Remark.RemarkType, remarks::Type::Missed);
400 EXPECT_EQ(checkStr(Remark.PassName, 6), "inline");
401 EXPECT_EQ(checkStr(Remark.RemarkName, 12), "NoDefinition");
402 EXPECT_EQ(checkStr(Remark.FunctionName, 3), "foo");
403 EXPECT_TRUE(Remark.Loc);
404 const remarks::RemarkLocation &RL = *Remark.Loc;
405 EXPECT_EQ(checkStr(RL.SourceFilePath, 6), "file.c");
406 EXPECT_EQ(RL.SourceLine, 3U);
407 EXPECT_EQ(RL.SourceColumn, 12U);
408 EXPECT_TRUE(Remark.Hotness);
409 EXPECT_EQ(*Remark.Hotness, 4U);
410 EXPECT_EQ(Remark.Args.size(), 4U);
412 unsigned ArgID = 0;
413 for (const remarks::Argument &Arg : Remark.Args) {
414 switch (ArgID) {
415 case 0:
416 EXPECT_EQ(checkStr(Arg.Key, 6), "Callee");
417 EXPECT_EQ(checkStr(Arg.Val, 3), "bar");
418 EXPECT_FALSE(Arg.Loc);
419 break;
420 case 1:
421 EXPECT_EQ(checkStr(Arg.Key, 6), "String");
422 EXPECT_EQ(checkStr(Arg.Val, 26), " will not be inlined into ");
423 EXPECT_FALSE(Arg.Loc);
424 break;
425 case 2: {
426 EXPECT_EQ(checkStr(Arg.Key, 6), "Caller");
427 EXPECT_EQ(checkStr(Arg.Val, 3), "foo");
428 EXPECT_TRUE(Arg.Loc);
429 const remarks::RemarkLocation &RL = *Arg.Loc;
430 EXPECT_EQ(checkStr(RL.SourceFilePath, 6), "file.c");
431 EXPECT_EQ(RL.SourceLine, 2U);
432 EXPECT_EQ(RL.SourceColumn, 0U);
433 break;
435 case 3:
436 EXPECT_EQ(checkStr(Arg.Key, 6), "String");
437 EXPECT_EQ(checkStr(Arg.Val, 38),
438 " because its definition is unavailable");
439 EXPECT_FALSE(Arg.Loc);
440 break;
441 default:
442 break;
444 ++ArgID;
447 MaybeRemark = Parser.next();
448 Error E = MaybeRemark.takeError();
449 EXPECT_TRUE(E.isA<remarks::EndOfFileError>());
450 EXPECT_TRUE(errorToBool(std::move(E))); // Check for parsing errors.
453 static inline StringRef checkStr(LLVMRemarkStringRef Str,
454 unsigned ExpectedLen) {
455 const char *StrData = LLVMRemarkStringGetData(Str);
456 unsigned StrLen = LLVMRemarkStringGetLen(Str);
457 EXPECT_EQ(StrLen, ExpectedLen);
458 return StringRef(StrData, StrLen);
461 TEST(YAMLRemarks, ContentsCAPI) {
462 StringRef Buf = "\n"
463 "--- !Missed\n"
464 "Pass: inline\n"
465 "Name: NoDefinition\n"
466 "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
467 "Function: foo\n"
468 "Args:\n"
469 " - Callee: bar\n"
470 " - String: ' will not be inlined into '\n"
471 " - Caller: foo\n"
472 " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n"
473 " - String: ' because its definition is unavailable'\n"
474 "\n";
476 LLVMRemarkParserRef Parser =
477 LLVMRemarkParserCreateYAML(Buf.data(), Buf.size());
478 LLVMRemarkEntryRef Remark = LLVMRemarkParserGetNext(Parser);
479 EXPECT_FALSE(Remark == nullptr);
480 EXPECT_EQ(LLVMRemarkEntryGetType(Remark), LLVMRemarkTypeMissed);
481 EXPECT_EQ(checkStr(LLVMRemarkEntryGetPassName(Remark), 6), "inline");
482 EXPECT_EQ(checkStr(LLVMRemarkEntryGetRemarkName(Remark), 12), "NoDefinition");
483 EXPECT_EQ(checkStr(LLVMRemarkEntryGetFunctionName(Remark), 3), "foo");
484 LLVMRemarkDebugLocRef DL = LLVMRemarkEntryGetDebugLoc(Remark);
485 EXPECT_EQ(checkStr(LLVMRemarkDebugLocGetSourceFilePath(DL), 6), "file.c");
486 EXPECT_EQ(LLVMRemarkDebugLocGetSourceLine(DL), 3U);
487 EXPECT_EQ(LLVMRemarkDebugLocGetSourceColumn(DL), 12U);
488 EXPECT_EQ(LLVMRemarkEntryGetHotness(Remark), 0U);
489 EXPECT_EQ(LLVMRemarkEntryGetNumArgs(Remark), 4U);
491 unsigned ArgID = 0;
492 LLVMRemarkArgRef Arg = LLVMRemarkEntryGetFirstArg(Remark);
493 do {
494 switch (ArgID) {
495 case 0:
496 EXPECT_EQ(checkStr(LLVMRemarkArgGetKey(Arg), 6), "Callee");
497 EXPECT_EQ(checkStr(LLVMRemarkArgGetValue(Arg), 3), "bar");
498 EXPECT_EQ(LLVMRemarkArgGetDebugLoc(Arg), nullptr);
499 break;
500 case 1:
501 EXPECT_EQ(checkStr(LLVMRemarkArgGetKey(Arg), 6), "String");
502 EXPECT_EQ(checkStr(LLVMRemarkArgGetValue(Arg), 26),
503 " will not be inlined into ");
504 EXPECT_EQ(LLVMRemarkArgGetDebugLoc(Arg), nullptr);
505 break;
506 case 2: {
507 EXPECT_EQ(checkStr(LLVMRemarkArgGetKey(Arg), 6), "Caller");
508 EXPECT_EQ(checkStr(LLVMRemarkArgGetValue(Arg), 3), "foo");
509 LLVMRemarkDebugLocRef DL = LLVMRemarkArgGetDebugLoc(Arg);
510 EXPECT_EQ(checkStr(LLVMRemarkDebugLocGetSourceFilePath(DL), 6), "file.c");
511 EXPECT_EQ(LLVMRemarkDebugLocGetSourceLine(DL), 2U);
512 EXPECT_EQ(LLVMRemarkDebugLocGetSourceColumn(DL), 0U);
513 break;
515 case 3:
516 EXPECT_EQ(checkStr(LLVMRemarkArgGetKey(Arg), 6), "String");
517 EXPECT_EQ(checkStr(LLVMRemarkArgGetValue(Arg), 38),
518 " because its definition is unavailable");
519 EXPECT_EQ(LLVMRemarkArgGetDebugLoc(Arg), nullptr);
520 break;
521 default:
522 break;
524 ++ArgID;
525 } while ((Arg = LLVMRemarkEntryGetNextArg(Arg, Remark)));
527 LLVMRemarkEntryDispose(Remark);
529 EXPECT_EQ(LLVMRemarkParserGetNext(Parser), nullptr);
531 EXPECT_FALSE(LLVMRemarkParserHasError(Parser));
532 LLVMRemarkParserDispose(Parser);
535 TEST(YAMLRemarks, ContentsStrTab) {
536 StringRef Buf = "\n"
537 "--- !Missed\n"
538 "Pass: 0\n"
539 "Name: 1\n"
540 "DebugLoc: { File: 2, Line: 3, Column: 12 }\n"
541 "Function: 3\n"
542 "Hotness: 4\n"
543 "Args:\n"
544 " - Callee: 5\n"
545 " - String: 7\n"
546 " - Caller: 3\n"
547 " DebugLoc: { File: 2, Line: 2, Column: 0 }\n"
548 " - String: 8\n"
549 "\n";
551 StringRef StrTabBuf =
552 StringRef("inline\0NoDefinition\0file.c\0foo\0Callee\0bar\0String\0 "
553 "will not be inlined into \0 because its definition is "
554 "unavailable",
555 115);
557 remarks::ParsedStringTable StrTab(StrTabBuf);
558 Expected<std::unique_ptr<remarks::RemarkParser>> MaybeParser =
559 remarks::createRemarkParser(remarks::Format::YAMLStrTab, Buf,
560 std::move(StrTab));
561 EXPECT_FALSE(errorToBool(MaybeParser.takeError()));
562 EXPECT_TRUE(*MaybeParser != nullptr);
564 remarks::RemarkParser &Parser = **MaybeParser;
565 Expected<std::unique_ptr<remarks::Remark>> MaybeRemark = Parser.next();
566 EXPECT_FALSE(
567 errorToBool(MaybeRemark.takeError())); // Check for parsing errors.
568 EXPECT_TRUE(*MaybeRemark != nullptr); // At least one remark.
570 const remarks::Remark &Remark = **MaybeRemark;
571 EXPECT_EQ(Remark.RemarkType, remarks::Type::Missed);
572 EXPECT_EQ(checkStr(Remark.PassName, 6), "inline");
573 EXPECT_EQ(checkStr(Remark.RemarkName, 12), "NoDefinition");
574 EXPECT_EQ(checkStr(Remark.FunctionName, 3), "foo");
575 EXPECT_TRUE(Remark.Loc);
576 const remarks::RemarkLocation &RL = *Remark.Loc;
577 EXPECT_EQ(checkStr(RL.SourceFilePath, 6), "file.c");
578 EXPECT_EQ(RL.SourceLine, 3U);
579 EXPECT_EQ(RL.SourceColumn, 12U);
580 EXPECT_TRUE(Remark.Hotness);
581 EXPECT_EQ(*Remark.Hotness, 4U);
582 EXPECT_EQ(Remark.Args.size(), 4U);
584 unsigned ArgID = 0;
585 for (const remarks::Argument &Arg : Remark.Args) {
586 switch (ArgID) {
587 case 0:
588 EXPECT_EQ(checkStr(Arg.Key, 6), "Callee");
589 EXPECT_EQ(checkStr(Arg.Val, 3), "bar");
590 EXPECT_FALSE(Arg.Loc);
591 break;
592 case 1:
593 EXPECT_EQ(checkStr(Arg.Key, 6), "String");
594 EXPECT_EQ(checkStr(Arg.Val, 26), " will not be inlined into ");
595 EXPECT_FALSE(Arg.Loc);
596 break;
597 case 2: {
598 EXPECT_EQ(checkStr(Arg.Key, 6), "Caller");
599 EXPECT_EQ(checkStr(Arg.Val, 3), "foo");
600 EXPECT_TRUE(Arg.Loc);
601 const remarks::RemarkLocation &RL = *Arg.Loc;
602 EXPECT_EQ(checkStr(RL.SourceFilePath, 6), "file.c");
603 EXPECT_EQ(RL.SourceLine, 2U);
604 EXPECT_EQ(RL.SourceColumn, 0U);
605 break;
607 case 3:
608 EXPECT_EQ(checkStr(Arg.Key, 6), "String");
609 EXPECT_EQ(checkStr(Arg.Val, 38),
610 " because its definition is unavailable");
611 EXPECT_FALSE(Arg.Loc);
612 break;
613 default:
614 break;
616 ++ArgID;
619 MaybeRemark = Parser.next();
620 Error E = MaybeRemark.takeError();
621 EXPECT_TRUE(E.isA<remarks::EndOfFileError>());
622 EXPECT_TRUE(errorToBool(std::move(E))); // Check for parsing errors.
625 TEST(YAMLRemarks, ParsingBadStringTableIndex) {
626 StringRef Buf = "\n"
627 "--- !Missed\n"
628 "Pass: 50\n"
629 "\n";
631 StringRef StrTabBuf = StringRef("inline");
633 remarks::ParsedStringTable StrTab(StrTabBuf);
634 Expected<std::unique_ptr<remarks::RemarkParser>> MaybeParser =
635 remarks::createRemarkParser(remarks::Format::YAMLStrTab, Buf,
636 std::move(StrTab));
637 EXPECT_FALSE(errorToBool(MaybeParser.takeError()));
638 EXPECT_TRUE(*MaybeParser != nullptr);
640 remarks::RemarkParser &Parser = **MaybeParser;
641 Expected<std::unique_ptr<remarks::Remark>> MaybeRemark = Parser.next();
642 EXPECT_FALSE(MaybeRemark); // Expect an error here.
644 std::string ErrorStr;
645 raw_string_ostream Stream(ErrorStr);
646 handleAllErrors(MaybeRemark.takeError(),
647 [&](const ErrorInfoBase &EIB) { EIB.log(Stream); });
648 EXPECT_TRUE(
649 StringRef(Stream.str())
650 .contains("String with index 50 is out of bounds (size = 1)."));
653 TEST(YAMLRemarks, ParsingGoodMeta) {
654 // No metadata should also work.
655 parseGoodMeta("--- !Missed\n"
656 "Pass: inline\n"
657 "Name: NoDefinition\n"
658 "Function: foo\n");
660 // No string table.
661 parseGoodMeta(StringRef("REMARKS\0"
662 "\0\0\0\0\0\0\0\0"
663 "\0\0\0\0\0\0\0\0"
664 "--- !Missed\n"
665 "Pass: inline\n"
666 "Name: NoDefinition\n"
667 "Function: foo\n",
668 82));
670 // Use the string table from the metadata.
671 parseGoodMeta(StringRef("REMARKS\0"
672 "\0\0\0\0\0\0\0\0"
673 "\x02\0\0\0\0\0\0\0"
674 "a\0"
675 "--- !Missed\n"
676 "Pass: 0\n"
677 "Name: 0\n"
678 "Function: 0\n",
679 66));
682 TEST(YAMLRemarks, ParsingBadMeta) {
683 parseExpectErrorMeta(StringRef("REMARKSS", 9),
684 "Expecting \\0 after magic number.");
686 parseExpectErrorMeta(StringRef("REMARKS\0", 8), "Expecting version number.");
688 parseExpectErrorMeta(StringRef("REMARKS\0"
689 "\x09\0\0\0\0\0\0\0",
690 16),
691 "Mismatching remark version. Got 9, expected 0.");
693 parseExpectErrorMeta(StringRef("REMARKS\0"
694 "\0\0\0\0\0\0\0\0",
695 16),
696 "Expecting string table size.");
698 parseExpectErrorMeta(StringRef("REMARKS\0"
699 "\0\0\0\0\0\0\0\0"
700 "\x01\0\0\0\0\0\0\0",
701 24),
702 "Expecting string table.");
704 parseExpectErrorMeta(StringRef("REMARKS\0"
705 "\0\0\0\0\0\0\0\0"
706 "\0\0\0\0\0\0\0\0"
707 "/path/",
708 28),
709 "No such file or directory");