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