LCOV - code coverage report
Current view: top level - tests/unit - test_apply_controller.c (source / functions) Hit Total Coverage
Test: coverage.clean.info Lines: 186 186 100.0 %
Date: 2026-05-12 07:34:16 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file test_apply_controller.c
       3             :  * @brief Unit-Tests fuer den Apply-Controller (ASIL-D Kern).
       4             :  *
       5             :  * @reqs SWE-001 SWE-002 SWE-003 SWE-004
       6             :  * @arch SWA-002
       7             :  */
       8             : #include "../unit_test_framework.h"
       9             : #include "../../src/apply_controller.h"
      10             : #include "../../src/actuator_driver.h"
      11             : 
      12             : TestStats g_test_stats = {0, 0};
      13             : 
      14          20 : static ApplyInputs make_idle_inputs(void)
      15             : {
      16          20 :     ApplyInputs in = {0};
      17          20 :     in.sw_state              = SWITCH_NEUTRAL;
      18          20 :     in.standstill            = true;
      19          20 :     in.engine_running        = true;
      20          20 :     in.brake_pedal_pressed   = true;
      21          20 :     in.gear_engaged          = true;
      22          20 :     in.safety_apply_request  = false;
      23          20 :     in.left_force_n          = 0;
      24          20 :     in.right_force_n         = 0;
      25          20 :     return in;
      26             : }
      27             : 
      28           4 : static void apply_full_cycle_until_state(ApplyInputs* in, EpbState target, int max_steps)
      29             : {
      30         120 :     for (int i = 0; i < max_steps; ++i) {
      31         120 :         apply_ctrl_step_50ms(in);
      32         120 :         if (apply_ctrl_get_state() == target) {
      33           4 :             return;
      34             :         }
      35             :     }
      36             : }
      37             : 
      38           2 : static void test_init(void)
      39             : {
      40           2 :     TEST_BEGIN("init -> RELEASED");
      41           2 :     (void)actuator_init();
      42           2 :     ASSERT_EQ(apply_ctrl_init(), EPB_OK);
      43           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASED);
      44           2 :     TEST_END();
      45           2 : }
      46             : 
      47           2 : static void test_null_input(void)
      48             : {
      49           2 :     TEST_BEGIN("step_50ms(NULL) -> last_error=EINVAL");
      50           2 :     (void)actuator_init();
      51           2 :     (void)apply_ctrl_init();
      52           2 :     apply_ctrl_step_50ms(NULL);
      53           2 :     ASSERT_EQ(apply_ctrl_last_error(), EPB_EINVAL);
      54           2 :     TEST_END();
      55           2 : }
      56             : 
      57           2 : static void test_apply_request_starts_applying(void)
      58             : {
      59           2 :     TEST_BEGIN("Apply-Request bei Stillstand -> APPLYING");
      60           2 :     (void)actuator_init();
      61           2 :     (void)apply_ctrl_init();
      62           2 :     ApplyInputs in = make_idle_inputs();
      63           2 :     in.sw_state = SWITCH_APPLY;
      64           2 :     apply_ctrl_step_50ms(&in);
      65           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLYING);
      66           2 :     TEST_END();
      67           2 : }
      68             : 
      69           2 : static void test_no_apply_without_standstill(void)
      70             : {
      71           2 :     TEST_BEGIN("Apply-Request ohne Stillstand wird ignoriert");
      72           2 :     (void)actuator_init();
      73           2 :     (void)apply_ctrl_init();
      74           2 :     ApplyInputs in = make_idle_inputs();
      75           2 :     in.standstill = false;
      76           2 :     in.sw_state = SWITCH_APPLY;
      77           2 :     apply_ctrl_step_50ms(&in);
      78           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASED);
      79           2 :     TEST_END();
      80           2 : }
      81             : 
      82           2 : static void test_applying_reaches_applied_on_target_force(void)
      83             : {
      84           2 :     TEST_BEGIN("APPLYING -> APPLIED wenn beide Klemmkraefte >= Target");
      85           2 :     (void)actuator_init();
      86           2 :     (void)apply_ctrl_init();
      87           2 :     ApplyInputs in = make_idle_inputs();
      88           2 :     in.sw_state = SWITCH_APPLY;
      89           2 :     apply_ctrl_step_50ms(&in);  /* -> APPLYING */
      90           2 :     in.sw_state = SWITCH_NEUTRAL;
      91           2 :     in.left_force_n  = 12000;
      92           2 :     in.right_force_n = 12000;
      93           2 :     apply_ctrl_step_50ms(&in);
      94           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLIED);
      95           2 :     TEST_END();
      96           2 : }
      97             : 
      98           2 : static void test_applying_timeout_to_error(void)
      99             : {
     100           2 :     TEST_BEGIN("APPLYING-Timeout (>30 Steps) -> ERROR");
     101           2 :     (void)actuator_init();
     102           2 :     (void)apply_ctrl_init();
     103           2 :     ApplyInputs in = make_idle_inputs();
     104           2 :     in.sw_state = SWITCH_APPLY;
     105           2 :     apply_ctrl_step_50ms(&in);  /* -> APPLYING */
     106           2 :     in.sw_state = SWITCH_NEUTRAL;
     107             :     /* Klemmkraefte bleiben bei 0 -> Timeout nach 30 Steps */
     108           2 :     apply_full_cycle_until_state(&in, EPB_STATE_ERROR, 35);
     109           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_ERROR);
     110           2 :     ASSERT_EQ(apply_ctrl_last_error(), EPB_ETIMEOUT);
     111           2 :     TEST_END();
     112           2 : }
     113             : 
     114           2 : static void test_applied_holds_force(void)
     115             : {
     116           2 :     TEST_BEGIN("APPLIED haelt Klemmkraft (SWE-001)");
     117           2 :     (void)actuator_init();
     118           2 :     (void)apply_ctrl_init();
     119           2 :     ApplyInputs in = make_idle_inputs();
     120           2 :     in.sw_state = SWITCH_APPLY;
     121           2 :     apply_ctrl_step_50ms(&in);
     122           2 :     in.sw_state = SWITCH_NEUTRAL;
     123           2 :     in.left_force_n  = 12000;
     124           2 :     in.right_force_n = 12000;
     125           2 :     apply_ctrl_step_50ms(&in);  /* -> APPLIED */
     126             : 
     127             :     /* Klemmkraft sinkt auf 10000 (unter Toleranz-Schwelle 10800) */
     128           2 :     in.left_force_n  = 10000;
     129           2 :     in.right_force_n = 10000;
     130           2 :     apply_ctrl_step_50ms(&in);
     131             :     /* Apply-Controller muss nachregeln -> APPLYING */
     132           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLYING);
     133           2 :     TEST_END();
     134           2 : }
     135             : 
     136           2 : static void test_release_requires_preconditions(void)
     137             : {
     138           2 :     TEST_BEGIN("Release ohne Engine wird abgelehnt");
     139           2 :     (void)actuator_init();
     140           2 :     (void)apply_ctrl_init();
     141           2 :     ApplyInputs in = make_idle_inputs();
     142           2 :     in.sw_state = SWITCH_APPLY;
     143           2 :     apply_ctrl_step_50ms(&in);
     144           2 :     in.sw_state = SWITCH_NEUTRAL;
     145           2 :     in.left_force_n  = 12000;
     146           2 :     in.right_force_n = 12000;
     147           2 :     apply_ctrl_step_50ms(&in);  /* -> APPLIED */
     148             : 
     149           2 :     in.sw_state = SWITCH_RELEASE;
     150           2 :     in.engine_running = false;
     151           2 :     apply_ctrl_step_50ms(&in);
     152           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLIED);
     153           2 :     TEST_END();
     154           2 : }
     155             : 
     156           2 : static void test_release_with_preconditions(void)
     157             : {
     158           2 :     TEST_BEGIN("Release mit allen Voraussetzungen -> RELEASING -> RELEASED");
     159           2 :     (void)actuator_init();
     160           2 :     (void)apply_ctrl_init();
     161           2 :     ApplyInputs in = make_idle_inputs();
     162           2 :     in.sw_state = SWITCH_APPLY;
     163           2 :     apply_ctrl_step_50ms(&in);
     164           2 :     in.sw_state = SWITCH_NEUTRAL;
     165           2 :     in.left_force_n  = 12000;
     166           2 :     in.right_force_n = 12000;
     167           2 :     apply_ctrl_step_50ms(&in);  /* APPLIED */
     168             : 
     169           2 :     in.sw_state = SWITCH_RELEASE;
     170           2 :     apply_ctrl_step_50ms(&in);
     171           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASING);
     172             : 
     173           2 :     in.sw_state = SWITCH_NEUTRAL;
     174           2 :     in.left_force_n  = 0;
     175           2 :     in.right_force_n = 0;
     176           2 :     apply_ctrl_step_50ms(&in);
     177           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASED);
     178           2 :     TEST_END();
     179           2 : }
     180             : 
     181           2 : static void test_safety_apply_request(void)
     182             : {
     183           2 :     TEST_BEGIN("Safety-Manager Apply-Request (Hill-Hold/Auto-Apply)");
     184           2 :     (void)actuator_init();
     185           2 :     (void)apply_ctrl_init();
     186           2 :     ApplyInputs in = make_idle_inputs();
     187           2 :     in.sw_state = SWITCH_NEUTRAL;
     188           2 :     in.safety_apply_request = true;
     189           2 :     apply_ctrl_step_50ms(&in);
     190           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_APPLYING);
     191           2 :     TEST_END();
     192           2 : }
     193             : 
     194           2 : static void test_watchdog_alive_counter(void)
     195             : {
     196           2 :     TEST_BEGIN("Step-Counter steigt monoton (SWE-002 Watchdog-Alive)");
     197           2 :     (void)actuator_init();
     198           2 :     (void)apply_ctrl_init();
     199           2 :     ApplyInputs in = make_idle_inputs();
     200           2 :     uint32_t before = apply_ctrl_get_step_count();
     201           2 :     apply_ctrl_step_50ms(&in);
     202           2 :     apply_ctrl_step_50ms(&in);
     203           2 :     apply_ctrl_step_50ms(&in);
     204           2 :     ASSERT_EQ(apply_ctrl_get_step_count(), before + 3);
     205           2 :     TEST_END();
     206           2 : }
     207             : 
     208           2 : static void test_error_state_recoverable(void)
     209             : {
     210           2 :     TEST_BEGIN("ERROR -> RELEASED bei neutralem Switch");
     211           2 :     (void)actuator_init();
     212           2 :     (void)apply_ctrl_init();
     213           2 :     ApplyInputs in = make_idle_inputs();
     214           2 :     in.sw_state = SWITCH_APPLY;
     215           2 :     apply_ctrl_step_50ms(&in);
     216           2 :     in.sw_state = SWITCH_NEUTRAL;
     217           2 :     apply_full_cycle_until_state(&in, EPB_STATE_ERROR, 35);
     218           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_ERROR);
     219           2 :     apply_ctrl_step_50ms(&in);
     220           2 :     ASSERT_EQ(apply_ctrl_get_state(), EPB_STATE_RELEASED);
     221           2 :     TEST_END();
     222           2 : }
     223             : 
     224           2 : int main(void)
     225             : {
     226           2 :     printf("== test_apply_controller ==\n");
     227           2 :     test_init();
     228           2 :     test_null_input();
     229           2 :     test_apply_request_starts_applying();
     230           2 :     test_no_apply_without_standstill();
     231           2 :     test_applying_reaches_applied_on_target_force();
     232           2 :     test_applying_timeout_to_error();
     233           2 :     test_applied_holds_force();
     234           2 :     test_release_requires_preconditions();
     235           2 :     test_release_with_preconditions();
     236           2 :     test_safety_apply_request();
     237           2 :     test_watchdog_alive_counter();
     238           2 :     test_error_state_recoverable();
     239           2 :     TEST_SUMMARY();
     240             : }

Generated by: LCOV version 1.14