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