OpenShot Library | OpenShotAudio 0.2.2
juce_ArrayBase.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2018 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26#if JUCE_UNIT_TESTS
27
28namespace ArrayBaseTestsHelpers
29{
30 class TriviallyCopyableType
31 {
32 public:
33 TriviallyCopyableType() = default;
34
35 TriviallyCopyableType (int v)
36 : value (v)
37 {}
38
39 TriviallyCopyableType (float v)
40 : value ((int) v)
41 {}
42
43 bool operator== (const TriviallyCopyableType& other) const
44 {
45 return getValue() == other.getValue();
46 }
47
48 int getValue() const { return value; }
49
50 private:
51 int value { -1111 };
52 };
53
54 class NonTriviallyCopyableType
55 {
56 public:
57 NonTriviallyCopyableType() = default;
58
59 NonTriviallyCopyableType (int v)
60 : value (v)
61 {}
62
63 NonTriviallyCopyableType (float v)
64 : value ((int) v)
65 {}
66
67 NonTriviallyCopyableType (const NonTriviallyCopyableType& other)
68 : value (other.value)
69 {}
70
71 NonTriviallyCopyableType& operator= (const NonTriviallyCopyableType& other)
72 {
73 value = other.value;
74 return *this;
75 }
76
77 bool operator== (const NonTriviallyCopyableType& other) const
78 {
79 return getValue() == other.getValue();
80 }
81
82 int getValue() const { return *ptr; }
83
84 private:
85 int value { -1111 };
86 int* ptr = &value;
87 };
88}
89
90bool operator== (const ArrayBaseTestsHelpers::TriviallyCopyableType& tct,
91 const ArrayBaseTestsHelpers::NonTriviallyCopyableType& ntct)
92{
93 return tct.getValue() == ntct.getValue();
94}
95
96bool operator== (const ArrayBaseTestsHelpers::NonTriviallyCopyableType& ntct,
97 const ArrayBaseTestsHelpers::TriviallyCopyableType& tct)
98{
99 return tct == ntct;
100}
101
102class ArrayBaseTests : public UnitTest
103{
104 using CopyableType = ArrayBaseTestsHelpers::TriviallyCopyableType;
105 using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType;
106
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");
112 #endif
113
114public:
115 ArrayBaseTests()
116 : UnitTest ("ArrayBase", UnitTestCategories::containers)
117 {}
118
119 void runTest() override
120 {
121 beginTest ("grow capacity");
122 {
123 std::vector<CopyableType> referenceContainer;
124 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
125 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
126
127 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
128
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);
136
137 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
138
139 addData (referenceContainer, copyableContainer, noncopyableContainer, 33);
140
141 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
142
143 expect ((int) referenceContainer.capacity() != originalCapacity);
144 expect (copyableContainer.capacity() != originalCapacity);
145 expect (noncopyableContainer.capacity() != originalCapacity);
146 }
147
148 beginTest ("shrink capacity");
149 {
150 std::vector<CopyableType> referenceContainer;
151 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
152 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
153
154 int numElements = 45;
155 addData (referenceContainer, copyableContainer, noncopyableContainer, numElements);
156
157 copyableContainer.shrinkToNoMoreThan (numElements);
158 noncopyableContainer.setAllocatedSize (numElements + 1);
159
160 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
161
162 referenceContainer.clear();
163 copyableContainer.removeElements (0, numElements);
164 noncopyableContainer.removeElements (0, numElements);
165
166 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
167
168 copyableContainer.setAllocatedSize (0);
169 noncopyableContainer.setAllocatedSize (0);
170
171 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
172
173 addData (referenceContainer, copyableContainer, noncopyableContainer, numElements);
174
175 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
176 }
177
178 beginTest ("equality");
179 {
180 std::vector<int> referenceContainer = { 1, 2, 3 };
181 ArrayBase<int, DummyCriticalSection> testContainer1, testContainer2;
182
183 for (auto i : referenceContainer)
184 {
185 testContainer1.add (i);
186 testContainer2.add (i);
187 }
188
189 expect (testContainer1 == referenceContainer);
190 expect (testContainer2 == testContainer1);
191
192 testContainer1.ensureAllocatedSize (257);
193 referenceContainer.shrink_to_fit();
194
195 expect (testContainer1 == referenceContainer);
196 expect (testContainer2 == testContainer1);
197
198 testContainer1.removeElements (0, 1);
199
200 expect (testContainer1 != referenceContainer);
201 expect (testContainer2 != testContainer1);
202 }
203
204 beginTest ("accessors");
205 {
206 std::vector<CopyableType> referenceContainer;
207 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
208 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
209
210 addData (referenceContainer, copyableContainer, noncopyableContainer, 3);
211
212 int testValue = -123;
213 referenceContainer[0] = testValue;
214 copyableContainer[0] = testValue;
215 noncopyableContainer[0] = testValue;
216
217 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
218
219 expect (copyableContainer .getFirst().getValue() == testValue);
220 expect (noncopyableContainer.getFirst().getValue() == testValue);
221
222 auto last = referenceContainer.back().getValue();
223
224 expectEquals (copyableContainer .getLast().getValue(), last);
225 expectEquals (noncopyableContainer.getLast().getValue(), last);
226
227 ArrayBase<CopyableType, DummyCriticalSection> copyableEmpty;
228 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableEmpty;
229
230 auto defualtValue = CopyableType().getValue();
231 expectEquals (defualtValue, NoncopyableType().getValue());
232
233 expectEquals (copyableEmpty .getFirst().getValue(), defualtValue);
234 expectEquals (noncopyableEmpty.getFirst().getValue(), defualtValue);
235 expectEquals (copyableEmpty .getLast() .getValue(), defualtValue);
236 expectEquals (noncopyableEmpty.getLast() .getValue(), defualtValue);
237
238 ArrayBase<float*, DummyCriticalSection> floatPointers;
239 expect (floatPointers.getValueWithDefault (-3) == nullptr);
240 }
241
242 beginTest ("add moved");
243 {
244 std::vector<CopyableType> referenceContainer;
245 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
246 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
247
248 for (int i = 0; i < 5; ++i)
249 {
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));
256 }
257
258 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
259 }
260
261 beginTest ("add multiple");
262 {
263 std::vector<CopyableType> referenceContainer;
264 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
265 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
266
267 for (int i = 4; i < 7; ++i)
268 referenceContainer.push_back ({ -i });
269
270 copyableContainer.add (CopyableType (-4), CopyableType (-5), CopyableType (-6));
271 noncopyableContainer.add (NoncopyableType (-4), NoncopyableType (-5), NoncopyableType (-6));
272
273 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
274 }
275
276 beginTest ("add array from a pointer");
277 {
278 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
279 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
280
281 std::vector<CopyableType> copyableData = { 3, 4, 5 };
282 std::vector<NoncopyableType> noncopyableData = { 3, 4, 5 };
283
284 copyableContainer.addArray (copyableData.data(), (int) copyableData.size());
285 noncopyableContainer.addArray (noncopyableData.data(), (int) noncopyableData.size());
286
287 checkEqual (copyableContainer, noncopyableContainer, copyableData);
288 }
289
290 beginTest ("add array from a pointer of a different type");
291 {
292 std::vector<CopyableType> referenceContainer;
293 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
294 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
295
296 std::vector<float> floatData = { 1.4f, 2.5f, 3.6f };
297
298 for (auto f : floatData)
299 referenceContainer.push_back ({ f });
300
301 copyableContainer.addArray (floatData.data(), (int) floatData.size());
302 noncopyableContainer.addArray (floatData.data(), (int) floatData.size());
303
304 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
305 }
306
307 beginTest ("add array from initializer_list");
308 {
309 std::vector<CopyableType> referenceContainer;
310 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
311 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
312
313 std::initializer_list<CopyableType> ilct { { 3 }, { 4 }, { 5 } };
314 std::initializer_list<NoncopyableType> ilnct { { 3 }, { 4 }, { 5 } };
315
316 for (auto v : ilct)
317 referenceContainer.push_back ({ v });
318
319 copyableContainer.addArray (ilct);
320 noncopyableContainer.addArray (ilnct);
321
322 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
323 }
324
325 beginTest ("add array from containers");
326 {
327 std::vector<CopyableType> referenceContainer;
328 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
329 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
330
331 addData (referenceContainer, copyableContainer, noncopyableContainer, 5);
332
333 std::vector<CopyableType> referenceContainerCopy (referenceContainer);
334 std::vector<NoncopyableType> noncopyableReferenceContainerCopy;
335 ArrayBase<CopyableType, DummyCriticalSection> copyableContainerCopy;
336 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainerCopy;
337
338 for (auto& v : referenceContainerCopy)
339 noncopyableReferenceContainerCopy.push_back ({ v.getValue() });
340
341 for (size_t i = 0; i < referenceContainerCopy.size(); ++i)
342 {
343 auto value = referenceContainerCopy[i].getValue();
344 copyableContainerCopy.add ({ value });
345 noncopyableContainerCopy.add ({ value });
346 }
347
348 // From self-types
349 copyableContainer.addArray (copyableContainerCopy);
350 noncopyableContainer.addArray (noncopyableContainerCopy);
351
352 for (auto v : referenceContainerCopy)
353 referenceContainer.push_back (v);
354
355 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
356
357 // From std containers
358 copyableContainer.addArray (referenceContainerCopy);
359 noncopyableContainer.addArray (noncopyableReferenceContainerCopy);
360
361 for (auto v : referenceContainerCopy)
362 referenceContainer.push_back (v);
363
364 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
365
366 // From std containers with offset
367 int offset = 5;
368 copyableContainer.addArray (referenceContainerCopy, offset);
369 noncopyableContainer.addArray (noncopyableReferenceContainerCopy, offset);
370
371 for (size_t i = 5; i < referenceContainerCopy.size(); ++i)
372 referenceContainer.push_back (referenceContainerCopy[i]);
373
374 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
375 }
376
377 beginTest ("insert");
378 {
379 std::vector<CopyableType> referenceContainer;
380 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
381 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
382
383 addData (referenceContainer, copyableContainer, noncopyableContainer, 8);
384
385 referenceContainer.insert (referenceContainer.begin(), -4);
386 copyableContainer.insert (0, -4, 1);
387 noncopyableContainer.insert (0, -4, 1);
388
389 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
390
391 for (int i = 0; i < 3; ++i)
392 referenceContainer.insert (referenceContainer.begin() + 1, -3);
393
394 copyableContainer.insert (1, -3, 3);
395 noncopyableContainer.insert (1, -3, 3);
396
397 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
398
399 for (int i = 0; i < 50; ++i)
400 referenceContainer.insert (referenceContainer.end() - 1, -9);
401
402 copyableContainer.insert (copyableContainer.size() - 2, -9, 50);
403 noncopyableContainer.insert (noncopyableContainer.size() - 2, -9, 50);
404 }
405
406 beginTest ("insert array");
407 {
408 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
409 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
410
411 std::vector<CopyableType> copyableData = { 3, 4, 5, 6, 7, 8 };
412 std::vector<NoncopyableType> noncopyableData = { 3, 4, 5, 6, 7, 8 };
413
414 std::vector<CopyableType> referenceContainer { copyableData };
415
416 copyableContainer.insertArray (0, copyableData.data(), (int) copyableData.size());
417 noncopyableContainer.insertArray (0, noncopyableData.data(), (int) noncopyableData.size());
418
419 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
420
421 int insertPos = copyableContainer.size() - 1;
422
423 for (auto it = copyableData.end(); it != copyableData.begin(); --it)
424 referenceContainer.insert (referenceContainer.begin() + insertPos, CopyableType (*(it - 1)));
425
426 copyableContainer.insertArray (insertPos, copyableData.data(), (int) copyableData.size());
427 noncopyableContainer.insertArray (insertPos, noncopyableData.data(), (int) noncopyableData.size());
428
429 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
430 }
431
432 beginTest ("remove");
433 {
434 std::vector<CopyableType> referenceContainer;
435 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
436 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
437
438 addData (referenceContainer, copyableContainer, noncopyableContainer, 17);
439
440 for (int i = 0; i < 4; ++i)
441 {
442 referenceContainer.erase (referenceContainer.begin() + i);
443 copyableContainer.removeElements (i, 1);
444 noncopyableContainer.removeElements (i, 1);
445 }
446
447 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
448
449 addData (referenceContainer, copyableContainer, noncopyableContainer, 17);
450 int blockSize = 3;
451
452 for (int i = 0; i < 4; ++i)
453 {
454 for (int j = 0; j < blockSize; ++j)
455 referenceContainer.erase (referenceContainer.begin() + i);
456
457 copyableContainer.removeElements (i, blockSize);
458 noncopyableContainer.removeElements (i, blockSize);
459 }
460
461 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
462
463 auto numToRemove = copyableContainer.size() - 2;
464
465 for (int i = 0; i < numToRemove; ++i)
466 referenceContainer.erase (referenceContainer.begin() + 1);
467
468 copyableContainer.removeElements (1, numToRemove);
469 noncopyableContainer.removeElements (1, numToRemove);
470
471 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
472 }
473
474 beginTest ("move");
475 {
476 std::vector<CopyableType> referenceContainer;
477 ArrayBase<CopyableType, DummyCriticalSection> copyableContainer;
478 ArrayBase<NoncopyableType, DummyCriticalSection> noncopyableContainer;
479
480 addData (referenceContainer, copyableContainer, noncopyableContainer, 6);
481
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);
487
488 for (auto p : testValues)
489 {
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);
494 else
495 std::rotate (referenceContainer.begin() + p.second,
496 referenceContainer.begin() + p.first,
497 referenceContainer.begin() + p.first + 1);
498
499 copyableContainer.move (p.first, p.second);
500 noncopyableContainer.move (p.first, p.second);
501
502 checkEqual (copyableContainer, noncopyableContainer, referenceContainer);
503 }
504 }
505
506 beginTest ("After converting move construction, ownership is transferred");
507 {
508 Derived obj;
509 ArrayBase<Derived*, DummyCriticalSection> derived;
510 derived.setAllocatedSize (5);
511 derived.add (&obj);
512
513 ArrayBase<Base*, DummyCriticalSection> base { std::move (derived) };
514
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);
521 }
522
523 beginTest ("After converting move assignment, ownership is transferred");
524 {
525 Derived obj;
526 ArrayBase<Derived*, DummyCriticalSection> derived;
527 derived.setAllocatedSize (5);
528 derived.add (&obj);
529 ArrayBase<Base*, DummyCriticalSection> base;
530
531 base = std::move (derived);
532
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);
539 }
540 }
541
542private:
543 struct Base
544 {
545 virtual ~Base() = default;
546 };
547
548 struct Derived : Base
549 {
550 };
551
552 static void addData (std::vector<CopyableType>& referenceContainer,
553 ArrayBase<CopyableType, DummyCriticalSection>& copyableContainer,
554 ArrayBase<NoncopyableType, DummyCriticalSection>& NoncopyableContainer,
555 int numValues)
556 {
557 for (int i = 0; i < numValues; ++i)
558 {
559 referenceContainer.push_back ({ i });
560 copyableContainer.add ({ i });
561 NoncopyableContainer.add ({ i });
562 }
563 }
564
565 template<typename A, typename B>
566 void checkEqual (const ArrayBase<A, DummyCriticalSection>& a,
567 const ArrayBase<B, DummyCriticalSection>& b)
568 {
569 expectEquals ((int) a.size(), (int) b.size());
570
571 for (int i = 0; i < (int) a.size(); ++i)
572 expect (a[i] == b[i]);
573 }
574
575 template<typename A, typename B>
576 void checkEqual (ArrayBase<A, DummyCriticalSection>& a,
577 std::vector<B>& b)
578 {
579 expectEquals ((int) a.size(), (int) b.size());
580
581 for (int i = 0; i < (int) a.size(); ++i)
582 expect (a[i] == b[(size_t) i]);
583 }
584
585 template<typename A, typename B, typename C>
586 void checkEqual (ArrayBase<A, DummyCriticalSection>& a,
587 ArrayBase<B, DummyCriticalSection>& b,
588 std::vector<C>& c)
589 {
590 checkEqual (a, b);
591 checkEqual (a, c);
592 checkEqual (b, c);
593 }
594};
595
596static ArrayBaseTests arrayBaseTests;
597
598#endif
599
600} // namespace juce