GCC Code Coverage Report


Directory: ./
File: unit_tests/tests/controllers/test_long_term_fuel_trim.cpp
Date: 2025-11-16 14:52:24
Coverage Exec Excl Total
Lines: 100.0% 56 0 56
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[ftRegionIdle] = 30; // seconds
40 1 engineConfiguration->ltft.timeConstant[ftRegionOverrun] = 30; // seconds
41 1 engineConfiguration->ltft.timeConstant[ftRegionPower] = 30; // seconds
42 1 engineConfiguration->ltft.timeConstant[ftRegionCruise] = 30; // seconds
43
44 1 float rpm = config->veRpmBins[0];
45 1 float load = config->veLoadBins[0];
46 1 ClosedLoopFuelResult clInput;
47 1 ClosedLoopFuelResult clResult;
48
49 1 clInput.region = ftRegionIdle;
50 1 clInput.banks[0] = clInput.banks[1] = 1.5;
51 // Run for 100 sec
52
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))
53
54 // Disabled should not affect
55
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);
56
57 // Enabling
58 1 engineConfiguration->ltft.enabled = true;
59 1 engineConfiguration->ltft.correctionEnabled = true;
60
61 // Run for 100 sec with positive correction
62 1 clInput.banks[0] = clInput.banks[1] = 1.5;
63
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))
64
65 // test hiting maxAdd limit
66
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);
67
68 // Other cells should not be affected
69
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);
70
71 // Run for 100 sec with negative correction
72 1 clInput.banks[0] = clInput.banks[1] = 0.5;
73
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))
74
75 // test hiting maxRemove limit
76
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);
77
78 // Other cells should not be affected
79
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);
80
81 #if 0
82 rpm = config->veRpmBins[0] - (config->veRpmBins[1] - config->veRpmBins[0]) - 1;
83 load = config->veLoadBins[0] - (config->veLoadBins[1] - config->veLoadBins[0]) - 1;
84 // we are not learning, buts but still calculating correction if far outside table
85 // test far outside
86 ASSERT_LTFT_RESULT(ltft.getTrims(rpm, load), 1.0, 1.0);
87 ASSERT_LTFT_RESULT(ltft.getTrims(10000, 1000), 1.0, 1.0);
88 #endif
89 1 }
90
91 4 TEST(LTFT, testSlowCallbackLoadError) {
92
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
93
94 1 LtftState ltftState;
95 1 LongTermFuelTrim ltft;
96
97 // reset to zero
98
1/1
✓ Branch 1 taken 1 time.
1 ltftState.load();
99
1/1
✓ Branch 1 taken 1 time.
1 ltft.init(&ltftState);
100
101 // mock loading state
102 1 ltft.ltftLearning = false;
103 1 ltft.ltftLoadPending = true;
104
1/1
✓ Branch 1 taken 1 time.
1 engine->rpmCalculator.setRpmValue(1000);
105
106
1/1
✓ Branch 1 taken 1 time.
1 ltft.onSlowCallback();
107 // still in loading time:
108
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);
109
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);
110
111 1 ltft.ltftLoadPending = true;
112
113 // too much time loading!
114
1/1
✓ Branch 1 taken 1 time.
1 advanceTimeUs(8'000'000);
115
116
1/1
✓ Branch 1 taken 1 time.
1 ltft.onSlowCallback();
117
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);
118
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);
119 2 }
120