1 //===- unittest/ProfileData/SampleProfTest.cpp ------------------*- C++ -*-===// 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/ProfileData/SampleProf.h" 10 #include "llvm/ADT/StringMap.h" 11 #include "llvm/ADT/StringRef.h" 12 #include "llvm/IR/LLVMContext.h" 13 #include "llvm/IR/Metadata.h" 14 #include "llvm/IR/Module.h" 15 #include "llvm/ProfileData/SampleProfReader.h" 16 #include "llvm/ProfileData/SampleProfWriter.h" 17 #include "llvm/Support/Casting.h" 18 #include "llvm/Support/ErrorOr.h" 19 #include "llvm/Support/FileSystem.h" 20 #include "llvm/Support/MemoryBuffer.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include "gtest/gtest.h" 23 #include <string> 24 #include <vector> 25 26 using namespace llvm; 27 using namespace sampleprof; 28 29 static ::testing::AssertionResult NoError(std::error_code EC) { 30 if (!EC) 31 return ::testing::AssertionSuccess(); 32 return ::testing::AssertionFailure() << "error " << EC.value() << ": " 33 << EC.message(); 34 } 35 36 namespace { 37 38 struct SampleProfTest : ::testing::Test { 39 LLVMContext Context; 40 std::unique_ptr<SampleProfileWriter> Writer; 41 std::unique_ptr<SampleProfileReader> Reader; 42 43 SampleProfTest() : Writer(), Reader() {} 44 45 void createWriter(SampleProfileFormat Format, StringRef Profile) { 46 std::error_code EC; 47 std::unique_ptr<raw_ostream> OS( 48 new raw_fd_ostream(Profile, EC, sys::fs::OF_None)); 49 auto WriterOrErr = SampleProfileWriter::create(OS, Format); 50 ASSERT_TRUE(NoError(WriterOrErr.getError())); 51 Writer = std::move(WriterOrErr.get()); 52 } 53 54 void readProfile(const Module &M, StringRef Profile, 55 StringRef RemapFile = "") { 56 auto ReaderOrErr = SampleProfileReader::create( 57 std::string(Profile), Context, std::string(RemapFile)); 58 ASSERT_TRUE(NoError(ReaderOrErr.getError())); 59 Reader = std::move(ReaderOrErr.get()); 60 Reader->collectFuncsFrom(M); 61 } 62 63 void createRemapFile(SmallVectorImpl<char> &RemapPath, StringRef &RemapFile) { 64 std::error_code EC = 65 llvm::sys::fs::createTemporaryFile("remapfile", "", RemapPath); 66 ASSERT_TRUE(NoError(EC)); 67 RemapFile = StringRef(RemapPath.data(), RemapPath.size()); 68 69 std::unique_ptr<raw_fd_ostream> OS( 70 new raw_fd_ostream(RemapFile, EC, sys::fs::OF_None)); 71 *OS << R"( 72 # Types 'int' and 'long' are equivalent 73 type i l 74 # Function names 'foo' and 'faux' are equivalent 75 name 3foo 4faux 76 )"; 77 OS->close(); 78 } 79 80 // Verify profile summary is consistent in the roundtrip to and from 81 // Metadata. \p AddPartialField is to choose whether the Metadata 82 // contains the IsPartialProfile field which is optional. 83 void verifyProfileSummary(ProfileSummary &Summary, Module &M, 84 const bool AddPartialField, 85 const bool AddPartialProfileRatioField) { 86 LLVMContext &Context = M.getContext(); 87 const bool IsPartialProfile = Summary.isPartialProfile(); 88 const double PartialProfileRatio = Summary.getPartialProfileRatio(); 89 auto VerifySummary = [IsPartialProfile, PartialProfileRatio]( 90 ProfileSummary &Summary) mutable { 91 ASSERT_EQ(ProfileSummary::PSK_Sample, Summary.getKind()); 92 ASSERT_EQ(138211u, Summary.getTotalCount()); 93 ASSERT_EQ(10u, Summary.getNumCounts()); 94 ASSERT_EQ(4u, Summary.getNumFunctions()); 95 ASSERT_EQ(1437u, Summary.getMaxFunctionCount()); 96 ASSERT_EQ(60351u, Summary.getMaxCount()); 97 ASSERT_EQ(IsPartialProfile, Summary.isPartialProfile()); 98 ASSERT_EQ(PartialProfileRatio, Summary.getPartialProfileRatio()); 99 100 uint32_t Cutoff = 800000; 101 auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) { 102 return PE.Cutoff == Cutoff; 103 }; 104 std::vector<ProfileSummaryEntry> &Details = Summary.getDetailedSummary(); 105 auto EightyPerc = find_if(Details, Predicate); 106 Cutoff = 900000; 107 auto NinetyPerc = find_if(Details, Predicate); 108 Cutoff = 950000; 109 auto NinetyFivePerc = find_if(Details, Predicate); 110 Cutoff = 990000; 111 auto NinetyNinePerc = find_if(Details, Predicate); 112 ASSERT_EQ(60000u, EightyPerc->MinCount); 113 ASSERT_EQ(12557u, NinetyPerc->MinCount); 114 ASSERT_EQ(12557u, NinetyFivePerc->MinCount); 115 ASSERT_EQ(600u, NinetyNinePerc->MinCount); 116 }; 117 VerifySummary(Summary); 118 119 // Test that conversion of summary to and from Metadata works. 120 Metadata *MD = 121 Summary.getMD(Context, AddPartialField, AddPartialProfileRatioField); 122 ASSERT_TRUE(MD); 123 ProfileSummary *PS = ProfileSummary::getFromMD(MD); 124 ASSERT_TRUE(PS); 125 VerifySummary(*PS); 126 delete PS; 127 128 // Test that summary can be attached to and read back from module. 129 M.eraseNamedMetadata(M.getOrInsertModuleFlagsMetadata()); 130 M.setProfileSummary(MD, ProfileSummary::PSK_Sample); 131 MD = M.getProfileSummary(/* IsCS */ false); 132 ASSERT_TRUE(MD); 133 PS = ProfileSummary::getFromMD(MD); 134 ASSERT_TRUE(PS); 135 VerifySummary(*PS); 136 delete PS; 137 } 138 139 void testRoundTrip(SampleProfileFormat Format, bool Remap, bool UseMD5) { 140 SmallVector<char, 128> ProfilePath; 141 ASSERT_TRUE(NoError(llvm::sys::fs::createTemporaryFile("profile", "", ProfilePath))); 142 StringRef Profile(ProfilePath.data(), ProfilePath.size()); 143 createWriter(Format, Profile); 144 if (Format == SampleProfileFormat::SPF_Ext_Binary && UseMD5) 145 static_cast<SampleProfileWriterExtBinary *>(Writer.get())->setUseMD5(); 146 147 StringRef FooName("_Z3fooi"); 148 FunctionSamples FooSamples; 149 FooSamples.setName(FooName); 150 FooSamples.addTotalSamples(7711); 151 FooSamples.addHeadSamples(610); 152 FooSamples.addBodySamples(1, 0, 610); 153 FooSamples.addBodySamples(2, 0, 600); 154 FooSamples.addBodySamples(4, 0, 60000); 155 FooSamples.addBodySamples(8, 0, 60351); 156 FooSamples.addBodySamples(10, 0, 605); 157 158 // Add inline instance with name "_Z3gooi". 159 StringRef GooName("_Z3gooi"); 160 auto &GooSamples = 161 FooSamples.functionSamplesAt(LineLocation(7, 0))[GooName.str()]; 162 GooSamples.setName(GooName); 163 GooSamples.addTotalSamples(502); 164 GooSamples.addBodySamples(3, 0, 502); 165 166 // Add inline instance with name "_Z3hooi". 167 StringRef HooName("_Z3hooi"); 168 auto &HooSamples = 169 GooSamples.functionSamplesAt(LineLocation(9, 0))[HooName.str()]; 170 HooSamples.setName(HooName); 171 HooSamples.addTotalSamples(317); 172 HooSamples.addBodySamples(4, 0, 317); 173 174 StringRef BarName("_Z3bari"); 175 FunctionSamples BarSamples; 176 BarSamples.setName(BarName); 177 BarSamples.addTotalSamples(20301); 178 BarSamples.addHeadSamples(1437); 179 BarSamples.addBodySamples(1, 0, 1437); 180 // Test how reader/writer handles unmangled names. 181 StringRef MconstructName("_M_construct<char *>"); 182 StringRef StringviewName("string_view<std::allocator<char> >"); 183 BarSamples.addCalledTargetSamples(1, 0, MconstructName, 1000); 184 BarSamples.addCalledTargetSamples(1, 0, StringviewName, 437); 185 186 StringRef BazName("_Z3bazi"); 187 FunctionSamples BazSamples; 188 BazSamples.setName(BazName); 189 BazSamples.addTotalSamples(12557); 190 BazSamples.addHeadSamples(1257); 191 BazSamples.addBodySamples(1, 0, 12557); 192 193 StringRef BooName("_Z3booi"); 194 FunctionSamples BooSamples; 195 BooSamples.setName(BooName); 196 BooSamples.addTotalSamples(1232); 197 BooSamples.addHeadSamples(1); 198 BooSamples.addBodySamples(1, 0, 1232); 199 200 StringMap<FunctionSamples> Profiles; 201 Profiles[FooName] = std::move(FooSamples); 202 Profiles[BarName] = std::move(BarSamples); 203 Profiles[BazName] = std::move(BazSamples); 204 Profiles[BooName] = std::move(BooSamples); 205 206 Module M("my_module", Context); 207 FunctionType *fn_type = 208 FunctionType::get(Type::getVoidTy(Context), {}, false); 209 210 SmallVector<char, 128> RemapPath; 211 StringRef RemapFile; 212 if (Remap) { 213 createRemapFile(RemapPath, RemapFile); 214 FooName = "_Z4fauxi"; 215 BarName = "_Z3barl"; 216 GooName = "_Z3gool"; 217 HooName = "_Z3hool"; 218 } 219 220 M.getOrInsertFunction(FooName, fn_type); 221 M.getOrInsertFunction(BarName, fn_type); 222 M.getOrInsertFunction(BooName, fn_type); 223 224 ProfileSymbolList List; 225 if (Format == SampleProfileFormat::SPF_Ext_Binary) { 226 List.add("zoo", true); 227 List.add("moo", true); 228 } 229 Writer->setProfileSymbolList(&List); 230 231 std::error_code EC; 232 EC = Writer->write(Profiles); 233 ASSERT_TRUE(NoError(EC)); 234 235 Writer->getOutputStream().flush(); 236 237 readProfile(M, Profile, RemapFile); 238 EC = Reader->read(); 239 ASSERT_TRUE(NoError(EC)); 240 241 if (Format == SampleProfileFormat::SPF_Ext_Binary) { 242 std::unique_ptr<ProfileSymbolList> ReaderList = 243 Reader->getProfileSymbolList(); 244 ReaderList->contains("zoo"); 245 ReaderList->contains("moo"); 246 } 247 248 FunctionSamples *ReadFooSamples = Reader->getSamplesFor(FooName); 249 ASSERT_TRUE(ReadFooSamples != nullptr); 250 if (!UseMD5) { 251 ASSERT_EQ("_Z3fooi", ReadFooSamples->getName()); 252 } 253 ASSERT_EQ(7711u, ReadFooSamples->getTotalSamples()); 254 ASSERT_EQ(610u, ReadFooSamples->getHeadSamples()); 255 256 // Try to find a FunctionSamples with GooName at given callsites containing 257 // inline instance for GooName. Test the correct FunctionSamples can be 258 // found with Remapper support. 259 const FunctionSamples *ReadGooSamples = 260 ReadFooSamples->findFunctionSamplesAt(LineLocation(7, 0), GooName, 261 Reader->getRemapper()); 262 ASSERT_TRUE(ReadGooSamples != nullptr); 263 ASSERT_EQ(502u, ReadGooSamples->getTotalSamples()); 264 265 // Try to find a FunctionSamples with GooName at given callsites containing 266 // no inline instance for GooName. Test no FunctionSamples will be 267 // found with Remapper support. 268 const FunctionSamples *ReadGooSamplesAgain = 269 ReadFooSamples->findFunctionSamplesAt(LineLocation(9, 0), GooName, 270 Reader->getRemapper()); 271 ASSERT_TRUE(ReadGooSamplesAgain == nullptr); 272 273 // The inline instance of Hoo is inside of the inline instance of Goo. 274 // Try to find a FunctionSamples with HooName at given callsites containing 275 // inline instance for HooName. Test the correct FunctionSamples can be 276 // found with Remapper support. 277 const FunctionSamples *ReadHooSamples = 278 ReadGooSamples->findFunctionSamplesAt(LineLocation(9, 0), HooName, 279 Reader->getRemapper()); 280 ASSERT_TRUE(ReadHooSamples != nullptr); 281 ASSERT_EQ(317u, ReadHooSamples->getTotalSamples()); 282 283 FunctionSamples *ReadBarSamples = Reader->getSamplesFor(BarName); 284 ASSERT_TRUE(ReadBarSamples != nullptr); 285 if (!UseMD5) { 286 ASSERT_EQ("_Z3bari", ReadBarSamples->getName()); 287 } 288 ASSERT_EQ(20301u, ReadBarSamples->getTotalSamples()); 289 ASSERT_EQ(1437u, ReadBarSamples->getHeadSamples()); 290 ErrorOr<SampleRecord::CallTargetMap> CTMap = 291 ReadBarSamples->findCallTargetMapAt(1, 0); 292 ASSERT_FALSE(CTMap.getError()); 293 294 // Because _Z3bazi is not defined in module M, expect _Z3bazi's profile 295 // is not loaded when the profile is ExtBinary or Compact format because 296 // these formats support loading function profiles on demand. 297 FunctionSamples *ReadBazSamples = Reader->getSamplesFor(BazName); 298 if (Format == SampleProfileFormat::SPF_Ext_Binary || 299 Format == SampleProfileFormat::SPF_Compact_Binary) { 300 ASSERT_TRUE(ReadBazSamples == nullptr); 301 ASSERT_EQ(3u, Reader->getProfiles().size()); 302 } else { 303 ASSERT_TRUE(ReadBazSamples != nullptr); 304 ASSERT_EQ(12557u, ReadBazSamples->getTotalSamples()); 305 ASSERT_EQ(4u, Reader->getProfiles().size()); 306 } 307 308 FunctionSamples *ReadBooSamples = Reader->getSamplesFor(BooName); 309 ASSERT_TRUE(ReadBooSamples != nullptr); 310 ASSERT_EQ(1232u, ReadBooSamples->getTotalSamples()); 311 312 std::string MconstructGUID; 313 StringRef MconstructRep = 314 getRepInFormat(MconstructName, UseMD5, MconstructGUID); 315 std::string StringviewGUID; 316 StringRef StringviewRep = 317 getRepInFormat(StringviewName, UseMD5, StringviewGUID); 318 ASSERT_EQ(1000u, CTMap.get()[MconstructRep]); 319 ASSERT_EQ(437u, CTMap.get()[StringviewRep]); 320 321 322 ProfileSummary &Summary = Reader->getSummary(); 323 Summary.setPartialProfile(true); 324 verifyProfileSummary(Summary, M, true, false); 325 326 Summary.setPartialProfile(false); 327 verifyProfileSummary(Summary, M, true, false); 328 329 verifyProfileSummary(Summary, M, false, false); 330 331 Summary.setPartialProfile(true); 332 Summary.setPartialProfileRatio(0.5); 333 verifyProfileSummary(Summary, M, true, true); 334 } 335 336 void addFunctionSamples(StringMap<FunctionSamples> *Smap, const char *Fname, 337 uint64_t TotalSamples, uint64_t HeadSamples) { 338 StringRef Name(Fname); 339 FunctionSamples FcnSamples; 340 FcnSamples.setName(Name); 341 FcnSamples.addTotalSamples(TotalSamples); 342 FcnSamples.addHeadSamples(HeadSamples); 343 FcnSamples.addBodySamples(1, 0, HeadSamples); 344 (*Smap)[Name] = FcnSamples; 345 } 346 347 StringMap<FunctionSamples> setupFcnSamplesForElisionTest(StringRef Policy) { 348 StringMap<FunctionSamples> Smap; 349 addFunctionSamples(&Smap, "foo", uint64_t(20301), uint64_t(1437)); 350 if (Policy == "" || Policy == "all") 351 return Smap; 352 addFunctionSamples(&Smap, "foo.bar", uint64_t(20303), uint64_t(1439)); 353 if (Policy == "selected") 354 return Smap; 355 addFunctionSamples(&Smap, "foo.llvm.2465", uint64_t(20305), uint64_t(1441)); 356 return Smap; 357 } 358 359 void createFunctionWithSampleProfileElisionPolicy(Module *M, 360 const char *Fname, 361 StringRef Policy) { 362 FunctionType *FnType = 363 FunctionType::get(Type::getVoidTy(Context), {}, false); 364 auto Inserted = M->getOrInsertFunction(Fname, FnType); 365 auto Fcn = cast<Function>(Inserted.getCallee()); 366 if (Policy != "") 367 Fcn->addFnAttr("sample-profile-suffix-elision-policy", Policy); 368 } 369 370 void setupModuleForElisionTest(Module *M, StringRef Policy) { 371 createFunctionWithSampleProfileElisionPolicy(M, "foo", Policy); 372 createFunctionWithSampleProfileElisionPolicy(M, "foo.bar", Policy); 373 createFunctionWithSampleProfileElisionPolicy(M, "foo.llvm.2465", Policy); 374 } 375 376 void testSuffixElisionPolicy(SampleProfileFormat Format, StringRef Policy, 377 const StringMap<uint64_t> &Expected) { 378 SmallVector<char, 128> ProfilePath; 379 std::error_code EC; 380 EC = llvm::sys::fs::createTemporaryFile("profile", "", ProfilePath); 381 ASSERT_TRUE(NoError(EC)); 382 StringRef ProfileFile(ProfilePath.data(), ProfilePath.size()); 383 384 Module M("my_module", Context); 385 setupModuleForElisionTest(&M, Policy); 386 StringMap<FunctionSamples> ProfMap = setupFcnSamplesForElisionTest(Policy); 387 388 // write profile 389 createWriter(Format, ProfileFile); 390 EC = Writer->write(ProfMap); 391 ASSERT_TRUE(NoError(EC)); 392 Writer->getOutputStream().flush(); 393 394 // read profile 395 readProfile(M, ProfileFile); 396 EC = Reader->read(); 397 ASSERT_TRUE(NoError(EC)); 398 399 for (auto I = Expected.begin(); I != Expected.end(); ++I) { 400 uint64_t Esamples = uint64_t(-1); 401 FunctionSamples *Samples = Reader->getSamplesFor(I->getKey()); 402 if (Samples != nullptr) 403 Esamples = Samples->getTotalSamples(); 404 ASSERT_EQ(I->getValue(), Esamples); 405 } 406 } 407 }; 408 409 TEST_F(SampleProfTest, roundtrip_text_profile) { 410 testRoundTrip(SampleProfileFormat::SPF_Text, false, false); 411 } 412 413 TEST_F(SampleProfTest, roundtrip_raw_binary_profile) { 414 testRoundTrip(SampleProfileFormat::SPF_Binary, false, false); 415 } 416 417 TEST_F(SampleProfTest, roundtrip_compact_binary_profile) { 418 testRoundTrip(SampleProfileFormat::SPF_Compact_Binary, false, true); 419 } 420 421 TEST_F(SampleProfTest, roundtrip_ext_binary_profile) { 422 testRoundTrip(SampleProfileFormat::SPF_Ext_Binary, false, false); 423 } 424 425 TEST_F(SampleProfTest, roundtrip_md5_ext_binary_profile) { 426 testRoundTrip(SampleProfileFormat::SPF_Ext_Binary, false, true); 427 } 428 429 TEST_F(SampleProfTest, remap_text_profile) { 430 testRoundTrip(SampleProfileFormat::SPF_Text, true, false); 431 } 432 433 TEST_F(SampleProfTest, remap_raw_binary_profile) { 434 testRoundTrip(SampleProfileFormat::SPF_Binary, true, false); 435 } 436 437 TEST_F(SampleProfTest, remap_ext_binary_profile) { 438 testRoundTrip(SampleProfileFormat::SPF_Ext_Binary, true, false); 439 } 440 441 TEST_F(SampleProfTest, sample_overflow_saturation) { 442 const uint64_t Max = std::numeric_limits<uint64_t>::max(); 443 sampleprof_error Result; 444 445 FunctionSamples FooSamples; 446 Result = FooSamples.addTotalSamples(1); 447 ASSERT_EQ(Result, sampleprof_error::success); 448 449 Result = FooSamples.addHeadSamples(1); 450 ASSERT_EQ(Result, sampleprof_error::success); 451 452 Result = FooSamples.addBodySamples(10, 0, 1); 453 ASSERT_EQ(Result, sampleprof_error::success); 454 455 Result = FooSamples.addTotalSamples(Max); 456 ASSERT_EQ(Result, sampleprof_error::counter_overflow); 457 ASSERT_EQ(FooSamples.getTotalSamples(), Max); 458 459 Result = FooSamples.addHeadSamples(Max); 460 ASSERT_EQ(Result, sampleprof_error::counter_overflow); 461 ASSERT_EQ(FooSamples.getHeadSamples(), Max); 462 463 Result = FooSamples.addBodySamples(10, 0, Max); 464 ASSERT_EQ(Result, sampleprof_error::counter_overflow); 465 ErrorOr<uint64_t> BodySamples = FooSamples.findSamplesAt(10, 0); 466 ASSERT_FALSE(BodySamples.getError()); 467 ASSERT_EQ(BodySamples.get(), Max); 468 } 469 470 TEST_F(SampleProfTest, default_suffix_elision_text) { 471 // Default suffix elision policy: strip everything after first dot. 472 // This implies that all suffix variants will map to "foo", so 473 // we don't expect to see any entries for them in the sample 474 // profile. 475 StringMap<uint64_t> Expected; 476 Expected["foo"] = uint64_t(20301); 477 Expected["foo.bar"] = uint64_t(-1); 478 Expected["foo.llvm.2465"] = uint64_t(-1); 479 testSuffixElisionPolicy(SampleProfileFormat::SPF_Text, "", Expected); 480 } 481 482 TEST_F(SampleProfTest, default_suffix_elision_compact_binary) { 483 // Default suffix elision policy: strip everything after first dot. 484 // This implies that all suffix variants will map to "foo", so 485 // we don't expect to see any entries for them in the sample 486 // profile. 487 StringMap<uint64_t> Expected; 488 Expected["foo"] = uint64_t(20301); 489 Expected["foo.bar"] = uint64_t(-1); 490 Expected["foo.llvm.2465"] = uint64_t(-1); 491 testSuffixElisionPolicy(SampleProfileFormat::SPF_Compact_Binary, "", 492 Expected); 493 } 494 495 TEST_F(SampleProfTest, selected_suffix_elision_text) { 496 // Profile is created and searched using the "selected" 497 // suffix elision policy: we only strip a .XXX suffix if 498 // it matches a pattern known to be generated by the compiler 499 // (e.g. ".llvm.<digits>"). 500 StringMap<uint64_t> Expected; 501 Expected["foo"] = uint64_t(20301); 502 Expected["foo.bar"] = uint64_t(20303); 503 Expected["foo.llvm.2465"] = uint64_t(-1); 504 testSuffixElisionPolicy(SampleProfileFormat::SPF_Text, "selected", Expected); 505 } 506 507 TEST_F(SampleProfTest, selected_suffix_elision_compact_binary) { 508 // Profile is created and searched using the "selected" 509 // suffix elision policy: we only strip a .XXX suffix if 510 // it matches a pattern known to be generated by the compiler 511 // (e.g. ".llvm.<digits>"). 512 StringMap<uint64_t> Expected; 513 Expected["foo"] = uint64_t(20301); 514 Expected["foo.bar"] = uint64_t(20303); 515 Expected["foo.llvm.2465"] = uint64_t(-1); 516 testSuffixElisionPolicy(SampleProfileFormat::SPF_Compact_Binary, "selected", 517 Expected); 518 } 519 520 TEST_F(SampleProfTest, none_suffix_elision_text) { 521 // Profile is created and searched using the "none" 522 // suffix elision policy: no stripping of suffixes at all. 523 // Here we expect to see all variants in the profile. 524 StringMap<uint64_t> Expected; 525 Expected["foo"] = uint64_t(20301); 526 Expected["foo.bar"] = uint64_t(20303); 527 Expected["foo.llvm.2465"] = uint64_t(20305); 528 testSuffixElisionPolicy(SampleProfileFormat::SPF_Text, "none", Expected); 529 } 530 531 TEST_F(SampleProfTest, none_suffix_elision_compact_binary) { 532 // Profile is created and searched using the "none" 533 // suffix elision policy: no stripping of suffixes at all. 534 // Here we expect to see all variants in the profile. 535 StringMap<uint64_t> Expected; 536 Expected["foo"] = uint64_t(20301); 537 Expected["foo.bar"] = uint64_t(20303); 538 Expected["foo.llvm.2465"] = uint64_t(20305); 539 testSuffixElisionPolicy(SampleProfileFormat::SPF_Compact_Binary, "none", 540 Expected); 541 } 542 543 } // end anonymous namespace 544