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