1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <zephyr/types.h>
9 #include <stdbool.h>
10 #include <zephyr/ztest.h>
11 #include <zephyr/drivers/flash.h>
12 #include <zephyr/settings/settings.h>
13 
14 #include <zephyr/storage/stream_flash.h>
15 
16 #define BUF_LEN 512
17 #define MAX_PAGE_SIZE 0x1000 /* Max supported page size to run test on */
18 #define MAX_NUM_PAGES 4      /* Max number of pages used in these tests */
19 #define TESTBUF_SIZE (MAX_PAGE_SIZE * MAX_NUM_PAGES)
20 #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash)
21 #define FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE)
22 
23 /* so that we don't overwrite the application when running on hw */
24 #define FLASH_BASE (128*1024)
25 #define FLASH_AVAILABLE (FLASH_SIZE-FLASH_BASE)
26 
27 static const struct device *const fdev = DEVICE_DT_GET(DT_CHOSEN(zephyr_flash_controller));
28 static const struct flash_driver_api *api;
29 static const struct flash_pages_layout *layout;
30 static size_t layout_size;
31 static struct stream_flash_ctx ctx;
32 static int page_size;
33 static uint8_t *cb_buf;
34 static size_t cb_len;
35 static size_t cb_offset;
36 static int cb_ret;
37 
38 static const char progress_key[] = "sf-test/progress";
39 
40 static uint8_t generic_buf[BUF_LEN];
41 static uint8_t read_buf[TESTBUF_SIZE];
42 const static uint8_t write_buf[TESTBUF_SIZE] = {[0 ... TESTBUF_SIZE - 1] = 0xaa};
43 static uint8_t written_pattern[TESTBUF_SIZE] = {[0 ... TESTBUF_SIZE - 1] = 0xaa};
44 #if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE)
45 static uint8_t erased_pattern[TESTBUF_SIZE]  = {[0 ... TESTBUF_SIZE - 1] = 0xff};
46 #endif
47 
48 #define VERIFY_BUF(start, size, buf) \
49 do { \
50 	rc = flash_read(fdev, FLASH_BASE + start, read_buf, size); \
51 	zassert_equal(rc, 0, "should succeed"); \
52 	zassert_mem_equal(read_buf, buf, size, "should equal %s", #buf);\
53 } while (0)
54 
55 #define VERIFY_WRITTEN(start, size) VERIFY_BUF(start, size, written_pattern)
56 #if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE)
57 #define VERIFY_ERASED(start, size) VERIFY_BUF(start, size, erased_pattern)
58 #else
59 #define VERIFY_ERASED(start, size)
60 #endif
61 
stream_flash_callback(uint8_t * buf,size_t len,size_t offset)62 int stream_flash_callback(uint8_t *buf, size_t len, size_t offset)
63 {
64 	if (cb_buf) {
65 		zassert_equal(cb_buf, buf, "incorrect buf");
66 		zassert_equal(cb_len, len, "incorrect length");
67 		zassert_equal(cb_offset, offset, "incorrect offset");
68 	}
69 
70 	return cb_ret;
71 }
72 
erase_flash(void)73 static void erase_flash(void)
74 {
75 #if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE)
76 	int rc;
77 #if defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE)
78 	const struct flash_parameters *fparam = flash_get_parameters(fdev);
79 
80 	if (!(flash_params_get_erase_cap(fparam) & FLASH_ERASE_C_EXPLICIT)) {
81 		return;
82 	}
83 #endif
84 
85 	for (int i = 0; i < MAX_NUM_PAGES; i++) {
86 		rc = flash_erase(fdev,
87 				 FLASH_BASE + (i * layout->pages_size),
88 				 layout->pages_size);
89 		zassert_equal(rc, 0, "should succeed");
90 	}
91 #endif
92 }
93 
94 
init_target(void)95 static void init_target(void)
96 {
97 	int rc;
98 
99 	/* Ensure that target is clean */
100 	memset(&ctx, 0, sizeof(ctx));
101 	memset(generic_buf, 0, BUF_LEN);
102 
103 	/* Disable callback tests */
104 	cb_len = 0;
105 	cb_offset = 0;
106 	cb_buf = NULL;
107 	cb_ret = 0;
108 
109 	erase_flash();
110 
111 	rc = stream_flash_init(&ctx, fdev, generic_buf, BUF_LEN, FLASH_BASE, FLASH_AVAILABLE,
112 			       stream_flash_callback);
113 	zassert_equal(rc, 0, "expected success");
114 }
115 
ZTEST(lib_stream_flash,test_stream_flash_init)116 ZTEST(lib_stream_flash, test_stream_flash_init)
117 {
118 	int rc;
119 
120 	init_target();
121 
122 	/* End address out of range */
123 	rc = stream_flash_init(&ctx, fdev, generic_buf, BUF_LEN, FLASH_BASE,
124 		      FLASH_AVAILABLE + 4, NULL);
125 	zassert_true(rc < 0, "should fail as size is more than available");
126 
127 	rc = stream_flash_init(NULL, fdev, generic_buf, BUF_LEN, FLASH_BASE, 0, NULL);
128 	zassert_true(rc < 0, "should fail as ctx is NULL");
129 
130 	rc = stream_flash_init(&ctx, NULL, generic_buf, BUF_LEN, FLASH_BASE, 0, NULL);
131 	zassert_true(rc < 0, "should fail as fdev is NULL");
132 
133 	rc = stream_flash_init(&ctx, fdev, NULL, BUF_LEN, FLASH_BASE, 0, NULL);
134 	zassert_true(rc < 0, "should fail as buffer is NULL");
135 
136 	rc = stream_flash_init(&ctx, fdev, generic_buf, BUF_LEN, FLASH_BASE, 0, NULL);
137 	zassert_equal(rc, -EFAULT, "should fail as size 0");
138 
139 	rc = stream_flash_init(&ctx, fdev, generic_buf, BUF_LEN,
140 			       flash_get_write_block_size(ctx.fdev) - 1, 0, NULL);
141 	zassert_equal(rc, -EFAULT, "should fail as size is not aligned to write block size ");
142 	flash_get_write_block_size(ctx.fdev);
143 }
144 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write)145 ZTEST(lib_stream_flash, test_stream_flash_buffered_write)
146 {
147 	int rc;
148 
149 	init_target();
150 
151 	/* Don't fill up the buffer */
152 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 1, false);
153 	zassert_equal(rc, 0, "expected success");
154 
155 	/* Verify that no data has been written */
156 	VERIFY_ERASED(0, BUF_LEN);
157 
158 	/* Now, write the missing byte, which should trigger a dump to flash */
159 	rc = stream_flash_buffered_write(&ctx, write_buf, 1, false);
160 	zassert_equal(rc, 0, "expected success");
161 
162 	VERIFY_WRITTEN(0, BUF_LEN);
163 }
164 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_cross_buf_border)165 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_cross_buf_border)
166 {
167 	int rc;
168 
169 	init_target();
170 
171 	/* Test when write crosses border of the buffer */
172 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN + 128, false);
173 	zassert_equal(rc, 0, "expected success");
174 
175 	/* 1xBuffer should be dumped to flash */
176 	VERIFY_WRITTEN(0, BUF_LEN);
177 
178 	/* Fill rest of the buffer */
179 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 128, false);
180 	zassert_equal(rc, 0, "expected success");
181 	VERIFY_WRITTEN(BUF_LEN, BUF_LEN);
182 
183 	/* Fill half of the buffer */
184 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN/2, false);
185 	zassert_equal(rc, 0, "expected success");
186 
187 	/* Flush the buffer */
188 	rc = stream_flash_buffered_write(&ctx, write_buf, 0, true);
189 	zassert_equal(rc, 0, "expected success");
190 
191 	/* Two and a half buffers should be written */
192 	VERIFY_WRITTEN(0, BUF_LEN * 2 + BUF_LEN / 2);
193 }
194 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_unaligned)195 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_unaligned)
196 {
197 	int rc;
198 
199 	if (flash_get_write_block_size(fdev) == 1) {
200 		ztest_test_skip();
201 	}
202 
203 	init_target();
204 
205 	/* Test unaligned data size */
206 	rc = stream_flash_buffered_write(&ctx, write_buf, 1, true);
207 	zassert_equal(rc, 0, "expected success (%d)", rc);
208 
209 	/* 1 byte should be dumped to flash */
210 	VERIFY_WRITTEN(0, 1);
211 
212 	rc = stream_flash_init(&ctx, fdev, generic_buf, BUF_LEN, FLASH_BASE + BUF_LEN,
213 			       FLASH_AVAILABLE - BUF_LEN, stream_flash_callback);
214 	zassert_equal(rc, 0, "expected success");
215 
216 	/* Trigger verification in callback */
217 	cb_buf = generic_buf;
218 	cb_len = BUF_LEN - 1;
219 	cb_offset = FLASH_BASE + BUF_LEN;
220 
221 	/* Test unaligned data size */
222 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 1, true);
223 	zassert_equal(rc, 0, "expected success");
224 
225 	/* BUF_LEN-1 bytes should be dumped to flash */
226 	VERIFY_WRITTEN(BUF_LEN, BUF_LEN - 1);
227 }
228 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_multi_page)229 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_multi_page)
230 {
231 	int rc;
232 	int num_pages = MAX_NUM_PAGES - 1;
233 
234 	init_target();
235 
236 	/* Test when write spans multiple pages crosses border of page */
237 	rc = stream_flash_buffered_write(&ctx, write_buf,
238 					 (page_size * num_pages) + 128, false);
239 	zassert_equal(rc, 0, "expected success");
240 
241 	/* First three pages should be written */
242 	VERIFY_WRITTEN(0, page_size * num_pages);
243 
244 	/* Fill rest of the page */
245 	rc = stream_flash_buffered_write(&ctx, write_buf,
246 					 page_size - 128, false);
247 	zassert_equal(rc, 0, "expected success");
248 
249 	/* First four pages should be written */
250 	VERIFY_WRITTEN(0, BUF_LEN * (num_pages + 1));
251 }
252 
ZTEST(lib_stream_flash,test_stream_flash_bytes_written)253 ZTEST(lib_stream_flash, test_stream_flash_bytes_written)
254 {
255 	int rc;
256 	size_t offset;
257 
258 	init_target();
259 
260 	/* Verify that the offset is retained across failed downloads */
261 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN + 128, false);
262 	zassert_equal(rc, 0, "expected success");
263 
264 	/* First page should be written */
265 	VERIFY_WRITTEN(0, BUF_LEN);
266 
267 	/* Fill rest of the page */
268 	offset = stream_flash_bytes_written(&ctx);
269 	zassert_equal(offset, BUF_LEN, "offset should match buf size");
270 
271 	/* Fill up the buffer MINUS 128 to verify that write_buf_pos is kept */
272 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 128, false);
273 	zassert_equal(rc, 0, "expected success");
274 
275 	/* Second page should be written */
276 	VERIFY_WRITTEN(BUF_LEN, BUF_LEN);
277 }
278 
ZTEST(lib_stream_flash,test_stream_flash_bytes_buffered)279 ZTEST(lib_stream_flash, test_stream_flash_bytes_buffered)
280 {
281 	int rc;
282 	size_t buffered;
283 
284 	init_target();
285 
286 	/* Initially no bytes should be buffered */
287 	buffered = stream_flash_bytes_buffered(&ctx);
288 	zassert_equal(buffered, 0, "expected no buffered bytes");
289 
290 	/* Write partial buffer */
291 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 128, false);
292 	zassert_equal(rc, 0, "expected success");
293 
294 	/* Verify buffered bytes */
295 	buffered = stream_flash_bytes_buffered(&ctx);
296 	zassert_equal(buffered, BUF_LEN - 128, "expected buffered bytes");
297 
298 	/* Write remaining buffer */
299 	rc = stream_flash_buffered_write(&ctx, write_buf, 128, false);
300 	zassert_equal(rc, 0, "expected success");
301 
302 	/* After auto-flush, no bytes should be buffered */
303 	buffered = stream_flash_bytes_buffered(&ctx);
304 	zassert_equal(buffered, 0, "expected no buffered bytes");
305 
306 	/* Write more than buffer size to trigger auto-flush */
307 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN + 128, false);
308 	zassert_equal(rc, 0, "expected success");
309 
310 	/* Verify buffered bytes */
311 	buffered = stream_flash_bytes_buffered(&ctx);
312 	zassert_equal(buffered, 128, "expected remaining buffered bytes after auto-flush");
313 }
314 
ZTEST(lib_stream_flash,test_stream_flash_buf_size_greater_than_page_size)315 ZTEST(lib_stream_flash, test_stream_flash_buf_size_greater_than_page_size)
316 {
317 	int rc;
318 
319 	/* To illustrate that other params does not trigger error */
320 	rc = stream_flash_init(&ctx, fdev, generic_buf, 0x10, 0, FLASH_AVAILABLE, NULL);
321 	zassert_equal(rc, 0, "expected success");
322 
323 	/* Only change buf_len param */
324 	rc = stream_flash_init(&ctx, fdev, generic_buf, 0x10000, 0, FLASH_AVAILABLE, NULL);
325 	zassert_true(rc < 0, "expected failure");
326 }
327 
bad_read(const struct device * dev,off_t off,void * data,size_t len)328 static int bad_read(const struct device *dev, off_t off, void *data, size_t len)
329 {
330 	return -EINVAL;
331 }
332 
fake_write(const struct device * dev,off_t off,const void * data,size_t len)333 static int fake_write(const struct device *dev, off_t off, const void *data, size_t len)
334 {
335 	return 0;
336 }
337 
bad_write(const struct device * dev,off_t off,const void * data,size_t len)338 static int bad_write(const struct device *dev, off_t off, const void *data, size_t len)
339 {
340 	return -EINVAL;
341 }
342 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_callback)343 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_callback)
344 {
345 	int rc;
346 
347 	init_target();
348 
349 	/* Trigger verification in callback */
350 	cb_buf = generic_buf;
351 	cb_len = BUF_LEN;
352 	cb_offset = FLASH_BASE;
353 
354 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN + 128, false);
355 	zassert_equal(rc, 0, "expected success");
356 
357 	cb_len = BUF_LEN;
358 	cb_offset = FLASH_BASE + BUF_LEN;
359 
360 	/* Fill rest of the buffer */
361 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 128, false);
362 	zassert_equal(rc, 0, "expected success");
363 	VERIFY_WRITTEN(BUF_LEN, BUF_LEN);
364 
365 	/* Fill half of the buffer and flush it to flash */
366 	cb_len = BUF_LEN/2;
367 	cb_offset = FLASH_BASE + (2 * BUF_LEN);
368 
369 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN/2, true);
370 	zassert_equal(rc, 0, "expected success");
371 
372 	/* Ensure that failing callback trickles up to caller */
373 	cb_ret = -EFAULT;
374 	cb_buf = NULL; /* Don't verify other parameters of the callback */
375 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN, true);
376 	zassert_equal(rc, -EFAULT, "expected failure from callback");
377 	/* Expect that the BUF_LEN of bytes got stuck in buffer as the  verification callback
378 	 * failed.
379 	 */
380 	zassert_equal(ctx.buf_bytes, BUF_LEN, "Expected bytes to be left in buffer");
381 
382 	struct device fake_dev = *ctx.fdev;
383 	struct flash_driver_api fake_api = *(struct flash_driver_api *)ctx.fdev->api;
384 	struct stream_flash_ctx bad_ctx = ctx;
385 	struct stream_flash_ctx cmp_ctx;
386 
387 	fake_api.read = bad_read;
388 	/* Using fake write here because after previous write, with faked callback failure,
389 	 * the flash is already written and real flash_write would cause failure.
390 	 */
391 	fake_api.write = fake_write;
392 	fake_dev.api = &fake_api;
393 	bad_ctx.fdev = &fake_dev;
394 	/* Trigger erase attempt */
395 	cmp_ctx = bad_ctx;
396 	/* Just flush buffer */
397 	rc = stream_flash_buffered_write(&bad_ctx, write_buf, 0, true);
398 	zassert_equal(rc, -EINVAL, "expected failure from flash_sync got %d", rc);
399 	zassert_equal(ctx.buf_bytes, BUF_LEN, "Expected bytes to be left in buffer");
400 
401 	/* Pretend flashed context and attempt write write block - 1 bytes to trigger unaligned
402 	 * write; the write needs to fail so that we could check that context does not get modified.
403 	 */
404 	fake_api.write = bad_write;
405 	bad_ctx.callback = NULL;
406 	bad_ctx.buf_bytes = 0;
407 	cmp_ctx = bad_ctx;
408 	size_t wblock = flash_get_write_block_size(ctx.fdev);
409 	size_t tow = (wblock == 1) ? 1 : wblock - 1;
410 
411 	rc = stream_flash_buffered_write(&bad_ctx, write_buf, tow, true);
412 	zassert_equal(rc, -EINVAL, "expected failure from flash_sync got %d", rc);
413 	zassert_equal(cmp_ctx.bytes_written, bad_ctx.bytes_written,
414 		      "Expected bytes_written not modified");
415 	/* The write failed but bytes have already been added to buffer and buffer offset
416 	 * increased.
417 	 */
418 	zassert_equal(bad_ctx.buf_bytes, cmp_ctx.buf_bytes + tow,
419 		      "Expected %d bytes added to buffer", tow);
420 }
421 
ZTEST(lib_stream_flash,test_stream_flash_flush)422 ZTEST(lib_stream_flash, test_stream_flash_flush)
423 {
424 	int rc;
425 
426 	init_target();
427 
428 	/* Perform flush with NULL data pointer and 0 length */
429 	rc = stream_flash_buffered_write(&ctx, NULL, 0, true);
430 	zassert_equal(rc, 0, "expected success");
431 }
432 
433 #ifdef CONFIG_STREAM_FLASH_ERASE
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_whole_page)434 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_whole_page)
435 {
436 	int rc;
437 
438 	init_target();
439 
440 	/* Write all bytes of a page, verify that next page is not erased */
441 
442 	/* First fill two pages with data */
443 	rc = stream_flash_buffered_write(&ctx, write_buf, page_size * 2, true);
444 	zassert_equal(rc, 0, "expected success");
445 
446 	VERIFY_WRITTEN(0, page_size);
447 	VERIFY_WRITTEN(page_size, page_size);
448 
449 	/* Reset stream_flash context */
450 	memset(&ctx, 0, sizeof(ctx));
451 	memset(generic_buf, 0, BUF_LEN);
452 	rc = stream_flash_init(&ctx, fdev, generic_buf, BUF_LEN, FLASH_BASE, FLASH_AVAILABLE,
453 			       stream_flash_callback);
454 	zassert_equal(rc, 0, "expected success");
455 
456 	/* Write all bytes of a page, verify that next page is not erased */
457 	rc = stream_flash_buffered_write(&ctx, write_buf, page_size, true);
458 	zassert_equal(rc, 0, "expected success");
459 
460 	/* Second page should not be erased */
461 	VERIFY_WRITTEN(page_size, page_size);
462 }
463 #endif
464 
write_and_save_progress(size_t bytes,const char * save_key)465 static size_t write_and_save_progress(size_t bytes, const char *save_key)
466 {
467 	int rc;
468 	size_t bytes_written;
469 
470 	rc = stream_flash_buffered_write(&ctx, write_buf, bytes, true);
471 	zassert_equal(rc, 0, "expected success");
472 
473 	bytes_written = stream_flash_bytes_written(&ctx);
474 	zassert_true(bytes_written > 0, "expected bytes to be written");
475 
476 	if (save_key) {
477 		rc = stream_flash_progress_save(&ctx, save_key);
478 		zassert_equal(rc, 0, "expected success");
479 	}
480 
481 	return bytes_written;
482 }
483 
clear_all_progress(void)484 static void clear_all_progress(void)
485 {
486 	(void) settings_delete(progress_key);
487 }
488 
load_progress(const char * load_key)489 static size_t load_progress(const char *load_key)
490 {
491 	int rc;
492 
493 	rc = stream_flash_progress_load(&ctx, progress_key);
494 	zassert_equal(rc, 0, "expected success");
495 
496 	return stream_flash_bytes_written(&ctx);
497 }
498 
ZTEST(lib_stream_flash,test_stream_flash_progress_api)499 ZTEST(lib_stream_flash, test_stream_flash_progress_api)
500 {
501 	int rc;
502 
503 	clear_all_progress();
504 	init_target();
505 
506 	/* Test save parameter validation */
507 	rc = stream_flash_progress_save(NULL, progress_key);
508 	zassert_true(rc < 0, "expected error since ctx is NULL");
509 
510 	rc = stream_flash_progress_save(&ctx, NULL);
511 	zassert_true(rc < 0, "expected error since key is NULL");
512 
513 	rc = stream_flash_progress_save(&ctx, progress_key);
514 	zassert_equal(rc, 0, "expected success");
515 
516 	(void) write_and_save_progress(BUF_LEN, progress_key);
517 
518 	/* Test load parameter validation */
519 	rc = stream_flash_progress_load(NULL, progress_key);
520 	zassert_true(rc < 0, "expected error since ctx is NULL");
521 
522 	rc = stream_flash_progress_load(&ctx, NULL);
523 	zassert_true(rc < 0, "expected error since key is NULL");
524 
525 	rc = stream_flash_progress_load(&ctx, progress_key);
526 	zassert_equal(rc, 0, "expected success");
527 
528 	/* Test clear parameter validation */
529 	rc = stream_flash_progress_clear(NULL, progress_key);
530 	zassert_true(rc < 0, "expected error since ctx is NULL");
531 
532 	rc = stream_flash_progress_clear(&ctx, NULL);
533 	zassert_true(rc < 0, "expected error since key is NULL");
534 
535 	rc = stream_flash_progress_clear(&ctx, progress_key);
536 	zassert_equal(rc, 0, "expected success");
537 }
538 
ZTEST(lib_stream_flash,test_stream_flash_progress_resume)539 ZTEST(lib_stream_flash, test_stream_flash_progress_resume)
540 {
541 	int rc;
542 	size_t bytes_written_old;
543 	size_t bytes_written;
544 #ifdef CONFIG_STREAM_FLASH_ERASE
545 	size_t erased_up_to_old;
546 #endif
547 
548 	clear_all_progress();
549 	init_target();
550 
551 	bytes_written_old = stream_flash_bytes_written(&ctx);
552 #ifdef CONFIG_STREAM_FLASH_ERASE
553 	erased_up_to_old = ctx.erased_up_to;
554 #endif
555 
556 	/* Test load with zero bytes_written */
557 	rc = stream_flash_progress_save(&ctx, progress_key);
558 	zassert_equal(rc, 0, "expected success");
559 
560 	rc = stream_flash_progress_load(&ctx, progress_key);
561 	zassert_equal(rc, 0, "expected success");
562 
563 	bytes_written = stream_flash_bytes_written(&ctx);
564 	zassert_equal(bytes_written, bytes_written_old,
565 		      "expected bytes_written to be unchanged");
566 #ifdef CONFIG_STREAM_FLASH_ERASE
567 	zassert_equal(ctx.erased_up_to, erased_up_to_old,
568 		      "expected erase offset to be unchanged");
569 #endif
570 
571 	clear_all_progress();
572 	init_target();
573 
574 	/* Write some data and save the progress */
575 	bytes_written_old = write_and_save_progress(page_size * 2,
576 						    progress_key);
577 #ifdef CONFIG_STREAM_FLASH_ERASE
578 	zassert_false(ctx.erased_up_to == 0, "expected pages to be erased");
579 	erased_up_to_old = ctx.erased_up_to;
580 #endif
581 
582 	init_target();
583 
584 	/* Load the previous progress */
585 	bytes_written = load_progress(progress_key);
586 	zassert_equal(bytes_written, bytes_written_old,
587 		      "expected bytes_written to be loaded");
588 #if defined(CONFIG_STREAM_FLASH_ERASE)
589 	zassert_equal(erased_up_to_old, ctx.erased_up_to,
590 		      "expected last erased page offset to be loaded");
591 #endif
592 
593 	/* Check that outdated progress does not overwrite current progress */
594 	init_target();
595 
596 	(void) write_and_save_progress(BUF_LEN, progress_key);
597 	bytes_written_old = write_and_save_progress(BUF_LEN, NULL);
598 	bytes_written = load_progress(progress_key);
599 	zassert_equal(bytes_written, bytes_written_old,
600 		      "expected bytes_written to not be overwritten");
601 }
602 
ZTEST(lib_stream_flash,test_stream_flash_progress_clear)603 ZTEST(lib_stream_flash, test_stream_flash_progress_clear)
604 {
605 	int rc;
606 	size_t bytes_written_old;
607 	size_t bytes_written;
608 #ifdef CONFIG_STREAM_FLASH_ERASE
609 	off_t erase_offset_old;
610 #endif
611 
612 	clear_all_progress();
613 	init_target();
614 
615 	/* Test that progress is cleared. */
616 	(void) write_and_save_progress(BUF_LEN, progress_key);
617 
618 	rc = stream_flash_progress_clear(&ctx, progress_key);
619 	zassert_equal(rc, 0, "expected success");
620 
621 	init_target();
622 
623 	bytes_written_old = stream_flash_bytes_written(&ctx);
624 #ifdef CONFIG_STREAM_FLASH_ERASE
625 	erase_offset_old = ctx.erased_up_to;
626 #endif
627 
628 	rc = stream_flash_progress_load(&ctx, progress_key);
629 	zassert_equal(rc, 0, "expected success");
630 
631 	bytes_written = stream_flash_bytes_written(&ctx);
632 	zassert_equal(bytes_written, bytes_written_old,
633 		      "expected bytes_written to be unchanged");
634 
635 #ifdef CONFIG_STREAM_FLASH_ERASE
636 	zassert_equal(ctx.erased_up_to, erase_offset_old,
637 		      "expected erase offset to be unchanged");
638 #endif
639 }
640 
lib_stream_flash_before(void * data)641 void lib_stream_flash_before(void *data)
642 {
643 	zassume_true(device_is_ready(fdev), "Device is not ready");
644 
645 	api = fdev->api;
646 	api->page_layout(fdev, &layout, &layout_size);
647 
648 	page_size = layout->pages_size;
649 	zassume_true((page_size > BUF_LEN), "page size is not enough");
650 }
651 
652 ZTEST_SUITE(lib_stream_flash, NULL, NULL, lib_stream_flash_before, NULL, NULL);
653