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 25 static void check(remarks::SerializerMode Mode, ArrayRef<remarks::Remark> Rs, 26 StringRef ExpectedR, Optional<StringRef> ExpectedMeta, 27 bool UseStrTab = false, 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 (UseStrTab) { 33 if (StrTab) 34 return createRemarkSerializer(remarks::Format::YAMLStrTab, Mode, OS, 35 std::move(*StrTab)); 36 else 37 return createRemarkSerializer(remarks::Format::YAMLStrTab, Mode, OS); 38 } else 39 return createRemarkSerializer(remarks::Format::YAML, Mode, OS); 40 }(); 41 EXPECT_FALSE(errorToBool(MaybeS.takeError())); 42 std::unique_ptr<remarks::RemarkSerializer> S = std::move(*MaybeS); 43 44 for (const remarks::Remark &R : Rs) 45 S->emit(R); 46 EXPECT_EQ(OS.str(), ExpectedR); 47 48 if (ExpectedMeta) { 49 Buf.clear(); 50 std::unique_ptr<remarks::MetaSerializer> MS = 51 S->metaSerializer(OS, StringRef(EXTERNALFILETESTPATH)); 52 MS->emit(); 53 EXPECT_EQ(OS.str(), *ExpectedMeta); 54 } 55 } 56 57 static void check(const remarks::Remark &R, StringRef ExpectedR, 58 StringRef ExpectedMeta, bool UseStrTab = false, 59 Optional<remarks::StringTable> StrTab = None) { 60 return check(remarks::SerializerMode::Separate, makeArrayRef(&R, &R + 1), ExpectedR, ExpectedMeta, 61 UseStrTab, std::move(StrTab)); 62 } 63 64 static void checkStandalone(const remarks::Remark &R, StringRef ExpectedR, 65 Optional<remarks::StringTable> StrTab = None) { 66 bool UseStrTab = StrTab.hasValue(); 67 return check(remarks::SerializerMode::Standalone, makeArrayRef(&R, &R +1), ExpectedR, 68 /*ExpectedMeta=*/None, UseStrTab, std::move(StrTab)); 69 } 70 71 TEST(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{"path", 3, 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{"argpath", 6, 7}; 86 check(R, 87 "--- !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 StringRef("REMARKS\0" 99 "\0\0\0\0\0\0\0\0" 100 "\0\0\0\0\0\0\0\0" 101 EXTERNALFILETESTPATH"\0", 102 38)); 103 } 104 105 TEST(YAMLRemarks, SerializerRemarkStandalone) { 106 remarks::Remark R; 107 R.RemarkType = remarks::Type::Missed; 108 R.PassName = "pass"; 109 R.RemarkName = "name"; 110 R.FunctionName = "func"; 111 R.Loc = remarks::RemarkLocation{"path", 3, 4}; 112 R.Hotness = 5; 113 R.Args.emplace_back(); 114 R.Args.back().Key = "key"; 115 R.Args.back().Val = "value"; 116 R.Args.emplace_back(); 117 R.Args.back().Key = "keydebug"; 118 R.Args.back().Val = "valuedebug"; 119 R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; 120 checkStandalone( 121 R, 122 StringRef("--- !Missed\n" 123 "Pass: pass\n" 124 "Name: name\n" 125 "DebugLoc: { File: path, Line: 3, Column: 4 }\n" 126 "Function: func\n" 127 "Hotness: 5\n" 128 "Args:\n" 129 " - key: value\n" 130 " - keydebug: valuedebug\n" 131 " DebugLoc: { File: argpath, Line: 6, Column: 7 }\n" 132 "...\n")); 133 } 134 135 TEST(YAMLRemarks, SerializerRemarkStrTab) { 136 remarks::Remark R; 137 R.RemarkType = remarks::Type::Missed; 138 R.PassName = "pass"; 139 R.RemarkName = "name"; 140 R.FunctionName = "func"; 141 R.Loc = remarks::RemarkLocation{"path", 3, 4}; 142 R.Hotness = 5; 143 R.Args.emplace_back(); 144 R.Args.back().Key = "key"; 145 R.Args.back().Val = "value"; 146 R.Args.emplace_back(); 147 R.Args.back().Key = "keydebug"; 148 R.Args.back().Val = "valuedebug"; 149 R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; 150 check(R, 151 "--- !Missed\n" 152 "Pass: 0\n" 153 "Name: 1\n" 154 "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" 155 "Function: 2\n" 156 "Hotness: 5\n" 157 "Args:\n" 158 " - key: 4\n" 159 " - keydebug: 5\n" 160 " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" 161 "...\n", 162 StringRef("REMARKS\0" 163 "\0\0\0\0\0\0\0\0" 164 "\x2d\0\0\0\0\0\0\0" 165 "pass\0name\0func\0path\0value\0valuedebug\0argpath\0" 166 EXTERNALFILETESTPATH"\0", 167 83), 168 /*UseStrTab=*/true); 169 } 170 171 TEST(YAMLRemarks, SerializerRemarkParsedStrTab) { 172 StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45); 173 remarks::Remark R; 174 R.RemarkType = remarks::Type::Missed; 175 R.PassName = "pass"; 176 R.RemarkName = "name"; 177 R.FunctionName = "func"; 178 R.Loc = remarks::RemarkLocation{"path", 3, 4}; 179 R.Hotness = 5; 180 R.Args.emplace_back(); 181 R.Args.back().Key = "key"; 182 R.Args.back().Val = "value"; 183 R.Args.emplace_back(); 184 R.Args.back().Key = "keydebug"; 185 R.Args.back().Val = "valuedebug"; 186 R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; 187 check(R, 188 "--- !Missed\n" 189 "Pass: 0\n" 190 "Name: 1\n" 191 "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" 192 "Function: 2\n" 193 "Hotness: 5\n" 194 "Args:\n" 195 " - key: 4\n" 196 " - keydebug: 5\n" 197 " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" 198 "...\n", 199 StringRef("REMARKS\0" 200 "\0\0\0\0\0\0\0\0" 201 "\x2d\0\0\0\0\0\0\0" 202 "pass\0name\0func\0path\0value\0valuedebug\0argpath\0" 203 EXTERNALFILETESTPATH"\0", 204 83), 205 /*UseStrTab=*/true, 206 remarks::StringTable(remarks::ParsedStringTable(StrTab))); 207 } 208 209 TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandalone) { 210 StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45); 211 remarks::ParsedStringTable ParsedStrTab(StrTab); 212 remarks::StringTable PreFilledStrTab(ParsedStrTab); 213 remarks::Remark R; 214 R.RemarkType = remarks::Type::Missed; 215 R.PassName = "pass"; 216 R.RemarkName = "name"; 217 R.FunctionName = "func"; 218 R.Loc = remarks::RemarkLocation{"path", 3, 4}; 219 R.Hotness = 5; 220 R.Args.emplace_back(); 221 R.Args.back().Key = "key"; 222 R.Args.back().Val = "value"; 223 R.Args.emplace_back(); 224 R.Args.back().Key = "keydebug"; 225 R.Args.back().Val = "valuedebug"; 226 R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; 227 checkStandalone( 228 R, 229 StringRef("REMARKS\0" 230 "\0\0\0\0\0\0\0\0" 231 "\x2d\0\0\0\0\0\0\0" 232 "pass\0name\0func\0path\0value\0valuedebug\0argpath\0" 233 "--- !Missed\n" 234 "Pass: 0\n" 235 "Name: 1\n" 236 "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" 237 "Function: 2\n" 238 "Hotness: 5\n" 239 "Args:\n" 240 " - key: 4\n" 241 " - keydebug: 5\n" 242 " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" 243 "...\n", 244 315), 245 std::move(PreFilledStrTab)); 246 } 247 248 TEST(YAMLRemarks, SerializerRemarkParsedStrTabStandaloneMultipleRemarks) { 249 StringRef StrTab("pass\0name\0func\0path\0value\0valuedebug\0argpath\0", 45); 250 remarks::ParsedStringTable ParsedStrTab(StrTab); 251 remarks::StringTable PreFilledStrTab(ParsedStrTab); 252 SmallVector<remarks::Remark, 2> Rs; 253 remarks::Remark R; 254 R.RemarkType = remarks::Type::Missed; 255 R.PassName = "pass"; 256 R.RemarkName = "name"; 257 R.FunctionName = "func"; 258 R.Loc = remarks::RemarkLocation{"path", 3, 4}; 259 R.Hotness = 5; 260 R.Args.emplace_back(); 261 R.Args.back().Key = "key"; 262 R.Args.back().Val = "value"; 263 R.Args.emplace_back(); 264 R.Args.back().Key = "keydebug"; 265 R.Args.back().Val = "valuedebug"; 266 R.Args.back().Loc = remarks::RemarkLocation{"argpath", 6, 7}; 267 Rs.emplace_back(R.clone()); 268 Rs.emplace_back(std::move(R)); 269 check(remarks::SerializerMode::Standalone, Rs, 270 StringRef("REMARKS\0" 271 "\0\0\0\0\0\0\0\0" 272 "\x2d\0\0\0\0\0\0\0" 273 "pass\0name\0func\0path\0value\0valuedebug\0argpath\0" 274 "--- !Missed\n" 275 "Pass: 0\n" 276 "Name: 1\n" 277 "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" 278 "Function: 2\n" 279 "Hotness: 5\n" 280 "Args:\n" 281 " - key: 4\n" 282 " - keydebug: 5\n" 283 " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" 284 "...\n" 285 "--- !Missed\n" 286 "Pass: 0\n" 287 "Name: 1\n" 288 "DebugLoc: { File: 3, Line: 3, Column: 4 }\n" 289 "Function: 2\n" 290 "Hotness: 5\n" 291 "Args:\n" 292 " - key: 4\n" 293 " - keydebug: 5\n" 294 " DebugLoc: { File: 6, Line: 6, Column: 7 }\n" 295 "...\n", 296 561), 297 /*ExpectedMeta=*/None, 298 /*UseStrTab=*/true, std::move(PreFilledStrTab)); 299 } 300