C/C++ Test Harnesses
Relevant source files
The following files were used as context for generating this wiki page:
C/C++ Test Harnesses within the Muse Gadget SDK provide a deterministic environment to validate firmware logic on a host machine without requiring physical ESP32 hardware. These harnesses use "host fakes" to replace hardware-dependent services such as storage, Bluetooth, Wi-Fi, and the FreeRTOS scheduler, allowing core application logic to be compiled and executed as native host binaries.
The test suite integrates Python-based drivers that compile C code on-the-fly, inject test data via standard input, and verify the resulting output against expected behaviors. This architecture ensures that critical features like the Noise protocol handshake, voice note streaming, and device lifecycle management function correctly before deployment to a device.
Sources: esp32/tests/test_link_endpoint_lifecycle.py:32-38, esp32/simulator/README.md:20-25, esp32/tests/test_muse_voice_note.py:36-40
Architecture and Test Execution Flow
The testing architecture relies on a hybrid model where Python unit tests manage the lifecycle of C-based test harnesses. The Python layer performs the following actions:
- Extracts specific production C/C++ code segments from the
main/orcomponents/directories. - Wraps this production code with host-compatible headers and mock functions (fakes).
- Compiles the resulting source into a temporary native binary using a system compiler (e.g.,
ccorc++). - Executes the binary, providing inputs and capturing outputs for assertion.
Execution Sequence Diagram
The following diagram illustrates how the Python test driver interacts with the compiled C harness to validate firmware behavior.
Host Fakes and Service Mocking
Because the firmware is designed for ESP-IDF, the test harnesses must provide "fake" implementations of ESP32-specific APIs. These fakes allow the code to link and run on Linux or macOS.
Mocked Subsystems
| Subsystem | Mocked Component | Purpose |
|---|---|---|
| Storage | config_set_str, config_get_str | Simulates NVS (Non-Volatile Storage) using local memory buffers. |
| Networking | wifi_mgr_disconnect, vm_api_set_base_url | Prevents real network calls; tracks connectivity state changes. |
| OS/Tasking | xTaskCreate, esp_timer_get_time | Fakes task creation and uses host system time for timeouts. |
| OTA | esp_ota_get_running_partition | Returns null pointers to bypass partition table lookups. |
| Simulator | sim_services_reset | Resets global states for Wi-Fi, BLE, and Link in the desktop preview. |
Sources: esp32/tests/test_link_endpoint_lifecycle.py:84-125, esp32/simulator/src/sim_services.c:64-79, esp32/tests/test_link_bug_report.py:73-85
Specialized Harness Types
The SDK employs different harness strategies depending on the module being tested.
Voice Note and Audio Harnesses
These harnesses validate the streaming of 16 kHz mono speech. They verify that the riff_header and base64 encoding correctly wrap the PCM data for the /chat/stream API. The harness simulates the "mic backlog" by providing data through a fake xStreamBufferReceive function.
Sources: esp32/tests/test_muse_voice_note.py:165-185, esp32/tests/test_muse_voice_note.py:65-75
Endpoint Lifecycle Harnesses
This harness focuses on how the device handles API URLs and credentials during provisioning and boot. It uses a stored[4][256] char array to act as the NVS backend, ensuring that endpoints are correctly migrated or cleared during pairing failures.
Sources: esp32/tests/test_link_endpoint_lifecycle.py:87-105
Bug Report Harnesses
This harness validates the generation of JSON bug reports. It links the production bug_report.c with a fake cJSON.c implementation and verifies that the primary payload does not exceed the 32 KB limit and contains the required redaction profiles.
Sources: esp32/tests/test_link_bug_report.py:76-110
Deterministic Testing and Sanitization
To ensure high code quality, harnesses are often compiled with AddressSanitizer (ASan) and UndefinedBehaviorSanitizer (UBSAN). This detects memory leaks, buffer overruns, and undefined behavior during the execution of host-based tests.
// Example of a compile-time flag configuration for sanitization
#define SANITIZE ["-O1", "-g", "-fsanitize=address,undefined", "-fno-omit-frame-pointer"]
In headless runs, the simulator uses a dummy SDL video driver to validate UI scenarios without a display server. This allows CI systems to verify that the avatar renderer produces identical framebuffer captures for identical inputs.
Sources: esp32/tests/test_muse_voice_note.py:30-33, esp32/simulator/README.md:65-75, esp32/tests/test_link_bug_report.py:53-65
Conclusion
C/C++ Test Harnesses are a critical component of the Muse Gadget SDK, providing a fast feedback loop for firmware developers. By isolating application logic from ESP32 hardware through host fakes and automated Python drivers, the project maintains high reliability in its core networking, audio, and device management protocols.