//===- unittest/Support/YAMLRemarksSerializerTest.cpp --------------------===// // // 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/Remarks/Remark.h" #include "llvm/Remarks/RemarkParser.h" #include "llvm/Remarks/YAMLRemarkSerializer.h" #include "llvm/Support/Error.h" #include "gtest/gtest.h" // We need to supprt Windows paths as well. In order to have paths with the same // length, use a different path according to the platform. #ifdef _WIN32 #define EXTERNALFILETESTPATH "C:/externalfi" #else #define EXTERNALFILETESTPATH "/externalfile" #endif using namespace llvm; static void check(remarks::Format SerializerFormat, remarks::SerializerMode Mode, ArrayRef Rs, StringRef ExpectedR, Optional ExpectedMeta, Optional StrTab = None) { std::string Buf; raw_string_ostream OS(Buf); Expected> MaybeS = [&] { if (StrTab) return createRemarkSerializer(SerializerFormat, Mode, OS, std::move(*StrTab)); else return createRemarkSerializer(SerializerFormat, Mode, OS); }(); EXPECT_FALSE(errorToBool(MaybeS.takeError())); std::unique_ptr S = std::move(*MaybeS); for (const remarks::Remark &R : Rs) S->emit(R); EXPECT_EQ(OS.str(), ExpectedR); if (ExpectedMeta) { Buf.clear(); std::unique_ptr MS = S->metaSerializer(OS, StringRef(EXTERNALFILETESTPATH)); MS->emit(); EXPECT_EQ(OS.str(), *ExpectedMeta); } } static void check(remarks::Format SerializerFormat, const remarks::Remark &R, StringRef ExpectedR, StringRef ExpectedMeta, Optional StrTab = None) { return check(SerializerFormat, remarks::SerializerMode::Separate, makeArrayRef(&R, &R + 1), ExpectedR, ExpectedMeta, std::move(StrTab)); } static void checkStandalone(remarks::Format SerializerFormat, const remarks::Remark &R, StringRef ExpectedR, Optional StrTab = None) { return check(SerializerFormat, remarks::SerializerMode::Standalone, makeArrayRef(&R, &R + 1), ExpectedR, /*ExpectedMeta=*/None, std::move(StrTab)); } TEST(YAMLRemarks, SerializerRemark) { remarks::Remark R; R.RemarkType = remarks::Type::Missed; R.PassName = "pass"; R.RemarkName = "name"; R.FunctionName = "func"; R.Loc = remarks::RemarkLocation{"path", 3, 4}; R.Hotness = 5; R.Args.emplace_back(); R.Args.back().Key = "key"; R.Args.back().Val = "value"; R.Args.emplace_back(); R.Args.back().Key = "keydebug"; R.Args.back().Val = "valuedebug"; R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; check(remarks::Format::YAML, R, "--- !Missed\n" "Pass: pass\n" "Name: name\n" "DebugLoc: { File: path, Line: 3, Column: 4 }\n" "Function: func\n" "Hotness: 5\n" "Args:\n" " - key: value\n" " - keydebug: valuedebug\n" " DebugLoc: { File: argpath, Line: 6, Column: 7 }\n" "...\n", StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0" EXTERNALFILETESTPATH "\0", 38)); } TEST(YAMLRemarks, SerializerRemarkStandalone) { remarks::Remark R; R.RemarkType = remarks::Type::Missed; R.PassName = "pass"; R.RemarkName = "name"; R.FunctionName = "func"; R.Loc = remarks::RemarkLocation{"path", 3, 4}; R.Hotness = 5; R.Args.emplace_back(); R.Args.back().Key = "key"; R.Args.back().Val = "value"; R.Args.emplace_back(); R.Args.back().Key = "keydebug"; R.Args.back().Val = "valuedebug"; R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; checkStandalone( remarks::Format::YAML, R, StringRef("--- !Missed\n" "Pass: pass\n" "Name: name\n" "DebugLoc: { File: path, Line: 3, Column: 4 }\n" "Function: func\n" "Hotness: 5\n" "Args:\n" " - key: value\n" " - keydebug: valuedebug\n" " DebugLoc: { File: argpath, Line: 6, Column: 7 }\n" "...\n")); } TEST(YAMLRemarks, SerializerRemarkStrTab) { remarks::Remark R; R.RemarkType = remarks::Type::Missed; R.PassName = "pass"; R.RemarkName = "name"; R.FunctionName = "func"; R.Loc = remarks::RemarkLocation{"path", 3, 4}; R.Hotness = 5; R.Args.emplace_back(); R.Args.back().Key = "key"; R.Args.back().Val = "value"; R.Args.emplace_back(); R.Args.back().Key = "keydebug"; R.Args.back().Val = "valuedebug"; R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; check(remarks::Format::YAMLStrTab, R, "--- !Missed\n" "Pass: 0\n" "Name: 1\n" "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" "Function: 2\n" "Hotness: 5\n" "Args:\n" " - key: 4\n" " - keydebug: 5\n" " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" "...\n", StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\x2d\0\0\0\0\0\0\0" "pass\0name\0func\0path\0value\0valuedebug\0argpath" "\0" EXTERNALFILETESTPATH "\0", 83)); } TEST(YAMLRemarks, SerializerRemarkParsedStrTab) { StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45); remarks::Remark R; R.RemarkType = remarks::Type::Missed; R.PassName = "pass"; R.RemarkName = "name"; R.FunctionName = "func"; R.Loc = remarks::RemarkLocation{"path", 3, 4}; R.Hotness = 5; R.Args.emplace_back(); R.Args.back().Key = "key"; R.Args.back().Val = "value"; R.Args.emplace_back(); R.Args.back().Key = "keydebug"; R.Args.back().Val = "valuedebug"; R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; check(remarks::Format::YAMLStrTab, R, "--- !Missed\n" "Pass: 0\n" "Name: 1\n" "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" "Function: 2\n" "Hotness: 5\n" "Args:\n" " - key: 4\n" " - keydebug: 5\n" " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" "...\n", StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\x2d\0\0\0\0\0\0\0" "pass\0name\0func\0path\0value\0valuedebug\0argpath" "\0" EXTERNALFILETESTPATH "\0", 83), remarks::StringTable(remarks::ParsedStringTable(StrTab))); } TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandaloneNoStrTab) { // Check that we don't use the string table even if it was provided. StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45); remarks::ParsedStringTable ParsedStrTab(StrTab); remarks::StringTable PreFilledStrTab(ParsedStrTab); remarks::Remark R; R.RemarkType = remarks::Type::Missed; R.PassName = "pass"; R.RemarkName = "name"; R.FunctionName = "func"; R.Loc = remarks::RemarkLocation{"path", 3, 4}; R.Hotness = 5; R.Args.emplace_back(); R.Args.back().Key = "key"; R.Args.back().Val = "value"; R.Args.emplace_back(); R.Args.back().Key = "keydebug"; R.Args.back().Val = "valuedebug"; R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; checkStandalone( remarks::Format::YAML, R, StringRef("--- !Missed\n" "Pass: pass\n" "Name: name\n" "DebugLoc: { File: path, Line: 3, Column: 4 }\n" "Function: func\n" "Hotness: 5\n" "Args:\n" " - key: value\n" " - keydebug: valuedebug\n" " DebugLoc: { File: argpath, Line: 6, Column: 7 }\n" "...\n"), std::move(PreFilledStrTab)); } TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandalone) { StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45); remarks::ParsedStringTable ParsedStrTab(StrTab); remarks::StringTable PreFilledStrTab(ParsedStrTab); remarks::Remark R; R.RemarkType = remarks::Type::Missed; R.PassName = "pass"; R.RemarkName = "name"; R.FunctionName = "func"; R.Loc = remarks::RemarkLocation{"path", 3, 4}; R.Hotness = 5; R.Args.emplace_back(); R.Args.back().Key = "key"; R.Args.back().Val = "value"; R.Args.emplace_back(); R.Args.back().Key = "keydebug"; R.Args.back().Val = "valuedebug"; R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; checkStandalone( remarks::Format::YAMLStrTab, R, StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\x2d\0\0\0\0\0\0\0" "pass\0name\0func\0path\0value\0valuedebug\0argpath\0" "--- !Missed\n" "Pass: 0\n" "Name: 1\n" "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" "Function: 2\n" "Hotness: 5\n" "Args:\n" " - key: 4\n" " - keydebug: 5\n" " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" "...\n", 315), std::move(PreFilledStrTab)); } TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandaloneMultipleRemarks) { StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45); remarks::ParsedStringTable ParsedStrTab(StrTab); remarks::StringTable PreFilledStrTab(ParsedStrTab); SmallVector Rs; remarks::Remark R; R.RemarkType = remarks::Type::Missed; R.PassName = "pass"; R.RemarkName = "name"; R.FunctionName = "func"; R.Loc = remarks::RemarkLocation{"path", 3, 4}; R.Hotness = 5; R.Args.emplace_back(); R.Args.back().Key = "key"; R.Args.back().Val = "value"; R.Args.emplace_back(); R.Args.back().Key = "keydebug"; R.Args.back().Val = "valuedebug"; R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; Rs.emplace_back(R.clone()); Rs.emplace_back(std::move(R)); check(remarks::Format::YAMLStrTab, remarks::SerializerMode::Standalone, Rs, StringRef("REMARKS\0" "\0\0\0\0\0\0\0\0" "\x2d\0\0\0\0\0\0\0" "pass\0name\0func\0path\0value\0valuedebug\0argpath\0" "--- !Missed\n" "Pass: 0\n" "Name: 1\n" "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" "Function: 2\n" "Hotness: 5\n" "Args:\n" " - key: 4\n" " - keydebug: 5\n" " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" "...\n" "--- !Missed\n" "Pass: 0\n" "Name: 1\n" "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" "Function: 2\n" "Hotness: 5\n" "Args:\n" " - key: 4\n" " - keydebug: 5\n" " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" "...\n", 561), /*ExpectedMeta=*/None, std::move(PreFilledStrTab)); }