1 /*
2  * Copyright (c) 2019 Nordic Semiconductor ASA
3  * Copyright (c) 2024 BayLibre SAS
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <stdio.h>
9 #include <string.h>
10 #include <zephyr/ztest.h>
11 
12 #include <zephyr/drivers/flash.h>
13 #include <zephyr/fs/zms.h>
14 #include <zephyr/stats/stats.h>
15 #include <zephyr/storage/flash_map.h>
16 #include <zephyr/sys/crc.h>
17 #include "zms_priv.h"
18 
19 #define TEST_ZMS_AREA        storage_partition
20 #define TEST_ZMS_AREA_OFFSET FIXED_PARTITION_OFFSET(TEST_ZMS_AREA)
21 #define TEST_ZMS_AREA_ID     FIXED_PARTITION_ID(TEST_ZMS_AREA)
22 #define TEST_ZMS_AREA_DEV    DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(TEST_ZMS_AREA)))
23 #define TEST_DATA_ID         1
24 #define TEST_SECTOR_COUNT    5U
25 
26 static const struct device *const flash_dev = TEST_ZMS_AREA_DEV;
27 
28 struct zms_fixture {
29 	struct zms_fs fs;
30 #ifdef CONFIG_TEST_ZMS_SIMULATOR
31 	struct stats_hdr *sim_stats;
32 	struct stats_hdr *sim_thresholds;
33 #endif /* CONFIG_TEST_ZMS_SIMULATOR */
34 };
35 
setup(void)36 static void *setup(void)
37 {
38 	int err;
39 	const struct flash_area *fa;
40 	struct flash_pages_info info;
41 	static struct zms_fixture fixture;
42 
43 	__ASSERT_NO_MSG(device_is_ready(flash_dev));
44 
45 	err = flash_area_open(TEST_ZMS_AREA_ID, &fa);
46 	zassert_true(err == 0, "flash_area_open() fail: %d", err);
47 
48 	fixture.fs.offset = TEST_ZMS_AREA_OFFSET;
49 	err = flash_get_page_info_by_offs(flash_area_get_device(fa), fixture.fs.offset, &info);
50 	zassert_true(err == 0, "Unable to get page info: %d", err);
51 
52 	fixture.fs.sector_size = info.size;
53 	fixture.fs.sector_count = TEST_SECTOR_COUNT;
54 	fixture.fs.flash_device = flash_area_get_device(fa);
55 
56 	return &fixture;
57 }
58 
before(void * data)59 static void before(void *data)
60 {
61 #ifdef CONFIG_TEST_ZMS_SIMULATOR
62 	struct zms_fixture *fixture = (struct zms_fixture *)data;
63 
64 	fixture->sim_stats = stats_group_find("flash_sim_stats");
65 	fixture->sim_thresholds = stats_group_find("flash_sim_thresholds");
66 #endif /* CONFIG_TEST_ZMS_SIMULATOR */
67 }
68 
after(void * data)69 static void after(void *data)
70 {
71 	struct zms_fixture *fixture = (struct zms_fixture *)data;
72 
73 #ifdef CONFIG_TEST_ZMS_SIMULATOR
74 	if (fixture->sim_stats) {
75 		stats_reset(fixture->sim_stats);
76 	}
77 	if (fixture->sim_thresholds) {
78 		stats_reset(fixture->sim_thresholds);
79 	}
80 #endif /* CONFIG_TEST_ZMS_SIMULATOR */
81 
82 	/* Clear ZMS */
83 	if (fixture->fs.ready) {
84 		int err;
85 
86 		err = zms_clear(&fixture->fs);
87 		zassert_true(err == 0, "zms_clear call failure: %d", err);
88 	}
89 
90 	fixture->fs.sector_count = TEST_SECTOR_COUNT;
91 }
92 
93 ZTEST_SUITE(zms, NULL, setup, before, after, NULL);
94 
ZTEST_F(zms,test_zms_mount)95 ZTEST_F(zms, test_zms_mount)
96 {
97 	int err;
98 
99 	err = zms_mount(&fixture->fs);
100 	zassert_true(err == 0, "zms_mount call failure: %d", err);
101 }
102 
execute_long_pattern_write(uint32_t id,struct zms_fs * fs)103 static void execute_long_pattern_write(uint32_t id, struct zms_fs *fs)
104 {
105 	char rd_buf[512];
106 	char wr_buf[512];
107 	char pattern[] = {0xDE, 0xAD, 0xBE, 0xEF};
108 	size_t len;
109 
110 	len = zms_read(fs, id, rd_buf, sizeof(rd_buf));
111 	zassert_true(len == -ENOENT, "zms_read unexpected failure: %d", len);
112 
113 	BUILD_ASSERT((sizeof(wr_buf) % sizeof(pattern)) == 0);
114 	for (int i = 0; i < sizeof(wr_buf); i += sizeof(pattern)) {
115 		memcpy(wr_buf + i, pattern, sizeof(pattern));
116 	}
117 
118 	len = zms_write(fs, id, wr_buf, sizeof(wr_buf));
119 	zassert_true(len == sizeof(wr_buf), "zms_write failed: %d", len);
120 
121 	len = zms_read(fs, id, rd_buf, sizeof(rd_buf));
122 	zassert_true(len == sizeof(rd_buf), "zms_read unexpected failure: %d", len);
123 	zassert_mem_equal(wr_buf, rd_buf, sizeof(rd_buf), "RD buff should be equal to the WR buff");
124 }
125 
ZTEST_F(zms,test_zms_write)126 ZTEST_F(zms, test_zms_write)
127 {
128 	int err;
129 
130 	err = zms_mount(&fixture->fs);
131 	zassert_true(err == 0, "zms_mount call failure: %d", err);
132 
133 	execute_long_pattern_write(TEST_DATA_ID, &fixture->fs);
134 }
135 
136 #ifdef CONFIG_TEST_ZMS_SIMULATOR
flash_sim_write_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)137 static int flash_sim_write_calls_find(struct stats_hdr *hdr, void *arg, const char *name,
138 				      uint16_t off)
139 {
140 	if (!strcmp(name, "flash_write_calls")) {
141 		uint32_t **flash_write_stat = (uint32_t **)arg;
142 		*flash_write_stat = (uint32_t *)((uint8_t *)hdr + off);
143 	}
144 
145 	return 0;
146 }
147 
flash_sim_max_write_calls_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)148 static int flash_sim_max_write_calls_find(struct stats_hdr *hdr, void *arg, const char *name,
149 					  uint16_t off)
150 {
151 	if (!strcmp(name, "max_write_calls")) {
152 		uint32_t **max_write_calls = (uint32_t **)arg;
153 		*max_write_calls = (uint32_t *)((uint8_t *)hdr + off);
154 	}
155 
156 	return 0;
157 }
158 
ZTEST_F(zms,test_zms_corrupted_write)159 ZTEST_F(zms, test_zms_corrupted_write)
160 {
161 	int err;
162 	size_t len;
163 	char rd_buf[512];
164 	char wr_buf_1[512];
165 	char wr_buf_2[512];
166 	char pattern_1[] = {0xDE, 0xAD, 0xBE, 0xEF};
167 	char pattern_2[] = {0x03, 0xAA, 0x85, 0x6F};
168 	uint32_t *flash_write_stat;
169 	uint32_t *flash_max_write_calls;
170 
171 	err = zms_mount(&fixture->fs);
172 	zassert_true(err == 0, "zms_mount call failure: %d", err);
173 
174 	err = zms_read(&fixture->fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
175 	zassert_true(err == -ENOENT, "zms_read unexpected failure: %d", err);
176 
177 	BUILD_ASSERT((sizeof(wr_buf_1) % sizeof(pattern_1)) == 0);
178 	for (int i = 0; i < sizeof(wr_buf_1); i += sizeof(pattern_1)) {
179 		memcpy(wr_buf_1 + i, pattern_1, sizeof(pattern_1));
180 	}
181 
182 	len = zms_write(&fixture->fs, TEST_DATA_ID, wr_buf_1, sizeof(wr_buf_1));
183 	zassert_true(len == sizeof(wr_buf_1), "zms_write failed: %d", len);
184 
185 	len = zms_read(&fixture->fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
186 	zassert_true(len == sizeof(rd_buf), "zms_read unexpected failure: %d", len);
187 	zassert_mem_equal(wr_buf_1, rd_buf, sizeof(rd_buf),
188 			  "RD buff should be equal to the first WR buff");
189 
190 	BUILD_ASSERT((sizeof(wr_buf_2) % sizeof(pattern_2)) == 0);
191 	for (int i = 0; i < sizeof(wr_buf_2); i += sizeof(pattern_2)) {
192 		memcpy(wr_buf_2 + i, pattern_2, sizeof(pattern_2));
193 	}
194 
195 	/* Set the maximum number of writes that the flash simulator can
196 	 * execute.
197 	 */
198 	stats_walk(fixture->sim_thresholds, flash_sim_max_write_calls_find, &flash_max_write_calls);
199 	stats_walk(fixture->sim_stats, flash_sim_write_calls_find, &flash_write_stat);
200 
201 	*flash_max_write_calls = *flash_write_stat - 1;
202 	*flash_write_stat = 0;
203 
204 	/* Flash simulator will lose part of the data at the end of this write.
205 	 * This should simulate power down during flash write. The written data
206 	 * are corrupted at this point and should be discarded by the ZMS.
207 	 */
208 	len = zms_write(&fixture->fs, TEST_DATA_ID, wr_buf_2, sizeof(wr_buf_2));
209 	zassert_true(len == sizeof(wr_buf_2), "zms_write failed: %d", len);
210 
211 	/* Reinitialize the ZMS. */
212 	memset(&fixture->fs, 0, sizeof(fixture->fs));
213 	(void)setup();
214 	err = zms_mount(&fixture->fs);
215 	zassert_true(err == 0, "zms_mount call failure: %d", err);
216 
217 	len = zms_read(&fixture->fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
218 	zassert_true(len == sizeof(rd_buf), "zms_read unexpected failure: %d", len);
219 	zassert_true(memcmp(wr_buf_2, rd_buf, sizeof(rd_buf)) != 0,
220 		     "RD buff should not be equal to the second WR buff because of "
221 		     "corrupted write operation");
222 	zassert_mem_equal(wr_buf_1, rd_buf, sizeof(rd_buf),
223 			  "RD buff should be equal to the first WR buff because subsequent "
224 			  "write operation has failed");
225 }
226 
ZTEST_F(zms,test_zms_gc)227 ZTEST_F(zms, test_zms_gc)
228 {
229 	int err;
230 	int len;
231 	uint8_t buf[32];
232 	uint8_t rd_buf[32];
233 	const uint8_t max_id = 10;
234 	/* 21st write will trigger GC. */
235 	const uint16_t max_writes = 21;
236 
237 	fixture->fs.sector_count = 2;
238 
239 	err = zms_mount(&fixture->fs);
240 	zassert_true(err == 0, "zms_mount call failure: %d", err);
241 
242 	for (int i = 0; i < max_writes; i++) {
243 		uint8_t id = (i % max_id);
244 		uint8_t id_data = id + max_id * (i / max_id);
245 
246 		memset(buf, id_data, sizeof(buf));
247 
248 		len = zms_write(&fixture->fs, id, buf, sizeof(buf));
249 		zassert_true(len == sizeof(buf), "zms_write failed: %d", len);
250 	}
251 
252 	for (int id = 0; id < max_id; id++) {
253 		len = zms_read(&fixture->fs, id, rd_buf, sizeof(buf));
254 		zassert_true(len == sizeof(rd_buf), "zms_read unexpected failure: %d", len);
255 
256 		for (int i = 0; i < sizeof(rd_buf); i++) {
257 			rd_buf[i] = rd_buf[i] % max_id;
258 			buf[i] = id;
259 		}
260 		zassert_mem_equal(buf, rd_buf, sizeof(rd_buf),
261 				  "RD buff should be equal to the WR buff");
262 	}
263 
264 	err = zms_mount(&fixture->fs);
265 	zassert_true(err == 0, "zms_mount call failure: %d", err);
266 
267 	for (int id = 0; id < max_id; id++) {
268 		len = zms_read(&fixture->fs, id, rd_buf, sizeof(buf));
269 		zassert_true(len == sizeof(rd_buf), "zms_read unexpected failure: %d", len);
270 
271 		for (int i = 0; i < sizeof(rd_buf); i++) {
272 			rd_buf[i] = rd_buf[i] % max_id;
273 			buf[i] = id;
274 		}
275 		zassert_mem_equal(buf, rd_buf, sizeof(rd_buf),
276 				  "RD buff should be equal to the WR buff");
277 	}
278 }
279 
write_content(uint32_t max_id,uint32_t begin,uint32_t end,struct zms_fs * fs)280 static void write_content(uint32_t max_id, uint32_t begin, uint32_t end, struct zms_fs *fs)
281 {
282 	uint8_t buf[32];
283 	ssize_t len;
284 
285 	for (int i = begin; i < end; i++) {
286 		uint8_t id = (i % max_id);
287 		uint8_t id_data = id + max_id * (i / max_id);
288 
289 		memset(buf, id_data, sizeof(buf));
290 
291 		len = zms_write(fs, id, buf, sizeof(buf));
292 		zassert_true(len == sizeof(buf), "zms_write failed: %d", len);
293 	}
294 }
295 
check_content(uint32_t max_id,struct zms_fs * fs)296 static void check_content(uint32_t max_id, struct zms_fs *fs)
297 {
298 	uint8_t rd_buf[32];
299 	uint8_t buf[32];
300 	ssize_t len;
301 
302 	for (int id = 0; id < max_id; id++) {
303 		len = zms_read(fs, id, rd_buf, sizeof(buf));
304 		zassert_true(len == sizeof(rd_buf), "zms_read unexpected failure: %d", len);
305 
306 		for (int i = 0; i < ARRAY_SIZE(rd_buf); i++) {
307 			rd_buf[i] = rd_buf[i] % max_id;
308 			buf[i] = id;
309 		}
310 		zassert_mem_equal(buf, rd_buf, sizeof(rd_buf),
311 				  "RD buff should be equal to the WR buff");
312 	}
313 }
314 
315 /**
316  * Full round of GC over 3 sectors
317  */
ZTEST_F(zms,test_zms_gc_3sectors)318 ZTEST_F(zms, test_zms_gc_3sectors)
319 {
320 	int err;
321 	const uint16_t max_id = 10;
322 	/* 41st write will trigger 1st GC. */
323 	const uint16_t max_writes = 41;
324 	/* 61st write will trigger 2nd GC. */
325 	const uint16_t max_writes_2 = 41 + 20;
326 	/* 81st write will trigger 3rd GC. */
327 	const uint16_t max_writes_3 = 41 + 20 + 20;
328 	/* 101st write will trigger 4th GC. */
329 	const uint16_t max_writes_4 = 41 + 20 + 20 + 20;
330 
331 	fixture->fs.sector_count = 3;
332 
333 	err = zms_mount(&fixture->fs);
334 	zassert_true(err == 0, "zms_mount call failure: %d", err);
335 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0, "unexpected write sector");
336 
337 	/* Trigger 1st GC */
338 	write_content(max_id, 0, max_writes, &fixture->fs);
339 
340 	/* sector sequence: empty,closed, write */
341 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2, "unexpected write sector");
342 	check_content(max_id, &fixture->fs);
343 
344 	err = zms_mount(&fixture->fs);
345 	zassert_true(err == 0, "zms_mount call failure: %d", err);
346 
347 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2, "unexpected write sector");
348 	check_content(max_id, &fixture->fs);
349 
350 	/* Trigger 2nd GC */
351 	write_content(max_id, max_writes, max_writes_2, &fixture->fs);
352 
353 	/* sector sequence: write, empty, closed */
354 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0, "unexpected write sector");
355 	check_content(max_id, &fixture->fs);
356 
357 	err = zms_mount(&fixture->fs);
358 	zassert_true(err == 0, "zms_mount call failure: %d", err);
359 
360 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0, "unexpected write sector");
361 	check_content(max_id, &fixture->fs);
362 
363 	/* Trigger 3rd GC */
364 	write_content(max_id, max_writes_2, max_writes_3, &fixture->fs);
365 
366 	/* sector sequence: closed, write, empty */
367 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 1, "unexpected write sector");
368 	check_content(max_id, &fixture->fs);
369 
370 	err = zms_mount(&fixture->fs);
371 	zassert_true(err == 0, "zms_mount call failure: %d", err);
372 
373 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 1, "unexpected write sector");
374 	check_content(max_id, &fixture->fs);
375 
376 	/* Trigger 4th GC */
377 	write_content(max_id, max_writes_3, max_writes_4, &fixture->fs);
378 
379 	/* sector sequence: empty,closed, write */
380 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2, "unexpected write sector");
381 	check_content(max_id, &fixture->fs);
382 
383 	err = zms_mount(&fixture->fs);
384 	zassert_true(err == 0, "zms_mount call failure: %d", err);
385 
386 	zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 2, "unexpected write sector");
387 	check_content(max_id, &fixture->fs);
388 }
389 
flash_sim_max_len_find(struct stats_hdr * hdr,void * arg,const char * name,uint16_t off)390 static int flash_sim_max_len_find(struct stats_hdr *hdr, void *arg, const char *name, uint16_t off)
391 {
392 	if (!strcmp(name, "max_len")) {
393 		uint32_t **max_len = (uint32_t **)arg;
394 		*max_len = (uint32_t *)((uint8_t *)hdr + off);
395 	}
396 
397 	return 0;
398 }
399 
ZTEST_F(zms,test_zms_corrupted_sector_close_operation)400 ZTEST_F(zms, test_zms_corrupted_sector_close_operation)
401 {
402 	int err;
403 	int len;
404 	uint8_t buf[32];
405 	uint32_t *flash_write_stat;
406 	uint32_t *flash_max_write_calls;
407 	uint32_t *flash_max_len;
408 	const uint16_t max_id = 10;
409 	/* 21st write will trigger GC. */
410 	const uint16_t max_writes = 21;
411 
412 	/* Get the address of simulator parameters. */
413 	stats_walk(fixture->sim_thresholds, flash_sim_max_write_calls_find, &flash_max_write_calls);
414 	stats_walk(fixture->sim_thresholds, flash_sim_max_len_find, &flash_max_len);
415 	stats_walk(fixture->sim_stats, flash_sim_write_calls_find, &flash_write_stat);
416 
417 	err = zms_mount(&fixture->fs);
418 	zassert_true(err == 0, "zms_mount call failure: %d", err);
419 
420 	for (int i = 0; i < max_writes; i++) {
421 		uint8_t id = (i % max_id);
422 		uint8_t id_data = id + max_id * (i / max_id);
423 
424 		memset(buf, id_data, sizeof(buf));
425 
426 		if (i == max_writes - 1) {
427 			/* Reset stats. */
428 			*flash_write_stat = 0;
429 
430 			/* Block write calls and simulate power down during
431 			 * sector closing operation, so only a part of a ZMS
432 			 * closing ate will be written.
433 			 */
434 			*flash_max_write_calls = 1;
435 			*flash_max_len = 4;
436 		}
437 		len = zms_write(&fixture->fs, id, buf, sizeof(buf));
438 		zassert_true(len == sizeof(buf), "zms_write failed: %d", len);
439 	}
440 
441 	/* Make the flash simulator functional again. */
442 	*flash_max_write_calls = 0;
443 	*flash_max_len = 0;
444 
445 	err = zms_mount(&fixture->fs);
446 	zassert_true(err == 0, "zms_mount call failure: %d", err);
447 
448 	check_content(max_id, &fixture->fs);
449 
450 	/* Ensure that the ZMS is able to store new content. */
451 	execute_long_pattern_write(max_id, &fixture->fs);
452 }
453 #endif /* CONFIG_TEST_ZMS_SIMULATOR */
454 
455 /**
456  * @brief Test case when storage become full, so only deletion is possible.
457  */
ZTEST_F(zms,test_zms_full_sector)458 ZTEST_F(zms, test_zms_full_sector)
459 {
460 	int err;
461 	ssize_t len;
462 	uint32_t filling_id = 0;
463 	uint32_t data_read;
464 
465 	fixture->fs.sector_count = 3;
466 
467 	err = zms_mount(&fixture->fs);
468 	zassert_true(err == 0, "zms_mount call failure: %d", err);
469 
470 	while (1) {
471 		len = zms_write(&fixture->fs, filling_id, &filling_id, sizeof(filling_id));
472 		if (len == -ENOSPC) {
473 			break;
474 		}
475 		zassert_true(len == sizeof(filling_id), "zms_write failed: %d", len);
476 		filling_id++;
477 	}
478 
479 	/* check whether can delete whatever from full storage */
480 	err = zms_delete(&fixture->fs, 1);
481 	zassert_true(err == 0, "zms_delete call failure: %d", err);
482 
483 	/* the last sector is full now, test re-initialization */
484 	err = zms_mount(&fixture->fs);
485 	zassert_true(err == 0, "zms_mount call failure: %d", err);
486 
487 	len = zms_write(&fixture->fs, filling_id, &filling_id, sizeof(filling_id));
488 	zassert_true(len == sizeof(filling_id), "zms_write failed: %d", len);
489 
490 	/* coherence check on ZMS content */
491 	for (int i = 0; i <= filling_id; i++) {
492 		len = zms_read(&fixture->fs, i, &data_read, sizeof(data_read));
493 		if (i == 1) {
494 			zassert_true(len == -ENOENT, "zms_read shouldn't found the entry: %d", len);
495 		} else {
496 			zassert_true(len == sizeof(data_read),
497 				     "zms_read #%d failed: len is %zd instead of %zu", i, len,
498 				     sizeof(data_read));
499 			zassert_equal(data_read, i, "read unexpected data: %d instead of %d",
500 				      data_read, i);
501 		}
502 	}
503 }
504 
ZTEST_F(zms,test_delete)505 ZTEST_F(zms, test_delete)
506 {
507 	int err;
508 	ssize_t len;
509 	uint32_t filling_id;
510 	uint32_t data_read;
511 	uint32_t ate_wra;
512 	uint32_t data_wra;
513 
514 	fixture->fs.sector_count = 3;
515 
516 	err = zms_mount(&fixture->fs);
517 	zassert_true(err == 0, "zms_mount call failure: %d", err);
518 
519 	for (filling_id = 0; filling_id < 10; filling_id++) {
520 		len = zms_write(&fixture->fs, filling_id, &filling_id, sizeof(filling_id));
521 
522 		zassert_true(len == sizeof(filling_id), "zms_write failed: %d", len);
523 
524 		if (filling_id != 0) {
525 			continue;
526 		}
527 
528 		/* delete the first entry while it is the most recent one */
529 		err = zms_delete(&fixture->fs, filling_id);
530 		zassert_true(err == 0, "zms_delete call failure: %d", err);
531 
532 		len = zms_read(&fixture->fs, filling_id, &data_read, sizeof(data_read));
533 		zassert_true(len == -ENOENT, "zms_read shouldn't found the entry: %d", len);
534 	}
535 
536 	/* delete existing entry */
537 	err = zms_delete(&fixture->fs, 1);
538 	zassert_true(err == 0, "zms_delete call failure: %d", err);
539 
540 	len = zms_read(&fixture->fs, 1, &data_read, sizeof(data_read));
541 	zassert_true(len == -ENOENT, "zms_read shouldn't found the entry: %d", len);
542 
543 	ate_wra = fixture->fs.ate_wra;
544 	data_wra = fixture->fs.data_wra;
545 
546 #ifdef CONFIG_ZMS_NO_DOUBLE_WRITE
547 	/* delete already deleted entry */
548 	err = zms_delete(&fixture->fs, 1);
549 	zassert_true(err == 0, "zms_delete call failure: %d", err);
550 	zassert_true(ate_wra == fixture->fs.ate_wra && data_wra == fixture->fs.data_wra,
551 		     "delete already deleted entry should not make"
552 		     " any footprint in the storage");
553 
554 	/* delete nonexisting entry */
555 	err = zms_delete(&fixture->fs, filling_id);
556 	zassert_true(err == 0, "zms_delete call failure: %d", err);
557 	zassert_true(ate_wra == fixture->fs.ate_wra && data_wra == fixture->fs.data_wra,
558 		     "delete nonexistent entry should not make"
559 		     " any footprint in the storage");
560 #endif
561 }
562 
563 #ifdef CONFIG_TEST_ZMS_SIMULATOR
564 /*
565  * Test that garbage-collection can recover all ate's even when the last ate,
566  * ie close_ate, is corrupt. In this test the close_ate is set to point to the
567  * last ate at -5. A valid ate is however present at -6. Since the close_ate
568  * has an invalid crc8, the offset should not be used and a recover of the
569  * last ate should be done instead.
570  */
ZTEST_F(zms,test_zms_gc_corrupt_close_ate)571 ZTEST_F(zms, test_zms_gc_corrupt_close_ate)
572 {
573 	struct zms_ate ate;
574 	struct zms_ate close_ate;
575 	struct zms_ate empty_ate;
576 	uint32_t data;
577 	ssize_t len;
578 	int err;
579 
580 	Z_TEST_SKIP_IFNDEF(CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES);
581 	memset(&close_ate, 0xff, sizeof(struct zms_ate));
582 	close_ate.id = ZMS_HEAD_ID;
583 	close_ate.offset = fixture->fs.sector_size - sizeof(struct zms_ate) * 5;
584 	close_ate.len = 0;
585 	close_ate.cycle_cnt = 1;
586 	close_ate.crc8 = 0xff; /* Incorrect crc8 */
587 
588 	memset(&empty_ate, 0, sizeof(struct zms_ate));
589 	empty_ate.id = ZMS_HEAD_ID;
590 	empty_ate.len = 0xffff;
591 	empty_ate.metadata = FIELD_PREP(ZMS_VERSION_MASK, ZMS_DEFAULT_VERSION) |
592 			     FIELD_PREP(ZMS_MAGIC_NUMBER_MASK, ZMS_MAGIC_NUMBER) |
593 			     FIELD_PREP(ZMS_ATE_FORMAT_MASK, ZMS_DEFAULT_ATE_FORMAT);
594 	empty_ate.cycle_cnt = 1;
595 	empty_ate.crc8 =
596 		crc8_ccitt(0xff, (uint8_t *)&empty_ate + SIZEOF_FIELD(struct zms_ate, crc8),
597 			   sizeof(struct zms_ate) - SIZEOF_FIELD(struct zms_ate, crc8));
598 
599 	memset(&ate, 0, sizeof(struct zms_ate));
600 	ate.id = 0x1;
601 	ate.len = sizeof(data);
602 	ate.cycle_cnt = 1;
603 	data = 0xaa55aa55;
604 	memcpy(&ate.data, &data, sizeof(data));
605 	ate.crc8 = crc8_ccitt(0xff, (uint8_t *)&ate + SIZEOF_FIELD(struct zms_ate, crc8),
606 			      sizeof(struct zms_ate) - SIZEOF_FIELD(struct zms_ate, crc8));
607 
608 	/* Add empty ATE */
609 	err = flash_write(fixture->fs.flash_device,
610 			  fixture->fs.offset + fixture->fs.sector_size - sizeof(struct zms_ate),
611 			  &empty_ate, sizeof(empty_ate));
612 	zassert_true(err == 0, "flash_write failed: %d", err);
613 
614 	/* Mark sector 0 as closed */
615 	err = flash_write(fixture->fs.flash_device,
616 			  fixture->fs.offset + fixture->fs.sector_size - 2 * sizeof(struct zms_ate),
617 			  &close_ate, sizeof(close_ate));
618 	zassert_true(err == 0, "flash_write failed: %d", err);
619 
620 	/* Write valid ate at -6 */
621 	err = flash_write(fixture->fs.flash_device,
622 			  fixture->fs.offset + fixture->fs.sector_size - 6 * sizeof(struct zms_ate),
623 			  &ate, sizeof(ate));
624 	zassert_true(err == 0, "flash_write failed: %d", err);
625 
626 	/* Mark sector 1 as closed */
627 	err = flash_write(fixture->fs.flash_device,
628 			  fixture->fs.offset + (2 * fixture->fs.sector_size) -
629 				  2 * sizeof(struct zms_ate),
630 			  &close_ate, sizeof(close_ate));
631 	zassert_true(err == 0, "flash_write failed: %d", err);
632 
633 	fixture->fs.sector_count = 3;
634 
635 	err = zms_mount(&fixture->fs);
636 	zassert_true(err == 0, "zms_mount call failure: %d", err);
637 
638 	data = 0;
639 	len = zms_read(&fixture->fs, 1, &data, sizeof(data));
640 	zassert_true(len == sizeof(data), "zms_read should have read %d bytes", sizeof(data));
641 	zassert_true(data == 0xaa55aa55, "unexpected value %d", data);
642 }
643 #endif /* CONFIG_TEST_ZMS_SIMULATOR */
644 
645 /*
646  * Test that garbage-collection correctly handles corrupt ate's.
647  */
ZTEST_F(zms,test_zms_gc_corrupt_ate)648 ZTEST_F(zms, test_zms_gc_corrupt_ate)
649 {
650 	struct zms_ate corrupt_ate;
651 	struct zms_ate close_ate;
652 	int err;
653 
654 	close_ate.id = ZMS_HEAD_ID;
655 	close_ate.offset = fixture->fs.sector_size / 2;
656 	close_ate.len = 0;
657 	close_ate.crc8 =
658 		crc8_ccitt(0xff, (uint8_t *)&close_ate + SIZEOF_FIELD(struct zms_ate, crc8),
659 			   sizeof(struct zms_ate) - SIZEOF_FIELD(struct zms_ate, crc8));
660 
661 	corrupt_ate.id = 0xdeadbeef;
662 	corrupt_ate.offset = 0;
663 	corrupt_ate.len = 20;
664 	corrupt_ate.crc8 = 0xff; /* Incorrect crc8 */
665 
666 	/* Mark sector 0 as closed */
667 	err = flash_write(fixture->fs.flash_device,
668 			  fixture->fs.offset + fixture->fs.sector_size - 2 * sizeof(struct zms_ate),
669 			  &close_ate, sizeof(close_ate));
670 	zassert_true(err == 0, "flash_write failed: %d", err);
671 
672 	/* Write a corrupt ate */
673 	err = flash_write(fixture->fs.flash_device,
674 			  fixture->fs.offset + (fixture->fs.sector_size / 2), &corrupt_ate,
675 			  sizeof(corrupt_ate));
676 	zassert_true(err == 0, "flash_write failed: %d", err);
677 
678 	/* Mark sector 1 as closed */
679 	err = flash_write(fixture->fs.flash_device,
680 			  fixture->fs.offset + (2 * fixture->fs.sector_size) -
681 				  2 * sizeof(struct zms_ate),
682 			  &close_ate, sizeof(close_ate));
683 	zassert_true(err == 0, "flash_write failed: %d", err);
684 
685 	fixture->fs.sector_count = 3;
686 
687 	err = zms_mount(&fixture->fs);
688 	zassert_true(err == 0, "zms_mount call failure: %d", err);
689 }
690 
691 #ifdef CONFIG_ZMS_LOOKUP_CACHE
num_matching_cache_entries(uint64_t addr,bool compare_sector_only,struct zms_fs * fs)692 static size_t num_matching_cache_entries(uint64_t addr, bool compare_sector_only, struct zms_fs *fs)
693 {
694 	size_t num = 0;
695 	uint64_t mask = compare_sector_only ? ADDR_SECT_MASK : UINT64_MAX;
696 
697 	for (int i = 0; i < CONFIG_ZMS_LOOKUP_CACHE_SIZE; i++) {
698 		if ((fs->lookup_cache[i] & mask) == addr) {
699 			num++;
700 		}
701 	}
702 
703 	return num;
704 }
705 
num_occupied_cache_entries(struct zms_fs * fs)706 static size_t num_occupied_cache_entries(struct zms_fs *fs)
707 {
708 	return CONFIG_ZMS_LOOKUP_CACHE_SIZE -
709 	       num_matching_cache_entries(ZMS_LOOKUP_CACHE_NO_ADDR, false, fs);
710 }
711 #endif
712 
713 /*
714  * Test that ZMS lookup cache is properly rebuilt on zms_mount(), or initialized
715  * to ZMS_LOOKUP_CACHE_NO_ADDR if the store is empty.
716  */
ZTEST_F(zms,test_zms_cache_init)717 ZTEST_F(zms, test_zms_cache_init)
718 {
719 #ifdef CONFIG_ZMS_LOOKUP_CACHE
720 	int err;
721 	size_t num;
722 	uint64_t ate_addr;
723 	uint8_t data = 0;
724 
725 	/* Test cache initialization when the store is empty */
726 
727 	fixture->fs.sector_count = 3;
728 	err = zms_mount(&fixture->fs);
729 	zassert_true(err == 0, "zms_mount call failure: %d", err);
730 
731 	num = num_occupied_cache_entries(&fixture->fs);
732 	zassert_equal(num, 0, "uninitialized cache");
733 
734 	/* Test cache update after zms_write() */
735 
736 	ate_addr = fixture->fs.ate_wra;
737 	err = zms_write(&fixture->fs, 1, &data, sizeof(data));
738 	zassert_equal(err, sizeof(data), "zms_write call failure: %d", err);
739 
740 	num = num_occupied_cache_entries(&fixture->fs);
741 	zassert_equal(num, 1, "cache not updated after write");
742 
743 	num = num_matching_cache_entries(ate_addr, false, &fixture->fs);
744 	zassert_equal(num, 1, "invalid cache entry after write");
745 
746 	/* Test cache initialization when the store is non-empty */
747 
748 	memset(fixture->fs.lookup_cache, 0xAA, sizeof(fixture->fs.lookup_cache));
749 	err = zms_mount(&fixture->fs);
750 	zassert_true(err == 0, "zms_mount call failure: %d", err);
751 
752 	num = num_occupied_cache_entries(&fixture->fs);
753 	zassert_equal(num, 1, "uninitialized cache after restart");
754 
755 	num = num_matching_cache_entries(ate_addr, false, &fixture->fs);
756 	zassert_equal(num, 1, "invalid cache entry after restart");
757 #else
758 	ztest_test_skip();
759 #endif
760 }
761 
762 /*
763  * Test that even after writing more ZMS IDs than the number of ZMS lookup cache
764  * entries they all can be read and deleted correctly.
765  */
ZTEST_F(zms,test_zms_cache_collision)766 ZTEST_F(zms, test_zms_cache_collision)
767 {
768 #ifdef CONFIG_ZMS_LOOKUP_CACHE
769 	int err;
770 	uint16_t data;
771 
772 	fixture->fs.sector_count = 4;
773 	err = zms_mount(&fixture->fs);
774 	zassert_true(err == 0, "zms_mount call failure: %d", err);
775 
776 	for (int id = 0; id < CONFIG_ZMS_LOOKUP_CACHE_SIZE + 1; id++) {
777 		data = id;
778 		err = zms_write(&fixture->fs, id, &data, sizeof(data));
779 		zassert_equal(err, sizeof(data), "zms_write call failure: %d", err);
780 	}
781 
782 	for (int id = 0; id < CONFIG_ZMS_LOOKUP_CACHE_SIZE + 1; id++) {
783 		err = zms_read(&fixture->fs, id, &data, sizeof(data));
784 		zassert_equal(err, sizeof(data), "zms_read call failure: %d", err);
785 		zassert_equal(data, id, "incorrect data read");
786 	}
787 
788 	for (int id = 0; id < CONFIG_ZMS_LOOKUP_CACHE_SIZE + 1; id++) {
789 		err = zms_delete(&fixture->fs, id);
790 		zassert_equal(0, err, "zms_delete failed: %d", err);
791 	}
792 
793 	for (int id = 0; id < CONFIG_ZMS_LOOKUP_CACHE_SIZE + 1; id++) {
794 		err = zms_read(&fixture->fs, id, &data, sizeof(data));
795 		zassert_equal(-ENOENT, err, "zms_delete failed: %d", err);
796 	}
797 #else
798 	ztest_test_skip();
799 #endif
800 }
801 
802 /*
803  * Test that ZMS lookup cache does not contain any address from gc-ed sector
804  */
ZTEST_F(zms,test_zms_cache_gc)805 ZTEST_F(zms, test_zms_cache_gc)
806 {
807 #ifdef CONFIG_ZMS_LOOKUP_CACHE
808 	int err;
809 	size_t num;
810 	uint16_t data = 0;
811 
812 	fixture->fs.sector_count = 3;
813 	err = zms_mount(&fixture->fs);
814 	zassert_true(err == 0, "zms_mount call failure: %d", err);
815 
816 	/* Fill the first sector with writes of ID 1 */
817 
818 	while (fixture->fs.data_wra + sizeof(data) + sizeof(struct zms_ate) <=
819 	       fixture->fs.ate_wra) {
820 		++data;
821 		err = zms_write(&fixture->fs, 1, &data, sizeof(data));
822 		zassert_equal(err, sizeof(data), "zms_write call failure: %d", err);
823 	}
824 
825 	/* Verify that cache contains a single entry for sector 0 */
826 
827 	num = num_matching_cache_entries(0ULL << ADDR_SECT_SHIFT, true, &fixture->fs);
828 	zassert_equal(num, 1, "invalid cache content after filling sector 0");
829 
830 	/* Fill the second sector with writes of ID 2 */
831 
832 	while ((fixture->fs.ate_wra >> ADDR_SECT_SHIFT) != 2) {
833 		++data;
834 		err = zms_write(&fixture->fs, 2, &data, sizeof(data));
835 		zassert_equal(err, sizeof(data), "zms_write call failure: %d", err);
836 	}
837 
838 	/*
839 	 * At this point sector 0 should have been gc-ed. Verify that action is
840 	 * reflected by the cache content.
841 	 */
842 
843 	num = num_matching_cache_entries(0ULL << ADDR_SECT_SHIFT, true, &fixture->fs);
844 	zassert_equal(num, 0, "not invalidated cache entries aftetr gc");
845 
846 	num = num_matching_cache_entries(2ULL << ADDR_SECT_SHIFT, true, &fixture->fs);
847 	zassert_equal(num, 2, "invalid cache content after gc");
848 #else
849 	ztest_test_skip();
850 #endif
851 }
852 
853 /*
854  * Test ZMS lookup cache hash quality.
855  */
ZTEST_F(zms,test_zms_cache_hash_quality)856 ZTEST_F(zms, test_zms_cache_hash_quality)
857 {
858 #ifdef CONFIG_ZMS_LOOKUP_CACHE
859 	const size_t MIN_CACHE_OCCUPANCY = CONFIG_ZMS_LOOKUP_CACHE_SIZE * 6 / 10;
860 	int err;
861 	size_t num;
862 	uint32_t id;
863 	uint16_t data;
864 
865 	err = zms_mount(&fixture->fs);
866 	zassert_true(err == 0, "zms_mount call failure: %d", err);
867 
868 	/* Write ZMS IDs from 0 to CONFIG_ZMS_LOOKUP_CACHE_SIZE - 1 */
869 
870 	for (int i = 0; i < CONFIG_ZMS_LOOKUP_CACHE_SIZE; i++) {
871 		id = i;
872 		data = 0;
873 
874 		err = zms_write(&fixture->fs, id, &data, sizeof(data));
875 		zassert_equal(err, sizeof(data), "zms_write call failure: %d", err);
876 	}
877 
878 	/* Verify that at least 60% cache entries are occupied */
879 
880 	num = num_occupied_cache_entries(&fixture->fs);
881 	TC_PRINT("Cache occupancy: %u\n", (unsigned int)num);
882 	zassert_between_inclusive(num, MIN_CACHE_OCCUPANCY, CONFIG_ZMS_LOOKUP_CACHE_SIZE,
883 				  "too low cache occupancy - poor hash quality");
884 
885 	err = zms_clear(&fixture->fs);
886 	zassert_true(err == 0, "zms_clear call failure: %d", err);
887 
888 	err = zms_mount(&fixture->fs);
889 	zassert_true(err == 0, "zms_mount call failure: %d", err);
890 
891 	/* Write CONFIG_ZMS_LOOKUP_CACHE_SIZE ZMS IDs that form the following series: 0, 4, 8... */
892 
893 	for (int i = 0; i < CONFIG_ZMS_LOOKUP_CACHE_SIZE; i++) {
894 		id = i * 4;
895 		data = 0;
896 
897 		err = zms_write(&fixture->fs, id, &data, sizeof(data));
898 		zassert_equal(err, sizeof(data), "zms_write call failure: %d", err);
899 	}
900 
901 	/* Verify that at least 60% cache entries are occupied */
902 
903 	num = num_occupied_cache_entries(&fixture->fs);
904 	TC_PRINT("Cache occupancy: %u\n", (unsigned int)num);
905 	zassert_between_inclusive(num, MIN_CACHE_OCCUPANCY, CONFIG_ZMS_LOOKUP_CACHE_SIZE,
906 				  "too low cache occupancy - poor hash quality");
907 #else
908 	ztest_test_skip();
909 #endif
910 }
911 
ZTEST_F(zms,test_zms_input_validation)912 ZTEST_F(zms, test_zms_input_validation)
913 {
914 	int err;
915 
916 	err = zms_mount(NULL);
917 	zassert_true(err == -EINVAL, "zms_mount call with NULL fs failure: %d", err);
918 
919 	err = zms_clear(NULL);
920 	zassert_true(err == -EINVAL, "zms_clear call with NULL fs failure: %d", err);
921 	err = zms_clear(&fixture->fs);
922 	zassert_true(err == -EACCES, "zms_clear call before mount fs failure: %d", err);
923 
924 	err = zms_calc_free_space(NULL);
925 	zassert_true(err == -EINVAL, "zms_calc_free_space call with NULL fs failure: %d", err);
926 	err = zms_calc_free_space(&fixture->fs);
927 	zassert_true(err == -EACCES, "zms_calc_free_space call before mount fs failure: %d", err);
928 
929 	err = zms_active_sector_free_space(NULL);
930 	zassert_true(err == -EINVAL, "zms_active_sector_free_space call with NULL fs failure: %d",
931 		     err);
932 	err = zms_active_sector_free_space(&fixture->fs);
933 	zassert_true(err == -EACCES, "zms_calc_free_space call before mount fs failure: %d", err);
934 
935 	err = zms_sector_use_next(NULL);
936 	zassert_true(err == -EINVAL, "zms_sector_use_next call with NULL fs failure: %d", err);
937 	err = zms_sector_use_next(&fixture->fs);
938 	zassert_true(err == -EACCES, "zms_sector_use_next call before mount fs failure: %d", err);
939 
940 	/* Read */
941 	err = zms_read(NULL, 0, NULL, 0);
942 	zassert_true(err == -EINVAL, "zms_read call with NULL fs failure: %d", err);
943 	err = zms_read(&fixture->fs, 0, NULL, 0);
944 	zassert_true(err == -EACCES, "zms_read call before mount fs failure: %d", err);
945 
946 	/* zms_read() and zms_get_data_length() are currently wrappers around zms_read_hist() but
947 	 * add test here in case that is ever changed. Same is true for zms_delete() and zms_write()
948 	 */
949 	err = zms_read_hist(NULL, 0, NULL, 0, 0);
950 	zassert_true(err == -EINVAL, "zms_read_hist call with NULL fs failure: %d", err);
951 	err = zms_read_hist(&fixture->fs, 0, NULL, 0, 0);
952 	zassert_true(err == -EACCES, "zms_read_hist call before mount fs failure: %d", err);
953 	err = zms_get_data_length(NULL, 0);
954 	zassert_true(err == -EINVAL, "zms_get_data_length call with NULL fs failure: %d", err);
955 	err = zms_get_data_length(&fixture->fs, 0);
956 	zassert_true(err == -EACCES, "zms_get_data_length call before mount fs failure: %d", err);
957 
958 	/* Write */
959 	err = zms_write(NULL, 0, NULL, 0);
960 	zassert_true(err == -EINVAL, "zms_write call with NULL fs failure: %d", err);
961 	err = zms_write(&fixture->fs, 0, NULL, 0);
962 	zassert_true(err == -EACCES, "zms_write call before mount fs failure: %d", err);
963 
964 	/* Delete */
965 	err = zms_delete(NULL, 0);
966 	zassert_true(err == -EINVAL, "zms_delete call with NULL fs failure: %d", err);
967 	err = zms_delete(&fixture->fs, 0);
968 	zassert_true(err == -EACCES, "zms_delete call before mount fs failure: %d", err);
969 }
970 
971 /*
972  * Test 64 bit ZMS ID support.
973  */
ZTEST_F(zms,test_zms_id_64bit)974 ZTEST_F(zms, test_zms_id_64bit)
975 {
976 	int err;
977 	ssize_t len;
978 	uint64_t data_wra;
979 	uint64_t filling_id_1 = 0xdeadbeefULL;
980 	uint64_t filling_id_2 = 0xdefacedbULL;
981 	uint64_t data_1;
982 	uint32_t data_2;
983 
984 	Z_TEST_SKIP_IFNDEF(CONFIG_ZMS_ID_64BIT);
985 
986 	err = zms_mount(&fixture->fs);
987 	zassert_true(err == 0, "zms_mount call failure: %d", err);
988 
989 	/* Fill the first sector with writes of different IDs */
990 
991 	while (fixture->fs.data_wra + sizeof(data_1) + sizeof(struct zms_ate) <=
992 	       fixture->fs.ate_wra) {
993 		data_1 = filling_id_1;
994 		len = zms_write(&fixture->fs, (zms_id_t)filling_id_1, &data_1, sizeof(data_1));
995 		zassert_true(len == sizeof(data_1), "zms_write failed: %d", len);
996 
997 		/* Choose the next ID so that its lower 32 bits stay invariant.
998 		 * The purpose is to test that ZMS doesn't mistakenly cast the
999 		 * 64 bit ID to a 32 bit one somewhere.
1000 		 */
1001 		filling_id_1 += BIT64(32);
1002 	}
1003 
1004 	/* Fill the second sector similarly, except with small data in ATE */
1005 
1006 	err = zms_sector_use_next(&fixture->fs);
1007 	zassert_true(err == 0, "zms_sector_use_next call failure: %d", err);
1008 
1009 	data_wra = fixture->fs.data_wra;
1010 	while (data_wra + sizeof(data_2) + sizeof(struct zms_ate) <= fixture->fs.ate_wra) {
1011 		/* Again, the lower 32 bits are invariant, so use the upper bits
1012 		 * to get unique data contents.
1013 		 */
1014 		data_2 = (uint32_t)(filling_id_2 >> 32);
1015 		len = zms_write(&fixture->fs, (zms_id_t)filling_id_2, &data_2, sizeof(data_2));
1016 		zassert_true(len == sizeof(data_2), "zms_write failed: %d", len);
1017 
1018 		/* Expect no data to be stored outside of the ATE */
1019 		zassert_equal(data_wra, fixture->fs.data_wra, "data_wra should not have changed");
1020 
1021 		filling_id_2 += BIT64(32);
1022 	}
1023 
1024 	/* Read back the written entries and check that they're all unique */
1025 
1026 	for (uint64_t id = 0xdeadbeefULL; id < filling_id_1; id += BIT64(32)) {
1027 		len = zms_read_hist(&fixture->fs, (zms_id_t)id, &data_1, sizeof(data_1), 0);
1028 		zassert_true(len == sizeof(data_1), "zms_read_hist unexpected failure: %d", len);
1029 		zassert_equal(id, data_1, "read unexpected data for id %llx: %llx", id, data_1);
1030 
1031 		len = zms_read_hist(&fixture->fs, (zms_id_t)id, &data_1, sizeof(data_1), 1);
1032 		zassert_true(len == -ENOENT, "zms_read_hist unexpected failure: %d", len);
1033 	}
1034 
1035 	for (uint64_t id = 0xdefacedbULL; id < filling_id_2; id += BIT64(32)) {
1036 		len = zms_read_hist(&fixture->fs, (zms_id_t)id, &data_2, sizeof(data_2), 0);
1037 		zassert_true(len == sizeof(data_2), "zms_read_hist unexpected failure: %d", len);
1038 		zassert_equal((uint32_t)(id >> 32), data_2, "read unexpected data for id %llx: %x",
1039 			      id, data_2);
1040 
1041 		len = zms_read_hist(&fixture->fs, (zms_id_t)id, &data_2, sizeof(data_2), 1);
1042 		zassert_true(len == -ENOENT, "zms_read_hist unexpected failure: %d", len);
1043 	}
1044 }
1045 
1046 /*
1047  * Test zms_active_sector_free_space() and zms_calc_free_space().
1048  */
ZTEST_F(zms,test_zms_free_space)1049 ZTEST_F(zms, test_zms_free_space)
1050 {
1051 	const size_t max_space_in_sector = fixture->fs.sector_size - sizeof(struct zms_ate) * 5;
1052 	size_t free_space_sector;
1053 	size_t free_space_total;
1054 	size_t write_len;
1055 	ssize_t len;
1056 	zms_id_t id;
1057 	int err;
1058 	char write_buf[max_space_in_sector + 1];
1059 
1060 	fixture->fs.sector_count = 2;
1061 
1062 	err = zms_mount(&fixture->fs);
1063 	zassert_true(err == 0, "zms_mount call failure: %d", err);
1064 
1065 	/* Set and verify the initial values of free_space_sector and free_space_total */
1066 
1067 	free_space_sector = max_space_in_sector;
1068 	zassert_equal(free_space_sector, zms_active_sector_free_space(&fixture->fs),
1069 		      "unexpected free space in empty sector");
1070 	free_space_total = max_space_in_sector;
1071 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1072 		      "unexpected free space in empty filesystem");
1073 
1074 	id = 0;
1075 
1076 	len = zms_write(&fixture->fs, id, write_buf, sizeof(write_buf));
1077 	zassert_true(len == -EINVAL, "zms_write unexpected failure: %d", len);
1078 
1079 	do {
1080 		/* fill the filesystem with a single entry */
1081 		write_len = free_space_total;
1082 		len = zms_write(&fixture->fs, id, write_buf, write_len);
1083 		zassert_true(len == write_len, "zms_write failed: %d", len);
1084 		zassert_equal(0, zms_active_sector_free_space(&fixture->fs),
1085 			      "expected sector to appear full");
1086 		zassert_equal(0, zms_calc_free_space(&fixture->fs),
1087 			      "expected filesystem to appear full");
1088 
1089 		/* no space in filesystem -> next write must fail */
1090 		len = zms_write(&fixture->fs, id + 1, write_buf, 1);
1091 		zassert_true(len == -ENOSPC, "zms_write unexpected failure: %d", len);
1092 
1093 		/* drop the filler entry; expect delete ATE to fit in the active sector */
1094 		err = zms_delete(&fixture->fs, id);
1095 		zassert_true(err == 0, "zms_delete call failure: %d", err);
1096 		zassert_equal(0, zms_active_sector_free_space(&fixture->fs),
1097 			      "expected sector to appear full");
1098 		zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1099 			      "unexpected total free space");
1100 
1101 		/* Check cases where the active sector is filled in such a way
1102 		 * that there is only room for one ATE, and there is more space
1103 		 * for data to be stored within that ATE, than outside of it.
1104 		 * The calculated free space shall be ZMS_DATA_IN_ATE_SIZE.
1105 		 */
1106 		write_len -= sizeof(struct zms_ate);
1107 		while (write_len > ZMS_DATA_IN_ATE_SIZE) {
1108 			len = zms_write(&fixture->fs, id, write_buf, write_len);
1109 			zassert_true(len == write_len, "zms_write failed: %d", len);
1110 			zassert_equal(ZMS_DATA_IN_ATE_SIZE,
1111 				      zms_active_sector_free_space(&fixture->fs),
1112 				      "unexpected free space in active sector");
1113 			zassert_equal(ZMS_DATA_IN_ATE_SIZE, zms_calc_free_space(&fixture->fs),
1114 				      "unexpected total free space");
1115 
1116 			/* no space for data outside of ATE -> next write must fail */
1117 			len = zms_write(&fixture->fs, id + 1, write_buf, ZMS_DATA_IN_ATE_SIZE + 1);
1118 			zassert_true(len == -ENOSPC, "zms_write unexpected failure: %d", len);
1119 
1120 			/* add ATE with data inside it */
1121 			len = zms_write(&fixture->fs, id + 1, write_buf, ZMS_DATA_IN_ATE_SIZE);
1122 			zassert_true(len == ZMS_DATA_IN_ATE_SIZE, "zms_write failed: %d", len);
1123 			zassert_equal(0, zms_active_sector_free_space(&fixture->fs),
1124 				      "expected sector to appear full");
1125 			zassert_equal(0, zms_calc_free_space(&fixture->fs),
1126 				      "expected filesystem to appear full");
1127 
1128 			/* cleanup; expect delete ATE to fit in the active sector */
1129 			err = zms_delete(&fixture->fs, id + 1);
1130 			zassert_true(err == 0, "zms_delete call failure: %d", err);
1131 			zassert_equal(0, zms_active_sector_free_space(&fixture->fs),
1132 				      "expected sector to appear full");
1133 			zassert_equal(ZMS_DATA_IN_ATE_SIZE, zms_calc_free_space(&fixture->fs),
1134 				      "unexpected total free space");
1135 
1136 			err = zms_delete(&fixture->fs, id);
1137 			zassert_true(err == 0, "zms_delete call failure: %d", err);
1138 			zassert_equal(0, zms_active_sector_free_space(&fixture->fs),
1139 				      "expected sector to appear full");
1140 			zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1141 				      "unexpected total free space");
1142 
1143 			write_len -= fixture->fs.flash_parameters->write_block_size;
1144 
1145 			if (write_len <
1146 			    (free_space_total - sizeof(struct zms_ate) - ZMS_DATA_IN_ATE_SIZE)) {
1147 				break;
1148 			}
1149 		}
1150 
1151 		/* add small data ATE with unique ID; these will accumulate until the loop ends */
1152 		len = zms_write(&fixture->fs, id, write_buf, 1);
1153 		zassert_true(len == 1, "zms_write failed: %d", len);
1154 		id++;
1155 
1156 		free_space_sector -= sizeof(struct zms_ate);
1157 		zassert_equal(free_space_sector, zms_active_sector_free_space(&fixture->fs),
1158 			      "unexpected free space in active sector");
1159 		free_space_total = free_space_sector;
1160 		zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1161 			      "unexpected total free space");
1162 	} while (free_space_total > 0);
1163 
1164 	/* Filesystem is filled with small data ATEs, now delete them all */
1165 
1166 	for (zms_id_t delete_id = 0; delete_id < id; delete_id++) {
1167 		err = zms_delete(&fixture->fs, delete_id);
1168 		zassert_true(err == 0, "zms_delete call failure: %d", err);
1169 
1170 		free_space_total += sizeof(struct zms_ate);
1171 		zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1172 			      "unexpected total free space");
1173 
1174 		if (free_space_sector == 0) {
1175 			free_space_sector = free_space_total;
1176 			zassert_equal(0, zms_active_sector_free_space(&fixture->fs),
1177 				      "unexpected free space in active sector");
1178 		} else {
1179 			free_space_sector -= sizeof(struct zms_ate);
1180 			zassert_equal(free_space_sector, zms_active_sector_free_space(&fixture->fs),
1181 				      "unexpected free space in active sector");
1182 		}
1183 	}
1184 	zassert_equal(free_space_total, max_space_in_sector, "expected file system to be empty");
1185 
1186 	/* Trigger garbage-collection */
1187 
1188 	err = zms_sector_use_next(&fixture->fs);
1189 	zassert_true(err == 0, "zms_sector_use_next call failure: %d", err);
1190 
1191 	free_space_sector = max_space_in_sector;
1192 	zassert_equal(free_space_sector, zms_active_sector_free_space(&fixture->fs),
1193 		      "unexpected free space in empty sector");
1194 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1195 		      "total free space should not have changed");
1196 
1197 	/* Finally, fill the active sector with redundant entries */
1198 
1199 	write_len = 64;
1200 	len = zms_write(&fixture->fs, id, write_buf, write_len);
1201 	zassert_true(len == write_len, "zms_write failed: %d", len);
1202 
1203 	free_space_sector -= (write_len + sizeof(struct zms_ate));
1204 	zassert_equal(free_space_sector, zms_active_sector_free_space(&fixture->fs),
1205 		      "unexpected free space in active sector");
1206 	free_space_total -= (write_len + sizeof(struct zms_ate));
1207 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1208 		      "unexpected total free space");
1209 
1210 #ifndef CONFIG_ZMS_NO_DOUBLE_WRITE
1211 	while (free_space_sector >= (write_len + sizeof(struct zms_ate))) {
1212 		len = zms_write(&fixture->fs, id, write_buf, write_len);
1213 		zassert_true(len == write_len, "zms_write failed: %d", len);
1214 
1215 		free_space_sector -= (write_len + sizeof(struct zms_ate));
1216 		zassert_equal(free_space_sector, zms_active_sector_free_space(&fixture->fs),
1217 			      "unexpected free space in active sector");
1218 		zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1219 			      "total free space should not have changed");
1220 	}
1221 #else
1222 	/* With no double write, the above loop would never terminate */
1223 	len = zms_write(&fixture->fs, id, write_buf, write_len);
1224 	zassert_true(len == 0, "zms_write failed: %d", len);
1225 
1226 	zassert_equal(free_space_sector, zms_active_sector_free_space(&fixture->fs),
1227 		      "active sector free space should not have changed");
1228 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1229 		      "total free space should not have changed");
1230 #endif
1231 }
1232 
1233 /*
1234  * Test zms_calc_free_space() with more than 2 sectors.
1235  * This is to exercise its handling of closed sectors.
1236  */
ZTEST_F(zms,test_zms_free_space_5sectors)1237 ZTEST_F(zms, test_zms_free_space_5sectors)
1238 {
1239 	const size_t max_space_in_sector = fixture->fs.sector_size - sizeof(struct zms_ate) * 5;
1240 	size_t free_space_total;
1241 	int err;
1242 	char write_buf[max_space_in_sector];
1243 
1244 	fixture->fs.sector_count = 5;
1245 
1246 	err = zms_mount(&fixture->fs);
1247 	zassert_true(err == 0, "zms_mount call failure: %d", err);
1248 
1249 	free_space_total = max_space_in_sector * (fixture->fs.sector_count - 1);
1250 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1251 		      "unexpected free space in empty filesystem");
1252 
1253 	/* Sector 1: add 3 new ATEs */
1254 
1255 	zms_write(&fixture->fs, 0, write_buf, 100);
1256 	zms_write(&fixture->fs, 1, write_buf, 200);
1257 	zms_write(&fixture->fs, 2, write_buf, 300);
1258 
1259 	free_space_total -= (100 + 200 + 300 + 3 * sizeof(struct zms_ate));
1260 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1261 		      "unexpected total free space");
1262 
1263 	err = zms_sector_use_next(&fixture->fs);
1264 	zassert_true(err == 0, "zms_sector_use_next call failure: %d", err);
1265 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1266 		      "total free space should not have changed");
1267 
1268 	/* Sector 2: add 1 new ATE and update 1 existing ATE */
1269 
1270 	zms_write(&fixture->fs, 3, write_buf, 100);
1271 	zms_write(&fixture->fs, 1, write_buf, 800);
1272 
1273 	free_space_total -= (100 + (800 - 200) + sizeof(struct zms_ate));
1274 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1275 		      "unexpected total free space");
1276 
1277 	err = zms_sector_use_next(&fixture->fs);
1278 	zassert_true(err == 0, "zms_sector_use_next call failure: %d", err);
1279 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1280 		      "total free space should not have changed");
1281 
1282 	/* Sector 3: add 2 new ATEs */
1283 
1284 	zms_write(&fixture->fs, 4, write_buf, max_space_in_sector - sizeof(struct zms_ate));
1285 	zms_write(&fixture->fs, 5, write_buf, ZMS_DATA_IN_ATE_SIZE);
1286 
1287 	free_space_total -= max_space_in_sector;
1288 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1289 		      "unexpected total free space");
1290 
1291 	err = zms_sector_use_next(&fixture->fs);
1292 	zassert_true(err == 0, "zms_sector_use_next call failure: %d", err);
1293 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1294 		      "total free space should not have changed");
1295 
1296 	/* Sector 4: update 1 existing ATE */
1297 
1298 	zms_write(&fixture->fs, 4, write_buf, max_space_in_sector);
1299 
1300 	free_space_total -= sizeof(struct zms_ate);
1301 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1302 		      "unexpected total free space");
1303 
1304 	err = zms_sector_use_next(&fixture->fs);
1305 	zassert_true(err == 0, "zms_sector_use_next call failure: %d", err);
1306 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1307 		      "total free space should not have changed");
1308 
1309 	/* GC all sectors and verify relation with zms_active_sector_free_space() */
1310 
1311 	free_space_total = 0;
1312 	for (int i = 0; i < fixture->fs.sector_count - 1; i++) {
1313 		free_space_total += zms_active_sector_free_space(&fixture->fs);
1314 
1315 		err = zms_sector_use_next(&fixture->fs);
1316 		zassert_true(err == 0, "zms_sector_use_next call failure: %d", err);
1317 	}
1318 	zassert_equal(free_space_total, zms_calc_free_space(&fixture->fs),
1319 		      "total free space did not match sum of gc'd sectors");
1320 }
1321