CoverageMappingTest.cpp 22 KB

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