foxBMS - Unit Tests  1.6.0
The foxBMS Unit Tests API Documentation
test_bender_iso165c.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2023, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file test_bender_iso165c.c
44  * @author foxBMS Team
45  * @date 2021-01-19 (date of creation)
46  * @updated 2023-10-12 (date of last update)
47  * @version v1.6.0
48  * @ingroup UNIT_TEST_IMPLEMENTATION
49  * @prefix TEST
50  *
51  * @brief Test of the Bender iso165c driver
52  *
53  */
54 
55 /*========== Includes =======================================================*/
56 #include "unity.h"
57 #include "Mockcan.h"
58 #include "Mockcan_cfg.h"
59 #include "Mockdatabase.h"
60 #include "Mockdiag.h"
61 #include "Mockftask.h"
62 #include "Mockio.h"
63 #include "Mockmcu.h"
64 #include "Mockmpu_prototypes.h"
65 #include "Mockos.h"
66 
67 #include "bender_iso165c.h"
69 #include "test_assert_helper.h"
70 
71 #include <stdbool.h>
72 
73 /*========== Unit Testing Framework Directives ==============================*/
74 TEST_INCLUDE_PATH("../../src/app/driver/can")
75 TEST_INCLUDE_PATH("../../src/app/driver/can/cbs")
76 TEST_INCLUDE_PATH("../../src/app/driver/config")
77 TEST_INCLUDE_PATH("../../src/app/driver/imd")
78 TEST_INCLUDE_PATH("../../src/app/driver/imd/bender/iso165c")
79 TEST_INCLUDE_PATH("../../src/app/driver/imd/bender/iso165c/config")
80 TEST_INCLUDE_PATH("../../src/app/driver/io")
81 TEST_INCLUDE_PATH("../../src/app/driver/rtc")
82 TEST_INCLUDE_PATH("../../src/app/engine/diag")
83 TEST_INCLUDE_PATH("../../src/app/task/config")
84 TEST_INCLUDE_PATH("../../src/app/task/ftask")
85 
86 /*========== Definitions and Implementations for Unit Test ==================*/
87 
91 volatile bool ftsk_allQueuesCreated = false;
92 
94  .canNodeRegister = canREG1,
95 };
96 
98  .canNodeRegister = canREG2, /* Isolated CAN interface */
99 };
100 
101 /*========== Setup and Teardown =============================================*/
102 void setUp(void) {
103 }
104 
105 void tearDown(void) {
106 }
107 
108 /*========== Test Cases =====================================================*/
109 
110 /**
111  * @brief Test function to compose/use CAN messages.
112  *
113  */
115  CAN_BUFFER_ELEMENT_s canMessage;
116  uint8_t dataWord;
117  uint8_t dataByte;
118  uint16_t data16;
119  uint8_t data8;
120  uint8_t command;
121  uint8_t id;
122  uint8_t tries;
123 
124  /* Do as if there is a message in the queue */
125  OS_GetNumberOfStoredMessagesInQueue_IgnoreAndReturn(1u);
126  MPU_xQueueReceive_IgnoreAndReturn(1u);
127  OS_ReceiveFromQueue_IgnoreAndReturn(OS_SUCCESS);
128 
129  canMessage.id = 0x22u;
130  for (uint8_t i = 1u; i <= 8u; i++) {
131  canMessage.data[i] = i;
132  }
134  /* Reset must set all data to 0 */
135  TEST_I165C_ResetCanData(&canMessage);
136  for (uint8_t i = 0u; i < 8u; i++) {
137  TEST_ASSERT_EQUAL(0u, canMessage.data[i]);
138  }
139 
140  data16 = 666u;
141  dataWord = I165C_DW1;
143  /* Test that data is written correctly to CAN frame */
144  TEST_I165C_WriteDataWord(dataWord, data16, &canMessage);
145  TEST_ASSERT_EQUAL(0x9Au, canMessage.data[1u]);
146  TEST_ASSERT_EQUAL(0x02u, canMessage.data[2u]);
147  dataWord = I165C_DW2;
148  TEST_I165C_WriteDataWord(dataWord, data16, &canMessage);
149  TEST_ASSERT_EQUAL(0x9Au, canMessage.data[3u]);
150  TEST_ASSERT_EQUAL(0x02u, canMessage.data[4u]);
151 
152  for (uint8_t i = 1u; i <= 4u; i++) {
153  canMessage.data[i] = i;
154  }
155  data16 = 0u;
156  dataWord = I165C_DW1;
158  /* Test that dataword data is read correctly from usual CAN frame */
159  TEST_I165C_ReadDataWord(dataWord, &data16, canMessage);
160  TEST_ASSERT_EQUAL(0x201u, data16);
161  data16 = 0u;
162  dataWord = I165C_DW2;
163  TEST_I165C_ReadDataWord(dataWord, &data16, canMessage);
164  TEST_ASSERT_EQUAL(0x403u, data16);
165 
166  for (uint8_t i = 0u; i <= 5u; i++) {
167  canMessage.data[i] = i + 1u;
168  }
169  data16 = 0u;
170  dataWord = I165C_DW1;
172  /* Test that dataword data is read correctly from special IMD_Info CAN frame */
173  TEST_I165C_ReadDataWordImdInfo(dataWord, &data16, canMessage);
174  TEST_ASSERT_EQUAL(0x201u, data16);
175  data16 = 0u;
176  dataWord = I165C_DW2;
177  TEST_I165C_ReadDataWordImdInfo(dataWord, &data16, canMessage);
178  TEST_ASSERT_EQUAL(0x403u, data16);
179  data16 = 0u;
180  dataWord = I165C_DW3;
181  TEST_I165C_ReadDataWordImdInfo(dataWord, &data16, canMessage);
182  TEST_ASSERT_EQUAL(0x605u, data16);
183 
184  for (uint8_t i = 1u; i <= 4u; i++) {
185  canMessage.data[i] = i;
186  }
187  data8 = 0u;
188  dataByte = I165C_DB1;
190  /* Test that databyte data is read correctly from usual CAN frame */
191  TEST_I165C_ReadDataByte(dataByte, &data8, canMessage);
192  TEST_ASSERT_EQUAL(0x1u, data8);
193  data8 = 0u;
194  dataByte = I165C_DB2;
195  TEST_I165C_ReadDataByte(dataByte, &data8, canMessage);
196  TEST_ASSERT_EQUAL(0x2u, data8);
197  data8 = 0u;
198  dataByte = I165C_DB3;
199  TEST_I165C_ReadDataByte(dataByte, &data8, canMessage);
200  TEST_ASSERT_EQUAL(0x3u, data8);
201  data8 = 0u;
202  dataByte = I165C_DB4;
203  TEST_I165C_ReadDataByte(dataByte, &data8, canMessage);
204  TEST_ASSERT_EQUAL(0x4u, data8);
205 
206  id = 0xA;
207  command = 0xB;
209  /* Test that cmd is written correctly to CAN frame */
210  TEST_I165C_WriteCmd(id, command, &canMessage);
211  TEST_ASSERT_EQUAL(0xAu, canMessage.id);
212  TEST_ASSERT_EQUAL(I165C_RX_MESSAGE_IDENTIFIER_TYPE, canMessage.idType);
213  TEST_ASSERT_EQUAL(0xBu, canMessage.data[0u]);
214 
215  /* Check assertion of invalid parameter */
216  canMessage.data[0u] = 0xA;
217  command = 0xA;
219 
220  /* Check that response ID corresponds to awaited acknowledge */
221  canMessage.id = CANRX_IMD_RESPONSE_ID;
222  canMessage.data[0u] = 0xA;
223  command = 0xA;
224  TEST_ASSERT_EQUAL(true, TEST_I165C_CheckResponse(command, &canMessage));
225 
226  /* Check that response ID does not correspond to awaited acknowledge */
227  canMessage.id = CANRX_IMD_RESPONSE_ID;
228  canMessage.data[0u] = 0xA;
229  command = 0xB;
230  TEST_ASSERT_EQUAL(false, TEST_I165C_CheckResponse(command, &canMessage));
231 
232  /* Check that response failed if ID is not CANRX_IMD_RESPONSE_ID, even if response matches command */
233  canMessage.id = CANRX_IMD_INFO_ID;
234  canMessage.data[0u] = 0xA;
235  command = 0xA;
236  TEST_ASSERT_EQUAL(false, TEST_I165C_CheckResponse(command, &canMessage));
237 
238  /* Check that response failed if ID is not CANRX_IMD_RESPONSE_ID, if respose does not match command */
239  canMessage.id = CANRX_IMD_INFO_ID;
240  canMessage.data[0u] = 0xA;
241  command = 0xB;
242  TEST_ASSERT_EQUAL(false, TEST_I165C_CheckResponse(command, &canMessage));
243 
244  canMessage.id = I165C_MESSAGETYPE_IMD_INFO;
246  /* Test that an IMD_info frame was received on CAN */
247  TEST_ASSERT_EQUAL(true, TEST_I165C_GetImdInfo(&canMessage));
248  canMessage.id = I165C_MESSAGETYPE_IMD_INFO + 1u;
249  TEST_ASSERT_EQUAL(false, TEST_I165C_GetImdInfo(&canMessage));
250 
251  /* Test if CAN data indicated that iso165c is not initialized */
252  for (uint8_t i = 0u; i < 8u; i++) {
253  canMessage.data[i] = 0u;
254  }
255  TEST_ASSERT_EQUAL(false, TEST_I165C_IsSelfTestFinished(canMessage));
256 
257  /* Test if CAN data indicated that iso165c is not initialized */
258  for (uint8_t i = 0u; i < 8u; i++) {
259  canMessage.data[i] = 0x00u;
260  }
261  /*
262  * D_IMC_STATUS is located in byte 2 and byte 3 of CAN message:
263  * Bit 4: Self test running -> set to 1 */
264  canMessage.data[2u] |= (1u << I165C_SELFTEST_RUNNING_SHIFT);
265  /* D_VIFC_STATUS is located in byte 4 and byte 5 of CAN message
266  * Bit 0: Insulation measurement active -> set to 0
267  * Bit 12: Self-test long executed -> set to 0
268  * Bit 13: Self-test short executed -> set to 0
269  */
270  canMessage.data[4u] |= (0u << I165C_INSULATION_MEASUREMENT_STATUS_SHIFT);
271  canMessage.data[5u] |=
272  (0u << (I165C_IMC_SELFTEST_OVERALL_SCENARIO_SHIFT - 8u)); /* Subtract 8 because upper byte is used */
273  canMessage.data[5u] |=
274  (0u << (I165C_IMC_SELFTEST_PARAMETERCONFIG_SCENARIO_SHIFT - 8u)); /* Subtract 8 because upper byte is used */
275 
276  TEST_ASSERT_EQUAL(true, TEST_I165C_IsSelfTestFinished(canMessage));
277 
278  /* ----------- Test function that waits for acknowledge -----------------*/
279 
280  /* Check for invalid function parameters */
284 
285  /* Acknowledge arrived */
286  canMessage.id = CANRX_IMD_RESPONSE_ID;
287  tries = 0u;
288  command = 0xA;
289  canMessage.data[0] = 0xA;
290  bool ackReceived = false;
291 
292  ackReceived = TEST_I165C_CheckAcknowledgeArrived(command, &tries, &canMessage);
293  TEST_ASSERT_EQUAL(true, ackReceived);
294  TEST_ASSERT_EQUAL(0u, tries);
295 
296  /* Acknowledge not arrived, increment try counter */
297  canMessage.id = CANRX_IMD_RESPONSE_ID;
298  tries = 0u;
299  command = 0xA;
300  canMessage.data[0] = 0xB;
301 
302  ackReceived = TEST_I165C_CheckAcknowledgeArrived(command, &tries, &canMessage);
303  TEST_ASSERT_EQUAL(1u, tries);
304  TEST_ASSERT_EQUAL(false, ackReceived);
305 
306  /* Acknowledge not arrived, and allowed number of tries made, restart
307  * Initialization (go to self test) */
308  tries = I165C_TRANSMISSION_ATTEMPTS - 1u;
309  command = 0xA;
310  canMessage.data[0] = 0xB;
311 
312  ackReceived = TEST_I165C_CheckAcknowledgeArrived(command, &tries, &canMessage);
313  TEST_ASSERT_EQUAL(I165C_TRANSMISSION_ATTEMPTS, tries);
314  TEST_ASSERT_EQUAL(false, ackReceived);
315 }
void TEST_I165C_WriteCmd(uint8_t id, uint8_t command, CAN_BUFFER_ELEMENT_s *canMessage)
void TEST_I165C_ReadDataByte(uint8_t dataByte, uint8_t *data, CAN_BUFFER_ELEMENT_s canMessage)
bool TEST_I165C_GetImdInfo(CAN_BUFFER_ELEMENT_s *canMessage)
bool TEST_I165C_IsSelfTestFinished(CAN_BUFFER_ELEMENT_s canMessage)
void TEST_I165C_ResetCanData(CAN_BUFFER_ELEMENT_s *canMessage)
void TEST_I165C_ReadDataWordImdInfo(uint8_t dataWord, uint16_t *data, CAN_BUFFER_ELEMENT_s canMessage)
bool TEST_I165C_CheckAcknowledgeArrived(uint8_t command, uint8_t *tries, CAN_BUFFER_ELEMENT_s *canMessage)
void TEST_I165C_ReadDataWord(uint8_t dataWord, uint16_t *data, CAN_BUFFER_ELEMENT_s canMessage)
bool TEST_I165C_CheckResponse(uint8_t command, CAN_BUFFER_ELEMENT_s *canMessage)
void TEST_I165C_WriteDataWord(uint8_t dataWord, uint16_t data, CAN_BUFFER_ELEMENT_s *canMessage)
Headers for the driver for the insulation monitoring.
#define I165C_IMC_SELFTEST_PARAMETERCONFIG_SCENARIO_SHIFT
#define I165C_INSULATION_MEASUREMENT_STATUS_SHIFT
#define I165C_DB2
#define I165C_TRANSMISSION_ATTEMPTS
#define I165C_RX_MESSAGE_IDENTIFIER_TYPE
#define I165C_MESSAGETYPE_IMD_INFO
#define I165C_DW2
#define I165C_SELFTEST_RUNNING_SHIFT
#define I165C_DB3
#define I165C_DW1
#define I165C_DB1
#define I165C_IMC_SELFTEST_OVERALL_SCENARIO_SHIFT
#define I165C_DW3
#define I165C_DB4
Header for the driver for the CAN module.
#define CANRX_IMD_INFO_ID
#define CANRX_IMD_RESPONSE_ID
static DIAG_DIAGNOSIS_STATE_s diag
Definition: diag.c:71
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:77
@ OS_SUCCESS
Definition: os.h:86
uint8_t data[CAN_MAX_DLC]
Definition: can_cfg.h:173
CAN_IDENTIFIER_TYPE_e idType
Definition: can_cfg.h:172
canBASE_t * canNodeRegister
Definition: can_cfg.h:76
Helper for unit tests.
#define TEST_ASSERT_FAIL_ASSERT(_code_under_test)
assert whether assert macro has failed
OS_QUEUE ftsk_imdCanDataQueue
volatile bool ftsk_allQueuesCreated
void testMessageComposition(void)
Test function to compose/use CAN messages.
void setUp(void)
void tearDown(void)
const CAN_NODE_s can_node1
OS_QUEUE ftsk_canRxQueue
const CAN_NODE_s can_node2Isolated
OS_QUEUE ftsk_dataQueue