10cca70a6SJustin Bogner //===- unittest/ProfileData/CoverageMappingTest.cpp -------------------------=//
20cca70a6SJustin Bogner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60cca70a6SJustin Bogner //
70cca70a6SJustin Bogner //===----------------------------------------------------------------------===//
80cca70a6SJustin Bogner 
9dc707122SEaswaran Raman #include "llvm/ProfileData/Coverage/CoverageMapping.h"
10dc707122SEaswaran Raman #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
11dc707122SEaswaran Raman #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
121d29c080SJustin Bogner #include "llvm/ProfileData/InstrProfReader.h"
131d29c080SJustin Bogner #include "llvm/ProfileData/InstrProfWriter.h"
140cca70a6SJustin Bogner #include "llvm/Support/raw_ostream.h"
1594b98b2cSDavid Blaikie #include "llvm/Testing/Support/Error.h"
1694b98b2cSDavid Blaikie #include "llvm/Testing/Support/SupportHelpers.h"
170cca70a6SJustin Bogner #include "gtest/gtest.h"
180cca70a6SJustin Bogner 
19b550cb17SMehdi Amini #include <ostream>
20743574b8SVedant Kumar #include <utility>
211f92ce67SJustin Bogner 
220cca70a6SJustin Bogner using namespace llvm;
230cca70a6SJustin Bogner using namespace coverage;
240cca70a6SJustin Bogner 
2594b98b2cSDavid Blaikie LLVM_NODISCARD static ::testing::AssertionResult
ErrorEquals(coveragemap_error Expected,Error E)2694b98b2cSDavid Blaikie ErrorEquals(coveragemap_error Expected, Error E) {
27b1d331a3SVedant Kumar   coveragemap_error Found;
28b1d331a3SVedant Kumar   std::string FoundMsg;
29b1d331a3SVedant Kumar   handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
30b1d331a3SVedant Kumar     Found = CME.get();
31b1d331a3SVedant Kumar     FoundMsg = CME.message();
32b1d331a3SVedant Kumar   });
33b1d331a3SVedant Kumar   if (Expected == Found)
34b1d331a3SVedant Kumar     return ::testing::AssertionSuccess();
35b1d331a3SVedant Kumar   return ::testing::AssertionFailure() << "error: " << FoundMsg << "\n";
36b1d331a3SVedant Kumar }
37b1d331a3SVedant Kumar 
380cca70a6SJustin Bogner namespace llvm {
390cca70a6SJustin Bogner namespace coverage {
PrintTo(const Counter & C,::std::ostream * os)400cca70a6SJustin Bogner void PrintTo(const Counter &C, ::std::ostream *os) {
410cca70a6SJustin Bogner   if (C.isZero())
420cca70a6SJustin Bogner     *os << "Zero";
430cca70a6SJustin Bogner   else if (C.isExpression())
440cca70a6SJustin Bogner     *os << "Expression " << C.getExpressionID();
450cca70a6SJustin Bogner   else
460cca70a6SJustin Bogner     *os << "Counter " << C.getCounterID();
470cca70a6SJustin Bogner }
481d29c080SJustin Bogner 
PrintTo(const CoverageSegment & S,::std::ostream * os)491d29c080SJustin Bogner void PrintTo(const CoverageSegment &S, ::std::ostream *os) {
501d29c080SJustin Bogner   *os << "CoverageSegment(" << S.Line << ", " << S.Col << ", ";
511d29c080SJustin Bogner   if (S.HasCount)
521d29c080SJustin Bogner     *os << S.Count << ", ";
531d29c080SJustin Bogner   *os << (S.IsRegionEntry ? "true" : "false") << ")";
541d29c080SJustin Bogner }
550cca70a6SJustin Bogner }
560cca70a6SJustin Bogner }
570cca70a6SJustin Bogner 
580cca70a6SJustin Bogner namespace {
590cca70a6SJustin Bogner 
60df5a8310SIgor Kudrin struct OutputFunctionCoverageData {
611d29c080SJustin Bogner   StringRef Name;
621d29c080SJustin Bogner   uint64_t Hash;
631d29c080SJustin Bogner   std::vector<StringRef> Filenames;
64df5a8310SIgor Kudrin   std::vector<CounterMappingRegion> Regions;
65e4274cfeSPirama Arumuga Nainar   std::vector<CounterExpression> Expressions;
661d29c080SJustin Bogner 
OutputFunctionCoverageData__anonb0afedee0211::OutputFunctionCoverageData67b13ed136SVedant Kumar   OutputFunctionCoverageData() : Hash(0) {}
68b13ed136SVedant Kumar 
OutputFunctionCoverageData__anonb0afedee0211::OutputFunctionCoverageData69b13ed136SVedant Kumar   OutputFunctionCoverageData(OutputFunctionCoverageData &&OFCD)
70b13ed136SVedant Kumar       : Name(OFCD.Name), Hash(OFCD.Hash), Filenames(std::move(OFCD.Filenames)),
71b13ed136SVedant Kumar         Regions(std::move(OFCD.Regions)) {}
72b13ed136SVedant Kumar 
73b13ed136SVedant Kumar   OutputFunctionCoverageData(const OutputFunctionCoverageData &) = delete;
74b13ed136SVedant Kumar   OutputFunctionCoverageData &
75b13ed136SVedant Kumar   operator=(const OutputFunctionCoverageData &) = delete;
76b13ed136SVedant Kumar   OutputFunctionCoverageData &operator=(OutputFunctionCoverageData &&) = delete;
77b13ed136SVedant Kumar 
fillCoverageMappingRecord__anonb0afedee0211::OutputFunctionCoverageData78df5a8310SIgor Kudrin   void fillCoverageMappingRecord(CoverageMappingRecord &Record) const {
791d29c080SJustin Bogner     Record.FunctionName = Name;
801d29c080SJustin Bogner     Record.FunctionHash = Hash;
811d29c080SJustin Bogner     Record.Filenames = Filenames;
82e4274cfeSPirama Arumuga Nainar     Record.Expressions = Expressions;
831d29c080SJustin Bogner     Record.MappingRegions = Regions;
84df5a8310SIgor Kudrin   }
85df5a8310SIgor Kudrin };
86df5a8310SIgor Kudrin 
87df5a8310SIgor Kudrin struct CoverageMappingReaderMock : CoverageMappingReader {
88df5a8310SIgor Kudrin   ArrayRef<OutputFunctionCoverageData> Functions;
89df5a8310SIgor Kudrin 
CoverageMappingReaderMock__anonb0afedee0211::CoverageMappingReaderMock90df5a8310SIgor Kudrin   CoverageMappingReaderMock(ArrayRef<OutputFunctionCoverageData> Functions)
91df5a8310SIgor Kudrin       : Functions(Functions) {}
92df5a8310SIgor Kudrin 
readNextRecord__anonb0afedee0211::CoverageMappingReaderMock939152fd17SVedant Kumar   Error readNextRecord(CoverageMappingRecord &Record) override {
94df5a8310SIgor Kudrin     if (Functions.empty())
959152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::eof);
96df5a8310SIgor Kudrin 
97df5a8310SIgor Kudrin     Functions.front().fillCoverageMappingRecord(Record);
98df5a8310SIgor Kudrin     Functions = Functions.slice(1);
99df5a8310SIgor Kudrin 
1009152fd17SVedant Kumar     return Error::success();
1011d29c080SJustin Bogner   }
1021d29c080SJustin Bogner };
1031d29c080SJustin Bogner 
104df5a8310SIgor Kudrin struct InputFunctionCoverageData {
105df5a8310SIgor Kudrin   // Maps the global file index from CoverageMappingTest.Files
106df5a8310SIgor Kudrin   // to the index of that file within this function. We can't just use
107df5a8310SIgor Kudrin   // global file indexes here because local indexes have to be dense.
108df5a8310SIgor Kudrin   // This map is used during serialization to create the virtual file mapping
109df5a8310SIgor Kudrin   // (from local fileId to global Index) in the head of the per-function
110df5a8310SIgor Kudrin   // coverage mapping data.
111df5a8310SIgor Kudrin   SmallDenseMap<unsigned, unsigned> ReverseVirtualFileMapping;
112df5a8310SIgor Kudrin   std::string Name;
113df5a8310SIgor Kudrin   uint64_t Hash;
114df5a8310SIgor Kudrin   std::vector<CounterMappingRegion> Regions;
115e4274cfeSPirama Arumuga Nainar   std::vector<CounterExpression> Expressions;
116df5a8310SIgor Kudrin 
InputFunctionCoverageData__anonb0afedee0211::InputFunctionCoverageData117df5a8310SIgor Kudrin   InputFunctionCoverageData(std::string Name, uint64_t Hash)
118df5a8310SIgor Kudrin       : Name(std::move(Name)), Hash(Hash) {}
1191edd169eSVedant Kumar 
InputFunctionCoverageData__anonb0afedee0211::InputFunctionCoverageData1201edd169eSVedant Kumar   InputFunctionCoverageData(InputFunctionCoverageData &&IFCD)
1211edd169eSVedant Kumar       : ReverseVirtualFileMapping(std::move(IFCD.ReverseVirtualFileMapping)),
1221edd169eSVedant Kumar         Name(std::move(IFCD.Name)), Hash(IFCD.Hash),
1231edd169eSVedant Kumar         Regions(std::move(IFCD.Regions)) {}
1241edd169eSVedant Kumar 
1251edd169eSVedant Kumar   InputFunctionCoverageData(const InputFunctionCoverageData &) = delete;
1261edd169eSVedant Kumar   InputFunctionCoverageData &
1271edd169eSVedant Kumar   operator=(const InputFunctionCoverageData &) = delete;
1281edd169eSVedant Kumar   InputFunctionCoverageData &operator=(InputFunctionCoverageData &&) = delete;
129df5a8310SIgor Kudrin };
130df5a8310SIgor Kudrin 
1319c88fb4eSBenjamin Kramer struct CoverageMappingTest : ::testing::TestWithParam<std::tuple<bool, bool>> {
132743574b8SVedant Kumar   bool UseMultipleReaders;
1339f61520dSJustin Bogner   StringMap<unsigned> Files;
1345fbd1a33SPetr Hosek   std::vector<std::string> Filenames;
135df5a8310SIgor Kudrin   std::vector<InputFunctionCoverageData> InputFunctions;
136df5a8310SIgor Kudrin   std::vector<OutputFunctionCoverageData> OutputFunctions;
1379f61520dSJustin Bogner 
1381d29c080SJustin Bogner   InstrProfWriter ProfileWriter;
1391d29c080SJustin Bogner   std::unique_ptr<IndexedInstrProfReader> ProfileReader;
1401d29c080SJustin Bogner 
1411d29c080SJustin Bogner   std::unique_ptr<CoverageMapping> LoadedCoverage;
1421d29c080SJustin Bogner 
SetUp__anonb0afedee0211::CoverageMappingTest1439f61520dSJustin Bogner   void SetUp() override {
1449c88fb4eSBenjamin Kramer     ProfileWriter.setOutputSparse(std::get<0>(GetParam()));
1459c88fb4eSBenjamin Kramer     UseMultipleReaders = std::get<1>(GetParam());
1469f61520dSJustin Bogner   }
1479f61520dSJustin Bogner 
getGlobalFileIndex__anonb0afedee0211::CoverageMappingTest148df5a8310SIgor Kudrin   unsigned getGlobalFileIndex(StringRef Name) {
1499f61520dSJustin Bogner     auto R = Files.find(Name);
150ae7528a3SPetr Hosek     if (R != Files.end())
1519f61520dSJustin Bogner       return R->second;
1525fbd1a33SPetr Hosek     unsigned Index = Files.size() + 1;
153eab3d367SBenjamin Kramer     Files.try_emplace(Name, Index);
154e4034e36SIgor Kudrin     return Index;
1559f61520dSJustin Bogner   }
1569f61520dSJustin Bogner 
157df5a8310SIgor Kudrin   // Return the file index of file 'Name' for the current function.
158dae11f7aSSimon Pilgrim   // Add the file into the global map if necessary.
159df5a8310SIgor Kudrin   // See also InputFunctionCoverageData::ReverseVirtualFileMapping
160df5a8310SIgor Kudrin   // for additional comments.
getFileIndexForFunction__anonb0afedee0211::CoverageMappingTest161df5a8310SIgor Kudrin   unsigned getFileIndexForFunction(StringRef Name) {
162df5a8310SIgor Kudrin     unsigned GlobalIndex = getGlobalFileIndex(Name);
163df5a8310SIgor Kudrin     auto &CurrentFunctionFileMapping =
164df5a8310SIgor Kudrin         InputFunctions.back().ReverseVirtualFileMapping;
165df5a8310SIgor Kudrin     auto R = CurrentFunctionFileMapping.find(GlobalIndex);
166ae7528a3SPetr Hosek     if (R != CurrentFunctionFileMapping.end())
167df5a8310SIgor Kudrin       return R->second;
168df5a8310SIgor Kudrin     unsigned IndexInFunction = CurrentFunctionFileMapping.size();
169df5a8310SIgor Kudrin     CurrentFunctionFileMapping.insert(
170df5a8310SIgor Kudrin         std::make_pair(GlobalIndex, IndexInFunction));
171df5a8310SIgor Kudrin     return IndexInFunction;
172df5a8310SIgor Kudrin   }
173df5a8310SIgor Kudrin 
startFunction__anonb0afedee0211::CoverageMappingTest174df5a8310SIgor Kudrin   void startFunction(StringRef FuncName, uint64_t Hash) {
175df5a8310SIgor Kudrin     InputFunctions.emplace_back(FuncName.str(), Hash);
176df5a8310SIgor Kudrin   }
177df5a8310SIgor Kudrin 
addCMR__anonb0afedee0211::CoverageMappingTest1789f61520dSJustin Bogner   void addCMR(Counter C, StringRef File, unsigned LS, unsigned CS, unsigned LE,
17979a1b5eeSVedant Kumar               unsigned CE, bool Skipped = false) {
18079a1b5eeSVedant Kumar     auto &Regions = InputFunctions.back().Regions;
18179a1b5eeSVedant Kumar     unsigned FileID = getFileIndexForFunction(File);
18279a1b5eeSVedant Kumar     Regions.push_back(
18379a1b5eeSVedant Kumar         Skipped ? CounterMappingRegion::makeSkipped(FileID, LS, CS, LE, CE)
18479a1b5eeSVedant Kumar                 : CounterMappingRegion::makeRegion(C, FileID, LS, CS, LE, CE));
1859f61520dSJustin Bogner   }
1869f61520dSJustin Bogner 
addExpansionCMR__anonb0afedee0211::CoverageMappingTest1879f61520dSJustin Bogner   void addExpansionCMR(StringRef File, StringRef ExpandedFile, unsigned LS,
1889f61520dSJustin Bogner                        unsigned CS, unsigned LE, unsigned CE) {
189df5a8310SIgor Kudrin     InputFunctions.back().Regions.push_back(CounterMappingRegion::makeExpansion(
190df5a8310SIgor Kudrin         getFileIndexForFunction(File), getFileIndexForFunction(ExpandedFile),
191df5a8310SIgor Kudrin         LS, CS, LE, CE));
1929f61520dSJustin Bogner   }
1939f61520dSJustin Bogner 
addExpression__anonb0afedee0211::CoverageMappingTest194e4274cfeSPirama Arumuga Nainar   void addExpression(CounterExpression CE) {
195e4274cfeSPirama Arumuga Nainar     InputFunctions.back().Expressions.push_back(CE);
196e4274cfeSPirama Arumuga Nainar   }
197e4274cfeSPirama Arumuga Nainar 
writeCoverageRegions__anonb0afedee0211::CoverageMappingTest198df5a8310SIgor Kudrin   std::string writeCoverageRegions(InputFunctionCoverageData &Data) {
199df5a8310SIgor Kudrin     SmallVector<unsigned, 8> FileIDs(Data.ReverseVirtualFileMapping.size());
200df5a8310SIgor Kudrin     for (const auto &E : Data.ReverseVirtualFileMapping)
201df5a8310SIgor Kudrin       FileIDs[E.second] = E.first;
2020cca70a6SJustin Bogner     std::string Coverage;
2030cca70a6SJustin Bogner     llvm::raw_string_ostream OS(Coverage);
204e4274cfeSPirama Arumuga Nainar     CoverageMappingWriter(FileIDs, Data.Expressions, Data.Regions).write(OS);
2059f61520dSJustin Bogner     return OS.str();
2060cca70a6SJustin Bogner   }
2070cca70a6SJustin Bogner 
readCoverageRegions__anonb0afedee0211::CoverageMappingTest2089a4abcebSVedant Kumar   void readCoverageRegions(const std::string &Coverage,
209df5a8310SIgor Kudrin                            OutputFunctionCoverageData &Data) {
210ff6dc053SJinsong Ji     // We will re-use the StringRef in duplicate tests, clear it to avoid
211ff6dc053SJinsong Ji     // clobber previous ones.
212ff6dc053SJinsong Ji     Filenames.clear();
2135fbd1a33SPetr Hosek     Filenames.resize(Files.size() + 1);
2149f61520dSJustin Bogner     for (const auto &E : Files)
2155fbd1a33SPetr Hosek       Filenames[E.getValue()] = E.getKey().str();
2165fbd1a33SPetr Hosek     ArrayRef<std::string> FilenameRefs = llvm::makeArrayRef(Filenames);
2175fbd1a33SPetr Hosek     RawCoverageMappingReader Reader(Coverage, FilenameRefs, Data.Filenames,
218e4274cfeSPirama Arumuga Nainar                                     Data.Expressions, Data.Regions);
21994b98b2cSDavid Blaikie     EXPECT_THAT_ERROR(Reader.read(), Succeeded());
2200cca70a6SJustin Bogner   }
2211d29c080SJustin Bogner 
writeAndReadCoverageRegions__anonb0afedee0211::CoverageMappingTest222df5a8310SIgor Kudrin   void writeAndReadCoverageRegions(bool EmitFilenames = true) {
223df5a8310SIgor Kudrin     OutputFunctions.resize(InputFunctions.size());
224df5a8310SIgor Kudrin     for (unsigned I = 0; I < InputFunctions.size(); ++I) {
225df5a8310SIgor Kudrin       std::string Regions = writeCoverageRegions(InputFunctions[I]);
226df5a8310SIgor Kudrin       readCoverageRegions(Regions, OutputFunctions[I]);
227df5a8310SIgor Kudrin       OutputFunctions[I].Name = InputFunctions[I].Name;
228df5a8310SIgor Kudrin       OutputFunctions[I].Hash = InputFunctions[I].Hash;
229df5a8310SIgor Kudrin       if (!EmitFilenames)
230df5a8310SIgor Kudrin         OutputFunctions[I].Filenames.clear();
231df5a8310SIgor Kudrin     }
232df5a8310SIgor Kudrin   }
233df5a8310SIgor Kudrin 
readProfCounts__anonb0afedee0211::CoverageMappingTest2341d29c080SJustin Bogner   void readProfCounts() {
2351d29c080SJustin Bogner     auto Profile = ProfileWriter.writeBuffer();
2361d29c080SJustin Bogner     auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile));
23794b98b2cSDavid Blaikie     EXPECT_THAT_ERROR(ReaderOrErr.takeError(), Succeeded());
2381d29c080SJustin Bogner     ProfileReader = std::move(ReaderOrErr.get());
2391d29c080SJustin Bogner   }
2401d29c080SJustin Bogner 
readOutputFunctions__anonb0afedee0211::CoverageMappingTest241743574b8SVedant Kumar   Expected<std::unique_ptr<CoverageMapping>> readOutputFunctions() {
242743574b8SVedant Kumar     std::vector<std::unique_ptr<CoverageMappingReader>> CoverageReaders;
243cc34e619SVedant Kumar     if (UseMultipleReaders) {
244743574b8SVedant Kumar       for (const auto &OF : OutputFunctions) {
245743574b8SVedant Kumar         ArrayRef<OutputFunctionCoverageData> Funcs(OF);
246cc34e619SVedant Kumar         CoverageReaders.push_back(
2470eaee545SJonas Devlieghere             std::make_unique<CoverageMappingReaderMock>(Funcs));
248cc34e619SVedant Kumar       }
249cc34e619SVedant Kumar     } else {
2503fde2d36SVedant Kumar       ArrayRef<OutputFunctionCoverageData> Funcs(OutputFunctions);
251cc34e619SVedant Kumar       CoverageReaders.push_back(
2520eaee545SJonas Devlieghere           std::make_unique<CoverageMappingReaderMock>(Funcs));
253743574b8SVedant Kumar     }
254743574b8SVedant Kumar     return CoverageMapping::load(CoverageReaders, *ProfileReader);
255743574b8SVedant Kumar   }
256743574b8SVedant Kumar 
loadCoverageMapping__anonb0afedee0211::CoverageMappingTest257b1d331a3SVedant Kumar   Error loadCoverageMapping(bool EmitFilenames = true) {
258df5a8310SIgor Kudrin     readProfCounts();
259df5a8310SIgor Kudrin     writeAndReadCoverageRegions(EmitFilenames);
260743574b8SVedant Kumar     auto CoverageOrErr = readOutputFunctions();
261b1d331a3SVedant Kumar     if (!CoverageOrErr)
262b1d331a3SVedant Kumar       return CoverageOrErr.takeError();
2631d29c080SJustin Bogner     LoadedCoverage = std::move(CoverageOrErr.get());
264b1d331a3SVedant Kumar     return Error::success();
2651d29c080SJustin Bogner   }
2660cca70a6SJustin Bogner };
2670cca70a6SJustin Bogner 
TEST_P(CoverageMappingTest,basic_write_read)2688750e94cSVedant Kumar TEST_P(CoverageMappingTest, basic_write_read) {
269df5a8310SIgor Kudrin   startFunction("func", 0x1234);
2709f61520dSJustin Bogner   addCMR(Counter::getCounter(0), "foo", 1, 1, 1, 1);
2719f61520dSJustin Bogner   addCMR(Counter::getCounter(1), "foo", 2, 1, 2, 2);
2729f61520dSJustin Bogner   addCMR(Counter::getZero(),     "foo", 3, 1, 3, 4);
2739f61520dSJustin Bogner   addCMR(Counter::getCounter(2), "foo", 4, 1, 4, 8);
2749f61520dSJustin Bogner   addCMR(Counter::getCounter(3), "bar", 1, 2, 3, 4);
2759f61520dSJustin Bogner 
276df5a8310SIgor Kudrin   writeAndReadCoverageRegions();
277df5a8310SIgor Kudrin   ASSERT_EQ(1u, InputFunctions.size());
278df5a8310SIgor Kudrin   ASSERT_EQ(1u, OutputFunctions.size());
279df5a8310SIgor Kudrin   InputFunctionCoverageData &Input = InputFunctions.back();
280df5a8310SIgor Kudrin   OutputFunctionCoverageData &Output = OutputFunctions.back();
281df5a8310SIgor Kudrin 
282df5a8310SIgor Kudrin   size_t N = makeArrayRef(Input.Regions).size();
283df5a8310SIgor Kudrin   ASSERT_EQ(N, Output.Regions.size());
2840cca70a6SJustin Bogner   for (size_t I = 0; I < N; ++I) {
285df5a8310SIgor Kudrin     ASSERT_EQ(Input.Regions[I].Count, Output.Regions[I].Count);
286df5a8310SIgor Kudrin     ASSERT_EQ(Input.Regions[I].FileID, Output.Regions[I].FileID);
287df5a8310SIgor Kudrin     ASSERT_EQ(Input.Regions[I].startLoc(), Output.Regions[I].startLoc());
288df5a8310SIgor Kudrin     ASSERT_EQ(Input.Regions[I].endLoc(), Output.Regions[I].endLoc());
289df5a8310SIgor Kudrin     ASSERT_EQ(Input.Regions[I].Kind, Output.Regions[I].Kind);
2900cca70a6SJustin Bogner   }
2910cca70a6SJustin Bogner }
2920cca70a6SJustin Bogner 
TEST_P(CoverageMappingTest,correct_deserialize_for_more_than_two_files)2938750e94cSVedant Kumar TEST_P(CoverageMappingTest, correct_deserialize_for_more_than_two_files) {
294e4034e36SIgor Kudrin   const char *FileNames[] = {"bar", "baz", "foo"};
295f15014ffSBenjamin Kramer   static const unsigned N = array_lengthof(FileNames);
296e4034e36SIgor Kudrin 
297df5a8310SIgor Kudrin   startFunction("func", 0x1234);
298e4034e36SIgor Kudrin   for (unsigned I = 0; I < N; ++I)
299e4034e36SIgor Kudrin     // Use LineStart to hold the index of the file name
300e4034e36SIgor Kudrin     // in order to preserve that information during possible sorting of CMRs.
301e4034e36SIgor Kudrin     addCMR(Counter::getCounter(0), FileNames[I], I, 1, I, 1);
302e4034e36SIgor Kudrin 
303df5a8310SIgor Kudrin   writeAndReadCoverageRegions();
304df5a8310SIgor Kudrin   ASSERT_EQ(1u, OutputFunctions.size());
305df5a8310SIgor Kudrin   OutputFunctionCoverageData &Output = OutputFunctions.back();
306e4034e36SIgor Kudrin 
307df5a8310SIgor Kudrin   ASSERT_EQ(N, Output.Regions.size());
308df5a8310SIgor Kudrin   ASSERT_EQ(N, Output.Filenames.size());
309e4034e36SIgor Kudrin 
310e4034e36SIgor Kudrin   for (unsigned I = 0; I < N; ++I) {
311df5a8310SIgor Kudrin     ASSERT_GT(N, Output.Regions[I].FileID);
312df5a8310SIgor Kudrin     ASSERT_GT(N, Output.Regions[I].LineStart);
313df5a8310SIgor Kudrin     EXPECT_EQ(FileNames[Output.Regions[I].LineStart],
314df5a8310SIgor Kudrin               Output.Filenames[Output.Regions[I].FileID]);
315e4034e36SIgor Kudrin   }
316e4034e36SIgor Kudrin }
317e4034e36SIgor Kudrin 
__anonb0afedee0302(Error E) 31898cce003SDavid Blaikie static const auto Err = [](Error E) { FAIL(); };
31998cce003SDavid Blaikie 
TEST_P(CoverageMappingTest,load_coverage_for_more_than_two_files)3208750e94cSVedant Kumar TEST_P(CoverageMappingTest, load_coverage_for_more_than_two_files) {
32198cce003SDavid Blaikie   ProfileWriter.addRecord({"func", 0x1234, {0}}, Err);
322e4034e36SIgor Kudrin 
323e4034e36SIgor Kudrin   const char *FileNames[] = {"bar", "baz", "foo"};
324f15014ffSBenjamin Kramer   static const unsigned N = array_lengthof(FileNames);
325e4034e36SIgor Kudrin 
326df5a8310SIgor Kudrin   startFunction("func", 0x1234);
327e4034e36SIgor Kudrin   for (unsigned I = 0; I < N; ++I)
328e4034e36SIgor Kudrin     // Use LineStart to hold the index of the file name
329e4034e36SIgor Kudrin     // in order to preserve that information during possible sorting of CMRs.
330e4034e36SIgor Kudrin     addCMR(Counter::getCounter(0), FileNames[I], I, 1, I, 1);
331e4034e36SIgor Kudrin 
33294b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
333e4034e36SIgor Kudrin 
334e4034e36SIgor Kudrin   for (unsigned I = 0; I < N; ++I) {
335e4034e36SIgor Kudrin     CoverageData Data = LoadedCoverage->getCoverageForFile(FileNames[I]);
336e4034e36SIgor Kudrin     ASSERT_TRUE(!Data.empty());
337e4034e36SIgor Kudrin     EXPECT_EQ(I, Data.begin()->Line);
338e4034e36SIgor Kudrin   }
339e4034e36SIgor Kudrin }
340e4034e36SIgor Kudrin 
TEST_P(CoverageMappingTest,load_coverage_with_bogus_function_name)341b1d331a3SVedant Kumar TEST_P(CoverageMappingTest, load_coverage_with_bogus_function_name) {
34298cce003SDavid Blaikie   ProfileWriter.addRecord({"", 0x1234, {10}}, Err);
343b1d331a3SVedant Kumar   startFunction("", 0x1234);
344b1d331a3SVedant Kumar   addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5);
34594b98b2cSDavid Blaikie   EXPECT_TRUE(ErrorEquals(coveragemap_error::malformed, loadCoverageMapping()));
346b1d331a3SVedant Kumar }
347b1d331a3SVedant Kumar 
TEST_P(CoverageMappingTest,load_coverage_for_several_functions)3488750e94cSVedant Kumar TEST_P(CoverageMappingTest, load_coverage_for_several_functions) {
34998cce003SDavid Blaikie   ProfileWriter.addRecord({"func1", 0x1234, {10}}, Err);
35098cce003SDavid Blaikie   ProfileWriter.addRecord({"func2", 0x2345, {20}}, Err);
351df5a8310SIgor Kudrin 
352df5a8310SIgor Kudrin   startFunction("func1", 0x1234);
353df5a8310SIgor Kudrin   addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5);
354df5a8310SIgor Kudrin 
355df5a8310SIgor Kudrin   startFunction("func2", 0x2345);
356df5a8310SIgor Kudrin   addCMR(Counter::getCounter(0), "bar", 2, 2, 6, 6);
357df5a8310SIgor Kudrin 
35894b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
359df5a8310SIgor Kudrin 
360df5a8310SIgor Kudrin   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
361b3f72ea7SSimon Pilgrim   EXPECT_EQ(2, std::distance(FunctionRecords.begin(), FunctionRecords.end()));
362df5a8310SIgor Kudrin   for (const auto &FunctionRecord : FunctionRecords) {
363df5a8310SIgor Kudrin     CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
364df5a8310SIgor Kudrin     std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
365df5a8310SIgor Kudrin     ASSERT_EQ(2U, Segments.size());
366df5a8310SIgor Kudrin     if (FunctionRecord.Name == "func1") {
367df5a8310SIgor Kudrin       EXPECT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
368df5a8310SIgor Kudrin       EXPECT_EQ(CoverageSegment(5, 5, false), Segments[1]);
369df5a8310SIgor Kudrin     } else {
370df5a8310SIgor Kudrin       ASSERT_EQ("func2", FunctionRecord.Name);
371df5a8310SIgor Kudrin       EXPECT_EQ(CoverageSegment(2, 2, 20, true), Segments[0]);
372df5a8310SIgor Kudrin       EXPECT_EQ(CoverageSegment(6, 6, false), Segments[1]);
373df5a8310SIgor Kudrin     }
374df5a8310SIgor Kudrin   }
375df5a8310SIgor Kudrin }
376df5a8310SIgor Kudrin 
TEST_P(CoverageMappingTest,create_combined_regions)37779a1b5eeSVedant Kumar TEST_P(CoverageMappingTest, create_combined_regions) {
37879a1b5eeSVedant Kumar   ProfileWriter.addRecord({"func1", 0x1234, {1, 2, 3}}, Err);
37979a1b5eeSVedant Kumar   startFunction("func1", 0x1234);
38079a1b5eeSVedant Kumar 
38179a1b5eeSVedant Kumar   // Given regions which start at the same location, emit a segment for the
38279a1b5eeSVedant Kumar   // last region.
38379a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 2, 2);
38479a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 1, 1, 2, 2);
38579a1b5eeSVedant Kumar   addCMR(Counter::getCounter(2), "file1", 1, 1, 2, 2);
38679a1b5eeSVedant Kumar 
38779a1b5eeSVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
38879a1b5eeSVedant Kumar   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
38979a1b5eeSVedant Kumar   const auto &FunctionRecord = *FunctionRecords.begin();
39079a1b5eeSVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
39179a1b5eeSVedant Kumar   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
39279a1b5eeSVedant Kumar 
39379a1b5eeSVedant Kumar   ASSERT_EQ(2U, Segments.size());
39479a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 1, 6, true), Segments[0]);
39579a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(2, 2, false), Segments[1]);
39679a1b5eeSVedant Kumar }
39779a1b5eeSVedant Kumar 
TEST_P(CoverageMappingTest,skipped_segments_have_no_count)39879a1b5eeSVedant Kumar TEST_P(CoverageMappingTest, skipped_segments_have_no_count) {
39979a1b5eeSVedant Kumar   ProfileWriter.addRecord({"func1", 0x1234, {1}}, Err);
40079a1b5eeSVedant Kumar   startFunction("func1", 0x1234);
40179a1b5eeSVedant Kumar 
40279a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 5, 5);
40379a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 5, 1, 5, 5, /*Skipped=*/true);
40479a1b5eeSVedant Kumar 
40579a1b5eeSVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
40679a1b5eeSVedant Kumar   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
40779a1b5eeSVedant Kumar   const auto &FunctionRecord = *FunctionRecords.begin();
40879a1b5eeSVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
40979a1b5eeSVedant Kumar   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
41079a1b5eeSVedant Kumar 
41179a1b5eeSVedant Kumar   ASSERT_EQ(3U, Segments.size());
41279a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]);
41379a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(5, 1, true), Segments[1]);
41479a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(5, 5, false), Segments[2]);
41579a1b5eeSVedant Kumar }
41679a1b5eeSVedant Kumar 
TEST_P(CoverageMappingTest,multiple_regions_end_after_parent_ends)41779a1b5eeSVedant Kumar TEST_P(CoverageMappingTest, multiple_regions_end_after_parent_ends) {
41879a1b5eeSVedant Kumar   ProfileWriter.addRecord({"func1", 0x1234, {1, 0}}, Err);
41979a1b5eeSVedant Kumar   startFunction("func1", 0x1234);
42079a1b5eeSVedant Kumar 
42179a1b5eeSVedant Kumar   // 1| F{ a{
42279a1b5eeSVedant Kumar   // 2|
42379a1b5eeSVedant Kumar   // 3|    a} b{ c{
42479a1b5eeSVedant Kumar   // 4|
42579a1b5eeSVedant Kumar   // 5|    b}
42679a1b5eeSVedant Kumar   // 6|
42779a1b5eeSVedant Kumar   // 7| c} d{   e{
42879a1b5eeSVedant Kumar   // 8|
42979a1b5eeSVedant Kumar   // 9| d}      e} F}
43079a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); // < F
43179a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 3, 5); // < a
43279a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 3, 5, 5, 4); // < b
43379a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 3, 5, 7, 3); // < c
43479a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 7, 3, 9, 2); // < d
43579a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 7, 7, 9, 7); // < e
43679a1b5eeSVedant Kumar 
43779a1b5eeSVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
43879a1b5eeSVedant Kumar   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
43979a1b5eeSVedant Kumar   const auto &FunctionRecord = *FunctionRecords.begin();
44079a1b5eeSVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
44179a1b5eeSVedant Kumar   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
44279a1b5eeSVedant Kumar 
44379a1b5eeSVedant Kumar   // Old output (not sorted or unique):
44479a1b5eeSVedant Kumar   //   Segment at 1:1 with count 1
44579a1b5eeSVedant Kumar   //   Segment at 1:1 with count 1
44679a1b5eeSVedant Kumar   //   Segment at 3:5 with count 1
44779a1b5eeSVedant Kumar   //   Segment at 3:5 with count 0
44879a1b5eeSVedant Kumar   //   Segment at 3:5 with count 1
44979a1b5eeSVedant Kumar   //   Segment at 5:4 with count 0
45079a1b5eeSVedant Kumar   //   Segment at 7:3 with count 1
45179a1b5eeSVedant Kumar   //   Segment at 7:3 with count 0
45279a1b5eeSVedant Kumar   //   Segment at 7:7 with count 0
45379a1b5eeSVedant Kumar   //   Segment at 9:7 with count 0
45479a1b5eeSVedant Kumar   //   Segment at 9:2 with count 1
45579a1b5eeSVedant Kumar   //   Top level segment at 9:9
45679a1b5eeSVedant Kumar 
45779a1b5eeSVedant Kumar   // New output (sorted and unique):
45879a1b5eeSVedant Kumar   //   Segment at 1:1 (count = 1), RegionEntry
45979a1b5eeSVedant Kumar   //   Segment at 3:5 (count = 1), RegionEntry
46079a1b5eeSVedant Kumar   //   Segment at 5:4 (count = 0)
46179a1b5eeSVedant Kumar   //   Segment at 7:3 (count = 0), RegionEntry
46279a1b5eeSVedant Kumar   //   Segment at 7:7 (count = 0), RegionEntry
46379a1b5eeSVedant Kumar   //   Segment at 9:2 (count = 0)
46479a1b5eeSVedant Kumar   //   Segment at 9:7 (count = 1)
46579a1b5eeSVedant Kumar   //   Segment at 9:9 (count = 0), Skipped
46679a1b5eeSVedant Kumar 
46779a1b5eeSVedant Kumar   ASSERT_EQ(8U, Segments.size());
46879a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]);
46979a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(3, 5, 1, true), Segments[1]);
47079a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(5, 4, 0, false), Segments[2]);
47179a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(7, 3, 0, true), Segments[3]);
47279a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(7, 7, 0, true), Segments[4]);
47379a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(9, 2, 0, false), Segments[5]);
47479a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(9, 7, 1, false), Segments[6]);
47579a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(9, 9, false), Segments[7]);
47679a1b5eeSVedant Kumar }
47779a1b5eeSVedant Kumar 
TEST_P(CoverageMappingTest,multiple_completed_segments_at_same_loc)47880fbb855SVedant Kumar TEST_P(CoverageMappingTest, multiple_completed_segments_at_same_loc) {
47980fbb855SVedant Kumar   ProfileWriter.addRecord({"func1", 0x1234, {0, 1, 2}}, Err);
48080fbb855SVedant Kumar   startFunction("func1", 0x1234);
48180fbb855SVedant Kumar 
482337b0db1SVedant Kumar   // PR35495
48380fbb855SVedant Kumar   addCMR(Counter::getCounter(1), "file1", 2, 1, 18, 2);
484337b0db1SVedant Kumar   addCMR(Counter::getCounter(0), "file1", 8, 10, 14, 6);
48580fbb855SVedant Kumar   addCMR(Counter::getCounter(0), "file1", 8, 12, 14, 6);
48680fbb855SVedant Kumar   addCMR(Counter::getCounter(1), "file1", 9, 1, 14, 6);
48780fbb855SVedant Kumar   addCMR(Counter::getCounter(2), "file1", 11, 13, 11, 14);
48880fbb855SVedant Kumar 
48980fbb855SVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
49080fbb855SVedant Kumar   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
49180fbb855SVedant Kumar   const auto &FunctionRecord = *FunctionRecords.begin();
49280fbb855SVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
49380fbb855SVedant Kumar   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
49480fbb855SVedant Kumar 
495337b0db1SVedant Kumar   ASSERT_EQ(7U, Segments.size());
49680fbb855SVedant Kumar   EXPECT_EQ(CoverageSegment(2, 1, 1, true), Segments[0]);
497337b0db1SVedant Kumar   EXPECT_EQ(CoverageSegment(8, 10, 0, true), Segments[1]);
498337b0db1SVedant Kumar   EXPECT_EQ(CoverageSegment(8, 12, 0, true), Segments[2]);
499337b0db1SVedant Kumar   EXPECT_EQ(CoverageSegment(9, 1, 1, true), Segments[3]);
500337b0db1SVedant Kumar   EXPECT_EQ(CoverageSegment(11, 13, 2, true), Segments[4]);
50180fbb855SVedant Kumar   // Use count=1 (from 9:1 -> 14:6), not count=0 (from 8:12 -> 14:6).
502337b0db1SVedant Kumar   EXPECT_EQ(CoverageSegment(11, 14, 1, false), Segments[5]);
503337b0db1SVedant Kumar   EXPECT_EQ(CoverageSegment(18, 2, false), Segments[6]);
50480fbb855SVedant Kumar }
50580fbb855SVedant Kumar 
TEST_P(CoverageMappingTest,dont_emit_redundant_segments)50679a1b5eeSVedant Kumar TEST_P(CoverageMappingTest, dont_emit_redundant_segments) {
50779a1b5eeSVedant Kumar   ProfileWriter.addRecord({"func1", 0x1234, {1, 1}}, Err);
50879a1b5eeSVedant Kumar   startFunction("func1", 0x1234);
50979a1b5eeSVedant Kumar 
51079a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 4, 4);
51179a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 2, 2, 5, 5);
51279a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 3, 3, 6, 6);
51379a1b5eeSVedant Kumar 
51479a1b5eeSVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
51579a1b5eeSVedant Kumar   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
51679a1b5eeSVedant Kumar   const auto &FunctionRecord = *FunctionRecords.begin();
51779a1b5eeSVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
51879a1b5eeSVedant Kumar   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
51979a1b5eeSVedant Kumar 
52079a1b5eeSVedant Kumar   ASSERT_EQ(5U, Segments.size());
52179a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]);
52279a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(2, 2, 1, true), Segments[1]);
52379a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(3, 3, 1, true), Segments[2]);
52479a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(4, 4, 1, false), Segments[3]);
52579a1b5eeSVedant Kumar   // A closing segment starting at 5:5 would be redundant: it would have the
52679a1b5eeSVedant Kumar   // same count as the segment starting at 4:4, and has all the same metadata.
52779a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(6, 6, false), Segments[4]);
52879a1b5eeSVedant Kumar }
52979a1b5eeSVedant Kumar 
TEST_P(CoverageMappingTest,dont_emit_closing_segment_at_new_region_start)53079a1b5eeSVedant Kumar TEST_P(CoverageMappingTest, dont_emit_closing_segment_at_new_region_start) {
53179a1b5eeSVedant Kumar   ProfileWriter.addRecord({"func1", 0x1234, {1}}, Err);
53279a1b5eeSVedant Kumar   startFunction("func1", 0x1234);
53379a1b5eeSVedant Kumar 
53479a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 6, 5);
53579a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 2, 2, 6, 5);
53679a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 3, 3, 6, 5);
53779a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 6, 5, 7, 7);
53879a1b5eeSVedant Kumar 
53979a1b5eeSVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
54079a1b5eeSVedant Kumar   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
54179a1b5eeSVedant Kumar   const auto &FunctionRecord = *FunctionRecords.begin();
54279a1b5eeSVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
54379a1b5eeSVedant Kumar   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
54479a1b5eeSVedant Kumar 
54579a1b5eeSVedant Kumar   ASSERT_EQ(5U, Segments.size());
54679a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]);
54779a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(2, 2, 1, true), Segments[1]);
54879a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(3, 3, 1, true), Segments[2]);
54979a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(6, 5, 1, true), Segments[3]);
55079a1b5eeSVedant Kumar   // The old segment builder would get this wrong by emitting multiple segments
55179a1b5eeSVedant Kumar   // which start at 6:5 (a few of which were skipped segments). We should just
55279a1b5eeSVedant Kumar   // get a segment for the region entry.
55379a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(7, 7, false), Segments[4]);
55479a1b5eeSVedant Kumar }
55579a1b5eeSVedant Kumar 
TEST_P(CoverageMappingTest,handle_consecutive_regions_with_zero_length)55679a1b5eeSVedant Kumar TEST_P(CoverageMappingTest, handle_consecutive_regions_with_zero_length) {
55779a1b5eeSVedant Kumar   ProfileWriter.addRecord({"func1", 0x1234, {1, 2}}, Err);
55879a1b5eeSVedant Kumar   startFunction("func1", 0x1234);
55979a1b5eeSVedant Kumar 
56079a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 1, 1);
56179a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 1, 1, 1, 1);
56279a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 1, 1);
56379a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 1, 1, 1, 1);
56479a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 1, 1);
56579a1b5eeSVedant Kumar 
56679a1b5eeSVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
56779a1b5eeSVedant Kumar   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
56879a1b5eeSVedant Kumar   const auto &FunctionRecord = *FunctionRecords.begin();
56979a1b5eeSVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
57079a1b5eeSVedant Kumar   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
57179a1b5eeSVedant Kumar 
57279a1b5eeSVedant Kumar   ASSERT_EQ(1U, Segments.size());
57379a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 1, true), Segments[0]);
57479a1b5eeSVedant Kumar   // We need to get a skipped segment starting at 1:1. In this case there is
57579a1b5eeSVedant Kumar   // also a region entry at 1:1.
57679a1b5eeSVedant Kumar }
57779a1b5eeSVedant Kumar 
TEST_P(CoverageMappingTest,handle_sandwiched_zero_length_region)57879a1b5eeSVedant Kumar TEST_P(CoverageMappingTest, handle_sandwiched_zero_length_region) {
57979a1b5eeSVedant Kumar   ProfileWriter.addRecord({"func1", 0x1234, {2, 1}}, Err);
58079a1b5eeSVedant Kumar   startFunction("func1", 0x1234);
58179a1b5eeSVedant Kumar 
58279a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 5, 4, 4);
58379a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 1, 9, 1, 50);
58479a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 2, 7, 2, 34);
58579a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 3, 5, 3, 21);
58679a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 3, 21, 3, 21);
58779a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 4, 12, 4, 17);
58879a1b5eeSVedant Kumar 
58979a1b5eeSVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
59079a1b5eeSVedant Kumar   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
59179a1b5eeSVedant Kumar   const auto &FunctionRecord = *FunctionRecords.begin();
59279a1b5eeSVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
59379a1b5eeSVedant Kumar   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
59479a1b5eeSVedant Kumar 
59579a1b5eeSVedant Kumar   ASSERT_EQ(10U, Segments.size());
59679a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 5, 2, true), Segments[0]);
59779a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 9, 1, true), Segments[1]);
59879a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 50, 2, false), Segments[2]);
59979a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(2, 7, 1, true), Segments[3]);
60079a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(2, 34, 2, false), Segments[4]);
60179a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(3, 5, 1, true), Segments[5]);
60279a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(3, 21, 2, true), Segments[6]);
60379a1b5eeSVedant Kumar   // Handle the zero-length region by creating a segment with its predecessor's
60479a1b5eeSVedant Kumar   // count (i.e the count from 1:5 -> 4:4).
60579a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(4, 4, false), Segments[7]);
60679a1b5eeSVedant Kumar   // The area between 4:4 and 4:12 is skipped.
60779a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(4, 12, 1, true), Segments[8]);
60879a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(4, 17, false), Segments[9]);
60979a1b5eeSVedant Kumar }
61079a1b5eeSVedant Kumar 
TEST_P(CoverageMappingTest,handle_last_completed_region)61179a1b5eeSVedant Kumar TEST_P(CoverageMappingTest, handle_last_completed_region) {
61279a1b5eeSVedant Kumar   ProfileWriter.addRecord({"func1", 0x1234, {1, 2, 3, 4}}, Err);
61379a1b5eeSVedant Kumar   startFunction("func1", 0x1234);
61479a1b5eeSVedant Kumar 
61579a1b5eeSVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 8, 8);
61679a1b5eeSVedant Kumar   addCMR(Counter::getCounter(1), "file1", 2, 2, 5, 5);
61779a1b5eeSVedant Kumar   addCMR(Counter::getCounter(2), "file1", 3, 3, 4, 4);
61879a1b5eeSVedant Kumar   addCMR(Counter::getCounter(3), "file1", 6, 6, 7, 7);
61979a1b5eeSVedant Kumar 
62079a1b5eeSVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
62179a1b5eeSVedant Kumar   const auto FunctionRecords = LoadedCoverage->getCoveredFunctions();
62279a1b5eeSVedant Kumar   const auto &FunctionRecord = *FunctionRecords.begin();
62379a1b5eeSVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFunction(FunctionRecord);
62479a1b5eeSVedant Kumar   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
62579a1b5eeSVedant Kumar 
62679a1b5eeSVedant Kumar   ASSERT_EQ(8U, Segments.size());
62779a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(1, 1, 1, true), Segments[0]);
62879a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(2, 2, 2, true), Segments[1]);
62979a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(3, 3, 3, true), Segments[2]);
63079a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(4, 4, 2, false), Segments[3]);
63179a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(5, 5, 1, false), Segments[4]);
63279a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(6, 6, 4, true), Segments[5]);
63379a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(7, 7, 1, false), Segments[6]);
63479a1b5eeSVedant Kumar   EXPECT_EQ(CoverageSegment(8, 8, false), Segments[7]);
63579a1b5eeSVedant Kumar }
63679a1b5eeSVedant Kumar 
TEST_P(CoverageMappingTest,expansion_gets_first_counter)6378750e94cSVedant Kumar TEST_P(CoverageMappingTest, expansion_gets_first_counter) {
638df5a8310SIgor Kudrin   startFunction("func", 0x1234);
6399f61520dSJustin Bogner   addCMR(Counter::getCounter(1), "foo", 10, 1, 10, 2);
6409f61520dSJustin Bogner   // This starts earlier in "foo", so the expansion should get its counter.
6419f61520dSJustin Bogner   addCMR(Counter::getCounter(2), "foo", 1, 1, 20, 1);
6429f61520dSJustin Bogner   addExpansionCMR("bar", "foo", 3, 3, 3, 3);
6430cca70a6SJustin Bogner 
644df5a8310SIgor Kudrin   writeAndReadCoverageRegions();
645df5a8310SIgor Kudrin   ASSERT_EQ(1u, OutputFunctions.size());
646df5a8310SIgor Kudrin   OutputFunctionCoverageData &Output = OutputFunctions.back();
647df5a8310SIgor Kudrin 
648df5a8310SIgor Kudrin   ASSERT_EQ(CounterMappingRegion::ExpansionRegion, Output.Regions[2].Kind);
649df5a8310SIgor Kudrin   ASSERT_EQ(Counter::getCounter(2), Output.Regions[2].Count);
650df5a8310SIgor Kudrin   ASSERT_EQ(3U, Output.Regions[2].LineStart);
6510cca70a6SJustin Bogner }
6520cca70a6SJustin Bogner 
TEST_P(CoverageMappingTest,basic_coverage_iteration)6538750e94cSVedant Kumar TEST_P(CoverageMappingTest, basic_coverage_iteration) {
65498cce003SDavid Blaikie   ProfileWriter.addRecord({"func", 0x1234, {30, 20, 10, 0}}, Err);
6551d29c080SJustin Bogner 
656df5a8310SIgor Kudrin   startFunction("func", 0x1234);
6571d29c080SJustin Bogner   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
6581d29c080SJustin Bogner   addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7);
6591d29c080SJustin Bogner   addCMR(Counter::getCounter(2), "file1", 5, 8, 9, 1);
6601d29c080SJustin Bogner   addCMR(Counter::getCounter(3), "file1", 10, 10, 11, 11);
66194b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
6621d29c080SJustin Bogner 
6631d29c080SJustin Bogner   CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
6641d29c080SJustin Bogner   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
6651d29c080SJustin Bogner   ASSERT_EQ(7U, Segments.size());
6661d29c080SJustin Bogner   ASSERT_EQ(CoverageSegment(1, 1, 20, true),  Segments[0]);
6671d29c080SJustin Bogner   ASSERT_EQ(CoverageSegment(4, 7, 30, false), Segments[1]);
6681d29c080SJustin Bogner   ASSERT_EQ(CoverageSegment(5, 8, 10, true),  Segments[2]);
6691d29c080SJustin Bogner   ASSERT_EQ(CoverageSegment(9, 1, 30, false), Segments[3]);
6701d29c080SJustin Bogner   ASSERT_EQ(CoverageSegment(9, 9, false),     Segments[4]);
6711d29c080SJustin Bogner   ASSERT_EQ(CoverageSegment(10, 10, 0, true), Segments[5]);
6721d29c080SJustin Bogner   ASSERT_EQ(CoverageSegment(11, 11, false),   Segments[6]);
6731d29c080SJustin Bogner }
6740cca70a6SJustin Bogner 
TEST_P(CoverageMappingTest,test_line_coverage_iterator)675821160d5SVedant Kumar TEST_P(CoverageMappingTest, test_line_coverage_iterator) {
676821160d5SVedant Kumar   ProfileWriter.addRecord({"func", 0x1234, {30, 20, 10, 0}}, Err);
677821160d5SVedant Kumar 
678821160d5SVedant Kumar   startFunction("func", 0x1234);
679821160d5SVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
680821160d5SVedant Kumar   addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7);
681821160d5SVedant Kumar   addCMR(Counter::getCounter(2), "file1", 5, 8, 9, 1);
682821160d5SVedant Kumar   addCMR(Counter::getCounter(3), "file1", 10, 10, 11, 11);
683821160d5SVedant Kumar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
684821160d5SVedant Kumar 
685821160d5SVedant Kumar   CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
686821160d5SVedant Kumar 
687f5f153ddSVedant Kumar   unsigned Line = 0;
6888d5c3ae3SZequan Wu   unsigned LineCounts[] = {20, 20, 20, 20, 30, 10, 10, 10, 10, 0, 0};
689821160d5SVedant Kumar   for (const auto &LCS : getLineCoverageStats(Data)) {
690f5f153ddSVedant Kumar     ASSERT_EQ(Line + 1, LCS.getLine());
69143247f05SVedant Kumar     errs() << "Line: " << Line + 1 << ", count = " << LCS.getExecutionCount() << "\n";
692f5f153ddSVedant Kumar     ASSERT_EQ(LineCounts[Line], LCS.getExecutionCount());
693f5f153ddSVedant Kumar     ++Line;
694821160d5SVedant Kumar   }
695f5f153ddSVedant Kumar   ASSERT_EQ(11U, Line);
69677898a4cSDuncan P. N. Exon Smith 
69777898a4cSDuncan P. N. Exon Smith   // Check that operator->() works / compiles.
69877898a4cSDuncan P. N. Exon Smith   ASSERT_EQ(1U, LineCoverageIterator(Data)->getLine());
699821160d5SVedant Kumar }
700821160d5SVedant Kumar 
TEST_P(CoverageMappingTest,uncovered_function)7018750e94cSVedant Kumar TEST_P(CoverageMappingTest, uncovered_function) {
702df5a8310SIgor Kudrin   startFunction("func", 0x1234);
703428c605dSJustin Bogner   addCMR(Counter::getZero(), "file1", 1, 2, 3, 4);
70494b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
705428c605dSJustin Bogner 
706428c605dSJustin Bogner   CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
707428c605dSJustin Bogner   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
708428c605dSJustin Bogner   ASSERT_EQ(2U, Segments.size());
709428c605dSJustin Bogner   ASSERT_EQ(CoverageSegment(1, 2, 0, true), Segments[0]);
710428c605dSJustin Bogner   ASSERT_EQ(CoverageSegment(3, 4, false),   Segments[1]);
711428c605dSJustin Bogner }
712428c605dSJustin Bogner 
TEST_P(CoverageMappingTest,uncovered_function_with_mapping)7138750e94cSVedant Kumar TEST_P(CoverageMappingTest, uncovered_function_with_mapping) {
714df5a8310SIgor Kudrin   startFunction("func", 0x1234);
71582a64517SJustin Bogner   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
71682a64517SJustin Bogner   addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7);
71794b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
71882a64517SJustin Bogner 
71982a64517SJustin Bogner   CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
72082a64517SJustin Bogner   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
72182a64517SJustin Bogner   ASSERT_EQ(3U, Segments.size());
72282a64517SJustin Bogner   ASSERT_EQ(CoverageSegment(1, 1, 0, true),  Segments[0]);
72382a64517SJustin Bogner   ASSERT_EQ(CoverageSegment(4, 7, 0, false), Segments[1]);
72482a64517SJustin Bogner   ASSERT_EQ(CoverageSegment(9, 9, false),    Segments[2]);
72582a64517SJustin Bogner }
72682a64517SJustin Bogner 
TEST_P(CoverageMappingTest,combine_regions)7278750e94cSVedant Kumar TEST_P(CoverageMappingTest, combine_regions) {
72898cce003SDavid Blaikie   ProfileWriter.addRecord({"func", 0x1234, {10, 20, 30}}, Err);
72911ae7789SJustin Bogner 
730df5a8310SIgor Kudrin   startFunction("func", 0x1234);
73111ae7789SJustin Bogner   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
73211ae7789SJustin Bogner   addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4);
73311ae7789SJustin Bogner   addCMR(Counter::getCounter(2), "file1", 3, 3, 4, 4);
73494b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
73511ae7789SJustin Bogner 
73611ae7789SJustin Bogner   CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
73711ae7789SJustin Bogner   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
73811ae7789SJustin Bogner   ASSERT_EQ(4U, Segments.size());
73911ae7789SJustin Bogner   ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
74011ae7789SJustin Bogner   ASSERT_EQ(CoverageSegment(3, 3, 50, true), Segments[1]);
74111ae7789SJustin Bogner   ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]);
74211ae7789SJustin Bogner   ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]);
74311ae7789SJustin Bogner }
74411ae7789SJustin Bogner 
TEST_P(CoverageMappingTest,restore_combined_counter_after_nested_region)7458750e94cSVedant Kumar TEST_P(CoverageMappingTest, restore_combined_counter_after_nested_region) {
74698cce003SDavid Blaikie   ProfileWriter.addRecord({"func", 0x1234, {10, 20, 40}}, Err);
747ed99a96fSIgor Kudrin 
748ed99a96fSIgor Kudrin   startFunction("func", 0x1234);
749ed99a96fSIgor Kudrin   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
750ed99a96fSIgor Kudrin   addCMR(Counter::getCounter(1), "file1", 1, 1, 9, 9);
751ed99a96fSIgor Kudrin   addCMR(Counter::getCounter(2), "file1", 3, 3, 5, 5);
75294b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
753ed99a96fSIgor Kudrin 
754ed99a96fSIgor Kudrin   CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
755ed99a96fSIgor Kudrin   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
756ed99a96fSIgor Kudrin   ASSERT_EQ(4U, Segments.size());
757ed99a96fSIgor Kudrin   EXPECT_EQ(CoverageSegment(1, 1, 30, true), Segments[0]);
758ed99a96fSIgor Kudrin   EXPECT_EQ(CoverageSegment(3, 3, 40, true), Segments[1]);
759ed99a96fSIgor Kudrin   EXPECT_EQ(CoverageSegment(5, 5, 30, false), Segments[2]);
760ed99a96fSIgor Kudrin   EXPECT_EQ(CoverageSegment(9, 9, false), Segments[3]);
761ed99a96fSIgor Kudrin }
762ed99a96fSIgor Kudrin 
76327d8dd39SIgor Kudrin // If CodeRegions and ExpansionRegions cover the same area,
76427d8dd39SIgor Kudrin // only counts of CodeRegions should be used.
TEST_P(CoverageMappingTest,dont_combine_expansions)7658750e94cSVedant Kumar TEST_P(CoverageMappingTest, dont_combine_expansions) {
76698cce003SDavid Blaikie   ProfileWriter.addRecord({"func", 0x1234, {10, 20}}, Err);
76798cce003SDavid Blaikie   ProfileWriter.addRecord({"func", 0x1234, {0, 0}}, Err);
76811ae7789SJustin Bogner 
769df5a8310SIgor Kudrin   startFunction("func", 0x1234);
77011ae7789SJustin Bogner   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
77111ae7789SJustin Bogner   addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4);
77211ae7789SJustin Bogner   addCMR(Counter::getCounter(1), "include1", 6, 6, 7, 7);
77311ae7789SJustin Bogner   addExpansionCMR("file1", "include1", 3, 3, 4, 4);
77494b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
77511ae7789SJustin Bogner 
77611ae7789SJustin Bogner   CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
77711ae7789SJustin Bogner   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
77811ae7789SJustin Bogner   ASSERT_EQ(4U, Segments.size());
77911ae7789SJustin Bogner   ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
78011ae7789SJustin Bogner   ASSERT_EQ(CoverageSegment(3, 3, 20, true), Segments[1]);
78111ae7789SJustin Bogner   ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]);
78211ae7789SJustin Bogner   ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]);
78311ae7789SJustin Bogner }
78411ae7789SJustin Bogner 
78527d8dd39SIgor Kudrin // If an area is covered only by ExpansionRegions, they should be combinated.
TEST_P(CoverageMappingTest,combine_expansions)7868750e94cSVedant Kumar TEST_P(CoverageMappingTest, combine_expansions) {
78798cce003SDavid Blaikie   ProfileWriter.addRecord({"func", 0x1234, {2, 3, 7}}, Err);
78827d8dd39SIgor Kudrin 
78927d8dd39SIgor Kudrin   startFunction("func", 0x1234);
79027d8dd39SIgor Kudrin   addCMR(Counter::getCounter(1), "include1", 1, 1, 1, 10);
79127d8dd39SIgor Kudrin   addCMR(Counter::getCounter(2), "include2", 1, 1, 1, 10);
79227d8dd39SIgor Kudrin   addCMR(Counter::getCounter(0), "file", 1, 1, 5, 5);
79327d8dd39SIgor Kudrin   addExpansionCMR("file", "include1", 3, 1, 3, 5);
79427d8dd39SIgor Kudrin   addExpansionCMR("file", "include2", 3, 1, 3, 5);
79527d8dd39SIgor Kudrin 
79694b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
79727d8dd39SIgor Kudrin 
79827d8dd39SIgor Kudrin   CoverageData Data = LoadedCoverage->getCoverageForFile("file");
79927d8dd39SIgor Kudrin   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
80027d8dd39SIgor Kudrin   ASSERT_EQ(4U, Segments.size());
80127d8dd39SIgor Kudrin   EXPECT_EQ(CoverageSegment(1, 1, 2, true), Segments[0]);
80227d8dd39SIgor Kudrin   EXPECT_EQ(CoverageSegment(3, 1, 10, true), Segments[1]);
80327d8dd39SIgor Kudrin   EXPECT_EQ(CoverageSegment(3, 5, 2, false), Segments[2]);
80427d8dd39SIgor Kudrin   EXPECT_EQ(CoverageSegment(5, 5, false), Segments[3]);
80527d8dd39SIgor Kudrin }
80627d8dd39SIgor Kudrin 
807e4274cfeSPirama Arumuga Nainar // Test that counters not associated with any code regions are allowed.
TEST_P(CoverageMappingTest,non_code_region_counters)808e4274cfeSPirama Arumuga Nainar TEST_P(CoverageMappingTest, non_code_region_counters) {
809e4274cfeSPirama Arumuga Nainar   // No records in profdata
810e4274cfeSPirama Arumuga Nainar 
811e4274cfeSPirama Arumuga Nainar   startFunction("func", 0x1234);
812e4274cfeSPirama Arumuga Nainar   addCMR(Counter::getCounter(0), "file", 1, 1, 5, 5);
813e4274cfeSPirama Arumuga Nainar   addCMR(Counter::getExpression(0), "file", 6, 1, 6, 5);
814e4274cfeSPirama Arumuga Nainar   addExpression(CounterExpression(
815e4274cfeSPirama Arumuga Nainar       CounterExpression::Add, Counter::getCounter(1), Counter::getCounter(2)));
816e4274cfeSPirama Arumuga Nainar 
817e4274cfeSPirama Arumuga Nainar   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
818e4274cfeSPirama Arumuga Nainar 
819e4274cfeSPirama Arumuga Nainar   std::vector<std::string> Names;
820e4274cfeSPirama Arumuga Nainar   for (const auto &Func : LoadedCoverage->getCoveredFunctions()) {
821e4274cfeSPirama Arumuga Nainar     Names.push_back(Func.Name);
822e4274cfeSPirama Arumuga Nainar     ASSERT_EQ(2U, Func.CountedRegions.size());
823e4274cfeSPirama Arumuga Nainar   }
824e4274cfeSPirama Arumuga Nainar   ASSERT_EQ(1U, Names.size());
825e4274cfeSPirama Arumuga Nainar }
826e4274cfeSPirama Arumuga Nainar 
TEST_P(CoverageMappingTest,strip_filename_prefix)8278750e94cSVedant Kumar TEST_P(CoverageMappingTest, strip_filename_prefix) {
82898cce003SDavid Blaikie   ProfileWriter.addRecord({"file1:func", 0x1234, {0}}, Err);
8290b4c484fSJustin Bogner 
830df5a8310SIgor Kudrin   startFunction("file1:func", 0x1234);
8310b4c484fSJustin Bogner   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
83294b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
8330b4c484fSJustin Bogner 
8340b4c484fSJustin Bogner   std::vector<std::string> Names;
8350b4c484fSJustin Bogner   for (const auto &Func : LoadedCoverage->getCoveredFunctions())
8360b4c484fSJustin Bogner     Names.push_back(Func.Name);
8370b4c484fSJustin Bogner   ASSERT_EQ(1U, Names.size());
8380b4c484fSJustin Bogner   ASSERT_EQ("func", Names[0]);
8390b4c484fSJustin Bogner }
8400b4c484fSJustin Bogner 
TEST_P(CoverageMappingTest,strip_unknown_filename_prefix)8418750e94cSVedant Kumar TEST_P(CoverageMappingTest, strip_unknown_filename_prefix) {
84298cce003SDavid Blaikie   ProfileWriter.addRecord({"<unknown>:func", 0x1234, {0}}, Err);
843141ed944SVedant Kumar 
844df5a8310SIgor Kudrin   startFunction("<unknown>:func", 0x1234);
845141ed944SVedant Kumar   addCMR(Counter::getCounter(0), "", 1, 1, 9, 9);
84694b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(/*EmitFilenames=*/false), Succeeded());
847141ed944SVedant Kumar 
848141ed944SVedant Kumar   std::vector<std::string> Names;
849141ed944SVedant Kumar   for (const auto &Func : LoadedCoverage->getCoveredFunctions())
850141ed944SVedant Kumar     Names.push_back(Func.Name);
851141ed944SVedant Kumar   ASSERT_EQ(1U, Names.size());
852141ed944SVedant Kumar   ASSERT_EQ("func", Names[0]);
853141ed944SVedant Kumar }
854141ed944SVedant Kumar 
TEST_P(CoverageMappingTest,dont_detect_false_instantiations)8558750e94cSVedant Kumar TEST_P(CoverageMappingTest, dont_detect_false_instantiations) {
85698cce003SDavid Blaikie   ProfileWriter.addRecord({"foo", 0x1234, {10}}, Err);
85798cce003SDavid Blaikie   ProfileWriter.addRecord({"bar", 0x2345, {20}}, Err);
8581c14dc4cSIgor Kudrin 
8591c14dc4cSIgor Kudrin   startFunction("foo", 0x1234);
8601c14dc4cSIgor Kudrin   addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
8611c14dc4cSIgor Kudrin   addExpansionCMR("main", "expanded", 4, 1, 4, 5);
8621c14dc4cSIgor Kudrin 
8631c14dc4cSIgor Kudrin   startFunction("bar", 0x2345);
8641c14dc4cSIgor Kudrin   addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
8651c14dc4cSIgor Kudrin   addExpansionCMR("main", "expanded", 9, 1, 9, 5);
8661c14dc4cSIgor Kudrin 
86794b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
8681c14dc4cSIgor Kudrin 
869dde19c5aSVedant Kumar   std::vector<InstantiationGroup> InstantiationGroups =
870dde19c5aSVedant Kumar       LoadedCoverage->getInstantiationGroups("expanded");
871a0749f9bSPaul Robinson   ASSERT_TRUE(InstantiationGroups.empty());
8721c14dc4cSIgor Kudrin }
8731c14dc4cSIgor Kudrin 
TEST_P(CoverageMappingTest,load_coverage_for_expanded_file)8748750e94cSVedant Kumar TEST_P(CoverageMappingTest, load_coverage_for_expanded_file) {
87598cce003SDavid Blaikie   ProfileWriter.addRecord({"func", 0x1234, {10}}, Err);
8761c14dc4cSIgor Kudrin 
8771c14dc4cSIgor Kudrin   startFunction("func", 0x1234);
8781c14dc4cSIgor Kudrin   addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
8791c14dc4cSIgor Kudrin   addExpansionCMR("main", "expanded", 4, 1, 4, 5);
8801c14dc4cSIgor Kudrin 
88194b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
8821c14dc4cSIgor Kudrin 
8831c14dc4cSIgor Kudrin   CoverageData Data = LoadedCoverage->getCoverageForFile("expanded");
8841c14dc4cSIgor Kudrin   std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
8851c14dc4cSIgor Kudrin   ASSERT_EQ(2U, Segments.size());
8861c14dc4cSIgor Kudrin   EXPECT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
8871c14dc4cSIgor Kudrin   EXPECT_EQ(CoverageSegment(1, 10, false), Segments[1]);
8881c14dc4cSIgor Kudrin }
8891c14dc4cSIgor Kudrin 
TEST_P(CoverageMappingTest,skip_duplicate_function_record)890743574b8SVedant Kumar TEST_P(CoverageMappingTest, skip_duplicate_function_record) {
89198cce003SDavid Blaikie   ProfileWriter.addRecord({"func", 0x1234, {1}}, Err);
892743574b8SVedant Kumar 
8930c5b6020SMax Moroz   // This record should be loaded.
894743574b8SVedant Kumar   startFunction("func", 0x1234);
895743574b8SVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
896743574b8SVedant Kumar 
8970c5b6020SMax Moroz   // This record should be loaded.
898743574b8SVedant Kumar   startFunction("func", 0x1234);
899743574b8SVedant Kumar   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
9000c5b6020SMax Moroz   addCMR(Counter::getCounter(0), "file2", 1, 1, 9, 9);
9010c5b6020SMax Moroz 
9020c5b6020SMax Moroz   // This record should be skipped.
9030c5b6020SMax Moroz   startFunction("func", 0x1234);
9040c5b6020SMax Moroz   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
9050c5b6020SMax Moroz 
9060c5b6020SMax Moroz   // This record should be loaded.
9070c5b6020SMax Moroz   startFunction("func", 0x1234);
9080c5b6020SMax Moroz   addCMR(Counter::getCounter(0), "file2", 1, 1, 9, 9);
9090c5b6020SMax Moroz   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
9100c5b6020SMax Moroz 
9110c5b6020SMax Moroz   // This record should be skipped.
9120c5b6020SMax Moroz   startFunction("func", 0x1234);
9130c5b6020SMax Moroz   addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
9140c5b6020SMax Moroz   addCMR(Counter::getCounter(0), "file2", 1, 1, 9, 9);
915743574b8SVedant Kumar 
91694b98b2cSDavid Blaikie   EXPECT_THAT_ERROR(loadCoverageMapping(), Succeeded());
917743574b8SVedant Kumar 
918743574b8SVedant Kumar   auto Funcs = LoadedCoverage->getCoveredFunctions();
919743574b8SVedant Kumar   unsigned NumFuncs = std::distance(Funcs.begin(), Funcs.end());
9200c5b6020SMax Moroz   ASSERT_EQ(3U, NumFuncs);
921743574b8SVedant Kumar }
922743574b8SVedant Kumar 
9239c88fb4eSBenjamin Kramer INSTANTIATE_TEST_SUITE_P(ParameterizedCovMapTest, CoverageMappingTest,
9249c88fb4eSBenjamin Kramer                          ::testing::Combine(::testing::Bool(),
9259c88fb4eSBenjamin Kramer                                             ::testing::Bool()));
92600dab228SVedant Kumar 
TEST(CoverageMappingTest,filename_roundtrip)927dd1ea9deSVedant Kumar TEST(CoverageMappingTest, filename_roundtrip) {
9288280ece0SPetr Hosek   std::vector<std::string> Paths({"dir", "a", "b", "c", "d", "e"});
929dd1ea9deSVedant Kumar 
930dd1ea9deSVedant Kumar   for (bool Compress : {false, true}) {
931dd1ea9deSVedant Kumar     std::string EncodedFilenames;
932dd1ea9deSVedant Kumar     {
933dd1ea9deSVedant Kumar       raw_string_ostream OS(EncodedFilenames);
934dd1ea9deSVedant Kumar       CoverageFilenamesSectionWriter Writer(Paths);
935dd1ea9deSVedant Kumar       Writer.write(OS, Compress);
936dd1ea9deSVedant Kumar     }
937dd1ea9deSVedant Kumar 
9385fbd1a33SPetr Hosek     std::vector<std::string> ReadFilenames;
939dd1ea9deSVedant Kumar     RawCoverageFilenamesReader Reader(EncodedFilenames, ReadFilenames);
9405fbd1a33SPetr Hosek     EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded());
941dd1ea9deSVedant Kumar 
942dd1ea9deSVedant Kumar     ASSERT_EQ(ReadFilenames.size(), Paths.size());
9438280ece0SPetr Hosek     for (unsigned I = 1; I < Paths.size(); ++I) {
9448280ece0SPetr Hosek       SmallString<256> P(Paths[0]);
9458280ece0SPetr Hosek       llvm::sys::path::append(P, Paths[I]);
946*0204fd25SPetr Hosek       ASSERT_EQ(ReadFilenames[I], P);
9478280ece0SPetr Hosek     }
9488280ece0SPetr Hosek   }
9498280ece0SPetr Hosek }
9508280ece0SPetr Hosek 
TEST(CoverageMappingTest,filename_compilation_dir)9518280ece0SPetr Hosek TEST(CoverageMappingTest, filename_compilation_dir) {
9528280ece0SPetr Hosek   std::vector<std::string> Paths({"dir", "a", "b", "c", "d", "e"});
9538280ece0SPetr Hosek 
9548280ece0SPetr Hosek   for (bool Compress : {false, true}) {
9558280ece0SPetr Hosek     std::string EncodedFilenames;
9568280ece0SPetr Hosek     {
9578280ece0SPetr Hosek       raw_string_ostream OS(EncodedFilenames);
9588280ece0SPetr Hosek       CoverageFilenamesSectionWriter Writer(Paths);
9598280ece0SPetr Hosek       Writer.write(OS, Compress);
9608280ece0SPetr Hosek     }
9618280ece0SPetr Hosek 
9628280ece0SPetr Hosek     StringRef CompilationDir = "out";
9638280ece0SPetr Hosek     std::vector<std::string> ReadFilenames;
9648280ece0SPetr Hosek     RawCoverageFilenamesReader Reader(EncodedFilenames, ReadFilenames,
9658280ece0SPetr Hosek                                       CompilationDir);
9668280ece0SPetr Hosek     EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded());
9678280ece0SPetr Hosek 
9688280ece0SPetr Hosek     ASSERT_EQ(ReadFilenames.size(), Paths.size());
9698280ece0SPetr Hosek     for (unsigned I = 1; I < Paths.size(); ++I) {
9708280ece0SPetr Hosek       SmallString<256> P(CompilationDir);
9718280ece0SPetr Hosek       llvm::sys::path::append(P, Paths[I]);
972*0204fd25SPetr Hosek       ASSERT_EQ(ReadFilenames[I], P);
9738280ece0SPetr Hosek     }
974dd1ea9deSVedant Kumar   }
975dd1ea9deSVedant Kumar }
976dd1ea9deSVedant Kumar 
9770cca70a6SJustin Bogner } // end anonymous namespace
978