//===- unittest/Support/YAMLRemarksParsingTest.cpp - OptTable tests -------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm-c/Remarks.h" #include "llvm/Remarks/Remark.h" #include "llvm/Remarks/RemarkParser.h" #include "gtest/gtest.h" using namespace llvm; template void parseGood(const char (&Buf)[N]) { Expected> MaybeParser = remarks::createRemarkParser(remarks::Format::YAML, {Buf, N - 1}); EXPECT_FALSE(errorToBool(MaybeParser.takeError())); EXPECT_TRUE(*MaybeParser != nullptr); remarks::RemarkParser &Parser = **MaybeParser; Expected> Remark = Parser.next(); EXPECT_FALSE(errorToBool(Remark.takeError())); // Check for parsing errors. EXPECT_TRUE(*Remark != nullptr); // At least one remark. Remark = Parser.next(); Error E = Remark.takeError(); EXPECT_TRUE(E.isA()); EXPECT_TRUE(errorToBool(std::move(E))); // Check for parsing errors. } void parseGoodMeta(StringRef Buf) { Expected> MaybeParser = remarks::createRemarkParserFromMeta(remarks::Format::YAML, Buf); EXPECT_FALSE(errorToBool(MaybeParser.takeError())); EXPECT_TRUE(*MaybeParser != nullptr); remarks::RemarkParser &Parser = **MaybeParser; Expected> Remark = Parser.next(); EXPECT_FALSE(errorToBool(Remark.takeError())); // Check for parsing errors. EXPECT_TRUE(*Remark != nullptr); // At least one remark. Remark = Parser.next(); Error E = Remark.takeError(); EXPECT_TRUE(E.isA()); EXPECT_TRUE(errorToBool(std::move(E))); // Check for parsing errors. } template bool parseExpectError(const char (&Buf)[N], const char *Error) { Expected> MaybeParser = remarks::createRemarkParser(remarks::Format::YAML, {Buf, N - 1}); EXPECT_FALSE(errorToBool(MaybeParser.takeError())); EXPECT_TRUE(*MaybeParser != nullptr); remarks::RemarkParser &Parser = **MaybeParser; Expected> Remark = Parser.next(); EXPECT_FALSE(Remark); // Check for parsing errors. std::string ErrorStr; raw_string_ostream Stream(ErrorStr); handleAllErrors(Remark.takeError(), [&](const ErrorInfoBase &EIB) { EIB.log(Stream); }); return StringRef(Stream.str()).contains(Error); } enum class CmpType { Equal, Contains }; void parseExpectErrorMeta(StringRef Buf, const char *Error, CmpType Cmp, Optional ExternalFilePrependPath = None) { std::string ErrorStr; raw_string_ostream Stream(ErrorStr); Expected> MaybeParser = remarks::createRemarkParserFromMeta(remarks::Format::YAML, Buf, /*StrTab=*/None, std::move(ExternalFilePrependPath)); handleAllErrors(MaybeParser.takeError(), [&](const ErrorInfoBase &EIB) { EIB.log(Stream); }); // Use a case insensitive comparision due to case differences in error strings // for different OSs. if (Cmp == CmpType::Equal) { EXPECT_EQ(StringRef(Stream.str()).lower(), StringRef(Error).lower()); } if (Cmp == CmpType::Contains) { EXPECT_TRUE(StringRef(Stream.str()).contains(StringRef(Error))); } } TEST(YAMLRemarks, ParsingEmpty) { EXPECT_TRUE(parseExpectError("\n\n", "document root is not of mapping type.")); } TEST(YAMLRemarks, ParsingNotYAML) { EXPECT_TRUE( parseExpectError("\x01\x02\x03\x04\x05\x06", "Got empty plain scalar")); } TEST(YAMLRemarks, ParsingGood) { parseGood("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n" "Function: foo\n" "Args:\n" " - Callee: bar\n" " - String: ' will not be inlined into '\n" " - Caller: foo\n" " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n" " - String: ' because its definition is unavailable'\n" ""); // No debug loc should also pass. parseGood("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "Args:\n" " - Callee: bar\n" " - String: ' will not be inlined into '\n" " - Caller: foo\n" " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n" " - String: ' because its definition is unavailable'\n" ""); // No args is also ok. parseGood("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n" "Function: foo\n" ""); // Different order. parseGood("\n" "--- !Missed\n" "DebugLoc: { Line: 3, Column: 12, File: file.c }\n" "Function: foo\n" "Name: NoDefinition\n" "Args:\n" " - Callee: bar\n" " - String: ' will not be inlined into '\n" " - Caller: foo\n" " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n" " - String: ' because its definition is unavailable'\n" "Pass: inline\n" ""); } // Mandatory common part of a remark. #define COMMON_REMARK "\nPass: inline\nName: NoDefinition\nFunction: foo\n\n" // Test all the types. TEST(YAMLRemarks, ParsingTypes) { // Type: Passed parseGood("--- !Passed" COMMON_REMARK); // Type: Missed parseGood("--- !Missed" COMMON_REMARK); // Type: Analysis parseGood("--- !Analysis" COMMON_REMARK); // Type: AnalysisFPCommute parseGood("--- !AnalysisFPCommute" COMMON_REMARK); // Type: AnalysisAliasing parseGood("--- !AnalysisAliasing" COMMON_REMARK); // Type: Failure parseGood("--- !Failure" COMMON_REMARK); } #undef COMMON_REMARK TEST(YAMLRemarks, ParsingMissingFields) { // No type. EXPECT_TRUE(parseExpectError("\n" "---\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "", "expected a remark tag.")); // No pass. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Name: NoDefinition\n" "Function: foo\n" "", "Type, Pass, Name or Function missing.")); // No name. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Function: foo\n" "", "Type, Pass, Name or Function missing.")); // No function. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "", "Type, Pass, Name or Function missing.")); // Debug loc but no file. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { Line: 3, Column: 12 }\n" "", "DebugLoc node incomplete.")); // Debug loc but no line. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { File: file.c, Column: 12 }\n" "", "DebugLoc node incomplete.")); // Debug loc but no column. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { File: file.c, Line: 3 }\n" "", "DebugLoc node incomplete.")); } TEST(YAMLRemarks, ParsingWrongTypes) { // Wrong debug loc type. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: foo\n" "", "expected a value of mapping type.")); // Wrong line type. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { File: file.c, Line: b, Column: 12 }\n" "", "expected a value of integer type.")); // Wrong column type. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { File: file.c, Line: 3, Column: c }\n" "", "expected a value of integer type.")); // Wrong args type. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "Args: foo\n" "", "wrong value type for key.")); // Wrong key type. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "{ A: a }: inline\n" "Name: NoDefinition\n" "Function: foo\n" "", "key is not a string.")); // Debug loc with unknown entry. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { File: file.c, Column: 12, Unknown: 12 }\n" "", "unknown entry in DebugLoc map.")); // Unknown entry. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Unknown: inline\n" "", "unknown key.")); // Not a scalar. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: { File: a, Line: 1, Column: 2 }\n" "Name: NoDefinition\n" "Function: foo\n" "", "expected a value of scalar type.")); // Not a string file in debug loc. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { File: { a: b }, Column: 12, Line: 12 }\n" "", "expected a value of scalar type.")); // Not a integer column in debug loc. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { File: file.c, Column: { a: b }, Line: 12 }\n" "", "expected a value of scalar type.")); // Not a integer line in debug loc. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { File: file.c, Column: 12, Line: { a: b } }\n" "", "expected a value of scalar type.")); // Not a mapping type value for args. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "DebugLoc: { File: file.c, Column: 12, Line: { a: b } }\n" "", "expected a value of scalar type.")); } TEST(YAMLRemarks, ParsingWrongArgs) { // Multiple debug locs per arg. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "Args:\n" " - Str: string\n" " DebugLoc: { File: a, Line: 1, Column: 2 }\n" " DebugLoc: { File: a, Line: 1, Column: 2 }\n" "", "only one DebugLoc entry is allowed per argument.")); // Multiple strings per arg. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "Args:\n" " - Str: string\n" " Str2: string\n" " DebugLoc: { File: a, Line: 1, Column: 2 }\n" "", "only one string entry is allowed per argument.")); // No arg value. EXPECT_TRUE(parseExpectError("\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n" "Args:\n" " - DebugLoc: { File: a, Line: 1, Column: 2 }\n" "", "argument key is missing.")); } static inline StringRef checkStr(StringRef Str, unsigned ExpectedLen) { const char *StrData = Str.data(); unsigned StrLen = Str.size(); EXPECT_EQ(StrLen, ExpectedLen); return StringRef(StrData, StrLen); } TEST(YAMLRemarks, Contents) { StringRef Buf = "\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n" "Function: foo\n" "Hotness: 4\n" "Args:\n" " - Callee: bar\n" " - String: ' will not be inlined into '\n" " - Caller: foo\n" " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n" " - String: ' because its definition is unavailable'\n" "\n"; Expected> MaybeParser = remarks::createRemarkParser(remarks::Format::YAML, Buf); EXPECT_FALSE(errorToBool(MaybeParser.takeError())); EXPECT_TRUE(*MaybeParser != nullptr); remarks::RemarkParser &Parser = **MaybeParser; Expected> MaybeRemark = Parser.next(); EXPECT_FALSE( errorToBool(MaybeRemark.takeError())); // Check for parsing errors. EXPECT_TRUE(*MaybeRemark != nullptr); // At least one remark. const remarks::Remark &Remark = **MaybeRemark; EXPECT_EQ(Remark.RemarkType, remarks::Type::Missed); EXPECT_EQ(checkStr(Remark.PassName, 6), "inline"); EXPECT_EQ(checkStr(Remark.RemarkName, 12), "NoDefinition"); EXPECT_EQ(checkStr(Remark.FunctionName, 3), "foo"); EXPECT_TRUE(Remark.Loc); const remarks::RemarkLocation &RL = *Remark.Loc; EXPECT_EQ(checkStr(RL.SourceFilePath, 6), "file.c"); EXPECT_EQ(RL.SourceLine, 3U); EXPECT_EQ(RL.SourceColumn, 12U); EXPECT_TRUE(Remark.Hotness); EXPECT_EQ(*Remark.Hotness, 4U); EXPECT_EQ(Remark.Args.size(), 4U); unsigned ArgID = 0; for (const remarks::Argument &Arg : Remark.Args) { switch (ArgID) { case 0: EXPECT_EQ(checkStr(Arg.Key, 6), "Callee"); EXPECT_EQ(checkStr(Arg.Val, 3), "bar"); EXPECT_FALSE(Arg.Loc); break; case 1: EXPECT_EQ(checkStr(Arg.Key, 6), "String"); EXPECT_EQ(checkStr(Arg.Val, 26), " will not be inlined into "); EXPECT_FALSE(Arg.Loc); break; case 2: { EXPECT_EQ(checkStr(Arg.Key, 6), "Caller"); EXPECT_EQ(checkStr(Arg.Val, 3), "foo"); EXPECT_TRUE(Arg.Loc); const remarks::RemarkLocation &RL = *Arg.Loc; EXPECT_EQ(checkStr(RL.SourceFilePath, 6), "file.c"); EXPECT_EQ(RL.SourceLine, 2U); EXPECT_EQ(RL.SourceColumn, 0U); break; } case 3: EXPECT_EQ(checkStr(Arg.Key, 6), "String"); EXPECT_EQ(checkStr(Arg.Val, 38), " because its definition is unavailable"); EXPECT_FALSE(Arg.Loc); break; default: break; } ++ArgID; } MaybeRemark = Parser.next(); Error E = MaybeRemark.takeError(); EXPECT_TRUE(E.isA()); EXPECT_TRUE(errorToBool(std::move(E))); // Check for parsing errors. } static inline StringRef checkStr(LLVMRemarkStringRef Str, unsigned ExpectedLen) { const char *StrData = LLVMRemarkStringGetData(Str); unsigned StrLen = LLVMRemarkStringGetLen(Str); EXPECT_EQ(StrLen, ExpectedLen); return StringRef(StrData, StrLen); } TEST(YAMLRemarks, ContentsCAPI) { StringRef Buf = "\n" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "DebugLoc: { File: file.c, Line: 3, Column: 12 }\n" "Function: foo\n" "Args:\n" " - Callee: bar\n" " - String: ' will not be inlined into '\n" " - Caller: foo\n" " DebugLoc: { File: file.c, Line: 2, Column: 0 }\n" " - String: ' because its definition is unavailable'\n" "\n"; LLVMRemarkParserRef Parser = LLVMRemarkParserCreateYAML(Buf.data(), Buf.size()); LLVMRemarkEntryRef Remark = LLVMRemarkParserGetNext(Parser); EXPECT_FALSE(Remark == nullptr); EXPECT_EQ(LLVMRemarkEntryGetType(Remark), LLVMRemarkTypeMissed); EXPECT_EQ(checkStr(LLVMRemarkEntryGetPassName(Remark), 6), "inline"); EXPECT_EQ(checkStr(LLVMRemarkEntryGetRemarkName(Remark), 12), "NoDefinition"); EXPECT_EQ(checkStr(LLVMRemarkEntryGetFunctionName(Remark), 3), "foo"); LLVMRemarkDebugLocRef DL = LLVMRemarkEntryGetDebugLoc(Remark); EXPECT_EQ(checkStr(LLVMRemarkDebugLocGetSourceFilePath(DL), 6), "file.c"); EXPECT_EQ(LLVMRemarkDebugLocGetSourceLine(DL), 3U); EXPECT_EQ(LLVMRemarkDebugLocGetSourceColumn(DL), 12U); EXPECT_EQ(LLVMRemarkEntryGetHotness(Remark), 0U); EXPECT_EQ(LLVMRemarkEntryGetNumArgs(Remark), 4U); unsigned ArgID = 0; LLVMRemarkArgRef Arg = LLVMRemarkEntryGetFirstArg(Remark); do { switch (ArgID) { case 0: EXPECT_EQ(checkStr(LLVMRemarkArgGetKey(Arg), 6), "Callee"); EXPECT_EQ(checkStr(LLVMRemarkArgGetValue(Arg), 3), "bar"); EXPECT_EQ(LLVMRemarkArgGetDebugLoc(Arg), nullptr); break; case 1: EXPECT_EQ(checkStr(LLVMRemarkArgGetKey(Arg), 6), "String"); EXPECT_EQ(checkStr(LLVMRemarkArgGetValue(Arg), 26), " will not be inlined into "); EXPECT_EQ(LLVMRemarkArgGetDebugLoc(Arg), nullptr); break; case 2: { EXPECT_EQ(checkStr(LLVMRemarkArgGetKey(Arg), 6), "Caller"); EXPECT_EQ(checkStr(LLVMRemarkArgGetValue(Arg), 3), "foo"); LLVMRemarkDebugLocRef DL = LLVMRemarkArgGetDebugLoc(Arg); EXPECT_EQ(checkStr(LLVMRemarkDebugLocGetSourceFilePath(DL), 6), "file.c"); EXPECT_EQ(LLVMRemarkDebugLocGetSourceLine(DL), 2U); EXPECT_EQ(LLVMRemarkDebugLocGetSourceColumn(DL), 0U); break; } case 3: EXPECT_EQ(checkStr(LLVMRemarkArgGetKey(Arg), 6), "String"); EXPECT_EQ(checkStr(LLVMRemarkArgGetValue(Arg), 38), " because its definition is unavailable"); EXPECT_EQ(LLVMRemarkArgGetDebugLoc(Arg), nullptr); break; default: break; } ++ArgID; } while ((Arg = LLVMRemarkEntryGetNextArg(Arg, Remark))); LLVMRemarkEntryDispose(Remark); EXPECT_EQ(LLVMRemarkParserGetNext(Parser), nullptr); EXPECT_FALSE(LLVMRemarkParserHasError(Parser)); LLVMRemarkParserDispose(Parser); } TEST(YAMLRemarks, ContentsStrTab) { StringRef Buf = "\n" "--- !Missed\n" "Pass: 0\n" "Name: 1\n" "DebugLoc: { File: 2, Line: 3, Column: 12 }\n" "Function: 3\n" "Hotness: 4\n" "Args:\n" " - Callee: 5\n" " - String: 7\n" " - Caller: 3\n" " DebugLoc: { File: 2, Line: 2, Column: 0 }\n" " - String: 8\n" "\n"; StringRef StrTabBuf = StringRef("inline\0NoDefinition\0file.c\0foo\0Callee\0bar\0String\0 " "will not be inlined into \0 because its definition is " "unavailable", 115); remarks::ParsedStringTable StrTab(StrTabBuf); Expected> MaybeParser = remarks::createRemarkParser(remarks::Format::YAMLStrTab, Buf, std::move(StrTab)); EXPECT_FALSE(errorToBool(MaybeParser.takeError())); EXPECT_TRUE(*MaybeParser != nullptr); remarks::RemarkParser &Parser = **MaybeParser; Expected> MaybeRemark = Parser.next(); EXPECT_FALSE( errorToBool(MaybeRemark.takeError())); // Check for parsing errors. EXPECT_TRUE(*MaybeRemark != nullptr); // At least one remark. const remarks::Remark &Remark = **MaybeRemark; EXPECT_EQ(Remark.RemarkType, remarks::Type::Missed); EXPECT_EQ(checkStr(Remark.PassName, 6), "inline"); EXPECT_EQ(checkStr(Remark.RemarkName, 12), "NoDefinition"); EXPECT_EQ(checkStr(Remark.FunctionName, 3), "foo"); EXPECT_TRUE(Remark.Loc); const remarks::RemarkLocation &RL = *Remark.Loc; EXPECT_EQ(checkStr(RL.SourceFilePath, 6), "file.c"); EXPECT_EQ(RL.SourceLine, 3U); EXPECT_EQ(RL.SourceColumn, 12U); EXPECT_TRUE(Remark.Hotness); EXPECT_EQ(*Remark.Hotness, 4U); EXPECT_EQ(Remark.Args.size(), 4U); unsigned ArgID = 0; for (const remarks::Argument &Arg : Remark.Args) { switch (ArgID) { case 0: EXPECT_EQ(checkStr(Arg.Key, 6), "Callee"); EXPECT_EQ(checkStr(Arg.Val, 3), "bar"); EXPECT_FALSE(Arg.Loc); break; case 1: EXPECT_EQ(checkStr(Arg.Key, 6), "String"); EXPECT_EQ(checkStr(Arg.Val, 26), " will not be inlined into "); EXPECT_FALSE(Arg.Loc); break; case 2: { EXPECT_EQ(checkStr(Arg.Key, 6), "Caller"); EXPECT_EQ(checkStr(Arg.Val, 3), "foo"); EXPECT_TRUE(Arg.Loc); const remarks::RemarkLocation &RL = *Arg.Loc; EXPECT_EQ(checkStr(RL.SourceFilePath, 6), "file.c"); EXPECT_EQ(RL.SourceLine, 2U); EXPECT_EQ(RL.SourceColumn, 0U); break; } case 3: EXPECT_EQ(checkStr(Arg.Key, 6), "String"); EXPECT_EQ(checkStr(Arg.Val, 38), " because its definition is unavailable"); EXPECT_FALSE(Arg.Loc); break; default: break; } ++ArgID; } MaybeRemark = Parser.next(); Error E = MaybeRemark.takeError(); EXPECT_TRUE(E.isA()); EXPECT_TRUE(errorToBool(std::move(E))); // Check for parsing errors. } TEST(YAMLRemarks, ParsingBadStringTableIndex) { StringRef Buf = "\n" "--- !Missed\n" "Pass: 50\n" "\n"; StringRef StrTabBuf = StringRef("inline"); remarks::ParsedStringTable StrTab(StrTabBuf); Expected> MaybeParser = remarks::createRemarkParser(remarks::Format::YAMLStrTab, Buf, std::move(StrTab)); EXPECT_FALSE(errorToBool(MaybeParser.takeError())); EXPECT_TRUE(*MaybeParser != nullptr); remarks::RemarkParser &Parser = **MaybeParser; Expected> MaybeRemark = Parser.next(); EXPECT_FALSE(MaybeRemark); // Expect an error here. std::string ErrorStr; raw_string_ostream Stream(ErrorStr); handleAllErrors(MaybeRemark.takeError(), [&](const ErrorInfoBase &EIB) { EIB.log(Stream); }); EXPECT_TRUE( StringRef(Stream.str()) .contains("String with index 50 is out of bounds (size = 1).")); } TEST(YAMLRemarks, ParsingGoodMeta) { // No metadata should also work. parseGoodMeta("--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n"); // No string table. parseGoodMeta(StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0" "--- !Missed\n" "Pass: inline\n" "Name: NoDefinition\n" "Function: foo\n", 82)); // Use the string table from the metadata. parseGoodMeta(StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\x02\0\0\0\0\0\0\0" "a\0" "--- !Missed\n" "Pass: 0\n" "Name: 0\n" "Function: 0\n", 66)); } TEST(YAMLRemarks, ParsingBadMeta) { parseExpectErrorMeta(StringRef("REMARKSS", 9), "Expecting \\0 after magic number.", CmpType::Equal); parseExpectErrorMeta(StringRef("REMARKS\0", 8), "Expecting version number.", CmpType::Equal); parseExpectErrorMeta(StringRef("REMARKS\0" "\x09\0\0\0\0\0\0\0", 16), "Mismatching remark version. Got 9, expected 0.", CmpType::Equal); parseExpectErrorMeta(StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0", 16), "Expecting string table size.", CmpType::Equal); parseExpectErrorMeta(StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\x01\0\0\0\0\0\0\0", 24), "Expecting string table.", CmpType::Equal); parseExpectErrorMeta(StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0" "/path/", 30), "'/path/'", CmpType::Contains); parseExpectErrorMeta(StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0" "/path/", 30), "'/baddir/path/'", CmpType::Contains, StringRef("/baddir/")); }