GCC Code Coverage Report


Directory: ./
File: unit_tests/tests/controllers/test_long_term_fuel_trim.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 100.0% 52 0 52
Functions: 100.0% 6 0 6
Branches: 45.3% 58 0 128
Decisions: -% 0 - 0

Line Branch Decision Exec Source
1 /*
2 * @file test_long_term_fuel_trim.cpp
3 *
4 * @date Jun 6, 2025
5 * @author Andrey Gusakov, 2025
6 * @author Andrey Belomutskiy, (c) 2012-2025
7 */
8
9 #include "pch.h"
10
11 #define ITERATE_TIME(time, action) \
12 for (size_t i = 0; i < (time * 1000 / FAST_CALLBACK_PERIOD_MS); i++) { \
13 (action); \
14 }
15
16 #define ASSERT_LTFT_RESULT(action, val0, val1) \
17 { \
18 ClosedLoopFuelResult clResult = action; \
19 ASSERT_FLOAT_EQ(clResult.banks[0], val0); \
20 ASSERT_FLOAT_EQ(clResult.banks[1], val1); \
21 }
22
23 4 TEST(LTFT, testLearning)
24 {
25
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
26
27 1 LtftState ltftState;
28 1 LongTermFuelTrim ltft;
29
30 // reset to zero
31
1/1
✓ Branch 1 taken 1 time.
1 ltftState.load();
32
1/1
✓ Branch 1 taken 1 time.
1 ltft.init(&ltftState);
33
34 1 engineConfiguration->ltft.enabled = false;
35 1 engineConfiguration->ltft.correctionEnabled = false;
36 1 engineConfiguration->ltft.deadband = 0.5; // %
37 1 engineConfiguration->ltft.maxAdd = 15.0; // %
38 1 engineConfiguration->ltft.maxRemove = 5; // %
39 1 engineConfiguration->ltft.timeConstant = 30; // seconds
40
41 1 float rpm = config->veRpmBins[0];
42 1 float load = config->veLoadBins[0];
43 1 ClosedLoopFuelResult clInput;
44 1 ClosedLoopFuelResult clResult;
45
46 1 clInput.banks[0] = clInput.banks[1] = 1.5;
47 // Run for 100 sec
48
3/3
✓ Branch 1 taken 20000 times.
✓ Branch 4 taken 20000 times.
✓ Branch 5 taken 1 time.
20001 ITERATE_TIME(100, ltft.learn(clInput, rpm, load))
49
50 // Disabled should not affect
51
7/17
✓ Branch 1 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
✓ Branch 31 taken 1 time.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 time.
✗ Branch 38 not taken.
✗ Branch 43 not taken.
✗ Branch 46 not taken.
✓ Branch 53 taken 1 time.
✗ Branch 54 not taken.
2 ASSERT_LTFT_RESULT(ltft.getTrims(rpm, load), 1.0, 1.0);
52
53 // Enabling
54 1 engineConfiguration->ltft.enabled = true;
55 1 engineConfiguration->ltft.correctionEnabled = true;
56
57 // Run for 100 sec with positive correction
58 1 clInput.banks[0] = clInput.banks[1] = 1.5;
59
3/3
✓ Branch 1 taken 20000 times.
✓ Branch 4 taken 20000 times.
✓ Branch 5 taken 1 time.
20001 ITERATE_TIME(100, ltft.learn(clInput, rpm, load))
60
61 // test hiting maxAdd limit
62
7/17
✓ Branch 1 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
✓ Branch 31 taken 1 time.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 time.
✗ Branch 38 not taken.
✗ Branch 43 not taken.
✗ Branch 46 not taken.
✓ Branch 53 taken 1 time.
✗ Branch 54 not taken.
2 ASSERT_LTFT_RESULT(ltft.getTrims(rpm, load), 1.15, 1.15);
63
64 // Other cells should not be affected
65
7/17
✓ Branch 1 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
✓ Branch 31 taken 1 time.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 time.
✗ Branch 38 not taken.
✗ Branch 43 not taken.
✗ Branch 46 not taken.
✓ Branch 53 taken 1 time.
✗ Branch 54 not taken.
2 ASSERT_LTFT_RESULT(ltft.getTrims(5000, 50), 1.0, 1.0);
66
67 // Run for 100 sec with negative correction
68 1 clInput.banks[0] = clInput.banks[1] = 0.5;
69
3/3
✓ Branch 1 taken 20000 times.
✓ Branch 4 taken 20000 times.
✓ Branch 5 taken 1 time.
20001 ITERATE_TIME(100, ltft.learn(clInput, rpm, load))
70
71 // test hiting maxRemove limit
72
7/17
✓ Branch 1 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
✓ Branch 31 taken 1 time.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 time.
✗ Branch 38 not taken.
✗ Branch 43 not taken.
✗ Branch 46 not taken.
✓ Branch 53 taken 1 time.
✗ Branch 54 not taken.
2 ASSERT_LTFT_RESULT(ltft.getTrims(rpm, load), 0.95, 0.95);
73
74 // Other cells should not be affected
75
7/17
✓ Branch 1 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
✓ Branch 31 taken 1 time.
✗ Branch 34 not taken.
✓ Branch 35 taken 1 time.
✗ Branch 38 not taken.
✗ Branch 43 not taken.
✗ Branch 46 not taken.
✓ Branch 53 taken 1 time.
✗ Branch 54 not taken.
2 ASSERT_LTFT_RESULT(ltft.getTrims(5000, 50), 1.0, 1.0);
76
77 #if 0
78 rpm = config->veRpmBins[0] - (config->veRpmBins[1] - config->veRpmBins[0]) - 1;
79 load = config->veLoadBins[0] - (config->veLoadBins[1] - config->veLoadBins[0]) - 1;
80 // we are not learning, buts but still calculating correction if far outside table
81 // test far outside
82 ASSERT_LTFT_RESULT(ltft.getTrims(rpm, load), 1.0, 1.0);
83 ASSERT_LTFT_RESULT(ltft.getTrims(10000, 1000), 1.0, 1.0);
84 #endif
85 1 }
86
87 4 TEST(LTFT, testSlowCallbackLoadError) {
88
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
89
90 1 LtftState ltftState;
91 1 LongTermFuelTrim ltft;
92
93 // reset to zero
94
1/1
✓ Branch 1 taken 1 time.
1 ltftState.load();
95
1/1
✓ Branch 1 taken 1 time.
1 ltft.init(&ltftState);
96
97 // mock loading state
98 1 ltft.ltftLearning = false;
99 1 ltft.ltftLoadPending = true;
100
1/1
✓ Branch 1 taken 1 time.
1 engine->rpmCalculator.setRpmValue(1000);
101
102
1/1
✓ Branch 1 taken 1 time.
1 ltft.onSlowCallback();
103 // still in loading time:
104
1/6
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 14 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
1 EXPECT_TRUE(ltft.ltftLoadPending);
105
1/6
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 14 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
1 EXPECT_FALSE(ltft.ltftLoadError);
106
107 1 ltft.ltftLoadPending = true;
108
109 // too much time loading!
110
1/1
✓ Branch 1 taken 1 time.
1 advanceTimeUs(8'000'000);
111
112
1/1
✓ Branch 1 taken 1 time.
1 ltft.onSlowCallback();
113
1/6
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 14 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
1 EXPECT_FALSE(ltft.ltftLoadPending);
114
1/6
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 14 not taken.
✗ Branch 18 not taken.
✗ Branch 21 not taken.
1 EXPECT_TRUE(ltft.ltftLoadError);
115 2 }
116