CoverageMappingTest.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. //===- unittest/ProfileData/CoverageMappingTest.cpp -------------------------=//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  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 "gtest/gtest.h"
  16. #include <ostream>
  17. #include <utility>
  18. using namespace llvm;
  19. using namespace coverage;
  20. static ::testing::AssertionResult NoError(Error E) {
  21. if (!E)
  22. return ::testing::AssertionSuccess();
  23. return ::testing::AssertionFailure() << "error: " << toString(std::move(E))
  24. << "\n";
  25. }
  26. namespace llvm {
  27. namespace coverage {
  28. void PrintTo(const Counter &C, ::std::ostream *os) {
  29. if (C.isZero())
  30. *os << "Zero";
  31. else if (C.isExpression())
  32. *os << "Expression " << C.getExpressionID();
  33. else
  34. *os << "Counter " << C.getCounterID();
  35. }
  36. void PrintTo(const CoverageSegment &S, ::std::ostream *os) {
  37. *os << "CoverageSegment(" << S.Line << ", " << S.Col << ", ";
  38. if (S.HasCount)
  39. *os << S.Count << ", ";
  40. *os << (S.IsRegionEntry ? "true" : "false") << ")";
  41. }
  42. }
  43. }
  44. namespace {
  45. struct OutputFunctionCoverageData {
  46. StringRef Name;
  47. uint64_t Hash;
  48. std::vector<StringRef> Filenames;
  49. std::vector<CounterMappingRegion> Regions;
  50. OutputFunctionCoverageData() : Hash(0) {}
  51. OutputFunctionCoverageData(OutputFunctionCoverageData &&OFCD)
  52. : Name(OFCD.Name), Hash(OFCD.Hash), Filenames(std::move(OFCD.Filenames)),
  53. Regions(std::move(OFCD.Regions)) {}
  54. OutputFunctionCoverageData(const OutputFunctionCoverageData &) = delete;
  55. OutputFunctionCoverageData &
  56. operator=(const OutputFunctionCoverageData &) = delete;
  57. OutputFunctionCoverageData &operator=(OutputFunctionCoverageData &&) = delete;
  58. void fillCoverageMappingRecord(CoverageMappingRecord &Record) const {
  59. Record.FunctionName = Name;
  60. Record.FunctionHash = Hash;
  61. Record.Filenames = Filenames;
  62. Record.Expressions = {};
  63. Record.MappingRegions = Regions;
  64. }
  65. };
  66. struct CoverageMappingReaderMock : CoverageMappingReader {
  67. ArrayRef<OutputFunctionCoverageData> Functions;
  68. CoverageMappingReaderMock(ArrayRef<OutputFunctionCoverageData> Functions)
  69. : Functions(Functions) {}
  70. Error readNextRecord(CoverageMappingRecord &Record) override {
  71. if (Functions.empty())
  72. return make_error<CoverageMapError>(coveragemap_error::eof);
  73. Functions.front().fillCoverageMappingRecord(Record);
  74. Functions = Functions.slice(1);
  75. return Error::success();
  76. }
  77. };
  78. struct InputFunctionCoverageData {
  79. // Maps the global file index from CoverageMappingTest.Files
  80. // to the index of that file within this function. We can't just use
  81. // global file indexes here because local indexes have to be dense.
  82. // This map is used during serialization to create the virtual file mapping
  83. // (from local fileId to global Index) in the head of the per-function
  84. // coverage mapping data.
  85. SmallDenseMap<unsigned, unsigned> ReverseVirtualFileMapping;
  86. std::string Name;
  87. uint64_t Hash;
  88. std::vector<CounterMappingRegion> Regions;
  89. InputFunctionCoverageData(std::string Name, uint64_t Hash)
  90. : Name(std::move(Name)), Hash(Hash) {}
  91. InputFunctionCoverageData(InputFunctionCoverageData &&IFCD)
  92. : ReverseVirtualFileMapping(std::move(IFCD.ReverseVirtualFileMapping)),
  93. Name(std::move(IFCD.Name)), Hash(IFCD.Hash),
  94. Regions(std::move(IFCD.Regions)) {}
  95. InputFunctionCoverageData(const InputFunctionCoverageData &) = delete;
  96. InputFunctionCoverageData &
  97. operator=(const InputFunctionCoverageData &) = delete;
  98. InputFunctionCoverageData &operator=(InputFunctionCoverageData &&) = delete;
  99. };
  100. struct CoverageMappingTest : ::testing::TestWithParam<std::pair<bool, bool>> {
  101. bool UseMultipleReaders;
  102. StringMap<unsigned> Files;
  103. std::vector<InputFunctionCoverageData> InputFunctions;
  104. std::vector<OutputFunctionCoverageData> OutputFunctions;
  105. InstrProfWriter ProfileWriter;
  106. std::unique_ptr<IndexedInstrProfReader> ProfileReader;
  107. std::unique_ptr<CoverageMapping> LoadedCoverage;
  108. void SetUp() override {
  109. ProfileWriter.setOutputSparse(GetParam().first);
  110. UseMultipleReaders = GetParam().second;
  111. }
  112. unsigned getGlobalFileIndex(StringRef Name) {
  113. auto R = Files.find(Name);
  114. if (R != Files.end())
  115. return R->second;
  116. unsigned Index = Files.size();
  117. Files.try_emplace(Name, Index);
  118. return Index;
  119. }
  120. // Return the file index of file 'Name' for the current function.
  121. // Add the file into the global map if necessary.
  122. // See also InputFunctionCoverageData::ReverseVirtualFileMapping
  123. // for additional comments.
  124. unsigned getFileIndexForFunction(StringRef Name) {
  125. unsigned GlobalIndex = getGlobalFileIndex(Name);
  126. auto &CurrentFunctionFileMapping =
  127. InputFunctions.back().ReverseVirtualFileMapping;
  128. auto R = CurrentFunctionFileMapping.find(GlobalIndex);
  129. if (R != CurrentFunctionFileMapping.end())
  130. return R->second;
  131. unsigned IndexInFunction = CurrentFunctionFileMapping.size();
  132. CurrentFunctionFileMapping.insert(
  133. std::make_pair(GlobalIndex, IndexInFunction));
  134. return IndexInFunction;
  135. }
  136. void startFunction(StringRef FuncName, uint64_t Hash) {
  137. InputFunctions.emplace_back(FuncName.str(), Hash);
  138. }
  139. void addCMR(Counter C, StringRef File, unsigned LS, unsigned CS, unsigned LE,
  140. unsigned CE) {
  141. InputFunctions.back().Regions.push_back(CounterMappingRegion::makeRegion(
  142. C, getFileIndexForFunction(File), LS, CS, LE, CE));
  143. }
  144. void addExpansionCMR(StringRef File, StringRef ExpandedFile, unsigned LS,
  145. unsigned CS, unsigned LE, unsigned CE) {
  146. InputFunctions.back().Regions.push_back(CounterMappingRegion::makeExpansion(
  147. getFileIndexForFunction(File), getFileIndexForFunction(ExpandedFile),
  148. LS, CS, LE, CE));
  149. }
  150. std::string writeCoverageRegions(InputFunctionCoverageData &Data) {
  151. SmallVector<unsigned, 8> FileIDs(Data.ReverseVirtualFileMapping.size());
  152. for (const auto &E : Data.ReverseVirtualFileMapping)
  153. FileIDs[E.second] = E.first;
  154. std::string Coverage;
  155. llvm::raw_string_ostream OS(Coverage);
  156. CoverageMappingWriter(FileIDs, None, Data.Regions).write(OS);
  157. return OS.str();
  158. }
  159. void readCoverageRegions(const std::string &Coverage,
  160. OutputFunctionCoverageData &Data) {
  161. SmallVector<StringRef, 8> Filenames(Files.size());
  162. for (const auto &E : Files)
  163. Filenames[E.getValue()] = E.getKey();
  164. std::vector<CounterExpression> Expressions;
  165. RawCoverageMappingReader Reader(Coverage, Filenames, Data.Filenames,
  166. Expressions, Data.Regions);
  167. ASSERT_TRUE(NoError(Reader.read()));
  168. }
  169. void writeAndReadCoverageRegions(bool EmitFilenames = true) {
  170. OutputFunctions.resize(InputFunctions.size());
  171. for (unsigned I = 0; I < InputFunctions.size(); ++I) {
  172. std::string Regions = writeCoverageRegions(InputFunctions[I]);
  173. readCoverageRegions(Regions, OutputFunctions[I]);
  174. OutputFunctions[I].Name = InputFunctions[I].Name;
  175. OutputFunctions[I].Hash = InputFunctions[I].Hash;
  176. if (!EmitFilenames)
  177. OutputFunctions[I].Filenames.clear();
  178. }
  179. }
  180. void readProfCounts() {
  181. auto Profile = ProfileWriter.writeBuffer();
  182. auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile));
  183. ASSERT_TRUE(NoError(ReaderOrErr.takeError()));
  184. ProfileReader = std::move(ReaderOrErr.get());
  185. }
  186. Expected<std::unique_ptr<CoverageMapping>> readOutputFunctions() {
  187. if (!UseMultipleReaders) {
  188. CoverageMappingReaderMock CovReader(OutputFunctions);
  189. return CoverageMapping::load(CovReader, *ProfileReader);
  190. }
  191. std::vector<std::unique_ptr<CoverageMappingReader>> CoverageReaders;
  192. for (const auto &OF : OutputFunctions) {
  193. ArrayRef<OutputFunctionCoverageData> Funcs(OF);
  194. CoverageReaders.push_back(make_unique<CoverageMappingReaderMock>(Funcs));
  195. }
  196. return CoverageMapping::load(CoverageReaders, *ProfileReader);
  197. }
  198. void loadCoverageMapping(bool EmitFilenames = true) {
  199. readProfCounts();
  200. writeAndReadCoverageRegions(EmitFilenames);
  201. auto CoverageOrErr = readOutputFunctions();
  202. ASSERT_TRUE(NoError(CoverageOrErr.takeError()));
  203. LoadedCoverage = std::move(CoverageOrErr.get());
  204. }
  205. };
  206. TEST_P(CoverageMappingTest, basic_write_read) {
  207. startFunction("func", 0x1234);
  208. addCMR(Counter::getCounter(0), "foo", 1, 1, 1, 1);
  209. addCMR(Counter::getCounter(1), "foo", 2, 1, 2, 2);
  210. addCMR(Counter::getZero(), "foo", 3, 1, 3, 4);
  211. addCMR(Counter::getCounter(2), "foo", 4, 1, 4, 8);
  212. addCMR(Counter::getCounter(3), "bar", 1, 2, 3, 4);
  213. writeAndReadCoverageRegions();
  214. ASSERT_EQ(1u, InputFunctions.size());
  215. ASSERT_EQ(1u, OutputFunctions.size());
  216. InputFunctionCoverageData &Input = InputFunctions.back();
  217. OutputFunctionCoverageData &Output = OutputFunctions.back();
  218. size_t N = makeArrayRef(Input.Regions).size();
  219. ASSERT_EQ(N, Output.Regions.size());
  220. for (size_t I = 0; I < N; ++I) {
  221. ASSERT_EQ(Input.Regions[I].Count, Output.Regions[I].Count);
  222. ASSERT_EQ(Input.Regions[I].FileID, Output.Regions[I].FileID);
  223. ASSERT_EQ(Input.Regions[I].startLoc(), Output.Regions[I].startLoc());
  224. ASSERT_EQ(Input.Regions[I].endLoc(), Output.Regions[I].endLoc());
  225. ASSERT_EQ(Input.Regions[I].Kind, Output.Regions[I].Kind);
  226. }
  227. }
  228. TEST_P(CoverageMappingTest, correct_deserialize_for_more_than_two_files) {
  229. const char *FileNames[] = {"bar", "baz", "foo"};
  230. static const unsigned N = array_lengthof(FileNames);
  231. startFunction("func", 0x1234);
  232. for (unsigned I = 0; I < N; ++I)
  233. // Use LineStart to hold the index of the file name
  234. // in order to preserve that information during possible sorting of CMRs.
  235. addCMR(Counter::getCounter(0), FileNames[I], I, 1, I, 1);
  236. writeAndReadCoverageRegions();
  237. ASSERT_EQ(1u, OutputFunctions.size());
  238. OutputFunctionCoverageData &Output = OutputFunctions.back();
  239. ASSERT_EQ(N, Output.Regions.size());
  240. ASSERT_EQ(N, Output.Filenames.size());
  241. for (unsigned I = 0; I < N; ++I) {
  242. ASSERT_GT(N, Output.Regions[I].FileID);
  243. ASSERT_GT(N, Output.Regions[I].LineStart);
  244. EXPECT_EQ(FileNames[Output.Regions[I].LineStart],
  245. Output.Filenames[Output.Regions[I].FileID]);
  246. }
  247. }
  248. TEST_P(CoverageMappingTest, load_coverage_for_more_than_two_files) {
  249. InstrProfRecord Record("func", 0x1234, {0});
  250. NoError(ProfileWriter.addRecord(std::move(Record)));
  251. const char *FileNames[] = {"bar", "baz", "foo"};
  252. static const unsigned N = array_lengthof(FileNames);
  253. startFunction("func", 0x1234);
  254. for (unsigned I = 0; I < N; ++I)
  255. // Use LineStart to hold the index of the file name
  256. // in order to preserve that information during possible sorting of CMRs.
  257. addCMR(Counter::getCounter(0), FileNames[I], I, 1, I, 1);
  258. loadCoverageMapping();
  259. for (unsigned I = 0; I < N; ++I) {
  260. CoverageData Data = LoadedCoverage->getCoverageForFile(FileNames[I]);
  261. ASSERT_TRUE(!Data.empty());
  262. EXPECT_EQ(I, Data.begin()->Line);
  263. }
  264. }
  265. TEST_P(CoverageMappingTest, load_coverage_for_several_functions) {
  266. InstrProfRecord RecordFunc1("func1", 0x1234, {10});
  267. NoError(ProfileWriter.addRecord(std::move(RecordFunc1)));
  268. InstrProfRecord RecordFunc2("func2", 0x2345, {20});
  269. NoError(ProfileWriter.addRecord(std::move(RecordFunc2)));
  270. startFunction("func1", 0x1234);
  271. addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5);
  272. startFunction("func2", 0x2345);
  273. addCMR(Counter::getCounter(0), "bar", 2, 2, 6, 6);
  274. loadCoverageMapping();
  275. const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
  276. EXPECT_EQ(2U, std::distance(FunctionRecords.begin(), FunctionRecords.end()));
  277. for (const auto &FunctionRecord : FunctionRecords) {
  278. CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
  279. std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
  280. ASSERT_EQ(2U, Segments.size());
  281. if (FunctionRecord.Name == "func1") {
  282. EXPECT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
  283. EXPECT_EQ(CoverageSegment(5, 5, false), Segments[1]);
  284. } else {
  285. ASSERT_EQ("func2", FunctionRecord.Name);
  286. EXPECT_EQ(CoverageSegment(2, 2, 20, true), Segments[0]);
  287. EXPECT_EQ(CoverageSegment(6, 6, false), Segments[1]);
  288. }
  289. }
  290. }
  291. TEST_P(CoverageMappingTest, expansion_gets_first_counter) {
  292. startFunction("func", 0x1234);
  293. addCMR(Counter::getCounter(1), "foo", 10, 1, 10, 2);
  294. // This starts earlier in "foo", so the expansion should get its counter.
  295. addCMR(Counter::getCounter(2), "foo", 1, 1, 20, 1);
  296. addExpansionCMR("bar", "foo", 3, 3, 3, 3);
  297. writeAndReadCoverageRegions();
  298. ASSERT_EQ(1u, OutputFunctions.size());
  299. OutputFunctionCoverageData &Output = OutputFunctions.back();
  300. ASSERT_EQ(CounterMappingRegion::ExpansionRegion, Output.Regions[2].Kind);
  301. ASSERT_EQ(Counter::getCounter(2), Output.Regions[2].Count);
  302. ASSERT_EQ(3U, Output.Regions[2].LineStart);
  303. }
  304. TEST_P(CoverageMappingTest, basic_coverage_iteration) {
  305. InstrProfRecord Record("func", 0x1234, {30, 20, 10, 0});
  306. NoError(ProfileWriter.addRecord(std::move(Record)));
  307. startFunction("func", 0x1234);
  308. addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
  309. addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7);
  310. addCMR(Counter::getCounter(2), "file1", 5, 8, 9, 1);
  311. addCMR(Counter::getCounter(3), "file1", 10, 10, 11, 11);
  312. loadCoverageMapping();
  313. CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
  314. std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
  315. ASSERT_EQ(7U, Segments.size());
  316. ASSERT_EQ(CoverageSegment(1, 1, 20, true), Segments[0]);
  317. ASSERT_EQ(CoverageSegment(4, 7, 30, false), Segments[1]);
  318. ASSERT_EQ(CoverageSegment(5, 8, 10, true), Segments[2]);
  319. ASSERT_EQ(CoverageSegment(9, 1, 30, false), Segments[3]);
  320. ASSERT_EQ(CoverageSegment(9, 9, false), Segments[4]);
  321. ASSERT_EQ(CoverageSegment(10, 10, 0, true), Segments[5]);
  322. ASSERT_EQ(CoverageSegment(11, 11, false), Segments[6]);
  323. }
  324. TEST_P(CoverageMappingTest, uncovered_function) {
  325. startFunction("func", 0x1234);
  326. addCMR(Counter::getZero(), "file1", 1, 2, 3, 4);
  327. loadCoverageMapping();
  328. CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
  329. std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
  330. ASSERT_EQ(2U, Segments.size());
  331. ASSERT_EQ(CoverageSegment(1, 2, 0, true), Segments[0]);
  332. ASSERT_EQ(CoverageSegment(3, 4, false), Segments[1]);
  333. }
  334. TEST_P(CoverageMappingTest, uncovered_function_with_mapping) {
  335. startFunction("func", 0x1234);
  336. addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
  337. addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7);
  338. loadCoverageMapping();
  339. CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
  340. std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
  341. ASSERT_EQ(3U, Segments.size());
  342. ASSERT_EQ(CoverageSegment(1, 1, 0, true), Segments[0]);
  343. ASSERT_EQ(CoverageSegment(4, 7, 0, false), Segments[1]);
  344. ASSERT_EQ(CoverageSegment(9, 9, false), Segments[2]);
  345. }
  346. TEST_P(CoverageMappingTest, combine_regions) {
  347. InstrProfRecord Record("func", 0x1234, {10, 20, 30});
  348. NoError(ProfileWriter.addRecord(std::move(Record)));
  349. startFunction("func", 0x1234);
  350. addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
  351. addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4);
  352. addCMR(Counter::getCounter(2), "file1", 3, 3, 4, 4);
  353. loadCoverageMapping();
  354. CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
  355. std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
  356. ASSERT_EQ(4U, Segments.size());
  357. ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
  358. ASSERT_EQ(CoverageSegment(3, 3, 50, true), Segments[1]);
  359. ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]);
  360. ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]);
  361. }
  362. TEST_P(CoverageMappingTest, restore_combined_counter_after_nested_region) {
  363. InstrProfRecord Record("func", 0x1234, {10, 20, 40});
  364. NoError(ProfileWriter.addRecord(std::move(Record)));
  365. startFunction("func", 0x1234);
  366. addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
  367. addCMR(Counter::getCounter(1), "file1", 1, 1, 9, 9);
  368. addCMR(Counter::getCounter(2), "file1", 3, 3, 5, 5);
  369. loadCoverageMapping();
  370. CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
  371. std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
  372. ASSERT_EQ(4U, Segments.size());
  373. EXPECT_EQ(CoverageSegment(1, 1, 30, true), Segments[0]);
  374. EXPECT_EQ(CoverageSegment(3, 3, 40, true), Segments[1]);
  375. EXPECT_EQ(CoverageSegment(5, 5, 30, false), Segments[2]);
  376. EXPECT_EQ(CoverageSegment(9, 9, false), Segments[3]);
  377. }
  378. // If CodeRegions and ExpansionRegions cover the same area,
  379. // only counts of CodeRegions should be used.
  380. TEST_P(CoverageMappingTest, dont_combine_expansions) {
  381. InstrProfRecord Record1("func", 0x1234, {10, 20});
  382. InstrProfRecord Record2("func", 0x1234, {0, 0});
  383. NoError(ProfileWriter.addRecord(std::move(Record1)));
  384. NoError(ProfileWriter.addRecord(std::move(Record2)));
  385. startFunction("func", 0x1234);
  386. addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
  387. addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4);
  388. addCMR(Counter::getCounter(1), "include1", 6, 6, 7, 7);
  389. addExpansionCMR("file1", "include1", 3, 3, 4, 4);
  390. loadCoverageMapping();
  391. CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
  392. std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
  393. ASSERT_EQ(4U, Segments.size());
  394. ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
  395. ASSERT_EQ(CoverageSegment(3, 3, 20, true), Segments[1]);
  396. ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]);
  397. ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]);
  398. }
  399. // If an area is covered only by ExpansionRegions, they should be combinated.
  400. TEST_P(CoverageMappingTest, combine_expansions) {
  401. InstrProfRecord Record("func", 0x1234, {2, 3, 7});
  402. NoError(ProfileWriter.addRecord(std::move(Record)));
  403. startFunction("func", 0x1234);
  404. addCMR(Counter::getCounter(1), "include1", 1, 1, 1, 10);
  405. addCMR(Counter::getCounter(2), "include2", 1, 1, 1, 10);
  406. addCMR(Counter::getCounter(0), "file", 1, 1, 5, 5);
  407. addExpansionCMR("file", "include1", 3, 1, 3, 5);
  408. addExpansionCMR("file", "include2", 3, 1, 3, 5);
  409. loadCoverageMapping();
  410. CoverageData Data = LoadedCoverage->getCoverageForFile("file");
  411. std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
  412. ASSERT_EQ(4U, Segments.size());
  413. EXPECT_EQ(CoverageSegment(1, 1, 2, true), Segments[0]);
  414. EXPECT_EQ(CoverageSegment(3, 1, 10, true), Segments[1]);
  415. EXPECT_EQ(CoverageSegment(3, 5, 2, false), Segments[2]);
  416. EXPECT_EQ(CoverageSegment(5, 5, false), Segments[3]);
  417. }
  418. TEST_P(CoverageMappingTest, strip_filename_prefix) {
  419. InstrProfRecord Record("file1:func", 0x1234, {0});
  420. NoError(ProfileWriter.addRecord(std::move(Record)));
  421. startFunction("file1:func", 0x1234);
  422. addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
  423. loadCoverageMapping();
  424. std::vector<std::string> Names;
  425. for (const auto &Func : LoadedCoverage->getCoveredFunctions())
  426. Names.push_back(Func.Name);
  427. ASSERT_EQ(1U, Names.size());
  428. ASSERT_EQ("func", Names[0]);
  429. }
  430. TEST_P(CoverageMappingTest, strip_unknown_filename_prefix) {
  431. InstrProfRecord Record("<unknown>:func", 0x1234, {0});
  432. NoError(ProfileWriter.addRecord(std::move(Record)));
  433. startFunction("<unknown>:func", 0x1234);
  434. addCMR(Counter::getCounter(0), "", 1, 1, 9, 9);
  435. loadCoverageMapping(/*EmitFilenames=*/false);
  436. std::vector<std::string> Names;
  437. for (const auto &Func : LoadedCoverage->getCoveredFunctions())
  438. Names.push_back(Func.Name);
  439. ASSERT_EQ(1U, Names.size());
  440. ASSERT_EQ("func", Names[0]);
  441. }
  442. TEST_P(CoverageMappingTest, dont_detect_false_instantiations) {
  443. InstrProfRecord Record1("foo", 0x1234, {10});
  444. InstrProfRecord Record2("bar", 0x2345, {20});
  445. NoError(ProfileWriter.addRecord(std::move(Record1)));
  446. NoError(ProfileWriter.addRecord(std::move(Record2)));
  447. startFunction("foo", 0x1234);
  448. addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
  449. addExpansionCMR("main", "expanded", 4, 1, 4, 5);
  450. startFunction("bar", 0x2345);
  451. addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
  452. addExpansionCMR("main", "expanded", 9, 1, 9, 5);
  453. loadCoverageMapping();
  454. std::vector<const FunctionRecord *> Instantiations =
  455. LoadedCoverage->getInstantiations("expanded");
  456. ASSERT_TRUE(Instantiations.empty());
  457. }
  458. TEST_P(CoverageMappingTest, load_coverage_for_expanded_file) {
  459. InstrProfRecord Record("func", 0x1234, {10});
  460. NoError(ProfileWriter.addRecord(std::move(Record)));
  461. startFunction("func", 0x1234);
  462. addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
  463. addExpansionCMR("main", "expanded", 4, 1, 4, 5);
  464. loadCoverageMapping();
  465. CoverageData Data = LoadedCoverage->getCoverageForFile("expanded");
  466. std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
  467. ASSERT_EQ(2U, Segments.size());
  468. EXPECT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
  469. EXPECT_EQ(CoverageSegment(1, 10, false), Segments[1]);
  470. }
  471. TEST_P(CoverageMappingTest, skip_duplicate_function_record) {
  472. InstrProfRecord Record("func", 0x1234, {1});
  473. NoError(ProfileWriter.addRecord(std::move(Record)));
  474. startFunction("func", 0x1234);
  475. addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
  476. startFunction("func", 0x1234);
  477. addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
  478. loadCoverageMapping();
  479. auto Funcs = LoadedCoverage->getCoveredFunctions();
  480. unsigned NumFuncs = std::distance(Funcs.begin(), Funcs.end());
  481. ASSERT_EQ(1U, NumFuncs);
  482. }
  483. // FIXME: Use ::testing::Combine() when llvm updates its copy of googletest.
  484. INSTANTIATE_TEST_CASE_P(ParameterizedCovMapTest, CoverageMappingTest,
  485. ::testing::Values(std::pair<bool, bool>({false, false}),
  486. std::pair<bool, bool>({false, true}),
  487. std::pair<bool, bool>({true, false}),
  488. std::pair<bool, bool>({true, true})));
  489. } // end anonymous namespace