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.
This commit is contained in:
parent
ce7cc4492c
commit
1126ee30d8
35
tests/unit/model.hh
Normal file
35
tests/unit/model.hh
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
template <typename K, typename V> struct Range {
|
||||||
|
K begin;
|
||||||
|
K end;
|
||||||
|
V val;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Same behaviour as interval_map, but implementation is trivally correct
|
||||||
|
template <typename K, typename V> 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<Range<K, V>> ranges_{};
|
||||||
|
};
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "model.hh"
|
||||||
|
|
||||||
template <typename T> class KeyInterface {
|
template <typename T> class KeyInterface {
|
||||||
public:
|
public:
|
||||||
explicit KeyInterface(T val) : underlying_(val) {}
|
explicit KeyInterface(T val) : underlying_(val) {}
|
||||||
|
@ -63,17 +65,40 @@ protected:
|
||||||
using key_type = char;
|
using key_type = char;
|
||||||
using value_type = int;
|
using value_type = int;
|
||||||
using map_type = amby::interval_map<key_type, value_type>;
|
using map_type = amby::interval_map<key_type, value_type>;
|
||||||
|
using model_type = Model<key_type, value_type>;
|
||||||
|
|
||||||
map_type map{0};
|
map_type map{0};
|
||||||
|
model_type model{0};
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
map = map_type{0};
|
map = map_type{0};
|
||||||
|
model = model_type{0};
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown() override {
|
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();
|
check_canonicity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compare against the fake 'Model' implementation
|
||||||
|
void check_ranges() const {
|
||||||
|
auto i = std::numeric_limits<key_type>::min();
|
||||||
|
for (; i < std::numeric_limits<key_type>::max(); ++i) {
|
||||||
|
ASSERT_EQ(map[i], model[i]) << "(i: " << +i << ")";
|
||||||
|
}
|
||||||
|
ASSERT_EQ(map[i], model[i]) << "(i: " << +i << ")";
|
||||||
|
};
|
||||||
|
|
||||||
void check_canonicity() const {
|
void check_canonicity() const {
|
||||||
// Consecutive map entries must not contain the same value
|
// Consecutive map entries must not contain the same value
|
||||||
for (auto it = map.underlying_.begin(); it != map.underlying_.end();
|
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));
|
map.assign(Key(0), Key(1), Value(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IntervalMapTest, no_insertion) {
|
TEST_F(IntervalMapTest, no_insertion) {}
|
||||||
for (int i = std::numeric_limits<char>::min();
|
|
||||||
i <= std::numeric_limits<char>::max(); ++i) {
|
|
||||||
ASSERT_EQ(map[i], 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(IntervalMapTest, insert_begin_equal_end) {
|
TEST_F(IntervalMapTest, insert_begin_equal_end) {
|
||||||
map.assign(0, 0, 1);
|
assign(0, 0, 1);
|
||||||
for (int i = std::numeric_limits<char>::min();
|
|
||||||
i <= std::numeric_limits<char>::max(); ++i) {
|
|
||||||
ASSERT_EQ(map[i], 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IntervalMapTest, insert_begin_bigger_than_end) {
|
TEST_F(IntervalMapTest, insert_begin_bigger_than_end) {
|
||||||
map.assign(1, 0, 1);
|
assign(1, 0, 1);
|
||||||
for (int i = std::numeric_limits<char>::min();
|
|
||||||
i <= std::numeric_limits<char>::max(); ++i) {
|
|
||||||
ASSERT_EQ(map[i], 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue