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