Unravel Engine C++ Reference
Loading...
Searching...
No Matches
tests.cpp
Go to the documentation of this file.
1#include "tests.h"
2#include "tests_helper.h"
4#include <seq/seq.h>
5#include <suitepp/suite.hpp>
6
7namespace seq
8{
9
12
13inline void seq_update(seq::duration_t duration)
14{
15 // test update with 0
16 seq::update(seq::duration_t::zero());
17 auto step = duration / SEQ_UPDATE_STEP_COUNT;
18 for(int i = 0; i < SEQ_UPDATE_STEP_COUNT; ++i)
19 {
20 seq::update(step);
21 }
22}
23
24template<typename T>
26{
27 values_t() = default;
28 values_t(T val, bool use_shared)
29 {
30 ptr = std::make_shared<T>(val);
31 value = val;
32 sentinel = std::make_shared<T>(val);
33 ;
34 use_shared_ptr = use_shared;
35 }
37 {
38 return use_shared_ptr ? *ptr : value;
39 }
40
41 const T& get_value() const
42 {
43 return use_shared_ptr ? *ptr : value;
44 }
45
47 {
48 use_shared_ptr ? ptr.reset() : sentinel.reset();
49 }
50
51 bool sentinel_expired() const
52 {
53 return use_shared_ptr ? ptr == nullptr : sentinel == nullptr;
54 }
55
56 std::shared_ptr<T> ptr{};
57 T value{};
58 std::shared_ptr<void> sentinel{};
60};
61
62template<typename T>
64 seq::duration_t duration,
65 bool step_update,
66 const values_t<T>& values,
67 const T& begin,
68 const T& end)
69{
70 THEN("the action should be valid")
71 {
72 REQUIRE(action.is_valid());
73 };
74
75 WHEN("the action is paused before starting")
76 {
77 // pause before starting should do nothing
78 REQUIRE_NOTHROWS(seq::pause(action));
79 };
80
81 THEN("it should not be paused")
82 {
83 REQUIRE(!seq::is_paused(action));
84 };
85
86 WHEN("the action is resumed before starting")
87 {
88 REQUIRE_NOTHROWS(seq::resume(action));
89 };
90
91 THEN("it should not be running")
92 {
93 REQUIRE(!seq::is_running(action));
94 };
95
96 AND_WHEN("the action action is started")
97 {
98 REQUIRE_NOTHROWS(seq::start(action));
99 };
100
101 THEN("if the actiony is running")
102 {
103 // pause after starting successfully should work just fine
104 if(seq::is_running(action))
105 {
106 REQUIRE_NOTHROWS(seq::set_speed_multiplier(action, 10.0f));
107 REQUIRE(int(seq::get_speed_multiplier(action)) == int(10.0f));
108 REQUIRE(seq::get_duration(action) > 0s);
109 REQUIRE(seq::get_elapsed(action) == 0s);
110
111 REQUIRE_NOTHROWS(seq::pause(action));
112 REQUIRE(seq::is_paused(action));
113
114 REQUIRE_NOTHROWS(seq::resume(action));
115 REQUIRE(seq::is_running(action));
116 REQUIRE(!seq::is_finished(action));
117 }
118 };
119
120 WHEN("'stop_when_finished' is called")
121 {
122 REQUIRE_NOTHROWS(seq::stop_when_finished(action));
123 };
124 THEN("the action is 'stopping'")
125 {
126 REQUIRE(seq::is_stopping(action));
127 };
128
129 if(duration > 0s)
130 {
131 if(!values.sentinel_expired())
132 {
133 if(seq::is_running(action))
134 {
135 WHEN("duration > 0 and the sentinel is NOT expierd and the action is running"){};
136 AND_WHEN("the sentinel is NOT expierd"){};
137 AND_WHEN("the action is running"){};
138 THEN("the object should be equal to the begin value")
139 {
140 auto result = helper::compare(values.get_value(), begin);
141 if(!result)
142 {
143 REQUIRE(values.get_value() == begin);
144 }
145 };
146 }
147 }
148 }
149
150 if(step_update)
151 {
152 WHEN("'update' is called")
153 {
154 REQUIRE_NOTHROWS(seq_update(duration));
155 };
156 }
157 else
158 {
159 WHEN("'stop_and_finish' is called")
160 {
161 REQUIRE_NOTHROWS(seq::stop_and_finish(action));
162 };
163 }
164
165 THEN("there should be no lingering actions internally")
166 {
167 REQUIRE_NOTHROWS(seq::detail::get_manager().get_actions().empty());
168 };
169
170 if(duration > 0s && seq::get_elapsed(action) >= duration)
171 {
172 if(!values.sentinel_expired())
173 {
174 WHEN("duration > 0 and the action actually finished its duration"){
175
176 };
177
178 AND_WHEN("the sentinel is not expired"){
179
180 };
181
182 THEN("the object should be equal to the end value")
183 {
184 auto result = helper::compare(values.get_value(), end);
185 if(!result)
186 {
187 REQUIRE(values.get_value() == end);
188 }
189 };
190 }
191 }
192}
193
194template<typename T>
195seq::seq_action creator(const std::string& type, values_t<T>& values, T& begin, const T& end, seq::duration_t duration)
196{
197 if(type == "seq_from_to")
198 {
199 if(values.use_shared_ptr)
200 {
201 return seq::change_from_to(values.ptr, begin, end, duration, EASING);
202 }
203 return seq::change_from_to(values.value, begin, end, duration, values.sentinel, EASING);
204 }
205
206 if(type == "seq_to")
207 {
208 if(!values.sentinel_expired())
209 {
210 begin = values.get_value();
211 }
212
213 if(values.use_shared_ptr)
214 {
215 return seq::change_to(values.ptr, end, duration, EASING);
216 }
217 return seq::change_to(values.value, end, duration, values.sentinel, EASING);
218 }
219
220 if(type == "seq_by")
221 {
222 if(!values.sentinel_expired())
223 {
224 begin = values.get_value();
225 }
226
227 if(values.use_shared_ptr)
228 {
229 return seq::change_by(values.ptr, end, duration, EASING);
230 }
231 return seq::change_by(values.value, end, duration, values.sentinel, EASING);
232 }
233
234 return {};
235}
236template<typename T>
237void scenario(bool use_shared_ptr,
238 bool step_update,
239 const std::string& type,
240 seq::duration_t duration,
241 T begin,
242 T end,
243 T object_value)
244{
245 {
246 auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(duration);
247 auto record_input = [&]()
248 {
249 GIVEN("object == " + suite::helper::to_string(object_value)){};
250 GIVEN("begin == " + suite::helper::to_string(begin)){};
251 GIVEN("end == " + suite::helper::to_string(end)){};
252 GIVEN("duration == " + suite::helper::to_string(duration_ms) + "ms"){};
253 GIVEN("step_update == " + suite::helper::to_string(step_update)){};
254 };
255
256 SCENARIO("a valid sentinel is passed")
257 {
258 record_input();
259
260 values_t<T> values;
261 GIVEN("a valid object and a valid sentinel")
262 {
263 values = values_t<T>(object_value, use_shared_ptr);
264 };
265
266 seq::seq_action action{};
267 WHEN("the action action is created")
268 {
269 action = creator(type, values, begin, end, duration);
270 };
271
272 core_seq_test_impl(action, duration, step_update, values, begin, end);
273
274 THEN("the action should finish successfully")
275 {
276 REQUIRE(seq::is_finished(action));
277 };
278 };
279
280 SCENARIO("an invalid sentinel is passed")
281 {
282 record_input();
283
284 values_t<T> values;
285 GIVEN("a valid object and an invalid sentinel")
286 {
287 values = values_t<T>(object_value, use_shared_ptr);
288 values.sentinel_reset();
289 };
290
291 seq::seq_action action{};
292 WHEN("the action action is created")
293 {
294 action = creator(type, values, begin, end, duration);
295 };
296
297 THEN("the action should not be valid")
298 {
299 REQUIRE(!action.is_valid());
300 };
301 };
302
303 SCENARIO("the 'on_begin' callback expires the sentinel")
304 {
305 record_input();
306
307 values_t<T> values;
308 GIVEN("a valid object and a valid sentinel")
309 {
310 values = values_t<T>(object_value, use_shared_ptr);
311 };
312
313 seq::seq_action action{};
314 WHEN("the action action is created")
315 {
316 action = creator(type, values, begin, end, duration);
317 };
318
319 AND_WHEN("an 'on_begin' callback is connected")
320 {
321 action.on_begin.connect(
322 [&values]()
323 {
324 values.sentinel_reset();
325 });
326 };
327
328 core_seq_test_impl(action, duration, step_update, values, begin, end);
329
330 THEN("the action should be finished and the sentinel should be expired")
331 {
332 REQUIRE(seq::is_finished(action));
333 REQUIRE(values.sentinel_expired());
334 };
335 };
336
337 SCENARIO("the 'on_begin' callback calls 'stop'")
338 {
339 record_input();
340
341 values_t<T> values;
342 GIVEN("a valid object and a valid sentinel")
343 {
344 values = values_t<T>(object_value, use_shared_ptr);
345 };
346
347 seq::seq_action action{};
348 WHEN("the action action is created")
349 {
350 action = creator(type, values, begin, end, duration);
351 };
352 AND_WHEN("an 'on_begin' callback is connected")
353 {
354 action.on_begin.connect(
355 [&action]()
356 {
357 REQUIRE_NOTHROWS(seq::stop(action));
358 });
359 };
360
361 core_seq_test_impl(action, duration, step_update, values, begin, end);
362
363 THEN("the action should finish successfully")
364 {
365 REQUIRE(seq::is_finished(action));
366 };
367 };
368
369 SCENARIO("the 'on_begin' callback calls 'stop_and_finish'")
370 {
371 record_input();
372
373 values_t<T> values;
374 GIVEN("a valid object and a valid sentinel")
375 {
376 values = values_t<T>(object_value, use_shared_ptr);
377 };
378
379 seq::seq_action action{};
380 WHEN("the action action is created")
381 {
382 action = creator(type, values, begin, end, duration);
383 };
384
385 AND_WHEN("an 'on_begin' callback is connected")
386 {
387 action.on_begin.connect(
388 [&action]()
389 {
390 REQUIRE_NOTHROWS(seq::stop_and_finish(action));
391 });
392 };
393
394 core_seq_test_impl(action, duration, step_update, values, begin, end);
395
396 THEN("the action should finish successfully")
397 {
398 REQUIRE(seq::is_finished(action));
399 };
400 };
401
402 SCENARIO("the 'on_begin' callback calls 'pause'")
403 {
404 record_input();
405
406 values_t<T> values;
407 GIVEN("a valid object and a valid sentinel")
408 {
409 values = values_t<T>(object_value, use_shared_ptr);
410 };
411
412 seq::seq_action action{};
413 WHEN("the action action is created")
414 {
415 action = creator(type, values, begin, end, duration);
416 };
417 AND_WHEN("an 'on_begin' callback is connected")
418 {
419 action.on_begin.connect(
420 [&action]()
421 {
422 REQUIRE_NOTHROWS(seq::pause(action));
423 });
424 };
425
426 core_seq_test_impl(action, duration, step_update, values, begin, end);
427
428 if(step_update)
429 {
430 THEN("the action should be paused")
431 {
432 REQUIRE(seq::is_paused(action));
433 };
434 }
435 else
436 {
437 THEN("the action should be finished")
438 {
439 REQUIRE(seq::is_finished(action));
440 };
441 }
442 };
443
444 SCENARIO("the 'on_update' callback expires the sentinel")
445 {
446 record_input();
447
448 values_t<T> values;
449 GIVEN("a valid object and a valid sentinel")
450 {
451 values = values_t<T>(object_value, use_shared_ptr);
452 };
453
454 seq::seq_action action{};
455 WHEN("the action action is created")
456 {
457 action = creator(type, values, begin, end, duration);
458 };
459 bool is_sentinel_reset_requested = false;
460
461 AND_WHEN("an 'on_update' callback is connected")
462 {
463 action.on_update.connect(
464 [&]()
465 {
466 is_sentinel_reset_requested = true;
467 values.sentinel_reset();
468 });
469 };
470
471 core_seq_test_impl(action, duration, step_update, values, begin, end);
472
473 THEN("the action should be finished")
474 {
475 REQUIRE(seq::is_finished(action));
476 };
477 if(is_sentinel_reset_requested)
478 {
479 REQUIRE(values.sentinel_expired());
480 }
481 };
482
483 SCENARIO("the 'on_update' callback calls 'stop'")
484 {
485 record_input();
486
487 values_t<T> values;
488 GIVEN("a valid object and a valid sentinel")
489 {
490 values = values_t<T>(object_value, use_shared_ptr);
491 };
492
493 seq::seq_action action{};
494 WHEN("the action action is created")
495 {
496 action = creator(type, values, begin, end, duration);
497 };
498 AND_WHEN("an 'on_update' callback is connected")
499 {
500 action.on_update.connect(
501 [&action]()
502 {
503 REQUIRE_NOTHROWS(seq::stop(action));
504 });
505 };
506
507 core_seq_test_impl(action, duration, step_update, values, begin, end);
508
509 THEN("the action should be finished")
510 {
511 REQUIRE(seq::is_finished(action));
512 };
513 };
514
515 SCENARIO("the 'on_update' callback calls 'stop_and_finish'")
516 {
517 record_input();
518
519 values_t<T> values;
520 GIVEN("a valid object and a valid sentinel")
521 {
522 values = values_t<T>(object_value, use_shared_ptr);
523 };
524
525 seq::seq_action action{};
526 WHEN("the action action is created")
527 {
528 action = creator(type, values, begin, end, duration);
529 };
530 AND_WHEN("an 'on_update' callback is connected")
531 {
532 action.on_update.connect(
533 [&action]()
534 {
535 REQUIRE_THROWS_AS(seq::stop_and_finish(action), std::runtime_error);
536 });
537 };
538
539 core_seq_test_impl(action, duration, step_update, values, begin, end);
540
541 THEN("the action should be finished")
542 {
543 REQUIRE(seq::is_finished(action));
544 };
545 };
546
547 SCENARIO("the 'on_update' callback calls 'pause'")
548 {
549 record_input();
550
551 values_t<T> values;
552 GIVEN("a valid object and a valid sentinel")
553 {
554 values = values_t<T>(object_value, use_shared_ptr);
555 };
556
557 seq::seq_action action{};
558 WHEN("the action action is created")
559 {
560 action = creator(type, values, begin, end, duration);
561 };
562 bool is_pause_requested = false;
563 AND_WHEN("an 'on_update' callback is connected")
564 {
565 action.on_update.connect(
566 [&]()
567 {
568 is_pause_requested = true;
569 REQUIRE_NOTHROWS(seq::pause(action));
570 });
571 };
572
573 core_seq_test_impl(action, duration, step_update, values, begin, end);
574
575 if(is_pause_requested && step_update)
576 {
577 THEN("the action should be paused")
578 {
579 REQUIRE(seq::is_paused(action));
580 };
581 }
582 else
583 {
584 THEN("the action should be is_finished")
585 {
586 REQUIRE(seq::is_finished(action));
587 };
588 }
589 };
590
591 SCENARIO("the 'on_step' callback expires the sentinel")
592 {
593 record_input();
594
595 values_t<T> values;
596 GIVEN("a valid object and a valid sentinel")
597 {
598 values = values_t<T>(object_value, use_shared_ptr);
599 };
600
601 seq::seq_action action{};
602 WHEN("the action action is created")
603 {
604 action = creator(type, values, begin, end, duration);
605 };
606
607 bool is_sentinel_reset_requested = false;
608
609 AND_WHEN("an 'on_step' callback is connected")
610 {
611 action.on_step.connect(
612 [&]()
613 {
614 is_sentinel_reset_requested = true;
615 values.sentinel_reset();
616 });
617 };
618
619 core_seq_test_impl(action, duration, step_update, values, begin, end);
620
621 THEN("the action should be is_finished")
622 {
623 REQUIRE(seq::is_finished(action));
624 };
625 if(is_sentinel_reset_requested)
626 {
627 REQUIRE(values.sentinel_expired());
628 }
629 };
630
631 SCENARIO("the 'on_step' callback calls 'stop'")
632 {
633 record_input();
634
635 values_t<T> values;
636 GIVEN("a valid object and a valid sentinel")
637 {
638 values = values_t<T>(object_value, use_shared_ptr);
639 };
640
641 seq::seq_action action{};
642 WHEN("the action action is created")
643 {
644 action = creator(type, values, begin, end, duration);
645 };
646
647 AND_WHEN("an 'on_step' callback is connected")
648 {
649 action.on_step.connect(
650 [&]()
651 {
652 REQUIRE_NOTHROWS(seq::stop(action));
653 });
654 };
655
656 core_seq_test_impl(action, duration, step_update, values, begin, end);
657
658 THEN("the action should be is_finished")
659 {
660 REQUIRE(seq::is_finished(action));
661 };
662 };
663
664 SCENARIO("the 'on_step' callback calls 'stop_and_finish'")
665 {
666 record_input();
667
668 values_t<T> values;
669 GIVEN("a valid object and a valid sentinel")
670 {
671 values = values_t<T>(object_value, use_shared_ptr);
672 };
673
674 seq::seq_action action{};
675 WHEN("the action action is created")
676 {
677 action = creator(type, values, begin, end, duration);
678 };
679 AND_WHEN("an 'on_step' callback is connected")
680 {
681 action.on_step.connect(
682 [&action, counter = 0]() mutable
683 {
684 // first on_step can be called from start();
685 if(counter++ > 0)
686 {
687 REQUIRE_THROWS_AS(seq::stop_and_finish(action), std::runtime_error);
688 }
689 });
690 };
691
692 core_seq_test_impl(action, duration, step_update, values, begin, end);
693
694 THEN("the action should be is_finished")
695 {
696 REQUIRE(seq::is_finished(action));
697 };
698 };
699
700 SCENARIO("the 'on_step' callback calls 'pause'")
701 {
702 record_input();
703
704 values_t<T> values;
705 GIVEN("a valid object and a valid sentinel")
706 {
707 values = values_t<T>(object_value, use_shared_ptr);
708 };
709
710 seq::seq_action action{};
711 WHEN("the action action is created")
712 {
713 action = creator(type, values, begin, end, duration);
714 };
715
716 bool is_pause_requested = false;
717
718 AND_WHEN("an 'on_step' callback is connected")
719 {
720 action.on_step.connect(
721 [&]()
722 {
723 is_pause_requested = true;
724 REQUIRE_NOTHROWS(seq::pause(action));
725 });
726 };
727
728 core_seq_test_impl(action, duration, step_update, values, begin, end);
729
730 if(is_pause_requested && step_update)
731 {
732 THEN("the action should be is_paused")
733 {
734 REQUIRE(seq::is_paused(action));
735 };
736 }
737 else
738 {
739 THEN("the action should be is_finished")
740 {
741 REQUIRE(seq::is_finished(action));
742 };
743 }
744 };
745
746 SCENARIO("the 'on_end' callback expires the sentinel")
747 {
748 record_input();
749
750 values_t<T> values;
751 GIVEN("a valid object and a valid sentinel")
752 {
753 values = values_t<T>(object_value, use_shared_ptr);
754 };
755
756 seq::seq_action action{};
757 WHEN("the action action is created")
758 {
759 action = creator(type, values, begin, end, duration);
760 };
761 bool is_sentinel_reset_requested = false;
762
763 AND_WHEN("an 'on_end' callback is connected")
764 {
765 action.on_end.connect(
766 [&]()
767 {
768 is_sentinel_reset_requested = true;
769 values.sentinel_reset();
770 });
771 };
772
773 core_seq_test_impl(action, duration, step_update, values, begin, end);
774
775 THEN("the action should be is_finished")
776 {
777 REQUIRE(seq::is_finished(action));
778 };
779
780 if(is_sentinel_reset_requested)
781 {
782 REQUIRE(values.sentinel_expired());
783 }
784 };
785
786 SCENARIO("the 'on_end' callback calls 'stop'")
787 {
788 record_input();
789
790 values_t<T> values;
791 GIVEN("a valid object and a valid sentinel")
792 {
793 values = values_t<T>(object_value, use_shared_ptr);
794 };
795
796 seq::seq_action action{};
797 WHEN("the action action is created")
798 {
799 action = creator(type, values, begin, end, duration);
800 };
801
802 AND_WHEN("an 'on_end' callback is connected")
803 {
804 action.on_end.connect(
805 [&action]()
806 {
807 REQUIRE_NOTHROWS(seq::stop(action));
808 });
809 };
810
811 core_seq_test_impl(action, duration, step_update, values, begin, end);
812
813 THEN("the action should be is_finished")
814 {
815 REQUIRE(seq::is_finished(action));
816 };
817 };
818
819 SCENARIO("the 'on_end' callback calls 'stop_and_finish'")
820 {
821 record_input();
822
823 values_t<T> values;
824 GIVEN("a valid object and a valid sentinel")
825 {
826 values = values_t<T>(object_value, use_shared_ptr);
827 };
828
829 seq::seq_action action{};
830 WHEN("the action action is created")
831 {
832 action = creator(type, values, begin, end, duration);
833 };
834 AND_WHEN("an 'on_end' callback is connected")
835 {
836 action.on_end.connect(
837 [&action]()
838 {
839 REQUIRE_NOTHROWS(seq::stop_and_finish(action));
840 });
841 };
842
843 core_seq_test_impl(action, duration, step_update, values, begin, end);
844
845 THEN("the action should be is_finished")
846 {
847 REQUIRE(seq::is_finished(action));
848 };
849 };
850
851 SCENARIO("the 'on_end' callback calls 'pause'")
852 {
853 record_input();
854
855 values_t<T> values;
856 GIVEN("a valid object and a valid sentinel")
857 {
858 values = values_t<T>(object_value, use_shared_ptr);
859 };
860
861 seq::seq_action action{};
862 WHEN("the action action is created")
863 {
864 action = creator(type, values, begin, end, duration);
865 };
866
867 AND_WHEN("an 'on_end' callback is connected")
868 {
869 action.on_end.connect(
870 [&action]()
871 {
872 REQUIRE_NOTHROWS(seq::pause(action));
873 });
874 };
875
876 core_seq_test_impl(action, duration, step_update, values, begin, end);
877
878 THEN("the action should be is_finished")
879 {
880 REQUIRE(seq::is_finished(action));
881 };
882 };
883 };
884}
885
886template<typename T>
887void core_seq_test(const std::string& type,
888 const std::string& easing_type,
889 seq::duration_t duration,
890 T begin,
891 T end,
892 T object_value)
893{
894 TEST_GROUP(type + "<" + seq::inspector::type_to_str(T{}) + "> with easing [" + easing_type + "]")
895 {
896 TEST_GROUP("with a value")
897 {
898 scenario(false, true, type, duration, begin, end, object_value);
899 };
900
901 TEST_GROUP("with a value")
902 {
903 scenario(false, true, type, duration, begin, end, object_value);
904 };
905
906 TEST_GROUP("with a shared_ptr")
907 {
908 scenario(true, true, type, duration, begin, end, object_value);
909 };
910
911 TEST_GROUP("with a shared_ptr")
912 {
913 scenario(true, false, type, duration, begin, end, object_value);
914 };
915 };
916}
917
918template<typename T>
919void run_seq_test(const std::string& type,
920 const std::string& easing_type,
921 const T& begin,
922 const T& end,
923 const T& object)
924{
925 core_seq_test<T>(type, easing_type, helper::random_value(-1000s, -1s), begin, end, object);
926 core_seq_test<T>(type, easing_type, 0s, begin, end, object);
927 core_seq_test<T>(type, easing_type, helper::random_value(1s, 1000s), begin, end, object);
928}
929
931{
932 seq::scope::push("test1");
933 {
934 auto t1 = seq::start(seq::delay(1s));
935 auto t2 = seq::start(seq::delay(1s));
936 seq::scope::pause_all("test1");
937 REQUIRE(seq::is_paused(t1));
938 REQUIRE(seq::is_paused(t2));
939 seq::scope::resume_all("test1");
940 REQUIRE(!seq::is_paused(t1));
941 REQUIRE(!seq::is_paused(t2));
943 REQUIRE(seq::is_finished(t1));
944 REQUIRE(seq::is_finished(t2));
945 }
946
947 {
948 seq::scope::push("test2");
949 auto t1 = seq::start(seq::delay(1s));
950 auto t2 = seq::start(seq::delay(1s));
951 seq::scope::push("test3");
952 auto t3 = seq::start(seq::delay(1s));
953 auto t4 = seq::start(seq::delay(1s));
954
956 REQUIRE(seq::is_finished(t1));
957 REQUIRE(seq::is_finished(t2));
958 REQUIRE(seq::is_finished(t3));
959 REQUIRE(seq::is_finished(t4));
960 }
961
962 REQUIRE(seq::scope::get_current() == "test3");
964 REQUIRE(seq::scope::get_current() == "test2");
965 seq::scope::close("test1");
966 REQUIRE(seq::scope::get_current().empty());
967
968 REQUIRE_THROWS(seq::scope::pop());
969 seq::scope::push("test1");
970 seq::scope::push("test2");
971 seq::scope::push("test3");
972 seq::scope::push("test4");
973 REQUIRE(seq::scope::get_current() == "test4");
975 REQUIRE(seq::scope::get_current() == "test3");
976
977 REQUIRE_THROWS_AS(seq::scope::push("test2"), std::logic_error);
979
980 {
981 // stacked
982 seq::scope::push("test1");
983 seq::scope::push("test2");
984 auto t1 = seq::start(seq::delay(100s), "test3");
985 REQUIRE(seq::scope::get_current() == "test2");
986 REQUIRE(seq::has_action_with_scope("test3"));
988 REQUIRE(seq::is_finished(t1));
989
990 seq_update(1s); // process for actions pending to remove.
991 REQUIRE(!seq::has_action_with_scope("test3"));
992
994 }
995
996 {
997 seq::seq_scope_policy scope_policy;
998 scope_policy.scope = "test3";
1000
1001 seq::scope::push("test1");
1002 seq::scope::push("test2");
1003
1004 auto t1 = seq::start(seq::delay(100s), scope_policy);
1005 REQUIRE(seq::scope::get_current() == "test2");
1006 REQUIRE(seq::has_action_with_scope("test3"));
1008 seq::scope::close("test2");
1009
1010 seq_update(1s); // process for actions pending to remove.
1011
1012 REQUIRE(seq::scope::get_current() == "test1");
1013 REQUIRE(seq::is_running(t1));
1014 REQUIRE(seq::has_action_with_scope("test3"));
1016 }
1017
1018 {
1020 REQUIRE(seq::scope::get_current().empty());
1021 seq::scope::push("test1");
1022 auto t1 = seq::start(seq::delay(100s));
1023 REQUIRE(seq::has_action_with_scope("test1"));
1024
1025 seq::scope::push("test2");
1026 auto t2 = seq::start(seq::delay(100s));
1027 REQUIRE(seq::has_action_with_scope("test2"));
1028
1029 seq::scope::push("test3");
1030 auto t3 = seq::start(seq::delay(100s));
1031 REQUIRE(seq::has_action_with_scope("test3"));
1032
1033 seq::scope::push("test4");
1034 auto t4 = seq::start(seq::delay(100s));
1035 REQUIRE(seq::has_action_with_scope("test4"));
1036
1038 REQUIRE(seq::scope::get_current() == "test3");
1039 seq::scope::stop_all("test1");
1040
1041 seq_update(1s); // process for actions pending to remove.
1042
1043 REQUIRE(!seq::has_action_with_scope("test1"));
1044 REQUIRE(!seq::has_action_with_scope("test2"));
1045 REQUIRE(!seq::has_action_with_scope("test3"));
1046 REQUIRE(!seq::has_action_with_scope("test4"));
1047 }
1048
1049 {
1051 REQUIRE(seq::scope::get_current().empty());
1052
1053 seq::scope::push("test1");
1054 auto t1 = seq::start(seq::delay(100s));
1055 REQUIRE(seq::has_action_with_scope("test1"));
1056
1057 seq::scope::push("test2");
1058 auto t2 = seq::start(seq::delay(100s));
1059 REQUIRE(seq::has_action_with_scope("test2"));
1060
1061 seq::scope::push("test3");
1062 auto t3 = seq::start(seq::delay(100s));
1063 REQUIRE(seq::has_action_with_scope("test3"));
1064
1065 seq::scope::push("test4");
1066 auto t4 = seq::start(seq::delay(100s));
1067 REQUIRE(seq::has_action_with_scope("test4"));
1068
1069 seq::scope::pause_all("test1", "KEY");
1070 REQUIRE(seq::is_paused(t1));
1071 REQUIRE(seq::is_paused(t2));
1072 REQUIRE(seq::is_paused(t3));
1073 REQUIRE(seq::is_paused(t4));
1074
1075 seq::resume(t1);
1076 REQUIRE(seq::is_paused(t1));
1077 seq::resume(t2);
1078 REQUIRE(seq::is_paused(t2));
1079 seq::resume(t3);
1080 REQUIRE(seq::is_paused(t3));
1081 seq::resume(t4);
1082 REQUIRE(seq::is_paused(t4));
1083
1084 seq::scope::resume_all("test1", "KEY");
1085
1086 REQUIRE(!seq::is_paused(t1));
1087 REQUIRE(!seq::is_paused(t2));
1088 REQUIRE(!seq::is_paused(t3));
1089 REQUIRE(!seq::is_paused(t4));
1090 }
1091}
1092
1093void run(bool use_random_inputs)
1094{
1095 // suite::get_test_label_matcher() = "*[155724]";
1096 const auto& ease_list = ease::get_ease_list();
1097 // for(const auto& kvp : ease_list)
1098 {
1099 const auto& kvp = ease_list.front();
1100 const auto& easing_type = kvp.first;
1101 EASING = kvp.second;
1102
1103 hpp::for_each_type<uint8_t, // uint16_t, uint32_t, uint64_t,
1104 int8_t, // int16_t, int32_t, int64_t,
1105 float //, double
1106 >(
1107 [&](const auto& el)
1108 {
1109 using T = typename std::decay_t<decltype(el)>::type;
1110
1111 auto object = helper::random_value<T>();
1112 auto begin = std::numeric_limits<T>::min() / 2;
1113 auto end = std::numeric_limits<T>::max() / 2;
1114
1115 if(use_random_inputs)
1116 {
1117 begin = helper::random_value<T>();
1119 }
1120
1121 run_seq_test<T>("seq_from_to", easing_type, begin, end, object);
1122 run_seq_test<T>("seq_to", easing_type, begin, end, object);
1123 run_seq_test<T>("seq_by", easing_type, begin, end, {});
1124 });
1125 }
1126 test_scopes();
1127}
1128
1129} // namespace seq
manifold_type type
T random_value()
auto compare(const T &a, const T &b) -> bool
auto get_manager() -> seq_manager &
float linear(float progress)
Definition seq_ease.cpp:292
const std::vector< std::pair< std::string, std::function< float(float)> > > & get_ease_list()
Definition seq_ease.cpp:535
auto type_to_str(const T &t) -> std::string
Gets the type of a value as a string using ADL.
Definition seq_common.h:311
void pause_all(const std::string &scope)
Pauses all actions within the specified scope.
Definition seq.cpp:159
void push(const std::string &scope)
Pushes a new scope to the stack.
Definition seq.cpp:129
void stop_all(const std::string &scope)
Stops all actions within the specified scope.
Definition seq.cpp:154
auto get_current() -> const std::string &
Gets the name of the current scope.
Definition seq.cpp:149
void pop()
Pops the current scope from the stack.
Definition seq.cpp:134
void close(const std::string &scope)
Closes the specified scope.
Definition seq.cpp:139
void clear()
Clears all scopes from the stack.
Definition seq.cpp:144
void resume_all(const std::string &scope)
Resumes all actions within the specified scope.
Definition seq.cpp:164
void stop_and_finish_all(const std::string &scope)
Stops and finishes all actions within the specified scope.
Definition seq.cpp:179
Provides a sequence-based action management system for controlling and scheduling actions.
void run_seq_test(const std::string &type, const std::string &easing_type, const T &begin, const T &end, const T &object)
Definition tests.cpp:919
void update(seq_id_t id, duration_t delta)
Updates the elapsed duration of a specific action.
Definition seq.cpp:94
auto is_finished(seq_id_t id) -> bool
Checks if the action has finished.
Definition seq.cpp:54
auto is_paused(seq_id_t id) -> bool
Checks if the action is paused.
Definition seq.cpp:49
void resume(const seq_id_t id)
Resumes the action associated with the given ID.
Definition seq.cpp:24
seq::seq_action creator(const std::string &type, values_t< T > &values, T &begin, const T &end, seq::duration_t duration)
Definition tests.cpp:195
auto start(seq_action action, const seq_scope_policy &scope_policy, hpp::source_location location) -> seq_id_t
Starts a new action.
Definition seq.cpp:8
auto get_duration(seq_id_t id) -> duration_t
Gets the total duration of an action.
Definition seq.cpp:84
void core_seq_test(const std::string &type, const std::string &easing_type, seq::duration_t duration, T begin, T end, T object_value)
Definition tests.cpp:887
void stop_and_finish(seq_id_t id, duration_t finish_after)
Stops the action after a specified duration.
Definition seq.cpp:34
auto is_running(seq_id_t id) -> bool
Checks if the action is running.
Definition seq.cpp:44
std::function< float(float)> ease_t
Represents an easing function for interpolation.
Definition seq_common.h:61
void run(bool use_random_inputs)
Definition tests.cpp:1093
auto change_by(T &object, const std::decay_t< T > &amount, const duration_t &duration, const sentinel_t &sentinel, const ease_t &ease_func=ease::linear) -> seq_action
Creates an action to change an object by a specified amount over a specified duration.
Definition seq_core.hpp:139
void set_speed_multiplier(seq_id_t id, float speed_multiplier)
Sets the speed multiplier for an action.
Definition seq.cpp:64
int SEQ_UPDATE_STEP_COUNT
Definition tests.cpp:10
auto is_stopping(seq_id_t id) -> bool
Checks if the action is stopping.
Definition seq.cpp:39
auto get_speed_multiplier(seq_id_t id) -> float
Gets the speed multiplier of an action.
Definition seq.cpp:69
void core_seq_test_impl(seq::seq_action &action, seq::duration_t duration, bool step_update, const values_t< T > &values, const T &begin, const T &end)
Definition tests.cpp:63
auto get_elapsed(seq_id_t id) -> duration_t
Gets the elapsed duration of an action.
Definition seq.cpp:74
void stop_when_finished(seq_id_t id)
Marks the action to stop when it finishes.
Definition seq.cpp:29
auto delay(const duration_t &duration, const sentinel_t &sentinel) -> seq_action
Creates a delay action.
Definition seq_core.cpp:182
seq::ease_t EASING
Definition tests.cpp:11
auto has_action_with_scope(const std::string &scope_id) -> bool
Checks if there is an action associated with the given scope ID.
Definition seq.cpp:59
auto change_from_to(T &object, const std::decay_t< T > &begin, const std::decay_t< T > &end, const duration_t &duration, const sentinel_t &sentinel, const ease_t &ease_func=ease::linear) -> seq_action
Creates an action to change an object from one value to another over a specified duration.
Definition seq_core.hpp:11
void stop(seq_id_t id)
Stops the action associated with the given ID.
Definition seq.cpp:14
std::chrono::nanoseconds duration_t
Represents a duration in nanoseconds.
Definition seq_common.h:41
void test_scopes()
Definition tests.cpp:930
void pause(const seq_id_t id)
Pauses the action associated with the given ID.
Definition seq.cpp:19
void seq_update(seq::duration_t duration)
Definition tests.cpp:13
void scenario(bool use_shared_ptr, bool step_update, const std::string &type, seq::duration_t duration, T begin, T end, T object_value)
Definition tests.cpp:237
auto change_to(T &object, const std::decay_t< T > &end, const duration_t &duration, const sentinel_t &sentinel, const ease_t &ease_func=ease::linear) -> seq_action
Creates an action to change an object to a specified value over a specified duration.
Definition seq_core.hpp:76
Represents an action within the sequence management system. Contains lifecycle events and management ...
Definition seq_action.h:18
auto is_valid() const noexcept -> bool
Checks if the action is valid.
Defines policies for scoping actions in a sequence.
Definition seq_common.h:92
std::string scope
The name of the scope.
Definition seq_common.h:106
@ independent
Actions operate independently within their scope.
policy_t policy
The scoping policy (default is stacked).
Definition seq_common.h:111
std::shared_ptr< void > sentinel
Definition tests.cpp:58
std::shared_ptr< T > ptr
Definition tests.cpp:56
const T & get_value() const
Definition tests.cpp:41
void sentinel_reset()
Definition tests.cpp:46
bool sentinel_expired() const
Definition tests.cpp:51
values_t(T val, bool use_shared)
Definition tests.cpp:28
T & get_value()
Definition tests.cpp:36
bool use_shared_ptr
Definition tests.cpp:59
values_t()=default