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, 0,
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 	/* Entering '0' as flash size uses rest of flash. */
137 	rc = stream_flash_init(&ctx, fdev, generic_buf, BUF_LEN, FLASH_BASE, 0, NULL);
138 	zassert_equal(rc, 0, "should succeed");
139 	zassert_equal(FLASH_AVAILABLE, ctx.available, "Wrong size");
140 }
141 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write)142 ZTEST(lib_stream_flash, test_stream_flash_buffered_write)
143 {
144 	int rc;
145 
146 	init_target();
147 
148 	/* Don't fill up the buffer */
149 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 1, false);
150 	zassert_equal(rc, 0, "expected success");
151 
152 	/* Verify that no data has been written */
153 	VERIFY_ERASED(0, BUF_LEN);
154 
155 	/* Now, write the missing byte, which should trigger a dump to flash */
156 	rc = stream_flash_buffered_write(&ctx, write_buf, 1, false);
157 	zassert_equal(rc, 0, "expected success");
158 
159 	VERIFY_WRITTEN(0, BUF_LEN);
160 }
161 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_cross_buf_border)162 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_cross_buf_border)
163 {
164 	int rc;
165 
166 	init_target();
167 
168 	/* Test when write crosses border of the buffer */
169 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN + 128, false);
170 	zassert_equal(rc, 0, "expected success");
171 
172 	/* 1xBuffer should be dumped to flash */
173 	VERIFY_WRITTEN(0, BUF_LEN);
174 
175 	/* Fill rest of the buffer */
176 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 128, false);
177 	zassert_equal(rc, 0, "expected success");
178 	VERIFY_WRITTEN(BUF_LEN, BUF_LEN);
179 
180 	/* Fill half of the buffer */
181 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN/2, false);
182 	zassert_equal(rc, 0, "expected success");
183 
184 	/* Flush the buffer */
185 	rc = stream_flash_buffered_write(&ctx, write_buf, 0, true);
186 	zassert_equal(rc, 0, "expected success");
187 
188 	/* Two and a half buffers should be written */
189 	VERIFY_WRITTEN(0, BUF_LEN * 2 + BUF_LEN / 2);
190 }
191 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_unaligned)192 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_unaligned)
193 {
194 	int rc;
195 
196 	if (flash_get_write_block_size(fdev) == 1) {
197 		ztest_test_skip();
198 	}
199 
200 	init_target();
201 
202 	/* Test unaligned data size */
203 	rc = stream_flash_buffered_write(&ctx, write_buf, 1, true);
204 	zassert_equal(rc, 0, "expected success (%d)", rc);
205 
206 	/* 1 byte should be dumped to flash */
207 	VERIFY_WRITTEN(0, 1);
208 
209 	rc = stream_flash_init(&ctx, fdev, generic_buf, BUF_LEN, FLASH_BASE + BUF_LEN,
210 			       0, stream_flash_callback);
211 	zassert_equal(rc, 0, "expected success");
212 
213 	/* Trigger verification in callback */
214 	cb_buf = generic_buf;
215 	cb_len = BUF_LEN - 1;
216 	cb_offset = FLASH_BASE + BUF_LEN;
217 
218 	/* Test unaligned data size */
219 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 1, true);
220 	zassert_equal(rc, 0, "expected success");
221 
222 	/* BUF_LEN-1 bytes should be dumped to flash */
223 	VERIFY_WRITTEN(BUF_LEN, BUF_LEN - 1);
224 }
225 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_multi_page)226 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_multi_page)
227 {
228 	int rc;
229 	int num_pages = MAX_NUM_PAGES - 1;
230 
231 	init_target();
232 
233 	/* Test when write spans multiple pages crosses border of page */
234 	rc = stream_flash_buffered_write(&ctx, write_buf,
235 					 (page_size * num_pages) + 128, false);
236 	zassert_equal(rc, 0, "expected success");
237 
238 	/* First three pages should be written */
239 	VERIFY_WRITTEN(0, page_size * num_pages);
240 
241 	/* Fill rest of the page */
242 	rc = stream_flash_buffered_write(&ctx, write_buf,
243 					 page_size - 128, false);
244 	zassert_equal(rc, 0, "expected success");
245 
246 	/* First four pages should be written */
247 	VERIFY_WRITTEN(0, BUF_LEN * (num_pages + 1));
248 }
249 
ZTEST(lib_stream_flash,test_stream_flash_bytes_written)250 ZTEST(lib_stream_flash, test_stream_flash_bytes_written)
251 {
252 	int rc;
253 	size_t offset;
254 
255 	init_target();
256 
257 	/* Verify that the offset is retained across failed downloads */
258 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN + 128, false);
259 	zassert_equal(rc, 0, "expected success");
260 
261 	/* First page should be written */
262 	VERIFY_WRITTEN(0, BUF_LEN);
263 
264 	/* Fill rest of the page */
265 	offset = stream_flash_bytes_written(&ctx);
266 	zassert_equal(offset, BUF_LEN, "offset should match buf size");
267 
268 	/* Fill up the buffer MINUS 128 to verify that write_buf_pos is kept */
269 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 128, false);
270 	zassert_equal(rc, 0, "expected success");
271 
272 	/* Second page should be written */
273 	VERIFY_WRITTEN(BUF_LEN, BUF_LEN);
274 }
275 
ZTEST(lib_stream_flash,test_stream_flash_buf_size_greater_than_page_size)276 ZTEST(lib_stream_flash, test_stream_flash_buf_size_greater_than_page_size)
277 {
278 	int rc;
279 
280 	/* To illustrate that other params does not trigger error */
281 	rc = stream_flash_init(&ctx, fdev, generic_buf, 0x10, 0, 0, NULL);
282 	zassert_equal(rc, 0, "expected success");
283 
284 	/* Only change buf_len param */
285 	rc = stream_flash_init(&ctx, fdev, generic_buf, 0x10000, 0, 0, NULL);
286 	zassert_true(rc < 0, "expected failure");
287 }
288 
bad_read(const struct device * dev,off_t off,void * data,size_t len)289 static int bad_read(const struct device *dev, off_t off, void *data, size_t len)
290 {
291 	return -EINVAL;
292 }
293 
fake_write(const struct device * dev,off_t off,const void * data,size_t len)294 static int fake_write(const struct device *dev, off_t off, const void *data, size_t len)
295 {
296 	return 0;
297 }
298 
bad_write(const struct device * dev,off_t off,const void * data,size_t len)299 static int bad_write(const struct device *dev, off_t off, const void *data, size_t len)
300 {
301 	return -EINVAL;
302 }
303 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_callback)304 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_callback)
305 {
306 	int rc;
307 
308 	init_target();
309 
310 	/* Trigger verification in callback */
311 	cb_buf = generic_buf;
312 	cb_len = BUF_LEN;
313 	cb_offset = FLASH_BASE;
314 
315 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN + 128, false);
316 	zassert_equal(rc, 0, "expected success");
317 
318 	cb_len = BUF_LEN;
319 	cb_offset = FLASH_BASE + BUF_LEN;
320 
321 	/* Fill rest of the buffer */
322 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN - 128, false);
323 	zassert_equal(rc, 0, "expected success");
324 	VERIFY_WRITTEN(BUF_LEN, BUF_LEN);
325 
326 	/* Fill half of the buffer and flush it to flash */
327 	cb_len = BUF_LEN/2;
328 	cb_offset = FLASH_BASE + (2 * BUF_LEN);
329 
330 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN/2, true);
331 	zassert_equal(rc, 0, "expected success");
332 
333 	/* Ensure that failing callback trickles up to caller */
334 	cb_ret = -EFAULT;
335 	cb_buf = NULL; /* Don't verify other parameters of the callback */
336 	rc = stream_flash_buffered_write(&ctx, write_buf, BUF_LEN, true);
337 	zassert_equal(rc, -EFAULT, "expected failure from callback");
338 	/* Expect that the BUF_LEN of bytes got stuck in buffer as the  verification callback
339 	 * failed.
340 	 */
341 	zassert_equal(ctx.buf_bytes, BUF_LEN, "Expected bytes to be left in buffer");
342 
343 	struct device fake_dev = *ctx.fdev;
344 	struct flash_driver_api fake_api = *(struct flash_driver_api *)ctx.fdev->api;
345 	struct stream_flash_ctx bad_ctx = ctx;
346 	struct stream_flash_ctx cmp_ctx;
347 
348 	fake_api.read = bad_read;
349 	/* Using fake write here because after previous write, with faked callback failure,
350 	 * the flash is already written and real flash_write would cause failure.
351 	 */
352 	fake_api.write = fake_write;
353 	fake_dev.api = &fake_api;
354 	bad_ctx.fdev = &fake_dev;
355 	/* Trigger erase attempt */
356 	cmp_ctx = bad_ctx;
357 	/* Just flush buffer */
358 	rc = stream_flash_buffered_write(&bad_ctx, write_buf, 0, true);
359 	zassert_equal(rc, -EINVAL, "expected failure from flash_sync", rc);
360 	zassert_equal(ctx.buf_bytes, BUF_LEN, "Expected bytes to be left in buffer");
361 
362 	/* Pretend flashed context and attempt write write block - 1 bytes to trigger unaligned
363 	 * write; the write needs to fail so that we could check that context does not get modified.
364 	 */
365 	fake_api.write = bad_write;
366 	bad_ctx.callback = NULL;
367 	bad_ctx.buf_bytes = 0;
368 	cmp_ctx = bad_ctx;
369 	size_t wblock = flash_get_write_block_size(ctx.fdev);
370 	size_t tow = (wblock == 1) ? 1 : wblock - 1;
371 
372 	rc = stream_flash_buffered_write(&bad_ctx, write_buf, tow, true);
373 	zassert_equal(rc, -EINVAL, "expected failure from flash_sync", rc);
374 	zassert_equal(cmp_ctx.bytes_written, bad_ctx.bytes_written,
375 		      "Expected bytes_written not modified");
376 	/* The write failed but bytes have already been added to buffer and buffer offset
377 	 * increased.
378 	 */
379 	zassert_equal(bad_ctx.buf_bytes, cmp_ctx.buf_bytes + tow,
380 		      "Expected %d bytes added to buffer", tow);
381 }
382 
ZTEST(lib_stream_flash,test_stream_flash_flush)383 ZTEST(lib_stream_flash, test_stream_flash_flush)
384 {
385 	int rc;
386 
387 	init_target();
388 
389 	/* Perform flush with NULL data pointer and 0 length */
390 	rc = stream_flash_buffered_write(&ctx, NULL, 0, true);
391 	zassert_equal(rc, 0, "expected success");
392 }
393 
394 #ifdef CONFIG_STREAM_FLASH_ERASE
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_whole_page)395 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_whole_page)
396 {
397 	int rc;
398 
399 	init_target();
400 
401 	/* Write all bytes of a page, verify that next page is not erased */
402 
403 	/* First fill two pages with data */
404 	rc = stream_flash_buffered_write(&ctx, write_buf, page_size * 2, true);
405 	zassert_equal(rc, 0, "expected success");
406 
407 	VERIFY_WRITTEN(0, page_size);
408 	VERIFY_WRITTEN(page_size, page_size);
409 
410 	/* Reset stream_flash context */
411 	memset(&ctx, 0, sizeof(ctx));
412 	memset(generic_buf, 0, BUF_LEN);
413 	rc = stream_flash_init(&ctx, fdev, generic_buf, BUF_LEN, FLASH_BASE, 0,
414 			       stream_flash_callback);
415 	zassert_equal(rc, 0, "expected success");
416 
417 	/* Write all bytes of a page, verify that next page is not erased */
418 	rc = stream_flash_buffered_write(&ctx, write_buf, page_size, true);
419 	zassert_equal(rc, 0, "expected success");
420 
421 	/* Second page should not be erased */
422 	VERIFY_WRITTEN(page_size, page_size);
423 }
424 
425 /* Erase that never completes successfully */
bad_erase(const struct device * dev,off_t offset,size_t size)426 static int bad_erase(const struct device *dev, off_t offset, size_t size)
427 {
428 	return -EINVAL;
429 }
430 
ZTEST(lib_stream_flash,test_stream_flash_erase_page)431 ZTEST(lib_stream_flash, test_stream_flash_erase_page)
432 {
433 	int rc;
434 
435 	init_target();
436 
437 	/* Write something to make page dirty */
438 	rc = flash_write(ctx.fdev, FLASH_BASE, write_buf, BUF_LEN);
439 	zassert_equal(rc, 0, "expected success");
440 
441 	rc = stream_flash_erase_page(&ctx, FLASH_BASE);
442 	zassert_equal(rc, 0, "expected success");
443 
444 	VERIFY_ERASED(0, page_size);
445 
446 	/*
447 	 * Test failure in erase does not change context.
448 	 * The test is done by replacing erase function of device API with fake
449 	 * one that returns with an error, invoking the erase procedure
450 	 * and than comparing state of context prior to call to the one after.
451 	 */
452 	struct device fake_dev = *ctx.fdev;
453 	struct flash_driver_api fake_api = *(struct flash_driver_api *)ctx.fdev->api;
454 	struct stream_flash_ctx bad_ctx = ctx;
455 	struct stream_flash_ctx cmp_ctx;
456 
457 	fake_api.erase = bad_erase;
458 	fake_dev.api = &fake_api;
459 	bad_ctx.fdev = &fake_dev;
460 	/* Triger erase attempt */
461 	bad_ctx.last_erased_page_start_offset = FLASH_BASE - 16;
462 	cmp_ctx = bad_ctx;
463 
464 	rc = stream_flash_erase_page(&bad_ctx, FLASH_BASE);
465 	zassert_equal(memcmp(&bad_ctx, &cmp_ctx, sizeof(bad_ctx)), 0,
466 		      "Ctx should not get altered");
467 	zassert_equal(rc, -EINVAL, "Expected failure");
468 }
469 #else
ZTEST(lib_stream_flash,test_stream_flash_erase_page)470 ZTEST(lib_stream_flash, test_stream_flash_erase_page)
471 {
472 	ztest_test_skip();
473 }
474 
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_whole_page)475 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_whole_page)
476 {
477 	ztest_test_skip();
478 }
479 #endif
480 
write_and_save_progress(size_t bytes,const char * save_key)481 static size_t write_and_save_progress(size_t bytes, const char *save_key)
482 {
483 	int rc;
484 	size_t bytes_written;
485 
486 	rc = stream_flash_buffered_write(&ctx, write_buf, bytes, true);
487 	zassert_equal(rc, 0, "expected success");
488 
489 	bytes_written = stream_flash_bytes_written(&ctx);
490 	zassert_true(bytes_written > 0, "expected bytes to be written");
491 
492 	if (save_key) {
493 		rc = stream_flash_progress_save(&ctx, save_key);
494 		zassert_equal(rc, 0, "expected success");
495 	}
496 
497 	return bytes_written;
498 }
499 
clear_all_progress(void)500 static void clear_all_progress(void)
501 {
502 	(void) settings_delete(progress_key);
503 }
504 
load_progress(const char * load_key)505 static size_t load_progress(const char *load_key)
506 {
507 	int rc;
508 
509 	rc = stream_flash_progress_load(&ctx, progress_key);
510 	zassert_equal(rc, 0, "expected success");
511 
512 	return stream_flash_bytes_written(&ctx);
513 }
514 
ZTEST(lib_stream_flash,test_stream_flash_progress_api)515 ZTEST(lib_stream_flash, test_stream_flash_progress_api)
516 {
517 	int rc;
518 
519 	clear_all_progress();
520 	init_target();
521 
522 	/* Test save parameter validation */
523 	rc = stream_flash_progress_save(NULL, progress_key);
524 	zassert_true(rc < 0, "expected error since ctx is NULL");
525 
526 	rc = stream_flash_progress_save(&ctx, NULL);
527 	zassert_true(rc < 0, "expected error since key is NULL");
528 
529 	rc = stream_flash_progress_save(&ctx, progress_key);
530 	zassert_equal(rc, 0, "expected success");
531 
532 	(void) write_and_save_progress(BUF_LEN, progress_key);
533 
534 	/* Test load parameter validation */
535 	rc = stream_flash_progress_load(NULL, progress_key);
536 	zassert_true(rc < 0, "expected error since ctx is NULL");
537 
538 	rc = stream_flash_progress_load(&ctx, NULL);
539 	zassert_true(rc < 0, "expected error since key is NULL");
540 
541 	rc = stream_flash_progress_load(&ctx, progress_key);
542 	zassert_equal(rc, 0, "expected success");
543 
544 	/* Test clear parameter validation */
545 	rc = stream_flash_progress_clear(NULL, progress_key);
546 	zassert_true(rc < 0, "expected error since ctx is NULL");
547 
548 	rc = stream_flash_progress_clear(&ctx, NULL);
549 	zassert_true(rc < 0, "expected error since key is NULL");
550 
551 	rc = stream_flash_progress_clear(&ctx, progress_key);
552 	zassert_equal(rc, 0, "expected success");
553 }
554 
ZTEST(lib_stream_flash,test_stream_flash_progress_resume)555 ZTEST(lib_stream_flash, test_stream_flash_progress_resume)
556 {
557 	int rc;
558 	size_t bytes_written_old;
559 	size_t bytes_written;
560 #ifdef CONFIG_STREAM_FLASH_ERASE
561 	off_t erase_offset_old;
562 	off_t erase_offset;
563 #endif
564 
565 	clear_all_progress();
566 	init_target();
567 
568 	bytes_written_old = stream_flash_bytes_written(&ctx);
569 #ifdef CONFIG_STREAM_FLASH_ERASE
570 	erase_offset_old = ctx.last_erased_page_start_offset;
571 #endif
572 
573 	/* Test load with zero bytes_written */
574 	rc = stream_flash_progress_save(&ctx, progress_key);
575 	zassert_equal(rc, 0, "expected success");
576 
577 	rc = stream_flash_progress_load(&ctx, progress_key);
578 	zassert_equal(rc, 0, "expected success");
579 
580 	bytes_written = stream_flash_bytes_written(&ctx);
581 	zassert_equal(bytes_written, bytes_written_old,
582 		      "expected bytes_written to be unchanged");
583 #ifdef CONFIG_STREAM_FLASH_ERASE
584 	erase_offset = ctx.last_erased_page_start_offset;
585 	zassert_equal(erase_offset, erase_offset_old,
586 		      "expected erase offset to be unchanged");
587 #endif
588 
589 	clear_all_progress();
590 	init_target();
591 
592 	/* Write some data and save the progress */
593 	bytes_written_old = write_and_save_progress(page_size * 2,
594 						    progress_key);
595 #ifdef CONFIG_STREAM_FLASH_ERASE
596 	erase_offset_old = ctx.last_erased_page_start_offset;
597 	zassert_true(erase_offset_old != 0, "expected pages to be erased");
598 #endif
599 
600 	init_target();
601 
602 	/* Load the previous progress */
603 	bytes_written = load_progress(progress_key);
604 	zassert_equal(bytes_written, bytes_written_old,
605 		      "expected bytes_written to be loaded");
606 #if defined(CONFIG_STREAM_FLASH_ERASE)
607 	zassert_equal(erase_offset_old, ctx.last_erased_page_start_offset,
608 		      "expected last erased page offset to be loaded");
609 #endif
610 
611 	/* Check that outdated progress does not overwrite current progress */
612 	init_target();
613 
614 	(void) write_and_save_progress(BUF_LEN, progress_key);
615 	bytes_written_old = write_and_save_progress(BUF_LEN, NULL);
616 	bytes_written = load_progress(progress_key);
617 	zassert_equal(bytes_written, bytes_written_old,
618 		      "expected bytes_written to not be overwritten");
619 }
620 
ZTEST(lib_stream_flash,test_stream_flash_progress_clear)621 ZTEST(lib_stream_flash, test_stream_flash_progress_clear)
622 {
623 	int rc;
624 	size_t bytes_written_old;
625 	size_t bytes_written;
626 #ifdef CONFIG_STREAM_FLASH_ERASE
627 	off_t erase_offset_old;
628 	off_t erase_offset;
629 #endif
630 
631 	clear_all_progress();
632 	init_target();
633 
634 	/* Test that progress is cleared. */
635 	(void) write_and_save_progress(BUF_LEN, progress_key);
636 
637 	rc = stream_flash_progress_clear(&ctx, progress_key);
638 	zassert_equal(rc, 0, "expected success");
639 
640 	init_target();
641 
642 	bytes_written_old = stream_flash_bytes_written(&ctx);
643 #ifdef CONFIG_STREAM_FLASH_ERASE
644 	erase_offset_old = ctx.last_erased_page_start_offset;
645 #endif
646 
647 	rc = stream_flash_progress_load(&ctx, progress_key);
648 	zassert_equal(rc, 0, "expected success");
649 
650 	bytes_written = stream_flash_bytes_written(&ctx);
651 	zassert_equal(bytes_written, bytes_written_old,
652 		      "expected bytes_written to be unchanged");
653 
654 #ifdef CONFIG_STREAM_FLASH_ERASE
655 	erase_offset = ctx.last_erased_page_start_offset;
656 	zassert_equal(erase_offset, erase_offset_old,
657 		      "expected erase offset to be unchanged");
658 #endif
659 }
660 
lib_stream_flash_before(void * data)661 void lib_stream_flash_before(void *data)
662 {
663 	zassume_true(device_is_ready(fdev), "Device is not ready");
664 
665 	api = fdev->api;
666 	api->page_layout(fdev, &layout, &layout_size);
667 
668 	page_size = layout->pages_size;
669 	zassume_true((page_size > BUF_LEN), "page size is not enough");
670 }
671 
672 ZTEST_SUITE(lib_stream_flash, NULL, NULL, lib_stream_flash_before, NULL, NULL);
673