Files
jsix_import/src/tests/linked_list.cpp
F in Chat for Tabs 8f529046a9 [project] Lose the battle between tabs & spaces
I'm a tabs guy. I like tabs, it's an elegant way to represent
indentation instead of brute-forcing it. But I have to admit that the
world seems to be going towards spaces, and tooling tends not to play
nice with tabs. So here we go, changing the whole repo to spaces since
I'm getting tired of all the inconsistent formatting.
2021-08-01 17:46:16 -07:00

155 lines
3.7 KiB
C++

#include <chrono>
#include <iostream>
#include <limits>
#include <random>
#include <vector>
#include "kutil/linked_list.h"
#include "catch.hpp"
#include "container_helpers.h"
using namespace kutil;
const int test_list_size = 100;
template <typename T>
class ListVectorCompare :
public Catch::MatcherBase<std::vector<list_node<T>>>
{
public:
using item = list_node<T>;
using vector = std::vector<item>;
ListVectorCompare(const linked_list<T> &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<T> &m_list;
bool m_reverse;
};
template <typename T>
class IsSorted :
public Catch::MatcherBase<linked_list<T>>
{
public:
using item = list_node<T>;
using list = linked_list<T>;
IsSorted() {}
virtual bool match (list const& l) const override
{
int big = std::numeric_limits<int>::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 <typename T>
class ListContainsMatcher :
public Catch::MatcherBase<linked_list<T>>
{
public:
using item = list_node<T>;
using list = linked_list<T>;
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 <typename T>
ListVectorCompare<T> IsSameAsList(const linked_list<T> &list, bool reversed = false)
{
return ListVectorCompare<T>(list, reversed);
}
template <typename T>
ListContainsMatcher<T> ListContains(const list_node<T> &item)
{
return ListContainsMatcher<T>(item);
}
TEST_CASE( "Linked list tests", "[containers] [list]" )
{
linked_list<unsortableT> ulist;
int value = 0;
std::vector<list_node<unsortableT>> 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<unsortableT> 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<int> gen(1, 1000);
linked_list<sortableT> slist;
CHECK( slist.length() == 0 );
std::vector<list_node<sortableT>> 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<sortableT>() );
}