1 //===- unittest/ProfileData/SampleProfTest.cpp -------------------*- C++
2 //-*-===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 
11 #include "llvm/ProfileData/SampleProfReader.h"
12 #include "llvm/ProfileData/SampleProfWriter.h"
13 #include "gtest/gtest.h"
14 
15 #include <cstdarg>
16 
17 using namespace llvm;
18 using namespace sampleprof;
19 
NoError(std::error_code EC)20 static ::testing::AssertionResult NoError(std::error_code EC) {
21   if (!EC)
22     return ::testing::AssertionSuccess();
23   return ::testing::AssertionFailure() << "error " << EC.value() << ": "
24                                        << EC.message();
25 }
26 
27 namespace {
28 
29 struct SampleProfTest : ::testing::Test {
30   std::string Data;
31   std::unique_ptr<raw_ostream> OS;
32   std::unique_ptr<SampleProfileWriter> Writer;
33   std::unique_ptr<SampleProfileReader> Reader;
34 
SampleProfTest__anon04ae7cc10111::SampleProfTest35   SampleProfTest()
36       : Data(), OS(new raw_string_ostream(Data)), Writer(), Reader() {}
37 
createWriter__anon04ae7cc10111::SampleProfTest38   void createWriter(SampleProfileFormat Format) {
39     auto WriterOrErr = SampleProfileWriter::create(OS, Format);
40     ASSERT_TRUE(NoError(WriterOrErr.getError()));
41     Writer = std::move(WriterOrErr.get());
42   }
43 
readProfile__anon04ae7cc10111::SampleProfTest44   void readProfile(std::unique_ptr<MemoryBuffer> &Profile) {
45     auto ReaderOrErr = SampleProfileReader::create(Profile, getGlobalContext());
46     ASSERT_TRUE(NoError(ReaderOrErr.getError()));
47     Reader = std::move(ReaderOrErr.get());
48   }
49 
testRoundTrip__anon04ae7cc10111::SampleProfTest50   void testRoundTrip(SampleProfileFormat Format) {
51     createWriter(Format);
52 
53     StringRef FooName("_Z3fooi");
54     FunctionSamples FooSamples;
55     FooSamples.addTotalSamples(7711);
56     FooSamples.addHeadSamples(610);
57     FooSamples.addBodySamples(1, 0, 610);
58 
59     StringRef BarName("_Z3bari");
60     FunctionSamples BarSamples;
61     BarSamples.addTotalSamples(20301);
62     BarSamples.addHeadSamples(1437);
63     BarSamples.addBodySamples(1, 0, 1437);
64 
65     StringMap<FunctionSamples> Profiles;
66     Profiles[FooName] = std::move(FooSamples);
67     Profiles[BarName] = std::move(BarSamples);
68 
69     std::error_code EC;
70     EC = Writer->write(Profiles);
71     ASSERT_TRUE(NoError(EC));
72 
73     Writer->getOutputStream().flush();
74 
75     auto Profile = MemoryBuffer::getMemBufferCopy(Data);
76     readProfile(Profile);
77 
78     EC = Reader->read();
79     ASSERT_TRUE(NoError(EC));
80 
81     StringMap<FunctionSamples> &ReadProfiles = Reader->getProfiles();
82     ASSERT_EQ(2u, ReadProfiles.size());
83 
84     FunctionSamples &ReadFooSamples = ReadProfiles[FooName];
85     ASSERT_EQ(7711u, ReadFooSamples.getTotalSamples());
86     ASSERT_EQ(610u, ReadFooSamples.getHeadSamples());
87 
88     FunctionSamples &ReadBarSamples = ReadProfiles[BarName];
89     ASSERT_EQ(20301u, ReadBarSamples.getTotalSamples());
90     ASSERT_EQ(1437u, ReadBarSamples.getHeadSamples());
91   }
92 };
93 
TEST_F(SampleProfTest,roundtrip_text_profile)94 TEST_F(SampleProfTest, roundtrip_text_profile) {
95   testRoundTrip(SampleProfileFormat::SPF_Text);
96 }
97 
TEST_F(SampleProfTest,roundtrip_binary_profile)98 TEST_F(SampleProfTest, roundtrip_binary_profile) {
99   testRoundTrip(SampleProfileFormat::SPF_Binary);
100 }
101 
TEST_F(SampleProfTest,sample_overflow_saturation)102 TEST_F(SampleProfTest, sample_overflow_saturation) {
103   const uint64_t Max = std::numeric_limits<uint64_t>::max();
104   sampleprof_error Result;
105 
106   StringRef FooName("_Z3fooi");
107   FunctionSamples FooSamples;
108   Result = FooSamples.addTotalSamples(1);
109   ASSERT_EQ(Result, sampleprof_error::success);
110 
111   Result = FooSamples.addHeadSamples(1);
112   ASSERT_EQ(Result, sampleprof_error::success);
113 
114   Result = FooSamples.addBodySamples(10, 0, 1);
115   ASSERT_EQ(Result, sampleprof_error::success);
116 
117   Result = FooSamples.addTotalSamples(Max);
118   ASSERT_EQ(Result, sampleprof_error::counter_overflow);
119   ASSERT_EQ(FooSamples.getTotalSamples(), Max);
120 
121   Result = FooSamples.addHeadSamples(Max);
122   ASSERT_EQ(Result, sampleprof_error::counter_overflow);
123   ASSERT_EQ(FooSamples.getHeadSamples(), Max);
124 
125   Result = FooSamples.addBodySamples(10, 0, Max);
126   ASSERT_EQ(Result, sampleprof_error::counter_overflow);
127   ErrorOr<uint64_t> BodySamples = FooSamples.findSamplesAt(10, 0);
128   ASSERT_FALSE(BodySamples.getError());
129   ASSERT_EQ(BodySamples.get(), Max);
130 }
131 
132 } // end anonymous namespace
133