brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · d21c378 Raw
171 lines · cpp
1//===- llvm/unittests/tools/llvm-profdata/OutputSizeLimitTest.cpp ---------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 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"15 16using namespace llvm;17using llvm::unittest::TempFile;18 19std::string Input1 = R"(main:184019:020 4: 53421 4.2: 53422 5: 107523 5.1: 107524 6: 208025 7: 53426 9: 2064 _Z3bari:1471 _Z3fooi:63127 10: inline1:100028  1: 100029 10: inline2:200030  1: 200031_Z3bari:20301:143732 1: 143733_Z3fooi:7711:61034 1: 610)";35 36const char EmptyProfile[18] = "\xff\xe5\xd0\xb1\xf4\xc9\x94\xa8\x53\x67";37 38/// sys::fs and SampleProf mix Error and error_code, making an adapter class39/// to keep code elegant.40template <typename T> class ExpectedErrorOr : public Expected<T> {41public:42  ExpectedErrorOr(T &&Obj) : Expected<T>(Obj) {}43 44  ExpectedErrorOr(std::error_code EC) : Expected<T>(errorCodeToError(EC)) {}45 46  ExpectedErrorOr(Error &&E) : Expected<T>(std::move(E)) {}47 48  template <typename U>49  ExpectedErrorOr(ErrorOr<U> &&E)50      : Expected<T>(errorCodeToError(E.getError())) {}51 52  template <typename U>53  ExpectedErrorOr(Expected<U> &&E) : Expected<T>(E.takeError()) {}54};55 56#define DEF_VAR_RETURN_IF_ERROR(Var, Value)                                    \57  auto Var##OrErr = Value;                                                     \58  if (!Var##OrErr)                                                             \59    return Var##OrErr;                                                         \60  auto Var = std::move(Var##OrErr.get())61 62#define VAR_RETURN_IF_ERROR(Var, Value)                                        \63  Var##OrErr = Value;                                                          \64  if (!Var##OrErr)                                                             \65    return Var##OrErr;                                                         \66  Var = std::move(Var##OrErr.get())67 68#define RETURN_IF_ERROR(Value)                                                 \69  if (auto E = Value)                                                          \70  return std::move(E)71 72/// The main testing routine. After rewriting profiles with size limit, check73/// the following: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 every76/// sample in the new profile is unchanged.77/// Note that even though by default samples with fewest total count are dropped78/// first, this is not a requirement. Samples can be dropped by any order.79static ExpectedErrorOr<void *> RunTest(StringRef Input, size_t SizeLimit,80                                       SampleProfileFormat Format,81                                       bool Compress = false) {82  // Read Input profile.83  auto FS = vfs::getRealFileSystem();84  LLVMContext Context;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();90 91  // Rewrite it to a temp file with size limit.92  TempFile Temp("profile", "afdo", "", true);93  bool isEmpty = false;94  {95    DEF_VAR_RETURN_IF_ERROR(Writer,96                            SampleProfileWriter::create(Temp.path(), Format));97    if (Compress)98      Writer->setToCompressAllSections();99    std::error_code EC = Writer->writeWithSizeLimit(OldProfiles, SizeLimit);100    // too_large means no sample could be written because SizeLimit is too101    // small. Otherwise any other error code indicates unexpected failure.102    if (EC == sampleprof_error::too_large)103      isEmpty = true;104    else if (EC)105      return EC;106  }107 108  // Read the temp file to get new profiles. Use the default empty profile if109  // 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));114  if (!isEmpty) {115    VAR_RETURN_IF_ERROR(NewReader, SampleProfileReader::create(116                                       Temp.path().str(), Context, *FS));117    RETURN_IF_ERROR(NewReader->read());118    NewProfiles = NewReader->getProfiles();119  }120 121  // Check temp file is actually within size limit.122  uint64_t FileSize;123  RETURN_IF_ERROR(sys::fs::file_size(Temp.path(), FileSize));124  EXPECT_LE(FileSize, SizeLimit);125 126  // For every sample in the new profile, confirm it is in the old profile and127  // unchanged.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);135    }136  }137  return nullptr;138}139 140TEST(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),144        Succeeded());145}146 147TEST(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),151        Succeeded());152}153 154TEST(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),159        Succeeded());160}161 162#if LLVM_ENABLE_ZLIB163TEST(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),168                         Succeeded());169}170#endif171