GCC Code Coverage Report


Directory: ./
File: unit_tests/tests/controllers/can/test_can_wideband.cpp
Date: 2025-10-03 00:57:22
Coverage Exec Excl Total
Lines: 100.0% 203 0 203
Functions: 100.0% 24 0 24
Branches: 47.4% 120 0 253
Decisions: -% 0 - 0

Line Branch Decision Exec Source
1 #include "pch.h"
2
3 #include "AemXSeriesLambda.h"
4
5 4 TEST(CanWideband, AcceptFrameId0) {
6
1/1
✓ Branch 2 taken 1 time.
1 AemXSeriesWideband dut(0, SensorType::Lambda1);
7
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
8
9 1 CANRxFrame frame;
10
11 // AEM uses extended CAN ID!
12 1 frame.IDE = true;
13 1 frame.DLC = 8;
14
15 1 engineConfiguration->canWbo[0].type = AEM;
16
17 // Check that the AEM format frame is accepted
18 1 frame.EID = 0x180;
19
2/7
✓ Branch 3 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
1 EXPECT_TRUE(dut.acceptFrame(0, frame));
20
21 // Check that the AEM frame with standard CAN ID is not accepted
22 1 frame.IDE = false;
23 1 frame.SID = 0x180;
24
2/7
✓ Branch 3 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
1 EXPECT_FALSE(dut.acceptFrame(0, frame));
25
26 // Now switch to RusEFI
27 1 engineConfiguration->canWbo[0].type = RUSEFI;
28
29 // Check that the rusEFI standard data is accepted
30 1 frame.IDE = false;
31 1 frame.SID = 0x190;
32
2/7
✓ Branch 3 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
1 EXPECT_TRUE(dut.acceptFrame(0, frame));
33
34 // Check that the rusEFI extended data is accepted
35 1 frame.SID = 0x191;
36
2/7
✓ Branch 3 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
1 EXPECT_TRUE(dut.acceptFrame(0, frame));
37
38 // Check that the rusEFI frames with extended CAN ID are not accepted
39 1 frame.IDE = true;
40 1 frame.EID = 0x190;
41
2/7
✓ Branch 3 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
1 EXPECT_FALSE(dut.acceptFrame(0, frame));
42 1 frame.EID = 0x191;
43
2/7
✓ Branch 3 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
1 EXPECT_FALSE(dut.acceptFrame(0, frame));
44 2 }
45
46 4 TEST(CanWideband, AcceptFrameId1) {
47
1/1
✓ Branch 2 taken 1 time.
1 AemXSeriesWideband dut(1, SensorType::Lambda2);
48
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
49
50 1 CANRxFrame frame;
51
52 // AEM uses extended CAN ID!
53 1 frame.IDE = true;
54 1 frame.DLC = 8;
55
56 1 engineConfiguration->canWbo[1].type = AEM;
57 1 engineConfiguration->canWbo[1].aemId = WBO_AEM_ID2;
58
59 // Check that the AEM format frame is accepted
60 1 frame.EID = 0x181;
61
2/7
✓ Branch 3 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
1 EXPECT_TRUE(dut.acceptFrame(0, frame));
62
63 // Now switch to RusEFI
64 1 engineConfiguration->canWbo[1].type = RUSEFI;
65 1 engineConfiguration->canWbo[1].reId = WBO_RE_ID2;
66
67 // Check that the rusEFI standard data is accepted
68 1 frame.IDE = false;
69 1 frame.SID = 0x192;
70
2/7
✓ Branch 3 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
1 EXPECT_TRUE(dut.acceptFrame(0, frame));
71
72 // Check that the rusEFI extended data is accepted
73 1 frame.SID = 0x193;
74
2/7
✓ Branch 3 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 21 not taken.
✗ Branch 24 not taken.
1 EXPECT_TRUE(dut.acceptFrame(0, frame));
75 2 }
76
77 class AemXSeriesWidebandWrapper: AemXSeriesWideband {
78 public:
79 using AemXSeriesWideband::AemXSeriesWideband;
80 using AemXSeriesWideband::decodeAemXSeries;
81 using AemXSeriesWideband::Register;
82 };
83
84 4 TEST(CanWideband,DecodeAemXSeriesInvalidLambda){
85
1/1
✓ Branch 2 taken 1 time.
1 AemXSeriesWidebandWrapper wbo(0, SensorType::Lambda1);
86
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
87 1 CANRxFrame frame;
88
89 1 engineConfiguration->canWbo[0].type = AEM;
90
91 // AEM uses extended CAN ID!
92 1 frame.IDE = true;
93 1 frame.EID = 0x180;
94
95 1 frame.DLC = 8;
96
97 1 frame.data8[0] = 0x1F;
98 1 frame.data8[1] = 0x40;
99 1 frame.data8[2] = 0;
100 1 frame.data8[3] = 0;
101 1 frame.data8[4] = 0x79;
102 1 frame.data8[5] = 0x6E;
103 1 frame.data8[6] = 0b01000000;
104 1 frame.data8[7] = 0;
105
106
3/8
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
1 EXPECT_FALSE(wbo.decodeAemXSeries(frame, getTimeNowNt()));
107 2 }
108
109 4 TEST(CanWideband,DecodeAemXSeriesSensorFault){
110
1/1
✓ Branch 2 taken 1 time.
1 AemXSeriesWidebandWrapper wbo(0, SensorType::Lambda1);
111
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
112 1 CANRxFrame frame;
113
114 1 engineConfiguration->canWbo[0].type = AEM;
115
116 // AEM uses extended CAN ID!
117 1 frame.IDE = true;
118 1 frame.EID = 0x180;
119
120 1 frame.DLC = 8;
121
122 1 frame.data8[0] = 0x1F;
123 1 frame.data8[1] = 0x40;
124 1 frame.data8[2] = 0;
125 1 frame.data8[3] = 0;
126 1 frame.data8[4] = 0x79;
127 1 frame.data8[5] = 0x6E;
128 1 frame.data8[6] = 0;
129 1 frame.data8[7] = 0b00000010;
130
131
3/8
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
1 EXPECT_FALSE(wbo.decodeAemXSeries(frame, getTimeNowNt()));
132 2 }
133
134
135 4 TEST(CanWideband,DecodeAemXSeriesValidLambda){
136
1/1
✓ Branch 2 taken 1 time.
1 AemXSeriesWidebandWrapper wbo(0, SensorType::Lambda1);
137
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
138 // we dont call initLambda on the tests init code. so we need to register this sensor on the test
139
1/1
✓ Branch 1 taken 1 time.
1 smoothedLambda1Sensor.Register();
140
141 1 engineConfiguration->canWbo[0].type = AEM;
142
143 // only this tests needs register
144
1/1
✓ Branch 1 taken 1 time.
1 wbo.Register();
145
146 1 CANRxFrame frame;
147
148 // AEM uses extended CAN ID!
149 1 frame.IDE = true;
150 1 frame.EID = 0x180;
151
152 1 frame.DLC = 8;
153
154 1 frame.data8[0] = 0x2F; // 8000, lambda 0.8
155 1 frame.data8[1] = 0x00;
156 1 frame.data8[2] = 0;
157 1 frame.data8[3] = 0;
158 1 frame.data8[4] = 0;
159 1 frame.data8[5] = 0;
160 1 frame.data8[6] =
161 1 << 1 | // LSU 4.9 detected
162 1 << 7; // Data valid
163 1 frame.data8[7] = 0;
164
165
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 wbo.decodeAemXSeries(frame, getTimeNowNt());
166
167
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(1.2032f, Sensor::get(SensorType::Lambda1).value_or(-1));
168
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(1.2032f, Sensor::get(SensorType::SmoothedLambda1).value_or(-1));
169
1/1
✓ Branch 1 taken 1 time.
1 Sensor::resetRegistry();
170 2 }
171
172 4 TEST(CanWideband, DecodeValidAemFormat) {
173
1/1
✓ Branch 2 taken 1 time.
1 AemXSeriesWideband dut(0, SensorType::Lambda1);
174
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
175
1/1
✓ Branch 1 taken 1 time.
1 dut.Register();
176
177 1 engineConfiguration->canWbo[0].type = AEM;
178
179 // check not set
180
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(-1, Sensor::get(SensorType::Lambda1).value_or(-1));
181
182 1 CANRxFrame frame;
183
184 // AEM uses extended CAN ID!
185 1 frame.IDE = true;
186 1 frame.EID = 0x180;
187
188 1 frame.DLC = 8;
189
190 1 frame.data8[0] = 0x1F;
191 1 frame.data8[1] = 0x40;
192 1 frame.data8[2] = 0;
193 1 frame.data8[3] = 0;
194 1 frame.data8[4] = 0;
195 1 frame.data8[5] = 0;
196 1 frame.data8[6] =
197 1 << 1 | // LSU 4.9 detected
198 1 << 7; // Data valid
199 1 frame.data8[7] = 0;
200
201 // check that lambda updates
202
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, frame, getTimeNowNt());
203
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(0.8f, Sensor::get(SensorType::Lambda1).value_or(-1));
204
205
206 // Now check invalid data
207 1 frame.data8[6] =
208 1 << 1 | // LSU 4.9 detected
209 0 << 7; // Data INVALID
210
211
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, frame, getTimeNowNt());
212
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(-1, Sensor::get(SensorType::Lambda1).value_or(-1));
213
214
215 // Now check sensor fault
216 1 frame.data8[6] =
217 1 << 1 | // LSU 4.9 detected
218 1 << 7; // Data valid
219 1 frame.data8[7] = 1 << 6; // Sensor fault!
220
221
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, frame, getTimeNowNt());
222
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(-1, Sensor::get(SensorType::Lambda1).value_or(-1));
223
224
1/1
✓ Branch 1 taken 1 time.
1 Sensor::resetRegistry();
225 2 }
226
227 #include "wideband_firmware/for_rusefi/wideband_can.h"
228
229 4 TEST(CanWideband, DecodeRusefiStandard)
230 {
231
1/1
✓ Branch 2 taken 1 time.
1 AemXSeriesWideband dut(0, SensorType::Lambda1);
232
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
233 // we dont call initLambda on the tests init code. so we need to register this sensor on the test
234
1/1
✓ Branch 1 taken 1 time.
1 smoothedLambda1Sensor.Register();
235
236 1 engineConfiguration->canWbo[0].type = RUSEFI;
237
238
1/1
✓ Branch 1 taken 1 time.
1 dut.Register();
239
240 1 CANRxFrame frame;
241 1 frame.SID = 0x190;
242 1 frame.IDE = false;
243 1 frame.DLC = 8;
244
245 // version
246 1 frame.data8[0] = RUSEFI_WIDEBAND_VERSION;
247
248 // valid
249 1 frame.data8[1] = 1;
250
251 // data = 0.7 lambda
252 1 *reinterpret_cast<uint16_t*>(&frame.data8[2]) = 7000;
253
254 // data = 1234 deg C
255 1 *reinterpret_cast<uint16_t*>(&frame.data8[4]) = 1234;
256
257 1 CANRxFrame diagFrame;
258 1 diagFrame.SID = 0x191;
259 1 diagFrame.IDE = false;
260 1 diagFrame.DLC = 8;
261
262 // ESR
263 1 *reinterpret_cast<uint16_t*>(&diagFrame.data8[0]) = 720;
264
265 // nernst DC
266 1 *reinterpret_cast<uint16_t*>(&diagFrame.data8[2]) = 450;
267
268 // PumpDuty
269 1 diagFrame.data8[4] = 127;
270
271 // Status
272 1 diagFrame.data8[5] = 0;
273
274 // HeaterDuty
275 1 diagFrame.data8[6] = 127;
276
277 // check not set
278
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(-1, Sensor::get(SensorType::Lambda1).value_or(-1));
279
280 // check that lambda updates
281
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, frame, getTimeNowNt());
282
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, diagFrame, getTimeNowNt());
283
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(0.7f, Sensor::get(SensorType::Lambda1).value_or(-1));
284
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(0.7f, Sensor::get(SensorType::SmoothedLambda1).value_or(-1));
285
286 // Check that temperature updates
287
2/6
✓ Branch 3 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 11 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
1 EXPECT_EQ(dut.tempC, 1234);
288
289 // Check that valid bit is respected (should be invalid now)
290 1 frame.data8[1] = 0;
291
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, frame, getTimeNowNt());
292
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, diagFrame, getTimeNowNt());
293
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(-1, Sensor::get(SensorType::Lambda1).value_or(-1));
294
295 // ...but no error until egine is runnig
296
2/6
✓ Branch 3 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 11 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
1 EXPECT_EQ((uint8_t)wbo::Fault::NotAllowed, dut.faultCode);
297
298 // Now driver should handle valid bit and error states from wbo
299 1 engine->engineState.heaterControlEnabled = true;
300
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, frame, getTimeNowNt());
301
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, diagFrame, getTimeNowNt());
302
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(-1, Sensor::get(SensorType::Lambda1).value_or(-1));
303
304 // make valid again, but report WBO error in diagnostic frame
305 1 frame.data8[1] = 1;
306 1 diagFrame.data8[5] = (uint8_t)wbo::Fault::SensorNoHeatSupply;
307
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, frame, getTimeNowNt());
308
2/2
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
1 dut.processFrame(0, diagFrame, getTimeNowNt());
309
2/6
✓ Branch 3 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 11 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
1 EXPECT_EQ((uint8_t)wbo::Fault::SensorNoHeatSupply, dut.faultCode);
310
3/7
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
1 EXPECT_FLOAT_EQ(0.7f, Sensor::get(SensorType::Lambda1).value_or(-1));
311 2 }
312
313 4 TEST(CanWideband, DecodeRusefiStandardWrongVersion)
314 {
315
1/1
✓ Branch 2 taken 1 time.
1 AemXSeriesWideband dut(0, SensorType::Lambda1);
316
1/1
✓ Branch 2 taken 1 time.
1 EngineTestHelper eth(engine_type_e::TEST_ENGINE);
317
318 1 engineConfiguration->canWbo[0].type = RUSEFI;
319
320
1/1
✓ Branch 1 taken 1 time.
1 dut.Register();
321
322 1 CANRxFrame frame;
323 1 frame.SID = 0x190;
324 1 frame.IDE = false;
325 1 frame.DLC = 8;
326
327 // version - WRONG VERSION ON PURPOSE!
328 1 frame.data8[0] = RUSEFI_WIDEBAND_VERSION_MIN - 1;
329
330
6/24
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 time.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 time.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 time.
✗ Branch 19 not taken.
✗ Branch 27 not taken.
✗ Branch 32 not taken.
✗ Branch 35 not taken.
✓ Branch 42 taken 1 time.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 49 not taken.
✗ Branch 54 not taken.
✗ Branch 57 not taken.
✗ Branch 63 not taken.
✗ Branch 67 not taken.
✗ Branch 70 not taken.
✗ Branch 75 not taken.
✗ Branch 78 not taken.
1 EXPECT_FATAL_ERROR(dut.processFrame(0, frame, getTimeNowNt()));
331 2 }
332