From 65e0d4991fc7679fcf61bfd0f253e9d8589a3ec5 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Fri, 23 Aug 2024 23:38:05 +0100 Subject: [PATCH] Test against fake 'Model' implementation This removes most of the redundant `for` loops that would appear in hand-written unit tests, and could potentially open the door to fuzz-testing/property-test the implementation for a more in-depth test-suite. --- tests/unit/model.hh | 35 ++++++++++++++++++++++++++++++++ tests/unit/unit_test.cc | 44 ++++++++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 tests/unit/model.hh diff --git a/tests/unit/model.hh b/tests/unit/model.hh new file mode 100644 index 0000000..9acb19f --- /dev/null +++ b/tests/unit/model.hh @@ -0,0 +1,35 @@ +#pragma once + +#include + +template struct Range { + K begin; + K end; + V val; +}; + +// Same behaviour as interval_map, but implementation is trivally correct +template class Model { +public: + Model(V const& init) : init_(init) {} + + void assign(K const& begin, K const& end, V const& val) { + if (!(begin < end)) + return; + ranges_.emplace_back(begin, end, val); + } + + V const& operator[](K const& key) const { + for (auto it = ranges_.rbegin(); it != ranges_.rend(); ++it) { + if (key < it->begin) + continue; + if (it->end <= key) + continue; + return it->val; + } + return init_; + } + + V init_; + std::vector> ranges_{}; +}; diff --git a/tests/unit/unit_test.cc b/tests/unit/unit_test.cc index d51db5a..7b9e4ce 100644 --- a/tests/unit/unit_test.cc +++ b/tests/unit/unit_test.cc @@ -4,6 +4,8 @@ #include +#include "model.hh" + template class KeyInterface { public: explicit KeyInterface(T val) : underlying_(val) {} @@ -63,17 +65,40 @@ protected: using key_type = char; using value_type = int; using map_type = amby::interval_map; + using model_type = Model; map_type map{0}; + model_type model{0}; void SetUp() override { map = map_type{0}; + model = model_type{0}; } void TearDown() override { + check(); + } + + void assign(key_type const& begin, key_type const& end, + value_type const& val) { + map.assign(begin, end, val); + model.assign(begin, end, val); + } + + void check() const { + check_ranges(); check_canonicity(); } + // Compare against the fake 'Model' implementation + void check_ranges() const { + auto i = std::numeric_limits::min(); + for (; i < std::numeric_limits::max(); ++i) { + ASSERT_EQ(map[i], model[i]) << "(i: " << +i << ")"; + } + ASSERT_EQ(map[i], model[i]) << "(i: " << +i << ")"; + }; + void check_canonicity() const { // Consecutive map entries must not contain the same value for (auto it = map.underlying_.begin(); it != map.underlying_.end(); @@ -101,25 +126,12 @@ TEST_F(IntervalMapTest, minimal_interface) { map.assign(Key(0), Key(1), Value(1)); } -TEST_F(IntervalMapTest, no_insertion) { - for (int i = std::numeric_limits::min(); - i <= std::numeric_limits::max(); ++i) { - ASSERT_EQ(map[i], 0); - } -} +TEST_F(IntervalMapTest, no_insertion) {} TEST_F(IntervalMapTest, insert_begin_equal_end) { - map.assign(0, 0, 1); - for (int i = std::numeric_limits::min(); - i <= std::numeric_limits::max(); ++i) { - ASSERT_EQ(map[i], 0); - } + assign(0, 0, 1); } TEST_F(IntervalMapTest, insert_begin_bigger_than_end) { - map.assign(1, 0, 1); - for (int i = std::numeric_limits::min(); - i <= std::numeric_limits::max(); ++i) { - ASSERT_EQ(map[i], 0); - } + assign(1, 0, 1); }