From 77a70fc0da2a4bf942b4f4f96d71c5d17de50204 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 22:43:35 +0000 Subject: [PATCH] Fix GPIO tests to use meaningful assertions instead of tautologies Co-authored-by: pmarchini <49943249+pmarchini@users.noreply.github.com> --- test_app/README.md | 10 ++-- test_app/main/test_main.c | 117 +++++++++++++++++++------------------- 2 files changed, 63 insertions(+), 64 deletions(-) diff --git a/test_app/README.md b/test_app/README.md index 30e91f9..bb6c631 100644 --- a/test_app/README.md +++ b/test_app/README.md @@ -35,11 +35,11 @@ The tests are organized using the ESP-IDF Unity testing framework and cover the - `test_multiple_dimmers_independent`: Verifies multiple dimmers operate independently 7. **GPIO and Timer ISR Tests** - - `test_gpio_output_timing_high`: Verifies GPIO output pin timing after zero-crossing - - `test_gpio_output_pulse_width`: Tests the pulse width timing on GPIO output - - `test_gpio_output_zero_crossing_response`: Validates dimmer response to zero-crossing interrupts - - `test_multiple_dimmers_gpio_independence`: Tests that multiple dimmers control GPIO pins independently - - `test_timer_isr_respects_state_changes`: Verifies timer ISR respects dimmer state changes (ON/OFF) + - `test_gpio_output_timing_high`: Verifies GPIO output pin goes HIGH after zero-crossing trigger (tests with power=99 for immediate response) + - `test_gpio_output_pulse_width`: Tests the pulse completes and pin returns to LOW after full cycle + - `test_gpio_output_zero_crossing_response`: Validates dimmer triggers output HIGH in response to zero-crossing events + - `test_multiple_dimmers_gpio_independence`: Tests that ON dimmer triggers output while OFF dimmer remains LOW + - `test_timer_isr_respects_state_changes`: Verifies timer ISR keeps pin LOW when OFF and triggers HIGH when ON ## Running the Tests diff --git a/test_app/main/test_main.c b/test_app/main/test_main.c index ae50b12..db87ec9 100644 --- a/test_app/main/test_main.c +++ b/test_app/main/test_main.c @@ -269,29 +269,26 @@ void test_gpio_output_timing_high(void) begin(dimmer, NORMAL_MODE, ON, 50); - // Set power to 50 (mid-range) - setPower(dimmer, 50); + // Set power to 99 (maximum power, earliest trigger, dimPulseBegin=1) + setPower(dimmer, 99); vTaskDelay(pdMS_TO_TICKS(10)); - // Trigger zero-crossing by toggling the ZC pin - // This simulates the external zero-crossing detector + // Initial pin state should be LOW before zero-crossing + int initial_state = gpio_get_level(TEST_TRIAC_GPIO); + TEST_ASSERT_EQUAL(0, initial_state); + + // Trigger zero-crossing by creating a falling edge on ZC pin + gpio_set_level(TEST_ZC_GPIO, 1); + vTaskDelay(pdMS_TO_TICKS(1)); gpio_set_level(TEST_ZC_GPIO, 0); + + // Wait briefly for the first timer tick + // With power=99, dimPulseBegin=1, pin should go HIGH almost immediately vTaskDelay(pdMS_TO_TICKS(1)); - // Wait for timer ISR to fire and set the output high - // The timer runs at intervals based on AC frequency (50Hz = 10ms half-period) - // Each timer tick is 1/100th of the half-period (~100us for 50Hz) - // With power=50, dimPulseBegin=50, so pin should go high after ~5ms - vTaskDelay(pdMS_TO_TICKS(6)); - - // The pin should have been set HIGH at some point during the cycle - // Note: Due to the pulsed nature, we might catch it HIGH or LOW - // This test verifies the mechanism is working - int pin_level = gpio_get_level(TEST_TRIAC_GPIO); - - // The pin should be either HIGH (during pulse) or LOW (after pulse) - // Both are valid depending on timing, but the system should be responsive - TEST_ASSERT_TRUE(pin_level == 0 || pin_level == 1); + // At this point, the pin should be HIGH (during the pulse) + int pin_during_pulse = gpio_get_level(TEST_TRIAC_GPIO); + TEST_ASSERT_EQUAL(1, pin_during_pulse); } // Test: GPIO output pulse timing - verify pulse width @@ -302,24 +299,21 @@ void test_gpio_output_pulse_width(void) begin(dimmer, NORMAL_MODE, ON, 50); - // Set power to 10 (low power, early in cycle) - setPower(dimmer, 10); + // Set power to 99 for fastest response + setPower(dimmer, 99); vTaskDelay(pdMS_TO_TICKS(10)); // Trigger zero-crossing - gpio_set_level(TEST_ZC_GPIO, 0); + gpio_set_level(TEST_ZC_GPIO, 1); vTaskDelay(pdMS_TO_TICKS(1)); + gpio_set_level(TEST_ZC_GPIO, 0); - // Wait for pulse to happen - // With power=10, dimPulseBegin should be high (~90 from powerBuf) - // So pin should go high late in the cycle - vTaskDelay(pdMS_TO_TICKS(11)); + // Wait for a full AC half-cycle to complete (~10ms for 50Hz) + vTaskDelay(pdMS_TO_TICKS(12)); - // After the full cycle, pin should be LOW (pulse complete) + // After the full cycle, pin should be back to LOW (pulse complete) int pin_level = gpio_get_level(TEST_TRIAC_GPIO); - - // Verify the pin state is valid (0 or 1) - TEST_ASSERT_TRUE(pin_level == 0 || pin_level == 1); + TEST_ASSERT_EQUAL(0, pin_level); } // Test: GPIO output with zero-crossing interrupt @@ -336,6 +330,7 @@ void test_gpio_output_zero_crossing_response(void) // Initial pin state should be LOW int initial_state = gpio_get_level(TEST_TRIAC_GPIO); + TEST_ASSERT_EQUAL(0, initial_state); // Trigger zero-crossing by creating a falling edge on ZC pin gpio_set_level(TEST_ZC_GPIO, 1); @@ -344,12 +339,11 @@ void test_gpio_output_zero_crossing_response(void) // Wait for timer ISR cycles to process // With power=99, dimPulseBegin=1, so pin should go high very quickly - vTaskDelay(pdMS_TO_TICKS(2)); + vTaskDelay(pdMS_TO_TICKS(1)); - // The dimmer should have responded to the zero-crossing - // Verify system is operational by checking pin is still valid - int final_state = gpio_get_level(TEST_TRIAC_GPIO); - TEST_ASSERT_TRUE(final_state == 0 || final_state == 1); + // Pin should be HIGH during the pulse + int state_during_pulse = gpio_get_level(TEST_TRIAC_GPIO); + TEST_ASSERT_EQUAL(1, state_during_pulse); } // Test: Multiple dimmers GPIO independence @@ -362,30 +356,33 @@ void test_multiple_dimmers_gpio_independence(void) TEST_ASSERT_NOT_NULL(dimmer2); begin(dimmer1, NORMAL_MODE, ON, 50); - begin(dimmer2, NORMAL_MODE, ON, 50); + begin(dimmer2, NORMAL_MODE, OFF, 50); // dimmer2 is OFF - // Set different power levels - setPower(dimmer1, 25); - setPower(dimmer2, 75); + // Set power for dimmer1 + setPower(dimmer1, 99); vTaskDelay(pdMS_TO_TICKS(10)); + // Initial states + int pin1_initial = gpio_get_level(TEST_TRIAC_GPIO); + int pin2_initial = gpio_get_level(TEST_TRIAC_GPIO_2); + TEST_ASSERT_EQUAL(0, pin1_initial); + TEST_ASSERT_EQUAL(0, pin2_initial); + // Trigger zero-crossing + gpio_set_level(TEST_ZC_GPIO, 1); + vTaskDelay(pdMS_TO_TICKS(1)); gpio_set_level(TEST_ZC_GPIO, 0); + + // Wait for dimmer1 to trigger vTaskDelay(pdMS_TO_TICKS(1)); - // Wait for timer cycles - vTaskDelay(pdMS_TO_TICKS(8)); - - // Both GPIO pins should be independently controlled + // Dimmer1 should be HIGH (ON and triggered) + // Dimmer2 should remain LOW (OFF state) int pin1_level = gpio_get_level(TEST_TRIAC_GPIO); int pin2_level = gpio_get_level(TEST_TRIAC_GPIO_2); - // Verify both pins have valid states - TEST_ASSERT_TRUE(pin1_level == 0 || pin1_level == 1); - TEST_ASSERT_TRUE(pin2_level == 0 || pin2_level == 1); - - // Note: Pins might be in different states due to different power settings - // Both should be operational and independent + TEST_ASSERT_EQUAL(1, pin1_level); // dimmer1 is ON + TEST_ASSERT_EQUAL(0, pin2_level); // dimmer2 is OFF } // Test: Timer ISR execution with state changes @@ -395,37 +392,39 @@ void test_timer_isr_respects_state_changes(void) TEST_ASSERT_NOT_NULL(dimmer); begin(dimmer, NORMAL_MODE, ON, 50); - setPower(dimmer, 50); + setPower(dimmer, 99); vTaskDelay(pdMS_TO_TICKS(10)); // Turn dimmer OFF setState(dimmer, OFF); // Trigger zero-crossing - gpio_set_level(TEST_ZC_GPIO, 0); + gpio_set_level(TEST_ZC_GPIO, 1); vTaskDelay(pdMS_TO_TICKS(1)); + gpio_set_level(TEST_ZC_GPIO, 0); // Wait for timer cycles - vTaskDelay(pdMS_TO_TICKS(12)); + vTaskDelay(pdMS_TO_TICKS(5)); // Pin should remain LOW when dimmer is OFF - int pin_level = gpio_get_level(TEST_TRIAC_GPIO); - - // When OFF, the timer should not trigger the output - // However, due to race conditions, we just verify valid state - TEST_ASSERT_TRUE(pin_level == 0 || pin_level == 1); + int pin_level_off = gpio_get_level(TEST_TRIAC_GPIO); + TEST_ASSERT_EQUAL(0, pin_level_off); // Turn back ON and verify it responds setState(dimmer, ON); vTaskDelay(pdMS_TO_TICKS(2)); // Trigger another zero-crossing + gpio_set_level(TEST_ZC_GPIO, 1); + vTaskDelay(pdMS_TO_TICKS(1)); gpio_set_level(TEST_ZC_GPIO, 0); - vTaskDelay(pdMS_TO_TICKS(8)); - // Now the dimmer should be active + // Wait briefly for pulse + vTaskDelay(pdMS_TO_TICKS(1)); + + // Now the dimmer should be active and pin HIGH int pin_level_on = gpio_get_level(TEST_TRIAC_GPIO); - TEST_ASSERT_TRUE(pin_level_on == 0 || pin_level_on == 1); + TEST_ASSERT_EQUAL(1, pin_level_on); } // Main test runner