1
2 #include "CppUTest/TestHarness.h"
3 #include "CppUTest/CommandLineTestRunner.h"
4
5 #include "hal_flash_bank.h"
6 #include "hal_flash_bank_memory.h"
7 #include "btstack_tlv.h"
8 #include "btstack_tlv_flash_bank.h"
9 #include "hci_dump.h"
10 #include "hci_dump_posix_fs.h"
11 #include "classic/btstack_link_key_db.h"
12 #include "classic/btstack_link_key_db_tlv.h"
13 #include "btstack_util.h"
14 #include "btstack_config.h"
15 #include "btstack_debug.h"
16
17 #ifdef ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD
18 // Provide additional bytes for 3 x delete fields of 4 bytes (in both banks)
19 // note: only valid for alignments: 1,2 and 4
20 #define HAL_FLASH_BANK_MEMORY_STORAGE_SIZE (256 + 24)
21 #define TAG_OVERHEAD 12
22 #else
23 #define HAL_FLASH_BANK_MEMORY_STORAGE_SIZE (256)
24 #define TAG_OVERHEAD 8
25 #endif
26 #define HAL_FLASH_BANK_MEMORY_BANK_SIZE (HAL_FLASH_BANK_MEMORY_STORAGE_SIZE / 2)
27
28
29
30 static uint8_t hal_flash_bank_memory_storage[HAL_FLASH_BANK_MEMORY_STORAGE_SIZE];
31
CHECK_EQUAL_ARRAY(uint8_t * expected,uint8_t * actual,int size)32 static void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){
33 int i;
34 for (i=0; i<size; i++){
35 if (expected[i] != actual[i]) {
36 printf("offset %u wrong\n", i);
37 printf("expected: "); printf_hexdump(expected, size);
38 printf("actual: "); printf_hexdump(actual, size);
39 }
40 BYTES_EQUAL(expected[i], actual[i]);
41 }
42 }
43
TEST_GROUP(HAL_FLASH_bank)44 TEST_GROUP(HAL_FLASH_bank){
45 const hal_flash_bank_t * hal_flash_bank_impl;
46 hal_flash_bank_memory_t hal_flash_bank_context;
47 void setup(void){
48 hal_flash_bank_impl = hal_flash_bank_memory_init_instance(&hal_flash_bank_context, hal_flash_bank_memory_storage, HAL_FLASH_BANK_MEMORY_STORAGE_SIZE);
49 hal_flash_bank_impl->erase(&hal_flash_bank_context, 0);
50 hal_flash_bank_impl->erase(&hal_flash_bank_context, 1);
51 }
52 };
53
TEST(HAL_FLASH_bank,TestErased)54 TEST(HAL_FLASH_bank, TestErased){
55 uint8_t buffer;
56 int offsets[] = { 0, 10, 100};
57 int i;
58 for (i=0;i<sizeof(offsets)/sizeof(int);i++){
59 int bank;
60 for (bank=0;bank<2;bank++){
61 hal_flash_bank_impl->read(&hal_flash_bank_context, bank, offsets[i], &buffer, 1);
62 CHECK_EQUAL(buffer, 0xff);
63 }
64 }
65 }
66
TEST(HAL_FLASH_bank,TestWrite)67 TEST(HAL_FLASH_bank, TestWrite){
68 uint8_t buffer;
69 int offsets[] = { 0, 10, 100};
70 int i;
71 for (i=0;i<sizeof(offsets)/sizeof(int);i++){
72 int bank;
73 for (bank=0;bank<2;bank++){
74 buffer = i;
75 hal_flash_bank_impl->write(&hal_flash_bank_context, bank, offsets[i], &buffer, 1);
76 }
77 }
78 for (i=0;i<sizeof(offsets)/sizeof(int);i++){
79 int bank;
80 for (bank=0;bank<2;bank++){
81 hal_flash_bank_impl->read(&hal_flash_bank_context, bank, offsets[i], &buffer, 1);
82 CHECK_EQUAL(buffer, i);
83 }
84 }
85 }
86
87 #if 0
88 // prints error and exits tests. maybe all functions need to return ok
89 TEST(HAL_FLASH_bank, TestWriteTwice){
90 uint8_t buffer = 5;
91 hal_flash_bank_impl->write(&hal_flash_bank_context, 0, 5, &buffer, 1);
92 hal_flash_bank_impl->write(&hal_flash_bank_context, 0, 5, &buffer, 1);
93 }
94 #endif
95
TEST(HAL_FLASH_bank,TestWriteErase)96 TEST(HAL_FLASH_bank, TestWriteErase){
97 uint32_t offset = 7;
98 uint8_t value = 9;
99 uint8_t buffer = value;
100 hal_flash_bank_impl->write(&hal_flash_bank_context, 0, offset, &buffer, 1);
101 hal_flash_bank_impl->read(&hal_flash_bank_context, 0, offset, &buffer, 1);
102 CHECK_EQUAL(buffer, value);
103 hal_flash_bank_impl->erase(&hal_flash_bank_context, 0);
104 hal_flash_bank_impl->read(&hal_flash_bank_context, 0, offset, &buffer, 1);
105 CHECK_EQUAL(buffer, 0xff);
106 }
107
108 /// TLV
TEST_GROUP(BSTACK_TLV)109 TEST_GROUP(BSTACK_TLV){
110
111 const hal_flash_bank_t * hal_flash_bank_impl;
112 hal_flash_bank_memory_t hal_flash_bank_context;
113
114 const btstack_tlv_t * btstack_tlv_impl;
115 btstack_tlv_flash_bank_t btstack_tlv_context;
116
117 void setup(void){
118 hal_flash_bank_impl = hal_flash_bank_memory_init_instance(&hal_flash_bank_context, hal_flash_bank_memory_storage, HAL_FLASH_BANK_MEMORY_STORAGE_SIZE);
119 hal_flash_bank_impl->erase(&hal_flash_bank_context, 0);
120 hal_flash_bank_impl->erase(&hal_flash_bank_context, 1);
121 }
122 };
123
TEST(BSTACK_TLV,TestMissingTag)124 TEST(BSTACK_TLV, TestMissingTag){
125 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
126 uint32_t tag = 'abcd';
127 int size = btstack_tlv_impl->get_tag(&btstack_tlv_context, tag, NULL, 0);
128 CHECK_EQUAL(size, 0);
129 }
130
TEST(BSTACK_TLV,TestWriteRead)131 TEST(BSTACK_TLV, TestWriteRead){
132 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
133 uint32_t tag = 'abcd';
134 uint8_t data = 7;
135 uint8_t buffer = data;
136 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, &buffer, 1);
137 int size = btstack_tlv_impl->get_tag(&btstack_tlv_context, tag, NULL, 0);
138 CHECK_EQUAL(size, 1);
139 btstack_tlv_impl->get_tag(&btstack_tlv_context, tag, &buffer, 1);
140 CHECK_EQUAL(buffer, data);
141 }
142
TEST(BSTACK_TLV,TestWriteWriteRead)143 TEST(BSTACK_TLV, TestWriteWriteRead){
144 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
145 uint32_t tag = 'abcd';
146 uint8_t data = 7;
147 uint8_t buffer = data;
148 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, &buffer, 1);
149 data++;
150 buffer = data;
151 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, &buffer, 1);
152 int size = btstack_tlv_impl->get_tag(&btstack_tlv_context, tag, NULL, 0);
153 CHECK_EQUAL(size, 1);
154 btstack_tlv_impl->get_tag(&btstack_tlv_context, tag, &buffer, 1);
155 CHECK_EQUAL(buffer, data);
156 }
157
TEST(BSTACK_TLV,TestWriteABARead)158 TEST(BSTACK_TLV, TestWriteABARead){
159 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
160 uint32_t tag_a = 'aaaa';
161 uint32_t tag_b = 'bbbb';
162 uint8_t data = 7;
163 uint8_t buffer = data;
164 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag_a, &buffer, 1);
165 data++;
166 buffer = data;
167 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag_b, &buffer, 1);
168 data++;
169 buffer = data;
170 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag_a, &buffer, 1);
171 int size = btstack_tlv_impl->get_tag(&btstack_tlv_context, tag_a, NULL, 0);
172 CHECK_EQUAL(size, 1);
173 btstack_tlv_impl->get_tag(&btstack_tlv_context, tag_a, &buffer, 1);
174 CHECK_EQUAL(buffer, data);
175 }
176
TEST(BSTACK_TLV,TestWriteDeleteRead)177 TEST(BSTACK_TLV, TestWriteDeleteRead){
178 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
179 uint32_t tag = 'abcd';
180 uint8_t data = 7;
181 uint8_t buffer = data;
182 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, &buffer, 1);
183 data++;
184 buffer = data;
185 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, &buffer, 1);
186 btstack_tlv_impl->delete_tag(&btstack_tlv_context, tag);
187 int size = btstack_tlv_impl->get_tag(&btstack_tlv_context, tag, NULL, 0);
188 CHECK_EQUAL(size, 0);
189 }
190
TEST(BSTACK_TLV,TestMigrate)191 TEST(BSTACK_TLV, TestMigrate){
192
193 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
194
195 uint32_t tag = 'abcd';
196 uint8_t data[8];
197 memcpy(data, "01234567", 8);
198
199 // entry 8 + data 8 = 16.
200 int i;
201 for (i=0;i<8;i++){
202 data[0] = '0' + i;
203 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, &data[0], 8);
204 }
205
206 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
207
208 uint8_t buffer[8];
209 btstack_tlv_impl->get_tag(&btstack_tlv_context, tag, &buffer[0], 1);
210 CHECK_EQUAL(buffer[0], data[0]);
211 }
212
TEST(BSTACK_TLV,TestMigrate2)213 TEST(BSTACK_TLV, TestMigrate2){
214
215 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
216
217 uint32_t tag1 = 0x11223344;
218 uint32_t tag2 = 0x44556677;
219 uint8_t data1[8];
220 memcpy(data1, "01234567", 8);
221 uint8_t data2[8];
222 memcpy(data2, "abcdefgh", 8);
223
224 // entry 8 + data 8 = 16.
225 int i;
226 for (i=0;i<8;i++){
227 data1[0] = '0' + i;
228 data2[0] = 'a' + i;
229 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag1, data1, 8);
230 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag2, data2, 8);
231 }
232
233 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
234
235 uint8_t buffer[8];
236 btstack_tlv_impl->get_tag(&btstack_tlv_context, tag1, &buffer[0], 1);
237 CHECK_EQUAL(buffer[0], data1[0]);
238 btstack_tlv_impl->get_tag(&btstack_tlv_context, tag2, &buffer[0], 1);
239 CHECK_EQUAL(buffer[0], data2[0]);
240 }
241
TEST(BSTACK_TLV,TestWriteResetRead)242 TEST(BSTACK_TLV, TestWriteResetRead){
243 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
244 uint32_t tag = 'abcd';
245 uint8_t data = 7;
246 uint8_t buffer = data;
247 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, &buffer, 1);
248 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
249 int size = btstack_tlv_impl->get_tag(&btstack_tlv_context, tag, NULL, 0);
250 CHECK_EQUAL(size, 1);
251 btstack_tlv_impl->get_tag(&btstack_tlv_context, tag, &buffer, 1);
252 CHECK_EQUAL(buffer, data);
253 }
254
TEST(BSTACK_TLV,TestFullBankNormal)255 TEST(BSTACK_TLV, TestFullBankNormal){
256 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
257
258 // fill-up flash bank
259 uint32_t tag = 'abcd';
260 uint8_t blob[HAL_FLASH_BANK_MEMORY_BANK_SIZE - 8 - TAG_OVERHEAD];
261 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, (uint8_t *) &blob, sizeof(blob));
262 CHECK_EQUAL(0, btstack_tlv_context.current_bank);
263 CHECK_EQUAL(HAL_FLASH_BANK_MEMORY_BANK_SIZE, btstack_tlv_context.write_offset);
264
265 // check
266 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
267 CHECK_EQUAL(0, btstack_tlv_context.current_bank);
268 CHECK_EQUAL(HAL_FLASH_BANK_MEMORY_BANK_SIZE, btstack_tlv_context.write_offset);
269 }
270
TEST(BSTACK_TLV,TestAlmostFullBank)271 TEST(BSTACK_TLV, TestAlmostFullBank){
272 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
273
274 // fill-up flash bank without the last byte
275 uint32_t tag = 'abcd';
276 uint8_t blob[HAL_FLASH_BANK_MEMORY_BANK_SIZE - 8 - TAG_OVERHEAD - 1];
277 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, (uint8_t *) &blob, sizeof(blob));
278 CHECK_EQUAL(0, btstack_tlv_context.current_bank);
279 CHECK_EQUAL(HAL_FLASH_BANK_MEMORY_BANK_SIZE-1, btstack_tlv_context.write_offset);
280
281 // check
282 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
283 CHECK_EQUAL(0, btstack_tlv_context.current_bank);
284 CHECK_EQUAL(HAL_FLASH_BANK_MEMORY_BANK_SIZE-1, btstack_tlv_context.write_offset);
285 }
286
TEST(BSTACK_TLV,TestFullBankPlusMigrate)287 TEST(BSTACK_TLV, TestFullBankPlusMigrate){
288 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
289
290 // fill-up flash bank
291 uint32_t tag = 'abcd';
292 uint8_t blob[((HAL_FLASH_BANK_MEMORY_BANK_SIZE - 8) / 2) - TAG_OVERHEAD];
293 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, (uint8_t *) &blob, sizeof(blob));
294 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, (uint8_t *) &blob, sizeof(blob));
295 CHECK_EQUAL(0, btstack_tlv_context.current_bank);
296 CHECK_EQUAL(HAL_FLASH_BANK_MEMORY_BANK_SIZE, btstack_tlv_context.write_offset);
297
298 // check
299 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
300 CHECK_EQUAL(0, btstack_tlv_context.current_bank);
301 CHECK_EQUAL(HAL_FLASH_BANK_MEMORY_BANK_SIZE, btstack_tlv_context.write_offset);
302
303 // store one more -> trigger migration
304 btstack_tlv_impl->store_tag(&btstack_tlv_context, tag, (uint8_t *) &blob, sizeof(blob));
305 CHECK_EQUAL(1, btstack_tlv_context.current_bank);
306 CHECK_EQUAL(8 + 2 * (TAG_OVERHEAD + sizeof(blob)), btstack_tlv_context.write_offset);
307 }
308
309 //
TEST_GROUP(LINK_KEY_DB)310 TEST_GROUP(LINK_KEY_DB){
311 const hal_flash_bank_t * hal_flash_bank_impl;
312 hal_flash_bank_memory_t hal_flash_bank_context;
313
314 const btstack_tlv_t * btstack_tlv_impl;
315 btstack_tlv_flash_bank_t btstack_tlv_context;
316
317 const btstack_link_key_db_t * btstack_link_key_db;
318
319 bd_addr_t addr1, addr2, addr3;
320 link_key_t link_key1, link_key2;
321 link_key_type_t link_key_type;
322
323 void setup(void){
324 // hal_flash_bank
325 hal_flash_bank_impl = hal_flash_bank_memory_init_instance(&hal_flash_bank_context, hal_flash_bank_memory_storage, HAL_FLASH_BANK_MEMORY_STORAGE_SIZE);
326 hal_flash_bank_impl->erase(&hal_flash_bank_context, 0);
327 hal_flash_bank_impl->erase(&hal_flash_bank_context, 1);
328 // btstack_tlv
329 btstack_tlv_impl = btstack_tlv_flash_bank_init_instance(&btstack_tlv_context, hal_flash_bank_impl, &hal_flash_bank_context);
330 // btstack_link_key_db
331 btstack_link_key_db = btstack_link_key_db_tlv_get_instance(btstack_tlv_impl, &btstack_tlv_context);
332
333 bd_addr_t addr_1 = {0x00, 0x01, 0x02, 0x03, 0x04, 0x01 };
334 bd_addr_t addr_2 = {0x00, 0x01, 0x02, 0x03, 0x04, 0x02 };
335 bd_addr_t addr_3 = {0x00, 0x01, 0x02, 0x03, 0x04, 0x03 };
336 bd_addr_copy(addr1, addr_1);
337 bd_addr_copy(addr2, addr_2);
338 bd_addr_copy(addr3, addr_3);
339 for (int i=0;i<16;i++) {
340 link_key1[i] = 'a'+i;
341 link_key2[i] = 'A'+i;
342 }
343 link_key_type = COMBINATION_KEY;
344 }
345 };
346
TEST(LINK_KEY_DB,SinglePutGetDeleteKey)347 TEST(LINK_KEY_DB, SinglePutGetDeleteKey){
348
349 link_key_t test_link_key;
350 link_key_type_t test_link_key_type;
351
352 btstack_link_key_db->delete_link_key(addr1);
353 CHECK(btstack_link_key_db->get_link_key(addr1, test_link_key, &test_link_key_type) == 0);
354
355 btstack_link_key_db->put_link_key(addr1, link_key1, link_key_type);
356 CHECK(btstack_link_key_db->get_link_key(addr1, test_link_key, &test_link_key_type) == 1);
357 CHECK_EQUAL_ARRAY(link_key1, test_link_key, 16);
358
359 btstack_link_key_db->delete_link_key(addr1);
360 CHECK(btstack_link_key_db->get_link_key(addr1, test_link_key, &test_link_key_type) == 0);
361 }
362
TEST(LINK_KEY_DB,UpdateKey)363 TEST(LINK_KEY_DB, UpdateKey){
364 link_key_t test_link_key;
365 link_key_type_t test_link_key_type;
366
367 btstack_link_key_db->put_link_key(addr1, link_key1, link_key_type);
368 btstack_link_key_db->put_link_key(addr1, link_key2, link_key_type);
369 CHECK(btstack_link_key_db->get_link_key(addr1, test_link_key, &test_link_key_type) == 1);
370 CHECK_EQUAL_ARRAY(link_key2, test_link_key, 16);
371 }
372
TEST(LINK_KEY_DB,NumKeys)373 TEST(LINK_KEY_DB, NumKeys){
374 CHECK(NVM_NUM_LINK_KEYS == 2);
375 }
376
TEST(LINK_KEY_DB,KeyReplacement)377 TEST(LINK_KEY_DB, KeyReplacement){
378 link_key_t test_link_key;
379 link_key_type_t test_link_key_type;
380
381 btstack_link_key_db->put_link_key(addr1, link_key1, link_key_type);
382 btstack_link_key_db->put_link_key(addr2, link_key1, link_key_type);
383 btstack_link_key_db->put_link_key(addr3, link_key1, link_key_type);
384
385 CHECK(btstack_link_key_db->get_link_key(addr3, test_link_key, &test_link_key_type) == 1);
386 CHECK(btstack_link_key_db->get_link_key(addr2, test_link_key, &test_link_key_type) == 1);
387 CHECK(btstack_link_key_db->get_link_key(addr1, test_link_key, &test_link_key_type) == 0);
388 CHECK_EQUAL_ARRAY(link_key1, test_link_key, 16);
389 }
390
main(int argc,const char * argv[])391 int main (int argc, const char * argv[]){
392 // log into file using HCI_DUMP_PACKETLOGGER format
393 #ifdef ENABLE_TLV_FLASH_WRITE_ONCE
394 const char * pklg_path = "hci_dump_write_once.pklg";
395 #elif defined(ENABLE_TLV_FLASH_EXPLICIT_DELETE_FIELD)
396 const char * pklg_path = "hci_dump_delete_field.pklg";
397 #else
398 const char * pklg_path = "hci_dump.pklg";
399 #endif
400 hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER);
401 hci_dump_init(hci_dump_posix_fs_get_instance());
402 printf("Packet Log: %s\n", pklg_path);
403
404 return CommandLineTestRunner::RunAllTests(argc, argv);
405 }
406