1 //===- unittest/ProfileData/CoverageMappingTest.cpp -------------------------=//
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
7 //===----------------------------------------------------------------------===//
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"
23 using namespace coverage
;
25 [[nodiscard
]] static ::testing::AssertionResult
26 ErrorEquals(coveragemap_error Expected
, Error E
) {
27 coveragemap_error Found
;
29 handleAllErrors(std::move(E
), [&](const CoverageMapError
&CME
) {
31 FoundMsg
= CME
.message();
33 if (Expected
== Found
)
34 return ::testing::AssertionSuccess();
35 return ::testing::AssertionFailure() << "error: " << FoundMsg
<< "\n";
40 void PrintTo(const Counter
&C
, ::std::ostream
*os
) {
43 else if (C
.isExpression())
44 *os
<< "Expression " << C
.getExpressionID();
46 *os
<< "Counter " << C
.getCounterID();
49 void PrintTo(const CoverageSegment
&S
, ::std::ostream
*os
) {
50 *os
<< "CoverageSegment(" << S
.Line
<< ", " << S
.Col
<< ", ";
52 *os
<< S
.Count
<< ", ";
53 *os
<< (S
.IsRegionEntry
? "true" : "false") << ")";
60 struct OutputFunctionCoverageData
{
63 std::vector
<StringRef
> Filenames
;
64 std::vector
<CounterMappingRegion
> Regions
;
65 std::vector
<CounterExpression
> Expressions
;
67 OutputFunctionCoverageData() : Hash(0) {}
69 OutputFunctionCoverageData(OutputFunctionCoverageData
&&OFCD
)
70 : Name(OFCD
.Name
), Hash(OFCD
.Hash
), Filenames(std::move(OFCD
.Filenames
)),
71 Regions(std::move(OFCD
.Regions
)) {}
73 OutputFunctionCoverageData(const OutputFunctionCoverageData
&) = delete;
74 OutputFunctionCoverageData
&
75 operator=(const OutputFunctionCoverageData
&) = delete;
76 OutputFunctionCoverageData
&operator=(OutputFunctionCoverageData
&&) = delete;
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
;
87 struct CoverageMappingReaderMock
: CoverageMappingReader
{
88 ArrayRef
<OutputFunctionCoverageData
> Functions
;
90 CoverageMappingReaderMock(ArrayRef
<OutputFunctionCoverageData
> Functions
)
91 : Functions(Functions
) {}
93 Error
readNextRecord(CoverageMappingRecord
&Record
) override
{
94 if (Functions
.empty())
95 return make_error
<CoverageMapError
>(coveragemap_error::eof
);
97 Functions
.front().fillCoverageMappingRecord(Record
);
98 Functions
= Functions
.slice(1);
100 return Error::success();
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
;
114 std::vector
<CounterMappingRegion
> Regions
;
115 std::vector
<CounterExpression
> Expressions
;
117 InputFunctionCoverageData(std::string Name
, uint64_t Hash
)
118 : Name(std::move(Name
)), Hash(Hash
) {}
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
)) {}
125 InputFunctionCoverageData(const InputFunctionCoverageData
&) = delete;
126 InputFunctionCoverageData
&
127 operator=(const InputFunctionCoverageData
&) = delete;
128 InputFunctionCoverageData
&operator=(InputFunctionCoverageData
&&) = delete;
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
;
138 InstrProfWriter ProfileWriter
;
139 std::unique_ptr
<IndexedInstrProfReader
> ProfileReader
;
141 std::unique_ptr
<CoverageMapping
> LoadedCoverage
;
143 void SetUp() override
{
144 ProfileWriter
.setOutputSparse(std::get
<0>(GetParam()));
145 UseMultipleReaders
= std::get
<1>(GetParam());
148 unsigned getGlobalFileIndex(StringRef Name
) {
149 auto R
= Files
.find(Name
);
150 if (R
!= Files
.end())
152 unsigned Index
= Files
.size() + 1;
153 Files
.try_emplace(Name
, Index
);
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())
168 unsigned IndexInFunction
= CurrentFunctionFileMapping
.size();
169 CurrentFunctionFileMapping
.insert(
170 std::make_pair(GlobalIndex
, IndexInFunction
));
171 return IndexInFunction
;
174 void startFunction(StringRef FuncName
, uint64_t Hash
) {
175 InputFunctions
.emplace_back(FuncName
.str(), Hash
);
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
);
183 Skipped
? CounterMappingRegion::makeSkipped(FileID
, LS
, CS
, LE
, CE
)
184 : CounterMappingRegion::makeRegion(C
, FileID
, LS
, CS
, LE
, CE
));
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
),
194 void addExpression(CounterExpression CE
) {
195 InputFunctions
.back().Expressions
.push_back(CE
);
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
);
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.
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());
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
;
230 OutputFunctions
[I
].Filenames
.clear();
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());
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
));
250 ArrayRef
<OutputFunctionCoverageData
> Funcs(OutputFunctions
);
251 CoverageReaders
.push_back(
252 std::make_unique
<CoverageMappingReaderMock
>(Funcs
));
254 return CoverageMapping::load(CoverageReaders
, *ProfileReader
);
257 Error
loadCoverageMapping(bool EmitFilenames
= true) {
259 writeAndReadCoverageRegions(EmitFilenames
);
260 auto CoverageOrErr
= readOutputFunctions();
262 return CoverageOrErr
.takeError();
263 LoadedCoverage
= std::move(CoverageOrErr
.get());
264 return Error::success();
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);
276 writeAndReadCoverageRegions();
277 ASSERT_EQ(1u, InputFunctions
.size());
278 ASSERT_EQ(1u, OutputFunctions
.size());
279 InputFunctionCoverageData
&Input
= InputFunctions
.back();
280 OutputFunctionCoverageData
&Output
= OutputFunctions
.back();
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
);
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
);
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);
303 writeAndReadCoverageRegions();
304 ASSERT_EQ(1u, OutputFunctions
.size());
305 OutputFunctionCoverageData
&Output
= OutputFunctions
.back();
307 ASSERT_EQ(N
, Output
.Regions
.size());
308 ASSERT_EQ(N
, Output
.Filenames
.size());
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
]);
318 static const auto Err
= [](Error E
) { FAIL(); };
320 TEST_P(CoverageMappingTest
, load_coverage_for_more_than_two_files
) {
321 ProfileWriter
.addRecord({"func", 0x1234, {0}}, Err
);
323 const char *FileNames
[] = {"bar", "baz", "foo"};
324 static const unsigned N
= array_lengthof(FileNames
);
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);
332 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
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
);
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()));
348 TEST_P(CoverageMappingTest
, load_coverage_for_several_functions
) {
349 ProfileWriter
.addRecord({"func1", 0x1234, {10}}, Err
);
350 ProfileWriter
.addRecord({"func2", 0x2345, {20}}, Err
);
352 startFunction("func1", 0x1234);
353 addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5);
355 startFunction("func2", 0x2345);
356 addCMR(Counter::getCounter(0), "bar", 2, 2, 6, 6);
358 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
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]);
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]);
377 TEST_P(CoverageMappingTest
, create_combined_regions
) {
378 ProfileWriter
.addRecord({"func1", 0x1234, {1, 2, 3}}, Err
);
379 startFunction("func1", 0x1234);
381 // Given regions which start at the same location, emit a segment for the
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);
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());
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]);
398 TEST_P(CoverageMappingTest
, skipped_segments_have_no_count
) {
399 ProfileWriter
.addRecord({"func1", 0x1234, {1}}, Err
);
400 startFunction("func1", 0x1234);
402 addCMR(Counter::getCounter(0), "file1", 1, 1, 5, 5);
403 addCMR(Counter::getCounter(0), "file1", 5, 1, 5, 5, /*Skipped=*/true);
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());
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]);
417 TEST_P(CoverageMappingTest
, multiple_regions_end_after_parent_ends
) {
418 ProfileWriter
.addRecord({"func1", 0x1234, {1, 0}}, Err
);
419 startFunction("func1", 0x1234);
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
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());
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
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
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]);
478 TEST_P(CoverageMappingTest
, multiple_completed_segments_at_same_loc
) {
479 ProfileWriter
.addRecord({"func1", 0x1234, {0, 1, 2}}, Err
);
480 startFunction("func1", 0x1234);
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);
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());
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]);
506 TEST_P(CoverageMappingTest
, dont_emit_redundant_segments
) {
507 ProfileWriter
.addRecord({"func1", 0x1234, {1, 1}}, Err
);
508 startFunction("func1", 0x1234);
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);
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());
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]);
530 TEST_P(CoverageMappingTest
, dont_emit_closing_segment_at_new_region_start
) {
531 ProfileWriter
.addRecord({"func1", 0x1234, {1}}, Err
);
532 startFunction("func1", 0x1234);
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);
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());
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]);
556 TEST_P(CoverageMappingTest
, handle_consecutive_regions_with_zero_length
) {
557 ProfileWriter
.addRecord({"func1", 0x1234, {1, 2}}, Err
);
558 startFunction("func1", 0x1234);
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);
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());
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.
578 TEST_P(CoverageMappingTest
, handle_sandwiched_zero_length_region
) {
579 ProfileWriter
.addRecord({"func1", 0x1234, {2, 1}}, Err
);
580 startFunction("func1", 0x1234);
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);
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());
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]);
611 TEST_P(CoverageMappingTest
, handle_last_completed_region
) {
612 ProfileWriter
.addRecord({"func1", 0x1234, {1, 2, 3, 4}}, Err
);
613 startFunction("func1", 0x1234);
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);
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());
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]);
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);
644 writeAndReadCoverageRegions();
645 ASSERT_EQ(1u, OutputFunctions
.size());
646 OutputFunctionCoverageData
&Output
= OutputFunctions
.back();
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
);
653 TEST_P(CoverageMappingTest
, basic_coverage_iteration
) {
654 ProfileWriter
.addRecord({"func", 0x1234, {30, 20, 10, 0}}, Err
);
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());
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]);
675 TEST_P(CoverageMappingTest
, test_line_coverage_iterator
) {
676 ProfileWriter
.addRecord({"func", 0x1234, {30, 20, 10, 0}}, Err
);
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());
685 CoverageData Data
= LoadedCoverage
->getCoverageForFile("file1");
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());
695 ASSERT_EQ(11U, Line
);
697 // Check that operator->() works / compiles.
698 ASSERT_EQ(1U, LineCoverageIterator(Data
)->getLine());
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());
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]);
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());
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]);
727 TEST_P(CoverageMappingTest
, combine_regions
) {
728 ProfileWriter
.addRecord({"func", 0x1234, {10, 20, 30}}, Err
);
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());
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]);
745 TEST_P(CoverageMappingTest
, restore_combined_counter_after_nested_region
) {
746 ProfileWriter
.addRecord({"func", 0x1234, {10, 20, 40}}, Err
);
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());
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]);
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
);
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());
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]);
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
);
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);
796 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
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]);
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
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)));
817 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
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());
824 ASSERT_EQ(1U, Names
.size());
827 TEST_P(CoverageMappingTest
, strip_filename_prefix
) {
828 ProfileWriter
.addRecord({"file1:func", 0x1234, {0}}, Err
);
830 startFunction("file1:func", 0x1234);
831 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
832 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
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]);
841 TEST_P(CoverageMappingTest
, strip_unknown_filename_prefix
) {
842 ProfileWriter
.addRecord({"<unknown>:func", 0x1234, {0}}, Err
);
844 startFunction("<unknown>:func", 0x1234);
845 addCMR(Counter::getCounter(0), "", 1, 1, 9, 9);
846 EXPECT_THAT_ERROR(loadCoverageMapping(/*EmitFilenames=*/false), Succeeded());
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]);
855 TEST_P(CoverageMappingTest
, dont_detect_false_instantiations
) {
856 ProfileWriter
.addRecord({"foo", 0x1234, {10}}, Err
);
857 ProfileWriter
.addRecord({"bar", 0x2345, {20}}, Err
);
859 startFunction("foo", 0x1234);
860 addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
861 addExpansionCMR("main", "expanded", 4, 1, 4, 5);
863 startFunction("bar", 0x2345);
864 addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
865 addExpansionCMR("main", "expanded", 9, 1, 9, 5);
867 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
869 std::vector
<InstantiationGroup
> InstantiationGroups
=
870 LoadedCoverage
->getInstantiationGroups("expanded");
871 ASSERT_TRUE(InstantiationGroups
.empty());
874 TEST_P(CoverageMappingTest
, load_coverage_for_expanded_file
) {
875 ProfileWriter
.addRecord({"func", 0x1234, {10}}, Err
);
877 startFunction("func", 0x1234);
878 addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
879 addExpansionCMR("main", "expanded", 4, 1, 4, 5);
881 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
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]);
890 TEST_P(CoverageMappingTest
, skip_duplicate_function_record
) {
891 ProfileWriter
.addRecord({"func", 0x1234, {1}}, Err
);
893 // This record should be loaded.
894 startFunction("func", 0x1234);
895 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
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);
902 // This record should be skipped.
903 startFunction("func", 0x1234);
904 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
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);
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);
916 EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
918 auto Funcs
= LoadedCoverage
->getCoveredFunctions();
919 unsigned NumFuncs
= std::distance(Funcs
.begin(), Funcs
.end());
920 ASSERT_EQ(3U, NumFuncs
);
923 INSTANTIATE_TEST_SUITE_P(ParameterizedCovMapTest
, CoverageMappingTest
,
924 ::testing::Combine(::testing::Bool(),
927 TEST(CoverageMappingTest
, filename_roundtrip
) {
928 std::vector
<std::string
> Paths({"dir", "a", "b", "c", "d", "e"});
930 for (bool Compress
: {false, true}) {
931 std::string EncodedFilenames
;
933 raw_string_ostream
OS(EncodedFilenames
);
934 CoverageFilenamesSectionWriter
Writer(Paths
);
935 Writer
.write(OS
, Compress
);
938 std::vector
<std::string
> ReadFilenames
;
939 RawCoverageFilenamesReader
Reader(EncodedFilenames
, ReadFilenames
);
940 EXPECT_THAT_ERROR(Reader
.read(CovMapVersion::CurrentVersion
), Succeeded());
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
);
951 TEST(CoverageMappingTest
, filename_compilation_dir
) {
952 std::vector
<std::string
> Paths({"dir", "a", "b", "c", "d", "e"});
954 for (bool Compress
: {false, true}) {
955 std::string EncodedFilenames
;
957 raw_string_ostream
OS(EncodedFilenames
);
958 CoverageFilenamesSectionWriter
Writer(Paths
);
959 Writer
.write(OS
, Compress
);
962 StringRef CompilationDir
= "out";
963 std::vector
<std::string
> ReadFilenames
;
964 RawCoverageFilenamesReader
Reader(EncodedFilenames
, ReadFilenames
,
966 EXPECT_THAT_ERROR(Reader
.read(CovMapVersion::CurrentVersion
), Succeeded());
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
);
977 } // end anonymous namespace