Prusa-Firmware-MMU/tests/unit/hal/circular_buffer/test_circular_buffer.cpp

136 lines
3.1 KiB
C++

#include "catch2/catch.hpp"
#include "circular_buffer.h"
using Catch::Matchers::Equals;
TEST_CASE("circular_buffer::basic", "[circular_buffer]") {
using CB = CircularBuffer<uint8_t, uint8_t, 32>;
CB cb;
// at the beginning the buffer is empty
REQUIRE(cb.empty());
// since its capacity was defined as 32, at least one element must be successfully inserted
CHECK(cb.push(1));
CHECK(cb.count() == 1);
// is the element there?
REQUIRE(!cb.empty());
CHECK(cb.front() == 1);
// remove the element
uint8_t b = 0;
CHECK(cb.pop(b));
CHECK(b == 1);
CHECK(cb.empty());
CHECK(cb.count() == 0);
}
TEST_CASE("circular_buffer::fill", "[circular_buffer]") {
static constexpr auto size = 4;
using CB = CircularBuffer<uint8_t, uint8_t, size>;
// start with an empty buffer
CB cb;
REQUIRE(cb.empty());
REQUIRE(cb.count() == 0);
// ensure we can fill the buffer
for (auto i = 0; i != size; ++i) {
CHECK(!cb.full());
cb.push(i);
CHECK(cb.count() == i + 1);
}
REQUIRE(cb.full());
REQUIRE(cb.count() == size);
// ensure another push fails
REQUIRE(!cb.push(0));
REQUIRE(cb.count() == size);
// retrieve all elements
for (auto i = 0; i != size; ++i) {
uint8_t v;
CHECK(cb.pop(v));
CHECK(v == i);
REQUIRE(cb.count() == size - i - 1);
}
REQUIRE(cb.empty());
REQUIRE(cb.count() == 0);
}
TEST_CASE("circular_buffer::wrap_around", "[circular_buffer]") {
static constexpr auto size = 4;
using CB = CircularBuffer<uint8_t, uint8_t, size>;
// start with an empty buffer
CB cb;
REQUIRE(cb.empty());
// test inverse logic
REQUIRE(!cb.full());
// add two elements to shift the internal offset
uint8_t v;
cb.push(size + 1);
cb.pop(v);
cb.push(size + 1);
cb.pop(v);
REQUIRE(cb.empty());
// loop to test the internal cursor wrap-around logic
// the number of loops needs to be equal or greater than the index type
for (auto loop = 0; loop != 256; ++loop) {
INFO("loop " << loop)
// ensure we can fill the buffer
for (auto i = 0; i != size; ++i) {
CHECK(!cb.full());
cb.push(i);
CHECK(!cb.empty());
CHECK(cb.count() == i + 1);
}
REQUIRE(cb.full());
REQUIRE(!cb.empty());
REQUIRE(cb.count() == size);
// retrieve all elements
for (auto i = 0; i != size; ++i) {
uint8_t v;
CHECK(cb.pop(v));
CHECK(v == i);
CHECK(cb.count() == size - i - 1);
}
REQUIRE(cb.empty());
}
}
TEST_CASE("circular_buffer::minimal_size", "[circular_buffer]") {
using CB = CircularBuffer<uint8_t, uint8_t, 1>;
// test a buffer with a minimal size (1 element)
CB cb;
// initial state
REQUIRE(cb.empty());
REQUIRE(!cb.full());
// push one element
REQUIRE(cb.push(1));
REQUIRE(cb.full());
REQUIRE(!cb.empty());
REQUIRE(!cb.push(2));
// retrieve the element
uint8_t v;
REQUIRE(cb.pop(v));
REQUIRE(v == 1);
REQUIRE(cb.empty());
REQUIRE(!cb.pop(v));
}