23#include "freertos/FreeRTOS.h"
24#include "freertos/queue.h"
25#include "freertos/semphr.h"
26#include "freertos/task.h"
104 const char*
TAG =
"TestFramework";
108 vTaskDelay(pdMS_TO_TICKS(50));
138 for (uint8_t i = 0; i < blink_count; ++i) {
140 vTaskDelay(pdMS_TO_TICKS(50));
142 vTaskDelay(pdMS_TO_TICKS(50));
177 void add_result(
bool passed, uint64_t execution_time)
noexcept {
220#define RUN_TEST(test_func) \
222 ensure_gpio14_initialized(); \
225 "╔══════════════════════════════════════════════════════════════════════════════╗\n" \
226 "║ Running: " #test_func " \n" \
227 "╚══════════════════════════════════════════════════════════════════════════════╝"); \
228 uint64_t start_time = esp_timer_get_time(); \
229 bool result = test_func(); \
230 uint64_t end_time = esp_timer_get_time(); \
231 uint64_t execution_time = end_time - start_time; \
232 g_test_results.add_result(result, execution_time); \
234 ESP_LOGI(TAG, "[SUCCESS] PASSED: " #test_func " (%.2f ms)", execution_time / 1000.0); \
236 ESP_LOGE(TAG, "[FAILED] FAILED: " #test_func " (%.2f ms)", execution_time / 1000.0); \
238 vTaskDelay(pdMS_TO_TICKS(100)); \
259 "╔══════════════════════════════════════════════════════════════════════════════╗\n"
260 "║ Running (task): %s \n"
261 "╚══════════════════════════════════════════════════════════════════════════════╝",
263 uint64_t start_time = esp_timer_get_time();
265 uint64_t end_time = esp_timer_get_time();
266 uint64_t execution_time = end_time - start_time;
269 ESP_LOGI(ctx->
tag,
"[SUCCESS] PASSED (task): %s (%.2f ms)", ctx->
test_name,
270 execution_time / 1000.0);
272 ESP_LOGE(ctx->
tag,
"[FAILED] FAILED (task): %s (%.2f ms)", ctx->
test_name,
273 execution_time / 1000.0);
281 vTaskDelete(
nullptr);
291#define RUN_TEST_IN_TASK(name, func, stack_size_bytes, priority) \
293 ensure_gpio14_initialized(); \
294 static TestTaskContext ctx; \
295 ctx.test_name = name; \
296 ctx.test_func = func; \
297 ctx.results = &g_test_results; \
299 ctx.completion_semaphore = xSemaphoreCreateBinary(); \
300 if (ctx.completion_semaphore == nullptr) { \
301 ESP_LOGE(TAG, "Failed to create semaphore for test: %s", name); \
305 BaseType_t created = \
306 xTaskCreate(test_task_trampoline, name, (stack_size_bytes) / sizeof(StackType_t), &ctx, \
307 (priority), nullptr); \
308 if (created != pdPASS) { \
309 ESP_LOGE(TAG, "Failed to create test task: %s", name); \
310 vSemaphoreDelete(ctx.completion_semaphore); \
315 if (xSemaphoreTake(ctx.completion_semaphore, pdMS_TO_TICKS(30000)) == pdTRUE) { \
316 ESP_LOGI(TAG, "Test task completed: %s", name); \
318 ESP_LOGW(TAG, "Test task timeout: %s", name); \
320 vSemaphoreDelete(ctx.completion_semaphore); \
322 vTaskDelay(pdMS_TO_TICKS(100)); \
334 const char* tag)
noexcept {
336 ESP_LOGI(tag,
"\n=== %s TEST SUMMARY ===", test_suite_name);
337 ESP_LOGI(tag,
"Total: %d, Passed: %d, Failed: %d, Success: %.2f%%, Time: %.2f ms",
338 test_results.total_tests, test_results.passed_tests, test_results.failed_tests,
339 test_results.get_success_percentage(), test_results.get_total_time_ms());
341 if (test_results.failed_tests == 0) {
342 ESP_LOGI(tag,
"[SUCCESS] ALL %s TESTS PASSED!", test_suite_name);
344 ESP_LOGE(tag,
"[FAILED] Some tests failed. Review the results above.");
356 ESP_LOGI(tag,
"╔══════════════════════════════════════════════════════════════════════════════╗");
357 ESP_LOGI(tag,
"║ %s TEST SECTION CONFIGURATION ║",
359 ESP_LOGI(tag,
"╚══════════════════════════════════════════════════════════════════════════════╝");
360 ESP_LOGI(tag,
"To modify test sections, edit the defines at the top of your test file");
361 ESP_LOGI(tag,
"╔══════════════════════════════════════════════════════════════════════════════╗");
371 bool enabled =
true) noexcept {
375 "╔══════════════════════════════════════════════════════════════════════════════╗");
376 ESP_LOGI(tag,
"║ %s ",
379 "╠══════════════════════════════════════════════════════════════════════════════╣");
383 "╔══════════════════════════════════════════════════════════════════════════════╗");
384 ESP_LOGI(tag,
"║ %s (DISABLED) ",
387 "╚══════════════════════════════════════════════════════════════════════════════╝");
398 bool enabled =
true) noexcept {
401 "╚══════════════════════════════════════════════════════════════════════════════╝");
423#define RUN_TEST_SECTION_IF_ENABLED(define_name, section_name, ...) \
425 ensure_gpio14_initialized(); \
427 print_test_section_header(TAG, section_name, true); \
429 print_test_section_footer(TAG, section_name, true); \
431 print_test_section_header(TAG, section_name, false); \
432 ESP_LOGI(TAG, "Section disabled by configuration"); \
437#define RUN_SINGLE_TEST_IF_ENABLED(define_name, test_name, test_func, stack_size, priority) \
439 ensure_gpio14_initialized(); \
441 RUN_TEST_IN_TASK(test_name, test_func, stack_size, priority); \
442 flip_test_progress_indicator(); \
444 ESP_LOGI(TAG, "Test '%s' disabled by configuration", test_name); \
449#define RUN_TEST_GROUP_IF_ENABLED(define_name, section_name, ...) \
450 RUN_TEST_SECTION_IF_ENABLED(define_name, section_name, __VA_ARGS__)
453#define RUN_TEST_SECTION_IF_ENABLED_WITH_PROGRESS(define_name, section_name, progress_func, ...) \
455 ensure_gpio14_initialized(); \
457 print_test_section_header(TAG, section_name, true); \
461 print_test_section_footer(TAG, section_name, true); \
463 print_test_section_header(TAG, section_name, false); \
464 ESP_LOGI(TAG, "Section disabled by configuration"); \
469#define RUN_TEST_SECTION_IF_ENABLED_AUTO_PROGRESS(define_name, section_name, ...) \
470 RUN_TEST_SECTION_IF_ENABLED_WITH_PROGRESS(define_name, section_name, \
471 flip_test_progress_indicator, __VA_ARGS__)
474#define RUN_TEST_SECTION_IF_ENABLED_WITH_PATTERN(define_name, section_name, blink_count, ...) \
476 ensure_gpio14_initialized(); \
478 print_test_section_header(TAG, section_name, true); \
479 output_section_indicator(blink_count); \
481 output_section_indicator(blink_count); \
482 print_test_section_footer(TAG, section_name, true); \
484 print_test_section_header(TAG, section_name, false); \
485 ESP_LOGI(TAG, "Section disabled by configuration"); \
static const char * TAG
Definition EspBluetooth.cpp:30
Advanced MCU-specific implementation of the unified BaseGpio class with ESP32C6/ESP-IDF v5....
Platform-agnostic hardware type definitions for the HardFOC system.
static bool g_test_progress_state
Definition TestFramework.h:46
void output_section_indicator(uint8_t blink_count=5) noexcept
Output section start/end indicator on GPIO14.
Definition TestFramework.h:132
void print_test_section_status(const char *tag, const char *test_suite_name) noexcept
Print standardized test section status.
Definition TestFramework.h:353
bool init_test_progress_indicator() noexcept
Initialize the test progression indicator on GPIO14.
Definition TestFramework.h:56
static EspGpio * g_test_progress_gpio
Definition TestFramework.h:45
static constexpr int TEST_PROGRESS_PIN
Definition TestFramework.h:47
void ensure_gpio14_initialized() noexcept
Automatically initialize GPIO14 test indicator if not already done.
Definition TestFramework.h:157
void print_test_section_header(const char *tag, const char *section_name, bool enabled=true) noexcept
Print test section header with consistent formatting.
Definition TestFramework.h:370
void cleanup_test_progress_indicator() noexcept
Cleanup the test progression indicator GPIO.
Definition TestFramework.h:115
void print_test_section_footer(const char *tag, const char *section_name, bool enabled=true) noexcept
Print test section footer with consistent formatting.
Definition TestFramework.h:397
void flip_test_progress_indicator() noexcept
Flip the test progression indicator to show next test.
Definition TestFramework.h:90
void print_test_summary(const TestResults &test_results, const char *test_suite_name, const char *tag) noexcept
Print standardized test summary.
Definition TestFramework.h:333
void test_task_trampoline(void *param)
FreeRTOS task trampoline to execute a test with a larger dedicated stack.
Definition TestFramework.h:255
hf_gpio_err_t SetInactive() noexcept
Set the GPIO to inactive state.
Definition BaseGpio.h:920
bool EnsureInitialized() noexcept
Ensures the pin is initialized (lazy initialization).
Definition BaseGpio.h:790
hf_gpio_err_t SetActive() noexcept
Set the GPIO to active state.
Definition BaseGpio.h:905
Advanced MCU-specific implementation of unified BaseGpio with ESP32C6/ESP-IDF v5.5+ features.
Definition EspGpio.h:65
@ HF_GPIO_DIRECTION_OUTPUT
Pin configured as output.
@ HF_GPIO_PULL_MODE_DOWN
Internal pull-down resistor enabled.
@ HF_GPIO_OUTPUT_MODE_PUSH_PULL
Push-pull output (strong high and low)
@ HF_GPIO_ACTIVE_HIGH
Active state is electrical high.
Test execution tracking and results accumulation.
Definition TestFramework.h:166
int failed_tests
Definition TestFramework.h:169
void add_result(bool passed, uint64_t execution_time) noexcept
Add test result and update statistics.
Definition TestFramework.h:177
int passed_tests
Definition TestFramework.h:168
double get_total_time_ms() const noexcept
Get total execution time in milliseconds.
Definition TestFramework.h:199
uint64_t total_execution_time_us
Definition TestFramework.h:170
double get_success_percentage() const noexcept
Calculate success percentage.
Definition TestFramework.h:191
int total_tests
Definition TestFramework.h:167
Context passed to test task trampoline.
Definition TestFramework.h:244
TestResults * results
Definition TestFramework.h:247
bool(* test_func)() noexcept
Definition TestFramework.h:246
SemaphoreHandle_t completion_semaphore
Definition TestFramework.h:249
const char * test_name
Definition TestFramework.h:245
const char * tag
Definition TestFramework.h:248