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