Home | History | Annotate | Download | only in XRay
      1 //===- llvm/unittest/XRay/GraphTest.cpp - XRay Graph unit tests -*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/XRay/Graph.h"
     11 #include "gtest/gtest.h"
     12 #include <iostream>
     13 #include <set>
     14 #include <type_traits>
     15 
     16 using namespace llvm;
     17 using namespace xray;
     18 
     19 namespace {
     20 struct VAttr {
     21   unsigned VA;
     22 };
     23 struct EAttr {
     24   unsigned EA;
     25 };
     26 typedef Graph<VAttr, EAttr, unsigned> GraphT;
     27 typedef typename GraphT::VertexIdentifier VI;
     28 typedef typename GraphT::EdgeIdentifier EI;
     29 
     30 // Test Fixture
     31 template <typename T> class GraphTest : public testing::Test {
     32 protected:
     33   T Graph = getTestGraph();
     34 
     35 private:
     36   static T getTestGraph() {
     37     using std::make_pair;
     38     typename std::remove_const<T>::type G;
     39     G.insert(make_pair(1u, VAttr({3u})));
     40     G.insert(make_pair(2u, VAttr({5u})));
     41     G.insert(make_pair(3u, VAttr({7u})));
     42     G.insert(make_pair(4u, VAttr({11u})));
     43     G.insert(make_pair(5u, VAttr({13u})));
     44     G.insert(make_pair(6u, VAttr({17u})));
     45 
     46     G.insert(std::make_pair(EI(1u, 2u), EAttr({3u * 5u})));
     47     G.insert(std::make_pair(EI(2u, 3u), EAttr({5u * 7u})));
     48     G.insert(std::make_pair(EI(6u, 3u), EAttr({2u * 7u * 17u})));
     49     G.insert(std::make_pair(EI(4u, 6u), EAttr({11u * 17u})));
     50     G.insert(std::make_pair(EI(2u, 4u), EAttr({5u * 11u})));
     51     G.insert(std::make_pair(EI(2u, 5u), EAttr({5u * 13u})));
     52     G.insert(std::make_pair(EI(4u, 5u), EAttr({11u * 13u})));
     53 
     54     return G;
     55   }
     56 };
     57 
     58 typedef ::testing::Types<GraphT, const GraphT> GraphTestTypes;
     59 
     60 using VVT = typename GraphT::VertexValueType;
     61 using EVT = typename GraphT::EdgeValueType;
     62 
     63 TYPED_TEST_CASE(GraphTest, GraphTestTypes);
     64 
     65 template <typename T> void graphVertexTester(T &G) {
     66   std::set<unsigned> V({1u, 2u, 3u, 4u, 5u, 6u});
     67   std::vector<unsigned> VA({0u, 3u, 5u, 7u, 11u, 13u, 17u});
     68 
     69   EXPECT_EQ(V.size(), G.vertices().size());
     70   EXPECT_FALSE(G.vertices().empty());
     71   for (unsigned u : V) {
     72     auto EVV = G.at(u);
     73     ASSERT_TRUE(!!EVV);
     74     EXPECT_EQ(1u, G.count(u));
     75     EXPECT_EQ(VA[u], EVV->VA);
     76     EXPECT_NE(G.vertices().end(),
     77               std::find_if(G.vertices().begin(), G.vertices().end(),
     78                            [&](const VVT &VV) { return VV.first == u; }));
     79     consumeError(EVV.takeError());
     80   }
     81 
     82   for (auto &VVT : G.vertices()) {
     83     EXPECT_EQ(1u, V.count(VVT.first));
     84     EXPECT_EQ(VA[VVT.first], VVT.second.VA);
     85   }
     86 }
     87 
     88 template <typename T> void graphEdgeTester(T &G) {
     89   std::set<unsigned> V({1u, 2u, 3u, 4u, 5u, 6u});
     90 
     91   std::set<std::pair<unsigned, unsigned>> E(
     92       {{1u, 2u}, {2u, 3u}, {6u, 3u}, {4u, 6u}, {2u, 4u}, {2u, 5u}, {4u, 5u}});
     93   std::vector<unsigned> VA({0u, 3u, 5u, 7u, 11u, 13u, 17u});
     94 
     95   EXPECT_EQ(E.size(), G.edges().size());
     96   EXPECT_FALSE(G.edges().empty());
     97   for (std::pair<unsigned, unsigned> u : E) {
     98     auto EEV = G.at(u);
     99     ASSERT_TRUE(!!EEV);
    100     EXPECT_EQ(1u, G.count(u));
    101     EXPECT_EQ(VA[u.first] * VA[u.second] * ((u.first > u.second) ? 2 : 1),
    102               EEV->EA);
    103     auto Pred = [&](const EVT &EV) { return EV.first == u; };
    104     EXPECT_NE(G.edges().end(),
    105               std::find_if(G.edges().begin(), G.edges().end(), Pred));
    106     consumeError(EEV.takeError());
    107   }
    108 
    109   for (auto &EV : G.edges()) {
    110     EXPECT_EQ(1u, E.count(EV.first));
    111     EXPECT_EQ(VA[EV.first.first] * VA[EV.first.second] *
    112                   ((EV.first.first > EV.first.second) ? 2 : 1),
    113               EV.second.EA);
    114     const auto &IE = G.inEdges(EV.first.second);
    115     const auto &OE = G.outEdges(EV.first.first);
    116     EXPECT_NE(IE.size(), 0u);
    117     EXPECT_NE(OE.size(), 0u);
    118     EXPECT_NE(IE.begin(), IE.end());
    119     EXPECT_NE(OE.begin(), OE.end());
    120     {
    121       auto It = std::find_if(
    122           G.inEdges(EV.first.second).begin(), G.inEdges(EV.first.second).end(),
    123           [&](const EVT &EVI) { return EVI.first == EV.first; });
    124       EXPECT_NE(G.inEdges(EV.first.second).end(), It);
    125     }
    126     {
    127       auto It = std::find_if(
    128           G.inEdges(EV.first.first).begin(), G.inEdges(EV.first.first).end(),
    129           [&](const EVT &EVI) { return EVI.first == EV.first; });
    130       EXPECT_EQ(G.inEdges(EV.first.first).end(), It);
    131     }
    132     {
    133       auto It =
    134           std::find_if(G.outEdges(EV.first.second).begin(),
    135                        G.outEdges(EV.first.second).end(),
    136                        [&](const EVT &EVI) { return EVI.first == EV.first; });
    137       EXPECT_EQ(G.outEdges(EV.first.second).end(), It);
    138     }
    139     {
    140       auto It = std::find_if(
    141           G.outEdges(EV.first.first).begin(), G.outEdges(EV.first.first).end(),
    142           [&](const EVT &EVI) { return EVI.first == EV.first; });
    143       EXPECT_NE(G.outEdges(EV.first.first).end(), It);
    144     }
    145   }
    146 }
    147 
    148 TYPED_TEST(GraphTest, TestGraphEdge) {
    149   auto &G = this->Graph;
    150 
    151   graphEdgeTester(G);
    152 }
    153 
    154 TYPED_TEST(GraphTest, TestGraphVertex) {
    155   auto &G = this->Graph;
    156 
    157   graphVertexTester(G);
    158 }
    159 
    160 TYPED_TEST(GraphTest, TestCopyConstructor) {
    161   TypeParam G(this->Graph);
    162 
    163   graphEdgeTester(G);
    164   graphVertexTester(G);
    165 }
    166 
    167 TYPED_TEST(GraphTest, TestCopyAssign) {
    168   TypeParam G = this->Graph;
    169 
    170   graphEdgeTester(G);
    171   graphVertexTester(G);
    172 }
    173 
    174 TYPED_TEST(GraphTest, TestMoveConstructor) {
    175   TypeParam G(std::move(this->Graph));
    176 
    177   graphEdgeTester(G);
    178   graphVertexTester(G);
    179 }
    180 
    181 // Tests the incremental Construction of a graph
    182 TEST(GraphTest, TestConstruction) {
    183   GraphT MG;
    184   const GraphT &G = MG;
    185   EXPECT_EQ(0u, G.count(0u));
    186   EXPECT_EQ(0u, G.count({0u, 1u}));
    187   auto VE = G.at(0);
    188   auto EE = G.at({0, 0});
    189   EXPECT_FALSE(VE); // G.at[0] returns an error
    190   EXPECT_FALSE(EE); // G.at[{0,0}] returns an error
    191   consumeError(VE.takeError());
    192   consumeError(EE.takeError());
    193   EXPECT_TRUE(G.vertices().empty());
    194   EXPECT_TRUE(G.edges().empty());
    195   EXPECT_EQ(G.vertices().begin(), G.vertices().end());
    196   EXPECT_EQ(G.edges().begin(), G.edges().end());
    197 }
    198 
    199 TEST(GraphTest, TestiVertexAccessOperator) {
    200   GraphT MG;
    201   const GraphT &G = MG;
    202 
    203   MG[0u] = {1u};
    204   EXPECT_EQ(1u, MG[0u].VA);
    205   EXPECT_EQ(1u, G.count(0u));
    206   EXPECT_EQ(0u, G.count(1u));
    207   EXPECT_EQ(1u, MG[0u].VA);
    208   auto T = G.at(0u);
    209   EXPECT_TRUE(!!T);
    210   EXPECT_EQ(1u, T->VA);
    211 
    212   EXPECT_EQ(1u, G.vertices().size());
    213   EXPECT_EQ(0u, G.edges().size());
    214   EXPECT_FALSE(G.vertices().empty());
    215   EXPECT_TRUE(G.edges().empty());
    216   EXPECT_NE(G.vertices().begin(), G.vertices().end());
    217   EXPECT_EQ(G.edges().begin(), G.edges().end());
    218   EXPECT_EQ(1u, G.vertices().begin()->second.VA);
    219   EXPECT_EQ(0u, G.vertices().begin()->first);
    220   EXPECT_EQ(0u, G.outEdges(0u).size());
    221   EXPECT_TRUE(G.outEdges(0u).empty());
    222   EXPECT_EQ(G.outEdges(0u).begin(), G.outEdges(0u).end());
    223   EXPECT_EQ(0u, G.inEdges(0u).size());
    224   EXPECT_TRUE(G.inEdges(0u).empty());
    225   EXPECT_EQ(G.inEdges(0u).begin(), G.inEdges(0u).end());
    226 }
    227 
    228 TEST(GraphTest, TestEdgeAccessOperator) {
    229   GraphT MG;
    230   const GraphT &G = MG;
    231 
    232   MG[{0u, 0u}] = {2u};
    233   EI EdgeIdent({0u, 0u});
    234   EXPECT_EQ(2u, MG[EdgeIdent].EA);
    235   EXPECT_EQ(1u, G.count({0u, 0u}));
    236   EXPECT_EQ(0u, G.count({0u, 1u}));
    237   EXPECT_EQ(1u, G.count(0u));
    238   EXPECT_NE(1u, G.count(1u));
    239   auto T = G.at({0u, 0u});
    240   EXPECT_TRUE(T && T->EA == 2u);
    241   EXPECT_EQ(1u, G.edges().size());
    242   EXPECT_EQ(1u, G.vertices().size());
    243   EXPECT_FALSE(G.edges().empty());
    244   EXPECT_FALSE(G.vertices().empty());
    245   EXPECT_NE(G.edges().begin(), G.edges().end());
    246   EXPECT_EQ(EI(0u, 0u), G.edges().begin()->first);
    247   EXPECT_EQ(2u, G.edges().begin()->second.EA);
    248   EXPECT_EQ(1u, G.outEdges(0u).size());
    249   EXPECT_FALSE(G.outEdges(0u).empty());
    250   EXPECT_NE(G.outEdges(0u).begin(), G.outEdges(0u).end());
    251   EXPECT_EQ(EI(0u, 0u), G.outEdges(0u).begin()->first);
    252   EXPECT_EQ(2u, G.outEdges(0u).begin()->second.EA);
    253   EXPECT_EQ(++(G.outEdges(0u).begin()), G.outEdges(0u).end());
    254   EXPECT_EQ(1u, G.inEdges(0u).size());
    255   EXPECT_FALSE(G.inEdges(0u).empty());
    256   EXPECT_NE(G.inEdges(0u).begin(), G.inEdges(0u).end());
    257   EXPECT_EQ(EI(0u, 0u), G.inEdges(0u).begin()->first);
    258   EXPECT_EQ(2u, G.inEdges(0u).begin()->second.EA);
    259   EXPECT_EQ(++(G.inEdges(0u).begin()), G.inEdges(0u).end());
    260 }
    261 }
    262