OpenShot Audio Library | OpenShotAudio 0.4.0
Loading...
Searching...
No Matches
juce_Optional_test.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
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/* Not nested, so that ADL works for the swap function. */
27struct ThrowOnMoveOrSwap
28{
29 ThrowOnMoveOrSwap() = default;
30 ThrowOnMoveOrSwap (ThrowOnMoveOrSwap&&) { throw std::bad_alloc{}; }
31};
32static void swap (ThrowOnMoveOrSwap&, ThrowOnMoveOrSwap&) { throw std::bad_alloc{}; }
33
34class OptionalUnitTest final : public UnitTest
35{
36public:
37 OptionalUnitTest() : UnitTest ("Optional", UnitTestCategories::containers) {}
38
39 void runTest() override
40 {
41 beginTest ("Default-constructed optional is invalid");
42 {
43 Optional<int> o;
44 expect (! o.hasValue());
45 }
46
47 beginTest ("Constructing from Nullopt is invalid");
48 {
49 Optional<int> o (nullopt);
50 expect (! o.hasValue());
51 }
52
53 beginTest ("Optional constructed from value is valid");
54 {
55 Optional<int> o = 5;
56 expect (o.hasValue());
57 expectEquals (*o, 5);
58 }
59
60 using Ptr = std::shared_ptr<int>;
61 const auto makePtr = [] { return std::make_shared<int>(); };
62
63 beginTest ("Constructing from a moved optional calls appropriate member functions");
64 {
65 auto ptr = makePtr();
66 Optional<Ptr> original (ptr);
67 expect (ptr.use_count() == 2);
68 auto other = std::move (original);
69 // A moved-from optional still contains a value!
70 expect (original.hasValue());
71 expect (other.hasValue());
72 expect (ptr.use_count() == 2);
73 }
74
75 beginTest ("Moving an empty optional to a populated one destroys the instance");
76 {
77 auto ptr = makePtr();
78 Optional<Ptr> original (ptr);
79 expect (ptr.use_count() == 2);
80 original = Optional<Ptr>();
81 expect (ptr.use_count() == 1);
82 }
83
84 beginTest ("Copying an empty optional to a populated one destroys the instance");
85 {
86 auto ptr = makePtr();
87 Optional<Ptr> original (ptr);
88 expect (ptr.use_count() == 2);
89 Optional<Ptr> empty;
90 original = empty;
91 expect (ptr.use_count() == 1);
92 }
93
94 beginTest ("Moving a populated optional calls appropriate member functions");
95 {
96 auto a = makePtr();
97 auto b = makePtr();
98
99 Optional<Ptr> aOpt (a);
100 Optional<Ptr> bOpt (b);
101
102 expect (a.use_count() == 2);
103 expect (b.use_count() == 2);
104
105 aOpt = std::move (bOpt);
106
107 expect (aOpt.hasValue());
108 expect (bOpt.hasValue());
109
110 expect (a.use_count() == 1);
111 expect (b.use_count() == 2);
112 }
113
114 beginTest ("Copying a populated optional calls appropriate member functions");
115 {
116 auto a = makePtr();
117 auto b = makePtr();
118
119 Optional<Ptr> aOpt (a);
120 Optional<Ptr> bOpt (b);
121
122 expect (a.use_count() == 2);
123 expect (b.use_count() == 2);
124
125 aOpt = bOpt;
126
127 expect (aOpt.hasValue());
128 expect (bOpt.hasValue());
129
130 expect (a.use_count() == 1);
131 expect (b.use_count() == 3);
132 }
133
134 beginTest ("Moving an empty optional to an empty one does nothing");
135 {
136 Optional<Ptr> original;
137 original = Optional<Ptr>();
138 expect (! original.hasValue());
139 }
140
141 beginTest ("Copying an empty optional to an empty one does nothing");
142 {
143 Optional<Ptr> original;
144 Optional<Ptr> empty;
145 original = empty;
146 expect (! original.hasValue());
147 expect (! empty.hasValue());
148 }
149
150 beginTest ("Moving a populated optional calls appropriate member functions");
151 {
152 auto a = makePtr();
153
154 Optional<Ptr> aOpt (a);
155 Optional<Ptr> empty;
156
157 expect (a.use_count() == 2);
158
159 empty = std::move (aOpt);
160
161 expect (empty.hasValue());
162 expect (aOpt.hasValue());
163
164 expect (a.use_count() == 2);
165 }
166
167 beginTest ("Copying a populated optional calls appropriate member functions");
168 {
169 auto a = makePtr();
170
171 Optional<Ptr> aOpt (a);
172 Optional<Ptr> empty;
173
174 expect (a.use_count() == 2);
175
176 empty = aOpt;
177
178 expect (aOpt.hasValue());
179 expect (empty.hasValue());
180
181 expect (a.use_count() == 3);
182 }
183
184 struct ThrowOnCopy
185 {
186 ThrowOnCopy() = default;
187
188 // Put into an invalid state and throw
189 ThrowOnCopy (const ThrowOnCopy&)
190 {
191 value = -100;
192 throw std::bad_alloc{};
193 }
194
195 // Put into an invalid state and throw
196 ThrowOnCopy& operator= (const ThrowOnCopy&)
197 {
198 value = -100;
199 throw std::bad_alloc{};
200 }
201
202 ThrowOnCopy (ThrowOnCopy&&) noexcept = default;
203 ThrowOnCopy& operator= (ThrowOnCopy&&) noexcept = default;
204
205 ~ThrowOnCopy() = default;
206
207 int value = 0;
208 };
209
210 beginTest ("Strong exception safety is maintained when forwarding over empty object");
211 {
212 bool threw = false;
213 Optional<ThrowOnCopy> a;
214
215 try
216 {
217 ThrowOnCopy t;
218 a = t;
219 }
220 catch (const std::bad_alloc&)
221 {
222 threw = true;
223 }
224
225 expect (threw);
226 expect (! a.hasValue()); // If construction failed, this object should still be well-formed but empty
227 }
228
229 beginTest ("Weak exception safety is maintained when forwarding over populated object");
230 {
231 bool threw = false;
232 Optional<ThrowOnCopy> a = ThrowOnCopy();
233 a->value = 5;
234
235 try
236 {
237 ThrowOnCopy t;
238 a = t;
239 }
240 catch (const std::bad_alloc&)
241 {
242 threw = true;
243 }
244
245 expect (threw);
246 expect (a.hasValue());
247 expect (a->value == -100); // If we assign to an extant object, it's up to that object to provide an exception guarantee
248 }
249
250 beginTest ("Strong exception safety is maintained when copying over empty object");
251 {
252 bool threw = false;
253 Optional<ThrowOnCopy> a;
254
255 try
256 {
257 Optional<ThrowOnCopy> t = ThrowOnCopy{};
258 a = t;
259 }
260 catch (const std::bad_alloc&)
261 {
262 threw = true;
263 }
264
265 expect (threw);
266 expect (! a.hasValue());
267 }
268
269 beginTest ("Exception safety of contained type is maintained when copying over populated object");
270 {
271 bool threw = false;
272 Optional<ThrowOnCopy> a = ThrowOnCopy();
273 a->value = 5;
274
275 try
276 {
277 Optional<ThrowOnCopy> t = ThrowOnCopy{};
278 a = t;
279 }
280 catch (const std::bad_alloc&)
281 {
282 threw = true;
283 }
284
285 expect (threw);
286 expect (a.hasValue());
287 expect (a->value == -100);
288 }
289
290 beginTest ("Assigning from nullopt clears the instance");
291 {
292 auto ptr = makePtr();
293 Optional<Ptr> a (ptr);
294 expect (ptr.use_count() == 2);
295 a = nullopt;
296 expect (ptr.use_count() == 1);
297 }
298
299 struct Foo {};
300 struct Bar final : public Foo {};
301
302 beginTest ("Can be constructed from compatible type");
303 {
304 Optional<std::shared_ptr<Foo>> opt { std::make_shared<Bar>() };
305 }
306
307 beginTest ("Can be assigned from compatible type");
308 {
309 Optional<std::shared_ptr<Foo>> opt;
310 opt = std::make_shared<Bar>();
311 }
312
313 beginTest ("Can copy from compatible type");
314 {
315 auto ptr = std::make_shared<Bar>();
316 Optional<std::shared_ptr<Bar>> bar (ptr);
317 Optional<std::shared_ptr<Foo>> foo (bar);
318 expect (ptr.use_count() == 3);
319 }
320
321 beginTest ("Can move from compatible type");
322 {
323 auto ptr = std::make_shared<Bar>();
324 Optional<std::shared_ptr<Foo>> foo (Optional<std::shared_ptr<Bar>> { ptr });
325 expect (ptr.use_count() == 2);
326 }
327
328 beginTest ("Can copy assign from compatible type");
329 {
330 auto ptr = std::make_shared<Bar>();
331 Optional<std::shared_ptr<Bar>> bar (ptr);
332 Optional<std::shared_ptr<Foo>> foo;
333 foo = bar;
334 expect (ptr.use_count() == 3);
335 }
336
337 beginTest ("Can move assign from compatible type");
338 {
339 auto ptr = std::make_shared<Bar>();
340 Optional<std::shared_ptr<Foo>> foo;
341 foo = Optional<std::shared_ptr<Bar>> (ptr);
342 expect (ptr.use_count() == 2);
343 }
344
345 beginTest ("An exception thrown during emplace leaves the optional without a value");
346 {
347 Optional<ThrowOnCopy> opt { ThrowOnCopy{} };
348 bool threw = false;
349
350 try
351 {
352 ThrowOnCopy t;
353 opt.emplace (t);
354 }
355 catch (const std::bad_alloc&)
356 {
357 threw = true;
358 }
359
360 expect (threw);
361 expect (! opt.hasValue());
362 }
363
364 beginTest ("Swap does nothing to two empty optionals");
365 {
366 Optional<Ptr> a, b;
367 expect (! a.hasValue());
368 expect (! b.hasValue());
369
370 a.swap (b);
371
372 expect (! a.hasValue());
373 expect (! b.hasValue());
374 }
375
376 beginTest ("Swap transfers ownership if one optional contains a value");
377 {
378 {
379 Ptr ptr = makePtr();
380 Optional<Ptr> a, b = ptr;
381 expect (! a.hasValue());
382 expect (b.hasValue());
383 expect (ptr.use_count() == 2);
384
385 a.swap (b);
386
387 expect (a.hasValue());
388 expect (! b.hasValue());
389 expect (ptr.use_count() == 2);
390 }
391
392 {
393 auto ptr = makePtr();
394 Optional<Ptr> a = ptr, b;
395 expect (a.hasValue());
396 expect (! b.hasValue());
397 expect (ptr.use_count() == 2);
398
399 a.swap (b);
400
401 expect (! a.hasValue());
402 expect (b.hasValue());
403 expect (ptr.use_count() == 2);
404 }
405 }
406
407 beginTest ("Swap calls std::swap to swap two populated optionals");
408 {
409 auto x = makePtr(), y = makePtr();
410 Optional<Ptr> a = x, b = y;
411 expect (a.hasValue());
412 expect (b.hasValue());
413 expect (x.use_count() == 2);
414 expect (y.use_count() == 2);
415 expect (*a == x);
416 expect (*b == y);
417
418 a.swap (b);
419
420 expect (a.hasValue());
421 expect (b.hasValue());
422 expect (x.use_count() == 2);
423 expect (y.use_count() == 2);
424 expect (*a == y);
425 expect (*b == x);
426 }
427
428 beginTest ("An exception thrown during a swap leaves both objects in the previous populated state");
429 {
430 {
431 Optional<ThrowOnMoveOrSwap> a, b;
432 a.emplace();
433
434 expect (a.hasValue());
435 expect (! b.hasValue());
436
437 bool threw = false;
438
439 try
440 {
441 a.swap (b);
442 }
443 catch (const std::bad_alloc&)
444 {
445 threw = true;
446 }
447
448 expect (threw);
449 expect (a.hasValue());
450 expect (! b.hasValue());
451 }
452
453 {
454 Optional<ThrowOnMoveOrSwap> a, b;
455 b.emplace();
456
457 expect (! a.hasValue());
458 expect (b.hasValue());
459
460 bool threw = false;
461
462 try
463 {
464 a.swap (b);
465 }
466 catch (const std::bad_alloc&)
467 {
468 threw = true;
469 }
470
471 expect (threw);
472 expect (! a.hasValue());
473 expect (b.hasValue());
474 }
475
476 {
477 Optional<ThrowOnMoveOrSwap> a, b;
478 a.emplace();
479 b.emplace();
480
481 expect (a.hasValue());
482 expect (b.hasValue());
483
484 bool threw = false;
485
486 try
487 {
488 a.swap (b);
489 }
490 catch (const std::bad_alloc&)
491 {
492 threw = true;
493 }
494
495 expect (threw);
496 expect (a.hasValue());
497 expect (b.hasValue());
498 }
499 }
500
501 beginTest ("Relational tests");
502 {
503 expect (Optional<int> (1) == Optional<int> (1));
504 expect (Optional<int>() == Optional<int>());
505 expect (! (Optional<int> (1) == Optional<int>()));
506 expect (! (Optional<int>() == Optional<int> (1)));
507 expect (! (Optional<int> (1) == Optional<int> (2)));
508
509 expect (Optional<int> (1) != Optional<int> (2));
510 expect (! (Optional<int>() != Optional<int>()));
511 expect (Optional<int> (1) != Optional<int>());
512 expect (Optional<int>() != Optional<int> (1));
513 expect (! (Optional<int> (1) != Optional<int> (1)));
514
515 expect (Optional<int>() < Optional<int> (1));
516 expect (! (Optional<int> (1) < Optional<int>()));
517 expect (! (Optional<int>() < Optional<int>()));
518 expect (Optional<int> (1) < Optional<int> (2));
519
520 expect (Optional<int>() <= Optional<int> (1));
521 expect (! (Optional<int> (1) <= Optional<int>()));
522 expect (Optional<int>() <= Optional<int>());
523 expect (Optional<int> (1) <= Optional<int> (2));
524
525 expect (! (Optional<int>() > Optional<int> (1)));
526 expect (Optional<int> (1) > Optional<int>());
527 expect (! (Optional<int>() > Optional<int>()));
528 expect (! (Optional<int> (1) > Optional<int> (2)));
529
530 expect (! (Optional<int>() >= Optional<int> (1)));
531 expect (Optional<int> (1) >= Optional<int>());
532 expect (Optional<int>() >= Optional<int>());
533 expect (! (Optional<int> (1) >= Optional<int> (2)));
534
535 expect (Optional<int>() == nullopt);
536 expect (! (Optional<int> (1) == nullopt));
537 expect (nullopt == Optional<int>());
538 expect (! (nullopt == Optional<int> (1)));
539
540 expect (! (Optional<int>() != nullopt));
541 expect (Optional<int> (1) != nullopt);
542 expect (! (nullopt != Optional<int>()));
543 expect (nullopt != Optional<int> (1));
544
545 expect (! (Optional<int>() < nullopt));
546 expect (! (Optional<int> (1) < nullopt));
547
548 expect (! (nullopt < Optional<int>()));
549 expect (nullopt < Optional<int> (1));
550
551 expect (Optional<int>() <= nullopt);
552 expect (! (Optional<int> (1) <= nullopt));
553
554 expect (nullopt <= Optional<int>());
555 expect (nullopt <= Optional<int> (1));
556
557 expect (! (Optional<int>() > nullopt));
558 expect (Optional<int> (1) > nullopt);
559
560 expect (! (nullopt > Optional<int>()));
561 expect (! (nullopt > Optional<int> (1)));
562
563 expect (Optional<int>() >= nullopt);
564 expect (Optional<int> (1) >= nullopt);
565
566 expect (nullopt >= Optional<int>());
567 expect (! (nullopt >= Optional<int> (1)));
568
569 expect (! (Optional<int>() == 5));
570 expect (! (Optional<int> (1) == 5));
571 expect (Optional<int> (1) == 1);
572 expect (! (5 == Optional<int>()));
573 expect (! (5 == Optional<int> (1)));
574 expect (1 == Optional<int> (1));
575
576 expect (Optional<int>() != 5);
577 expect (Optional<int> (1) != 5);
578 expect (! (Optional<int> (1) != 1));
579 expect (5 != Optional<int>());
580 expect (5 != Optional<int> (1));
581 expect (! (1 != Optional<int> (1)));
582
583 expect (Optional<int>() < 5);
584 expect (Optional<int> (1) < 5);
585 expect (! (Optional<int> (1) < 1));
586 expect (! (Optional<int> (1) < 0));
587
588 expect (! (5 < Optional<int>()));
589 expect (! (5 < Optional<int> (1)));
590 expect (! (1 < Optional<int> (1)));
591 expect (0 < Optional<int> (1));
592
593 expect (Optional<int>() <= 5);
594 expect (Optional<int> (1) <= 5);
595 expect (Optional<int> (1) <= 1);
596 expect (! (Optional<int> (1) <= 0));
597
598 expect (! (5 <= Optional<int>()));
599 expect (! (5 <= Optional<int> (1)));
600 expect (1 <= Optional<int> (1));
601 expect (0 <= Optional<int> (1));
602
603 expect (! (Optional<int>() > 5));
604 expect (! (Optional<int> (1) > 5));
605 expect (! (Optional<int> (1) > 1));
606 expect (Optional<int> (1) > 0);
607
608 expect (5 > Optional<int>());
609 expect (5 > Optional<int> (1));
610 expect (! (1 > Optional<int> (1)));
611 expect (! (0 > Optional<int> (1)));
612
613 expect (! (Optional<int>() >= 5));
614 expect (! (Optional<int> (1) >= 5));
615 expect (Optional<int> (1) >= 1);
616 expect (Optional<int> (1) >= 0);
617
618 expect (5 >= Optional<int>());
619 expect (5 >= Optional<int> (1));
620 expect (1 >= Optional<int> (1));
621 expect (! (0 >= Optional<int> (1)));
622 }
623 }
624};
625
626static OptionalUnitTest optionalUnitTest;
627
628} // namespace juce
void expectEquals(ValueType actual, ValueType expected, String failureMessage=String())
UnitTest(const String &name, const String &category=String())
void beginTest(const String &testName)
void expect(bool testResult, const String &failureMessage=String())
virtual void runTest()=0