foxBMS - Unit Tests  1.4.1
The foxBMS Unit Tests API Documentation
test_bms.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2022, 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_bms.c
44  * @author foxBMS Team
45  * @date 2020-04-01 (date of creation)
46  * @updated 2022-10-27 (date of last update)
47  * @version v1.4.1
48  * @ingroup UNIT_TEST_IMPLEMENTATION
49  * @prefix TEST
50  *
51  * @brief Tests for the bms driver implementation
52  */
53 
54 /*========== Includes =======================================================*/
55 #include "unity.h"
56 #include "Mockafe.h"
57 #include "Mockbal.h"
58 #include "Mockbattery_system_cfg.h"
59 #include "Mockcontactor.h"
60 #include "Mockdatabase.h"
61 #include "Mockdiag.h"
62 #include "Mockfassert.h"
63 #include "Mockimd.h"
64 #include "Mockinterlock.h"
65 #include "Mockled.h"
66 #include "Mockmeas.h"
67 #include "Mockos.h"
68 #include "Mockplausibility.h"
69 #include "Mocksoa.h"
70 
71 #include "sps_cfg.h"
72 
73 #include "bms.h"
74 #include "foxmath.h"
75 #include "test_assert_helper.h"
76 
77 /*========== Definitions and Implementations for Unit Test ==================*/
79 
82  .pConfigurationOfDiagnosisEntries = &diag_diagnosisIdConfiguration[0],
83  .numberOfFatalErrors = 0u,
84 };
85 
88 };
89 
91  /* String contactors configuration */
95  BS_STRING0,
96  CONT_PLUS,
102  BS_STRING0,
103  CONT_MINUS,
106  /* Precharge contactors configuration */
110  BS_STRING0,
114 };
115 
116 /*========== Setup and Teardown =============================================*/
117 void setUp(void) {
118 }
119 
120 void tearDown(void) {
121 }
122 
123 /*========== Test Cases =====================================================*/
124 #define NUM_PRECHARGE_TESTS 13
126 /*
127  * mock callback in order to provide custom values to current_tab
128  */
129 STD_RETURN_TYPE_e MockDATA_ReadBlock_Callback(void *pDataToReceiver, int num_calls) {
130  int32_t current = 0;
131  int32_t voltage_1 = 0;
132  int32_t voltage_2 = 0;
133 
134  /* determine a value depending on num_calls (has to be synchronized with test) */
135  switch (num_calls) {
136  case 0:
138  /* no current, no voltage difference --> expect OK */
139  current = 0;
140  voltage_1 = 0;
141  voltage_2 = 0;
142  break;
143  case 1:
145  /* INT32_MAX current, no voltage difference --> expect NOK */
146  current = INT32_MAX;
147  voltage_1 = 0;
148  voltage_2 = 0;
149  break;
150  case 2:
152  /* INT32_MIN current, no voltage difference --> expect NOK */
153  current = INT32_MIN;
154  voltage_1 = 0;
155  voltage_2 = 0;
156  break;
157  case 3:
159  /* no current, no voltage difference --> expect OK */
160  current = 0;
161  voltage_1 = INT32_MAX;
162  voltage_2 = INT32_MAX;
163  break;
164  case 4:
166  /* no current, no voltage difference --> expect OK */
167  current = 0;
168  voltage_1 = INT32_MIN;
169  voltage_2 = INT32_MIN;
170  break;
171  case 5:
173  /* no current, maximum voltage difference --> expect NOK */
174  current = 0;
175  voltage_1 = INT32_MAX;
176  voltage_2 = INT32_MIN;
177  break;
178  case 6:
180  /* no current, maximum voltage difference --> expect NOK */
181  current = 0;
182  voltage_1 = INT32_MIN;
183  voltage_2 = INT32_MAX;
184  break;
185  case 7:
187  /* current exactly at threshold, no voltage difference --> expect NOK */
189  voltage_1 = 0;
190  voltage_2 = 0;
191  break;
192  case 8:
194  /* no current, voltage difference exactly at threshold --> expect NOK */
195  current = 0;
197  voltage_2 = 0;
198  break;
199  case 9:
201  /* no current, voltage difference exactly at threshold --> expect NOK */
202  current = 0;
203  voltage_1 = 0;
205  break;
206  case 10:
208  /* current exactly 1 below threshold, no voltage difference --> expect OK */
210  voltage_1 = 0;
211  voltage_2 = 0;
212  break;
213  case 11:
215  /* no current, voltage difference exactly 1 below threshold --> expect OK */
216  current = 0;
217  voltage_1 = BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV - 1;
218  voltage_2 = 0;
219  break;
220  case 12:
222  /* no current, voltage difference exactly 1 below threshold --> expect OK */
223  current = 0;
224  voltage_1 = 0;
225  voltage_2 = BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV - 1;
226  break;
227  default:
228  TEST_FAIL_MESSAGE("DATA_ReadBlock_Callback was called too often");
229  }
230  /* ENTER HIGHEST CASE NUMBER IN EXPECT; checks whether all cases are used */
231  TEST_ASSERT_EQUAL_MESSAGE(12, (NUM_PRECHARGE_TESTS - 1), "Check code of stub. Something does not fit.");
232 
233  if (num_calls >= NUM_PRECHARGE_TESTS) {
234  TEST_FAIL_MESSAGE("This stub is fishy, prechargeExpectedResults is too short for the number of calls");
235  }
236 
237  /* cast to correct struct in order to properly write current and other values */
238  for (uint8_t s = 0; s < BS_NR_OF_STRINGS; s++) {
239  for (uint8_t testNumber = 0; testNumber < NUM_PRECHARGE_TESTS; testNumber++) {
240  prechargeExpectedResults[s][testNumber] = prechargeExpectedResults[0][testNumber];
241  }
242 
243  ((DATA_BLOCK_PACK_VALUES_s *)pDataToReceiver)->stringCurrent_mA[0] = current;
244  ((DATA_BLOCK_PACK_VALUES_s *)pDataToReceiver)->stringVoltage_mV[0] = voltage_1;
245  }
246  ((DATA_BLOCK_PACK_VALUES_s *)pDataToReceiver)->highVoltageBusVoltage_mV = voltage_2;
247 
248  return STD_OK;
249 }
250 
251 /**
252  * @brief Iterate over a callback that supplies various scenarios and check if they work as expected
253  * @details This function uses the callback #MockDATA_ReadBlock_Callback() in order to inject
254  * current tables and voltage tables into the returned database tables. The array
255  * #prechargeExpectedResults contains prepared return values against which the output
256  * of #TEST_BMS_CheckPrecharge() is compared.
257  */
259  /* tell CMock to use our callback */
260  DATA_Read1DataBlock_Stub(MockDATA_ReadBlock_Callback);
261 
263 
264  /* iterate until we have all covered cases from our stub processed */
265  for (uint8_t i = 0u; i < NUM_PRECHARGE_TESTS; i++) {
266  char buffer[30];
267  snprintf(buffer, 30, "Loop iteration %d.", i);
268  for (uint8_t s = 0; s < BS_NR_OF_STRINGS; s++) {
269  TEST_ASSERT_EQUAL_MESSAGE(
270  prechargeExpectedResults[s][i], TEST_BMS_CheckPrecharge(s, &tablePackValues), buffer);
271  }
272  }
273 }
274 
276  /*
277  WARNING: the function under test has code that is unaccessible
278  in order to solve this situation it has to be refactored
279  so that the branch in it does not always evaluate to true.
280 
281  However, the way it is implemented now, the unit test will be
282  always valid for the currently active defines.
283  */
284 
285 #if (POSITIVE_DISCHARGE_CURRENT == true)
286  /* discharge is positive */
287 
288  /* maximum positive current has to be discharge */
289  TEST_ASSERT_EQUAL(BMS_DISCHARGING, BMS_GetCurrentFlowDirection(INT32_MAX));
290 
291  /* maximum negative current has to be charge */
292  TEST_ASSERT_EQUAL(BMS_CHARGING, BMS_GetCurrentFlowDirection(INT32_MIN));
293 #else
294  /* discharge is negative */
295 
296  /* maximum positive current has to be charge */
297  TEST_ASSERT_EQUAL(BMS_CHARGING, BMS_GetCurrentFlowDirection(INT32_MAX));
298 
299  /* maximum negative current has to be discharge */
300  TEST_ASSERT_EQUAL(BMS_DISCHARGING, BMS_GetCurrentFlowDirection(INT32_MIN));
301 #endif
302 
303  /* zero current has to be no charge */
304  TEST_ASSERT_EQUAL(BMS_AT_REST, BMS_GetCurrentFlowDirection(0));
305 
306  /* positive current below/equal to resting current is no current too */
307  TEST_ASSERT_EQUAL(BMS_AT_REST, BMS_GetCurrentFlowDirection(0 + BS_REST_CURRENT_mA - 1));
308 
309  /* negative current below/equal to resting current is no current too */
310  TEST_ASSERT_EQUAL(BMS_AT_REST, BMS_GetCurrentFlowDirection(0 - BS_REST_CURRENT_mA + 1));
311 
312  /* function should have same behavior for #BS_CS_THRESHOLD_NO_CURRENT_mA */
313  TEST_ASSERT_EQUAL(
316 }
317 
319  /* Set the current to 0 */
320  TEST_ASSERT_EQUAL(BMS_AT_REST, BMS_GetCurrentFlowDirection(0u));
321 
322  /* Set the current to #INT32_MAX */
323 #if (POSITIVE_DISCHARGE_CURRENT == true)
324  TEST_ASSERT_EQUAL(BMS_DISCHARGING, BMS_GetCurrentFlowDirection(INT32_MAX));
325 #else
326  TEST_ASSERT_EQUAL(BMS_CHARGING, BMS_GetCurrentFlowDirection(INT32_MAX));
327 #endif
328 
329  /* Set the current to #INT32_MIN */
330 #if (POSITIVE_DISCHARGE_CURRENT == true)
331  TEST_ASSERT_EQUAL(BMS_CHARGING, BMS_GetCurrentFlowDirection(INT32_MIN));
332 #else
333  TEST_ASSERT_EQUAL(BMS_DISCHARGING, BMS_GetCurrentFlowDirection(INT32_MIN));
334 #endif
335 }
336 
337 /** check that invalid values to BMS_CheckPrecharge trip an assertion
338  *
339  * invalid values are all those that do not fall into
340  * 0 <= stringNumber < #BS_NR_OF_STRINGS
341  */
346  TEST_ASSERT_FAIL_ASSERT(TEST_BMS_CheckPrecharge(UINT8_MAX, &tablePackValues));
347 
348  TEST_ASSERT_PASS_ASSERT(TEST_BMS_CheckPrecharge(0u, &tablePackValues));
349 }
#define BS_NR_OF_STRINGS
Number of parallel strings in the battery pack.
#define BS_REST_CURRENT_mA
current threshold for determing rest state of battery. If absolute current is below this limit value ...
BS_STRING_PRECHARGE_PRESENT_e
@ BS_STRING_WITH_PRECHARGE
@ BS_STRING0
#define BS_CS_THRESHOLD_NO_CURRENT_mA
current sensor threshold for 0 current in mA as the sensor has a jitter.
STD_RETURN_TYPE_e TEST_BMS_CheckPrecharge(uint8_t stringNumber, DATA_BLOCK_PACK_VALUES_s *pPackValues)
Definition: bms.c:1649
BMS_CURRENT_FLOW_STATE_e BMS_GetCurrentFlowDirection(int32_t current_mA)
Get current flow direction, current value as function parameter.
Definition: bms.c:1573
bms driver header
@ BMS_AT_REST
Definition: bms.h:72
@ BMS_DISCHARGING
Definition: bms.h:70
@ BMS_CHARGING
Definition: bms.h:69
#define BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV
Definition: bms_cfg.h:168
#define BMS_PRECHARGE_CURRENT_THRESHOLD_mA
Definition: bms_cfg.h:171
@ CONT_HAS_NO_FEEDBACK
Definition: contactor_cfg.h:80
@ CONT_FEEDBACK_NORMALLY_OPEN
Definition: contactor_cfg.h:77
@ CONT_PRECHARGE
Definition: contactor_cfg.h:87
@ CONT_MINUS
Definition: contactor_cfg.h:86
@ CONT_PLUS
Definition: contactor_cfg.h:85
@ CONT_SWITCH_OFF
Definition: contactor_cfg.h:70
@ CONT_BIDIRECTIONAL
@ CONT_CHARGING_DIRECTION
@ CONT_DISCHARGING_DIRECTION
@ DATA_BLOCK_ID_PACK_VALUES
Definition: database_cfg.h:105
math library for often used math functions
STD_RETURN_TYPE_e
Definition: fstd_types.h:81
@ STD_NOT_OK
Definition: fstd_types.h:83
@ STD_OK
Definition: fstd_types.h:82
Header for the configuration for the driver for the smart power switches.
#define SPS_CHANNEL_2
Definition: sps_cfg.h:88
#define SPS_CHANNEL_0
Definition: sps_cfg.h:86
#define SPS_CHANNEL_1
Definition: sps_cfg.h:87
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:119
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:187
uint8_t nrOfConfiguredDiagnosisEntries
Definition: diag_cfg.h:343
Helper for unit tests.
#define TEST_ASSERT_PASS_ASSERT(_code_under_test)
assert whether assert macro has passed
#define TEST_ASSERT_FAIL_ASSERT(_code_under_test)
assert whether assert macro has failed
BS_STRING_PRECHARGE_PRESENT_e bs_stringsWithPrecharge[BS_NR_OF_STRINGS]
Definition: test_bms.c:86
#define NUM_PRECHARGE_TESTS
Definition: test_bms.c:124
STD_RETURN_TYPE_e prechargeExpectedResults[BS_NR_OF_STRINGS][NUM_PRECHARGE_TESTS]
Definition: test_bms.c:125
void testBMS_CheckPrechargeInvalidStringNumber(void)
Definition: test_bms.c:342
CONT_CONTACTOR_STATE_s cont_contactorStates[]
Definition: test_bms.c:90
void testCheckPrechargeIterateStub(void)
Iterate over a callback that supplies various scenarios and check if they work as expected.
Definition: test_bms.c:258
void setUp(void)
Definition: test_bms.c:117
void tearDown(void)
Definition: test_bms.c:120
void testBMS_GetCurrentFlowDirectionWithTypicalValues(void)
Definition: test_bms.c:275
STD_RETURN_TYPE_e MockDATA_ReadBlock_Callback(void *pDataToReceiver, int num_calls)
Definition: test_bms.c:129
void testCheckCurrentValueDirectionWithCurrentZeroMaxAndMin(void)
Definition: test_bms.c:318
DIAG_ID_CFG_s diag_diagnosisIdConfiguration[]
Definition: test_bms.c:78
DIAG_DEV_s diag_device
Definition: test_bms.c:80