1 /*
2 * Copyright (c) 2019 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdio.h>
8 #include <string.h>
9 #include <zephyr/ztest.h>
10
11 #include <zephyr/drivers/flash.h>
12 #include <zephyr/fs/nvs.h>
13 #include <zephyr/stats/stats.h>
14 #include <zephyr/storage/flash_map.h>
15 #include <zephyr/sys/crc.h>
16 #include "nvs_priv.h"
17
18 #define TEST_NVS_FLASH_AREA storage_partition
19 #define TEST_NVS_FLASH_AREA_OFFSET FIXED_PARTITION_OFFSET(TEST_NVS_FLASH_AREA)
20 #define TEST_NVS_FLASH_AREA_ID FIXED_PARTITION_ID(TEST_NVS_FLASH_AREA)
21 #define TEST_NVS_FLASH_AREA_DEV \
22 DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(TEST_NVS_FLASH_AREA)))
23 #define TEST_DATA_ID 1
24 #define TEST_SECTOR_COUNT 5U
25
26 static const struct device *const flash_dev = TEST_NVS_FLASH_AREA_DEV;
27
28 struct nvs_fixture {
29 struct nvs_fs fs;
30 #ifdef CONFIG_TEST_NVS_SIMULATOR
31 struct stats_hdr *sim_stats;
32 struct stats_hdr *sim_thresholds;
33 #endif /* CONFIG_TEST_NVS_SIMULATOR */
34 };
35
setup(void)36 static void *setup(void)
37 {
38 int err;
39 const struct flash_area *fa;
40 struct flash_pages_info info;
41 static struct nvs_fixture fixture;
42
43 __ASSERT_NO_MSG(device_is_ready(flash_dev));
44
45 err = flash_area_open(TEST_NVS_FLASH_AREA_ID, &fa);
46 zassert_true(err == 0, "flash_area_open() fail: %d", err);
47
48 fixture.fs.offset = TEST_NVS_FLASH_AREA_OFFSET;
49 err = flash_get_page_info_by_offs(flash_area_get_device(fa), fixture.fs.offset,
50 &info);
51 zassert_true(err == 0, "Unable to get page info: %d", err);
52
53 fixture.fs.sector_size = info.size;
54 fixture.fs.sector_count = TEST_SECTOR_COUNT;
55 fixture.fs.flash_device = flash_area_get_device(fa);
56
57 return &fixture;
58 }
59
before(void * data)60 static void before(void *data)
61 {
62 #ifdef CONFIG_TEST_NVS_SIMULATOR
63 struct nvs_fixture *fixture = (struct nvs_fixture *)data;
64
65 fixture->sim_stats = stats_group_find("flash_sim_stats");
66 fixture->sim_thresholds = stats_group_find("flash_sim_thresholds");
67 #endif /* CONFIG_TEST_NVS_SIMULATOR */
68 }
69
after(void * data)70 static void after(void *data)
71 {
72 struct nvs_fixture *fixture = (struct nvs_fixture *)data;
73
74 #ifdef CONFIG_TEST_NVS_SIMULATOR
75 if (fixture->sim_stats) {
76 stats_reset(fixture->sim_stats);
77 }
78 if (fixture->sim_thresholds) {
79 stats_reset(fixture->sim_thresholds);
80 }
81 #endif /* CONFIG_TEST_NVS_SIMULATOR */
82
83 /* Clear NVS */
84 if (fixture->fs.ready) {
85 int err;
86
87 err = nvs_clear(&fixture->fs);
88 zassert_true(err == 0, "nvs_clear call failure: %d", err);
89 }
90
91 fixture->fs.sector_count = TEST_SECTOR_COUNT;
92 }
93
94 ZTEST_SUITE(nvs, NULL, setup, before, after, NULL);
95
ZTEST_F(nvs,test_nvs_mount)96 ZTEST_F(nvs, test_nvs_mount)
97 {
98 int err;
99 size_t orig_sector_size = fixture->fs.sector_size;
100
101 fixture->fs.sector_size = KB(128);
102 err = nvs_mount(&fixture->fs);
103 zassert_true(err == -EINVAL,
104 "nvs_mount did not return expected err for invalid sector_size");
105
106 fixture->fs.sector_size = orig_sector_size;
107 err = nvs_mount(&fixture->fs);
108 zassert_true(err == 0, "nvs_mount call failure: %d", err);
109 }
110
execute_long_pattern_write(uint16_t id,struct nvs_fs * fs)111 static void execute_long_pattern_write(uint16_t id, struct nvs_fs *fs)
112 {
113 char rd_buf[512];
114 char wr_buf[512];
115 char pattern[] = {0xDE, 0xAD, 0xBE, 0xEF};
116 size_t len;
117
118 len = nvs_read(fs, id, rd_buf, sizeof(rd_buf));
119 zassert_true(len == -ENOENT, "nvs_read unexpected failure: %d", len);
120
121 BUILD_ASSERT((sizeof(wr_buf) % sizeof(pattern)) == 0);
122 for (int i = 0; i < sizeof(wr_buf); i += sizeof(pattern)) {
123 memcpy(wr_buf + i, pattern, sizeof(pattern));
124 }
125
126 len = nvs_write(fs, id, wr_buf, sizeof(wr_buf));
127 zassert_true(len == sizeof(wr_buf), "nvs_write failed: %d", len);
128
129 len = nvs_read(fs, id, rd_buf, sizeof(rd_buf));
130 zassert_true(len == sizeof(rd_buf), "nvs_read unexpected failure: %d",
131 len);
132 zassert_mem_equal(wr_buf, rd_buf, sizeof(rd_buf),
133 "RD buff should be equal to the WR buff");
134 }
135
ZTEST_F(nvs,test_nvs_write)136 ZTEST_F(nvs, test_nvs_write)
137 {
138 int err;
139
140 err = nvs_mount(&fixture->fs);
141 zassert_true(err == 0, "nvs_mount call failure: %d", err);
142
143 execute_long_pattern_write(TEST_DATA_ID, &fixture->fs);
144 }
145
146 #ifdef CONFIG_TEST_NVS_SIMULATOR
flash_sim_write_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)147 static int flash_sim_write_calls_find(struct stats_hdr *hdr, void *arg,
148 const char *name, uint16_t off)
149 {
150 if (!strcmp(name, "flash_write_calls")) {
151 uint32_t **flash_write_stat = (uint32_t **) arg;
152 *flash_write_stat = (uint32_t *)((uint8_t *)hdr + off);
153 }
154
155 return 0;
156 }
157
flash_sim_max_write_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)158 static int flash_sim_max_write_calls_find(struct stats_hdr *hdr, void *arg,
159 const char *name, uint16_t off)
160 {
161 if (!strcmp(name, "max_write_calls")) {
162 uint32_t **max_write_calls = (uint32_t **) arg;
163 *max_write_calls = (uint32_t *)((uint8_t *)hdr + off);
164 }
165
166 return 0;
167 }
168
ZTEST_F(nvs,test_nvs_corrupted_write)169 ZTEST_F(nvs, test_nvs_corrupted_write)
170 {
171 int err;
172 size_t len;
173 char rd_buf[512];
174 char wr_buf_1[512];
175 char wr_buf_2[512];
176 char pattern_1[] = {0xDE, 0xAD, 0xBE, 0xEF};
177 char pattern_2[] = {0x03, 0xAA, 0x85, 0x6F};
178 uint32_t *flash_write_stat;
179 uint32_t *flash_max_write_calls;
180
181 err = nvs_mount(&fixture->fs);
182 zassert_true(err == 0, "nvs_mount call failure: %d", err);
183
184 err = nvs_read(&fixture->fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
185 zassert_true(err == -ENOENT, "nvs_read unexpected failure: %d", err);
186
187 BUILD_ASSERT((sizeof(wr_buf_1) % sizeof(pattern_1)) == 0);
188 for (int i = 0; i < sizeof(wr_buf_1); i += sizeof(pattern_1)) {
189 memcpy(wr_buf_1 + i, pattern_1, sizeof(pattern_1));
190 }
191
192 len = nvs_write(&fixture->fs, TEST_DATA_ID, wr_buf_1, sizeof(wr_buf_1));
193 zassert_true(len == sizeof(wr_buf_1), "nvs_write failed: %d", len);
194
195 len = nvs_read(&fixture->fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
196 zassert_true(len == sizeof(rd_buf), "nvs_read unexpected failure: %d",
197 len);
198 zassert_mem_equal(wr_buf_1, rd_buf, sizeof(rd_buf),
199 "RD buff should be equal to the first WR buff");
200
201 BUILD_ASSERT((sizeof(wr_buf_2) % sizeof(pattern_2)) == 0);
202 for (int i = 0; i < sizeof(wr_buf_2); i += sizeof(pattern_2)) {
203 memcpy(wr_buf_2 + i, pattern_2, sizeof(pattern_2));
204 }
205
206 /* Set the maximum number of writes that the flash simulator can
207 * execute.
208 */
209 stats_walk(fixture->sim_thresholds, flash_sim_max_write_calls_find,
210 &flash_max_write_calls);
211 stats_walk(fixture->sim_stats, flash_sim_write_calls_find, &flash_write_stat);
212
213 #if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE)
214 *flash_max_write_calls = *flash_write_stat - 1;
215 #else
216 /* When there is no explicit erase, erase is done with write, which means
217 * that there are more writes needed. The nvs_write here will cause erase
218 * to be called, which in turn calls the flash_fill; flash_fill will
219 * overwrite data using buffer of size CONFIG_FLASH_FILL_BUFFER_SIZE,
220 * and then two additional real writes are allowed.
221 */
222 *flash_max_write_calls = (fixture->fs.sector_size /
223 CONFIG_FLASH_FILL_BUFFER_SIZE) + 2;
224 #endif
225 *flash_write_stat = 0;
226
227 /* Flash simulator will lose part of the data at the end of this write.
228 * This should simulate power down during flash write. The written data
229 * are corrupted at this point and should be discarded by the NVS.
230 */
231 len = nvs_write(&fixture->fs, TEST_DATA_ID, wr_buf_2, sizeof(wr_buf_2));
232 zassert_true(len == sizeof(wr_buf_2), "nvs_write failed: %d", len);
233
234 /* Reinitialize the NVS. */
235 memset(&fixture->fs, 0, sizeof(fixture->fs));
236 (void)setup();
237 err = nvs_mount(&fixture->fs);
238 zassert_true(err == 0, "nvs_mount call failure: %d", err);
239
240 len = nvs_read(&fixture->fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
241 zassert_true(len == sizeof(rd_buf), "nvs_read unexpected failure: %d",
242 len);
243 zassert_true(memcmp(wr_buf_2, rd_buf, sizeof(rd_buf)) != 0,
244 "RD buff should not be equal to the second WR buff because of "
245 "corrupted write operation");
246 zassert_mem_equal(wr_buf_1, rd_buf, sizeof(rd_buf),
247 "RD buff should be equal to the first WR buff because subsequent "
248 "write operation has failed");
249 }
250
ZTEST_F(nvs,test_nvs_gc)251 ZTEST_F(nvs, test_nvs_gc)
252 {
253 int err;
254 int len;
255 uint8_t buf[32];
256 uint8_t rd_buf[32];
257
258 const uint16_t max_id = 10;
259 /* 25th write will trigger GC. */
260 const uint16_t max_writes = 26;
261
262 fixture->fs.sector_count = 2;
263
264 err = nvs_mount(&fixture->fs);
265 zassert_true(err == 0, "nvs_mount call failure: %d", err);
266
267 for (uint16_t i = 0; i < max_writes; i++) {
268 uint8_t id = (i % max_id);
269 uint8_t id_data = id + max_id * (i / max_id);
270
271 memset(buf, id_data, sizeof(buf));
272
273 len = nvs_write(&fixture->fs, id, buf, sizeof(buf));
274 zassert_true(len == sizeof(buf), "nvs_write failed: %d", len);
275 }
276
277 for (uint16_t id = 0; id < max_id; id++) {
278 len = nvs_read(&fixture->fs, id, rd_buf, sizeof(buf));
279 zassert_true(len == sizeof(rd_buf),
280 "nvs_read unexpected failure: %d", len);
281
282 for (uint16_t i = 0; i < sizeof(rd_buf); i++) {
283 rd_buf[i] = rd_buf[i] % max_id;
284 buf[i] = id;
285 }
286 zassert_mem_equal(buf, rd_buf, sizeof(rd_buf),
287 "RD buff should be equal to the WR buff");
288
289 }
290
291 err = nvs_mount(&fixture->fs);
292 zassert_true(err == 0, "nvs_mount call failure: %d", err);
293
294 for (uint16_t id = 0; id < max_id; id++) {
295 len = nvs_read(&fixture->fs, id, rd_buf, sizeof(buf));
296 zassert_true(len == sizeof(rd_buf),
297 "nvs_read unexpected failure: %d", len);
298
299 for (uint16_t i = 0; i < sizeof(rd_buf); i++) {
300 rd_buf[i] = rd_buf[i] % max_id;
301 buf[i] = id;
302 }
303 zassert_mem_equal(buf, rd_buf, sizeof(rd_buf),
304 "RD buff should be equal to the WR buff");
305
306 }
307 }
308
write_content(uint16_t max_id,uint16_t begin,uint16_t end,struct nvs_fs * fs)309 static void write_content(uint16_t max_id, uint16_t begin, uint16_t end,
310 struct nvs_fs *fs)
311 {
312 uint8_t buf[32];
313 ssize_t len;
314
315 for (uint16_t i = begin; i < end; i++) {
316 uint8_t id = (i % max_id);
317 uint8_t id_data = id + max_id * ((i % 256) / max_id);
318
319 memset(buf, id_data, sizeof(buf));
320
321 len = nvs_write(fs, id, buf, sizeof(buf));
322 zassert_true(len == sizeof(buf), "nvs_write failed: %d", len);
323 }
324 }
325
check_content(uint16_t max_id,struct nvs_fs * fs)326 static void check_content(uint16_t max_id, struct nvs_fs *fs)
327 {
328 uint8_t rd_buf[32];
329 uint8_t buf[32];
330 ssize_t len;
331
332 for (uint16_t id = 0; id < max_id; id++) {
333 len = nvs_read(fs, id, rd_buf, sizeof(buf));
334 zassert_true(len == sizeof(rd_buf),
335 "nvs_read unexpected failure: %d", len);
336
337 for (uint16_t i = 0; i < ARRAY_SIZE(rd_buf); i++) {
338 rd_buf[i] = rd_buf[i] % max_id;
339 buf[i] = id;
340 }
341 zassert_mem_equal(buf, rd_buf, sizeof(rd_buf),
342 "RD buff should be equal to the WR buff");
343
344 }
345 }
346
347 /**
348 * Full round of GC over 3 sectors
349 */
ZTEST_F(nvs,test_nvs_gc_3sectors)350 ZTEST_F(nvs, test_nvs_gc_3sectors)
351 {
352 int err;
353
354 const uint16_t max_id = 10;
355 /* 50th write will trigger 1st GC. */
356 uint16_t max_writes = 51;
357 /* 75th write will trigger 2st GC. */
358 uint16_t max_writes_2 = 51 + 25;
359 /* 100th write will trigger 3st GC. */
360 uint16_t max_writes_3 = 51 + 25 + 25;
361 /* 125th write will trigger 4st GC. */
362 uint16_t max_writes_4 = 51 + 25 + 25 + 25;
363
364 if (fixture->fs.sector_size == KB(64)) {
365 /* write 1637 will trigger 1st GC. */
366 /* write 3274 will trigger 2nd GC. */
367 max_writes = 3275;
368 /* write 4911 will trigger 3rd GC. */
369 max_writes_2 = 3275 + 1637;
370 /* write 6548 will trigger 4th GC. */
371 max_writes_3 = 3275 + 1637 + 1637;
372 /* write 8185 will trigger 5th GC. */
373 max_writes_4 = 3275 + 1637 + 1637 + 1637;
374 }
375
376 fixture->fs.sector_count = 3;
377
378 err = nvs_mount(&fixture->fs);
379 zassert_true(err == 0, "nvs_mount call failure: %d", err);
380 zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0,
381 "unexpected write sector");
382
383 /* Trigger 1st and 2nd GC */
384 write_content(max_id, 0, max_writes, &fixture->fs);
385
386 /* sector sequence: empty,closed, write */
387 zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2,
388 "unexpected write sector");
389 check_content(max_id, &fixture->fs);
390
391 err = nvs_mount(&fixture->fs);
392 zassert_true(err == 0, "nvs_mount call failure: %d", err);
393
394 zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2,
395 "unexpected write sector");
396 check_content(max_id, &fixture->fs);
397
398 /* Trigger 3rd GC */
399 write_content(max_id, max_writes, max_writes_2, &fixture->fs);
400
401 /* sector sequence: write, empty, closed */
402 zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0,
403 "unexpected write sector");
404 check_content(max_id, &fixture->fs);
405
406 err = nvs_mount(&fixture->fs);
407 zassert_true(err == 0, "nvs_mount call failure: %d", err);
408
409 zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0,
410 "unexpected write sector");
411 check_content(max_id, &fixture->fs);
412
413 /* Trigger 4th GC */
414 write_content(max_id, max_writes_2, max_writes_3, &fixture->fs);
415
416 /* sector sequence: closed, write, empty */
417 zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 1,
418 "unexpected write sector");
419 check_content(max_id, &fixture->fs);
420
421 err = nvs_mount(&fixture->fs);
422 zassert_true(err == 0, "nvs_mount call failure: %d", err);
423
424 zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 1,
425 "unexpected write sector");
426 check_content(max_id, &fixture->fs);
427
428 /* Trigger 5th GC */
429 write_content(max_id, max_writes_3, max_writes_4, &fixture->fs);
430
431 /* sector sequence: empty,closed, write */
432 zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2,
433 "unexpected write sector");
434 check_content(max_id, &fixture->fs);
435
436 err = nvs_mount(&fixture->fs);
437 zassert_true(err == 0, "nvs_mount call failure: %d", err);
438
439 zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2,
440 "unexpected write sector");
441 check_content(max_id, &fixture->fs);
442 }
443
flash_sim_erase_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)444 static int flash_sim_erase_calls_find(struct stats_hdr *hdr, void *arg,
445 const char *name, uint16_t off)
446 {
447 if (!strcmp(name, "flash_erase_calls")) {
448 uint32_t **flash_erase_stat = (uint32_t **) arg;
449 *flash_erase_stat = (uint32_t *)((uint8_t *)hdr + off);
450 }
451
452 return 0;
453 }
454
flash_sim_max_erase_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)455 static int flash_sim_max_erase_calls_find(struct stats_hdr *hdr, void *arg,
456 const char *name, uint16_t off)
457 {
458 if (!strcmp(name, "max_erase_calls")) {
459 uint32_t **max_erase_calls = (uint32_t **) arg;
460 *max_erase_calls = (uint32_t *)((uint8_t *)hdr + off);
461 }
462
463 return 0;
464 }
465
flash_sim_max_len_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)466 static int flash_sim_max_len_find(struct stats_hdr *hdr, void *arg,
467 const char *name, uint16_t off)
468 {
469 if (!strcmp(name, "max_len")) {
470 uint32_t **max_len = (uint32_t **) arg;
471 *max_len = (uint32_t *)((uint8_t *)hdr + off);
472 }
473
474 return 0;
475 }
476
ZTEST_F(nvs,test_nvs_corrupted_sector_close_operation)477 ZTEST_F(nvs, test_nvs_corrupted_sector_close_operation)
478 {
479 int err;
480 int len;
481 uint8_t buf[32];
482 uint32_t *flash_write_stat;
483 uint32_t *flash_erase_stat;
484 uint32_t *flash_max_write_calls;
485 uint32_t *flash_max_erase_calls;
486 uint32_t *flash_max_len;
487
488 const uint16_t max_id = 10;
489 /* 25th write will trigger GC. */
490 const uint16_t max_writes = 26;
491
492 /* Get the address of simulator parameters. */
493 stats_walk(fixture->sim_thresholds, flash_sim_max_write_calls_find,
494 &flash_max_write_calls);
495 stats_walk(fixture->sim_thresholds, flash_sim_max_erase_calls_find,
496 &flash_max_erase_calls);
497 stats_walk(fixture->sim_thresholds, flash_sim_max_len_find,
498 &flash_max_len);
499 stats_walk(fixture->sim_stats, flash_sim_write_calls_find, &flash_write_stat);
500 stats_walk(fixture->sim_stats, flash_sim_erase_calls_find, &flash_erase_stat);
501
502 err = nvs_mount(&fixture->fs);
503 zassert_true(err == 0, "nvs_mount call failure: %d", err);
504
505 for (uint16_t i = 0; i < max_writes; i++) {
506 uint8_t id = (i % max_id);
507 uint8_t id_data = id + max_id * (i / max_id);
508
509 memset(buf, id_data, sizeof(buf));
510
511 if (i == max_writes - 1) {
512 /* Reset stats. */
513 *flash_write_stat = 0;
514 *flash_erase_stat = 0;
515
516 /* Block write calls and simulate power down during
517 * sector closing operation, so only a part of a NVS
518 * closing ate will be written.
519 */
520 *flash_max_write_calls = 1;
521 *flash_max_erase_calls = 1;
522 *flash_max_len = 4;
523 }
524
525 len = nvs_write(&fixture->fs, id, buf, sizeof(buf));
526 zassert_true(len == sizeof(buf), "nvs_write failed: %d", len);
527 }
528
529 /* Make the flash simulator functional again. */
530 *flash_max_write_calls = 0;
531 *flash_max_erase_calls = 0;
532 *flash_max_len = 0;
533
534 err = nvs_mount(&fixture->fs);
535 zassert_true(err == 0, "nvs_mount call failure: %d", err);
536
537 check_content(max_id, &fixture->fs);
538
539 /* Ensure that the NVS is able to store new content. */
540 execute_long_pattern_write(max_id, &fixture->fs);
541 }
542 #endif /* CONFIG_TEST_NVS_SIMULATOR */
543
544 /**
545 * @brief Test case when storage become full, so only deletion is possible.
546 */
ZTEST_F(nvs,test_nvs_full_sector)547 ZTEST_F(nvs, test_nvs_full_sector)
548 {
549 int err;
550 ssize_t len;
551 uint16_t filling_id = 0;
552 uint16_t i, data_read;
553
554 fixture->fs.sector_count = 3;
555
556 err = nvs_mount(&fixture->fs);
557 zassert_true(err == 0, "nvs_mount call failure: %d", err);
558
559 while (1) {
560 len = nvs_write(&fixture->fs, filling_id, &filling_id,
561 sizeof(filling_id));
562 if (len == -ENOSPC) {
563 break;
564 }
565 zassert_true(len == sizeof(filling_id), "nvs_write failed: %d",
566 len);
567 filling_id++;
568 }
569
570 /* check whether can delete whatever from full storage */
571 err = nvs_delete(&fixture->fs, 1);
572 zassert_true(err == 0, "nvs_delete call failure: %d", err);
573
574 /* the last sector is full now, test re-initialization */
575 err = nvs_mount(&fixture->fs);
576 zassert_true(err == 0, "nvs_mount call failure: %d", err);
577
578 len = nvs_write(&fixture->fs, filling_id, &filling_id, sizeof(filling_id));
579 zassert_true(len == sizeof(filling_id), "nvs_write failed: %d", len);
580
581 /* coherence check on NVS content */
582 for (i = 0; i <= filling_id; i++) {
583 len = nvs_read(&fixture->fs, i, &data_read, sizeof(data_read));
584 if (i == 1) {
585 zassert_true(len == -ENOENT,
586 "nvs_read shouldn't found the entry: %d",
587 len);
588 } else {
589 zassert_true(len == sizeof(data_read),
590 "nvs_read #%d failed: len is %zd instead of %zu",
591 i, len, sizeof(data_read));
592 zassert_equal(data_read, i,
593 "read unexpected data: %d instead of %d",
594 data_read, i);
595 }
596 }
597 }
598
ZTEST_F(nvs,test_delete)599 ZTEST_F(nvs, test_delete)
600 {
601 int err;
602 ssize_t len;
603 uint16_t filling_id, data_read;
604 uint32_t ate_wra, data_wra;
605
606 fixture->fs.sector_count = 3;
607
608 err = nvs_mount(&fixture->fs);
609 zassert_true(err == 0, "nvs_mount call failure: %d", err);
610
611 for (filling_id = 0; filling_id < 10; filling_id++) {
612 len = nvs_write(&fixture->fs, filling_id, &filling_id,
613 sizeof(filling_id));
614
615 zassert_true(len == sizeof(filling_id), "nvs_write failed: %d",
616 len);
617
618 if (filling_id != 0) {
619 continue;
620 }
621
622 /* delete the first entry while it is the most recent one */
623 err = nvs_delete(&fixture->fs, filling_id);
624 zassert_true(err == 0, "nvs_delete call failure: %d", err);
625
626 len = nvs_read(&fixture->fs, filling_id, &data_read, sizeof(data_read));
627 zassert_true(len == -ENOENT,
628 "nvs_read shouldn't found the entry: %d", len);
629 }
630
631 /* delete existing entry */
632 err = nvs_delete(&fixture->fs, 1);
633 zassert_true(err == 0, "nvs_delete call failure: %d", err);
634
635 len = nvs_read(&fixture->fs, 1, &data_read, sizeof(data_read));
636 zassert_true(len == -ENOENT, "nvs_read shouldn't found the entry: %d",
637 len);
638
639 ate_wra = fixture->fs.ate_wra;
640 data_wra = fixture->fs.data_wra;
641
642 /* delete already deleted entry */
643 err = nvs_delete(&fixture->fs, 1);
644 zassert_true(err == 0, "nvs_delete call failure: %d", err);
645 zassert_true(ate_wra == fixture->fs.ate_wra && data_wra == fixture->fs.data_wra,
646 "delete already deleted entry should not make"
647 " any footprint in the storage");
648
649 /* delete nonexisting entry */
650 err = nvs_delete(&fixture->fs, filling_id);
651 zassert_true(err == 0, "nvs_delete call failure: %d", err);
652 zassert_true(ate_wra == fixture->fs.ate_wra && data_wra == fixture->fs.data_wra,
653 "delete nonexistent entry should not make"
654 " any footprint in the storage");
655 }
656
657 #ifdef CONFIG_TEST_NVS_SIMULATOR
658 /*
659 * Test that garbage-collection can recover all ate's even when the last ate,
660 * ie close_ate, is corrupt. In this test the close_ate is set to point to the
661 * last ate at -5. A valid ate is however present at -6. Since the close_ate
662 * has an invalid crc8, the offset should not be used and a recover of the
663 * last ate should be done instead.
664 */
ZTEST_F(nvs,test_nvs_gc_corrupt_close_ate)665 ZTEST_F(nvs, test_nvs_gc_corrupt_close_ate)
666 {
667 struct nvs_ate ate, close_ate;
668 uint32_t data;
669 ssize_t len;
670 int err;
671 #ifdef CONFIG_NVS_DATA_CRC
672 uint32_t data_crc;
673 #endif
674
675 close_ate.id = 0xffff;
676 close_ate.offset = fixture->fs.sector_size - sizeof(struct nvs_ate) * 5;
677 close_ate.len = 0;
678 close_ate.part = 0xff;
679 close_ate.crc8 = 0xff; /* Incorrect crc8 */
680
681 ate.id = 0x1;
682 ate.offset = 0;
683 ate.len = sizeof(data);
684 #ifdef CONFIG_NVS_DATA_CRC
685 ate.len += sizeof(data_crc);
686 #endif
687 ate.part = 0xff;
688 ate.crc8 = crc8_ccitt(0xff, &ate,
689 offsetof(struct nvs_ate, crc8));
690
691 /* Mark sector 0 as closed */
692 err = flash_write(fixture->fs.flash_device, fixture->fs.offset + fixture->fs.sector_size -
693 sizeof(struct nvs_ate), &close_ate,
694 sizeof(close_ate));
695 zassert_true(err == 0, "flash_write failed: %d", err);
696
697 /* Write valid ate at -6 */
698 err = flash_write(fixture->fs.flash_device, fixture->fs.offset + fixture->fs.sector_size -
699 sizeof(struct nvs_ate) * 6, &ate, sizeof(ate));
700 zassert_true(err == 0, "flash_write failed: %d", err);
701
702 /* Write data for previous ate */
703 data = 0xaa55aa55;
704 err = flash_write(fixture->fs.flash_device, fixture->fs.offset, &data, sizeof(data));
705 zassert_true(err == 0, "flash_write failed: %d", err);
706 #ifdef CONFIG_NVS_DATA_CRC
707 data_crc = crc32_ieee((const uint8_t *) &data, sizeof(data));
708 err = flash_write(fixture->fs.flash_device, fixture->fs.offset + sizeof(data), &data_crc,
709 sizeof(data_crc));
710 zassert_true(err == 0, "flash_write for data CRC failed: %d", err);
711 #endif
712
713 /* Mark sector 1 as closed */
714 err = flash_write(fixture->fs.flash_device,
715 fixture->fs.offset + (2 * fixture->fs.sector_size) -
716 sizeof(struct nvs_ate), &close_ate,
717 sizeof(close_ate));
718 zassert_true(err == 0, "flash_write failed: %d", err);
719
720 fixture->fs.sector_count = 3;
721
722 err = nvs_mount(&fixture->fs);
723 zassert_true(err == 0, "nvs_mount call failure: %d", err);
724
725 data = 0;
726 len = nvs_read(&fixture->fs, 1, &data, sizeof(data));
727 zassert_true(len == sizeof(data),
728 "nvs_read should have read %d bytes", sizeof(data));
729 zassert_true(data == 0xaa55aa55, "unexpected value %d", data);
730 }
731
732 /*
733 * Test that garbage-collection correctly handles corrupt ate's.
734 */
ZTEST_F(nvs,test_nvs_gc_corrupt_ate)735 ZTEST_F(nvs, test_nvs_gc_corrupt_ate)
736 {
737 struct nvs_ate corrupt_ate, close_ate;
738 int err;
739
740 close_ate.id = 0xffff;
741 close_ate.offset = fixture->fs.sector_size / 2;
742 close_ate.len = 0;
743 close_ate.part = 0xff;
744 close_ate.crc8 = crc8_ccitt(0xff, &close_ate,
745 offsetof(struct nvs_ate, crc8));
746
747 corrupt_ate.id = 0xdead;
748 corrupt_ate.offset = 0;
749 corrupt_ate.len = 20;
750 corrupt_ate.part = 0xff;
751 corrupt_ate.crc8 = 0xff; /* Incorrect crc8 */
752
753 /* Mark sector 0 as closed */
754 err = flash_write(fixture->fs.flash_device, fixture->fs.offset + fixture->fs.sector_size -
755 sizeof(struct nvs_ate), &close_ate,
756 sizeof(close_ate));
757 zassert_true(err == 0, "flash_write failed: %d", err);
758
759 /* Write a corrupt ate */
760 err = flash_write(fixture->fs.flash_device,
761 fixture->fs.offset + (fixture->fs.sector_size / 2),
762 &corrupt_ate, sizeof(corrupt_ate));
763 zassert_true(err == 0, "flash_write failed: %d", err);
764
765 /* Mark sector 1 as closed */
766 err = flash_write(fixture->fs.flash_device,
767 fixture->fs.offset + (2 * fixture->fs.sector_size) -
768 sizeof(struct nvs_ate), &close_ate,
769 sizeof(close_ate));
770 zassert_true(err == 0, "flash_write failed: %d", err);
771
772 fixture->fs.sector_count = 3;
773
774 err = nvs_mount(&fixture->fs);
775 zassert_true(err == 0, "nvs_mount call failure: %d", err);
776 }
777 #endif /* CONFIG_TEST_NVS_SIMULATOR */
778
779 #ifdef CONFIG_NVS_LOOKUP_CACHE
num_matching_cache_entries(uint32_t addr,bool compare_sector_only,struct nvs_fs * fs)780 static size_t num_matching_cache_entries(uint32_t addr, bool compare_sector_only, struct nvs_fs *fs)
781 {
782 size_t i, num = 0;
783 uint32_t mask = compare_sector_only ? ADDR_SECT_MASK : UINT32_MAX;
784
785 for (i = 0; i < CONFIG_NVS_LOOKUP_CACHE_SIZE; i++) {
786 if ((fs->lookup_cache[i] & mask) == addr) {
787 num++;
788 }
789 }
790
791 return num;
792 }
793
num_occupied_cache_entries(struct nvs_fs * fs)794 static size_t num_occupied_cache_entries(struct nvs_fs *fs)
795 {
796 return CONFIG_NVS_LOOKUP_CACHE_SIZE -
797 num_matching_cache_entries(NVS_LOOKUP_CACHE_NO_ADDR, false, fs);
798 }
799 #endif
800
801 /*
802 * Test that NVS lookup cache is properly rebuilt on nvs_mount(), or initialized
803 * to NVS_LOOKUP_CACHE_NO_ADDR if the store is empty.
804 */
ZTEST_F(nvs,test_nvs_cache_init)805 ZTEST_F(nvs, test_nvs_cache_init)
806 {
807 #ifdef CONFIG_NVS_LOOKUP_CACHE
808 int err;
809 size_t num;
810 uint32_t ate_addr;
811 uint8_t data = 0;
812
813 /* Test cache initialization when the store is empty */
814
815 fixture->fs.sector_count = 3;
816 err = nvs_mount(&fixture->fs);
817 zassert_true(err == 0, "nvs_mount call failure: %d", err);
818
819 num = num_occupied_cache_entries(&fixture->fs);
820 zassert_equal(num, 0, "uninitialized cache");
821
822 /* Test cache update after nvs_write() */
823
824 ate_addr = fixture->fs.ate_wra;
825 err = nvs_write(&fixture->fs, 1, &data, sizeof(data));
826 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
827
828 num = num_occupied_cache_entries(&fixture->fs);
829 zassert_equal(num, 1, "cache not updated after write");
830
831 num = num_matching_cache_entries(ate_addr, false, &fixture->fs);
832 zassert_equal(num, 1, "invalid cache entry after write");
833
834 /* Test cache initialization when the store is non-empty */
835
836 memset(fixture->fs.lookup_cache, 0xAA, sizeof(fixture->fs.lookup_cache));
837 err = nvs_mount(&fixture->fs);
838 zassert_true(err == 0, "nvs_mount call failure: %d", err);
839
840 num = num_occupied_cache_entries(&fixture->fs);
841 zassert_equal(num, 1, "uninitialized cache after restart");
842
843 num = num_matching_cache_entries(ate_addr, false, &fixture->fs);
844 zassert_equal(num, 1, "invalid cache entry after restart");
845 #endif
846 }
847
848 /*
849 * Test that even after writing more NVS IDs than the number of NVS lookup cache
850 * entries they all can be read correctly.
851 */
ZTEST_F(nvs,test_nvs_cache_collission)852 ZTEST_F(nvs, test_nvs_cache_collission)
853 {
854 #ifdef CONFIG_NVS_LOOKUP_CACHE
855 int err;
856 uint16_t id;
857 uint16_t data;
858
859 fixture->fs.sector_count = 3;
860 err = nvs_mount(&fixture->fs);
861 zassert_true(err == 0, "nvs_mount call failure: %d", err);
862
863 for (id = 0; id < CONFIG_NVS_LOOKUP_CACHE_SIZE + 1; id++) {
864 data = id;
865 err = nvs_write(&fixture->fs, id, &data, sizeof(data));
866 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
867 }
868
869 for (id = 0; id < CONFIG_NVS_LOOKUP_CACHE_SIZE + 1; id++) {
870 err = nvs_read(&fixture->fs, id, &data, sizeof(data));
871 zassert_equal(err, sizeof(data), "nvs_read call failure: %d", err);
872 zassert_equal(data, id, "incorrect data read");
873 }
874 #endif
875 }
876
877 /*
878 * Test that NVS lookup cache does not contain any address from gc-ed sector
879 */
ZTEST_F(nvs,test_nvs_cache_gc)880 ZTEST_F(nvs, test_nvs_cache_gc)
881 {
882 #ifdef CONFIG_NVS_LOOKUP_CACHE
883 int err;
884 size_t num;
885 uint16_t data = 0;
886
887 fixture->fs.sector_count = 3;
888 err = nvs_mount(&fixture->fs);
889 zassert_true(err == 0, "nvs_mount call failure: %d", err);
890
891 /* Fill the first sector with writes of ID 1 */
892
893 while (fixture->fs.data_wra + sizeof(data) + sizeof(struct nvs_ate)
894 <= fixture->fs.ate_wra) {
895 ++data;
896 err = nvs_write(&fixture->fs, 1, &data, sizeof(data));
897 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
898 }
899
900 /* Verify that cache contains a single entry for sector 0 */
901
902 num = num_matching_cache_entries(0 << ADDR_SECT_SHIFT, true, &fixture->fs);
903 zassert_equal(num, 1, "invalid cache content after filling sector 0");
904
905 /* Fill the second sector with writes of ID 2 */
906
907 while ((fixture->fs.ate_wra >> ADDR_SECT_SHIFT) != 2) {
908 ++data;
909 err = nvs_write(&fixture->fs, 2, &data, sizeof(data));
910 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
911 }
912
913 /*
914 * At this point sector 0 should have been gc-ed. Verify that action is
915 * reflected by the cache content.
916 */
917
918 num = num_matching_cache_entries(0 << ADDR_SECT_SHIFT, true, &fixture->fs);
919 zassert_equal(num, 0, "not invalidated cache entries aftetr gc");
920
921 num = num_matching_cache_entries(2 << ADDR_SECT_SHIFT, true, &fixture->fs);
922 zassert_equal(num, 2, "invalid cache content after gc");
923 #endif
924 }
925
926 /*
927 * Test NVS lookup cache hash quality.
928 */
ZTEST_F(nvs,test_nvs_cache_hash_quality)929 ZTEST_F(nvs, test_nvs_cache_hash_quality)
930 {
931 #ifdef CONFIG_NVS_LOOKUP_CACHE
932 const size_t MIN_CACHE_OCCUPANCY = CONFIG_NVS_LOOKUP_CACHE_SIZE * 6 / 10;
933 int err;
934 size_t num;
935 uint16_t id;
936 uint16_t data;
937
938 err = nvs_mount(&fixture->fs);
939 zassert_true(err == 0, "nvs_mount call failure: %d", err);
940
941 /* Write NVS IDs from 0 to CONFIG_NVS_LOOKUP_CACHE_SIZE - 1 */
942
943 for (uint16_t i = 0; i < CONFIG_NVS_LOOKUP_CACHE_SIZE; i++) {
944 id = i;
945 data = 0;
946
947 err = nvs_write(&fixture->fs, id, &data, sizeof(data));
948 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
949 }
950
951 /* Verify that at least 60% cache entries are occupied */
952
953 num = num_occupied_cache_entries(&fixture->fs);
954 TC_PRINT("Cache occupancy: %u\n", (unsigned int)num);
955 zassert_between_inclusive(num, MIN_CACHE_OCCUPANCY, CONFIG_NVS_LOOKUP_CACHE_SIZE,
956 "too low cache occupancy - poor hash quality");
957
958 err = nvs_clear(&fixture->fs);
959 zassert_true(err == 0, "nvs_clear call failure: %d", err);
960
961 err = nvs_mount(&fixture->fs);
962 zassert_true(err == 0, "nvs_mount call failure: %d", err);
963
964 /* Write CONFIG_NVS_LOOKUP_CACHE_SIZE NVS IDs that form the following series: 0, 4, 8... */
965
966 for (uint16_t i = 0; i < CONFIG_NVS_LOOKUP_CACHE_SIZE; i++) {
967 id = i * 4;
968 data = 0;
969
970 err = nvs_write(&fixture->fs, id, &data, sizeof(data));
971 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
972 }
973
974 /* Verify that at least 60% cache entries are occupied */
975
976 num = num_occupied_cache_entries(&fixture->fs);
977 TC_PRINT("Cache occupancy: %u\n", (unsigned int)num);
978 zassert_between_inclusive(num, MIN_CACHE_OCCUPANCY, CONFIG_NVS_LOOKUP_CACHE_SIZE,
979 "too low cache occupancy - poor hash quality");
980
981 #endif
982 }
983
984 #ifdef CONFIG_TEST_NVS_SIMULATOR
985 /*
986 * Test NVS bad region initialization recovery.
987 */
ZTEST_F(nvs,test_nvs_init_bad_memory_region)988 ZTEST_F(nvs, test_nvs_init_bad_memory_region)
989 {
990 int err;
991 uint32_t data;
992
993 err = nvs_mount(&fixture->fs);
994 zassert_true(err == 0, "nvs_mount call failure: %d", err);
995
996 /* Write bad ATE to each sector */
997 for (uint16_t i = 0; i < TEST_SECTOR_COUNT; i++) {
998 data = 0xdeadbeef;
999 err = flash_write(fixture->fs.flash_device,
1000 fixture->fs.offset + (fixture->fs.sector_size * (i + 1)) -
1001 sizeof(struct nvs_ate),
1002 &data, sizeof(data));
1003 zassert_true(err == 0, "flash_write failed: %d", err);
1004 }
1005
1006 /* Reinitialize the NVS. */
1007 memset(&fixture->fs, 0, sizeof(fixture->fs));
1008 (void)setup();
1009
1010 #ifdef CONFIG_NVS_INIT_BAD_MEMORY_REGION
1011 err = nvs_mount(&fixture->fs);
1012 zassert_true(err == 0, "nvs_mount call failure: %d", err);
1013
1014 /* Ensure that the NVS is able to store new content. */
1015 execute_long_pattern_write(TEST_DATA_ID, &fixture->fs);
1016 #else
1017 err = nvs_mount(&fixture->fs);
1018 zassert_true(err == -EDEADLK, "nvs_mount call ok, expect fail: %d", err);
1019 #endif
1020 }
1021 #endif /* CONFIG_TEST_NVS_SIMULATOR */
1022