|
@@ -0,0 +1,336 @@
|
|
|
+#include "tests/ProbingHashMapTests.h"
|
|
|
+
|
|
|
+#include <stdio.h>
|
|
|
+
|
|
|
+#include "data/ProbingHashMap.h"
|
|
|
+#include "test/Test.h"
|
|
|
+
|
|
|
+using IntMap = Core::ProbingHashMap<int, int>;
|
|
|
+
|
|
|
+static void testAdd() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(5, 4));
|
|
|
+ int* value = map.search(5);
|
|
|
+ CORE_TEST_NOT_NULL(value);
|
|
|
+ if(value != nullptr) {
|
|
|
+ CORE_TEST_EQUAL(4, *value);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void testMultipleAdd() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(5, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(10, 3));
|
|
|
+ CORE_TEST_ERROR(map.add(15, 2));
|
|
|
+ CORE_TEST_TRUE(map.contains(5));
|
|
|
+ CORE_TEST_TRUE(map.contains(10));
|
|
|
+ CORE_TEST_TRUE(map.contains(15));
|
|
|
+ int* a = map.search(5);
|
|
|
+ int* b = map.search(10);
|
|
|
+ int* c = map.search(15);
|
|
|
+ CORE_TEST_NOT_NULL(a);
|
|
|
+ CORE_TEST_NOT_NULL(b);
|
|
|
+ CORE_TEST_NOT_NULL(c);
|
|
|
+ if(a != nullptr && b != nullptr && c != nullptr) {
|
|
|
+ CORE_TEST_EQUAL(4, *a);
|
|
|
+ CORE_TEST_EQUAL(3, *b);
|
|
|
+ CORE_TEST_EQUAL(2, *c);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*static void testSearch() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_NULL(map.search(6));
|
|
|
+}
|
|
|
+
|
|
|
+static void testAddReplace() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(5, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(5, 10));
|
|
|
+ CORE_TEST_TRUE(map.contains(5));
|
|
|
+ int* a = map.search(5);
|
|
|
+ CORE_TEST_NOT_NULL(a);
|
|
|
+ if(a != nullptr) {
|
|
|
+ CORE_TEST_EQUAL(10, *a);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void testClear() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(5, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(4, 10));
|
|
|
+ map.clear();
|
|
|
+ CORE_TEST_FALSE(map.contains(5));
|
|
|
+ CORE_TEST_FALSE(map.contains(4));
|
|
|
+}
|
|
|
+
|
|
|
+static void testOverflow() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ for(int i = 0; i < 100000; i++) {
|
|
|
+ CORE_TEST_ERROR(map.add(i, i));
|
|
|
+ }
|
|
|
+ for(int i = 0; i < 100000; i++) {
|
|
|
+ CORE_TEST_TRUE(map.contains(i));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct A final {
|
|
|
+ int a;
|
|
|
+ int b;
|
|
|
+
|
|
|
+ A(int a_, int b_) : a(a_), b(b_) {
|
|
|
+ }
|
|
|
+
|
|
|
+ // none of these should be needed for the hashmap
|
|
|
+ A(const A&) = delete;
|
|
|
+ A(A&&) = delete;
|
|
|
+ A& operator=(const A&) = delete;
|
|
|
+ A& operator=(A&&) = delete;
|
|
|
+
|
|
|
+ bool operator==(const A& other) const {
|
|
|
+ return a == other.a && b == other.b;
|
|
|
+ }
|
|
|
+
|
|
|
+ template<typename String>
|
|
|
+ check_return Core::Error toString(String& s) const {
|
|
|
+ CORE_RETURN_ERROR(s.append("A("));
|
|
|
+ CORE_RETURN_ERROR(s.append(a));
|
|
|
+ CORE_RETURN_ERROR(s.append(", "));
|
|
|
+ CORE_RETURN_ERROR(s.append(b));
|
|
|
+ CORE_RETURN_ERROR(s.append(")"));
|
|
|
+ return Core::Error::NONE;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+static void testEmplace() {
|
|
|
+ Core::HashMap<int, A> map;
|
|
|
+
|
|
|
+ A* ar = nullptr;
|
|
|
+ CORE_TEST_ERROR(map.tryEmplace(ar, 0, 3, 4));
|
|
|
+ CORE_TEST_ERROR(map.tryEmplace(ar, 3, 4, 5));
|
|
|
+ CORE_TEST_ERROR(map.tryEmplace(ar, 20, 5, 6));
|
|
|
+ CORE_TEST_EQUAL(Core::Error::EXISTING_KEY, map.tryEmplace(ar, 3, 6, 7));
|
|
|
+ CORE_TEST_EQUAL(Core::Error::EXISTING_KEY, map.tryEmplace(ar, 20, 7, 8));
|
|
|
+
|
|
|
+ A* a = map.search(0);
|
|
|
+ A* b = map.search(3);
|
|
|
+ A* c = map.search(20);
|
|
|
+
|
|
|
+ CORE_TEST_NOT_NULL(a);
|
|
|
+ CORE_TEST_NOT_NULL(b);
|
|
|
+ CORE_TEST_NOT_NULL(c);
|
|
|
+
|
|
|
+ if(a != nullptr && b != nullptr && c != nullptr) {
|
|
|
+ CORE_TEST_EQUAL(A(3, 4), *a);
|
|
|
+ CORE_TEST_EQUAL(A(4, 5), *b);
|
|
|
+ CORE_TEST_EQUAL(A(5, 6), *c);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void testToString1() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(1, 3));
|
|
|
+ CORE_TEST_ERROR(map.add(2, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(3, 5));
|
|
|
+ CORE_TEST_STRING("[1 = 3, 2 = 4, 3 = 5]", map);
|
|
|
+}
|
|
|
+
|
|
|
+static void testToString2() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(1, 3));
|
|
|
+ CORE_TEST_STRING("[1 = 3]", map);
|
|
|
+}
|
|
|
+
|
|
|
+static void testToString3() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_STRING("[]", map);
|
|
|
+}
|
|
|
+
|
|
|
+static void testCopy() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(1, 3));
|
|
|
+ CORE_TEST_ERROR(map.add(2, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(3, 5));
|
|
|
+ IntMap copy;
|
|
|
+ CORE_TEST_ERROR(copy.copyFrom(map));
|
|
|
+
|
|
|
+ int* a[6] = {map.search(1), map.search(2), map.search(3),
|
|
|
+ copy.search(1), copy.search(2), copy.search(3)};
|
|
|
+ for(int i = 0; i < 3; i++) {
|
|
|
+ CORE_TEST_NOT_NULL(a[i]);
|
|
|
+ CORE_TEST_NOT_NULL(a[i + 3]);
|
|
|
+ if(a[i] != nullptr && a[i + 3] != nullptr) {
|
|
|
+ CORE_TEST_EQUAL(*(a[i]), *(a[i + 3]));
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void testMove() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(1, 3));
|
|
|
+ CORE_TEST_ERROR(map.add(2, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(3, 5));
|
|
|
+ IntMap move(Core::move(map));
|
|
|
+
|
|
|
+ int* a = move.search(1);
|
|
|
+ int* b = move.search(2);
|
|
|
+ int* c = move.search(3);
|
|
|
+
|
|
|
+ CORE_TEST_NOT_NULL(a);
|
|
|
+ CORE_TEST_NOT_NULL(b);
|
|
|
+ CORE_TEST_NOT_NULL(c);
|
|
|
+
|
|
|
+ if(a != nullptr && b != nullptr && c != nullptr) {
|
|
|
+ CORE_TEST_EQUAL(3, *a);
|
|
|
+ CORE_TEST_EQUAL(4, *b);
|
|
|
+ CORE_TEST_EQUAL(5, *c);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void testMoveAssignment() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(1, 3));
|
|
|
+ CORE_TEST_ERROR(map.add(2, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(3, 5));
|
|
|
+
|
|
|
+ IntMap move;
|
|
|
+ move = Core::move(map);
|
|
|
+
|
|
|
+ int* a = move.search(1);
|
|
|
+ int* b = move.search(2);
|
|
|
+ int* c = move.search(3);
|
|
|
+
|
|
|
+ CORE_TEST_NOT_NULL(a);
|
|
|
+ CORE_TEST_NOT_NULL(b);
|
|
|
+ CORE_TEST_NOT_NULL(c);
|
|
|
+
|
|
|
+ if(a != nullptr && b != nullptr && c != nullptr) {
|
|
|
+ CORE_TEST_EQUAL(3, *a);
|
|
|
+ CORE_TEST_EQUAL(4, *b);
|
|
|
+ CORE_TEST_EQUAL(5, *c);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void testRemove() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(1, 3));
|
|
|
+ CORE_TEST_ERROR(map.add(2, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(3, 5));
|
|
|
+
|
|
|
+ CORE_TEST_ERROR(map.remove(2));
|
|
|
+ CORE_TEST_EQUAL(Core::Error::NOT_FOUND, map.remove(7));
|
|
|
+
|
|
|
+ int* a = map.search(1);
|
|
|
+ int* b = map.search(2);
|
|
|
+ int* c = map.search(3);
|
|
|
+
|
|
|
+ CORE_TEST_NOT_NULL(a);
|
|
|
+ CORE_TEST_NULL(b);
|
|
|
+ CORE_TEST_NOT_NULL(c);
|
|
|
+
|
|
|
+ if(a != nullptr && c != nullptr) {
|
|
|
+ CORE_TEST_EQUAL(3, *a);
|
|
|
+ CORE_TEST_EQUAL(5, *c);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void testEntryForEach() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(5, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(10, 3));
|
|
|
+ CORE_TEST_ERROR(map.add(15, 2));
|
|
|
+
|
|
|
+ int counter = 0;
|
|
|
+ for(auto& entry : map.entries()) {
|
|
|
+ counter += entry.getKey() + entry.value;
|
|
|
+ }
|
|
|
+ CORE_TEST_EQUAL(39, counter);
|
|
|
+
|
|
|
+ const IntMap& cmap = map;
|
|
|
+ counter = 0;
|
|
|
+ for(const auto& entry : cmap.entries()) {
|
|
|
+ counter += entry.getKey() + entry.value;
|
|
|
+ }
|
|
|
+ CORE_TEST_EQUAL(39, counter);
|
|
|
+}
|
|
|
+
|
|
|
+static void testKeyForEach() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(5, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(10, 3));
|
|
|
+ CORE_TEST_ERROR(map.add(15, 2));
|
|
|
+
|
|
|
+ int counter = 0;
|
|
|
+ for(const int& key : map.keys()) {
|
|
|
+ counter += key;
|
|
|
+ }
|
|
|
+ CORE_TEST_EQUAL(30, counter);
|
|
|
+
|
|
|
+ const IntMap& cmap = map;
|
|
|
+ counter = 0;
|
|
|
+ for(const int& key : cmap.keys()) {
|
|
|
+ counter += key;
|
|
|
+ }
|
|
|
+ CORE_TEST_EQUAL(30, counter);
|
|
|
+}
|
|
|
+
|
|
|
+static void testValueForEach() {
|
|
|
+ IntMap map(1 << 30);
|
|
|
+ CORE_TEST_ERROR(map.add(5, 4));
|
|
|
+ CORE_TEST_ERROR(map.add(10, 3));
|
|
|
+ CORE_TEST_ERROR(map.add(15, 2));
|
|
|
+
|
|
|
+ int counter = 0;
|
|
|
+ for(int& value : map.values()) {
|
|
|
+ counter += value;
|
|
|
+ }
|
|
|
+ CORE_TEST_EQUAL(9, counter);
|
|
|
+
|
|
|
+ const IntMap& cmap = map;
|
|
|
+ counter = 0;
|
|
|
+ for(const int& value : cmap.values()) {
|
|
|
+ counter += value;
|
|
|
+ }
|
|
|
+ CORE_TEST_EQUAL(9, counter);
|
|
|
+}
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+static void testType() {
|
|
|
+ Core::HashMap<T, int> m;
|
|
|
+ CORE_TEST_ERROR(m.add(T(), 3));
|
|
|
+}
|
|
|
+
|
|
|
+static void testTypes() {
|
|
|
+ testType<char>();
|
|
|
+ testType<signed char>();
|
|
|
+ testType<signed short>();
|
|
|
+ testType<signed int>();
|
|
|
+ testType<signed long>();
|
|
|
+ testType<signed long long>();
|
|
|
+ testType<unsigned char>();
|
|
|
+ testType<unsigned short>();
|
|
|
+ testType<unsigned int>();
|
|
|
+ testType<unsigned long>();
|
|
|
+ testType<unsigned long long>();
|
|
|
+}*/
|
|
|
+
|
|
|
+void Core::ProbingHashMapTests::test() {
|
|
|
+ testAdd();
|
|
|
+ testMultipleAdd();
|
|
|
+ // testSearch();
|
|
|
+ // testAddReplace();
|
|
|
+ // testClear();
|
|
|
+ // testOverflow();
|
|
|
+ // testEmplace();
|
|
|
+ // testToString1();
|
|
|
+ // testToString2();
|
|
|
+ // testToString3();
|
|
|
+ // testCopy();
|
|
|
+ // testMove();
|
|
|
+ // testMoveAssignment();
|
|
|
+ // testRemove();
|
|
|
+ // testEntryForEach();
|
|
|
+ // testKeyForEach();
|
|
|
+ // testValueForEach();
|
|
|
+ // testTypes();
|
|
|
+}
|