1 //===- llvm/unittest/XRay/GraphTest.cpp - XRay Graph unit tests -*- C++ -*-===//
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/XRay/Graph.h"
10 #include "gtest/gtest.h"
13 #include <type_traits>
25 typedef Graph
<VAttr
, EAttr
, unsigned> GraphT
;
26 typedef typename
GraphT::VertexIdentifier VI
;
27 typedef typename
GraphT::EdgeIdentifier EI
;
30 template <typename T
> class GraphTest
: public testing::Test
{
32 T Graph
= getTestGraph();
35 static T
getTestGraph() {
37 typename
std::remove_const
<T
>::type G
;
38 G
.insert(make_pair(1u, VAttr({3u})));
39 G
.insert(make_pair(2u, VAttr({5u})));
40 G
.insert(make_pair(3u, VAttr({7u})));
41 G
.insert(make_pair(4u, VAttr({11u})));
42 G
.insert(make_pair(5u, VAttr({13u})));
43 G
.insert(make_pair(6u, VAttr({17u})));
45 G
.insert(std::make_pair(EI(1u, 2u), EAttr({3u * 5u})));
46 G
.insert(std::make_pair(EI(2u, 3u), EAttr({5u * 7u})));
47 G
.insert(std::make_pair(EI(6u, 3u), EAttr({2u * 7u * 17u})));
48 G
.insert(std::make_pair(EI(4u, 6u), EAttr({11u * 17u})));
49 G
.insert(std::make_pair(EI(2u, 4u), EAttr({5u * 11u})));
50 G
.insert(std::make_pair(EI(2u, 5u), EAttr({5u * 13u})));
51 G
.insert(std::make_pair(EI(4u, 5u), EAttr({11u * 13u})));
57 typedef ::testing::Types
<GraphT
, const GraphT
> GraphTestTypes
;
59 using VVT
= typename
GraphT::VertexValueType
;
60 using EVT
= typename
GraphT::EdgeValueType
;
62 TYPED_TEST_CASE(GraphTest
, GraphTestTypes
);
64 template <typename T
> void graphVertexTester(T
&G
) {
65 std::set
<unsigned> V({1u, 2u, 3u, 4u, 5u, 6u});
66 std::vector
<unsigned> VA({0u, 3u, 5u, 7u, 11u, 13u, 17u});
68 EXPECT_EQ(V
.size(), G
.vertices().size());
69 EXPECT_FALSE(G
.vertices().empty());
70 for (unsigned u
: V
) {
73 EXPECT_EQ(1u, G
.count(u
));
74 EXPECT_EQ(VA
[u
], EVV
->VA
);
75 EXPECT_NE(G
.vertices().end(),
76 std::find_if(G
.vertices().begin(), G
.vertices().end(),
77 [&](const VVT
&VV
) { return VV
.first
== u
; }));
78 consumeError(EVV
.takeError());
81 for (auto &VVT
: G
.vertices()) {
82 EXPECT_EQ(1u, V
.count(VVT
.first
));
83 EXPECT_EQ(VA
[VVT
.first
], VVT
.second
.VA
);
87 template <typename T
> void graphEdgeTester(T
&G
) {
88 std::set
<unsigned> V({1u, 2u, 3u, 4u, 5u, 6u});
90 std::set
<std::pair
<unsigned, unsigned>> E(
91 {{1u, 2u}, {2u, 3u}, {6u, 3u}, {4u, 6u}, {2u, 4u}, {2u, 5u}, {4u, 5u}});
92 std::vector
<unsigned> VA({0u, 3u, 5u, 7u, 11u, 13u, 17u});
94 EXPECT_EQ(E
.size(), G
.edges().size());
95 EXPECT_FALSE(G
.edges().empty());
96 for (std::pair
<unsigned, unsigned> u
: E
) {
99 EXPECT_EQ(1u, G
.count(u
));
100 EXPECT_EQ(VA
[u
.first
] * VA
[u
.second
] * ((u
.first
> u
.second
) ? 2 : 1),
102 auto Pred
= [&](const EVT
&EV
) { return EV
.first
== u
; };
103 EXPECT_NE(G
.edges().end(),
104 std::find_if(G
.edges().begin(), G
.edges().end(), Pred
));
105 consumeError(EEV
.takeError());
108 for (auto &EV
: G
.edges()) {
109 EXPECT_EQ(1u, E
.count(EV
.first
));
110 EXPECT_EQ(VA
[EV
.first
.first
] * VA
[EV
.first
.second
] *
111 ((EV
.first
.first
> EV
.first
.second
) ? 2 : 1),
113 const auto &IE
= G
.inEdges(EV
.first
.second
);
114 const auto &OE
= G
.outEdges(EV
.first
.first
);
115 EXPECT_NE(IE
.size(), 0u);
116 EXPECT_NE(OE
.size(), 0u);
117 EXPECT_NE(IE
.begin(), IE
.end());
118 EXPECT_NE(OE
.begin(), OE
.end());
120 auto It
= std::find_if(
121 G
.inEdges(EV
.first
.second
).begin(), G
.inEdges(EV
.first
.second
).end(),
122 [&](const EVT
&EVI
) { return EVI
.first
== EV
.first
; });
123 EXPECT_NE(G
.inEdges(EV
.first
.second
).end(), It
);
126 auto It
= std::find_if(
127 G
.inEdges(EV
.first
.first
).begin(), G
.inEdges(EV
.first
.first
).end(),
128 [&](const EVT
&EVI
) { return EVI
.first
== EV
.first
; });
129 EXPECT_EQ(G
.inEdges(EV
.first
.first
).end(), It
);
133 std::find_if(G
.outEdges(EV
.first
.second
).begin(),
134 G
.outEdges(EV
.first
.second
).end(),
135 [&](const EVT
&EVI
) { return EVI
.first
== EV
.first
; });
136 EXPECT_EQ(G
.outEdges(EV
.first
.second
).end(), It
);
139 auto It
= std::find_if(
140 G
.outEdges(EV
.first
.first
).begin(), G
.outEdges(EV
.first
.first
).end(),
141 [&](const EVT
&EVI
) { return EVI
.first
== EV
.first
; });
142 EXPECT_NE(G
.outEdges(EV
.first
.first
).end(), It
);
147 TYPED_TEST(GraphTest
, TestGraphEdge
) {
148 auto &G
= this->Graph
;
153 TYPED_TEST(GraphTest
, TestGraphVertex
) {
154 auto &G
= this->Graph
;
156 graphVertexTester(G
);
159 TYPED_TEST(GraphTest
, TestCopyConstructor
) {
160 TypeParam
G(this->Graph
);
163 graphVertexTester(G
);
166 TYPED_TEST(GraphTest
, TestCopyAssign
) {
167 TypeParam G
= this->Graph
;
170 graphVertexTester(G
);
173 TYPED_TEST(GraphTest
, TestMoveConstructor
) {
174 TypeParam
G(std::move(this->Graph
));
177 graphVertexTester(G
);
180 // Tests the incremental Construction of a graph
181 TEST(GraphTest
, TestConstruction
) {
183 const GraphT
&G
= MG
;
184 EXPECT_EQ(0u, G
.count(0u));
185 EXPECT_EQ(0u, G
.count({0u, 1u}));
187 auto EE
= G
.at({0, 0});
188 EXPECT_FALSE(VE
); // G.at[0] returns an error
189 EXPECT_FALSE(EE
); // G.at[{0,0}] returns an error
190 consumeError(VE
.takeError());
191 consumeError(EE
.takeError());
192 EXPECT_TRUE(G
.vertices().empty());
193 EXPECT_TRUE(G
.edges().empty());
194 EXPECT_EQ(G
.vertices().begin(), G
.vertices().end());
195 EXPECT_EQ(G
.edges().begin(), G
.edges().end());
198 TEST(GraphTest
, TestiVertexAccessOperator
) {
200 const GraphT
&G
= MG
;
203 EXPECT_EQ(1u, MG
[0u].VA
);
204 EXPECT_EQ(1u, G
.count(0u));
205 EXPECT_EQ(0u, G
.count(1u));
206 EXPECT_EQ(1u, MG
[0u].VA
);
209 EXPECT_EQ(1u, T
->VA
);
211 EXPECT_EQ(1u, G
.vertices().size());
212 EXPECT_EQ(0u, G
.edges().size());
213 EXPECT_FALSE(G
.vertices().empty());
214 EXPECT_TRUE(G
.edges().empty());
215 EXPECT_NE(G
.vertices().begin(), G
.vertices().end());
216 EXPECT_EQ(G
.edges().begin(), G
.edges().end());
217 EXPECT_EQ(1u, G
.vertices().begin()->second
.VA
);
218 EXPECT_EQ(0u, G
.vertices().begin()->first
);
219 EXPECT_EQ(0u, G
.outEdges(0u).size());
220 EXPECT_TRUE(G
.outEdges(0u).empty());
221 EXPECT_EQ(G
.outEdges(0u).begin(), G
.outEdges(0u).end());
222 EXPECT_EQ(0u, G
.inEdges(0u).size());
223 EXPECT_TRUE(G
.inEdges(0u).empty());
224 EXPECT_EQ(G
.inEdges(0u).begin(), G
.inEdges(0u).end());
227 TEST(GraphTest
, TestEdgeAccessOperator
) {
229 const GraphT
&G
= MG
;
232 EI
EdgeIdent({0u, 0u});
233 EXPECT_EQ(2u, MG
[EdgeIdent
].EA
);
234 EXPECT_EQ(1u, G
.count({0u, 0u}));
235 EXPECT_EQ(0u, G
.count({0u, 1u}));
236 EXPECT_EQ(1u, G
.count(0u));
237 EXPECT_NE(1u, G
.count(1u));
238 auto T
= G
.at({0u, 0u});
239 EXPECT_TRUE(T
&& T
->EA
== 2u);
240 EXPECT_EQ(1u, G
.edges().size());
241 EXPECT_EQ(1u, G
.vertices().size());
242 EXPECT_FALSE(G
.edges().empty());
243 EXPECT_FALSE(G
.vertices().empty());
244 EXPECT_NE(G
.edges().begin(), G
.edges().end());
245 EXPECT_EQ(EI(0u, 0u), G
.edges().begin()->first
);
246 EXPECT_EQ(2u, G
.edges().begin()->second
.EA
);
247 EXPECT_EQ(1u, G
.outEdges(0u).size());
248 EXPECT_FALSE(G
.outEdges(0u).empty());
249 EXPECT_NE(G
.outEdges(0u).begin(), G
.outEdges(0u).end());
250 EXPECT_EQ(EI(0u, 0u), G
.outEdges(0u).begin()->first
);
251 EXPECT_EQ(2u, G
.outEdges(0u).begin()->second
.EA
);
252 EXPECT_EQ(++(G
.outEdges(0u).begin()), G
.outEdges(0u).end());
253 EXPECT_EQ(1u, G
.inEdges(0u).size());
254 EXPECT_FALSE(G
.inEdges(0u).empty());
255 EXPECT_NE(G
.inEdges(0u).begin(), G
.inEdges(0u).end());
256 EXPECT_EQ(EI(0u, 0u), G
.inEdges(0u).begin()->first
);
257 EXPECT_EQ(2u, G
.inEdges(0u).begin()->second
.EA
);
258 EXPECT_EQ(++(G
.inEdges(0u).begin()), G
.inEdges(0u).end());