blob: c06ef0ef2d29a9dfcd5cda329776c41c320ab346 [file] [log] [blame]
James Kuszmaul97f750d2019-01-20 20:08:03 -08001#include "aos/containers/ring_buffer.h"
Parker Schuhecd057f2017-03-11 20:03:01 -08002
Austin Schuh4075ff62021-03-31 23:22:35 -07003#include "glog/logging.h"
Parker Schuhecd057f2017-03-11 20:03:01 -08004#include "gtest/gtest.h"
5
Stephan Pleinesf63bde82024-01-13 15:59:33 -08006namespace aos::testing {
Parker Schuhecd057f2017-03-11 20:03:01 -08007
Austin Schuh4075ff62021-03-31 23:22:35 -07008// A class which is implicitly convertible to and from int, and tracks object
9// lifetimes.
10struct TrackedInt {
11 enum class State { kNoValue, kAlive, kDestroyed };
12
13 static int instance_count;
14 int value;
15 State state;
16
17 TrackedInt(int new_value) : value(new_value), state(State::kAlive) {
18 ++instance_count;
19 }
20
21 TrackedInt(const TrackedInt &other) = delete;
22 TrackedInt(TrackedInt &&other) : value(other.value), state(other.state) {
23 CHECK(other.state != State::kDestroyed);
24 other.state = State::kNoValue;
25 ++instance_count;
26 }
27 ~TrackedInt() {
28 CHECK(state != State::kDestroyed);
29 state = State::kDestroyed;
30 --instance_count;
31 CHECK_GE(instance_count, 0);
32 }
33 TrackedInt &operator=(const TrackedInt &other) = delete;
34 TrackedInt &operator=(TrackedInt &&other) {
35 CHECK(state != State::kDestroyed);
36 CHECK(other.state != State::kDestroyed);
37 state = other.state;
38 other.state = State::kNoValue;
39 value = other.value;
40 return *this;
41 }
42
43 operator int() const {
44 CHECK(state == State::kAlive);
45 return value;
46 }
47};
48
49int TrackedInt::instance_count;
50
51struct TrackedIntTracker {
52 TrackedIntTracker() {
53 CHECK_EQ(0, TrackedInt::instance_count) << ": Instances alive before test";
54 }
55 ~TrackedIntTracker() {
56 CHECK_EQ(0, TrackedInt::instance_count) << ": Instances alive after test";
57 }
58};
59
Parker Schuhecd057f2017-03-11 20:03:01 -080060class RingBufferTest : public ::testing::Test {
61 public:
62 RingBufferTest() {}
63
64 protected:
Austin Schuh4075ff62021-03-31 23:22:35 -070065 TrackedIntTracker tracked_int_tracker_;
66 RingBuffer<TrackedInt, 10> buffer_;
Parker Schuhecd057f2017-03-11 20:03:01 -080067};
68
69// Test if the RingBuffer is empty when initialized properly
70TEST_F(RingBufferTest, DefaultIsEmpty) {
71 // The RingBuffer should have a size of 0, a capacity of 10 (note that it was
72 // initialized as 10), have no items, and not be full
73 ASSERT_EQ(0u, buffer_.size());
74 ASSERT_EQ(10u, buffer_.capacity());
75 ASSERT_TRUE(buffer_.empty());
76 ASSERT_FALSE(buffer_.full());
77}
78
79// Test that the RingBuffer can fill it's entire capacity and read back the data
80TEST_F(RingBufferTest, CanAddData) {
81 ASSERT_TRUE(buffer_.empty());
82
83 // Add sequential numbers to the RingBuffer
84 // (the value of each item is it's index #)
85 for (size_t i = 0; i < buffer_.capacity(); ++i) {
86 // The buffer shouldn't be full yet, and it's size should be how many items
87 // we've added so far. Once that happens, we add another item
88 ASSERT_FALSE(buffer_.full());
89 ASSERT_EQ(i, buffer_.size());
90 buffer_.Push(i);
91
92 // The buffer shouldn't be empty and it's size should be 1 more since we
Austin Schuh4075ff62021-03-31 23:22:35 -070093 // just added an item. Also, the last item in the buffer should equal the
94 // one we just added
Parker Schuhecd057f2017-03-11 20:03:01 -080095 ASSERT_FALSE(buffer_.empty());
96 ASSERT_EQ(i + 1, buffer_.size());
97 ASSERT_EQ(i, buffer_[i]);
98 }
99
100 ASSERT_TRUE(buffer_.full());
101}
102
103// Tests that the RingBuffer properly loops back and starts overwriting from the
104// first element after being filled up
105TEST_F(RingBufferTest, OverfillData) {
106 // Add numbers 0-24 to the RingBuffer
107 for (int i = 0; i < 25; ++i) {
108 buffer_.Push(i);
109 }
110
111 // It should now be full
112 ASSERT_TRUE(buffer_.full());
113
114 // Since the buffer is a size of 10 and has been filled up 2.5 times, it
Austin Schuh4075ff62021-03-31 23:22:35 -0700115 // should now contain the numbers 15-24
Parker Schuhecd057f2017-03-11 20:03:01 -0800116 for (size_t i = 0; i < buffer_.size(); ++i) {
117 ASSERT_EQ(15 + i, buffer_[i]);
118 }
119}
120
Parker Schuh208a58d2017-04-12 20:51:38 -0700121// Tests shifting from the front of the ringbuffer.
122TEST_F(RingBufferTest, RingBufferShift) {
123 // Add numbers 0-24 to the RingBuffer
124 for (int i = 0; i < 25; ++i) {
125 buffer_.Push(i);
126 }
127
128 // It should now be full
129 ASSERT_TRUE(buffer_.full());
130
131 buffer_.Shift();
132 buffer_.Shift();
133 buffer_.Shift();
134
135 ASSERT_EQ(buffer_.size(), 7);
136
137 // The buffer should now contain the numbers 18-24
138 for (size_t i = 0; i < buffer_.size(); ++i) {
139 ASSERT_EQ(18 + i, buffer_[i]);
140 }
141}
142
Austin Schuhd85c66e2017-04-16 10:50:33 -0700143// Test that the buffer works after Reset.
144TEST_F(RingBufferTest, ResetWorks) {
145 // Over fill it, and then clear it out.
146 ASSERT_TRUE(buffer_.empty());
147
148 for (size_t i = 0; i < 53; ++i) {
149 buffer_.Push(i);
150 }
151 ASSERT_TRUE(buffer_.full());
152
153 buffer_.Reset();
154
155 ASSERT_TRUE(buffer_.empty());
156
157 // Now, add numbers 0-9 to the RingBuffer.
158 for (int i = 0; i < 10; ++i) {
159 buffer_.Push(i);
160 }
161
162 // It should now be full.
163 ASSERT_TRUE(buffer_.full());
164
165 // The last 10 numbers were added 0-9, so verify that is what is in the
166 // buffer.
167 for (size_t i = 0; i < buffer_.size(); ++i) {
168 ASSERT_EQ(i, buffer_[i]);
169 }
170}
171
Austin Schuh39f7ae92019-04-14 17:14:50 -0700172// Test that an iterator over the buffer works.
173TEST_F(RingBufferTest, Iterator) {
174 // Over fill it, and then clear it out.
175 ASSERT_TRUE(buffer_.empty());
176
177 for (int i = 0; i < 12; ++i) {
178 buffer_.Push(i);
179 }
180
181 int i = 0;
182 for (int element : buffer_) {
183 EXPECT_EQ(i + 2, element);
184 ++i;
185 }
186 EXPECT_EQ(i, buffer_.size());
187}
188
189// Test that a const iterator over the buffer works.
190TEST_F(RingBufferTest, CIterator) {
191 // Over fill it, and then clear it out.
192 ASSERT_TRUE(buffer_.empty());
193
194 for (int i = 0; i < 12; ++i) {
195 buffer_.Push(i);
196 }
197
Austin Schuh4075ff62021-03-31 23:22:35 -0700198 const RingBuffer<TrackedInt, 10> &cbuffer = buffer_;
Austin Schuh39f7ae92019-04-14 17:14:50 -0700199
200 int i = 0;
201 for (const int element : cbuffer) {
202 EXPECT_EQ(i + 2, element);
203 ++i;
204 }
205 EXPECT_EQ(i, buffer_.size());
206}
207
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800208} // namespace aos::testing