summaryrefslogtreecommitdiff
path: root/test/example/small_set.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/example/small_set.cpp')
-rw-r--r--test/example/small_set.cpp221
1 files changed, 221 insertions, 0 deletions
diff --git a/test/example/small_set.cpp b/test/example/small_set.cpp
new file mode 100644
index 000000000..48bcb6a7b
--- /dev/null
+++ b/test/example/small_set.cpp
@@ -0,0 +1,221 @@
+#include <algorithm>
+#include <cassert>
+#include <iostream>
+#include <vector>
+
+#include "support/small_set.h"
+
+using namespace wasm;
+
+template<typename T>
+void assertContents(T& t, const std::vector<int>& expectedContents) {
+ assert(t.size() == expectedContents.size());
+ for (auto item : expectedContents) {
+ assert(t.count(item) == 1);
+ }
+ // Also test this using an iterator and a const iterator to also get
+ // coverage there.
+ for (auto& item : t) {
+ assert(std::find(expectedContents.begin(), expectedContents.end(), item) !=
+ expectedContents.end());
+ }
+ for (const auto& item : t) {
+ assert(std::find(expectedContents.begin(), expectedContents.end(), item) !=
+ expectedContents.end());
+ }
+}
+
+template<typename T> void testAPI() {
+ {
+ T t;
+
+ // build up with no duplicates
+ assert(t.empty());
+ assert(t.size() == 0);
+ t.insert(1);
+ assertContents(t, {1});
+ assert(!t.empty());
+ assert(t.size() == 1);
+ t.insert(2);
+ assertContents(t, {1, 2});
+ assert(!t.empty());
+ assert(t.size() == 2);
+ t.insert(3);
+ assertContents(t, {1, 2, 3});
+ assert(!t.empty());
+
+ // unwind
+ assert(t.size() == 3);
+ t.erase(3);
+ assertContents(t, {1, 2});
+ assert(t.size() == 2);
+ t.erase(2);
+ assertContents(t, {1});
+ assert(t.size() == 1);
+ t.erase(1);
+ assertContents(t, {});
+ assert(t.size() == 0);
+ assert(t.empty());
+ }
+ {
+ T t;
+
+ // build up with duplicates
+ t.insert(1);
+ t.insert(2);
+ t.insert(2);
+ t.insert(3);
+ assertContents(t, {1, 2, 3});
+ assert(t.size() == 3);
+
+ // unwind by erasing (in the opposite direction from before)
+ assert(t.count(1) == 1);
+ assert(t.count(2) == 1);
+ assert(t.count(3) == 1);
+ assert(t.count(1337) == 0);
+
+ t.erase(1);
+ assert(t.count(1) == 0);
+
+ assert(t.size() == 2);
+
+ assert(t.count(2) == 1);
+ t.erase(2);
+ assert(t.count(2) == 0);
+
+ assert(t.size() == 1);
+
+ assert(t.count(3) == 1);
+ t.erase(3);
+
+ assert(t.count(1) == 0);
+ assert(t.count(2) == 0);
+ assert(t.count(3) == 0);
+ assert(t.count(1337) == 0);
+
+ assert(t.size() == 0);
+ }
+ {
+ T t;
+
+ // build up
+ t.insert(1);
+ t.insert(2);
+ t.insert(3);
+
+ // unwind by clearing
+ t.clear();
+ assert(t.size() == 0);
+ assert(t.empty());
+ }
+ {
+ T t, u;
+ // comparisons
+ assert(t == u);
+ t.insert(1);
+ assert(t != u);
+ u.insert(1);
+ assert(t == u);
+ u.erase(1);
+ assert(t != u);
+ u.insert(2);
+ assert(t != u);
+ }
+ {
+ T t, u;
+ // comparisons should ignore the order of insertion
+ t.insert(1);
+ t.insert(2);
+ u.insert(2);
+ u.insert(1);
+ assert(t == u);
+ }
+ {
+ T t, u;
+ // comparisons should ignore the mode: in a SmallSet<1>, a set of size 1
+ // can be either fixed - if we just grew it to size 1 - or flexible - if we
+ // grew it enough to be flexible, then shrank it back (as it only becomes
+ // fixed at size 0).
+ t.insert(1);
+
+ u.insert(1);
+ u.insert(2);
+
+ // one extra item in u
+ assert(t != u);
+ assert(u != t);
+
+ // remove the extra item
+ u.erase(2);
+
+ assert(t == u);
+ assert(u == t);
+ }
+ {
+ T t, u;
+ // as above, but for size 2, and don't erase the last item added
+ t.insert(1);
+ t.insert(2);
+
+ u.insert(3);
+ u.insert(2);
+ u.insert(1);
+
+ // one extra item in u
+ assert(t != u);
+ assert(u != t);
+
+ // remove the extra item
+ u.erase(3);
+
+ assert(t == u);
+ assert(u == t);
+ }
+}
+
+template<typename T> void testInternals() {
+ {
+ T s;
+ // Start out using fixed storage.
+ assert(s.TEST_ONLY_NEVER_USE_usingFixed());
+ // Adding one item still keeps us using fixed storage, as that is the exact
+ // amount we have in fact.
+ s.insert(0);
+ assert(s.TEST_ONLY_NEVER_USE_usingFixed());
+ // Adding one more item forces us to use flexible storage.
+ s.insert(1);
+ assert(!s.TEST_ONLY_NEVER_USE_usingFixed());
+ // Removing an item returns us to size 1, *but we keep using flexible
+ // storage*. We do not ping-pong between flexible and fixed; once flexible,
+ // we stay that way.
+ s.erase(0);
+ assert(!s.TEST_ONLY_NEVER_USE_usingFixed());
+ // However, removing all items does return us to using fixed storage, should
+ // we ever insert again.
+ s.erase(1);
+ assert(s.empty());
+ assert(s.TEST_ONLY_NEVER_USE_usingFixed());
+ // And once more we can add an additional item while remaining fixed.
+ s.insert(10);
+ assert(s.TEST_ONLY_NEVER_USE_usingFixed());
+ }
+}
+
+int main() {
+ testAPI<SmallSet<int, 0>>();
+ testAPI<SmallSet<int, 1>>();
+ testAPI<SmallSet<int, 2>>();
+ testAPI<SmallSet<int, 3>>();
+ testAPI<SmallSet<int, 10>>();
+
+ testAPI<SmallUnorderedSet<int, 0>>();
+ testAPI<SmallUnorderedSet<int, 1>>();
+ testAPI<SmallUnorderedSet<int, 2>>();
+ testAPI<SmallUnorderedSet<int, 3>>();
+ testAPI<SmallUnorderedSet<int, 10>>();
+
+ testInternals<SmallSet<int, 1>>();
+ testInternals<SmallUnorderedSet<int, 1>>();
+
+ std::cout << "ok.\n";
+}