28 namespace ArrayBaseTestsHelpers
30 class TriviallyCopyableType
33 TriviallyCopyableType() =
default;
35 TriviallyCopyableType (
int v)
39 TriviallyCopyableType (
float v)
43 bool operator== (
const TriviallyCopyableType& other)
const
45 return getValue() == other.getValue();
48 int getValue()
const {
return value; }
54 class NonTriviallyCopyableType
57 NonTriviallyCopyableType() =
default;
59 NonTriviallyCopyableType (
int v)
63 NonTriviallyCopyableType (
float v)
67 NonTriviallyCopyableType (
const NonTriviallyCopyableType& other)
71 NonTriviallyCopyableType& operator= (
const NonTriviallyCopyableType& other)
77 bool operator== (
const NonTriviallyCopyableType& other)
const
79 return getValue() == other.getValue();
82 int getValue()
const {
return *ptr; }
90 bool operator== (
const ArrayBaseTestsHelpers::TriviallyCopyableType& tct,
91 const ArrayBaseTestsHelpers::NonTriviallyCopyableType& ntct)
93 return tct.getValue() == ntct.getValue();
96 bool operator== (
const ArrayBaseTestsHelpers::NonTriviallyCopyableType& ntct,
97 const ArrayBaseTestsHelpers::TriviallyCopyableType& tct)
102 class ArrayBaseTests :
public UnitTest
104 using CopyableType = ArrayBaseTestsHelpers::TriviallyCopyableType;
105 using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType;
107 #if ! (defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__))
108 static_assert (std::is_trivially_copyable<CopyableType>::value,
109 "Test TriviallyCopyableType is not trivially copyable");
110 static_assert (! std::is_trivially_copyable<NoncopyableType>::value,
111 "Test NonTriviallyCopyableType is trivially copyable");
116 : UnitTest (
"ArrayBase", UnitTestCategories::containers)
119 void runTest()
override
121 beginTest (
"grow capacity");
123 std::vector<CopyableType> referenceContainer;
124 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
125 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
127 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
129 int originalCapacity = 4;
130 referenceContainer.reserve ((
size_t) originalCapacity);
131 expectEquals ((
int) referenceContainer.capacity(), originalCapacity);
132 copyableContainer.setAllocatedSize (originalCapacity);
133 expectEquals (copyableContainer.capacity(), originalCapacity);
134 noncopyableContainer.setAllocatedSize (originalCapacity);
135 expectEquals (noncopyableContainer.capacity(), originalCapacity);
137 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
139 addData (referenceContainer, copyableContainer, noncopyableContainer, 33);
141 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
143 expect ((
int) referenceContainer.capacity() != originalCapacity);
144 expect (copyableContainer.capacity() != originalCapacity);
145 expect (noncopyableContainer.capacity() != originalCapacity);
148 beginTest (
"shrink capacity");
150 std::vector<CopyableType> referenceContainer;
151 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
152 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
154 int numElements = 45;
155 addData (referenceContainer, copyableContainer, noncopyableContainer, numElements);
157 copyableContainer.shrinkToNoMoreThan (numElements);
158 noncopyableContainer.setAllocatedSize (numElements + 1);
160 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
162 referenceContainer.clear();
163 copyableContainer.removeElements (0, numElements);
164 noncopyableContainer.removeElements (0, numElements);
166 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
168 copyableContainer.setAllocatedSize (0);
169 noncopyableContainer.setAllocatedSize (0);
171 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
173 addData (referenceContainer, copyableContainer, noncopyableContainer, numElements);
175 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
178 beginTest (
"equality");
180 std::vector<int> referenceContainer = { 1, 2, 3 };
181 ArrayBase<int, DummyCriticalSection> testContainer1, testContainer2;
183 for (
auto i : referenceContainer)
185 testContainer1.add (i);
186 testContainer2.add (i);
189 expect (testContainer1 == referenceContainer);
190 expect (testContainer2 == testContainer1);
192 testContainer1.ensureAllocatedSize (257);
193 referenceContainer.shrink_to_fit();
195 expect (testContainer1 == referenceContainer);
196 expect (testContainer2 == testContainer1);
198 testContainer1.removeElements (0, 1);
200 expect (testContainer1 != referenceContainer);
201 expect (testContainer2 != testContainer1);
204 beginTest (
"accessors");
206 std::vector<CopyableType> referenceContainer;
207 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
208 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
210 addData (referenceContainer, copyableContainer, noncopyableContainer, 3);
212 int testValue = -123;
213 referenceContainer[0] = testValue;
214 copyableContainer[0] = testValue;
215 noncopyableContainer[0] = testValue;
217 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
219 expect (copyableContainer .getFirst().getValue() == testValue);
220 expect (noncopyableContainer.getFirst().getValue() == testValue);
222 auto last = referenceContainer.back().getValue();
224 expectEquals (copyableContainer .getLast().getValue(), last);
225 expectEquals (noncopyableContainer.getLast().getValue(), last);
227 ArrayBase<CopyableType, DummyCriticalSection> copyableEmpty;
228 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableEmpty;
230 auto defualtValue = CopyableType().getValue();
231 expectEquals (defualtValue, NoncopyableType().getValue());
233 expectEquals (copyableEmpty .getFirst().getValue(), defualtValue);
234 expectEquals (noncopyableEmpty.getFirst().getValue(), defualtValue);
235 expectEquals (copyableEmpty .getLast() .getValue(), defualtValue);
236 expectEquals (noncopyableEmpty.getLast() .getValue(), defualtValue);
238 ArrayBase<float*, DummyCriticalSection> floatPointers;
239 expect (floatPointers.getValueWithDefault (-3) ==
nullptr);
242 beginTest (
"add moved");
244 std::vector<CopyableType> referenceContainer;
245 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
246 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
248 for (
int i = 0; i < 5; ++i)
250 CopyableType ref (-i);
251 CopyableType ct (-i);
252 NoncopyableType nct (-i);
253 referenceContainer.push_back (std::move (ref));
254 copyableContainer.add (std::move (ct));
255 noncopyableContainer.add (std::move (nct));
258 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
261 beginTest (
"add multiple");
263 std::vector<CopyableType> referenceContainer;
264 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
265 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
267 for (
int i = 4; i < 7; ++i)
268 referenceContainer.push_back ({ -i });
270 copyableContainer.add (CopyableType (-4), CopyableType (-5), CopyableType (-6));
271 noncopyableContainer.add (NoncopyableType (-4), NoncopyableType (-5), NoncopyableType (-6));
273 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
276 beginTest (
"add array from a pointer");
278 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
279 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
281 std::vector<CopyableType> copyableData = { 3, 4, 5 };
282 std::vector<NoncopyableType> noncopyableData = { 3, 4, 5 };
284 copyableContainer.addArray (copyableData.data(), (
int) copyableData.size());
285 noncopyableContainer.addArray (noncopyableData.data(), (
int) noncopyableData.size());
287 checkEqual (copyableContainer, noncopyableContainer, copyableData);
290 beginTest (
"add array from a pointer of a different type");
292 std::vector<CopyableType> referenceContainer;
293 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
294 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
296 std::vector<float> floatData = { 1.4f, 2.5f, 3.6f };
298 for (
auto f : floatData)
299 referenceContainer.push_back ({ f });
301 copyableContainer.addArray (floatData.data(), (
int) floatData.size());
302 noncopyableContainer.addArray (floatData.data(), (
int) floatData.size());
304 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
307 beginTest (
"add array from initializer_list");
309 std::vector<CopyableType> referenceContainer;
310 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
311 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
313 std::initializer_list<CopyableType> ilct { { 3 }, { 4 }, { 5 } };
314 std::initializer_list<NoncopyableType> ilnct { { 3 }, { 4 }, { 5 } };
317 referenceContainer.push_back ({ v });
319 copyableContainer.addArray (ilct);
320 noncopyableContainer.addArray (ilnct);
322 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
325 beginTest (
"add array from containers");
327 std::vector<CopyableType> referenceContainer;
328 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
329 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
331 addData (referenceContainer, copyableContainer, noncopyableContainer, 5);
333 std::vector<CopyableType> referenceContainerCopy (referenceContainer);
334 std::vector<NoncopyableType> noncopyableReferenceContainerCopy;
335 ArrayBase<CopyableType, DummyCriticalSection> copyableContainerCopy;
336 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainerCopy;
338 for (
auto& v : referenceContainerCopy)
339 noncopyableReferenceContainerCopy.push_back ({ v.getValue() });
341 for (
size_t i = 0; i < referenceContainerCopy.size(); ++i)
343 auto value = referenceContainerCopy[i].getValue();
344 copyableContainerCopy.add ({ value });
345 noncopyableContainerCopy.add ({ value });
349 copyableContainer.addArray (copyableContainerCopy);
350 noncopyableContainer.addArray (noncopyableContainerCopy);
352 for (
auto v : referenceContainerCopy)
353 referenceContainer.push_back (v);
355 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
358 copyableContainer.addArray (referenceContainerCopy);
359 noncopyableContainer.addArray (noncopyableReferenceContainerCopy);
361 for (
auto v : referenceContainerCopy)
362 referenceContainer.push_back (v);
364 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
368 copyableContainer.addArray (referenceContainerCopy, offset);
369 noncopyableContainer.addArray (noncopyableReferenceContainerCopy, offset);
371 for (
size_t i = 5; i < referenceContainerCopy.size(); ++i)
372 referenceContainer.push_back (referenceContainerCopy[i]);
374 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
377 beginTest (
"insert");
379 std::vector<CopyableType> referenceContainer;
380 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
381 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
383 addData (referenceContainer, copyableContainer, noncopyableContainer, 8);
385 referenceContainer.insert (referenceContainer.begin(), -4);
386 copyableContainer.insert (0, -4, 1);
387 noncopyableContainer.insert (0, -4, 1);
389 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
391 for (
int i = 0; i < 3; ++i)
392 referenceContainer.insert (referenceContainer.begin() + 1, -3);
394 copyableContainer.insert (1, -3, 3);
395 noncopyableContainer.insert (1, -3, 3);
397 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
399 for (
int i = 0; i < 50; ++i)
400 referenceContainer.insert (referenceContainer.end() - 1, -9);
402 copyableContainer.insert (copyableContainer.size() - 2, -9, 50);
403 noncopyableContainer.insert (noncopyableContainer.size() - 2, -9, 50);
406 beginTest (
"insert array");
408 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
409 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
411 std::vector<CopyableType> copyableData = { 3, 4, 5, 6, 7, 8 };
412 std::vector<NoncopyableType> noncopyableData = { 3, 4, 5, 6, 7, 8 };
414 std::vector<CopyableType> referenceContainer { copyableData };
416 copyableContainer.insertArray (0, copyableData.data(), (
int) copyableData.size());
417 noncopyableContainer.insertArray (0, noncopyableData.data(), (
int) noncopyableData.size());
419 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
421 int insertPos = copyableContainer.size() - 1;
423 for (
auto it = copyableData.end(); it != copyableData.begin(); --it)
424 referenceContainer.insert (referenceContainer.begin() + insertPos, CopyableType (*(it - 1)));
426 copyableContainer.insertArray (insertPos, copyableData.data(), (
int) copyableData.size());
427 noncopyableContainer.insertArray (insertPos, noncopyableData.data(), (
int) noncopyableData.size());
429 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
432 beginTest (
"remove");
434 std::vector<CopyableType> referenceContainer;
435 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
436 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
438 addData (referenceContainer, copyableContainer, noncopyableContainer, 17);
440 for (
int i = 0; i < 4; ++i)
442 referenceContainer.erase (referenceContainer.begin() + i);
443 copyableContainer.removeElements (i, 1);
444 noncopyableContainer.removeElements (i, 1);
447 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
449 addData (referenceContainer, copyableContainer, noncopyableContainer, 17);
452 for (
int i = 0; i < 4; ++i)
454 for (
int j = 0; j < blockSize; ++j)
455 referenceContainer.erase (referenceContainer.begin() + i);
457 copyableContainer.removeElements (i, blockSize);
458 noncopyableContainer.removeElements (i, blockSize);
461 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
463 auto numToRemove = copyableContainer.size() - 2;
465 for (
int i = 0; i < numToRemove; ++i)
466 referenceContainer.erase (referenceContainer.begin() + 1);
468 copyableContainer.removeElements (1, numToRemove);
469 noncopyableContainer.removeElements (1, numToRemove);
471 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
476 std::vector<CopyableType> referenceContainer;
477 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
478 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
480 addData (referenceContainer, copyableContainer, noncopyableContainer, 6);
482 std::vector<std::pair<int, int>> testValues;
483 testValues.emplace_back (2, 4);
484 testValues.emplace_back (0, 5);
485 testValues.emplace_back (4, 1);
486 testValues.emplace_back (5, 0);
488 for (
auto p : testValues)
490 if (p.second > p.first)
491 std::rotate (referenceContainer.begin() + p.first,
492 referenceContainer.begin() + p.first + 1,
493 referenceContainer.begin() + p.second + 1);
495 std::rotate (referenceContainer.begin() + p.second,
496 referenceContainer.begin() + p.first,
497 referenceContainer.begin() + p.first + 1);
499 copyableContainer.move (p.first, p.second);
500 noncopyableContainer.move (p.first, p.second);
502 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
506 beginTest (
"After converting move construction, ownership is transferred");
509 ArrayBase<Derived*, DummyCriticalSection> derived;
510 derived.setAllocatedSize (5);
513 ArrayBase<Base*, DummyCriticalSection> base { std::move (derived) };
515 expectEquals (base.capacity(), 5);
516 expectEquals (base.size(), 1);
517 expect (base.getFirst() == &obj);
518 expectEquals (derived.capacity(), 0);
519 expectEquals (derived.size(), 0);
520 expect (derived.data() ==
nullptr);
523 beginTest (
"After converting move assignment, ownership is transferred");
526 ArrayBase<Derived*, DummyCriticalSection> derived;
527 derived.setAllocatedSize (5);
529 ArrayBase<Base*, DummyCriticalSection> base;
531 base = std::move (derived);
533 expectEquals (base.capacity(), 5);
534 expectEquals (base.size(), 1);
535 expect (base.getFirst() == &obj);
536 expectEquals (derived.capacity(), 0);
537 expectEquals (derived.size(), 0);
538 expect (derived.data() ==
nullptr);
545 virtual ~Base() =
default;
548 struct Derived : Base
552 static void addData (std::vector<CopyableType>& referenceContainer,
553 ArrayBase<CopyableType, DummyCriticalSection>& copyableContainer,
554 ArrayBase<NoncopyableType, DummyCriticalSection>& NoncopyableContainer,
557 for (
int i = 0; i < numValues; ++i)
559 referenceContainer.push_back ({ i });
560 copyableContainer.add ({ i });
561 NoncopyableContainer.add ({ i });
565 template<
typename A,
typename B>
566 void checkEqual (
const ArrayBase<A, DummyCriticalSection>& a,
567 const ArrayBase<B, DummyCriticalSection>& b)
569 expectEquals ((
int) a.size(), (
int) b.size());
571 for (
int i = 0; i < (int) a.size(); ++i)
572 expect (a[i] == b[i]);
575 template<
typename A,
typename B>
576 void checkEqual (ArrayBase<A, DummyCriticalSection>& a,
579 expectEquals ((
int) a.size(), (
int) b.size());
581 for (
int i = 0; i < (int) a.size(); ++i)
582 expect (a[i] == b[(
size_t) i]);
585 template<
typename A,
typename B,
typename C>
586 void checkEqual (ArrayBase<A, DummyCriticalSection>& a,
587 ArrayBase<B, DummyCriticalSection>& b,
596 static ArrayBaseTests arrayBaseTests;