From ad3e4894da4d72d262bf70d0ddf76a249bd74f36 Mon Sep 17 00:00:00 2001
From: David Nieder <post@davidnieder.de>
Date: Sun, 1 Jan 2023 12:05:47 +0100
Subject: [PATCH] typed tests

---
 tests/argumentTypes.h      |  69 ++++++++++
 tests/test_constructor.cpp |  42 +++---
 tests/test_hashtable.cpp   | 254 +++++++++++++++++++++----------------
 3 files changed, 232 insertions(+), 133 deletions(-)
 create mode 100644 tests/argumentTypes.h

diff --git a/tests/argumentTypes.h b/tests/argumentTypes.h
new file mode 100644
index 0000000..ab884fa
--- /dev/null
+++ b/tests/argumentTypes.h
@@ -0,0 +1,69 @@
+/*
+ * Arguments to the hashtable construtor as different
+ * types to work with google tests typed tests.
+ */
+struct DefaultTable {
+	size_t m = 8;
+	float a = 0.75;
+	float s = 2;
+};
+
+struct EmptyTable {
+	size_t m = 0;
+	float a = 0.75;
+	float s = 2;
+};
+
+struct BigTable {
+	size_t m = 65536;
+	float a = 0.75;
+	float s = 2;
+};
+
+struct SmallAlphaDefaultS {
+	size_t m = 8;
+	float a = 0.10;
+	float s = 2;
+};
+
+struct SmallAlphaTinyS {
+	size_t m = 8;
+	float a = 0.10;
+	float s = 1.10;
+};
+
+struct SmallAlphaSmallS {
+	size_t m = 8;
+	float a = 0.10;
+	float s = 1.50;
+};
+
+struct SmallAlphaLargeS {
+	size_t m = 8;
+	float a = 0.10;
+	float s = 4;
+};
+
+struct LargeAlphaDefaultS {
+	size_t m = 8;
+	float a = 0.95;
+	float s = 2;
+};
+
+struct LargeAlphaTinyS {
+	size_t m = 8;
+	float a = 0.95;
+	float s = 1.10;
+};
+
+struct LargeAlphaSmallS {
+	size_t m = 8;
+	float a = 0.95;
+	float s = 1.50;
+};
+
+struct LargeAlphaLargeS {
+	size_t m = 8;
+	float a = 0.95;
+	float s = 4;
+};
diff --git a/tests/test_constructor.cpp b/tests/test_constructor.cpp
index d5e1217..d1c0831 100644
--- a/tests/test_constructor.cpp
+++ b/tests/test_constructor.cpp
@@ -3,7 +3,7 @@
 
 
 TEST(HashtableConstructor, DefaultParams) {
-	Hashtable h;
+	Hashtable<unsigned> h;
 
 	EXPECT_EQ(0, h.size());
 	EXPECT_EQ(8, h.capacity());
@@ -11,7 +11,7 @@ TEST(HashtableConstructor, DefaultParams) {
 }
 
 TEST(HashtableConstructor, TableSizeZero) {
-	Hashtable h(0);
+	Hashtable<unsigned> h(0);
 
 	EXPECT_EQ(0, h.size());
 	EXPECT_EQ(0, h.capacity());
@@ -19,40 +19,40 @@ TEST(HashtableConstructor, TableSizeZero) {
 }
 
 TEST(HashtableConstructor, VariousTableSizes) {
-	Hashtable h1(1);
+	Hashtable<unsigned> h1(1);
 	EXPECT_EQ(0, h1.size());
 	EXPECT_EQ(1, h1.capacity());
 	EXPECT_EQ(0, h1.load_factor());
 
-	Hashtable h2(42);
+	Hashtable<unsigned> h2(42);
 	EXPECT_EQ(0, h2.size());
 	EXPECT_EQ(42, h2.capacity());
 	EXPECT_EQ(0, h2.load_factor());
 
-	Hashtable h3(65535);
+	Hashtable<unsigned> h3(65535);
 	EXPECT_EQ(0, h3.size());
 	EXPECT_EQ(65535, h3.capacity());
 	EXPECT_EQ(0, h3.load_factor());
 }
 
 TEST(HashtableConstructor, ValidArguments) {
-	EXPECT_NO_THROW(Hashtable h1(0, 0.01));
-	EXPECT_NO_THROW(Hashtable h1(0, 0.5));
-	EXPECT_NO_THROW(Hashtable h1(0, 0.99));
-	EXPECT_NO_THROW(Hashtable h1(0, 0.75, 1.01));
-	EXPECT_NO_THROW(Hashtable h1(0, 0.01, 1.5));
-	EXPECT_NO_THROW(Hashtable h1(0, 0.01, 8));
+	EXPECT_NO_THROW(Hashtable<unsigned> h1(0, 0.01));
+	EXPECT_NO_THROW(Hashtable<unsigned> h1(0, 0.5));
+	EXPECT_NO_THROW(Hashtable<unsigned> h1(0, 0.99));
+	EXPECT_NO_THROW(Hashtable<unsigned> h1(0, 0.75, 1.01));
+	EXPECT_NO_THROW(Hashtable<unsigned> h1(0, 0.01, 1.5));
+	EXPECT_NO_THROW(Hashtable<unsigned> h1(0, 0.01, 8));
 }
 
 TEST(HashtableConstructor, InvalidArguments) {
-	EXPECT_THROW(Hashtable h1(0, 0), std::invalid_argument);
-	EXPECT_THROW(Hashtable h1(0, -1.2), std::invalid_argument);
-	EXPECT_THROW(Hashtable h1(0, 1.0), std::invalid_argument);
-	EXPECT_THROW(Hashtable h1(0, 1.01), std::invalid_argument);
-	EXPECT_THROW(Hashtable h1(0, 5), std::invalid_argument);
-	EXPECT_THROW(Hashtable h1(0, 0.75, -1), std::invalid_argument);
-	EXPECT_THROW(Hashtable h1(0, 0.75, 0), std::invalid_argument);
-	EXPECT_THROW(Hashtable h1(0, 0.75, 0.1), std::invalid_argument);
-	EXPECT_THROW(Hashtable h1(0, 0.75, 0.99), std::invalid_argument);
-	EXPECT_THROW(Hashtable h1(0, 0.75, 1), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, 0), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, -1.2), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, 1.0), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, 1.01), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, 5), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, 0.75, -1), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, 0.75, 0), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, 0.75, 0.1), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, 0.75, 0.99), std::invalid_argument);
+	EXPECT_THROW(Hashtable<unsigned> h1(0, 0.75, 1), std::invalid_argument);
 }
