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