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