diff --git a/tests/test_hashtable.cpp b/tests/test_hashtable.cpp
index e7c21a2..a21c0a2 100644
--- a/tests/test_hashtable.cpp
+++ b/tests/test_hashtable.cpp
@@ -1,166 +1,196 @@
 #include <gtest/gtest.h>
 #include <iostream>
+#include <utility>
 
 #include "hashtable.h"
+#include "argumentTypes.h"
 
-using ::testing::TestWithParam;
-using ::testing::ValuesIn;
+using std::pair;
 
 
-struct HashtableArguments {
-	size_t m;
-	float a;
-	float s;
-
-	// make error output readable
-	friend std::ostream& operator<<(std::ostream& os, const HashtableArguments& args) {
-		  return os << "[m: " << args.m << ", a: " << args.a << ", s: " << args.s << "]";
-	}
-};
-
-// below tests will run on hashtables contstructed with these arguments
-HashtableArguments argv[] = {
-	{8, 0.75, 2},	// default table
-	{0, 0.75, 2},   // empty table
-	{65536, 0.75, 2},// big table
-	{8, 0.10, 2},	// small alpha, default s
-	{8, 0.95, 2},	// large alpha, default s
-	{8, 0.10, 1.1}, // small alpha, tiny s
-	{8, 0.95, 1.5}, // large alpha, small s
-	{8, 0.10, 4},	// small alpha, large s
-	{8, 0.95, 1.1}, // large alpha, tiny s
-	{8, 0.10, 1.5}, // small alpha, small s
-	{8, 0.95, 4}	// large alpha, large s
-};
+template<typename T>
+class HashtableTest : public testing::Test {
+	public:
+		using keytype = typename T::first_type;
+		using argtype = typename T::second_type;
 
+		Hashtable<keytype> *table;
+		argtype args;
 
-class PTest : public TestWithParam<HashtableArguments> {
-	public:
-		Hashtable *table;
-		size_t m;
-		float a;
-		float s;
-
-		void SetUp() override {
-			m = GetParam().m; a = GetParam().a; s = GetParam().s;
-			table = new Hashtable(m, a, s);
+		HashtableTest() {
+			table = new Hashtable<keytype>(args.m, args.a, args.s);
 		}
 
-		void TearDown() override { delete table; table = nullptr; }
+		~HashtableTest() override { delete table; }
 };
 
-TEST_P(PTest, TestSetup) {
-	EXPECT_EQ(m, table->capacity());
-	EXPECT_EQ(0, table->size());
-	EXPECT_EQ(0, table->load_factor());
+using AllTheTypes = ::testing::Types<
+	pair<unsigned int,DefaultTable>,
+	pair<unsigned int,EmptyTable>,
+	pair<unsigned int,BigTable>,
+	pair<unsigned int,SmallAlphaDefaultS>,
+	pair<unsigned int,SmallAlphaTinyS>,
+	pair<unsigned int,SmallAlphaSmallS>,
+	pair<unsigned int,SmallAlphaLargeS>,
+	pair<unsigned int,LargeAlphaDefaultS>,
+	pair<unsigned int,LargeAlphaTinyS>,
+	pair<unsigned int,LargeAlphaSmallS>,
+	pair<unsigned int,LargeAlphaLargeS>,
+	pair<unsigned short,DefaultTable>,
+	pair<unsigned short,EmptyTable>,
+	pair<unsigned short,BigTable>,
+	pair<unsigned short,SmallAlphaDefaultS>,
+	pair<unsigned short,SmallAlphaTinyS>,
+	pair<unsigned short,SmallAlphaSmallS>,
+	pair<unsigned short,SmallAlphaLargeS>,
+	pair<unsigned short,LargeAlphaDefaultS>,
+	pair<unsigned short,LargeAlphaTinyS>,
+	pair<unsigned short,LargeAlphaSmallS>,
+	pair<unsigned short,LargeAlphaLargeS>,
+	pair<unsigned long,DefaultTable>,
+	pair<unsigned long,EmptyTable>,
+	pair<unsigned long,BigTable>,
+	pair<unsigned long,SmallAlphaDefaultS>,
+	pair<unsigned long,SmallAlphaTinyS>,
+	pair<unsigned long,SmallAlphaSmallS>,
+	pair<unsigned long,SmallAlphaLargeS>,
+	pair<unsigned long,LargeAlphaDefaultS>,
+	pair<unsigned long,LargeAlphaTinyS>,
+	pair<unsigned long,LargeAlphaSmallS>,
+	pair<unsigned long,LargeAlphaLargeS>
+>;
+
+TYPED_TEST_SUITE(HashtableTest, AllTheTypes);
+
+
+TYPED_TEST(HashtableTest, TestSetup) {
+	auto &table = *this->table;
+
+	EXPECT_EQ(this->args.m, table.capacity());
+	EXPECT_EQ(0, table.size());
+	EXPECT_EQ(0, table.load_factor());
 }
 
-TEST_P(PTest, InsertIntoEmpty) {
-	EXPECT_EQ(true, table->insert(0));
-	EXPECT_EQ(true, table->insert(23));
-	EXPECT_EQ(true, table->insert(512));
+TYPED_TEST(HashtableTest, InsertIntoEmpty) {
+	auto &table = *this->table;
+
+	EXPECT_EQ(true, table.insert(0));
+	EXPECT_EQ(true, table.insert(23));
+	EXPECT_EQ(true, table.insert(512));
 }
 
-TEST_P(PTest, InsertExisting) {
-	EXPECT_EQ(true, table->insert(2));
-	EXPECT_EQ(true, table->insert(9));
-	EXPECT_EQ(true, table->insert(32));
-	EXPECT_EQ(true, table->insert(575));
+TYPED_TEST(HashtableTest, InsertExisting) {
+	auto &table = *this->table;
+
+	EXPECT_EQ(true, table.insert(2));
+	EXPECT_EQ(true, table.insert(9));
+	EXPECT_EQ(true, table.insert(32));
+	EXPECT_EQ(true, table.insert(575));
 
-	EXPECT_EQ(false, table->insert(2));
-	EXPECT_EQ(false, table->insert(9));
-	EXPECT_EQ(false, table->insert(32));
-	EXPECT_EQ(false, table->insert(575));
+	EXPECT_EQ(false, table.insert(2));
+	EXPECT_EQ(false, table.insert(9));
+	EXPECT_EQ(false, table.insert(32));
+	EXPECT_EQ(false, table.insert(575));
 }
 
-TEST_P(PTest, RemoveFromEmpty) {
-	EXPECT_EQ(false, table->remove(0));
-	EXPECT_EQ(false, table->remove(7));
-	EXPECT_EQ(false, table->remove(77));
-	EXPECT_EQ(false, table->remove(2087));
+TYPED_TEST(HashtableTest, RemoveFromEmpty) {
+	auto &table = *this->table;
+
+	EXPECT_EQ(false, table.remove(0));
+	EXPECT_EQ(false, table.remove(7));
+	EXPECT_EQ(false, table.remove(77));
+	EXPECT_EQ(false, table.remove(2087));
 }
 
-TEST_P(PTest, RemoveExisting) {
-	EXPECT_EQ(true, table->insert(4));
-	EXPECT_EQ(true, table->insert(64));
-	EXPECT_EQ(true, table->insert(1023));
-	EXPECT_EQ(true, table->insert(408));
+TYPED_TEST(HashtableTest, RemoveExisting) {
+	auto &table = *this->table;
+
+	EXPECT_EQ(true, table.insert(4));
+	EXPECT_EQ(true, table.insert(64));
+	EXPECT_EQ(true, table.insert(1023));
+	EXPECT_EQ(true, table.insert(408));
 
-	EXPECT_EQ(true, table->remove(4));
-	EXPECT_EQ(true, table->remove(64));
-	EXPECT_EQ(true, table->remove(1023));
-	EXPECT_EQ(true, table->remove(408));
+	EXPECT_EQ(true, table.remove(4));
+	EXPECT_EQ(true, table.remove(64));
+	EXPECT_EQ(true, table.remove(1023));
+	EXPECT_EQ(true, table.remove(408));
 }
 
-TEST_P(PTest, RemoveSome) {
+TYPED_TEST(HashtableTest, RemoveSome) {
+	auto &table = *this->table;
+
 	for (int i=0; i<=100; i+=2) {
-		EXPECT_EQ(true, table->insert(i));
-		EXPECT_EQ(true, table->contains(i));
-		EXPECT_EQ(false, table->contains(i+1));
+		EXPECT_EQ(true, table.insert(i));
+		EXPECT_EQ(true, table.contains(i));
+		EXPECT_EQ(false, table.contains(i+1));
 	}
 
 	for (int i=0; i<=100; i+=2) {
-		EXPECT_EQ(true, table->remove(i));
-		EXPECT_EQ(false, table->remove(i+1));
-		EXPECT_EQ(false, table->contains(i));
+		EXPECT_EQ(true, table.remove(i));
+		EXPECT_EQ(false, table.remove(i+1));
+		EXPECT_EQ(false, table.contains(i));
 	}
 }
 
-TEST_P(PTest, Contains) {
-	EXPECT_EQ(false, table->contains(3));
-	EXPECT_EQ(false, table->contains(53));
-	EXPECT_EQ(false, table->contains(4265));
-	EXPECT_EQ(false, table->contains(10e6));
+TYPED_TEST(HashtableTest, Contains) {
+	auto &table = *this->table;
+
+	EXPECT_EQ(false, table.contains(3));
+	EXPECT_EQ(false, table.contains(53));
+	EXPECT_EQ(false, table.contains(4265));
+	EXPECT_EQ(false, table.contains(3601));
 
 	for (int i=0; i<200; i++)
-		EXPECT_EQ(true, table->insert(i));
+		EXPECT_EQ(true, table.insert(i));
 
 	for (int i=0; i<200; i++)
-		EXPECT_EQ(true, table->contains(i));
+		EXPECT_EQ(true, table.contains(i));
 
 	for (int i=0; i<200; i++)
-		EXPECT_EQ(true, table->remove(i));
+		EXPECT_EQ(true, table.remove(i));
 
 	for (int i=0; i<200; i++)
-		EXPECT_EQ(false, table->contains(i));
+		EXPECT_EQ(false, table.contains(i));
 }
 
-TEST_P(PTest, Size) {
-	EXPECT_EQ(0, table->size());
-
-	table->insert(0);
-	EXPECT_EQ(1, table->size());
-	table->insert(23);
-	EXPECT_EQ(2, table->size());
-	table->remove(55);
-	EXPECT_EQ(2, table->size());
-	table->remove(80);
-	EXPECT_EQ(2, table->size());
-	table->remove(23);
-	EXPECT_EQ(1, table->size());
-	table->remove(0);
-	EXPECT_EQ(0, table->size());
+TYPED_TEST(HashtableTest, Size) {
+	auto &table = *this->table;
+
+	EXPECT_EQ(0, table.size());
+
+	table.insert(0);
+	EXPECT_EQ(1, table.size());
+	table.insert(23);
+	EXPECT_EQ(2, table.size());
+	table.remove(55);
+	EXPECT_EQ(2, table.size());
+	table.remove(80);
+	EXPECT_EQ(2, table.size());
+	table.remove(23);
+	EXPECT_EQ(1, table.size());
+	table.remove(0);
+	EXPECT_EQ(0, table.size());
 
 	for (int i=0; i<200; i++) {
-		EXPECT_EQ(i, table->size());
-		table->insert(i);
-		EXPECT_EQ(i+1, table->size());
+		EXPECT_EQ(i, table.size());
+		table.insert(i);
+		EXPECT_EQ(i+1, table.size());
 	}
 
 	for (int i=0; i<200; i++) {
-		EXPECT_EQ(200-i, table->size());
-		table->remove(i);
-		EXPECT_EQ(199-i, table->size());
+		EXPECT_EQ(200-i, table.size());
+		table.remove(i);
+		EXPECT_EQ(199-i, table.size());
 	}
 }
 
-TEST_P(PTest, Capacity) {
-	EXPECT_EQ(m, table->capacity());
+TYPED_TEST(HashtableTest, Capacity) {
+	auto &table = *this->table;
+
+	EXPECT_EQ(this->args.m, table.capacity());
 
 	for (int i=0; i<200; i++) {
-		table->insert(i);
-		EXPECT_GT(table->capacity(), table->size());
+		table.insert(i);
+		EXPECT_GT(table.capacity(), table.size());
 	}
 }
-
-INSTANTIATE_TEST_SUITE_P(ParameterizedTests, PTest, ValuesIn(argv));
-- 
GitLab