llvm.org GIT mirror llvm / e5d4119
[Coverage] Add support for making test data for more than one function. Differential Revision: http://reviews.llvm.org/D18758 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266434 91177308-0d34-0410-b5e6-96231b3b80d8 Igor Kudrin 4 years ago
1 changed file(s) with 181 addition(s) and 95 deletion(s). Raw diff Collapse all Expand all
4848
4949 namespace {
5050
51 struct OneFunctionCoverageReader : CoverageMappingReader {
51 struct OutputFunctionCoverageData {
5252 StringRef Name;
5353 uint64_t Hash;
5454 std::vector Filenames;
55 ArrayRef Regions;
56 bool Done;
57
58 OneFunctionCoverageReader(StringRef Name, uint64_t Hash,
59 ArrayRef Filenames,
60 ArrayRef Regions)
61 : Name(Name), Hash(Hash), Filenames(Filenames), Regions(Regions),
62 Done(false) {}
63
64 std::error_code readNextRecord(CoverageMappingRecord &Record) override {
65 if (Done)
66 return instrprof_error::eof;
67 Done = true;
68
55 std::vector Regions;
56
57 void fillCoverageMappingRecord(CoverageMappingRecord &Record) const {
6958 Record.FunctionName = Name;
7059 Record.FunctionHash = Hash;
7160 Record.Filenames = Filenames;
7261 Record.Expressions = {};
7362 Record.MappingRegions = Regions;
63 }
64 };
65
66 struct CoverageMappingReaderMock : CoverageMappingReader {
67 ArrayRef Functions;
68
69 CoverageMappingReaderMock(ArrayRef Functions)
70 : Functions(Functions) {}
71
72 std::error_code readNextRecord(CoverageMappingRecord &Record) override {
73 if (Functions.empty())
74 return instrprof_error::eof;
75
76 Functions.front().fillCoverageMappingRecord(Record);
77 Functions = Functions.slice(1);
78
7479 return instrprof_error::success;
7580 }
81 };
82
83 struct InputFunctionCoverageData {
84 // Maps the global file index from CoverageMappingTest.Files
85 // to the index of that file within this function. We can't just use
86 // global file indexes here because local indexes have to be dense.
87 // This map is used during serialization to create the virtual file mapping
88 // (from local fileId to global Index) in the head of the per-function
89 // coverage mapping data.
90 SmallDenseMap ReverseVirtualFileMapping;
91 std::string Name;
92 uint64_t Hash;
93 std::vector Regions;
94
95 InputFunctionCoverageData(std::string Name, uint64_t Hash)
96 : Name(std::move(Name)), Hash(Hash) {}
7697 };
7798
7899 struct CoverageMappingTest : ::testing::Test {
79100 StringMap Files;
80 std::vector InputCMRs;
81
82 std::vector OutputFiles;
83 std::vector OutputExpressions;
84 std::vector<CounterMappingRegion> OutputCMRs;
101 std::vector<InputFunctionCoverageData> InputFunctions;
102 std::vector OutputFunctions;
85103
86104 InstrProfWriter ProfileWriter;
87105 std::unique_ptr ProfileReader;
92110 ProfileWriter.setOutputSparse(false);
93111 }
94112
95 unsigned getFile(StringRef Name) {
113 unsigned getGlobalFileIndex(StringRef Name) {
96114 auto R = Files.find(Name);
97115 if (R != Files.end())
98116 return R->second;
101119 return Index;
102120 }
103121
122 // Return the file index of file 'Name' for the current function.
123 // Add the file into the global map if necesary.
124 // See also InputFunctionCoverageData::ReverseVirtualFileMapping
125 // for additional comments.
126 unsigned getFileIndexForFunction(StringRef Name) {
127 unsigned GlobalIndex = getGlobalFileIndex(Name);
128 auto &CurrentFunctionFileMapping =
129 InputFunctions.back().ReverseVirtualFileMapping;
130 auto R = CurrentFunctionFileMapping.find(GlobalIndex);
131 if (R != CurrentFunctionFileMapping.end())
132 return R->second;
133 unsigned IndexInFunction = CurrentFunctionFileMapping.size();
134 CurrentFunctionFileMapping.insert(
135 std::make_pair(GlobalIndex, IndexInFunction));
136 return IndexInFunction;
137 }
138
139 void startFunction(StringRef FuncName, uint64_t Hash) {
140 InputFunctions.emplace_back(FuncName.str(), Hash);
141 }
142
104143 void addCMR(Counter C, StringRef File, unsigned LS, unsigned CS, unsigned LE,
105144 unsigned CE) {
106 InputCMRs.push_back(
107 CounterMappingRegion::makeRegion(C, getFile(File), LS, CS, LE, CE));
145 InputFunctions.back().Regions.push_back(CounterMappingRegion::makeRegion(
146 C, getFileIndexForFunction(File), LS, CS, LE, CE));
108147 }
109148
110149 void addExpansionCMR(StringRef File, StringRef ExpandedFile, unsigned LS,
111150 unsigned CS, unsigned LE, unsigned CE) {
112 InputCMRs.push_back(CounterMappingRegion::makeExpansion(
113 getFile(File), getFile(ExpandedFile), LS, CS, LE, CE));
114 }
115
116 std::string writeCoverageRegions() {
117 SmallVector FileIDs(Files.size());
118 for (unsigned I = 0; I < FileIDs.size(); ++I)
119 FileIDs[I] = I;
151 InputFunctions.back().Regions.push_back(CounterMappingRegion::makeExpansion(
152 getFileIndexForFunction(File), getFileIndexForFunction(ExpandedFile),
153 LS, CS, LE, CE));
154 }
155
156 std::string writeCoverageRegions(InputFunctionCoverageData &Data) {
157 SmallVector FileIDs(Data.ReverseVirtualFileMapping.size());
158 for (const auto &E : Data.ReverseVirtualFileMapping)
159 FileIDs[E.second] = E.first;
120160 std::string Coverage;
121161 llvm::raw_string_ostream OS(Coverage);
122 CoverageMappingWriter(FileIDs, None, InputCMRs).write(OS);
162 CoverageMappingWriter(FileIDs, None, Data.Regions).write(OS);
123163 return OS.str();
124164 }
125165
126 void readCoverageRegions(std::string Coverage) {
166 void readCoverageRegions(std::string Coverage,
167 OutputFunctionCoverageData &Data) {
127168 SmallVector Filenames(Files.size());
128169 for (const auto &E : Files)
129170 Filenames[E.getValue()] = E.getKey();
130 RawCoverageMappingReader Reader(Coverage, Filenames, OutputFiles,
131 OutputExpressions, OutputCMRs);
171 std::vector Expressions;
172 RawCoverageMappingReader Reader(Coverage, Filenames, Data.Filenames,
173 Expressions, Data.Regions);
132174 ASSERT_TRUE(NoError(Reader.read()));
175 }
176
177 void writeAndReadCoverageRegions(bool EmitFilenames = true) {
178 OutputFunctions.resize(InputFunctions.size());
179 for (unsigned I = 0; I < InputFunctions.size(); ++I) {
180 std::string Regions = writeCoverageRegions(InputFunctions[I]);
181 readCoverageRegions(Regions, OutputFunctions[I]);
182 OutputFunctions[I].Name = InputFunctions[I].Name;
183 OutputFunctions[I].Hash = InputFunctions[I].Hash;
184 if (!EmitFilenames)
185 OutputFunctions[I].Filenames.clear();
186 }
133187 }
134188
135189 void readProfCounts() {
139193 ProfileReader = std::move(ReaderOrErr.get());
140194 }
141195
142 void loadCoverageMapping(StringRef FuncName, uint64_t Hash,
143 bool EmitFilenames = true) {
144 std::string Regions = writeCoverageRegions();
145 readCoverageRegions(Regions);
146
147 SmallVector Filenames;
148 if (EmitFilenames) {
149 Filenames.resize(Files.size());
150 for (const auto &E : Files)
151 Filenames[E.getValue()] = E.getKey();
152 }
153 OneFunctionCoverageReader CovReader(FuncName, Hash, Filenames, OutputCMRs);
196 void loadCoverageMapping(bool EmitFilenames = true) {
197 readProfCounts();
198 writeAndReadCoverageRegions(EmitFilenames);
199
200 CoverageMappingReaderMock CovReader(OutputFunctions);
154201 auto CoverageOrErr = CoverageMapping::load(CovReader, *ProfileReader);
155202 ASSERT_TRUE(NoError(CoverageOrErr.getError()));
156203 LoadedCoverage = std::move(CoverageOrErr.get());
167214 };
168215
169216 TEST_P(MaybeSparseCoverageMappingTest, basic_write_read) {
217 startFunction("func", 0x1234);
170218 addCMR(Counter::getCounter(0), "foo", 1, 1, 1, 1);
171219 addCMR(Counter::getCounter(1), "foo", 2, 1, 2, 2);
172220 addCMR(Counter::getZero(), "foo", 3, 1, 3, 4);
173221 addCMR(Counter::getCounter(2), "foo", 4, 1, 4, 8);
174222 addCMR(Counter::getCounter(3), "bar", 1, 2, 3, 4);
175 std::string Coverage = writeCoverageRegions();
176 readCoverageRegions(Coverage);
177
178 size_t N = makeArrayRef(InputCMRs).size();
179 ASSERT_EQ(N, OutputCMRs.size());
223
224 writeAndReadCoverageRegions();
225 ASSERT_EQ(1u, InputFunctions.size());
226 ASSERT_EQ(1u, OutputFunctions.size());
227 InputFunctionCoverageData &Input = InputFunctions.back();
228 OutputFunctionCoverageData &Output = OutputFunctions.back();
229
230 size_t N = makeArrayRef(Input.Regions).size();
231 ASSERT_EQ(N, Output.Regions.size());
180232 for (size_t I = 0; I < N; ++I) {
181 ASSERT_EQ(InputCMRs[I].Count, OutputCMRs[I].Count);
182 ASSERT_EQ(InputCMRs[I].FileID, OutputCMRs[I].FileID);
183 ASSERT_EQ(InputCMRs[I].startLoc(), OutputCMRs[I].startLoc());
184 ASSERT_EQ(InputCMRs[I].endLoc(), OutputCMRs[I].endLoc());
185 ASSERT_EQ(InputCMRs[I].Kind, OutputCMRs[I].Kind);
233 ASSERT_EQ(Input.Regions[I].Count, Output.Regions[I].Count);
234 ASSERT_EQ(Input.Regions[I].FileID, Output.Regions[I].FileID);
235 ASSERT_EQ(Input.Regions[I].startLoc(), Output.Regions[I].startLoc());
236 ASSERT_EQ(Input.Regions[I].endLoc(), Output.Regions[I].endLoc());
237 ASSERT_EQ(Input.Regions[I].Kind, Output.Regions[I].Kind);
186238 }
187239 }
188240
191243 const char *FileNames[] = {"bar", "baz", "foo"};
192244 static const unsigned N = array_lengthof(FileNames);
193245
246 startFunction("func", 0x1234);
194247 for (unsigned I = 0; I < N; ++I)
195248 // Use LineStart to hold the index of the file name
196249 // in order to preserve that information during possible sorting of CMRs.
197250 addCMR(Counter::getCounter(0), FileNames[I], I, 1, I, 1);
198251
199 std::string Coverage = writeCoverageRegions();
200 readCoverageRegions(Coverage);
201
202 ASSERT_EQ(N, OutputCMRs.size());
203 ASSERT_EQ(N, OutputFiles.size());
252 writeAndReadCoverageRegions();
253 ASSERT_EQ(1u, OutputFunctions.size());
254 OutputFunctionCoverageData &Output = OutputFunctions.back();
255
256 ASSERT_EQ(N, Output.Regions.size());
257 ASSERT_EQ(N, Output.Filenames.size());
204258
205259 for (unsigned I = 0; I < N; ++I) {
206 ASSERT_GT(N, OutputCMRs[I].FileID);
207 ASSERT_GT(N, OutputCMRs[I].LineStart);
208 EXPECT_EQ(FileNames[OutputCMRs[I].LineStart],
209 OutputFiles[OutputCMRs[I].FileID]);
260 ASSERT_GT(N, Output.Regions[I].FileID);
261 ASSERT_GT(N, Output.Regions[I].LineStart);
262 EXPECT_EQ(FileNames[Output.Regions[I].LineStart],
263 Output.Filenames[Output.Regions[I].FileID]);
210264 }
211265 }
212266
213267 TEST_P(MaybeSparseCoverageMappingTest, load_coverage_for_more_than_two_files) {
214268 InstrProfRecord Record("func", 0x1234, {0});
215269 ProfileWriter.addRecord(std::move(Record));
216 readProfCounts();
217270
218271 const char *FileNames[] = {"bar", "baz", "foo"};
219272 static const unsigned N = array_lengthof(FileNames);
220273
274 startFunction("func", 0x1234);
221275 for (unsigned I = 0; I < N; ++I)
222276 // Use LineStart to hold the index of the file name
223277 // in order to preserve that information during possible sorting of CMRs.
224278 addCMR(Counter::getCounter(0), FileNames[I], I, 1, I, 1);
225279
226 loadCoverageMapping("func", 0x1234);
280 loadCoverageMapping();
227281
228282 for (unsigned I = 0; I < N; ++I) {
229283 CoverageData Data = LoadedCoverage->getCoverageForFile(FileNames[I]);
232286 }
233287 }
234288
289 TEST_P(MaybeSparseCoverageMappingTest, load_coverage_for_several_functions) {
290 InstrProfRecord RecordFunc1("func1", 0x1234, {10});
291 ProfileWriter.addRecord(std::move(RecordFunc1));
292 InstrProfRecord RecordFunc2("func2", 0x2345, {20});
293 ProfileWriter.addRecord(std::move(RecordFunc2));
294
295 startFunction("func1", 0x1234);
296 addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5);
297
298 startFunction("func2", 0x2345);
299 addCMR(Counter::getCounter(0), "bar", 2, 2, 6, 6);
300
301 loadCoverageMapping();
302
303 const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
304 EXPECT_EQ(2U, std::distance(FunctionRecords.begin(), FunctionRecords.end()));
305 for (const auto &FunctionRecord : FunctionRecords) {
306 CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
307 std::vector Segments(Data.begin(), Data.end());
308 ASSERT_EQ(2U, Segments.size());
309 if (FunctionRecord.Name == "func1") {
310 EXPECT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
311 EXPECT_EQ(CoverageSegment(5, 5, false), Segments[1]);
312 } else {
313 ASSERT_EQ("func2", FunctionRecord.Name);
314 EXPECT_EQ(CoverageSegment(2, 2, 20, true), Segments[0]);
315 EXPECT_EQ(CoverageSegment(6, 6, false), Segments[1]);
316 }
317 }
318 }
319
235320 TEST_P(MaybeSparseCoverageMappingTest, expansion_gets_first_counter) {
321 startFunction("func", 0x1234);
236322 addCMR(Counter::getCounter(1), "foo", 10, 1, 10, 2);
237323 // This starts earlier in "foo", so the expansion should get its counter.
238324 addCMR(Counter::getCounter(2), "foo", 1, 1, 20, 1);
239325 addExpansionCMR("bar", "foo", 3, 3, 3, 3);
240 std::string Coverage = writeCoverageRegions();
241 readCoverageRegions(Coverage);
242
243 ASSERT_EQ(CounterMappingRegion::ExpansionRegion, OutputCMRs[2].Kind);
244 ASSERT_EQ(Counter::getCounter(2), OutputCMRs[2].Count);
245 ASSERT_EQ(3U, OutputCMRs[2].LineStart);
326
327 writeAndReadCoverageRegions();
328 ASSERT_EQ(1u, OutputFunctions.size());
329 OutputFunctionCoverageData &Output = OutputFunctions.back();
330
331 ASSERT_EQ(CounterMappingRegion::ExpansionRegion, Output.Regions[2].Kind);
332 ASSERT_EQ(Counter::getCounter(2), Output.Regions[2].Count);
333 ASSERT_EQ(3U, Output.Regions[2].LineStart);
246334 }
247335
248336 TEST_P(MaybeSparseCoverageMappingTest, basic_coverage_iteration) {
249337 InstrProfRecord Record("func", 0x1234, {30, 20, 10, 0});
250338 ProfileWriter.addRecord(std::move(Record));
251 readProfCounts();
252
339
340 startFunction("func", 0x1234);
253341 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
254342 addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7);
255343 addCMR(Counter::getCounter(2), "file1", 5, 8, 9, 1);
256344 addCMR(Counter::getCounter(3), "file1", 10, 10, 11, 11);
257 loadCoverageMapping("func", 0x1234);
345 loadCoverageMapping();
258346
259347 CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
260348 std::vector Segments(Data.begin(), Data.end());
269357 }
270358
271359 TEST_P(MaybeSparseCoverageMappingTest, uncovered_function) {
272 readProfCounts();
273
360 startFunction("func", 0x1234);
274361 addCMR(Counter::getZero(), "file1", 1, 2, 3, 4);
275 loadCoverageMapping("func", 0x1234);
362 loadCoverageMapping();
276363
277364 CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
278365 std::vector Segments(Data.begin(), Data.end());
282369 }
283370
284371 TEST_P(MaybeSparseCoverageMappingTest, uncovered_function_with_mapping) {
285 readProfCounts();
286
372 startFunction("func", 0x1234);
287373 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
288374 addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7);
289 loadCoverageMapping("func", 0x1234);
375 loadCoverageMapping();
290376
291377 CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
292378 std::vector Segments(Data.begin(), Data.end());
299385 TEST_P(MaybeSparseCoverageMappingTest, combine_regions) {
300386 InstrProfRecord Record("func", 0x1234, {10, 20, 30});
301387 ProfileWriter.addRecord(std::move(Record));
302 readProfCounts();
303
388
389 startFunction("func", 0x1234);
304390 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
305391 addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4);
306392 addCMR(Counter::getCounter(2), "file1", 3, 3, 4, 4);
307 loadCoverageMapping("func", 0x1234);
393 loadCoverageMapping();
308394
309395 CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
310396 std::vector Segments(Data.begin(), Data.end());
320406 InstrProfRecord Record2("func", 0x1234, {0, 0});
321407 ProfileWriter.addRecord(std::move(Record1));
322408 ProfileWriter.addRecord(std::move(Record2));
323 readProfCounts();
324
409
410 startFunction("func", 0x1234);
325411 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
326412 addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4);
327413 addCMR(Counter::getCounter(1), "include1", 6, 6, 7, 7);
328414 addExpansionCMR("file1", "include1", 3, 3, 4, 4);
329 loadCoverageMapping("func", 0x1234);
415 loadCoverageMapping();
330416
331417 CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
332418 std::vector Segments(Data.begin(), Data.end());
340426 TEST_P(MaybeSparseCoverageMappingTest, strip_filename_prefix) {
341427 InstrProfRecord Record("file1:func", 0x1234, {0});
342428 ProfileWriter.addRecord(std::move(Record));
343 readProfCounts();
344
429
430 startFunction("file1:func", 0x1234);
345431 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
346 loadCoverageMapping("file1:func", 0x1234);
432 loadCoverageMapping();
347433
348434 std::vector Names;
349435 for (const auto &Func : LoadedCoverage->getCoveredFunctions())
355441 TEST_P(MaybeSparseCoverageMappingTest, strip_unknown_filename_prefix) {
356442 InstrProfRecord Record(":func", 0x1234, {0});
357443 ProfileWriter.addRecord(std::move(Record));
358 readProfCounts();
359
444
445 startFunction(":func", 0x1234);
360446 addCMR(Counter::getCounter(0), "", 1, 1, 9, 9);
361 loadCoverageMapping(":func", 0x1234, /*EmitFilenames=*/false);
447 loadCoverageMapping(/*EmitFilenames=*/false);
362448
363449 std::vector Names;
364450 for (const auto &Func : LoadedCoverage->getCoveredFunctions())