#include #include #include #include #include #include "kutil/linked_list.h" #include "catch.hpp" #include "container_helpers.h" using namespace kutil; const int test_list_size = 100; template class ListVectorCompare : public Catch::MatcherBase>> { public: using item = list_node; using vector = std::vector; ListVectorCompare(const linked_list &list, bool reversed) : m_list(list), m_reverse(reversed) {} virtual bool match (vector const& vec) const override { size_t index = m_reverse ? vec.size() - 1 : 0; for (const T *i : m_list) { if (i != &vec[index]) return false; index += m_reverse ? -1 : 1; } return true; } virtual std::string describe() const override { return "is the same as the given linked list"; } private: const linked_list &m_list; bool m_reverse; }; template class IsSorted : public Catch::MatcherBase> { public: using item = list_node; using list = linked_list; IsSorted() {} virtual bool match (list const& l) const override { int big = std::numeric_limits::min(); for (const T *i : l) { if (i->value < big) return false; big = i->value; } return true; } virtual std::string describe() const override { return "is sorted"; } }; template class ListContainsMatcher : public Catch::MatcherBase> { public: using item = list_node; using list = linked_list; ListContainsMatcher(const item &needle) : m_needle(needle) {} virtual bool match (list const& l) const override { for (const T *i : l) if (i == &m_needle) return true; return false; } virtual std::string describe() const override { return "contains the given item"; } const item &m_needle; }; template ListVectorCompare IsSameAsList(const linked_list &list, bool reversed = false) { return ListVectorCompare(list, reversed); } template ListContainsMatcher ListContains(const list_node &item) { return ListContainsMatcher(item); } TEST_CASE( "Linked list tests", "[containers] [list]" ) { linked_list ulist; int value = 0; std::vector> unsortables(test_list_size); for (auto &i : unsortables) { i.value = value++; ulist.push_back(&i); } CHECK( ulist.length() == test_list_size ); CHECK_THAT( unsortables, IsSameAsList(ulist) ); linked_list ulist_reversed; for (auto &i : unsortables) { ulist.remove(&i); ulist_reversed.push_front(&i); } CHECK( ulist_reversed.length() == test_list_size ); CHECK_THAT( unsortables, IsSameAsList(ulist_reversed, true) ); auto &removed = unsortables[test_list_size / 2]; ulist_reversed.remove(&removed); CHECK( ulist_reversed.length() == test_list_size - 1 ); CHECK_THAT( ulist_reversed, !ListContains(removed) ); } TEST_CASE( "Sorted list tests", "[containers] [list]" ) { using clock = std::chrono::system_clock; unsigned seed = clock::now().time_since_epoch().count(); std::default_random_engine rng(seed); std::uniform_int_distribution gen(1, 1000); linked_list slist; CHECK( slist.length() == 0 ); std::vector> sortables(test_list_size); for (auto &i : sortables) { i.value = gen(rng); slist.sorted_insert(&i); } CHECK( slist.length() == test_list_size ); CHECK_THAT( slist, IsSorted() ); }