brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.5 KiB · 7eb848f Raw
267 lines · cpp
1//===- ProfileTest.cpp - XRay Profile unit tests ----------------*- C++ -*-===//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#include "llvm/XRay/Profile.h"9#include "gmock/gmock.h"10#include "gtest/gtest.h"11 12#include <numeric>13 14namespace llvm {15namespace xray {16namespace {17 18using ::testing::AllOf;19using ::testing::ElementsAre;20using ::testing::Eq;21using ::testing::Field;22using ::testing::Not;23using ::testing::Pair;24using ::testing::UnorderedElementsAre;25 26TEST(ProfileTest, CreateProfile) { Profile P; }27 28TEST(ProfileTest, InternPath) {29  Profile P;30  auto Path0 = P.internPath({3, 2, 1});31  auto Path1 = P.internPath({3, 2, 1});32  auto Path2 = P.internPath({2, 1});33  EXPECT_THAT(Path0, Eq(Path1));34  EXPECT_THAT(Path0, Not(Eq(Path2)));35}36 37TEST(ProfileTest, ExpandPath) {38  Profile P;39  auto PathID = P.internPath({3, 2, 1});40  auto PathOrError = P.expandPath(PathID);41  if (!PathOrError)42    FAIL() << "Error: " << PathOrError.takeError();43  EXPECT_THAT(PathOrError.get(), ElementsAre(3, 2, 1));44}45 46TEST(ProfileTest, AddBlocks) {47  Profile P;48  // Expect an error on adding empty blocks.49  EXPECT_TRUE(errorToBool(P.addBlock({})));50 51  // Thread blocks may not be empty.52  EXPECT_TRUE(errorToBool(P.addBlock({1, {}})));53 54  // Thread blocks with data must succeed.55  EXPECT_FALSE(errorToBool(P.addBlock(56      Profile::Block{Profile::ThreadID{1},57                     {58                         {P.internPath({2, 1}), Profile::Data{1, 1000}},59                         {P.internPath({3, 2, 1}), Profile::Data{10, 100}},60                     }})));61}62 63TEST(ProfileTest, CopyProfile) {64  Profile P0, P1;65  EXPECT_FALSE(errorToBool(P0.addBlock(66      Profile::Block{Profile::ThreadID{1},67                     {68                         {P0.internPath({2, 1}), Profile::Data{1, 1000}},69                         {P0.internPath({3, 2, 1}), Profile::Data{10, 100}},70                     }})));71  P1 = P0;72  EXPECT_THAT(73      P1, UnorderedElementsAre(AllOf(74              Field(&Profile::Block::Thread, Eq(Profile::ThreadID{1})),75              Field(&Profile::Block::PathData,76                    UnorderedElementsAre(77                        Pair(P1.internPath({2, 1}),78                             AllOf(Field(&Profile::Data::CallCount, Eq(1u)),79                                   Field(&Profile::Data::CumulativeLocalTime,80                                         Eq(1000u)))),81                        Pair(P1.internPath({3, 2, 1}),82                             AllOf(Field(&Profile::Data::CallCount, Eq(10u)),83                                   Field(&Profile::Data::CumulativeLocalTime,84                                         Eq(100u)))))))));85}86 87TEST(ProfileTest, MoveProfile) {88  Profile P0, P1;89  EXPECT_FALSE(errorToBool(P0.addBlock(90      Profile::Block{Profile::ThreadID{1},91                     {92                         {P0.internPath({2, 1}), Profile::Data{1, 1000}},93                         {P0.internPath({3, 2, 1}), Profile::Data{10, 100}},94                     }})));95  P1 = std::move(P0);96  EXPECT_THAT(97      P1, UnorderedElementsAre(AllOf(98              Field(&Profile::Block::Thread, Eq(Profile::ThreadID{1})),99              Field(&Profile::Block::PathData,100                    UnorderedElementsAre(101                        Pair(P1.internPath({2, 1}),102                             AllOf(Field(&Profile::Data::CallCount, Eq(1u)),103                                   Field(&Profile::Data::CumulativeLocalTime,104                                         Eq(1000u)))),105                        Pair(P1.internPath({3, 2, 1}),106                             AllOf(Field(&Profile::Data::CallCount, Eq(10u)),107                                   Field(&Profile::Data::CumulativeLocalTime,108                                         Eq(100u)))))))));109  EXPECT_THAT(P0, UnorderedElementsAre());110}111 112TEST(ProfileTest, MergeProfilesByThread) {113  Profile P0, P1;114 115  // Set up the blocks for two different threads in P0.116  EXPECT_FALSE(errorToBool(P0.addBlock(117      Profile::Block{Profile::ThreadID{1},118                     {{P0.internPath({2, 1}), Profile::Data{1, 1000}},119                      {P0.internPath({4, 1}), Profile::Data{1, 1000}}}})));120  EXPECT_FALSE(errorToBool(P0.addBlock(121      Profile::Block{Profile::ThreadID{2},122                     {{P0.internPath({3, 1}), Profile::Data{1, 1000}}}})));123 124  // Set up the blocks for two different threads in P1.125  EXPECT_FALSE(errorToBool(P1.addBlock(126      Profile::Block{Profile::ThreadID{1},127                     {{P1.internPath({2, 1}), Profile::Data{1, 1000}}}})));128  EXPECT_FALSE(errorToBool(P1.addBlock(129      Profile::Block{Profile::ThreadID{2},130                     {{P1.internPath({3, 1}), Profile::Data{1, 1000}},131                      {P1.internPath({4, 1}), Profile::Data{1, 1000}}}})));132 133  Profile Merged = mergeProfilesByThread(P0, P1);134  EXPECT_THAT(135      Merged,136      UnorderedElementsAre(137          // We want to see two threads after the merge.138          AllOf(Field(&Profile::Block::Thread, Eq(Profile::ThreadID{1})),139                Field(&Profile::Block::PathData,140                      UnorderedElementsAre(141                          Pair(Merged.internPath({2, 1}),142                               AllOf(Field(&Profile::Data::CallCount, Eq(2u)),143                                     Field(&Profile::Data::CumulativeLocalTime,144                                           Eq(2000u)))),145                          Pair(Merged.internPath({4, 1}),146                               AllOf(Field(&Profile::Data::CallCount, Eq(1u)),147                                     Field(&Profile::Data::CumulativeLocalTime,148                                           Eq(1000u))))))),149          AllOf(Field(&Profile::Block::Thread, Eq(Profile::ThreadID{2})),150                Field(&Profile::Block::PathData,151                      UnorderedElementsAre(152                          Pair(Merged.internPath({3, 1}),153                               AllOf(Field(&Profile::Data::CallCount, Eq(2u)),154                                     Field(&Profile::Data::CumulativeLocalTime,155                                           Eq(2000u)))),156                          Pair(Merged.internPath({4, 1}),157                               AllOf(Field(&Profile::Data::CallCount, Eq(1u)),158                                     Field(&Profile::Data::CumulativeLocalTime,159                                           Eq(1000u)))))))));160}161 162TEST(ProfileTest, MergeProfilesByStack) {163  Profile P0, P1;164  EXPECT_FALSE(errorToBool(P0.addBlock(165      Profile::Block{Profile::ThreadID{1},166                     {{P0.internPath({2, 1}), Profile::Data{1, 1000}}}})));167  EXPECT_FALSE(errorToBool(P1.addBlock(168      Profile::Block{Profile::ThreadID{2},169                     {{P1.internPath({2, 1}), Profile::Data{1, 1000}}}})));170 171  Profile Merged = mergeProfilesByStack(P0, P1);172  EXPECT_THAT(Merged,173              ElementsAre(AllOf(174                  // We expect that we lose the ThreadID dimension in this175                  // algorithm.176                  Field(&Profile::Block::Thread, Eq(Profile::ThreadID{0})),177                  Field(&Profile::Block::PathData,178                        ElementsAre(Pair(179                            Merged.internPath({2, 1}),180                            AllOf(Field(&Profile::Data::CallCount, Eq(2u)),181                                  Field(&Profile::Data::CumulativeLocalTime,182                                        Eq(2000u)))))))));183}184 185TEST(ProfileTest, MergeProfilesByStackAccumulate) {186  std::vector<Profile> Profiles(3);187  EXPECT_FALSE(errorToBool(Profiles[0].addBlock(Profile::Block{188      Profile::ThreadID{1},189      {{Profiles[0].internPath({2, 1}), Profile::Data{1, 1000}}}})));190  EXPECT_FALSE(errorToBool(Profiles[1].addBlock(Profile::Block{191      Profile::ThreadID{2},192      {{Profiles[1].internPath({2, 1}), Profile::Data{1, 1000}}}})));193  EXPECT_FALSE(errorToBool(Profiles[2].addBlock(Profile::Block{194      Profile::ThreadID{3},195      {{Profiles[2].internPath({2, 1}), Profile::Data{1, 1000}}}})));196  Profile Merged = std::accumulate(Profiles.begin(), Profiles.end(), Profile(),197                                   mergeProfilesByStack);198  EXPECT_THAT(Merged,199              ElementsAre(AllOf(200                  // We expect that we lose the ThreadID dimension in this201                  // algorithm.202                  Field(&Profile::Block::Thread, Eq(Profile::ThreadID{0})),203                  Field(&Profile::Block::PathData,204                        ElementsAre(Pair(205                            Merged.internPath({2, 1}),206                            AllOf(Field(&Profile::Data::CallCount, Eq(3u)),207                                  Field(&Profile::Data::CumulativeLocalTime,208                                        Eq(3000u)))))))));209}210 211TEST(ProfileTest, MergeProfilesByThreadAccumulate) {212  std::vector<Profile> Profiles(2);213 214  // Set up the blocks for two different threads in Profiles[0].215  EXPECT_FALSE(errorToBool(Profiles[0].addBlock(Profile::Block{216      Profile::ThreadID{1},217      {{Profiles[0].internPath({2, 1}), Profile::Data{1, 1000}},218       {Profiles[0].internPath({4, 1}), Profile::Data{1, 1000}}}})));219  EXPECT_FALSE(errorToBool(Profiles[0].addBlock(Profile::Block{220      Profile::ThreadID{2},221      {{Profiles[0].internPath({3, 1}), Profile::Data{1, 1000}}}})));222 223  // Set up the blocks for two different threads in Profiles[1].224  EXPECT_FALSE(errorToBool(Profiles[1].addBlock(Profile::Block{225      Profile::ThreadID{1},226      {{Profiles[1].internPath({2, 1}), Profile::Data{1, 1000}}}})));227  EXPECT_FALSE(errorToBool(Profiles[1].addBlock(Profile::Block{228      Profile::ThreadID{2},229      {{Profiles[1].internPath({3, 1}), Profile::Data{1, 1000}},230       {Profiles[1].internPath({4, 1}), Profile::Data{1, 1000}}}})));231 232  Profile Merged = std::accumulate(Profiles.begin(), Profiles.end(), Profile(),233                                   mergeProfilesByThread);234  EXPECT_THAT(235      Merged,236      UnorderedElementsAre(237          // We want to see two threads after the merge.238          AllOf(Field(&Profile::Block::Thread, Eq(Profile::ThreadID{1})),239                Field(&Profile::Block::PathData,240                      UnorderedElementsAre(241                          Pair(Merged.internPath({2, 1}),242                               AllOf(Field(&Profile::Data::CallCount, Eq(2u)),243                                     Field(&Profile::Data::CumulativeLocalTime,244                                           Eq(2000u)))),245                          Pair(Merged.internPath({4, 1}),246                               AllOf(Field(&Profile::Data::CallCount, Eq(1u)),247                                     Field(&Profile::Data::CumulativeLocalTime,248                                           Eq(1000u))))))),249          AllOf(Field(&Profile::Block::Thread, Eq(Profile::ThreadID{2})),250                Field(&Profile::Block::PathData,251                      UnorderedElementsAre(252                          Pair(Merged.internPath({3, 1}),253                               AllOf(Field(&Profile::Data::CallCount, Eq(2u)),254                                     Field(&Profile::Data::CumulativeLocalTime,255                                           Eq(2000u)))),256                          Pair(Merged.internPath({4, 1}),257                               AllOf(Field(&Profile::Data::CallCount, Eq(1u)),258                                     Field(&Profile::Data::CumulativeLocalTime,259                                           Eq(1000u)))))))));260}261// FIXME: Add a test creating a Trace and generating a Profile262// FIXME: Add tests for ranking/sorting profile blocks by dimension263 264} // namespace265} // namespace xray266} // namespace llvm267