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