1 //===- unittest/ProfileData/CoverageMappingTest.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/ProfileData/Coverage/CoverageMapping.h" 10 #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 11 #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" 12 #include "llvm/ProfileData/InstrProfReader.h" 13 #include "llvm/ProfileData/InstrProfWriter.h" 14 #include "llvm/Support/raw_ostream.h" 15 #include "llvm/Testing/Support/Error.h" 16 #include "llvm/Testing/Support/SupportHelpers.h" 17 #include "gtest/gtest.h" 18 19 #include <ostream> 20 #include <utility> 21 22 using namespace llvm; 23 using namespace coverage; 24 25 [[nodiscard]] static ::testing::AssertionResult 26 ErrorEquals(coveragemap_error Expected, Error E) { 27 coveragemap_error Found; 28 std::string FoundMsg; 29 handleAllErrors(std::move(E), [&](const CoverageMapError &CME) { 30 Found = CME.get(); 31 FoundMsg = CME.message(); 32 }); 33 if (Expected == Found) 34 return ::testing::AssertionSuccess(); 35 return ::testing::AssertionFailure() << "error: " << FoundMsg << "\n"; 36 } 37 38 namespace llvm { 39 namespace coverage { 40 void PrintTo(const Counter &C, ::std::ostream *os) { 41 if (C.isZero()) 42 *os << "Zero"; 43 else if (C.isExpression()) 44 *os << "Expression " << C.getExpressionID(); 45 else 46 *os << "Counter " << C.getCounterID(); 47 } 48 49 void PrintTo(const CoverageSegment &S, ::std::ostream *os) { 50 *os << "CoverageSegment(" << S.Line << ", " << S.Col << ", "; 51 if (S.HasCount) 52 *os << S.Count << ", "; 53 *os << (S.IsRegionEntry ? "true" : "false") << ")"; 54 } 55 } 56 } 57 58 namespace { 59 60 struct OutputFunctionCoverageData { 61 StringRef Name; 62 uint64_t Hash; 63 std::vector<StringRef> Filenames; 64 std::vector<CounterMappingRegion> Regions; 65 std::vector<CounterExpression> Expressions; 66 67 OutputFunctionCoverageData() : Hash(0) {} 68 69 OutputFunctionCoverageData(OutputFunctionCoverageData &&OFCD) 70 : Name(OFCD.Name), Hash(OFCD.Hash), Filenames(std::move(OFCD.Filenames)), 71 Regions(std::move(OFCD.Regions)) {} 72 73 OutputFunctionCoverageData(const OutputFunctionCoverageData &) = delete; 74 OutputFunctionCoverageData & 75 operator=(const OutputFunctionCoverageData &) = delete; 76 OutputFunctionCoverageData &operator=(OutputFunctionCoverageData &&) = delete; 77 78 void fillCoverageMappingRecord(CoverageMappingRecord &Record) const { 79 Record.FunctionName = Name; 80 Record.FunctionHash = Hash; 81 Record.Filenames = Filenames; 82 Record.Expressions = Expressions; 83 Record.MappingRegions = Regions; 84 } 85 }; 86 87 struct CoverageMappingReaderMock : CoverageMappingReader { 88 ArrayRef<OutputFunctionCoverageData> Functions; 89 90 CoverageMappingReaderMock(ArrayRef<OutputFunctionCoverageData> Functions) 91 : Functions(Functions) {} 92 93 Error readNextRecord(CoverageMappingRecord &Record) override { 94 if (Functions.empty()) 95 return make_error<CoverageMapError>(coveragemap_error::eof); 96 97 Functions.front().fillCoverageMappingRecord(Record); 98 Functions = Functions.slice(1); 99 100 return Error::success(); 101 } 102 }; 103 104 struct InputFunctionCoverageData { 105 // Maps the global file index from CoverageMappingTest.Files 106 // to the index of that file within this function. We can't just use 107 // global file indexes here because local indexes have to be dense. 108 // This map is used during serialization to create the virtual file mapping 109 // (from local fileId to global Index) in the head of the per-function 110 // coverage mapping data. 111 SmallDenseMap<unsigned, unsigned> ReverseVirtualFileMapping; 112 std::string Name; 113 uint64_t Hash; 114 std::vector<CounterMappingRegion> Regions; 115 std::vector<CounterExpression> Expressions; 116 117 InputFunctionCoverageData(std::string Name, uint64_t Hash) 118 : Name(std::move(Name)), Hash(Hash) {} 119 120 InputFunctionCoverageData(InputFunctionCoverageData &&IFCD) 121 : ReverseVirtualFileMapping(std::move(IFCD.ReverseVirtualFileMapping)), 122 Name(std::move(IFCD.Name)), Hash(IFCD.Hash), 123 Regions(std::move(IFCD.Regions)) {} 124 125 InputFunctionCoverageData(const InputFunctionCoverageData &) = delete; 126 InputFunctionCoverageData & 127 operator=(const InputFunctionCoverageData &) = delete; 128 InputFunctionCoverageData &operator=(InputFunctionCoverageData &&) = delete; 129 }; 130 131 struct CoverageMappingTest : ::testing::TestWithParam<std::tuple<bool, bool>> { 132 bool UseMultipleReaders; 133 StringMap<unsigned> Files; 134 std::vector<std::string> Filenames; 135 std::vector<InputFunctionCoverageData> InputFunctions; 136 std::vector<OutputFunctionCoverageData> OutputFunctions; 137 138 InstrProfWriter ProfileWriter; 139 std::unique_ptr<IndexedInstrProfReader> ProfileReader; 140 141 std::unique_ptr<CoverageMapping> LoadedCoverage; 142 143 void SetUp() override { 144 ProfileWriter.setOutputSparse(std::get<0>(GetParam())); 145 UseMultipleReaders = std::get<1>(GetParam()); 146 } 147 148 unsigned getGlobalFileIndex(StringRef Name) { 149 auto R = Files.find(Name); 150 if (R != Files.end()) 151 return R->second; 152 unsigned Index = Files.size() + 1; 153 Files.try_emplace(Name, Index); 154 return Index; 155 } 156 157 // Return the file index of file 'Name' for the current function. 158 // Add the file into the global map if necessary. 159 // See also InputFunctionCoverageData::ReverseVirtualFileMapping 160 // for additional comments. 161 unsigned getFileIndexForFunction(StringRef Name) { 162 unsigned GlobalIndex = getGlobalFileIndex(Name); 163 auto &CurrentFunctionFileMapping = 164 InputFunctions.back().ReverseVirtualFileMapping; 165 auto R = CurrentFunctionFileMapping.find(GlobalIndex); 166 if (R != CurrentFunctionFileMapping.end()) 167 return R->second; 168 unsigned IndexInFunction = CurrentFunctionFileMapping.size(); 169 CurrentFunctionFileMapping.insert( 170 std::make_pair(GlobalIndex, IndexInFunction)); 171 return IndexInFunction; 172 } 173 174 void startFunction(StringRef FuncName, uint64_t Hash) { 175 InputFunctions.emplace_back(FuncName.str(), Hash); 176 } 177 178 void addCMR(Counter C, StringRef File, unsigned LS, unsigned CS, unsigned LE, 179 unsigned CE, bool Skipped = false) { 180 auto &Regions = InputFunctions.back().Regions; 181 unsigned FileID = getFileIndexForFunction(File); 182 Regions.push_back( 183 Skipped ? CounterMappingRegion::makeSkipped(FileID, LS, CS, LE, CE) 184 : CounterMappingRegion::makeRegion(C, FileID, LS, CS, LE, CE)); 185 } 186 187 void addExpansionCMR(StringRef File, StringRef ExpandedFile, unsigned LS, 188 unsigned CS, unsigned LE, unsigned CE) { 189 InputFunctions.back().Regions.push_back(CounterMappingRegion::makeExpansion( 190 getFileIndexForFunction(File), getFileIndexForFunction(ExpandedFile), 191 LS, CS, LE, CE)); 192 } 193 194 void addExpression(CounterExpression CE) { 195 InputFunctions.back().Expressions.push_back(CE); 196 } 197 198 std::string writeCoverageRegions(InputFunctionCoverageData &Data) { 199 SmallVector<unsigned, 8> FileIDs(Data.ReverseVirtualFileMapping.size()); 200 for (const auto &E : Data.ReverseVirtualFileMapping) 201 FileIDs[E.second] = E.first; 202 std::string Coverage; 203 llvm::raw_string_ostream OS(Coverage); 204 CoverageMappingWriter(FileIDs, Data.Expressions, Data.Regions).write(OS); 205 return OS.str(); 206 } 207 208 void readCoverageRegions(const std::string &Coverage, 209 OutputFunctionCoverageData &Data) { 210 // We will re-use the StringRef in duplicate tests, clear it to avoid 211 // clobber previous ones. 212 Filenames.clear(); 213 Filenames.resize(Files.size() + 1); 214 for (const auto &E : Files) 215 Filenames[E.getValue()] = E.getKey().str(); 216 ArrayRef<std::string> FilenameRefs = llvm::makeArrayRef(Filenames); 217 RawCoverageMappingReader Reader(Coverage, FilenameRefs, Data.Filenames, 218 Data.Expressions, Data.Regions); 219 EXPECT_THAT_ERROR(Reader.read(), Succeeded()); 220 } 221 222 void writeAndReadCoverageRegions(bool EmitFilenames = true) { 223 OutputFunctions.resize(InputFunctions.size()); 224 for (unsigned I = 0; I < InputFunctions.size(); ++I) { 225 std::string Regions = writeCoverageRegions(InputFunctions[I]); 226 readCoverageRegions(Regions, OutputFunctions[I]); 227 OutputFunctions[I].Name = InputFunctions[I].Name; 228 OutputFunctions[I].Hash = InputFunctions[I].Hash; 229 if (!EmitFilenames) 230 OutputFunctions[I].Filenames.clear(); 231 } 232 } 233 234 void readProfCounts() { 235 auto Profile = ProfileWriter.writeBuffer(); 236 auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile)); 237 EXPECT_THAT_ERROR(ReaderOrErr.takeError(), Succeeded()); 238 ProfileReader = std::move(ReaderOrErr.get()); 239 } 240 241 Expected<std::unique_ptr<CoverageMapping>> readOutputFunctions() { 242 std::vector<std::unique_ptr<CoverageMappingReader>> CoverageReaders; 243 if (UseMultipleReaders) { 244 for (const auto &OF : OutputFunctions) { 245 ArrayRef<OutputFunctionCoverageData> Funcs(OF); 246 CoverageReaders.push_back( 247 std::make_unique<CoverageMappingReaderMock>(Funcs)); 248 } 249 } else { 250 ArrayRef<OutputFunctionCoverageData> Funcs(OutputFunctions); 251 CoverageReaders.push_back( 252 std::make_unique<CoverageMappingReaderMock>(Funcs)); 253 } 254 return CoverageMapping::load(CoverageReaders, *ProfileReader); 255 } 256 257 Error loadCoverageMapping(bool EmitFilenames = true) { 258 readProfCounts(); 259 writeAndReadCoverageRegions(EmitFilenames); 260 auto CoverageOrErr = readOutputFunctions(); 261 if (!CoverageOrErr) 262 return CoverageOrErr.takeError(); 263 LoadedCoverage = std::move(CoverageOrErr.get()); 264 return Error::success(); 265 } 266 }; 267 268 TEST_P(CoverageMappingTest, basic_write_read) { 269 startFunction("func", 0x1234); 270 addCMR(Counter::getCounter(0), "foo", 1, 1, 1, 1); 271 addCMR(Counter::getCounter(1), "foo", 2, 1, 2, 2); 272 addCMR(Counter::getZero(), "foo", 3, 1, 3, 4); 273 addCMR(Counter::getCounter(2), "foo", 4, 1, 4, 8); 274 addCMR(Counter::getCounter(3), "bar", 1, 2, 3, 4); 275 276 writeAndReadCoverageRegions(); 277 ASSERT_EQ(1u, InputFunctions.size()); 278 ASSERT_EQ(1u, OutputFunctions.size()); 279 InputFunctionCoverageData &Input = InputFunctions.back(); 280 OutputFunctionCoverageData &Output = OutputFunctions.back(); 281 282 size_t N = makeArrayRef(Input.Regions).size(); 283 ASSERT_EQ(N, Output.Regions.size()); 284 for (size_t I = 0; I < N; ++I) { 285 ASSERT_EQ(Input.Regions[I].Count, Output.Regions[I].Count); 286 ASSERT_EQ(Input.Regions[I].FileID, Output.Regions[I].FileID); 287 ASSERT_EQ(Input.Regions[I].startLoc(), Output.Regions[I].startLoc()); 288 ASSERT_EQ(Input.Regions[I].endLoc(), Output.Regions[I].endLoc()); 289 ASSERT_EQ(Input.Regions[I].Kind, Output.Regions[I].Kind); 290 } 291 } 292 293 TEST_P(CoverageMappingTest, correct_deserialize_for_more_than_two_files) { 294 const char *FileNames[] = {"bar", "baz", "foo"}; 295 static const unsigned N = array_lengthof(FileNames); 296 297 startFunction("func", 0x1234); 298 for (unsigned I = 0; I < N; ++I) 299 // Use LineStart to hold the index of the file name 300 // in order to preserve that information during possible sorting of CMRs. 301 addCMR(Counter::getCounter(0), FileNames[I], I, 1, I, 1); 302 303 writeAndReadCoverageRegions(); 304 ASSERT_EQ(1u, OutputFunctions.size()); 305 OutputFunctionCoverageData &Output = OutputFunctions.back(); 306 307 ASSERT_EQ(N, Output.Regions.size()); 308 ASSERT_EQ(N, Output.Filenames.size()); 309 310 for (unsigned I = 0; I < N; ++I) { 311 ASSERT_GT(N, Output.Regions[I].FileID); 312 ASSERT_GT(N, Output.Regions[I].LineStart); 313 EXPECT_EQ(FileNames[Output.Regions[I].LineStart], 314 Output.Filenames[Output.Regions[I].FileID]); 315 } 316 } 317 318 static const auto Err = [](Error E) { FAIL(); }; 319 320 TEST_P(CoverageMappingTest, load_coverage_for_more_than_two_files) { 321 ProfileWriter.addRecord({"func", 0x1234, {0}}, Err); 322 323 const char *FileNames[] = {"bar", "baz", "foo"}; 324 static const unsigned N = array_lengthof(FileNames); 325 326 startFunction("func", 0x1234); 327 for (unsigned I = 0; I < N; ++I) 328 // Use LineStart to hold the index of the file name 329 // in order to preserve that information during possible sorting of CMRs. 330 addCMR(Counter::getCounter(0), FileNames[I], I, 1, I, 1); 331 332 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 333 334 for (unsigned I = 0; I < N; ++I) { 335 CoverageData Data = LoadedCoverage->getCoverageForFile(FileNames[I]); 336 ASSERT_TRUE(!Data.empty()); 337 EXPECT_EQ(I, Data.begin()->Line); 338 } 339 } 340 341 TEST_P(CoverageMappingTest, load_coverage_with_bogus_function_name) { 342 ProfileWriter.addRecord({"", 0x1234, {10}}, Err); 343 startFunction("", 0x1234); 344 addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5); 345 EXPECT_TRUE(ErrorEquals(coveragemap_error::malformed, loadCoverageMapping())); 346 } 347 348 TEST_P(CoverageMappingTest, load_coverage_for_several_functions) { 349 ProfileWriter.addRecord({"func1", 0x1234, {10}}, Err); 350 ProfileWriter.addRecord({"func2", 0x2345, {20}}, Err); 351 352 startFunction("func1", 0x1234); 353 addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5); 354 355 startFunction("func2", 0x2345); 356 addCMR(Counter::getCounter(0), "bar", 2, 2, 6, 6); 357 358 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 359 360 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 361 EXPECT_EQ(2, std::distance(FunctionRecords.begin(), FunctionRecords.end())); 362 for (const auto &FunctionRecord : FunctionRecords) { 363 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 364 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 365 ASSERT_EQ(2U, Segments.size()); 366 if (FunctionRecord.Name == "func1") { 367 EXPECT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]); 368 EXPECT_EQ(CoverageSegment(5, 5, false), Segments[1]); 369 } else { 370 ASSERT_EQ("func2", FunctionRecord.Name); 371 EXPECT_EQ(CoverageSegment(2, 2, 20, true), Segments[0]); 372 EXPECT_EQ(CoverageSegment(6, 6, false), Segments[1]); 373 } 374 } 375 } 376 377 TEST_P(CoverageMappingTest, create_combined_regions) { 378 ProfileWriter.addRecord({"func1", 0x1234, {1, 2, 3}}, Err); 379 startFunction("func1", 0x1234); 380 381 // Given regions which start at the same location, emit a segment for the 382 // last region. 383 addCMR(Counter::getCounter(0), "file1", 1, 1, 2, 2); 384 addCMR(Counter::getCounter(1), "file1", 1, 1, 2, 2); 385 addCMR(Counter::getCounter(2), "file1", 1, 1, 2, 2); 386 387 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 388 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 389 const auto &FunctionRecord = *FunctionRecords.begin(); 390 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 391 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 392 393 ASSERT_EQ(2U, Segments.size()); 394 EXPECT_EQ(CoverageSegment(1, 1, 6, true), Segments[0]); 395 EXPECT_EQ(CoverageSegment(2, 2, false), Segments[1]); 396 } 397 398 TEST_P(CoverageMappingTest, skipped_segments_have_no_count) { 399 ProfileWriter.addRecord({"func1", 0x1234, {1}}, Err); 400 startFunction("func1", 0x1234); 401 402 addCMR(Counter::getCounter(0), "file1", 1, 1, 5, 5); 403 addCMR(Counter::getCounter(0), "file1", 5, 1, 5, 5, /*Skipped=*/true); 404 405 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 406 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 407 const auto &FunctionRecord = *FunctionRecords.begin(); 408 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 409 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 410 411 ASSERT_EQ(3U, Segments.size()); 412 EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]); 413 EXPECT_EQ(CoverageSegment(5, 1, true), Segments[1]); 414 EXPECT_EQ(CoverageSegment(5, 5, false), Segments[2]); 415 } 416 417 TEST_P(CoverageMappingTest, multiple_regions_end_after_parent_ends) { 418 ProfileWriter.addRecord({"func1", 0x1234, {1, 0}}, Err); 419 startFunction("func1", 0x1234); 420 421 // 1| F{ a{ 422 // 2| 423 // 3| a} b{ c{ 424 // 4| 425 // 5| b} 426 // 6| 427 // 7| c} d{ e{ 428 // 8| 429 // 9| d} e} F} 430 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); // < F 431 addCMR(Counter::getCounter(0), "file1", 1, 1, 3, 5); // < a 432 addCMR(Counter::getCounter(0), "file1", 3, 5, 5, 4); // < b 433 addCMR(Counter::getCounter(1), "file1", 3, 5, 7, 3); // < c 434 addCMR(Counter::getCounter(1), "file1", 7, 3, 9, 2); // < d 435 addCMR(Counter::getCounter(1), "file1", 7, 7, 9, 7); // < e 436 437 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 438 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 439 const auto &FunctionRecord = *FunctionRecords.begin(); 440 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 441 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 442 443 // Old output (not sorted or unique): 444 // Segment at 1:1 with count 1 445 // Segment at 1:1 with count 1 446 // Segment at 3:5 with count 1 447 // Segment at 3:5 with count 0 448 // Segment at 3:5 with count 1 449 // Segment at 5:4 with count 0 450 // Segment at 7:3 with count 1 451 // Segment at 7:3 with count 0 452 // Segment at 7:7 with count 0 453 // Segment at 9:7 with count 0 454 // Segment at 9:2 with count 1 455 // Top level segment at 9:9 456 457 // New output (sorted and unique): 458 // Segment at 1:1 (count = 1), RegionEntry 459 // Segment at 3:5 (count = 1), RegionEntry 460 // Segment at 5:4 (count = 0) 461 // Segment at 7:3 (count = 0), RegionEntry 462 // Segment at 7:7 (count = 0), RegionEntry 463 // Segment at 9:2 (count = 0) 464 // Segment at 9:7 (count = 1) 465 // Segment at 9:9 (count = 0), Skipped 466 467 ASSERT_EQ(8U, Segments.size()); 468 EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]); 469 EXPECT_EQ(CoverageSegment(3, 5, 1, true), Segments[1]); 470 EXPECT_EQ(CoverageSegment(5, 4, 0, false), Segments[2]); 471 EXPECT_EQ(CoverageSegment(7, 3, 0, true), Segments[3]); 472 EXPECT_EQ(CoverageSegment(7, 7, 0, true), Segments[4]); 473 EXPECT_EQ(CoverageSegment(9, 2, 0, false), Segments[5]); 474 EXPECT_EQ(CoverageSegment(9, 7, 1, false), Segments[6]); 475 EXPECT_EQ(CoverageSegment(9, 9, false), Segments[7]); 476 } 477 478 TEST_P(CoverageMappingTest, multiple_completed_segments_at_same_loc) { 479 ProfileWriter.addRecord({"func1", 0x1234, {0, 1, 2}}, Err); 480 startFunction("func1", 0x1234); 481 482 // PR35495 483 addCMR(Counter::getCounter(1), "file1", 2, 1, 18, 2); 484 addCMR(Counter::getCounter(0), "file1", 8, 10, 14, 6); 485 addCMR(Counter::getCounter(0), "file1", 8, 12, 14, 6); 486 addCMR(Counter::getCounter(1), "file1", 9, 1, 14, 6); 487 addCMR(Counter::getCounter(2), "file1", 11, 13, 11, 14); 488 489 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 490 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 491 const auto &FunctionRecord = *FunctionRecords.begin(); 492 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 493 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 494 495 ASSERT_EQ(7U, Segments.size()); 496 EXPECT_EQ(CoverageSegment(2, 1, 1, true), Segments[0]); 497 EXPECT_EQ(CoverageSegment(8, 10, 0, true), Segments[1]); 498 EXPECT_EQ(CoverageSegment(8, 12, 0, true), Segments[2]); 499 EXPECT_EQ(CoverageSegment(9, 1, 1, true), Segments[3]); 500 EXPECT_EQ(CoverageSegment(11, 13, 2, true), Segments[4]); 501 // Use count=1 (from 9:1 -> 14:6), not count=0 (from 8:12 -> 14:6). 502 EXPECT_EQ(CoverageSegment(11, 14, 1, false), Segments[5]); 503 EXPECT_EQ(CoverageSegment(18, 2, false), Segments[6]); 504 } 505 506 TEST_P(CoverageMappingTest, dont_emit_redundant_segments) { 507 ProfileWriter.addRecord({"func1", 0x1234, {1, 1}}, Err); 508 startFunction("func1", 0x1234); 509 510 addCMR(Counter::getCounter(0), "file1", 1, 1, 4, 4); 511 addCMR(Counter::getCounter(1), "file1", 2, 2, 5, 5); 512 addCMR(Counter::getCounter(0), "file1", 3, 3, 6, 6); 513 514 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 515 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 516 const auto &FunctionRecord = *FunctionRecords.begin(); 517 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 518 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 519 520 ASSERT_EQ(5U, Segments.size()); 521 EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]); 522 EXPECT_EQ(CoverageSegment(2, 2, 1, true), Segments[1]); 523 EXPECT_EQ(CoverageSegment(3, 3, 1, true), Segments[2]); 524 EXPECT_EQ(CoverageSegment(4, 4, 1, false), Segments[3]); 525 // A closing segment starting at 5:5 would be redundant: it would have the 526 // same count as the segment starting at 4:4, and has all the same metadata. 527 EXPECT_EQ(CoverageSegment(6, 6, false), Segments[4]); 528 } 529 530 TEST_P(CoverageMappingTest, dont_emit_closing_segment_at_new_region_start) { 531 ProfileWriter.addRecord({"func1", 0x1234, {1}}, Err); 532 startFunction("func1", 0x1234); 533 534 addCMR(Counter::getCounter(0), "file1", 1, 1, 6, 5); 535 addCMR(Counter::getCounter(0), "file1", 2, 2, 6, 5); 536 addCMR(Counter::getCounter(0), "file1", 3, 3, 6, 5); 537 addCMR(Counter::getCounter(0), "file1", 6, 5, 7, 7); 538 539 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 540 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 541 const auto &FunctionRecord = *FunctionRecords.begin(); 542 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 543 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 544 545 ASSERT_EQ(5U, Segments.size()); 546 EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]); 547 EXPECT_EQ(CoverageSegment(2, 2, 1, true), Segments[1]); 548 EXPECT_EQ(CoverageSegment(3, 3, 1, true), Segments[2]); 549 EXPECT_EQ(CoverageSegment(6, 5, 1, true), Segments[3]); 550 // The old segment builder would get this wrong by emitting multiple segments 551 // which start at 6:5 (a few of which were skipped segments). We should just 552 // get a segment for the region entry. 553 EXPECT_EQ(CoverageSegment(7, 7, false), Segments[4]); 554 } 555 556 TEST_P(CoverageMappingTest, handle_consecutive_regions_with_zero_length) { 557 ProfileWriter.addRecord({"func1", 0x1234, {1, 2}}, Err); 558 startFunction("func1", 0x1234); 559 560 addCMR(Counter::getCounter(0), "file1", 1, 1, 1, 1); 561 addCMR(Counter::getCounter(1), "file1", 1, 1, 1, 1); 562 addCMR(Counter::getCounter(0), "file1", 1, 1, 1, 1); 563 addCMR(Counter::getCounter(1), "file1", 1, 1, 1, 1); 564 addCMR(Counter::getCounter(0), "file1", 1, 1, 1, 1); 565 566 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 567 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 568 const auto &FunctionRecord = *FunctionRecords.begin(); 569 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 570 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 571 572 ASSERT_EQ(1U, Segments.size()); 573 EXPECT_EQ(CoverageSegment(1, 1, true), Segments[0]); 574 // We need to get a skipped segment starting at 1:1. In this case there is 575 // also a region entry at 1:1. 576 } 577 578 TEST_P(CoverageMappingTest, handle_sandwiched_zero_length_region) { 579 ProfileWriter.addRecord({"func1", 0x1234, {2, 1}}, Err); 580 startFunction("func1", 0x1234); 581 582 addCMR(Counter::getCounter(0), "file1", 1, 5, 4, 4); 583 addCMR(Counter::getCounter(1), "file1", 1, 9, 1, 50); 584 addCMR(Counter::getCounter(1), "file1", 2, 7, 2, 34); 585 addCMR(Counter::getCounter(1), "file1", 3, 5, 3, 21); 586 addCMR(Counter::getCounter(1), "file1", 3, 21, 3, 21); 587 addCMR(Counter::getCounter(1), "file1", 4, 12, 4, 17); 588 589 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 590 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 591 const auto &FunctionRecord = *FunctionRecords.begin(); 592 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 593 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 594 595 ASSERT_EQ(10U, Segments.size()); 596 EXPECT_EQ(CoverageSegment(1, 5, 2, true), Segments[0]); 597 EXPECT_EQ(CoverageSegment(1, 9, 1, true), Segments[1]); 598 EXPECT_EQ(CoverageSegment(1, 50, 2, false), Segments[2]); 599 EXPECT_EQ(CoverageSegment(2, 7, 1, true), Segments[3]); 600 EXPECT_EQ(CoverageSegment(2, 34, 2, false), Segments[4]); 601 EXPECT_EQ(CoverageSegment(3, 5, 1, true), Segments[5]); 602 EXPECT_EQ(CoverageSegment(3, 21, 2, true), Segments[6]); 603 // Handle the zero-length region by creating a segment with its predecessor's 604 // count (i.e the count from 1:5 -> 4:4). 605 EXPECT_EQ(CoverageSegment(4, 4, false), Segments[7]); 606 // The area between 4:4 and 4:12 is skipped. 607 EXPECT_EQ(CoverageSegment(4, 12, 1, true), Segments[8]); 608 EXPECT_EQ(CoverageSegment(4, 17, false), Segments[9]); 609 } 610 611 TEST_P(CoverageMappingTest, handle_last_completed_region) { 612 ProfileWriter.addRecord({"func1", 0x1234, {1, 2, 3, 4}}, Err); 613 startFunction("func1", 0x1234); 614 615 addCMR(Counter::getCounter(0), "file1", 1, 1, 8, 8); 616 addCMR(Counter::getCounter(1), "file1", 2, 2, 5, 5); 617 addCMR(Counter::getCounter(2), "file1", 3, 3, 4, 4); 618 addCMR(Counter::getCounter(3), "file1", 6, 6, 7, 7); 619 620 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 621 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions(); 622 const auto &FunctionRecord = *FunctionRecords.begin(); 623 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord); 624 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 625 626 ASSERT_EQ(8U, Segments.size()); 627 EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]); 628 EXPECT_EQ(CoverageSegment(2, 2, 2, true), Segments[1]); 629 EXPECT_EQ(CoverageSegment(3, 3, 3, true), Segments[2]); 630 EXPECT_EQ(CoverageSegment(4, 4, 2, false), Segments[3]); 631 EXPECT_EQ(CoverageSegment(5, 5, 1, false), Segments[4]); 632 EXPECT_EQ(CoverageSegment(6, 6, 4, true), Segments[5]); 633 EXPECT_EQ(CoverageSegment(7, 7, 1, false), Segments[6]); 634 EXPECT_EQ(CoverageSegment(8, 8, false), Segments[7]); 635 } 636 637 TEST_P(CoverageMappingTest, expansion_gets_first_counter) { 638 startFunction("func", 0x1234); 639 addCMR(Counter::getCounter(1), "foo", 10, 1, 10, 2); 640 // This starts earlier in "foo", so the expansion should get its counter. 641 addCMR(Counter::getCounter(2), "foo", 1, 1, 20, 1); 642 addExpansionCMR("bar", "foo", 3, 3, 3, 3); 643 644 writeAndReadCoverageRegions(); 645 ASSERT_EQ(1u, OutputFunctions.size()); 646 OutputFunctionCoverageData &Output = OutputFunctions.back(); 647 648 ASSERT_EQ(CounterMappingRegion::ExpansionRegion, Output.Regions[2].Kind); 649 ASSERT_EQ(Counter::getCounter(2), Output.Regions[2].Count); 650 ASSERT_EQ(3U, Output.Regions[2].LineStart); 651 } 652 653 TEST_P(CoverageMappingTest, basic_coverage_iteration) { 654 ProfileWriter.addRecord({"func", 0x1234, {30, 20, 10, 0}}, Err); 655 656 startFunction("func", 0x1234); 657 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 658 addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7); 659 addCMR(Counter::getCounter(2), "file1", 5, 8, 9, 1); 660 addCMR(Counter::getCounter(3), "file1", 10, 10, 11, 11); 661 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 662 663 CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); 664 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 665 ASSERT_EQ(7U, Segments.size()); 666 ASSERT_EQ(CoverageSegment(1, 1, 20, true), Segments[0]); 667 ASSERT_EQ(CoverageSegment(4, 7, 30, false), Segments[1]); 668 ASSERT_EQ(CoverageSegment(5, 8, 10, true), Segments[2]); 669 ASSERT_EQ(CoverageSegment(9, 1, 30, false), Segments[3]); 670 ASSERT_EQ(CoverageSegment(9, 9, false), Segments[4]); 671 ASSERT_EQ(CoverageSegment(10, 10, 0, true), Segments[5]); 672 ASSERT_EQ(CoverageSegment(11, 11, false), Segments[6]); 673 } 674 675 TEST_P(CoverageMappingTest, test_line_coverage_iterator) { 676 ProfileWriter.addRecord({"func", 0x1234, {30, 20, 10, 0}}, Err); 677 678 startFunction("func", 0x1234); 679 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 680 addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7); 681 addCMR(Counter::getCounter(2), "file1", 5, 8, 9, 1); 682 addCMR(Counter::getCounter(3), "file1", 10, 10, 11, 11); 683 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 684 685 CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); 686 687 unsigned Line = 0; 688 unsigned LineCounts[] = {20, 20, 20, 20, 30, 10, 10, 10, 10, 0, 0}; 689 for (const auto &LCS : getLineCoverageStats(Data)) { 690 ASSERT_EQ(Line + 1, LCS.getLine()); 691 errs() << "Line: " << Line + 1 << ", count = " << LCS.getExecutionCount() << "\n"; 692 ASSERT_EQ(LineCounts[Line], LCS.getExecutionCount()); 693 ++Line; 694 } 695 ASSERT_EQ(11U, Line); 696 697 // Check that operator->() works / compiles. 698 ASSERT_EQ(1U, LineCoverageIterator(Data)->getLine()); 699 } 700 701 TEST_P(CoverageMappingTest, uncovered_function) { 702 startFunction("func", 0x1234); 703 addCMR(Counter::getZero(), "file1", 1, 2, 3, 4); 704 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 705 706 CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); 707 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 708 ASSERT_EQ(2U, Segments.size()); 709 ASSERT_EQ(CoverageSegment(1, 2, 0, true), Segments[0]); 710 ASSERT_EQ(CoverageSegment(3, 4, false), Segments[1]); 711 } 712 713 TEST_P(CoverageMappingTest, uncovered_function_with_mapping) { 714 startFunction("func", 0x1234); 715 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 716 addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7); 717 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 718 719 CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); 720 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 721 ASSERT_EQ(3U, Segments.size()); 722 ASSERT_EQ(CoverageSegment(1, 1, 0, true), Segments[0]); 723 ASSERT_EQ(CoverageSegment(4, 7, 0, false), Segments[1]); 724 ASSERT_EQ(CoverageSegment(9, 9, false), Segments[2]); 725 } 726 727 TEST_P(CoverageMappingTest, combine_regions) { 728 ProfileWriter.addRecord({"func", 0x1234, {10, 20, 30}}, Err); 729 730 startFunction("func", 0x1234); 731 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 732 addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4); 733 addCMR(Counter::getCounter(2), "file1", 3, 3, 4, 4); 734 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 735 736 CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); 737 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 738 ASSERT_EQ(4U, Segments.size()); 739 ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]); 740 ASSERT_EQ(CoverageSegment(3, 3, 50, true), Segments[1]); 741 ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]); 742 ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]); 743 } 744 745 TEST_P(CoverageMappingTest, restore_combined_counter_after_nested_region) { 746 ProfileWriter.addRecord({"func", 0x1234, {10, 20, 40}}, Err); 747 748 startFunction("func", 0x1234); 749 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 750 addCMR(Counter::getCounter(1), "file1", 1, 1, 9, 9); 751 addCMR(Counter::getCounter(2), "file1", 3, 3, 5, 5); 752 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 753 754 CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); 755 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 756 ASSERT_EQ(4U, Segments.size()); 757 EXPECT_EQ(CoverageSegment(1, 1, 30, true), Segments[0]); 758 EXPECT_EQ(CoverageSegment(3, 3, 40, true), Segments[1]); 759 EXPECT_EQ(CoverageSegment(5, 5, 30, false), Segments[2]); 760 EXPECT_EQ(CoverageSegment(9, 9, false), Segments[3]); 761 } 762 763 // If CodeRegions and ExpansionRegions cover the same area, 764 // only counts of CodeRegions should be used. 765 TEST_P(CoverageMappingTest, dont_combine_expansions) { 766 ProfileWriter.addRecord({"func", 0x1234, {10, 20}}, Err); 767 ProfileWriter.addRecord({"func", 0x1234, {0, 0}}, Err); 768 769 startFunction("func", 0x1234); 770 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 771 addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4); 772 addCMR(Counter::getCounter(1), "include1", 6, 6, 7, 7); 773 addExpansionCMR("file1", "include1", 3, 3, 4, 4); 774 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 775 776 CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); 777 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 778 ASSERT_EQ(4U, Segments.size()); 779 ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]); 780 ASSERT_EQ(CoverageSegment(3, 3, 20, true), Segments[1]); 781 ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]); 782 ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]); 783 } 784 785 // If an area is covered only by ExpansionRegions, they should be combinated. 786 TEST_P(CoverageMappingTest, combine_expansions) { 787 ProfileWriter.addRecord({"func", 0x1234, {2, 3, 7}}, Err); 788 789 startFunction("func", 0x1234); 790 addCMR(Counter::getCounter(1), "include1", 1, 1, 1, 10); 791 addCMR(Counter::getCounter(2), "include2", 1, 1, 1, 10); 792 addCMR(Counter::getCounter(0), "file", 1, 1, 5, 5); 793 addExpansionCMR("file", "include1", 3, 1, 3, 5); 794 addExpansionCMR("file", "include2", 3, 1, 3, 5); 795 796 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 797 798 CoverageData Data = LoadedCoverage->getCoverageForFile("file"); 799 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 800 ASSERT_EQ(4U, Segments.size()); 801 EXPECT_EQ(CoverageSegment(1, 1, 2, true), Segments[0]); 802 EXPECT_EQ(CoverageSegment(3, 1, 10, true), Segments[1]); 803 EXPECT_EQ(CoverageSegment(3, 5, 2, false), Segments[2]); 804 EXPECT_EQ(CoverageSegment(5, 5, false), Segments[3]); 805 } 806 807 // Test that counters not associated with any code regions are allowed. 808 TEST_P(CoverageMappingTest, non_code_region_counters) { 809 // No records in profdata 810 811 startFunction("func", 0x1234); 812 addCMR(Counter::getCounter(0), "file", 1, 1, 5, 5); 813 addCMR(Counter::getExpression(0), "file", 6, 1, 6, 5); 814 addExpression(CounterExpression( 815 CounterExpression::Add, Counter::getCounter(1), Counter::getCounter(2))); 816 817 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 818 819 std::vector<std::string> Names; 820 for (const auto &Func : LoadedCoverage->getCoveredFunctions()) { 821 Names.push_back(Func.Name); 822 ASSERT_EQ(2U, Func.CountedRegions.size()); 823 } 824 ASSERT_EQ(1U, Names.size()); 825 } 826 827 TEST_P(CoverageMappingTest, strip_filename_prefix) { 828 ProfileWriter.addRecord({"file1:func", 0x1234, {0}}, Err); 829 830 startFunction("file1:func", 0x1234); 831 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 832 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 833 834 std::vector<std::string> Names; 835 for (const auto &Func : LoadedCoverage->getCoveredFunctions()) 836 Names.push_back(Func.Name); 837 ASSERT_EQ(1U, Names.size()); 838 ASSERT_EQ("func", Names[0]); 839 } 840 841 TEST_P(CoverageMappingTest, strip_unknown_filename_prefix) { 842 ProfileWriter.addRecord({"<unknown>:func", 0x1234, {0}}, Err); 843 844 startFunction("<unknown>:func", 0x1234); 845 addCMR(Counter::getCounter(0), "", 1, 1, 9, 9); 846 EXPECT_THAT_ERROR(loadCoverageMapping(/*EmitFilenames=*/false), Succeeded()); 847 848 std::vector<std::string> Names; 849 for (const auto &Func : LoadedCoverage->getCoveredFunctions()) 850 Names.push_back(Func.Name); 851 ASSERT_EQ(1U, Names.size()); 852 ASSERT_EQ("func", Names[0]); 853 } 854 855 TEST_P(CoverageMappingTest, dont_detect_false_instantiations) { 856 ProfileWriter.addRecord({"foo", 0x1234, {10}}, Err); 857 ProfileWriter.addRecord({"bar", 0x2345, {20}}, Err); 858 859 startFunction("foo", 0x1234); 860 addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10); 861 addExpansionCMR("main", "expanded", 4, 1, 4, 5); 862 863 startFunction("bar", 0x2345); 864 addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10); 865 addExpansionCMR("main", "expanded", 9, 1, 9, 5); 866 867 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 868 869 std::vector<InstantiationGroup> InstantiationGroups = 870 LoadedCoverage->getInstantiationGroups("expanded"); 871 ASSERT_TRUE(InstantiationGroups.empty()); 872 } 873 874 TEST_P(CoverageMappingTest, load_coverage_for_expanded_file) { 875 ProfileWriter.addRecord({"func", 0x1234, {10}}, Err); 876 877 startFunction("func", 0x1234); 878 addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10); 879 addExpansionCMR("main", "expanded", 4, 1, 4, 5); 880 881 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 882 883 CoverageData Data = LoadedCoverage->getCoverageForFile("expanded"); 884 std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); 885 ASSERT_EQ(2U, Segments.size()); 886 EXPECT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]); 887 EXPECT_EQ(CoverageSegment(1, 10, false), Segments[1]); 888 } 889 890 TEST_P(CoverageMappingTest, skip_duplicate_function_record) { 891 ProfileWriter.addRecord({"func", 0x1234, {1}}, Err); 892 893 // This record should be loaded. 894 startFunction("func", 0x1234); 895 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 896 897 // This record should be loaded. 898 startFunction("func", 0x1234); 899 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 900 addCMR(Counter::getCounter(0), "file2", 1, 1, 9, 9); 901 902 // This record should be skipped. 903 startFunction("func", 0x1234); 904 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 905 906 // This record should be loaded. 907 startFunction("func", 0x1234); 908 addCMR(Counter::getCounter(0), "file2", 1, 1, 9, 9); 909 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 910 911 // This record should be skipped. 912 startFunction("func", 0x1234); 913 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); 914 addCMR(Counter::getCounter(0), "file2", 1, 1, 9, 9); 915 916 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded()); 917 918 auto Funcs = LoadedCoverage->getCoveredFunctions(); 919 unsigned NumFuncs = std::distance(Funcs.begin(), Funcs.end()); 920 ASSERT_EQ(3U, NumFuncs); 921 } 922 923 INSTANTIATE_TEST_SUITE_P(ParameterizedCovMapTest, CoverageMappingTest, 924 ::testing::Combine(::testing::Bool(), 925 ::testing::Bool())); 926 927 TEST(CoverageMappingTest, filename_roundtrip) { 928 std::vector<std::string> Paths({"dir", "a", "b", "c", "d", "e"}); 929 930 for (bool Compress : {false, true}) { 931 std::string EncodedFilenames; 932 { 933 raw_string_ostream OS(EncodedFilenames); 934 CoverageFilenamesSectionWriter Writer(Paths); 935 Writer.write(OS, Compress); 936 } 937 938 std::vector<std::string> ReadFilenames; 939 RawCoverageFilenamesReader Reader(EncodedFilenames, ReadFilenames); 940 EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded()); 941 942 ASSERT_EQ(ReadFilenames.size(), Paths.size()); 943 for (unsigned I = 1; I < Paths.size(); ++I) { 944 SmallString<256> P(Paths[0]); 945 llvm::sys::path::append(P, Paths[I]); 946 ASSERT_EQ(ReadFilenames[I], P); 947 } 948 } 949 } 950 951 TEST(CoverageMappingTest, filename_compilation_dir) { 952 std::vector<std::string> Paths({"dir", "a", "b", "c", "d", "e"}); 953 954 for (bool Compress : {false, true}) { 955 std::string EncodedFilenames; 956 { 957 raw_string_ostream OS(EncodedFilenames); 958 CoverageFilenamesSectionWriter Writer(Paths); 959 Writer.write(OS, Compress); 960 } 961 962 StringRef CompilationDir = "out"; 963 std::vector<std::string> ReadFilenames; 964 RawCoverageFilenamesReader Reader(EncodedFilenames, ReadFilenames, 965 CompilationDir); 966 EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded()); 967 968 ASSERT_EQ(ReadFilenames.size(), Paths.size()); 969 for (unsigned I = 1; I < Paths.size(); ++I) { 970 SmallString<256> P(CompilationDir); 971 llvm::sys::path::append(P, Paths[I]); 972 ASSERT_EQ(ReadFilenames[I], P); 973 } 974 } 975 } 976 977 } // end anonymous namespace 978