forked from OSchip/llvm-project
177 lines
4.8 KiB
C++
177 lines
4.8 KiB
C++
//===-- sanitizer_bitvector_test.cc ---------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file is a part of Sanitizer runtime.
|
|
// Tests for sanitizer_bitvector.h.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#include "sanitizer_common/sanitizer_bitvector.h"
|
|
|
|
#include "sanitizer_test_utils.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <set>
|
|
|
|
using namespace __sanitizer;
|
|
using namespace std;
|
|
|
|
|
|
// Check the 'bv' == 's' and that the indexes go in increasing order.
|
|
// Also check the BV::Iterator
|
|
template <class BV>
|
|
static void CheckBV(const BV &bv, const set<uptr> &s) {
|
|
BV t;
|
|
t.copyFrom(bv);
|
|
set<uptr> t_s(s);
|
|
uptr last_idx = bv.size();
|
|
uptr count = 0;
|
|
for (typename BV::Iterator it(bv); it.hasNext();) {
|
|
uptr idx = it.next();
|
|
count++;
|
|
if (last_idx != bv.size())
|
|
EXPECT_LT(last_idx, idx);
|
|
last_idx = idx;
|
|
EXPECT_TRUE(s.count(idx));
|
|
}
|
|
EXPECT_EQ(count, s.size());
|
|
|
|
last_idx = bv.size();
|
|
while (!t.empty()) {
|
|
uptr idx = t.getAndClearFirstOne();
|
|
if (last_idx != bv.size())
|
|
EXPECT_LT(last_idx, idx);
|
|
last_idx = idx;
|
|
EXPECT_TRUE(t_s.erase(idx));
|
|
}
|
|
EXPECT_TRUE(t_s.empty());
|
|
}
|
|
|
|
template <class BV>
|
|
void Print(const BV &bv) {
|
|
BV t;
|
|
t.copyFrom(bv);
|
|
while (!t.empty()) {
|
|
uptr idx = t.getAndClearFirstOne();
|
|
fprintf(stderr, "%zd ", idx);
|
|
}
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
void Print(const set<uptr> &s) {
|
|
for (set<uptr>::iterator it = s.begin(); it != s.end(); ++it) {
|
|
fprintf(stderr, "%zd ", *it);
|
|
}
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
template <class BV>
|
|
void TestBitVector(uptr expected_size) {
|
|
BV bv, bv1, t_bv;
|
|
EXPECT_EQ(expected_size, BV::kSize);
|
|
bv.clear();
|
|
EXPECT_TRUE(bv.empty());
|
|
bv.setBit(5);
|
|
EXPECT_FALSE(bv.empty());
|
|
EXPECT_FALSE(bv.getBit(4));
|
|
EXPECT_FALSE(bv.getBit(6));
|
|
EXPECT_TRUE(bv.getBit(5));
|
|
bv.clearBit(5);
|
|
EXPECT_FALSE(bv.getBit(5));
|
|
|
|
// test random bits
|
|
bv.clear();
|
|
set<uptr> s;
|
|
for (uptr it = 0; it < 1000; it++) {
|
|
uptr bit = ((uptr)my_rand() % bv.size());
|
|
EXPECT_EQ(bv.getBit(bit), s.count(bit) == 1);
|
|
switch (my_rand() % 2) {
|
|
case 0:
|
|
EXPECT_EQ(bv.setBit(bit), s.insert(bit).second);
|
|
break;
|
|
case 1:
|
|
size_t old_size = s.size();
|
|
s.erase(bit);
|
|
EXPECT_EQ(bv.clearBit(bit), old_size > s.size());
|
|
break;
|
|
}
|
|
EXPECT_EQ(bv.getBit(bit), s.count(bit) == 1);
|
|
}
|
|
|
|
vector<uptr>bits(bv.size());
|
|
// Test setUnion, setIntersection, setDifference,
|
|
// intersectsWith, and getAndClearFirstOne.
|
|
for (uptr it = 0; it < 30; it++) {
|
|
// iota
|
|
for (size_t j = 0; j < bits.size(); j++) bits[j] = j;
|
|
random_shuffle(bits.begin(), bits.end());
|
|
set<uptr> s, s1, t_s;
|
|
bv.clear();
|
|
bv1.clear();
|
|
uptr n_bits = ((uptr)my_rand() % bv.size()) + 1;
|
|
uptr n_bits1 = (uptr)my_rand() % (bv.size() / 2);
|
|
EXPECT_TRUE(n_bits > 0 && n_bits <= bv.size());
|
|
EXPECT_TRUE(n_bits1 < bv.size() / 2);
|
|
for (uptr i = 0; i < n_bits; i++) {
|
|
bv.setBit(bits[i]);
|
|
s.insert(bits[i]);
|
|
}
|
|
CheckBV(bv, s);
|
|
for (uptr i = 0; i < n_bits1; i++) {
|
|
bv1.setBit(bits[bv.size() / 2 + i]);
|
|
s1.insert(bits[bv.size() / 2 + i]);
|
|
}
|
|
CheckBV(bv1, s1);
|
|
|
|
vector<uptr> vec;
|
|
set_intersection(s.begin(), s.end(), s1.begin(), s1.end(),
|
|
back_insert_iterator<vector<uptr> >(vec));
|
|
EXPECT_EQ(bv.intersectsWith(bv1), !vec.empty());
|
|
|
|
// setUnion
|
|
t_s = s;
|
|
t_bv.copyFrom(bv);
|
|
t_s.insert(s1.begin(), s1.end());
|
|
EXPECT_EQ(t_bv.setUnion(bv1), s.size() != t_s.size());
|
|
CheckBV(t_bv, t_s);
|
|
|
|
// setIntersection
|
|
t_s = set<uptr>(vec.begin(), vec.end());
|
|
t_bv.copyFrom(bv);
|
|
EXPECT_EQ(t_bv.setIntersection(bv1), s.size() != t_s.size());
|
|
CheckBV(t_bv, t_s);
|
|
|
|
// setDifference
|
|
vec.clear();
|
|
set_difference(s.begin(), s.end(), s1.begin(), s1.end(),
|
|
back_insert_iterator<vector<uptr> >(vec));
|
|
t_s = set<uptr>(vec.begin(), vec.end());
|
|
t_bv.copyFrom(bv);
|
|
EXPECT_EQ(t_bv.setDifference(bv1), s.size() != t_s.size());
|
|
CheckBV(t_bv, t_s);
|
|
}
|
|
}
|
|
|
|
TEST(SanitizerCommon, BasicBitVector) {
|
|
TestBitVector<BasicBitVector<u8> >(8);
|
|
TestBitVector<BasicBitVector<u16> >(16);
|
|
TestBitVector<BasicBitVector<> >(SANITIZER_WORDSIZE);
|
|
}
|
|
|
|
TEST(SanitizerCommon, TwoLevelBitVector) {
|
|
uptr ws = SANITIZER_WORDSIZE;
|
|
TestBitVector<TwoLevelBitVector<1, BasicBitVector<u8> > >(8 * 8);
|
|
TestBitVector<TwoLevelBitVector<> >(ws * ws);
|
|
TestBitVector<TwoLevelBitVector<2> >(ws * ws * 2);
|
|
TestBitVector<TwoLevelBitVector<3> >(ws * ws * 3);
|
|
TestBitVector<TwoLevelBitVector<3, BasicBitVector<u16> > >(16 * 16 * 3);
|
|
}
|