test_rtti.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdexcept>
  7. #include <typeinfo>
  8. #include "unity.h"
  9. #include "unity_test_utils.h"
  10. /* Note: When first exception (in system) is thrown this test produces memory leaks report (~300 bytes):
  11. - 8 bytes are allocated by __cxa_get_globals() to keep __cxa_eh_globals
  12. - 16 bytes are allocated by pthread_setspecific() which is called by __cxa_get_globals() to init TLS var for __cxa_eh_globals
  13. - 88 bytes are allocated by pthread_setspecific() to init internal lock
  14. - some more memory...
  15. */
  16. #if CONFIG_IDF_TARGET_ESP32
  17. #define LEAKS (300)
  18. #elif CONFIG_IDF_TARGET_ESP32S2
  19. #define LEAKS (800)
  20. #elif CONFIG_IDF_TARGET_ESP32C3
  21. #define LEAKS (700)
  22. #else
  23. #error "unknown target in CXX tests, can't set leaks threshold"
  24. #endif
  25. extern "C" void setUp()
  26. {
  27. unity_utils_set_leak_level(0);
  28. unity_utils_record_free_mem();
  29. }
  30. extern "C" void tearDown()
  31. {
  32. unity_utils_evaluate_leaks();
  33. }
  34. using namespace std;
  35. class Base {
  36. public:
  37. virtual ~Base() {} ;
  38. virtual char name() = 0;
  39. };
  40. class DerivedA : public Base {
  41. public:
  42. char name() override
  43. {
  44. return 'A';
  45. }
  46. };
  47. class DerivedB : public Base {
  48. public:
  49. char name() override
  50. {
  51. return 'B';
  52. }
  53. };
  54. TEST_CASE("unsuccessful dynamic cast on pointer returns nullptr", "[cxx]")
  55. {
  56. Base *base = new DerivedA();
  57. DerivedB *derived = dynamic_cast<DerivedB*>(base);
  58. TEST_ASSERT_EQUAL(derived, nullptr);
  59. delete base;
  60. derived = nullptr;
  61. }
  62. TEST_CASE("dynamic cast works", "[cxx]")
  63. {
  64. Base *base = new DerivedA();
  65. DerivedA *derived = dynamic_cast<DerivedA*>(base);
  66. TEST_ASSERT_EQUAL(derived, base);
  67. delete base;
  68. }
  69. TEST_CASE("typeid of dynamic objects works", "[cxx]")
  70. {
  71. Base *base = new DerivedA();
  72. DerivedA *derived = dynamic_cast<DerivedA*>(base);
  73. TEST_ASSERT_EQUAL(typeid(*derived).hash_code(), typeid(*base).hash_code());
  74. TEST_ASSERT_EQUAL(typeid(*derived).hash_code(), typeid(DerivedA).hash_code());
  75. delete base;
  76. derived = nullptr;
  77. }
  78. int dummy_function1(int arg1, double arg2);
  79. int dummy_function2(int arg1, double arg2);
  80. TEST_CASE("typeid of function works", "[cxx]")
  81. {
  82. TEST_ASSERT_EQUAL(typeid(dummy_function1).hash_code(), typeid(dummy_function2).hash_code());
  83. }
  84. TEST_CASE("unsuccessful dynamic cast on reference throws exception", "[cxx]")
  85. {
  86. unity_utils_set_leak_level(LEAKS);
  87. bool thrown = false;
  88. DerivedA derived_a;
  89. Base &base = derived_a;
  90. try {
  91. DerivedB &derived_b = dynamic_cast<DerivedB&>(base);
  92. derived_b.name(); // suppress warning
  93. } catch (bad_cast &e) {
  94. thrown = true;
  95. }
  96. TEST_ASSERT(thrown);
  97. }
  98. TEST_CASE("typeid on nullptr throws bad_typeid", "[cxx]")
  99. {
  100. Base *base = nullptr;
  101. size_t hash = 0;
  102. bool thrown = false;
  103. try {
  104. hash = typeid(*base).hash_code();
  105. } catch (bad_typeid &e) {
  106. thrown = true;
  107. }
  108. TEST_ASSERT_EQUAL(0, hash);
  109. TEST_ASSERT(thrown);
  110. }
  111. extern "C" void app_main(void)
  112. {
  113. printf("CXX RTTI TEST\n");
  114. unity_run_menu();
  115. }