384 lines
8.7 KiB
C++
384 lines
8.7 KiB
C++
//
|
|
// Created by erki on 13.03.21.
|
|
//
|
|
|
|
#include <catch2/catch.hpp>
|
|
|
|
#include "utility_ringbuffer.hpp"
|
|
|
|
template<size_t N>
|
|
using Ringbuffer = Utility::Ringbuffer<int, N>;
|
|
|
|
TEST_CASE("Ringbuffer iterator", "[utility],[ringbuffer]")
|
|
{
|
|
using iterator = Ringbuffer<10>::iterator;
|
|
const auto begin = iterator::pointer(10);
|
|
const auto end = iterator::pointer(21);
|
|
iterator it = iterator(iterator::pointer(15), begin, end);
|
|
|
|
SECTION("Incrementing postfix increases its pointer and returns initial.")
|
|
{
|
|
iterator it_second = it++;
|
|
REQUIRE(it - it_second == iterator::difference_type(1));
|
|
}
|
|
|
|
SECTION("Incrementing prefix increases its pointer and returns new.")
|
|
{
|
|
const iterator original = it;
|
|
iterator it_second = ++it;
|
|
REQUIRE(it_second == it);
|
|
REQUIRE(it - original == iterator::difference_type(1));
|
|
}
|
|
|
|
SECTION("Subtracting 1 decreases its pointer.")
|
|
{
|
|
iterator it_second = it - 1;
|
|
REQUIRE(it - it_second == iterator::difference_type(1));
|
|
}
|
|
|
|
SECTION("Adding 1 increases its pointer.")
|
|
{
|
|
iterator it_second = it + 1;
|
|
REQUIRE(it_second - it == iterator::difference_type(1));
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer iterator at the end", "[utility],[ringbuffer]")
|
|
{
|
|
using iterator = Ringbuffer<10>::iterator;
|
|
const auto begin = iterator::pointer(10);
|
|
const auto end = iterator::pointer(21);
|
|
iterator it = iterator(end - 1, begin, end);
|
|
|
|
const auto it_begin = iterator(begin, begin, end);
|
|
|
|
SECTION("Incrementing postfix sets the pointer to begin().")
|
|
{
|
|
it++;
|
|
REQUIRE(it == it_begin);
|
|
}
|
|
|
|
SECTION("Incrementing prefix sets the pointer to begin().")
|
|
{
|
|
++it;
|
|
REQUIRE(it == it_begin);
|
|
}
|
|
|
|
SECTION("Adding 1 sets the pointer to begin().")
|
|
{
|
|
const iterator it_second = it + 1;
|
|
REQUIRE(it_second == it_begin);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer iterator at the beginning", "[utility],[ringbuffer]")
|
|
{
|
|
using iterator = Ringbuffer<10>::iterator;
|
|
const auto begin = iterator::pointer(10);
|
|
const auto end = iterator::pointer(21);
|
|
iterator it = iterator(begin, begin, end);
|
|
|
|
const auto it_last = iterator(end - 1, begin, end);
|
|
|
|
SECTION("Subtracting 1 sets the pointer to last element.")
|
|
{
|
|
const iterator it_second = it - 1;
|
|
REQUIRE(it_last == it_second);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer constructed buffer is empty.", "[utility],[ringbuffer]")
|
|
{
|
|
Ringbuffer<10> buffer;
|
|
|
|
REQUIRE(buffer.begin() == buffer.end());
|
|
REQUIRE(buffer.size() == 0);
|
|
REQUIRE(buffer.empty());
|
|
REQUIRE(&buffer.front() == &buffer.back());
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer reports size properly.", "[utility],[ringbuffer]")
|
|
{
|
|
Ringbuffer<3> buffer;
|
|
|
|
buffer.push_back(1);
|
|
buffer.push_back(2);
|
|
|
|
SECTION("max_size() reports maximum size properly.")
|
|
{
|
|
REQUIRE(buffer.max_size() == 3);
|
|
}
|
|
|
|
SECTION("After pushing 2 elements, size is reported properly.")
|
|
{
|
|
REQUIRE(buffer.size() == 2);
|
|
}
|
|
|
|
SECTION("A full buffer reports size as max_size.")
|
|
{
|
|
buffer.push_back(3);
|
|
REQUIRE(buffer.size() == 3);
|
|
REQUIRE(buffer.size() == buffer.max_size());
|
|
}
|
|
|
|
SECTION("Removing an element updates size properly.")
|
|
{
|
|
buffer.pop_front();
|
|
|
|
REQUIRE(buffer.size() == 1);
|
|
}
|
|
|
|
SECTION("Removing and adding an element updates size properly.")
|
|
{
|
|
buffer.pop_front();
|
|
buffer.push_back(4);
|
|
|
|
REQUIRE(buffer.size() == 2);
|
|
|
|
buffer.push_back(5);
|
|
|
|
REQUIRE(buffer.size() == 3);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer adding single element.", "[utility],[ringbuffer]")
|
|
{
|
|
Ringbuffer<10> buffer;
|
|
const auto old_end = buffer.end();
|
|
const auto old_begin = buffer.begin();
|
|
|
|
buffer.push_back(1);
|
|
|
|
SECTION("Increases size and empty appropriately.")
|
|
{
|
|
REQUIRE(buffer.size() == 1);
|
|
REQUIRE(!buffer.empty());
|
|
}
|
|
|
|
SECTION("Updates end() appropriately.") { REQUIRE(old_end != buffer.end()); }
|
|
|
|
SECTION("begin() remains the same.") { REQUIRE(old_begin == buffer.begin()); }
|
|
|
|
SECTION("Makes begin() refer to the inserted member.")
|
|
{
|
|
REQUIRE(*old_begin == 1);
|
|
REQUIRE(*buffer.begin() == 1);
|
|
}
|
|
|
|
SECTION("Distance between begin and end is 1.")
|
|
{
|
|
REQUIRE(buffer.end() - buffer.begin() == 1);
|
|
}
|
|
|
|
SECTION("Makes back() refer to the first element.")
|
|
{
|
|
REQUIRE(buffer.back() == 1);
|
|
}
|
|
|
|
SECTION("Makes front() refer to the first element.")
|
|
{
|
|
REQUIRE(buffer.front() == 1);
|
|
}
|
|
|
|
SECTION("Makes front() and back() refer to the same memory address.")
|
|
{
|
|
REQUIRE(&buffer.front() == &buffer.back());
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer adding multiple elements.", "[utility],[ringbuffer]")
|
|
{
|
|
Ringbuffer<10> buffer;
|
|
const auto old_begin = buffer.begin();
|
|
|
|
buffer.push_back(1);
|
|
buffer.push_back(2);
|
|
buffer.push_back(3);
|
|
|
|
SECTION("Increases size and empty appropriately.")
|
|
{
|
|
REQUIRE(buffer.size() == 3);
|
|
REQUIRE(!buffer.empty());
|
|
}
|
|
|
|
SECTION("Makes front() refer to the first element.")
|
|
{
|
|
REQUIRE(buffer.front() == 1);
|
|
}
|
|
|
|
SECTION("Makes back() refer to the last element.")
|
|
{
|
|
REQUIRE(buffer.back() == 3);
|
|
}
|
|
|
|
SECTION("Updates begin() and end() appropriately.")
|
|
{
|
|
REQUIRE(old_begin == buffer.begin());
|
|
REQUIRE(buffer.end() - buffer.begin() == 3);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer removing elements from the ringbuffer.",
|
|
"[utility],[ringbuffer]")
|
|
{
|
|
Ringbuffer<10> buffer;
|
|
const auto old_begin = buffer.begin();
|
|
|
|
buffer.push_back(1);
|
|
buffer.push_back(2);
|
|
buffer.push_back(3);
|
|
|
|
buffer.pop_front();
|
|
|
|
SECTION("Updates the front() appropriately.")
|
|
{
|
|
REQUIRE(buffer.front() == 2);
|
|
}
|
|
|
|
SECTION("Updates begin() appropriately.")
|
|
{
|
|
REQUIRE(buffer.begin() - old_begin == 1);
|
|
}
|
|
|
|
SECTION("Updates size() appropriately.") { REQUIRE(buffer.size() == 2); }
|
|
|
|
SECTION("Erasing remaining elements")
|
|
{
|
|
buffer.pop_front();
|
|
buffer.pop_front();
|
|
|
|
SECTION("Updates empty() appropriately.") { REQUIRE(buffer.empty()); }
|
|
|
|
SECTION("Updates begin() and end() appropriately.")
|
|
{
|
|
REQUIRE(buffer.begin() == buffer.end());
|
|
}
|
|
|
|
SECTION("Updates size() appropriately.") { REQUIRE(buffer.size() == 0); }
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer clearing a ringbuffer works.", "[utility],[ringbuffer]")
|
|
{
|
|
Ringbuffer<10> buffer;
|
|
|
|
buffer.push_back(1);
|
|
buffer.push_back(2);
|
|
buffer.push_back(3);
|
|
|
|
buffer.clear();
|
|
|
|
SECTION("Updates size() and empty() appropriately.")
|
|
{
|
|
REQUIRE(buffer.empty());
|
|
REQUIRE(buffer.size() == 0);
|
|
}
|
|
|
|
SECTION("Sets begin() and end() pointers appropriately.")
|
|
{
|
|
REQUIRE(buffer.begin() == buffer.end());
|
|
REQUIRE(&buffer.front() == &buffer.back());
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer manually incrementing tail works.",
|
|
"[utility],[ringbuffer]")
|
|
{
|
|
Ringbuffer<10> buffer;
|
|
|
|
buffer.push_back(1);
|
|
|
|
auto old_end = buffer.end();
|
|
*old_end = 2;
|
|
|
|
buffer.increment_tail();
|
|
|
|
SECTION("New end is set forward by 1.")
|
|
{
|
|
const auto new_end = buffer.end();
|
|
REQUIRE(old_end != new_end);
|
|
REQUIRE(new_end - old_end == 1);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer manually incrementing tail from empty state works.",
|
|
"[utility],[ringbuffer]")
|
|
{
|
|
Ringbuffer<10> buffer;
|
|
|
|
const auto old_end = buffer.end();
|
|
const auto old_begin = buffer.begin();
|
|
auto* old_tail_item_ptr = &(*old_end);
|
|
|
|
buffer.increment_tail();
|
|
|
|
SECTION("Head remains in place.")
|
|
{
|
|
const auto new_end = buffer.end();
|
|
const auto new_begin = buffer.begin();
|
|
REQUIRE(old_begin == new_begin);
|
|
REQUIRE(new_end != new_begin);
|
|
REQUIRE(new_end - new_begin == 1);
|
|
}
|
|
|
|
SECTION("Tail has been incremented.")
|
|
{
|
|
const auto new_end = buffer.end();
|
|
REQUIRE(new_end != old_end);
|
|
REQUIRE(new_end - old_end == 1);
|
|
REQUIRE(buffer.size() == 1);
|
|
}
|
|
|
|
SECTION("Item pointer for end is increased appropriately.")
|
|
{
|
|
auto* new_tail_item_ptr = &(*buffer.end());
|
|
REQUIRE(new_tail_item_ptr != old_tail_item_ptr);
|
|
REQUIRE(new_tail_item_ptr - old_tail_item_ptr == 1);
|
|
}
|
|
|
|
SECTION("Second incrementation works as expected.")
|
|
{
|
|
buffer.increment_tail();
|
|
const auto new_end = buffer.end();
|
|
const auto new_begin = buffer.begin();
|
|
auto* new_tail_item_ptr = &(*buffer.end());
|
|
|
|
REQUIRE(new_begin == old_begin);
|
|
REQUIRE(new_end - old_end == 2);
|
|
REQUIRE(new_tail_item_ptr - old_tail_item_ptr == 2);
|
|
REQUIRE(buffer.size() == 2);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Ringbuffer manually incrementing tail when full deletes data.",
|
|
"[utility],[ringbuffer]")
|
|
{
|
|
Ringbuffer<2> buffer;
|
|
|
|
buffer.push_back(1);
|
|
buffer.push_back(2);
|
|
|
|
const auto old_start = buffer.begin();
|
|
const auto old_end = buffer.end();
|
|
|
|
REQUIRE(buffer.size() == buffer.max_size());
|
|
|
|
buffer.increment_tail();
|
|
|
|
REQUIRE(buffer.size() == buffer.max_size());
|
|
|
|
SECTION("End is incremented properly.")
|
|
{
|
|
const auto new_end = buffer.end();
|
|
REQUIRE(old_end != new_end);
|
|
REQUIRE(new_end - old_end == 1);
|
|
}
|
|
|
|
SECTION("Begin is incremented properly.")
|
|
{
|
|
const auto new_start = buffer.begin();
|
|
REQUIRE(old_start != new_start);
|
|
REQUIRE(new_start - old_start == 1);
|
|
}
|
|
}
|