OpenShot Audio Library | OpenShotAudio  0.6.0
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 
23 namespace juce
24 {
25 
26 /* Not nested, so that ADL works for the swap function. */
27 struct ThrowOnMoveOrSwap
28 {
29  ThrowOnMoveOrSwap() = default;
30  ThrowOnMoveOrSwap (ThrowOnMoveOrSwap&&) { throw std::bad_alloc{}; }
31 };
32 static void swap (ThrowOnMoveOrSwap&, ThrowOnMoveOrSwap&) { throw std::bad_alloc{}; }
33 
34 class OptionalUnitTest final : public UnitTest
35 {
36 public:
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 
626 static 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())