1 //===- llvm/unittests/tools/llvm-profdata/OutputSizeLimitTest.cpp ---------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ProfileData/SampleProfReader.h"
10 #include "llvm/ProfileData/SampleProfWriter.h"
11 #include "llvm/Support/FileSystem.h"
12 #include "llvm/Support/VirtualFileSystem.h"
13 #include "llvm/Testing/Support/Error.h"
14 #include "gtest/gtest.h"
17 using llvm::unittest::TempFile
;
19 std::string Input1
= R
"(main:184019:0
26 9: 2064 _Z3bari:1471 _Z3fooi:631
36 const char EmptyProfile
[18] = "\xff\xe5\xd0\xb1\xf4\xc9\x94\xa8\x53\x67";
38 /// sys::fs and SampleProf mix Error and error_code, making an adapter class
39 /// to keep code elegant.
40 template <typename T
> class ExpectedErrorOr
: public Expected
<T
> {
42 ExpectedErrorOr(T
&&Obj
) : Expected
<T
>(Obj
) {}
44 ExpectedErrorOr(std::error_code EC
) : Expected
<T
>(errorCodeToError(EC
)) {}
46 ExpectedErrorOr(Error
&&E
) : Expected
<T
>(std::move(E
)) {}
49 ExpectedErrorOr(ErrorOr
<U
> &&E
)
50 : Expected
<T
>(errorCodeToError(E
.getError())) {}
53 ExpectedErrorOr(Expected
<U
> &&E
) : Expected
<T
>(E
.takeError()) {}
56 #define DEF_VAR_RETURN_IF_ERROR(Var, Value) \
57 auto Var##OrErr = Value; \
60 auto Var = std::move(Var##OrErr.get())
62 #define VAR_RETURN_IF_ERROR(Var, Value) \
66 Var = std::move(Var##OrErr.get())
68 #define RETURN_IF_ERROR(Value) \
72 /// The main testing routine. After rewriting profiles with size limit, check
74 /// 1. The file size of the new profile is within the size limit.
75 /// 2. The new profile is a subset of the old profile, and the content of every
76 /// sample in the new profile is unchanged.
77 /// Note that even though by default samples with fewest total count are dropped
78 /// first, this is not a requirement. Samples can be dropped by any order.
79 static ExpectedErrorOr
<void *> RunTest(StringRef Input
, size_t SizeLimit
,
80 SampleProfileFormat Format
,
81 bool Compress
= false) {
82 // Read Input profile.
83 auto FS
= vfs::getRealFileSystem();
85 auto InputBuffer
= MemoryBuffer::getMemBuffer(Input
);
86 DEF_VAR_RETURN_IF_ERROR(
87 Reader
, SampleProfileReader::create(InputBuffer
, Context
, *FS
));
88 RETURN_IF_ERROR(Reader
->read());
89 SampleProfileMap OldProfiles
= Reader
->getProfiles();
91 // Rewrite it to a temp file with size limit.
92 TempFile
Temp("profile", "afdo", "", true);
95 DEF_VAR_RETURN_IF_ERROR(Writer
,
96 SampleProfileWriter::create(Temp
.path(), Format
));
98 Writer
->setToCompressAllSections();
99 std::error_code EC
= Writer
->writeWithSizeLimit(OldProfiles
, SizeLimit
);
100 // too_large means no sample could be written because SizeLimit is too
101 // small. Otherwise any other error code indicates unexpected failure.
102 if (EC
== sampleprof_error::too_large
)
108 // Read the temp file to get new profiles. Use the default empty profile if
109 // temp file was not written because size limit is too small.
110 SampleProfileMap NewProfiles
;
111 InputBuffer
= MemoryBuffer::getMemBuffer(StringRef(EmptyProfile
, 17));
112 DEF_VAR_RETURN_IF_ERROR(
113 NewReader
, SampleProfileReader::create(InputBuffer
, Context
, *FS
));
115 VAR_RETURN_IF_ERROR(NewReader
, SampleProfileReader::create(
116 Temp
.path().str(), Context
, *FS
));
117 RETURN_IF_ERROR(NewReader
->read());
118 NewProfiles
= NewReader
->getProfiles();
121 // Check temp file is actually within size limit.
123 RETURN_IF_ERROR(sys::fs::file_size(Temp
.path(), FileSize
));
124 EXPECT_LE(FileSize
, SizeLimit
);
126 // For every sample in the new profile, confirm it is in the old profile and
128 for (auto Sample
: NewProfiles
) {
129 auto FindResult
= OldProfiles
.find(Sample
.second
.getContext());
130 EXPECT_NE(FindResult
, OldProfiles
.end());
131 if (FindResult
!= OldProfiles
.end()) {
132 EXPECT_EQ(Sample
.second
.getHeadSamples(),
133 FindResult
->second
.getHeadSamples());
134 EXPECT_EQ(Sample
.second
, FindResult
->second
);
140 TEST(TestOutputSizeLimit
, TestOutputSizeLimitExtBinary
) {
141 for (size_t OutputSizeLimit
: {490, 489, 488, 475, 474, 459, 400})
142 ASSERT_THAT_EXPECTED(
143 RunTest(Input1
, OutputSizeLimit
, llvm::sampleprof::SPF_Ext_Binary
),
147 TEST(TestOutputSizeLimit
, TestOutputSizeLimitBinary
) {
148 for (size_t OutputSizeLimit
: {250, 249, 248, 237, 236, 223, 200})
149 ASSERT_THAT_EXPECTED(
150 RunTest(Input1
, OutputSizeLimit
, llvm::sampleprof::SPF_Binary
),
154 TEST(TestOutputSizeLimit
, TestOutputSizeLimitText
) {
155 for (size_t OutputSizeLimit
:
156 {229, 228, 227, 213, 212, 211, 189, 188, 187, 186, 150})
157 ASSERT_THAT_EXPECTED(
158 RunTest(Input1
, OutputSizeLimit
, llvm::sampleprof::SPF_Text
),
163 TEST(TestOutputSizeLimit
, TestOutputSizeLimitExtBinaryCompressed
) {
164 for (size_t OutputSizeLimit
:
165 {507, 506, 505, 494, 493, 492, 483, 482, 481, 480})
166 ASSERT_THAT_EXPECTED(RunTest(Input1
, OutputSizeLimit
,
167 llvm::sampleprof::SPF_Ext_Binary
, true),