| 
									
										
										
										
											2021-05-17 03:43:02 +02:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-01-02 16:19:49 +08:00
										 |  |  |  * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD | 
					
						
							| 
									
										
										
										
											2021-05-17 03:43:02 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: Apache-2.0 | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-09-07 20:44:25 +08:00
										 |  |  | #include <stdexcept>
 | 
					
						
							| 
									
										
										
										
											2017-01-05 00:25:55 +08:00
										 |  |  | #include "unity.h"
 | 
					
						
							| 
									
										
										
										
											2022-03-31 18:16:19 +08:00
										 |  |  | #include "unity_test_utils.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-05 00:25:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-24 15:41:08 +08:00
										 |  |  | /* Note: When first exception (in system) is thrown this test produces memory leaks report (~300 bytes):
 | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  |    - 8 bytes are allocated by __cxa_get_globals() to keep __cxa_eh_globals | 
					
						
							|  |  |  |    - 16 bytes are allocated by pthread_setspecific() which is called by __cxa_get_globals() to init TLS var for __cxa_eh_globals | 
					
						
							|  |  |  |    - 88 bytes are allocated by pthread_setspecific() to init internal lock | 
					
						
							| 
									
										
										
										
											2020-04-24 15:41:08 +08:00
										 |  |  |    - some more memory... | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  |    */ | 
					
						
							| 
									
										
										
										
											2020-04-24 15:41:08 +08:00
										 |  |  | #if CONFIG_IDF_TARGET_ESP32
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | #define LEAKS (300)
 | 
					
						
							| 
									
										
										
										
											2020-04-24 15:41:08 +08:00
										 |  |  | #elif CONFIG_IDF_TARGET_ESP32S2
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | #define LEAKS (800)
 | 
					
						
							| 
									
										
										
										
											2020-12-30 16:10:37 +08:00
										 |  |  | #elif CONFIG_IDF_TARGET_ESP32C3
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | #define LEAKS (700)
 | 
					
						
							| 
									
										
										
										
											2020-04-24 15:41:08 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #error "unknown target in CXX tests, can't set leaks threshold"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | extern "C" void setUp() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-31 18:16:19 +08:00
										 |  |  |     unity_utils_record_free_mem(); | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern "C" void tearDown() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-31 18:16:19 +08:00
										 |  |  |     unity_utils_evaluate_leaks_direct(LEAKS); | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TEST_CASE("c++ exceptions work", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2017-10-04 16:00:11 +11:00
										 |  |  | { | 
					
						
							|  |  |  |     int thrown_value; | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  |     try { | 
					
						
							| 
									
										
										
										
											2017-10-04 16:00:11 +11:00
										 |  |  |         throw 20; | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  |     } catch (int e) { | 
					
						
							| 
									
										
										
										
											2017-10-04 16:00:11 +11:00
										 |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(20, thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ bool exception", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     bool thrown_value = false; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw true; | 
					
						
							|  |  |  |     } catch (bool e) { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(true, thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ void exception", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     void* thrown_value = 0; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw (void*) 47; | 
					
						
							|  |  |  |     } catch (void* e) { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(47, thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ uint64_t exception", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     uint64_t thrown_value = 0; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw (uint64_t) 47; | 
					
						
							|  |  |  |     } catch (uint64_t e) { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(47, thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ char exception", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     char thrown_value = '0'; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw '/'; | 
					
						
							|  |  |  |     } catch (char e) { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL('/', thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ wchar exception", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     wchar_t thrown_value = 0; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw (wchar_t) 47; | 
					
						
							|  |  |  |     } catch (wchar_t e) { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL((wchar_t) 47, thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ float exception", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     float thrown_value = 0; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw 23.5f; | 
					
						
							|  |  |  |     } catch (float e) { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(23.5, thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ double exception", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     double thrown_value = 0; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw 23.5d; | 
					
						
							|  |  |  |     } catch (double e) { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(23.5d, thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ const char* exception", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     const char *thrown_value = 0; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw "Hi :)"; | 
					
						
							|  |  |  |     } catch (const char *e) { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL_STRING("Hi :)", thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct NonExcTypeThrowee { | 
					
						
							|  |  |  |     int value; | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     NonExcTypeThrowee(int value) : value(value) { } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ any class exception", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int thrown_value = 0; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw NonExcTypeThrowee(47); | 
					
						
							|  |  |  |     } catch (NonExcTypeThrowee &e) { | 
					
						
							|  |  |  |         thrown_value = e.value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(47, thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct ExcTypeThrowee : public std::exception { | 
					
						
							|  |  |  |     int value; | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     ExcTypeThrowee(int value) : value(value) { } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ std::exception child", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2019-10-24 09:59:31 +08:00
										 |  |  | { | 
					
						
							|  |  |  |     int thrown_value = 0; | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         throw ExcTypeThrowee(47); | 
					
						
							|  |  |  |     } catch (ExcTypeThrowee &e) { | 
					
						
							|  |  |  |         thrown_value = e.value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(47, thrown_value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | TEST_CASE("c++ exceptions emergency pool", "[cxx] [exceptions]") | 
					
						
							| 
									
										
										
										
											2017-11-17 12:38:19 +03:00
										 |  |  | { | 
					
						
							|  |  |  |     void **p, **pprev = NULL; | 
					
						
							|  |  |  |     int thrown_value = 0; | 
					
						
							|  |  |  |     // throw first exception to ensure that all initial allocations are made
 | 
					
						
							|  |  |  |     try | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         throw 33; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     catch (int e) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(33, thrown_value); | 
					
						
							|  |  |  |     // consume all dynamic memory
 | 
					
						
							|  |  |  |     while ((p = (void **)malloc(sizeof(void *)))) { | 
					
						
							|  |  |  |         if (pprev) { | 
					
						
							|  |  |  |             *p = pprev; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             *p = NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         pprev = p; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     try | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         throw 20; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     catch (int e) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         thrown_value = e; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-24 15:02:25 +02:00
										 |  |  | #if CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE > 0
 | 
					
						
							| 
									
										
										
										
											2017-11-17 12:38:19 +03:00
										 |  |  |     // free all memory
 | 
					
						
							|  |  |  |     while (pprev) { | 
					
						
							|  |  |  |         p = (void **)(*pprev); | 
					
						
							|  |  |  |         free(pprev); | 
					
						
							|  |  |  |         pprev = p; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     TEST_ASSERT_EQUAL(20, thrown_value); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |     // if emergency pool is disabled we should never get here,
 | 
					
						
							|  |  |  |     // expect abort() due to lack of memory for new exception
 | 
					
						
							|  |  |  |     TEST_ASSERT_TRUE(0 == 1); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  | extern "C" void app_main(void) | 
					
						
							| 
									
										
										
										
											2017-01-10 23:45:44 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-22 16:20:51 +08:00
										 |  |  |     printf("CXX EXCEPTION TEST\n"); | 
					
						
							|  |  |  |     unity_run_menu(); | 
					
						
							| 
									
										
										
										
											2017-01-10 23:45:44 +08:00
										 |  |  | } |