1818#include " greentea-client/test_env.h"
1919#include " unity.h"
2020#include " utest.h"
21+ #include < mstd_functional>
2122
2223using namespace utest ::v1;
2324
25+ template <typename T>
26+ using func0_type = T();
27+
28+ template <typename T>
29+ using func1_type = T(T);
30+
31+ template <typename T>
32+ using func2_type = T(T, T);
33+
34+ template <typename T>
35+ using func3_type = T(T, T, T);
36+
37+ template <typename T>
38+ using func4_type = T(T, T, T, T);
39+
40+ template <typename T>
41+ using func5_type = T(T, T, T, T, T);
2442
2543// static functions
2644template <typename T>
@@ -523,13 +541,17 @@ void test_dispatch0()
523541 Verifier<T>::verify0 (&const_volatile_void_func0<T>, (const volatile Thing<T> *)&thing);
524542 Verifier<T>::verify0 (callback (static_func0<T>));
525543
526- Callback<T ()> cb (static_func0);
544+ Callback<T ()> cb (static_func0<T> );
527545 Verifier<T>::verify0 (cb);
528- cb = static_func0;
546+ TEST_ASSERT_TRUE (cb);
547+ func0_type<T> *p = nullptr ;
548+ cb = p;
549+ TEST_ASSERT_FALSE (cb);
550+ cb = static_func0<T>;
529551 Verifier<T>::verify0 (cb);
530552 cb = {&bound_func0<T>, &thing};
531553 Verifier<T>::verify0 (&cb, &Callback<T ()>::call);
532- Verifier<T>::verify0 (&Callback<T ()>::thunk, ( void *) &cb);
554+ Verifier<T>::verify0 (&Callback<T ()>::thunk, &cb);
533555}
534556
535557template <typename T>
@@ -554,9 +576,13 @@ void test_dispatch1()
554576 Verifier<T>::verify1 (&const_volatile_void_func1<T>, (const volatile Thing<T> *)&thing);
555577 Verifier<T>::verify1 (callback (static_func1<T>));
556578
557- Callback<T (T)> cb (static_func1);
579+ Callback<T (T)> cb (static_func1<T> );
558580 Verifier<T>::verify1 (cb);
559- cb = static_func1;
581+ TEST_ASSERT_TRUE (cb);
582+ func1_type<T> *p = nullptr ;
583+ cb = p;
584+ TEST_ASSERT_FALSE (cb);
585+ cb = static_func1<T>;
560586 Verifier<T>::verify1 (cb);
561587 cb = {&bound_func1<T>, &thing};
562588 Verifier<T>::verify1 (&cb, &Callback<T (T)>::call);
@@ -585,9 +611,13 @@ void test_dispatch2()
585611 Verifier<T>::verify2 (&const_volatile_void_func2<T>, (const volatile Thing<T> *)&thing);
586612 Verifier<T>::verify2 (callback (static_func2<T>));
587613
588- Callback<T (T, T)> cb (static_func2);
614+ Callback<T (T, T)> cb (static_func2<T> );
589615 Verifier<T>::verify2 (cb);
590- cb = static_func2;
616+ TEST_ASSERT_TRUE (cb);
617+ func2_type<T> *p = nullptr ;
618+ cb = p;
619+ TEST_ASSERT_FALSE (cb);
620+ cb = static_func2<T>;
591621 Verifier<T>::verify2 (cb);
592622 cb = {&bound_func2<T>, &thing};
593623 Verifier<T>::verify2 (&cb, &Callback<T (T, T)>::call);
@@ -616,9 +646,13 @@ void test_dispatch3()
616646 Verifier<T>::verify3 (&const_volatile_void_func3<T>, (const volatile Thing<T> *)&thing);
617647 Verifier<T>::verify3 (callback (static_func3<T>));
618648
619- Callback<T (T, T, T)> cb (static_func3);
649+ Callback<T (T, T, T)> cb (static_func3<T> );
620650 Verifier<T>::verify3 (cb);
621- cb = static_func3;
651+ TEST_ASSERT_TRUE (cb);
652+ func3_type<T> *p = nullptr ;
653+ cb = p;
654+ TEST_ASSERT_FALSE (cb);
655+ cb = static_func3<T>;
622656 Verifier<T>::verify3 (cb);
623657 cb = {&bound_func3<T>, &thing};
624658 Verifier<T>::verify3 (&cb, &Callback<T (T, T, T)>::call);
@@ -647,9 +681,13 @@ void test_dispatch4()
647681 Verifier<T>::verify4 (&const_volatile_void_func4<T>, (const volatile Thing<T> *)&thing);
648682 Verifier<T>::verify4 (callback (static_func4<T>));
649683
650- Callback<T (T, T, T, T)> cb (static_func4);
684+ Callback<T (T, T, T, T)> cb (static_func4<T> );
651685 Verifier<T>::verify4 (cb);
652- cb = static_func4;
686+ TEST_ASSERT_TRUE (cb);
687+ func4_type<T> *p = nullptr ;
688+ cb = p;
689+ TEST_ASSERT_FALSE (cb);
690+ cb = static_func4<T>;
653691 Verifier<T>::verify4 (cb);
654692 cb = {&bound_func4<T>, &thing};
655693 Verifier<T>::verify4 (&cb, &Callback<T (T, T, T, T)>::call);
@@ -678,15 +716,159 @@ void test_dispatch5()
678716 Verifier<T>::verify5 (&const_volatile_void_func5<T>, (const volatile Thing<T> *)&thing);
679717 Verifier<T>::verify5 (callback (static_func5<T>));
680718
681- Callback<T (T, T, T, T, T)> cb (static_func5);
719+ Callback<T (T, T, T, T, T)> cb (static_func5<T> );
682720 Verifier<T>::verify5 (cb);
683- cb = static_func5;
721+ TEST_ASSERT_TRUE (cb);
722+ func5_type<T> *p = nullptr ;
723+ cb = p;
724+ TEST_ASSERT_FALSE (cb);
725+ cb = static_func5<T>;
684726 Verifier<T>::verify5 (cb);
685727 cb = {&bound_func5<T>, &thing};
686728 Verifier<T>::verify5 (&cb, &Callback<T (T, T, T, T, T)>::call);
729+ #if 0
687730 Verifier<T>::verify5(&Callback<T(T, T, T, T, T)>::thunk, (void *)&cb);
731+ #endif
688732}
689733
734+ #include < mstd_functional>
735+
736+ struct TrivialFunctionObject {
737+ TrivialFunctionObject (int n) : val(n)
738+ {
739+ }
740+
741+ int operator ()(int x) const
742+ {
743+ return x + val;
744+ }
745+ private:
746+ int val;
747+ };
748+
749+ /* Exact count of copy, construction and destruction may vary depending on
750+ * copy elision by compiler, but the derived live count can be relied upon.
751+ */
752+ static int construct_count;
753+ static int destruct_count;
754+ static int copy_count;
755+
756+ static int live_count ()
757+ {
758+ return construct_count - destruct_count;
759+ }
760+
761+ struct FunctionObject {
762+ FunctionObject (int n) : val(n)
763+ {
764+ construct_count++;
765+ }
766+
767+ FunctionObject (const FunctionObject &other) : val(other.val)
768+ {
769+ construct_count++;
770+ copy_count++;
771+ }
772+
773+ ~FunctionObject ()
774+ {
775+ destruct_count++;
776+ destroyed = true ;
777+ }
778+
779+ int operator ()(int x) const
780+ {
781+ return destroyed ? -1000 : x + val;
782+ }
783+ private:
784+ const int val;
785+ bool destroyed = false ;
786+ };
787+
788+ void test_trivial ()
789+ {
790+ TrivialFunctionObject fn (1 );
791+ TEST_ASSERT_EQUAL (2 , fn (1 ));
792+ Callback<int (int )> cb (fn);
793+ TEST_ASSERT_TRUE (cb);
794+ TEST_ASSERT_EQUAL (2 , cb (1 ));
795+ fn = 5 ;
796+ TEST_ASSERT_EQUAL (6 , fn (1 ));
797+ TEST_ASSERT_EQUAL (2 , cb (1 ));
798+ cb = std::ref (fn);
799+ fn = 10 ;
800+ TEST_ASSERT_EQUAL (11 , fn (1 ));
801+ TEST_ASSERT_EQUAL (11 , cb (1 ));
802+ cb = TrivialFunctionObject (3 );
803+ TEST_ASSERT_EQUAL (7 , cb (4 ));
804+ cb = nullptr ;
805+ TEST_ASSERT_FALSE (cb);
806+ cb = TrivialFunctionObject (7 );
807+ Callback<int (int )> cb2 (cb);
808+ TEST_ASSERT_EQUAL (8 , cb (1 ));
809+ TEST_ASSERT_EQUAL (9 , cb2 (2 ));
810+ cb2 = cb;
811+ TEST_ASSERT_EQUAL (6 , cb2 (-1 ));
812+ cb = cb;
813+ TEST_ASSERT_EQUAL (8 , cb (1 ));
814+ cb = std::negate<int >();
815+ TEST_ASSERT_EQUAL (-4 , cb (4 ));
816+ cb = [](int x) {
817+ return x - 7 ;
818+ };
819+ TEST_ASSERT_EQUAL (1 , cb (8 ));
820+ cb = cb2 = nullptr ;
821+ TEST_ASSERT_FALSE (cb);
822+ }
823+
824+ #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL
825+ void test_nontrivial ()
826+ {
827+ {
828+ FunctionObject fn (1 );
829+ TEST_ASSERT_EQUAL (1 , construct_count);
830+ TEST_ASSERT_EQUAL (0 , destruct_count);
831+ TEST_ASSERT_EQUAL (2 , fn (1 ));
832+ Callback<int (int )> cb (fn);
833+ TEST_ASSERT_TRUE (cb);
834+ TEST_ASSERT_EQUAL (2 , live_count ());
835+ TEST_ASSERT_EQUAL (2 , cb (1 ));
836+ cb = std::ref (fn);
837+ TEST_ASSERT_EQUAL (1 , live_count ());
838+ TEST_ASSERT_EQUAL (5 , cb (4 ));
839+ cb = FunctionObject (3 );
840+ TEST_ASSERT_EQUAL (2 , live_count ());
841+ TEST_ASSERT_EQUAL (7 , cb (4 ));
842+ cb = nullptr ;
843+ TEST_ASSERT_FALSE (cb);
844+ TEST_ASSERT_EQUAL (1 , live_count ());
845+ cb = FunctionObject (7 );
846+ TEST_ASSERT_EQUAL (2 , live_count ());
847+ int old_copy_count = copy_count;
848+ Callback<int (int )> cb2 (cb);
849+ TEST_ASSERT_EQUAL (old_copy_count + 1 , copy_count);
850+ TEST_ASSERT_EQUAL (3 , live_count ());
851+ TEST_ASSERT_EQUAL (8 , cb (1 ));
852+ TEST_ASSERT_EQUAL (9 , cb2 (2 ));
853+ old_copy_count = copy_count;
854+ cb2 = cb;
855+ TEST_ASSERT_EQUAL (old_copy_count + 1 , copy_count);
856+ TEST_ASSERT_EQUAL (3 , live_count ());
857+ TEST_ASSERT_EQUAL (6 , cb2 (-1 ));
858+ int old_construct_count = construct_count;
859+ old_copy_count = copy_count;
860+ cb = cb;
861+ TEST_ASSERT_EQUAL (3 , live_count ());
862+ TEST_ASSERT_EQUAL (old_construct_count, construct_count);
863+ TEST_ASSERT_EQUAL (old_copy_count, copy_count);
864+ cb = cb2 = nullptr ;
865+ TEST_ASSERT_FALSE (cb);
866+ TEST_ASSERT_EQUAL (1 , live_count ());
867+ }
868+ TEST_ASSERT_EQUAL (0 , live_count ());
869+ }
870+ #endif
871+
690872
691873// Test setup
692874utest::v1::status_t test_setup (const size_t number_of_cases)
@@ -702,7 +884,10 @@ Case cases[] = {
702884 Case (" Testing callbacks with 2 uint64s" , test_dispatch2<uint64_t >),
703885 Case (" Testing callbacks with 3 uint64s" , test_dispatch3<uint64_t >),
704886 Case (" Testing callbacks with 4 uint64s" , test_dispatch4<uint64_t >),
887+ // IAR currently crashes at link time with this test - skip it as it's well beyond anything needed by real code
888+ #ifndef __ICCARM__
705889 Case (" Testing callbacks with 5 uint64s" , test_dispatch5<uint64_t >),
890+ #endif
706891#elif DO_SMALL_TEST
707892 Case (" Testing callbacks with 0 uchars" , test_dispatch0<unsigned char >),
708893 Case (" Testing callbacks with 1 uchars" , test_dispatch1<unsigned char >),
@@ -717,6 +902,10 @@ Case cases[] = {
717902 Case (" Testing callbacks with 3 ints" , test_dispatch3<int >),
718903 Case (" Testing callbacks with 4 ints" , test_dispatch4<int >),
719904 Case (" Testing callbacks with 5 ints" , test_dispatch5<int >),
905+ Case (" Testing trivial function object" , test_trivial),
906+ #if MBED_CONF_PLATFORM_CALLBACK_NONTRIVIAL
907+ Case (" Testing non-trivial function object" , test_nontrivial),
908+ #endif
720909#endif
721910};
722911
0 commit comments