1 //===-- sanitizer_bvgraph_test.cpp ----------------------------------------===//
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 // This file is a part of Sanitizer runtime.
10 // Tests for sanitizer_bvgraph.h.
12 //===----------------------------------------------------------------------===//
13 #include "sanitizer_common/sanitizer_bvgraph.h"
15 #include "sanitizer_test_utils.h"
17 #include "gtest/gtest.h"
23 using namespace __sanitizer
;
26 typedef BasicBitVector
<u8
> BV1
;
27 typedef BasicBitVector
<> BV2
;
28 typedef TwoLevelBitVector
<> BV3
;
29 typedef TwoLevelBitVector
<3, BasicBitVector
<u8
> > BV4
;
32 void PrintGraph(const G
&g
) {
33 for (uptr i
= 0; i
< g
.size(); i
++) {
34 for (uptr j
= 0; j
< g
.size(); j
++) {
35 fprintf(stderr
, "%d", g
.hasEdge(i
, j
));
37 fprintf(stderr
, "\n");
44 void clear() { s_
.clear(); }
45 bool addEdge(uptr from
, uptr to
) {
46 return s_
.insert(idx(from
, to
)).second
;
48 bool removeEdge(uptr from
, uptr to
) {
49 return s_
.erase(idx(from
, to
));
52 void checkSameAs(G
*g
) {
53 for (set
<uptr
>::iterator it
= s_
.begin(); it
!= s_
.end(); ++it
) {
54 uptr from
= *it
>> 16;
55 uptr to
= *it
& ((1 << 16) - 1);
56 EXPECT_TRUE(g
->removeEdge(from
, to
));
58 EXPECT_TRUE(g
->empty());
61 uptr
idx(uptr from
, uptr to
) {
62 CHECK_LE(from
|to
, 1 << 16);
63 return (from
<< 16) + to
;
76 int num_reachable
= 0;
77 for (int it
= 0; it
< 1000; it
++) {
80 for (int t
= 0; t
< 4; t
++) {
81 uptr idx
= (uptr
)my_rand() % g
.size();
82 EXPECT_EQ(target
.setBit(idx
), s_target
.insert(idx
).second
);
84 uptr from
= my_rand() % g
.size();
85 uptr to
= my_rand() % g
.size();
86 EXPECT_EQ(g
.addEdge(from
, to
), s_g
.addEdge(from
, to
));
87 EXPECT_TRUE(g
.hasEdge(from
, to
));
88 for (int i
= 0; i
< 10; i
++) {
89 from
= my_rand() % g
.size();
90 bool is_reachable
= g
.isReachable(from
, target
);
94 for (len
= 1; len
< BV::kSize
; len
++) {
95 if (g
.findPath(from
, target
, path
, len
) == len
)
98 EXPECT_LT(len
, BV::kSize
);
99 EXPECT_TRUE(target
.getBit(path
[len
- 1]));
100 // fprintf(stderr, "reachable: %zd; path %zd {%zd %zd %zd}\n",
101 // from, len, path[0], path[1], path[2]);
106 EXPECT_GT(num_reachable
, 0);
109 TEST(BVGraph
, BasicTest
) {
123 for (int it
= 0; it
< 100; it
++) {
128 for (uptr j
= 0; j
< g
.size() * 2; j
++) {
129 uptr from
= my_rand() % g
.size();
130 uptr to
= my_rand() % g
.size();
131 EXPECT_EQ(g
.addEdge(from
, to
), s_g
.addEdge(from
, to
));
133 for (uptr j
= 0; j
< 5; j
++) {
134 uptr idx
= my_rand() % g
.size();
140 g
.removeEdgesFrom(bv
);
141 for (set
<uptr
>::iterator from
= s
.begin(); from
!= s
.end(); ++from
) {
142 for (uptr to
= 0; to
< g
.size(); to
++)
143 s_g
.removeEdge(*from
, to
);
147 for (set
<uptr
>::iterator to
= s
.begin(); to
!= s
.end(); ++to
) {
148 for (uptr from
= 0; from
< g
.size(); from
++)
149 s_g
.removeEdge(from
, *to
);
156 TEST(BVGraph
, RemoveEdges
) {
164 void Test_isReachable() {
171 uptr t1
= g
.size() - 1;
177 uptr f2
= g
.size() / 2;
178 uptr f3
= g
.size() - 2;
180 EXPECT_FALSE(g
.isReachable(f0
, target
));
181 EXPECT_FALSE(g
.isReachable(f1
, target
));
182 EXPECT_FALSE(g
.isReachable(f2
, target
));
183 EXPECT_FALSE(g
.isReachable(f3
, target
));
188 EXPECT_FALSE(g
.isReachable(f0
, target
));
189 EXPECT_FALSE(g
.isReachable(f1
, target
));
190 EXPECT_FALSE(g
.isReachable(f2
, target
));
191 EXPECT_FALSE(g
.isReachable(f3
, target
));
194 EXPECT_TRUE(g
.isReachable(f0
, target
));
195 EXPECT_TRUE(g
.isReachable(f1
, target
));
196 EXPECT_FALSE(g
.isReachable(f2
, target
));
197 EXPECT_FALSE(g
.isReachable(f3
, target
));
198 EXPECT_EQ(g
.findPath(f0
, target
, path
, ARRAY_SIZE(path
)), 3U);
199 EXPECT_EQ(path
[0], f0
);
200 EXPECT_EQ(path
[1], f1
);
201 EXPECT_EQ(path
[2], t0
);
202 EXPECT_EQ(g
.findPath(f1
, target
, path
, ARRAY_SIZE(path
)), 2U);
203 EXPECT_EQ(path
[0], f1
);
204 EXPECT_EQ(path
[1], t0
);
207 EXPECT_TRUE(g
.isReachable(f0
, target
));
208 EXPECT_TRUE(g
.isReachable(f1
, target
));
209 EXPECT_TRUE(g
.isReachable(f2
, target
));
210 EXPECT_TRUE(g
.isReachable(f3
, target
));
213 TEST(BVGraph
, isReachable
) {
214 Test_isReachable
<BV1
>();
215 Test_isReachable
<BV2
>();
216 Test_isReachable
<BV3
>();
217 Test_isReachable
<BV4
>();
224 vector
<uptr
> path_vec(g
.size());
225 uptr
*path
= path_vec
.data();
227 for (uptr i
= start
; i
< g
.size() - 1; i
++) {
229 for (uptr j
= 0; j
< start
; j
++)
232 // Bad graph that looks like this:
246 // if (g.size() <= 64) PrintGraph(g);
248 for (uptr i
= start
+ 1; i
< g
.size(); i
+= 11) {
249 // if ((i & (i - 1)) == 0) fprintf(stderr, "Path: : %zd\n", i);
252 EXPECT_TRUE(g
.isReachable(start
, target
));
253 EXPECT_EQ(g
.findPath(start
, target
, path
, g
.size()), i
- start
+ 1);
257 TEST(BVGraph
, LongCycle
) {
265 void ShortestPath() {
272 // 1=>2=>3=>4=>5=>6=>7
281 EXPECT_TRUE(g
.isReachable(1, t7
));
282 // No path of length 1.
283 EXPECT_EQ(0U, g
.findPath(1, t7
, path
, 1));
284 // Trying to find a path of len 2..6 gives path of len 2.
285 EXPECT_EQ(2U, g
.findPath(1, t7
, path
, 2));
286 EXPECT_EQ(2U, g
.findPath(1, t7
, path
, 3));
287 EXPECT_EQ(2U, g
.findPath(1, t7
, path
, 4));
288 EXPECT_EQ(2U, g
.findPath(1, t7
, path
, 5));
289 EXPECT_EQ(2U, g
.findPath(1, t7
, path
, 6));
290 // Trying to find a path of len 7 gives path of len 7, because this is DFS.
291 EXPECT_EQ(7U, g
.findPath(1, t7
, path
, 7));
292 // But findShortestPath will find the shortest path.
293 EXPECT_EQ(2U, g
.findShortestPath(1, t7
, path
, 2));
294 EXPECT_EQ(2U, g
.findShortestPath(1, t7
, path
, 7));
297 TEST(BVGraph
, ShortestPath
) {
305 void RunAddEdgesTest() {
308 const int kMaxEdges
= 10;
309 uptr added_edges
[kMaxEdges
];
312 EXPECT_EQ(0U, g
.addEdges(from
, 0, added_edges
, kMaxEdges
));
313 EXPECT_EQ(0U, g
.addEdges(from
, 1, added_edges
, kMaxEdges
));
315 EXPECT_EQ(1U, g
.addEdges(from
, 1, added_edges
, kMaxEdges
));
316 EXPECT_EQ(0U, added_edges
[0]);
317 EXPECT_EQ(0U, g
.addEdges(from
, 1, added_edges
, kMaxEdges
));
321 EXPECT_EQ(1U, g
.addEdges(from
, 4, added_edges
, kMaxEdges
));
322 EXPECT_TRUE(g
.hasEdge(1, 4));
323 EXPECT_FALSE(g
.hasEdge(1, 5));
324 EXPECT_EQ(1U, added_edges
[0]);
327 EXPECT_EQ(2U, g
.addEdges(from
, 4, added_edges
, kMaxEdges
));
328 EXPECT_TRUE(g
.hasEdge(2, 4));
329 EXPECT_FALSE(g
.hasEdge(2, 5));
330 EXPECT_TRUE(g
.hasEdge(3, 4));
331 EXPECT_FALSE(g
.hasEdge(3, 5));
332 EXPECT_EQ(2U, added_edges
[0]);
333 EXPECT_EQ(3U, added_edges
[1]);
336 TEST(BVGraph
, AddEdgesTest
) {
337 RunAddEdgesTest
<BV2
>();