62 lines
2.6 KiB
C++
62 lines
2.6 KiB
C++
// SPDX-License-Identifier: MIT
|
|
// SPDX-FileCopyrightText: 2026 Martino Ferrari
|
|
|
|
#include "harness.hpp"
|
|
#include <plot/data/ring_buffer.hpp>
|
|
|
|
PLOT_TEST(ring_wraps_and_keeps_latest) {
|
|
plot::data::RingBuffer<f32> r(8); // capacity rounded up to a power of two
|
|
for (int i = 0; i < 20; ++i) r.push(f32(i));
|
|
PLOT_CHECK(r.size() == 8);
|
|
PLOT_CHECK_NEAR(r[0], 12.0); // oldest retained
|
|
PLOT_CHECK_NEAR(r[7], 19.0); // newest
|
|
}
|
|
PLOT_TEST(ring_clear_resets) {
|
|
plot::data::RingBuffer<f32> r(8);
|
|
for (int i = 0; i < 5; ++i) r.push(f32(i));
|
|
r.clear();
|
|
PLOT_CHECK(r.size() == 0);
|
|
r.push(42.0f);
|
|
PLOT_CHECK(r.size() == 1);
|
|
PLOT_CHECK_NEAR(r[0], 42.0);
|
|
}
|
|
|
|
PLOT_TEST(ring_capacity_rounds_up_to_a_power_of_two) {
|
|
// The capacity is rounded up so slot addressing stays a mask, and capacity()
|
|
// reports the rounded value -- the one callers must size for (R4).
|
|
PLOT_CHECK(plot::data::RingBuffer<f32>(100).capacity() == 128);
|
|
PLOT_CHECK(plot::data::RingBuffer<f32>(1).capacity() == 1);
|
|
PLOT_CHECK(plot::data::RingBuffer<f32>(0).capacity() == 1);
|
|
PLOT_CHECK(plot::data::RingBuffer<f32>(64).capacity() == 64); // already a power
|
|
|
|
plot::data::RingBuffer<f32> r(100);
|
|
for (int i = 0; i < 1000; ++i) r.push(f32(i));
|
|
PLOT_CHECK(r.size() == 128); // size() saturates at the rounded capacity
|
|
PLOT_CHECK_NEAR(r[0], 872.0); // oldest retained
|
|
PLOT_CHECK_NEAR(r[127], 999.0); // newest
|
|
}
|
|
|
|
PLOT_TEST(ring_amend_rewrites_a_retained_slot) {
|
|
// Backfill: a slot pushed as a placeholder is rewritten once the data that belongs there
|
|
// arrives. The index is absolute, because that is the only coordinate a late packet can
|
|
// compute -- a retained-window index would have moved by the time it got here.
|
|
plot::data::RingBuffer<f32> r(8);
|
|
for (int i = 0; i < 6; ++i) r.push(f32(i));
|
|
PLOT_CHECK(r.amend(3, 42.0f));
|
|
PLOT_CHECK_NEAR(r[3], 42.0);
|
|
PLOT_CHECK(r.produced() == 6); // an amend is not a push
|
|
}
|
|
|
|
PLOT_TEST(ring_amend_refuses_an_index_the_ring_no_longer_holds) {
|
|
// The window slides on the producer, so a late amend may arrive after its slot was
|
|
// overwritten. Writing it anyway would corrupt whatever sample now owns that slot, so the
|
|
// bounds test is the whole safety of the operation and the caller reads the result.
|
|
plot::data::RingBuffer<f32> r(8);
|
|
for (int i = 0; i < 20; ++i) r.push(f32(i));
|
|
PLOT_CHECK(r.base() == 12);
|
|
PLOT_CHECK(!r.amend(3, 42.0f)); // aged out
|
|
PLOT_CHECK(!r.amend(20, 42.0f)); // never produced
|
|
PLOT_CHECK_NEAR(r[0], 12.0); // and nothing moved
|
|
PLOT_CHECK_NEAR(r[7], 19.0);
|
|
}
|