1 //
2 // Copyright 2021 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // CircularBuffer_unittest:
7 // Tests of the CircularBuffer class
8 //
9
10 #include <gtest/gtest.h>
11
12 #include "common/CircularBuffer.h"
13
14 namespace angle
15 {
16 // Make sure the various constructors compile and do basic checks
TEST(CircularBuffer,Constructors)17 TEST(CircularBuffer, Constructors)
18 {
19 CircularBuffer<int, 5> defaultContructor;
20 EXPECT_EQ(5u, defaultContructor.size());
21
22 CircularBuffer<int, 5> valueConstructor(3);
23 EXPECT_EQ(5u, valueConstructor.size());
24 EXPECT_EQ(3, valueConstructor.front());
25
26 CircularBuffer<int, 5> copy(valueConstructor);
27 EXPECT_EQ(5u, copy.size());
28
29 CircularBuffer<int, 5> copyRValue(std::move(valueConstructor));
30 EXPECT_EQ(5u, copyRValue.size());
31 }
32
33 // Make sure the destructor destroys all elements.
TEST(CircularBuffer,Destructor)34 TEST(CircularBuffer, Destructor)
35 {
36 struct s
37 {
38 s() {}
39 s(int *c) : counter(c) {}
40 ~s()
41 {
42 if (counter)
43 {
44 ++*counter;
45 }
46 }
47
48 s(const s &) = default;
49 s &operator=(const s &) = default;
50
51 int *counter;
52 };
53
54 int destructorCount = 0;
55
56 {
57 CircularBuffer<s, 11> buf((s(&destructorCount)));
58
59 // Destructor called once for the temporary above.
60 EXPECT_EQ(destructorCount, 1);
61
62 // Change front index to be non-zero.
63 buf.next();
64 buf.next();
65 buf.next();
66 }
67
68 // Destructor should be called 11 more times, once for each element.
69 EXPECT_EQ(destructorCount, 12);
70 }
71
72 // Test circulating behavior.
TEST(CircularBuffer,Circulate)73 TEST(CircularBuffer, Circulate)
74 {
75 CircularBuffer<int, 7> buf(128);
76
77 for (int i = 0; i < 7; ++i)
78 {
79 int &value = buf.front();
80 EXPECT_EQ(value, 128);
81
82 value = i + 10;
83
84 buf.next();
85 }
86
87 for (int i = 0; i < 93; ++i)
88 {
89 EXPECT_EQ(buf.front(), i % 7 + 10);
90 buf.next();
91 }
92 }
93
94 // Test iteration.
TEST(CircularBuffer,Iterate)95 TEST(CircularBuffer, Iterate)
96 {
97 CircularBuffer<int, 3> buf(12);
98
99 for (int i = 0; i < 3; ++i)
100 {
101 int &value = buf.front();
102 buf.next();
103
104 EXPECT_EQ(value, 12);
105
106 value = i;
107 }
108
109 // Check that iteration returns all the values (with unknown order) regardless of where the
110 // front is pointing.
111 for (int i = 0; i < 10; ++i)
112 {
113 uint32_t valuesSeen = 0;
114 for (int value : buf)
115 {
116 valuesSeen |= 1 << value;
117 }
118 EXPECT_EQ(valuesSeen, 0x7u);
119
120 // Make sure iteration hasn't affected the front index.
121 EXPECT_EQ(buf.front(), i % 3);
122
123 buf.next();
124 }
125 }
126
127 // Tests buffer operations with a non copyable type.
TEST(CircularBuffer,NonCopyable)128 TEST(CircularBuffer, NonCopyable)
129 {
130 struct s : angle::NonCopyable
131 {
132 s() : x(0) {}
133 s(s &&other) : x(other.x) {}
134 s &operator=(s &&other)
135 {
136 x = other.x;
137 return *this;
138 }
139 int x;
140 };
141
142 CircularBuffer<s, 4> buf;
143
144 for (int i = 0; i < 4; ++i)
145 {
146 s &value = buf.front();
147 value.x = i;
148
149 buf.next();
150 }
151
152 // Make the front index non-zero.
153 buf.next();
154 EXPECT_EQ(buf.front().x, 1);
155
156 CircularBuffer<s, 4> copy = std::move(buf);
157
158 for (int i = 0; i < 4; ++i)
159 {
160 EXPECT_EQ(copy.front().x, (i + 1) % 4);
161 copy.next();
162 }
163 }
164 } // namespace angle
165