about summary refs log tree commit diff homepage
path: root/test/Dogfood/ImmutableSet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/Dogfood/ImmutableSet.cpp')
-rw-r--r--test/Dogfood/ImmutableSet.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/test/Dogfood/ImmutableSet.cpp b/test/Dogfood/ImmutableSet.cpp
new file mode 100644
index 00000000..7b816de4
--- /dev/null
+++ b/test/Dogfood/ImmutableSet.cpp
@@ -0,0 +1,134 @@
+// RUN: llvm-g++ -I../../../include -g -DMAX_ELEMENTS=4 -fno-exceptions --emit-llvm -c -o %t1.bc %s
+// RUN: %klee --libc=klee --max-forks=200 --no-output --exit-on-error --optimize --disable-inlining --use-non-uniform-random-search --use-cex-cache %t1.bc
+
+#include "klee/klee.h"
+#include "klee/Internal/ADT/ImmutableSet.h"
+
+using namespace klee;
+
+typedef ImmutableSet<unsigned> T;
+
+bool iff(bool a, bool b) {
+  return !!a == !!b;
+}
+
+template<typename InputIterator, typename T>
+bool contains(InputIterator begin, InputIterator end, T item) {
+  for (; begin!=end; ++begin)
+    if (*begin == item)
+      return true;
+  return false;
+}
+
+bool equal(T &a, T &b) {
+  T::iterator aIt=a.begin(), ae=a.end(), bIt=b.begin(), be=b.end();
+  for (; aIt!=ae && bIt!=be; ++aIt, ++bIt)
+    if (*aIt != *bIt)
+      return false;
+  if (aIt!=ae) return false;
+  if (bIt!=be) return false;
+  return true;
+}
+
+template<typename InputIterator, typename T>
+void remove(InputIterator begin, InputIterator end, T item) {
+  InputIterator out = begin;
+  for (; begin!=end; ++begin) {
+    if (*begin!=item) {
+      if (out!=begin)
+        *out = *begin;
+      ++out;
+    }
+  }
+}
+
+void check_set(T &set, unsigned num, unsigned *values) {
+  assert(set.size() == num);
+
+  // must contain only values
+  unsigned item = klee_range(0, 256, "range");
+  assert(iff(contains(values, values+num, item),
+             set.count(item)));
+
+  // each value must be findable, must be its own lower bound, and
+  // must be one behind its upper bound
+  for (unsigned i=0; i<num; i++) {
+    unsigned item = values[i];
+    assert(set.count(item));
+    T::iterator it = set.find(item);
+    T::iterator lb = set.lower_bound(item);
+    T::iterator ub = set.upper_bound(item);
+    assert(it != set.end());                // must exit
+    assert(*it == item);                    // must be itself
+    assert(lb == it);                       // must be own lower bound
+    assert(--ub == it);                     // must be one behind upper
+  }
+
+  // for items not in the set...
+  unsigned item2 = klee_range(0, 256, "range");
+  if (!set.count(item2)) {
+    assert(set.find(item2) == set.end());
+
+    T::iterator lb = set.lower_bound(item2);
+    for (T::iterator it=set.begin(); it!=lb; ++it)      
+      assert(*it < item2);
+    for (T::iterator it=lb, ie=set.end(); it!=ie; ++it)
+      assert(*it >= item2);
+
+    T::iterator ub = set.upper_bound(item2);
+    for (T::iterator it=set.begin(); it!=ub; ++it)
+      assert(*it <= item2);
+    for (T::iterator it=ub, ie=set.end(); it!=ie; ++it)
+      assert(*it > item2);
+  }
+}
+
+#ifndef MAX_ELEMENTS
+#define MAX_ELEMENTS 4
+#endif
+
+void test() {
+  unsigned num=0, values[MAX_ELEMENTS];
+  T set;
+
+  assert(MAX_ELEMENTS >= 0);
+  for (unsigned i=0; i<klee_range(0,MAX_ELEMENTS+1, "range"); i++) {
+    unsigned item = klee_range(0, 256, "range");
+    if (contains(values, values+num, item))
+      klee_silent_exit(0);
+
+    set = set.insert(item);
+    values[num++] = item;
+  }
+  
+  check_set(set, num, values);
+
+  unsigned item = klee_range(0, 256, "range");  
+  if (contains(values, values+num, item)) { // in tree
+    // insertion is invariant
+    T set2 = set.insert(item);
+    assert(equal(set2, set));
+
+    // check remove
+    T set3 = set.remove(item);
+    assert(!equal(set3, set)); // mostly just for coverage
+    assert(set3.size() + 1 == set.size());
+    assert(!set3.count(item));
+  } else { // not in tree
+    // removal is invariant
+    T set2 = set.remove(item);
+    assert(equal(set2, set));
+
+    // check insert
+    T set3 = set.insert(item);
+    assert(!equal(set3, set)); // mostly just for coverage
+    assert(set3.size() == set.size() + 1);
+    assert(set3.count(item));
+  }
+}
+
+int main(int argc, char **argv) {
+  test();
+  assert(T::getAllocated() == 0);
+  return 0;
+}