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