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