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.part = 0xff;
663 close_ate.crc8 = 0xff; /* Incorrect crc8 */
664
665 ate.id = 0x1;
666 ate.offset = 0;
667 ate.len = sizeof(data);
668 #ifdef CONFIG_NVS_DATA_CRC
669 ate.len += sizeof(data_crc);
670 #endif
671 ate.part = 0xff;
672 ate.crc8 = crc8_ccitt(0xff, &ate,
673 offsetof(struct nvs_ate, crc8));
674
675 /* Mark sector 0 as closed */
676 err = flash_write(fixture->fs.flash_device, fixture->fs.offset + fixture->fs.sector_size -
677 sizeof(struct nvs_ate), &close_ate,
678 sizeof(close_ate));
679 zassert_true(err == 0, "flash_write failed: %d", err);
680
681 /* Write valid ate at -6 */
682 err = flash_write(fixture->fs.flash_device, fixture->fs.offset + fixture->fs.sector_size -
683 sizeof(struct nvs_ate) * 6, &ate, sizeof(ate));
684 zassert_true(err == 0, "flash_write failed: %d", err);
685
686 /* Write data for previous ate */
687 data = 0xaa55aa55;
688 err = flash_write(fixture->fs.flash_device, fixture->fs.offset, &data, sizeof(data));
689 zassert_true(err == 0, "flash_write failed: %d", err);
690 #ifdef CONFIG_NVS_DATA_CRC
691 data_crc = crc32_ieee((const uint8_t *) &data, sizeof(data));
692 err = flash_write(fixture->fs.flash_device, fixture->fs.offset + sizeof(data), &data_crc,
693 sizeof(data_crc));
694 zassert_true(err == 0, "flash_write for data CRC failed: %d", err);
695 #endif
696
697 /* Mark sector 1 as closed */
698 err = flash_write(fixture->fs.flash_device,
699 fixture->fs.offset + (2 * fixture->fs.sector_size) -
700 sizeof(struct nvs_ate), &close_ate,
701 sizeof(close_ate));
702 zassert_true(err == 0, "flash_write failed: %d", err);
703
704 fixture->fs.sector_count = 3;
705
706 err = nvs_mount(&fixture->fs);
707 zassert_true(err == 0, "nvs_mount call failure: %d", err);
708
709 data = 0;
710 len = nvs_read(&fixture->fs, 1, &data, sizeof(data));
711 zassert_true(len == sizeof(data),
712 "nvs_read should have read %d bytes", sizeof(data));
713 zassert_true(data == 0xaa55aa55, "unexpected value %d", data);
714 }
715
716 /*
717 * Test that garbage-collection correctly handles corrupt ate's.
718 */
ZTEST_F(nvs,test_nvs_gc_corrupt_ate)719 ZTEST_F(nvs, test_nvs_gc_corrupt_ate)
720 {
721 struct nvs_ate corrupt_ate, close_ate;
722 int err;
723
724 close_ate.id = 0xffff;
725 close_ate.offset = fixture->fs.sector_size / 2;
726 close_ate.len = 0;
727 close_ate.part = 0xff;
728 close_ate.crc8 = crc8_ccitt(0xff, &close_ate,
729 offsetof(struct nvs_ate, crc8));
730
731 corrupt_ate.id = 0xdead;
732 corrupt_ate.offset = 0;
733 corrupt_ate.len = 20;
734 corrupt_ate.part = 0xff;
735 corrupt_ate.crc8 = 0xff; /* Incorrect crc8 */
736
737 /* Mark sector 0 as closed */
738 err = flash_write(fixture->fs.flash_device, fixture->fs.offset + fixture->fs.sector_size -
739 sizeof(struct nvs_ate), &close_ate,
740 sizeof(close_ate));
741 zassert_true(err == 0, "flash_write failed: %d", err);
742
743 /* Write a corrupt ate */
744 err = flash_write(fixture->fs.flash_device,
745 fixture->fs.offset + (fixture->fs.sector_size / 2),
746 &corrupt_ate, sizeof(corrupt_ate));
747 zassert_true(err == 0, "flash_write failed: %d", err);
748
749 /* Mark sector 1 as closed */
750 err = flash_write(fixture->fs.flash_device,
751 fixture->fs.offset + (2 * fixture->fs.sector_size) -
752 sizeof(struct nvs_ate), &close_ate,
753 sizeof(close_ate));
754 zassert_true(err == 0, "flash_write failed: %d", err);
755
756 fixture->fs.sector_count = 3;
757
758 err = nvs_mount(&fixture->fs);
759 zassert_true(err == 0, "nvs_mount call failure: %d", err);
760 }
761
762 #ifdef CONFIG_NVS_LOOKUP_CACHE
num_matching_cache_entries(uint32_t addr,bool compare_sector_only,struct nvs_fs * fs)763 static size_t num_matching_cache_entries(uint32_t addr, bool compare_sector_only, struct nvs_fs *fs)
764 {
765 size_t i, num = 0;
766 uint32_t mask = compare_sector_only ? ADDR_SECT_MASK : UINT32_MAX;
767
768 for (i = 0; i < CONFIG_NVS_LOOKUP_CACHE_SIZE; i++) {
769 if ((fs->lookup_cache[i] & mask) == addr) {
770 num++;
771 }
772 }
773
774 return num;
775 }
776
num_occupied_cache_entries(struct nvs_fs * fs)777 static size_t num_occupied_cache_entries(struct nvs_fs *fs)
778 {
779 return CONFIG_NVS_LOOKUP_CACHE_SIZE -
780 num_matching_cache_entries(NVS_LOOKUP_CACHE_NO_ADDR, false, fs);
781 }
782 #endif
783
784 /*
785 * Test that NVS lookup cache is properly rebuilt on nvs_mount(), or initialized
786 * to NVS_LOOKUP_CACHE_NO_ADDR if the store is empty.
787 */
ZTEST_F(nvs,test_nvs_cache_init)788 ZTEST_F(nvs, test_nvs_cache_init)
789 {
790 #ifdef CONFIG_NVS_LOOKUP_CACHE
791 int err;
792 size_t num;
793 uint32_t ate_addr;
794 uint8_t data = 0;
795
796 /* Test cache initialization when the store is empty */
797
798 fixture->fs.sector_count = 3;
799 err = nvs_mount(&fixture->fs);
800 zassert_true(err == 0, "nvs_mount call failure: %d", err);
801
802 num = num_occupied_cache_entries(&fixture->fs);
803 zassert_equal(num, 0, "uninitialized cache");
804
805 /* Test cache update after nvs_write() */
806
807 ate_addr = fixture->fs.ate_wra;
808 err = nvs_write(&fixture->fs, 1, &data, sizeof(data));
809 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
810
811 num = num_occupied_cache_entries(&fixture->fs);
812 zassert_equal(num, 1, "cache not updated after write");
813
814 num = num_matching_cache_entries(ate_addr, false, &fixture->fs);
815 zassert_equal(num, 1, "invalid cache entry after write");
816
817 /* Test cache initialization when the store is non-empty */
818
819 memset(fixture->fs.lookup_cache, 0xAA, sizeof(fixture->fs.lookup_cache));
820 err = nvs_mount(&fixture->fs);
821 zassert_true(err == 0, "nvs_mount call failure: %d", err);
822
823 num = num_occupied_cache_entries(&fixture->fs);
824 zassert_equal(num, 1, "uninitialized cache after restart");
825
826 num = num_matching_cache_entries(ate_addr, false, &fixture->fs);
827 zassert_equal(num, 1, "invalid cache entry after restart");
828 #endif
829 }
830
831 /*
832 * Test that even after writing more NVS IDs than the number of NVS lookup cache
833 * entries they all can be read correctly.
834 */
ZTEST_F(nvs,test_nvs_cache_collission)835 ZTEST_F(nvs, test_nvs_cache_collission)
836 {
837 #ifdef CONFIG_NVS_LOOKUP_CACHE
838 int err;
839 uint16_t id;
840 uint16_t data;
841
842 fixture->fs.sector_count = 3;
843 err = nvs_mount(&fixture->fs);
844 zassert_true(err == 0, "nvs_mount call failure: %d", err);
845
846 for (id = 0; id < CONFIG_NVS_LOOKUP_CACHE_SIZE + 1; id++) {
847 data = id;
848 err = nvs_write(&fixture->fs, id, &data, sizeof(data));
849 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
850 }
851
852 for (id = 0; id < CONFIG_NVS_LOOKUP_CACHE_SIZE + 1; id++) {
853 err = nvs_read(&fixture->fs, id, &data, sizeof(data));
854 zassert_equal(err, sizeof(data), "nvs_read call failure: %d", err);
855 zassert_equal(data, id, "incorrect data read");
856 }
857 #endif
858 }
859
860 /*
861 * Test that NVS lookup cache does not contain any address from gc-ed sector
862 */
ZTEST_F(nvs,test_nvs_cache_gc)863 ZTEST_F(nvs, test_nvs_cache_gc)
864 {
865 #ifdef CONFIG_NVS_LOOKUP_CACHE
866 int err;
867 size_t num;
868 uint16_t data = 0;
869
870 fixture->fs.sector_count = 3;
871 err = nvs_mount(&fixture->fs);
872 zassert_true(err == 0, "nvs_mount call failure: %d", err);
873
874 /* Fill the first sector with writes of ID 1 */
875
876 while (fixture->fs.data_wra + sizeof(data) + sizeof(struct nvs_ate)
877 <= fixture->fs.ate_wra) {
878 ++data;
879 err = nvs_write(&fixture->fs, 1, &data, sizeof(data));
880 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
881 }
882
883 /* Verify that cache contains a single entry for sector 0 */
884
885 num = num_matching_cache_entries(0 << ADDR_SECT_SHIFT, true, &fixture->fs);
886 zassert_equal(num, 1, "invalid cache content after filling sector 0");
887
888 /* Fill the second sector with writes of ID 2 */
889
890 while ((fixture->fs.ate_wra >> ADDR_SECT_SHIFT) != 2) {
891 ++data;
892 err = nvs_write(&fixture->fs, 2, &data, sizeof(data));
893 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
894 }
895
896 /*
897 * At this point sector 0 should have been gc-ed. Verify that action is
898 * reflected by the cache content.
899 */
900
901 num = num_matching_cache_entries(0 << ADDR_SECT_SHIFT, true, &fixture->fs);
902 zassert_equal(num, 0, "not invalidated cache entries aftetr gc");
903
904 num = num_matching_cache_entries(2 << ADDR_SECT_SHIFT, true, &fixture->fs);
905 zassert_equal(num, 2, "invalid cache content after gc");
906 #endif
907 }
908
909 /*
910 * Test NVS lookup cache hash quality.
911 */
ZTEST_F(nvs,test_nvs_cache_hash_quality)912 ZTEST_F(nvs, test_nvs_cache_hash_quality)
913 {
914 #ifdef CONFIG_NVS_LOOKUP_CACHE
915 const size_t MIN_CACHE_OCCUPANCY = CONFIG_NVS_LOOKUP_CACHE_SIZE * 6 / 10;
916 int err;
917 size_t num;
918 uint16_t id;
919 uint16_t data;
920
921 err = nvs_mount(&fixture->fs);
922 zassert_true(err == 0, "nvs_mount call failure: %d", err);
923
924 /* Write NVS IDs from 0 to CONFIG_NVS_LOOKUP_CACHE_SIZE - 1 */
925
926 for (uint16_t i = 0; i < CONFIG_NVS_LOOKUP_CACHE_SIZE; i++) {
927 id = i;
928 data = 0;
929
930 err = nvs_write(&fixture->fs, id, &data, sizeof(data));
931 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
932 }
933
934 /* Verify that at least 60% cache entries are occupied */
935
936 num = num_occupied_cache_entries(&fixture->fs);
937 TC_PRINT("Cache occupancy: %u\n", (unsigned int)num);
938 zassert_between_inclusive(num, MIN_CACHE_OCCUPANCY, CONFIG_NVS_LOOKUP_CACHE_SIZE,
939 "too low cache occupancy - poor hash quality");
940
941 err = nvs_clear(&fixture->fs);
942 zassert_true(err == 0, "nvs_clear call failure: %d", err);
943
944 err = nvs_mount(&fixture->fs);
945 zassert_true(err == 0, "nvs_mount call failure: %d", err);
946
947 /* Write CONFIG_NVS_LOOKUP_CACHE_SIZE NVS IDs that form the following series: 0, 4, 8... */
948
949 for (uint16_t i = 0; i < CONFIG_NVS_LOOKUP_CACHE_SIZE; i++) {
950 id = i * 4;
951 data = 0;
952
953 err = nvs_write(&fixture->fs, id, &data, sizeof(data));
954 zassert_equal(err, sizeof(data), "nvs_write call failure: %d", err);
955 }
956
957 /* Verify that at least 60% cache entries are occupied */
958
959 num = num_occupied_cache_entries(&fixture->fs);
960 TC_PRINT("Cache occupancy: %u\n", (unsigned int)num);
961 zassert_between_inclusive(num, MIN_CACHE_OCCUPANCY, CONFIG_NVS_LOOKUP_CACHE_SIZE,
962 "too low cache occupancy - poor hash quality");
963
964 #endif
965 }
966
967 /*
968 * Test NVS bad region initialization recovery.
969 */
ZTEST_F(nvs,test_nvs_init_bad_memory_region)970 ZTEST_F(nvs, test_nvs_init_bad_memory_region)
971 {
972 int err;
973 uint32_t data;
974
975 err = nvs_mount(&fixture->fs);
976 zassert_true(err == 0, "nvs_mount call failure: %d", err);
977
978 /* Write bad ATE to each sector */
979 for (uint16_t i = 0; i < TEST_SECTOR_COUNT; i++) {
980 data = 0xdeadbeef;
981 err = flash_write(fixture->fs.flash_device,
982 fixture->fs.offset + (fixture->fs.sector_size * (i + 1)) -
983 sizeof(struct nvs_ate),
984 &data, sizeof(data));
985 zassert_true(err == 0, "flash_write failed: %d", err);
986 }
987
988 /* Reinitialize the NVS. */
989 memset(&fixture->fs, 0, sizeof(fixture->fs));
990 (void)setup();
991
992 #ifdef CONFIG_NVS_INIT_BAD_MEMORY_REGION
993 err = nvs_mount(&fixture->fs);
994 zassert_true(err == 0, "nvs_mount call failure: %d", err);
995
996 /* Ensure that the NVS is able to store new content. */
997 execute_long_pattern_write(TEST_DATA_ID, &fixture->fs);
998 #else
999 err = nvs_mount(&fixture->fs);
1000 zassert_true(err == -EDEADLK, "nvs_mount call ok, expect fail: %d", err);
1001 #endif
1002 }
1003