1 /*
2  * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <typeinfo>
7 #include "unity.h"
8 
9 #ifdef CONFIG_COMPILER_CXX_RTTI
10 
11 using namespace std;
12 
13 class Base {
14 public:
~Base()15     virtual ~Base() {} ;
16     virtual char name() = 0;
17 };
18 
19 class DerivedA : public Base {
20 public:
name()21     char name() override
22     {
23         return 'A';
24     }
25 };
26 
27 class DerivedB : public Base {
28 public:
name()29     char name() override
30     {
31         return 'B';
32     }
33 };
34 
35 TEST_CASE("unsuccessful dynamic cast on pointer returns nullptr", "[cxx]")
36 {
37     Base *base = new DerivedA();
38     DerivedB *derived = dynamic_cast<DerivedB*>(base);
39     TEST_ASSERT_EQUAL(derived, nullptr);
40     delete base;
41     derived = nullptr;
42 }
43 
44 TEST_CASE("dynamic cast works", "[cxx]")
45 {
46     Base *base = new DerivedA();
47     DerivedA *derived = dynamic_cast<DerivedA*>(base);
48     TEST_ASSERT_EQUAL(derived, base);
49     delete base;
50 }
51 
52 TEST_CASE("typeid of dynamic objects works", "[cxx]")
53 {
54     Base *base = new DerivedA();
55     DerivedA *derived = dynamic_cast<DerivedA*>(base);
56     TEST_ASSERT_EQUAL(typeid(*derived).hash_code(), typeid(*base).hash_code());
57     TEST_ASSERT_EQUAL(typeid(*derived).hash_code(), typeid(DerivedA).hash_code());
58     delete base;
59     derived = nullptr;
60 }
61 
62 int dummy_function1(int arg1, double arg2);
63 int dummy_function2(int arg1, double arg2);
64 
65 TEST_CASE("typeid of function works", "[cxx]")
66 {
67     TEST_ASSERT_EQUAL(typeid(dummy_function1).hash_code(), typeid(dummy_function2).hash_code());
68 }
69 
70 #ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
71 TEST_CASE("unsuccessful dynamic cast on reference throws exception", "[cxx]")
72 {
73     bool thrown = false;
74     DerivedA derived_a;
75     Base &base = derived_a;
76     try {
77         DerivedB &derived_b = dynamic_cast<DerivedB&>(base);
78         derived_b.name(); // suppress warning
79     } catch (bad_cast &e) {
80         thrown = true;
81     }
82     TEST_ASSERT(thrown);
83 }
84 
85 TEST_CASE("typeid on nullptr throws bad_typeid", "[cxx]")
86 {
87     Base *base = nullptr;
88     size_t hash = 0;
89     bool thrown = false;
90     try {
91         hash = typeid(*base).hash_code();
92     } catch (bad_typeid &e) {
93         thrown = true;
94     }
95     TEST_ASSERT_EQUAL(0, hash);
96     TEST_ASSERT(thrown);
97 }
98 
99 #endif // CONFIG_COMPILER_CXX_EXCEPTIONS
100 #endif // CONFIG_COMPILER_CXX_RTTI
101