foxBMS - Unit Tests  1.2.1
The foxBMS Unit Tests API Documentation
test_bms.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, 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 2021-10-05 (date of last update)
47  * @ingroup UNIT_TEST_IMPLEMENTATION
48  * @prefix TEST
49  *
50  * @brief Tests for the bms driver implementation
51  */
52 
53 /*========== Includes =======================================================*/
54 #include "unity.h"
55 #include "Mockafe.h"
56 #include "Mockbal.h"
57 #include "Mockbattery_system_cfg.h"
58 #include "Mockcontactor.h"
59 #include "Mockdatabase.h"
60 #include "Mockdiag.h"
61 #include "Mockfassert.h"
62 #include "Mockinterlock.h"
63 #include "Mockled.h"
64 #include "Mockmeas.h"
65 #include "Mockos.h"
66 #include "Mockplausibility.h"
67 #include "Mocksoa.h"
68 
69 #include "bms.h"
70 #include "foxmath.h"
71 #include "test_assert_helper.h"
72 
73 /*========== Definitions and Implementations for Unit Test ==================*/
75 
77  .nr_of_ch = sizeof(DIAG_ID_cfg) / sizeof(DIAG_ID_CFG_s),
78  .ch_cfg = &DIAG_ID_cfg[0],
79  .numberOfFatalErrors = 0u,
80 };
81 
86 };
87 
88 /*========== Setup and Teardown =============================================*/
89 void setUp(void) {
90 }
91 
92 void tearDown(void) {
93 }
94 
95 /*========== Test Cases =====================================================*/
96 #define NUM_PRECHARGE_TESTS 13
98 /*
99  * mock callback in order to provide custom values to current_tab
100  */
101 STD_RETURN_TYPE_e MockDATA_ReadBlock_Callback(void *dataptrtoReceiver, int num_calls) {
102  int32_t current = 0;
103  int32_t voltage_1 = 0;
104  int32_t voltage_2 = 0;
105 
106  /* determine a value depending on num_calls (has to be synchronized with test) */
107  switch (num_calls) {
108  case 0:
110  /* no current, no voltage difference --> expect OK */
111  current = 0;
112  voltage_1 = 0;
113  voltage_2 = 0;
114  break;
115  case 1:
117  /* INT32_MAX current, no voltage difference --> expect NOK */
118  current = INT32_MAX;
119  voltage_1 = 0;
120  voltage_2 = 0;
121  break;
122  case 2:
124  /* INT32_MIN current, no voltage difference --> expect NOK */
125  current = INT32_MIN;
126  voltage_1 = 0;
127  voltage_2 = 0;
128  break;
129  case 3:
131  /* no current, no voltage difference --> expect OK */
132  current = 0;
133  voltage_1 = INT32_MAX;
134  voltage_2 = INT32_MAX;
135  break;
136  case 4:
138  /* no current, no voltage difference --> expect OK */
139  current = 0;
140  voltage_1 = INT32_MIN;
141  voltage_2 = INT32_MIN;
142  break;
143  case 5:
145  /* no current, maximum voltage difference --> expect NOK */
146  current = 0;
147  voltage_1 = INT32_MAX;
148  voltage_2 = INT32_MIN;
149  break;
150  case 6:
152  /* no current, maximum voltage difference --> expect NOK */
153  current = 0;
154  voltage_1 = INT32_MIN;
155  voltage_2 = INT32_MAX;
156  break;
157  case 7:
159  /* current exactly at threshold, no voltage difference --> expect NOK */
161  voltage_1 = 0;
162  voltage_2 = 0;
163  break;
164  case 8:
166  /* no current, voltage difference exactly at threshold --> expect NOK */
167  current = 0;
169  voltage_2 = 0;
170  break;
171  case 9:
173  /* no current, voltage difference exactly at threshold --> expect NOK */
174  current = 0;
175  voltage_1 = 0;
177  break;
178  case 10:
180  /* current exactly 1 below threshold, no voltage difference --> expect OK */
182  voltage_1 = 0;
183  voltage_2 = 0;
184  break;
185  case 11:
187  /* no current, voltage difference exactly 1 below threshold --> expect OK */
188  current = 0;
189  voltage_1 = BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV - 1;
190  voltage_2 = 0;
191  break;
192  case 12:
194  /* no current, voltage difference exactly 1 below threshold --> expect OK */
195  current = 0;
196  voltage_1 = 0;
197  voltage_2 = BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV - 1;
198  break;
199  default:
200  TEST_FAIL_MESSAGE("DATA_ReadBlock_Callback was called too often");
201  }
202  /* ENTER HIGHEST CASE NUMBER IN EXPECT; checks whether all cases are used */
203  TEST_ASSERT_EQUAL_MESSAGE(12, (NUM_PRECHARGE_TESTS - 1), "Check code of stub. Something does not fit.");
204 
205  if (num_calls >= NUM_PRECHARGE_TESTS) {
206  TEST_FAIL_MESSAGE("This stub is fishy, prechargeExpectedResults is too short for the number of calls");
207  }
208 
209  /* cast to correct struct in order to properly write current and other values */
210  for (uint8_t s = 0; s < BS_NR_OF_STRINGS; s++) {
211  for (uint8_t testNumber = 0; testNumber < NUM_PRECHARGE_TESTS; testNumber++) {
212  prechargeExpectedResults[s][testNumber] = prechargeExpectedResults[0][testNumber];
213  }
214 
215  ((DATA_BLOCK_PACK_VALUES_s *)dataptrtoReceiver)->stringCurrent_mA[0] = current;
216  ((DATA_BLOCK_PACK_VALUES_s *)dataptrtoReceiver)->stringVoltage_mV[0] = voltage_1;
217  }
218  ((DATA_BLOCK_PACK_VALUES_s *)dataptrtoReceiver)->highVoltageBusVoltage_mV = voltage_2;
219 
220  return STD_OK;
221 }
222 
223 /**
224  * @brief Iterate over a callback that supplies various scenarios and check if they work as expected
225  * @details This function uses the callback #MockDATA_ReadBlock_Callback() in order to inject
226  * current tables and voltage tables into the returned database tables. The array
227  * #prechargeExpectedResults contains prepared return values against which the output
228  * of #TEST_BMS_CheckPrecharge() is compared.
229  */
231  /* tell CMock to use our callback */
232  DATA_Read_1_DataBlock_Stub(MockDATA_ReadBlock_Callback);
233 
235 
236  /* iterate until we have all covered cases from our stub processed */
237  for (uint8_t i = 0u; i < NUM_PRECHARGE_TESTS; i++) {
238  char buffer[30];
239  snprintf(buffer, 30, "Loop iteration %d.", i);
240  for (uint8_t s = 0; s < BS_NR_OF_STRINGS; s++) {
241  TEST_ASSERT_EQUAL_MESSAGE(
242  prechargeExpectedResults[s][i], TEST_BMS_CheckPrecharge(s, &tablePackValues), buffer);
243  }
244  }
245 }
246 
248  /*
249  WARNING: the function under test has code that is unaccessible
250  in order to solve this situation it has to be refactored
251  so that the branch in it does not always evaluate to true.
252 
253  However, the way it is implemented now, the unit test will be
254  always valid for the currently active defines.
255  */
256 
257 #if (POSITIVE_DISCHARGE_CURRENT == true)
258  /* discharge is positive */
259 
260  /* maximum positive current has to be discharge */
261  TEST_ASSERT_EQUAL(BMS_DISCHARGING, BMS_GetCurrentFlowDirection(INT32_MAX));
262 
263  /* maximum negative current has to be charge */
264  TEST_ASSERT_EQUAL(BMS_CHARGING, BMS_GetCurrentFlowDirection(INT32_MIN));
265 #else
266  /* discharge is negative */
267 
268  /* maximum positive current has to be charge */
269  TEST_ASSERT_EQUAL(BMS_CHARGING, BMS_GetCurrentFlowDirection(INT32_MAX));
270 
271  /* maximum negative current has to be discharge */
272  TEST_ASSERT_EQUAL(BMS_DISCHARGING, BMS_GetCurrentFlowDirection(INT32_MIN));
273 #endif
274 
275  /* zero current has to be no charge */
276  TEST_ASSERT_EQUAL(BMS_AT_REST, BMS_GetCurrentFlowDirection(0));
277 
278  /* positive current below/equal to resting current is no current too */
279  TEST_ASSERT_EQUAL(BMS_AT_REST, BMS_GetCurrentFlowDirection(0 + BS_REST_CURRENT_mA - 1));
280 
281  /* negative current below/equal to resting current is no current too */
282  TEST_ASSERT_EQUAL(BMS_AT_REST, BMS_GetCurrentFlowDirection(0 - BS_REST_CURRENT_mA + 1));
283 
284  /* function should have same behavior for #BS_CS_THRESHOLD_NO_CURRENT_mA */
285  TEST_ASSERT_EQUAL(
288 }
289 
291  /* Set the current to 0 */
292  TEST_ASSERT_EQUAL(BMS_AT_REST, BMS_GetCurrentFlowDirection(0u));
293 
294  /* Set the current to #INT32_MAX */
295 #if (POSITIVE_DISCHARGE_CURRENT == true)
296  TEST_ASSERT_EQUAL(BMS_DISCHARGING, BMS_GetCurrentFlowDirection(INT32_MAX));
297 #else
298  TEST_ASSERT_EQUAL(BMS_CHARGING, BMS_GetCurrentFlowDirection(INT32_MAX));
299 #endif
300 
301  /* Set the current to #INT32_MIN */
302 #if (POSITIVE_DISCHARGE_CURRENT == true)
303  TEST_ASSERT_EQUAL(BMS_CHARGING, BMS_GetCurrentFlowDirection(INT32_MIN));
304 #else
305  TEST_ASSERT_EQUAL(BMS_DISCHARGING, BMS_GetCurrentFlowDirection(INT32_MIN));
306 #endif
307 }
308 
309 /** check that invalid values to BMS_CheckPrecharge trip an assertion
310  *
311  * invalid values are all those that do not fall into
312  * 0 <= stringNumber < #BS_NR_OF_STRINGS
313  */
318  TEST_ASSERT_FAIL_ASSERT(TEST_BMS_CheckPrecharge(UINT8_MAX, &tablePackValues));
319 
320  TEST_ASSERT_PASS_ASSERT(TEST_BMS_CheckPrecharge(0u, &tablePackValues));
321 }
#define BS_NR_OF_STRINGS
#define BS_REST_CURRENT_mA
current threshold for determing rest state of battery. If absolute current is below this limit value ...
enum BS_STRING_PRECHARGE_PRESENT BS_STRING_PRECHARGE_PRESENT_e
@ BS_STRING_WITH_PRECHARGE
#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:1340
BMS_CURRENT_FLOW_STATE_e BMS_GetCurrentFlowDirection(int32_t current_mA)
Get current flow direction, current value as function parameter.
Definition: bms.c:1265
bms driver header
@ BMS_AT_REST
Definition: bms.h:69
@ BMS_DISCHARGING
Definition: bms.h:67
@ BMS_CHARGING
Definition: bms.h:66
#define BMS_PRECHARGE_VOLTAGE_THRESHOLD_mV
Definition: bms_cfg.h:161
#define BMS_PRECHARGE_CURRENT_THRESHOLD_mA
Definition: bms_cfg.h:164
@ DATA_BLOCK_ID_PACK_VALUES
Definition: database_cfg.h:102
math library for often used math functions
@ STD_NOT_OK
Definition: fstd_types.h:82
@ STD_OK
Definition: fstd_types.h:81
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:111
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:178
uint8_t nr_of_ch
Definition: diag_cfg.h:321
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:82
#define NUM_PRECHARGE_TESTS
Definition: test_bms.c:96
STD_RETURN_TYPE_e MockDATA_ReadBlock_Callback(void *dataptrtoReceiver, int num_calls)
Definition: test_bms.c:101
STD_RETURN_TYPE_e prechargeExpectedResults[BS_NR_OF_STRINGS][NUM_PRECHARGE_TESTS]
Definition: test_bms.c:97
void testBMS_CheckPrechargeInvalidStringNumber(void)
Definition: test_bms.c:314
void testCheckPrechargeIterateStub(void)
Iterate over a callback that supplies various scenarios and check if they work as expected.
Definition: test_bms.c:230
void setUp(void)
Definition: test_bms.c:89
void tearDown(void)
Definition: test_bms.c:92
void testBMS_GetCurrentFlowDirectionWithTypicalValues(void)
Definition: test_bms.c:247
void testCheckCurrentValueDirectionWithCurrentZeroMaxAndMin(void)
Definition: test_bms.c:290
DIAG_ID_CFG_s DIAG_ID_cfg[]
Definition: test_bms.c:74
DIAG_DEV_s diag_device
Definition: test_bms.c:76