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