GCC Code Coverage Report


Directory: ./
File: unit_tests/tests/launch/test_spark_skip_ratio.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 100.0% 72 0 72
Functions: 100.0% 27 0 27
Branches: 49.5% 48 0 97
Decisions: 85.7% 6 - 7

Line Branch Decision Exec Source
1 //
2 // Created by kifir on 6/7/24.
3 //
4
5 #include "pch.h"
6
7 #include "launch_test_base.h"
8
9 namespace {
10 constexpr int TEST_LAUNCH_RPM = 3850;
11 constexpr int TEST_LAUNCH_RPM_WINDOW = 1850;
12 constexpr int TEST_LAUNCH_SPARK_SKIP_END_RPM = 850;
13 constexpr int TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START = TEST_LAUNCH_RPM - TEST_LAUNCH_RPM_WINDOW;
14 constexpr int TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END = TEST_LAUNCH_RPM - TEST_LAUNCH_SPARK_SKIP_END_RPM;
15
16 constexpr int TEST_INITIAL_IGNITION_CUT_PERCENT = 13;
17 constexpr float TEST_INITIAL_IGNITION_CUT_RATIO = 0.13f;
18
19 constexpr int TEST_FINAL_IGNITION_CUT_PERCENT = 42;
20 constexpr float TEST_FINAL_IGNITION_CUT_RATIO = 0.42f;
21
22 class SparkSkipRatioTestConfig : public LaunchTestConfig {
23 public:
24 SparkSkipRatioTestConfig(
25 const std::optional<bool> launchControlEnabled,
26 const std::optional<bool> enableIgnitionCut,
27 const bool satisfySwitchSpeedThresholdAndTpsConditions
28 );
29 };
30
31 8 SparkSkipRatioTestConfig::SparkSkipRatioTestConfig(
32 const std::optional<bool> launchControlEnabled,
33 const std::optional<bool> enableIgnitionCut,
34 const bool satisfySwitchSpeedThresholdAndTpsConditions
35 8 ) {
36
1/1
✓ Branch 2 taken 8 times.
8 setLaunchControlEnabled(launchControlEnabled);
37
38
1/1
✓ Branch 4 taken 8 times.
8 setLaunchRpm({ TEST_LAUNCH_RPM });
39
1/1
✓ Branch 4 taken 8 times.
8 setLaunchRpmWindow({ TEST_LAUNCH_RPM_WINDOW });
40
1/1
✓ Branch 4 taken 8 times.
8 setLaunchCorrectionsEndRpm({ TEST_LAUNCH_SPARK_SKIP_END_RPM });
41
42
1/1
✓ Branch 2 taken 8 times.
8 setEnableIgnitionCut(enableIgnitionCut);
43
1/1
✓ Branch 4 taken 8 times.
8 setInitialIgnitionCut({ TEST_INITIAL_IGNITION_CUT_PERCENT });
44
1/1
✓ Branch 4 taken 8 times.
8 setFinalIgnitionCutBeforeLaunch({ TEST_FINAL_IGNITION_CUT_PERCENT });
45
46 8 setSatisfyActivationSwitchSpeedAndTpsConditions(satisfySwitchSpeedThresholdAndTpsConditions);
47 8 }
48
49 struct SparkSkipRatioTestData {
50 const std::string context;
51 const int rpm;
52 const double expectedTargetSkipRatio;
53 const std::optional<LaunchCondition> expectedLaunchCondition;
54 };
55
56 class SparkSkipRatioTest : public LaunchTestBase {
57 protected:
58 static std::vector<SparkSkipRatioTestData> generateNoLaunchSparkSkipTestData(double expectedTargetSkipRatio);
59
60 static const std::vector<SparkSkipRatioTestData> DEFAULT_NO_LAUNCH_SPARK_SKIP_TEST_DATA;
61
62 void doTest(const SparkSkipRatioTestConfig &config, const std::vector<SparkSkipRatioTestData> &testData);
63 };
64
65 std::vector<SparkSkipRatioTestData>
66 1 SparkSkipRatioTest::generateNoLaunchSparkSkipTestData(const double expectedTargetSkipRatio) {
67 return std::vector<SparkSkipRatioTestData>{
68 {
69 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START - 1 (before entering spark skip RPM window)",
70 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START - 1,
71 expectedTargetSkipRatio,
72 {LaunchCondition::NotMet}
73 },
74 /* We've entered spark skip RPM window: */
75 {
76 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START (entering spark skip RPM window)",
77 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START,
78 expectedTargetSkipRatio,
79 {LaunchCondition::NotMet}
80 },
81 {
82 "rpm = (TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START + TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END) / 2 (inside spark skip RPM window)",
83 (TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START + TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END) / 2,
84 expectedTargetSkipRatio,
85 {LaunchCondition::NotMet}
86 },
87 {
88 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END (leaving spark skip RPM window)",
89 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END,
90 expectedTargetSkipRatio,
91 {LaunchCondition::NotMet}
92 },
93 /* We've left spark skip RPM window: */
94 {
95 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END + 1 (after spark skip RPM window)",
96 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END + 1,
97 expectedTargetSkipRatio,
98 {LaunchCondition::NotMet}
99 },
100 {
101 "rpm = TEST_LAUNCH_RPM - 1 (before launch)",
102 TEST_LAUNCH_RPM - 1,
103 expectedTargetSkipRatio,
104 {LaunchCondition::NotMet}
105 },
106 /* We've reached TEST_LAUNCH_RPM: */
107 {
108 "rpm = TEST_LAUNCH_RPM (launch condition is still not satisfied)",
109 TEST_LAUNCH_RPM,
110 expectedTargetSkipRatio,
111 {LaunchCondition::NotMet}
112 }
113
3/5
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 1 time.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
11 };
114 3 }
115
116 const std::vector<SparkSkipRatioTestData> SparkSkipRatioTest::DEFAULT_NO_LAUNCH_SPARK_SKIP_TEST_DATA =
117 SparkSkipRatioTest::generateNoLaunchSparkSkipTestData(0.0f);
118
119 8 void SparkSkipRatioTest::doTest(
120 const SparkSkipRatioTestConfig &config,
121 const std::vector<SparkSkipRatioTestData> &testData
122 ) {
123 8 setUpTestConfig(config);
124
125
2/2
✓ Branch 7 taken 56 times.
✓ Branch 8 taken 8 times.
2/2
✓ Decision 'true' taken 56 times.
✓ Decision 'false' taken 8 times.
64 for (const SparkSkipRatioTestData &testDataItem: testData) {
126
1/1
✓ Branch 3 taken 56 times.
56 updateRpm(testDataItem.rpm);
127
1/2
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
1/2
✓ Decision 'true' taken 56 times.
✗ Decision 'false' not taken.
56 if (testDataItem.expectedLaunchCondition.has_value()) {
128
4/5
✓ Branch 1 taken 56 times.
✓ Branch 3 taken 44 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
56 switch (testDataItem.expectedLaunchCondition.value()) {
129
1/1
✓ Decision 'true' taken 44 times.
44 case LaunchCondition::NotMet: {
130
1/7
✗ Branch 5 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
44 EXPECT_FALSE(engine->launchController.isPreLaunchCondition) << testDataItem.context;
131
1/7
✗ Branch 5 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
44 EXPECT_FALSE(engine->launchController.isLaunchCondition) << testDataItem.context;
132 break;
133 }
134
1/1
✓ Decision 'true' taken 10 times.
10 case LaunchCondition::PreLaunch: {
135
1/7
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
10 EXPECT_TRUE(engine->launchController.isPreLaunchCondition) << testDataItem.context;
136
1/7
✗ Branch 5 not taken.
✓ Branch 6 taken 10 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
10 EXPECT_FALSE(engine->launchController.isLaunchCondition) << testDataItem.context;
137 break;
138 }
139
1/1
✓ Decision 'true' taken 2 times.
2 case LaunchCondition::Launch: {
140
1/7
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
2 EXPECT_FALSE(engine->launchController.isPreLaunchCondition) << testDataItem.context;
141
1/7
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
2 EXPECT_TRUE(engine->launchController.isLaunchCondition) << testDataItem.context;
142 break;
143 }
144 }
145 }
146
2/6
✓ Branch 3 taken 56 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 56 times.
✗ Branch 10 not taken.
✗ Branch 14 not taken.
✗ Branch 17 not taken.
56 EXPECT_NEAR(engine->hardSparkLimiter.getTargetSkipRatio(), testDataItem.expectedTargetSkipRatio, EPS5D)
147
0/1
✗ Branch 1 not taken.
56 << testDataItem.context;
148 }
149 8 }
150
151 4 TEST_F(SparkSkipRatioTest, raisingRpmToLaunchCondition) {
152
5/7
✓ Branch 3 taken 1 time.
✓ Branch 13 taken 1 time.
✓ Branch 16 taken 1 time.
✓ Branch 25 taken 7 times.
✓ Branch 26 taken 1 time.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
11 doTest(
153 /* config = */ {
154 /* launchControlEnabled = */ {true},
155 /* enableIgnitionCut = */ {true},
156 /* satisfySwitchSpeedThresholdAndTpsConditions = */ true
157 },
158 /* testData = */ {
159 {
160 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START - 1 (before entering spark skip RPM window)",
161 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START - 1,
162 0.0f,
163 {LaunchCondition::NotMet}
164 },
165 /* We've entered spark skip RPM window: */
166 {
167 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START (entering spark skip RPM window)",
168 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START,
169 TEST_INITIAL_IGNITION_CUT_RATIO,
170 {LaunchCondition::PreLaunch}
171 },
172 {
173 "rpm = (TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START + TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END) / 2 (inside spark skip RPM window)",
174 (TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START +
175 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END) / 2,
176 (TEST_INITIAL_IGNITION_CUT_RATIO + TEST_FINAL_IGNITION_CUT_RATIO) / 2,
177 {LaunchCondition::PreLaunch}
178 },
179 {
180 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END (leaving spark skip RPM window)",
181 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END,
182 TEST_FINAL_IGNITION_CUT_RATIO,
183 {LaunchCondition::PreLaunch}
184 },
185 /* We've left spark skip RPM window: */
186 {
187 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END + 1 (after spark skip RPM window)",
188 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END + 1,
189 TEST_FINAL_IGNITION_CUT_RATIO,
190 {LaunchCondition::PreLaunch}
191 },
192 {
193 "rpm = TEST_LAUNCH_RPM - 1 (before launch)",
194 TEST_LAUNCH_RPM - 1,
195 TEST_FINAL_IGNITION_CUT_RATIO,
196 {LaunchCondition::PreLaunch}
197 },
198 /* We've reached TEST_LAUNCH_RPM: */
199 {
200 "rpm = TEST_LAUNCH_RPM (launching)",
201 TEST_LAUNCH_RPM,
202 1.0f,
203 {LaunchCondition::Launch}
204 }
205 }
206 );
207 4 }
208
209 4 TEST_F(SparkSkipRatioTest, raisingRpmWithoutLaunchCondition) {
210
2/2
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
1 doTest(
211 /* config = */ {
212 /* launchControlEnabled = */ {true},
213 /* enableIgnitionCut = */ {true},
214 /* satisfySwitchSpeedThresholdAndTpsConditions = */ false
215 },
216 /* testData = */ DEFAULT_NO_LAUNCH_SPARK_SKIP_TEST_DATA
217 );
218 1 }
219
220 4 TEST_F(SparkSkipRatioTest, raisingRpmWithDisabledIgnitionCut) {
221
5/7
✓ Branch 3 taken 1 time.
✓ Branch 13 taken 1 time.
✓ Branch 16 taken 1 time.
✓ Branch 25 taken 7 times.
✓ Branch 26 taken 1 time.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
11 doTest(
222 /* config = */ {
223 /* launchControlEnabled = */ {true},
224 /* enableIgnitionCut = */ {false},
225 /* satisfySwitchSpeedThresholdAndTpsConditions = */ true
226 },
227 /* testData = */ {
228 {
229 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START - 1 (before entering spark skip RPM window)",
230 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START - 1,
231 0.0f,
232 {LaunchCondition::NotMet}
233 },
234 /* We've entered spark skip RPM window: */
235 {
236 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START (entering spark skip RPM window)",
237 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START,
238 0.0f,
239 {LaunchCondition::PreLaunch}
240 },
241 {
242 "rpm = (TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START + TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END) / 2 (inside spark skip RPM window)",
243 (TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_START +
244 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END) / 2,
245 0.0f,
246 {LaunchCondition::PreLaunch}
247 },
248 {
249 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END (leaving spark skip RPM window)",
250 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END,
251 0.0f,
252 {LaunchCondition::PreLaunch}
253 },
254 /* We've left spark skip RPM window: */
255 {
256 "rpm = TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END + 1 (after spark skip RPM window)",
257 TEST_LAUNCH_SPARK_SKIP_RPM_WINDOW_END + 1,
258 0.0f,
259 {LaunchCondition::PreLaunch}
260 },
261 {
262 "rpm = TEST_LAUNCH_RPM - 1 (before launch)",
263 TEST_LAUNCH_RPM - 1,
264 0.0f,
265 {LaunchCondition::PreLaunch}
266 },
267 /* We've reached TEST_LAUNCH_RPM: */
268 {
269 "rpm = TEST_LAUNCH_RPM (launch condition is still not satisfied)",
270 TEST_LAUNCH_RPM,
271 0.0f,
272 {LaunchCondition::Launch}
273 }
274 }
275 );
276 4 }
277
278 4 TEST_F(SparkSkipRatioTest, raisingRpmWithDisabledLaunchControl) {
279
2/2
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
1 doTest(
280 /* config = */ {
281 /* launchControlEnabled = */ {false},
282 /* enableIgnitionCut = */ {true},
283 /* satisfySwitchSpeedThresholdAndTpsConditions = */ true
284 },
285 /* testData = */ DEFAULT_NO_LAUNCH_SPARK_SKIP_TEST_DATA
286 );
287 1 }
288
289 4 TEST_F(SparkSkipRatioTest, raisingRpmWithDisabledLaunchControlAndWithoutLaunchCondition) {
290
2/2
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
1 doTest(
291 /* config = */ {
292 /* launchControlEnabled = */ {false},
293 /* enableIgnitionCut = */ {true},
294 /* satisfySwitchSpeedThresholdAndTpsConditions = */ false
295 },
296 /* testData = */ DEFAULT_NO_LAUNCH_SPARK_SKIP_TEST_DATA
297 );
298 1 }
299
300 4 TEST_F(SparkSkipRatioTest, raisingRpmWithDisabledLaunchControlAndDisabledIgnitionCut) {
301
2/2
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
1 doTest(
302 /* config = */ {
303 /* launchControlEnabled = */ {false},
304 /* enableIgnitionCut = */ {false},
305 /* satisfySwitchSpeedThresholdAndTpsConditions = */ true
306 },
307 /* testData = */ DEFAULT_NO_LAUNCH_SPARK_SKIP_TEST_DATA
308 );
309 1 }
310
311 4 TEST_F(SparkSkipRatioTest, raisingRpmWithDisabledLaunchControlAndDisabledIgnitionCutAndWithoutLaunchCondition) {
312
2/2
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
1 doTest(
313 /* config = */ {
314 /* launchControlEnabled = */ {false},
315 /* enableIgnitionCut = */ {false},
316 /* satisfySwitchSpeedThresholdAndTpsConditions = */ false
317 },
318 /* testData = */ DEFAULT_NO_LAUNCH_SPARK_SKIP_TEST_DATA
319 );
320 1 }
321
322 4 TEST_F(SparkSkipRatioTest, raisingRpmWithDisabledIgnitionCutAndWithoutLaunchCondition) {
323
2/2
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
1 doTest(
324 /* config = */ {
325 /* launchControlEnabled = */ {true},
326 /* enableIgnitionCut = */ {false},
327 /* satisfySwitchSpeedThresholdAndTpsConditions = */ false
328 },
329 /* testData = */ DEFAULT_NO_LAUNCH_SPARK_SKIP_TEST_DATA
330 );
331 1 }
332 }
333