Home | History | Annotate | Download | only in tests
      1 //===-- sanitizer_bvgraph_test.cc -----------------------------------------===//
      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 // This file is a part of Sanitizer runtime.
     11 // Tests for sanitizer_bvgraph.h.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 #include "sanitizer_common/sanitizer_bvgraph.h"
     15 
     16 #include "sanitizer_test_utils.h"
     17 
     18 #include "gtest/gtest.h"
     19 
     20 #include <algorithm>
     21 #include <vector>
     22 #include <set>
     23 
     24 using namespace __sanitizer;
     25 using namespace std;
     26 
     27 typedef BasicBitVector<u8> BV1;
     28 typedef BasicBitVector<> BV2;
     29 typedef TwoLevelBitVector<> BV3;
     30 typedef TwoLevelBitVector<3, BasicBitVector<u8> > BV4;
     31 
     32 template<class G>
     33 void PrintGraph(const G &g) {
     34   for (uptr i = 0; i < g.size(); i++) {
     35     for (uptr j = 0; j < g.size(); j++) {
     36       fprintf(stderr, "%d", g.hasEdge(i, j));
     37     }
     38     fprintf(stderr, "\n");
     39   }
     40 }
     41 
     42 
     43 class SimpleGraph {
     44  public:
     45   void clear() { s_.clear(); }
     46   bool addEdge(uptr from, uptr to) {
     47     return s_.insert(idx(from, to)).second;
     48   }
     49   bool removeEdge(uptr from, uptr to) {
     50     return s_.erase(idx(from, to));
     51   }
     52   template <class G>
     53   void checkSameAs(G *g) {
     54     for (set<uptr>::iterator it = s_.begin(); it != s_.end(); ++it) {
     55       uptr from = *it >> 16;
     56       uptr to = *it & ((1 << 16) - 1);
     57       EXPECT_TRUE(g->removeEdge(from, to));
     58     }
     59     EXPECT_TRUE(g->empty());
     60   }
     61  private:
     62   uptr idx(uptr from, uptr to) {
     63     CHECK_LE(from|to, 1 << 16);
     64     return (from << 16) + to;
     65   }
     66   set<uptr> s_;
     67 };
     68 
     69 template <class BV>
     70 void BasicTest() {
     71   BVGraph<BV> g;
     72   g.clear();
     73   BV target;
     74   SimpleGraph s_g;
     75   set<uptr> s;
     76   set<uptr> s_target;
     77   int num_reachable = 0;
     78   for (int it = 0; it < 1000; it++) {
     79     target.clear();
     80     s_target.clear();
     81     for (int t = 0; t < 4; t++) {
     82       uptr idx = (uptr)my_rand() % g.size();
     83       EXPECT_EQ(target.setBit(idx), s_target.insert(idx).second);
     84     }
     85     uptr from = my_rand() % g.size();
     86     uptr to = my_rand() % g.size();
     87     EXPECT_EQ(g.addEdge(from, to), s_g.addEdge(from, to));
     88     EXPECT_TRUE(g.hasEdge(from, to));
     89     for (int i = 0; i < 10; i++) {
     90       from = my_rand() % g.size();
     91       bool is_reachable = g.isReachable(from, target);
     92       if (is_reachable) {
     93         uptr path[BV::kSize];
     94         uptr len;
     95         for (len = 1; len < BV::kSize; len++) {
     96           if (g.findPath(from, target, path, len) == len)
     97             break;
     98         }
     99         EXPECT_LT(len, BV::kSize);
    100         EXPECT_TRUE(target.getBit(path[len - 1]));
    101         // fprintf(stderr, "reachable: %zd; path %zd {%zd %zd %zd}\n",
    102         //        from, len, path[0], path[1], path[2]);
    103         num_reachable++;
    104       }
    105     }
    106   }
    107   EXPECT_GT(num_reachable, 0);
    108 }
    109 
    110 TEST(BVGraph, BasicTest) {
    111   BasicTest<BV1>();
    112   BasicTest<BV2>();
    113   BasicTest<BV3>();
    114   BasicTest<BV4>();
    115 }
    116 
    117 template <class BV>
    118 void RemoveEdges() {
    119   SimpleGraph s_g;
    120   BVGraph<BV> g;
    121   g.clear();
    122   BV bv;
    123   set<uptr> s;
    124   for (int it = 0; it < 100; it++) {
    125     s.clear();
    126     bv.clear();
    127     s_g.clear();
    128     g.clear();
    129     for (uptr j = 0; j < g.size() * 2; j++) {
    130       uptr from = my_rand() % g.size();
    131       uptr to = my_rand() % g.size();
    132       EXPECT_EQ(g.addEdge(from, to), s_g.addEdge(from, to));
    133     }
    134     for (uptr j = 0; j < 5; j++) {
    135       uptr idx = my_rand() % g.size();
    136       s.insert(idx);
    137       bv.setBit(idx);
    138     }
    139 
    140     if (it % 2) {
    141       g.removeEdgesFrom(bv);
    142       for (set<uptr>::iterator from = s.begin(); from != s.end(); ++from) {
    143         for (uptr to = 0; to < g.size(); to++)
    144           s_g.removeEdge(*from, to);
    145       }
    146     } else {
    147       g.removeEdgesTo(bv);
    148       for (set<uptr>::iterator to = s.begin(); to != s.end(); ++to) {
    149         for (uptr from = 0; from < g.size(); from++)
    150           s_g.removeEdge(from, *to);
    151       }
    152     }
    153     s_g.checkSameAs(&g);
    154   }
    155 }
    156 
    157 TEST(BVGraph, RemoveEdges) {
    158   RemoveEdges<BV1>();
    159   RemoveEdges<BV2>();
    160   RemoveEdges<BV3>();
    161   RemoveEdges<BV4>();
    162 }
    163 
    164 template <class BV>
    165 void Test_isReachable() {
    166   uptr path[5];
    167   BVGraph<BV> g;
    168   g.clear();
    169   BV target;
    170   target.clear();
    171   uptr t0 = 0;
    172   uptr t1 = g.size() - 1;
    173   target.setBit(t0);
    174   target.setBit(t1);
    175 
    176   uptr f0 = 1;
    177   uptr f1 = 2;
    178   uptr f2 = g.size() / 2;
    179   uptr f3 = g.size() - 2;
    180 
    181   EXPECT_FALSE(g.isReachable(f0, target));
    182   EXPECT_FALSE(g.isReachable(f1, target));
    183   EXPECT_FALSE(g.isReachable(f2, target));
    184   EXPECT_FALSE(g.isReachable(f3, target));
    185 
    186   g.addEdge(f0, f1);
    187   g.addEdge(f1, f2);
    188   g.addEdge(f2, f3);
    189   EXPECT_FALSE(g.isReachable(f0, target));
    190   EXPECT_FALSE(g.isReachable(f1, target));
    191   EXPECT_FALSE(g.isReachable(f2, target));
    192   EXPECT_FALSE(g.isReachable(f3, target));
    193 
    194   g.addEdge(f1, t0);
    195   EXPECT_TRUE(g.isReachable(f0, target));
    196   EXPECT_TRUE(g.isReachable(f1, target));
    197   EXPECT_FALSE(g.isReachable(f2, target));
    198   EXPECT_FALSE(g.isReachable(f3, target));
    199   EXPECT_EQ(g.findPath(f0, target, path, ARRAY_SIZE(path)), 3U);
    200   EXPECT_EQ(path[0], f0);
    201   EXPECT_EQ(path[1], f1);
    202   EXPECT_EQ(path[2], t0);
    203   EXPECT_EQ(g.findPath(f1, target, path, ARRAY_SIZE(path)), 2U);
    204   EXPECT_EQ(path[0], f1);
    205   EXPECT_EQ(path[1], t0);
    206 
    207   g.addEdge(f3, t1);
    208   EXPECT_TRUE(g.isReachable(f0, target));
    209   EXPECT_TRUE(g.isReachable(f1, target));
    210   EXPECT_TRUE(g.isReachable(f2, target));
    211   EXPECT_TRUE(g.isReachable(f3, target));
    212 }
    213 
    214 TEST(BVGraph, isReachable) {
    215   Test_isReachable<BV1>();
    216   Test_isReachable<BV2>();
    217   Test_isReachable<BV3>();
    218   Test_isReachable<BV4>();
    219 }
    220 
    221 template <class BV>
    222 void LongCycle() {
    223   BVGraph<BV> g;
    224   g.clear();
    225   vector<uptr> path_vec(g.size());
    226   uptr *path = path_vec.data();
    227   uptr start = 5;
    228   for (uptr i = start; i < g.size() - 1; i++) {
    229     g.addEdge(i, i + 1);
    230     for (uptr j = 0; j < start; j++)
    231       g.addEdge(i, j);
    232   }
    233   //  Bad graph that looks like this:
    234   // 00000000000000
    235   // 00000000000000
    236   // 00000000000000
    237   // 00000000000000
    238   // 00000000000000
    239   // 11111010000000
    240   // 11111001000000
    241   // 11111000100000
    242   // 11111000010000
    243   // 11111000001000
    244   // 11111000000100
    245   // 11111000000010
    246   // 11111000000001
    247   // if (g.size() <= 64) PrintGraph(g);
    248   BV target;
    249   for (uptr i = start + 1; i < g.size(); i += 11) {
    250     // if ((i & (i - 1)) == 0) fprintf(stderr, "Path: : %zd\n", i);
    251     target.clear();
    252     target.setBit(i);
    253     EXPECT_TRUE(g.isReachable(start, target));
    254     EXPECT_EQ(g.findPath(start, target, path, g.size()), i - start + 1);
    255   }
    256 }
    257 
    258 TEST(BVGraph, LongCycle) {
    259   LongCycle<BV1>();
    260   LongCycle<BV2>();
    261   LongCycle<BV3>();
    262   LongCycle<BV4>();
    263 }
    264 
    265 template <class BV>
    266 void ShortestPath() {
    267   uptr path[8];
    268   BVGraph<BV> g;
    269   g.clear();
    270   BV t7;
    271   t7.clear();
    272   t7.setBit(7);
    273   // 1=>2=>3=>4=>5=>6=>7
    274   // 1=>7
    275   g.addEdge(1, 2);
    276   g.addEdge(2, 3);
    277   g.addEdge(3, 4);
    278   g.addEdge(4, 5);
    279   g.addEdge(5, 6);
    280   g.addEdge(6, 7);
    281   g.addEdge(1, 7);
    282   EXPECT_TRUE(g.isReachable(1, t7));
    283   // No path of length 1.
    284   EXPECT_EQ(0U, g.findPath(1, t7, path, 1));
    285   // Trying to find a path of len 2..6 gives path of len 2.
    286   EXPECT_EQ(2U, g.findPath(1, t7, path, 2));
    287   EXPECT_EQ(2U, g.findPath(1, t7, path, 3));
    288   EXPECT_EQ(2U, g.findPath(1, t7, path, 4));
    289   EXPECT_EQ(2U, g.findPath(1, t7, path, 5));
    290   EXPECT_EQ(2U, g.findPath(1, t7, path, 6));
    291   // Trying to find a path of len 7 gives path of len 7, because this is DFS.
    292   EXPECT_EQ(7U, g.findPath(1, t7, path, 7));
    293   // But findShortestPath will find the shortest path.
    294   EXPECT_EQ(2U, g.findShortestPath(1, t7, path, 2));
    295   EXPECT_EQ(2U, g.findShortestPath(1, t7, path, 7));
    296 }
    297 
    298 TEST(BVGraph, ShortestPath) {
    299   ShortestPath<BV1>();
    300   ShortestPath<BV2>();
    301   ShortestPath<BV3>();
    302   ShortestPath<BV4>();
    303 }
    304 
    305 template <class BV>
    306 void RunAddEdgesTest() {
    307   BVGraph<BV> g;
    308   BV from;
    309   const int kMaxEdges = 10;
    310   uptr added_edges[kMaxEdges];
    311   g.clear();
    312   from.clear();
    313   EXPECT_EQ(0U, g.addEdges(from, 0, added_edges, kMaxEdges));
    314   EXPECT_EQ(0U, g.addEdges(from, 1, added_edges, kMaxEdges));
    315   from.setBit(0);
    316   EXPECT_EQ(1U, g.addEdges(from, 1, added_edges, kMaxEdges));
    317   EXPECT_EQ(0U, added_edges[0]);
    318   EXPECT_EQ(0U, g.addEdges(from, 1, added_edges, kMaxEdges));
    319 
    320   from.clear();
    321   from.setBit(1);
    322   EXPECT_EQ(1U, g.addEdges(from, 4, added_edges, kMaxEdges));
    323   EXPECT_TRUE(g.hasEdge(1, 4));
    324   EXPECT_FALSE(g.hasEdge(1, 5));
    325   EXPECT_EQ(1U, added_edges[0]);
    326   from.setBit(2);
    327   from.setBit(3);
    328   EXPECT_EQ(2U, g.addEdges(from, 4, added_edges, kMaxEdges));
    329   EXPECT_TRUE(g.hasEdge(2, 4));
    330   EXPECT_FALSE(g.hasEdge(2, 5));
    331   EXPECT_TRUE(g.hasEdge(3, 4));
    332   EXPECT_FALSE(g.hasEdge(3, 5));
    333   EXPECT_EQ(2U, added_edges[0]);
    334   EXPECT_EQ(3U, added_edges[1]);
    335 }
    336 
    337 TEST(BVGraph, AddEdgesTest) {
    338   RunAddEdgesTest<BV2>();
    339 }
    340