1// Copyright 2019 The Marl Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "marl/containers.h"
16#include "marl_test.h"
17
18#include "gmock/gmock.h"
19#include "gtest/gtest.h"
20
21#include <cstddef>
22#include <string>
23
24class ContainersVectorTest : public WithoutBoundScheduler {};
25
26TEST_F(ContainersVectorTest, Empty) {
27 marl::containers::vector<std::string, 4> vector(allocator);
28 ASSERT_EQ(vector.size(), size_t(0));
29}
30
31TEST_F(ContainersVectorTest, WithinFixedCapIndex) {
32 marl::containers::vector<std::string, 4> vector(allocator);
33 vector.resize(4);
34 vector[0] = "A";
35 vector[1] = "B";
36 vector[2] = "C";
37 vector[3] = "D";
38
39 ASSERT_EQ(vector[0], "A");
40 ASSERT_EQ(vector[1], "B");
41 ASSERT_EQ(vector[2], "C");
42 ASSERT_EQ(vector[3], "D");
43}
44
45TEST_F(ContainersVectorTest, BeyondFixedCapIndex) {
46 marl::containers::vector<std::string, 1> vector(allocator);
47 vector.resize(4);
48 vector[0] = "A";
49 vector[1] = "B";
50 vector[2] = "C";
51 vector[3] = "D";
52
53 ASSERT_EQ(vector[0], "A");
54 ASSERT_EQ(vector[1], "B");
55 ASSERT_EQ(vector[2], "C");
56 ASSERT_EQ(vector[3], "D");
57}
58
59TEST_F(ContainersVectorTest, WithinFixedCapPushPop) {
60 marl::containers::vector<std::string, 4> vector(allocator);
61 vector.push_back("A");
62 vector.push_back("B");
63 vector.push_back("C");
64 vector.push_back("D");
65
66 ASSERT_EQ(vector.size(), size_t(4));
67 ASSERT_EQ(vector.end() - vector.begin(), ptrdiff_t(4));
68
69 ASSERT_EQ(vector.front(), "A");
70 ASSERT_EQ(vector.back(), "D");
71 vector.pop_back();
72 ASSERT_EQ(vector.size(), size_t(3));
73 ASSERT_EQ(vector.end() - vector.begin(), ptrdiff_t(3));
74
75 ASSERT_EQ(vector.front(), "A");
76 ASSERT_EQ(vector.back(), "C");
77 vector.pop_back();
78 ASSERT_EQ(vector.size(), size_t(2));
79 ASSERT_EQ(vector.end() - vector.begin(), ptrdiff_t(2));
80
81 ASSERT_EQ(vector.front(), "A");
82 ASSERT_EQ(vector.back(), "B");
83 vector.pop_back();
84 ASSERT_EQ(vector.size(), size_t(1));
85 ASSERT_EQ(vector.end() - vector.begin(), ptrdiff_t(1));
86
87 ASSERT_EQ(vector.front(), "A");
88 ASSERT_EQ(vector.back(), "A");
89 vector.pop_back();
90 ASSERT_EQ(vector.size(), size_t(0));
91}
92
93TEST_F(ContainersVectorTest, BeyondFixedCapPushPop) {
94 marl::containers::vector<std::string, 2> vector(allocator);
95 vector.push_back("A");
96 vector.push_back("B");
97 vector.push_back("C");
98 vector.push_back("D");
99
100 ASSERT_EQ(vector.size(), size_t(4));
101 ASSERT_EQ(vector.end() - vector.begin(), ptrdiff_t(4));
102
103 ASSERT_EQ(vector.front(), "A");
104 ASSERT_EQ(vector.back(), "D");
105 vector.pop_back();
106 ASSERT_EQ(vector.size(), size_t(3));
107 ASSERT_EQ(vector.end() - vector.begin(), ptrdiff_t(3));
108
109 ASSERT_EQ(vector.front(), "A");
110 ASSERT_EQ(vector.back(), "C");
111 vector.pop_back();
112 ASSERT_EQ(vector.size(), size_t(2));
113 ASSERT_EQ(vector.end() - vector.begin(), ptrdiff_t(2));
114
115 ASSERT_EQ(vector.front(), "A");
116 ASSERT_EQ(vector.back(), "B");
117 vector.pop_back();
118 ASSERT_EQ(vector.size(), size_t(1));
119 ASSERT_EQ(vector.end() - vector.begin(), ptrdiff_t(1));
120
121 ASSERT_EQ(vector.front(), "A");
122 ASSERT_EQ(vector.back(), "A");
123 vector.pop_back();
124 ASSERT_EQ(vector.size(), size_t(0));
125}
126
127TEST_F(ContainersVectorTest, CopyConstruct) {
128 marl::containers::vector<std::string, 4> vectorA(allocator);
129
130 vectorA.resize(3);
131 vectorA[0] = "A";
132 vectorA[1] = "B";
133 vectorA[2] = "C";
134
135 marl::containers::vector<std::string, 4> vectorB(vectorA, allocator);
136 ASSERT_EQ(vectorB.size(), size_t(3));
137 ASSERT_EQ(vectorB[0], "A");
138 ASSERT_EQ(vectorB[1], "B");
139 ASSERT_EQ(vectorB[2], "C");
140}
141
142TEST_F(ContainersVectorTest, CopyConstructDifferentBaseCapacity) {
143 marl::containers::vector<std::string, 4> vectorA(allocator);
144
145 vectorA.resize(3);
146 vectorA[0] = "A";
147 vectorA[1] = "B";
148 vectorA[2] = "C";
149
150 marl::containers::vector<std::string, 2> vectorB(vectorA, allocator);
151 ASSERT_EQ(vectorB.size(), size_t(3));
152 ASSERT_EQ(vectorB[0], "A");
153 ASSERT_EQ(vectorB[1], "B");
154 ASSERT_EQ(vectorB[2], "C");
155}
156
157TEST_F(ContainersVectorTest, CopyAssignment) {
158 marl::containers::vector<std::string, 4> vectorA(allocator);
159
160 vectorA.resize(3);
161 vectorA[0] = "A";
162 vectorA[1] = "B";
163 vectorA[2] = "C";
164
165 marl::containers::vector<std::string, 4> vectorB(allocator);
166 vectorB = vectorA;
167 ASSERT_EQ(vectorB.size(), size_t(3));
168 ASSERT_EQ(vectorB[0], "A");
169 ASSERT_EQ(vectorB[1], "B");
170 ASSERT_EQ(vectorB[2], "C");
171}
172
173TEST_F(ContainersVectorTest, CopyAssignmentDifferentBaseCapacity) {
174 marl::containers::vector<std::string, 4> vectorA(allocator);
175
176 vectorA.resize(3);
177 vectorA[0] = "A";
178 vectorA[1] = "B";
179 vectorA[2] = "C";
180
181 marl::containers::vector<std::string, 2> vectorB(allocator);
182 vectorB = vectorA;
183 ASSERT_EQ(vectorB.size(), size_t(3));
184 ASSERT_EQ(vectorB[0], "A");
185 ASSERT_EQ(vectorB[1], "B");
186 ASSERT_EQ(vectorB[2], "C");
187}
188
189TEST_F(ContainersVectorTest, MoveConstruct) {
190 marl::containers::vector<std::string, 4> vectorA(allocator);
191
192 vectorA.resize(3);
193 vectorA[0] = "A";
194 vectorA[1] = "B";
195 vectorA[2] = "C";
196
197 marl::containers::vector<std::string, 2> vectorB(std::move(vectorA),
198 allocator);
199 ASSERT_EQ(vectorB.size(), size_t(3));
200 ASSERT_EQ(vectorB[0], "A");
201 ASSERT_EQ(vectorB[1], "B");
202 ASSERT_EQ(vectorB[2], "C");
203}
204
205TEST_F(ContainersVectorTest, Copy) {
206 marl::containers::vector<std::string, 4> vectorA(allocator);
207 marl::containers::vector<std::string, 2> vectorB(allocator);
208
209 vectorA.resize(3);
210 vectorA[0] = "A";
211 vectorA[1] = "B";
212 vectorA[2] = "C";
213
214 vectorB.resize(1);
215 vectorB[0] = "Z";
216
217 vectorB = vectorA;
218 ASSERT_EQ(vectorB.size(), size_t(3));
219 ASSERT_EQ(vectorB[0], "A");
220 ASSERT_EQ(vectorB[1], "B");
221 ASSERT_EQ(vectorB[2], "C");
222}
223
224TEST_F(ContainersVectorTest, Move) {
225 marl::containers::vector<std::string, 4> vectorA(allocator);
226 marl::containers::vector<std::string, 2> vectorB(allocator);
227
228 vectorA.resize(3);
229 vectorA[0] = "A";
230 vectorA[1] = "B";
231 vectorA[2] = "C";
232
233 vectorB.resize(1);
234 vectorB[0] = "Z";
235
236 vectorB = std::move(vectorA);
237 ASSERT_EQ(vectorA.size(), size_t(0));
238 ASSERT_EQ(vectorB.size(), size_t(3));
239 ASSERT_EQ(vectorB[0], "A");
240 ASSERT_EQ(vectorB[1], "B");
241 ASSERT_EQ(vectorB[2], "C");
242}
243
244class ContainersListTest : public WithoutBoundScheduler {};
245
246TEST_F(ContainersListTest, Empty) {
247 marl::containers::list<std::string> list(allocator);
248 ASSERT_EQ(list.size(), size_t(0));
249}
250
251TEST_F(ContainersListTest, EmplaceOne) {
252 marl::containers::list<std::string> list(allocator);
253 auto itEntry = list.emplace_front("hello world");
254 ASSERT_EQ(*itEntry, "hello world");
255 ASSERT_EQ(list.size(), size_t(1));
256 auto it = list.begin();
257 ASSERT_EQ(it, itEntry);
258 ++it;
259 ASSERT_EQ(it, list.end());
260}
261
262TEST_F(ContainersListTest, EmplaceThree) {
263 marl::containers::list<std::string> list(allocator);
264 auto itA = list.emplace_front("a");
265 auto itB = list.emplace_front("b");
266 auto itC = list.emplace_front("c");
267 ASSERT_EQ(*itA, "a");
268 ASSERT_EQ(*itB, "b");
269 ASSERT_EQ(*itC, "c");
270 ASSERT_EQ(list.size(), size_t(3));
271 auto it = list.begin();
272 ASSERT_EQ(it, itC);
273 ++it;
274 ASSERT_EQ(it, itB);
275 ++it;
276 ASSERT_EQ(it, itA);
277 ++it;
278 ASSERT_EQ(it, list.end());
279}
280
281TEST_F(ContainersListTest, EraseFront) {
282 marl::containers::list<std::string> list(allocator);
283 auto itA = list.emplace_front("a");
284 auto itB = list.emplace_front("b");
285 auto itC = list.emplace_front("c");
286 list.erase(itC);
287 ASSERT_EQ(list.size(), size_t(2));
288 auto it = list.begin();
289 ASSERT_EQ(it, itB);
290 ++it;
291 ASSERT_EQ(it, itA);
292 ++it;
293 ASSERT_EQ(it, list.end());
294}
295
296TEST_F(ContainersListTest, EraseBack) {
297 marl::containers::list<std::string> list(allocator);
298 auto itA = list.emplace_front("a");
299 auto itB = list.emplace_front("b");
300 auto itC = list.emplace_front("c");
301 list.erase(itA);
302 ASSERT_EQ(list.size(), size_t(2));
303 auto it = list.begin();
304 ASSERT_EQ(it, itC);
305 ++it;
306 ASSERT_EQ(it, itB);
307 ++it;
308 ASSERT_EQ(it, list.end());
309}
310
311TEST_F(ContainersListTest, EraseMid) {
312 marl::containers::list<std::string> list(allocator);
313 auto itA = list.emplace_front("a");
314 auto itB = list.emplace_front("b");
315 auto itC = list.emplace_front("c");
316 list.erase(itB);
317 ASSERT_EQ(list.size(), size_t(2));
318 auto it = list.begin();
319 ASSERT_EQ(it, itC);
320 ++it;
321 ASSERT_EQ(it, itA);
322 ++it;
323 ASSERT_EQ(it, list.end());
324}
325
326TEST_F(ContainersListTest, Grow) {
327 marl::containers::list<std::string> list(allocator);
328 for (int i = 0; i < 256; i++) {
329 list.emplace_front(std::to_string(i));
330 }
331 ASSERT_EQ(list.size(), size_t(256));
332}
333