Mercurial > hg > CbC > CbC_llvm
comparison unittests/ADT/DirectedGraphTest.cpp @ 147:c2174574ed3a
LLVM 10
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 16:55:33 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
134:3a76565eade5 | 147:c2174574ed3a |
---|---|
1 //===- llvm/unittest/ADT/DirectedGraphTest.cpp ------------------*- 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-exception | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 // | |
9 // This file defines concrete derivations of the directed-graph base classes | |
10 // for testing purposes. | |
11 // | |
12 //===----------------------------------------------------------------------===// | |
13 | |
14 #include "llvm/ADT/DirectedGraph.h" | |
15 #include "llvm/ADT/GraphTraits.h" | |
16 #include "llvm/ADT/SCCIterator.h" | |
17 #include "llvm/ADT/SmallPtrSet.h" | |
18 #include "gtest/gtest.h" | |
19 | |
20 namespace llvm { | |
21 | |
22 //===--------------------------------------------------------------------===// | |
23 // Derived nodes, edges and graph types based on DirectedGraph. | |
24 //===--------------------------------------------------------------------===// | |
25 | |
26 class DGTestNode; | |
27 class DGTestEdge; | |
28 using DGTestNodeBase = DGNode<DGTestNode, DGTestEdge>; | |
29 using DGTestEdgeBase = DGEdge<DGTestNode, DGTestEdge>; | |
30 using DGTestBase = DirectedGraph<DGTestNode, DGTestEdge>; | |
31 | |
32 class DGTestNode : public DGTestNodeBase { | |
33 public: | |
34 DGTestNode() = default; | |
35 }; | |
36 | |
37 class DGTestEdge : public DGTestEdgeBase { | |
38 public: | |
39 DGTestEdge() = delete; | |
40 DGTestEdge(DGTestNode &N) : DGTestEdgeBase(N) {} | |
41 }; | |
42 | |
43 class DGTestGraph : public DGTestBase { | |
44 public: | |
45 DGTestGraph() = default; | |
46 ~DGTestGraph(){}; | |
47 }; | |
48 | |
49 using EdgeListTy = SmallVector<DGTestEdge *, 2>; | |
50 | |
51 //===--------------------------------------------------------------------===// | |
52 // GraphTraits specializations for the DGTest | |
53 //===--------------------------------------------------------------------===// | |
54 | |
55 template <> struct GraphTraits<DGTestNode *> { | |
56 using NodeRef = DGTestNode *; | |
57 | |
58 static DGTestNode *DGTestGetTargetNode(DGEdge<DGTestNode, DGTestEdge> *P) { | |
59 return &P->getTargetNode(); | |
60 } | |
61 | |
62 // Provide a mapped iterator so that the GraphTrait-based implementations can | |
63 // find the target nodes without having to explicitly go through the edges. | |
64 using ChildIteratorType = | |
65 mapped_iterator<DGTestNode::iterator, decltype(&DGTestGetTargetNode)>; | |
66 using ChildEdgeIteratorType = DGTestNode::iterator; | |
67 | |
68 static NodeRef getEntryNode(NodeRef N) { return N; } | |
69 static ChildIteratorType child_begin(NodeRef N) { | |
70 return ChildIteratorType(N->begin(), &DGTestGetTargetNode); | |
71 } | |
72 static ChildIteratorType child_end(NodeRef N) { | |
73 return ChildIteratorType(N->end(), &DGTestGetTargetNode); | |
74 } | |
75 | |
76 static ChildEdgeIteratorType child_edge_begin(NodeRef N) { | |
77 return N->begin(); | |
78 } | |
79 static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } | |
80 }; | |
81 | |
82 template <> | |
83 struct GraphTraits<DGTestGraph *> : public GraphTraits<DGTestNode *> { | |
84 using nodes_iterator = DGTestGraph::iterator; | |
85 static NodeRef getEntryNode(DGTestGraph *DG) { return *DG->begin(); } | |
86 static nodes_iterator nodes_begin(DGTestGraph *DG) { return DG->begin(); } | |
87 static nodes_iterator nodes_end(DGTestGraph *DG) { return DG->end(); } | |
88 }; | |
89 | |
90 //===--------------------------------------------------------------------===// | |
91 // Test various modification and query functions. | |
92 //===--------------------------------------------------------------------===// | |
93 | |
94 TEST(DirectedGraphTest, AddAndConnectNodes) { | |
95 DGTestGraph DG; | |
96 DGTestNode N1, N2, N3; | |
97 DGTestEdge E1(N1), E2(N2), E3(N3); | |
98 | |
99 // Check that new nodes can be added successfully. | |
100 EXPECT_TRUE(DG.addNode(N1)); | |
101 EXPECT_TRUE(DG.addNode(N2)); | |
102 EXPECT_TRUE(DG.addNode(N3)); | |
103 | |
104 // Check that duplicate nodes are not added to the graph. | |
105 EXPECT_FALSE(DG.addNode(N1)); | |
106 | |
107 // Check that nodes can be connected using valid edges with no errors. | |
108 EXPECT_TRUE(DG.connect(N1, N2, E2)); | |
109 EXPECT_TRUE(DG.connect(N2, N3, E3)); | |
110 EXPECT_TRUE(DG.connect(N3, N1, E1)); | |
111 | |
112 // The graph looks like this now: | |
113 // | |
114 // +---------------+ | |
115 // v | | |
116 // N1 -> N2 -> N3 -+ | |
117 | |
118 // Check that already connected nodes with the given edge are not connected | |
119 // again (ie. edges are between nodes are not duplicated). | |
120 EXPECT_FALSE(DG.connect(N3, N1, E1)); | |
121 | |
122 // Check that there are 3 nodes in the graph. | |
123 EXPECT_TRUE(DG.size() == 3); | |
124 | |
125 // Check that the added nodes can be found in the graph. | |
126 EXPECT_NE(DG.findNode(N3), DG.end()); | |
127 | |
128 // Check that nodes that are not part of the graph are not found. | |
129 DGTestNode N4; | |
130 EXPECT_EQ(DG.findNode(N4), DG.end()); | |
131 | |
132 // Check that findIncommingEdgesToNode works correctly. | |
133 EdgeListTy EL; | |
134 EXPECT_TRUE(DG.findIncomingEdgesToNode(N1, EL)); | |
135 EXPECT_TRUE(EL.size() == 1); | |
136 EXPECT_EQ(*EL[0], E1); | |
137 } | |
138 | |
139 TEST(DirectedGraphTest, AddRemoveEdge) { | |
140 DGTestGraph DG; | |
141 DGTestNode N1, N2, N3; | |
142 DGTestEdge E1(N1), E2(N2), E3(N3); | |
143 DG.addNode(N1); | |
144 DG.addNode(N2); | |
145 DG.addNode(N3); | |
146 DG.connect(N1, N2, E2); | |
147 DG.connect(N2, N3, E3); | |
148 DG.connect(N3, N1, E1); | |
149 | |
150 // The graph looks like this now: | |
151 // | |
152 // +---------------+ | |
153 // v | | |
154 // N1 -> N2 -> N3 -+ | |
155 | |
156 // Check that there are 3 nodes in the graph. | |
157 EXPECT_TRUE(DG.size() == 3); | |
158 | |
159 // Check that the target nodes of the edges are correct. | |
160 EXPECT_EQ(E1.getTargetNode(), N1); | |
161 EXPECT_EQ(E2.getTargetNode(), N2); | |
162 EXPECT_EQ(E3.getTargetNode(), N3); | |
163 | |
164 // Remove the edge from N1 to N2. | |
165 N1.removeEdge(E2); | |
166 | |
167 // The graph looks like this now: | |
168 // | |
169 // N2 -> N3 -> N1 | |
170 | |
171 // Check that there are no incoming edges to N2. | |
172 EdgeListTy EL; | |
173 EXPECT_FALSE(DG.findIncomingEdgesToNode(N2, EL)); | |
174 EXPECT_TRUE(EL.empty()); | |
175 | |
176 // Put the edge from N1 to N2 back in place. | |
177 N1.addEdge(E2); | |
178 | |
179 // Check that E2 is the only incoming edge to N2. | |
180 EL.clear(); | |
181 EXPECT_TRUE(DG.findIncomingEdgesToNode(N2, EL)); | |
182 EXPECT_EQ(*EL[0], E2); | |
183 } | |
184 | |
185 TEST(DirectedGraphTest, hasEdgeTo) { | |
186 DGTestGraph DG; | |
187 DGTestNode N1, N2, N3; | |
188 DGTestEdge E1(N1), E2(N2), E3(N3), E4(N1); | |
189 DG.addNode(N1); | |
190 DG.addNode(N2); | |
191 DG.addNode(N3); | |
192 DG.connect(N1, N2, E2); | |
193 DG.connect(N2, N3, E3); | |
194 DG.connect(N3, N1, E1); | |
195 DG.connect(N2, N1, E4); | |
196 | |
197 // The graph looks like this now: | |
198 // | |
199 // +-----+ | |
200 // v | | |
201 // N1 -> N2 -> N3 | |
202 // ^ | | |
203 // +-----------+ | |
204 | |
205 EXPECT_TRUE(N2.hasEdgeTo(N1)); | |
206 EXPECT_TRUE(N3.hasEdgeTo(N1)); | |
207 } | |
208 | |
209 TEST(DirectedGraphTest, AddRemoveNode) { | |
210 DGTestGraph DG; | |
211 DGTestNode N1, N2, N3; | |
212 DGTestEdge E1(N1), E2(N2), E3(N3); | |
213 DG.addNode(N1); | |
214 DG.addNode(N2); | |
215 DG.addNode(N3); | |
216 DG.connect(N1, N2, E2); | |
217 DG.connect(N2, N3, E3); | |
218 DG.connect(N3, N1, E1); | |
219 | |
220 // The graph looks like this now: | |
221 // | |
222 // +---------------+ | |
223 // v | | |
224 // N1 -> N2 -> N3 -+ | |
225 | |
226 // Check that there are 3 nodes in the graph. | |
227 EXPECT_TRUE(DG.size() == 3); | |
228 | |
229 // Check that a node in the graph can be removed, but not more than once. | |
230 EXPECT_TRUE(DG.removeNode(N1)); | |
231 EXPECT_EQ(DG.findNode(N1), DG.end()); | |
232 EXPECT_FALSE(DG.removeNode(N1)); | |
233 | |
234 // The graph looks like this now: | |
235 // | |
236 // N2 -> N3 | |
237 | |
238 // Check that there are 2 nodes in the graph and only N2 is connected to N3. | |
239 EXPECT_TRUE(DG.size() == 2); | |
240 EXPECT_TRUE(N3.getEdges().empty()); | |
241 EdgeListTy EL; | |
242 EXPECT_FALSE(DG.findIncomingEdgesToNode(N2, EL)); | |
243 EXPECT_TRUE(EL.empty()); | |
244 } | |
245 | |
246 TEST(DirectedGraphTest, SCC) { | |
247 | |
248 DGTestGraph DG; | |
249 DGTestNode N1, N2, N3, N4; | |
250 DGTestEdge E1(N1), E2(N2), E3(N3), E4(N4); | |
251 DG.addNode(N1); | |
252 DG.addNode(N2); | |
253 DG.addNode(N3); | |
254 DG.addNode(N4); | |
255 DG.connect(N1, N2, E2); | |
256 DG.connect(N2, N3, E3); | |
257 DG.connect(N3, N1, E1); | |
258 DG.connect(N3, N4, E4); | |
259 | |
260 // The graph looks like this now: | |
261 // | |
262 // +---------------+ | |
263 // v | | |
264 // N1 -> N2 -> N3 -+ N4 | |
265 // | ^ | |
266 // +--------+ | |
267 | |
268 // Test that there are two SCCs: | |
269 // 1. {N1, N2, N3} | |
270 // 2. {N4} | |
271 using NodeListTy = SmallPtrSet<DGTestNode *, 3>; | |
272 SmallVector<NodeListTy, 4> ListOfSCCs; | |
273 for (auto &SCC : make_range(scc_begin(&DG), scc_end(&DG))) | |
274 ListOfSCCs.push_back(NodeListTy(SCC.begin(), SCC.end())); | |
275 | |
276 EXPECT_TRUE(ListOfSCCs.size() == 2); | |
277 | |
278 for (auto &SCC : ListOfSCCs) { | |
279 if (SCC.size() > 1) | |
280 continue; | |
281 EXPECT_TRUE(SCC.size() == 1); | |
282 EXPECT_TRUE(SCC.count(&N4) == 1); | |
283 } | |
284 for (auto &SCC : ListOfSCCs) { | |
285 if (SCC.size() <= 1) | |
286 continue; | |
287 EXPECT_TRUE(SCC.size() == 3); | |
288 EXPECT_TRUE(SCC.count(&N1) == 1); | |
289 EXPECT_TRUE(SCC.count(&N2) == 1); | |
290 EXPECT_TRUE(SCC.count(&N3) == 1); | |
291 EXPECT_TRUE(SCC.count(&N4) == 0); | |
292 } | |
293 } | |
294 | |
295 } // namespace llvm |