5 #include "freertos/FreeRTOS.h"
6 #include "freertos/task.h"
7 #include "freertos/semphr.h"
9 static const char* TAG = "cxx";
11 TEST_CASE("can use new and delete", "[cxx]")
13 int* int_p = new int(10);
15 int* int_array = new int[10];
23 virtual void foo() = 0;
26 class Derived : public Base
29 virtual void foo() { }
32 TEST_CASE("can call virtual functions", "[cxx]")
35 Base& b = static_cast<Base&>(d);
42 NonPOD(int a_) : a(a_) { }
46 static int non_pod_test_helper(int new_val)
48 static NonPOD non_pod(42);
54 TEST_CASE("can use static initializers for non-POD types", "[cxx]")
56 TEST_ASSERT_EQUAL(42, non_pod_test_helper(1));
57 TEST_ASSERT_EQUAL(1, non_pod_test_helper(0));
60 TEST_CASE("can use std::vector", "[cxx]")
62 std::vector<int> v(10, 1);
64 TEST_ASSERT_EQUAL(51, std::accumulate(std::begin(v), std::end(v), 0));
68 * This test exercises static initialization guards for two objects.
69 * For each object, 4 tasks are created which attempt to perform static initialization.
70 * We check that constructor runs only once for each object.
73 static SemaphoreHandle_t s_slow_init_sem = NULL;
80 ESP_LOGD(TAG, "init obj=%d start, arg=%d\n", obj, arg);
81 vTaskDelay(300/portTICK_PERIOD_MS);
82 TEST_ASSERT_EQUAL(-1, mInitBy);
83 TEST_ASSERT_EQUAL(0, mInitCount);
86 ESP_LOGD(TAG, "init obj=%d done\n", obj);
89 static void task(void* arg) {
90 int taskId = reinterpret_cast<int>(arg);
91 ESP_LOGD(TAG, "obj=%d before static init, task=%d\n", obj, taskId);
92 static SlowInit slowinit(taskId);
93 ESP_LOGD(TAG, "obj=%d after static init, task=%d\n", obj, taskId);
94 xSemaphoreGive(s_slow_init_sem);
99 static int mInitCount;
102 template<> int SlowInit<1>::mInitBy = -1;
103 template<> int SlowInit<1>::mInitCount = 0;
104 template<> int SlowInit<2>::mInitBy = -1;
105 template<> int SlowInit<2>::mInitCount = 0;
108 static void start_slow_init_task(int id, int affinity)
110 xTaskCreatePinnedToCore(&SlowInit<obj>::task, "slow_init", 2048,
111 reinterpret_cast<void*>(id), 3, NULL, affinity);
114 TEST_CASE("static initialization guards work as expected", "[cxx]")
116 s_slow_init_sem = xSemaphoreCreateCounting(10, 0);
117 TEST_ASSERT_NOT_NULL(s_slow_init_sem);
118 // four tasks competing for static initialization of one object
119 start_slow_init_task<1>(0, PRO_CPU_NUM);
120 start_slow_init_task<1>(1, APP_CPU_NUM);
121 start_slow_init_task<1>(2, PRO_CPU_NUM);
122 start_slow_init_task<1>(3, tskNO_AFFINITY);
124 // four tasks competing for static initialization of another object
125 start_slow_init_task<2>(0, PRO_CPU_NUM);
126 start_slow_init_task<2>(1, APP_CPU_NUM);
127 start_slow_init_task<2>(2, PRO_CPU_NUM);
128 start_slow_init_task<2>(3, tskNO_AFFINITY);
131 for (int i = 0; i < 8; ++i) {
132 TEST_ASSERT_TRUE(xSemaphoreTake(s_slow_init_sem, 500/portTICK_PERIOD_MS));
134 vSemaphoreDelete(s_slow_init_sem);
136 vTaskDelay(10); // Allow tasks to clean up, avoids race with leak detector
139 struct GlobalInitTest
141 GlobalInitTest() : index(order++) {
147 int GlobalInitTest::order = 0;
149 GlobalInitTest g_init_test1;
150 GlobalInitTest g_init_test2;
151 GlobalInitTest g_init_test3;
153 TEST_CASE("global initializers run in the correct order", "[cxx]")
155 TEST_ASSERT_EQUAL(0, g_init_test1.index);
156 TEST_ASSERT_EQUAL(1, g_init_test2.index);
157 TEST_ASSERT_EQUAL(2, g_init_test3.index);
160 struct StaticInitTestBeforeScheduler
162 StaticInitTestBeforeScheduler()
164 static int first_init_order = getOrder();
165 index = first_init_order;
177 int StaticInitTestBeforeScheduler::order = 1;
179 StaticInitTestBeforeScheduler g_static_init_test1;
180 StaticInitTestBeforeScheduler g_static_init_test2;
181 StaticInitTestBeforeScheduler g_static_init_test3;
183 TEST_CASE("before scheduler has started, static initializers work correctly", "[cxx]")
185 TEST_ASSERT_EQUAL(1, g_static_init_test1.index);
186 TEST_ASSERT_EQUAL(1, g_static_init_test2.index);
187 TEST_ASSERT_EQUAL(1, g_static_init_test3.index);
188 TEST_ASSERT_EQUAL(2, StaticInitTestBeforeScheduler::order);
191 #ifdef CONFIG_CXX_EXCEPTIONS
193 TEST_CASE("c++ exceptions work", "[cxx]")
195 /* Note: This test currently trips the memory leak threshold
196 as libunwind allocates ~4KB of data on first exception. */
206 TEST_ASSERT_EQUAL(20, thrown_value);
212 /* These test cases pull a lot of code from libstdc++ and are disabled for now
216 #include <functional>
218 TEST_CASE("can use iostreams", "[cxx]")
220 std::cout << "hello world";
223 TEST_CASE("can call std::function and bind", "[cxx]")
226 std::function<int(int)> fn = [&outer](int x) -> int {
230 TEST_ASSERT_EQUAL(6, fn(1));
232 auto bound = std::bind(fn, outer);
234 TEST_ASSERT_EQUAL(15, bound());