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 /* False dev with erase set to NULL to avoid actual erase */
470 fake_api.erase = NULL;
471 struct stream_flash_ctx range_test_ctx = {
472 .offset = 1024,
473 .available = 2048,
474 .fdev = &fake_dev,
475 .last_erased_page_start_offset = -1,
476 };
477
478 rc = stream_flash_erase_page(&range_test_ctx, 1024);
479 zassert_equal(rc, -ENOSYS, "%d No device attached - expected failure", rc);
480
481 rc = stream_flash_erase_page(&range_test_ctx, 1023);
482 zassert_equal(rc, -ERANGE, "Expected failure - offset before designated area");
483
484 rc = stream_flash_erase_page(&range_test_ctx,
485 range_test_ctx.offset + range_test_ctx.available + 1);
486 zassert_equal(rc, -ERANGE, "Expected failure - offset after designated area");
487 }
488 #else
ZTEST(lib_stream_flash,test_stream_flash_erase_page)489 ZTEST(lib_stream_flash, test_stream_flash_erase_page)
490 {
491 ztest_test_skip();
492 }
493
ZTEST(lib_stream_flash,test_stream_flash_buffered_write_whole_page)494 ZTEST(lib_stream_flash, test_stream_flash_buffered_write_whole_page)
495 {
496 ztest_test_skip();
497 }
498 #endif
499
write_and_save_progress(size_t bytes,const char * save_key)500 static size_t write_and_save_progress(size_t bytes, const char *save_key)
501 {
502 int rc;
503 size_t bytes_written;
504
505 rc = stream_flash_buffered_write(&ctx, write_buf, bytes, true);
506 zassert_equal(rc, 0, "expected success");
507
508 bytes_written = stream_flash_bytes_written(&ctx);
509 zassert_true(bytes_written > 0, "expected bytes to be written");
510
511 if (save_key) {
512 rc = stream_flash_progress_save(&ctx, save_key);
513 zassert_equal(rc, 0, "expected success");
514 }
515
516 return bytes_written;
517 }
518
clear_all_progress(void)519 static void clear_all_progress(void)
520 {
521 (void) settings_delete(progress_key);
522 }
523
load_progress(const char * load_key)524 static size_t load_progress(const char *load_key)
525 {
526 int rc;
527
528 rc = stream_flash_progress_load(&ctx, progress_key);
529 zassert_equal(rc, 0, "expected success");
530
531 return stream_flash_bytes_written(&ctx);
532 }
533
ZTEST(lib_stream_flash,test_stream_flash_progress_api)534 ZTEST(lib_stream_flash, test_stream_flash_progress_api)
535 {
536 int rc;
537
538 clear_all_progress();
539 init_target();
540
541 /* Test save parameter validation */
542 rc = stream_flash_progress_save(NULL, progress_key);
543 zassert_true(rc < 0, "expected error since ctx is NULL");
544
545 rc = stream_flash_progress_save(&ctx, NULL);
546 zassert_true(rc < 0, "expected error since key is NULL");
547
548 rc = stream_flash_progress_save(&ctx, progress_key);
549 zassert_equal(rc, 0, "expected success");
550
551 (void) write_and_save_progress(BUF_LEN, progress_key);
552
553 /* Test load parameter validation */
554 rc = stream_flash_progress_load(NULL, progress_key);
555 zassert_true(rc < 0, "expected error since ctx is NULL");
556
557 rc = stream_flash_progress_load(&ctx, NULL);
558 zassert_true(rc < 0, "expected error since key is NULL");
559
560 rc = stream_flash_progress_load(&ctx, progress_key);
561 zassert_equal(rc, 0, "expected success");
562
563 /* Test clear parameter validation */
564 rc = stream_flash_progress_clear(NULL, progress_key);
565 zassert_true(rc < 0, "expected error since ctx is NULL");
566
567 rc = stream_flash_progress_clear(&ctx, NULL);
568 zassert_true(rc < 0, "expected error since key is NULL");
569
570 rc = stream_flash_progress_clear(&ctx, progress_key);
571 zassert_equal(rc, 0, "expected success");
572 }
573
ZTEST(lib_stream_flash,test_stream_flash_progress_resume)574 ZTEST(lib_stream_flash, test_stream_flash_progress_resume)
575 {
576 int rc;
577 size_t bytes_written_old;
578 size_t bytes_written;
579 #ifdef CONFIG_STREAM_FLASH_ERASE
580 off_t erase_offset_old;
581 off_t erase_offset;
582 #endif
583
584 clear_all_progress();
585 init_target();
586
587 bytes_written_old = stream_flash_bytes_written(&ctx);
588 #ifdef CONFIG_STREAM_FLASH_ERASE
589 erase_offset_old = ctx.last_erased_page_start_offset;
590 #endif
591
592 /* Test load with zero bytes_written */
593 rc = stream_flash_progress_save(&ctx, progress_key);
594 zassert_equal(rc, 0, "expected success");
595
596 rc = stream_flash_progress_load(&ctx, progress_key);
597 zassert_equal(rc, 0, "expected success");
598
599 bytes_written = stream_flash_bytes_written(&ctx);
600 zassert_equal(bytes_written, bytes_written_old,
601 "expected bytes_written to be unchanged");
602 #ifdef CONFIG_STREAM_FLASH_ERASE
603 erase_offset = ctx.last_erased_page_start_offset;
604 zassert_equal(erase_offset, erase_offset_old,
605 "expected erase offset to be unchanged");
606 #endif
607
608 clear_all_progress();
609 init_target();
610
611 /* Write some data and save the progress */
612 bytes_written_old = write_and_save_progress(page_size * 2,
613 progress_key);
614 #ifdef CONFIG_STREAM_FLASH_ERASE
615 erase_offset_old = ctx.last_erased_page_start_offset;
616 zassert_true(erase_offset_old != 0, "expected pages to be erased");
617 #endif
618
619 init_target();
620
621 /* Load the previous progress */
622 bytes_written = load_progress(progress_key);
623 zassert_equal(bytes_written, bytes_written_old,
624 "expected bytes_written to be loaded");
625 #if defined(CONFIG_STREAM_FLASH_ERASE)
626 zassert_equal(erase_offset_old, ctx.last_erased_page_start_offset,
627 "expected last erased page offset to be loaded");
628 #endif
629
630 /* Check that outdated progress does not overwrite current progress */
631 init_target();
632
633 (void) write_and_save_progress(BUF_LEN, progress_key);
634 bytes_written_old = write_and_save_progress(BUF_LEN, NULL);
635 bytes_written = load_progress(progress_key);
636 zassert_equal(bytes_written, bytes_written_old,
637 "expected bytes_written to not be overwritten");
638 }
639
ZTEST(lib_stream_flash,test_stream_flash_progress_clear)640 ZTEST(lib_stream_flash, test_stream_flash_progress_clear)
641 {
642 int rc;
643 size_t bytes_written_old;
644 size_t bytes_written;
645 #ifdef CONFIG_STREAM_FLASH_ERASE
646 off_t erase_offset_old;
647 off_t erase_offset;
648 #endif
649
650 clear_all_progress();
651 init_target();
652
653 /* Test that progress is cleared. */
654 (void) write_and_save_progress(BUF_LEN, progress_key);
655
656 rc = stream_flash_progress_clear(&ctx, progress_key);
657 zassert_equal(rc, 0, "expected success");
658
659 init_target();
660
661 bytes_written_old = stream_flash_bytes_written(&ctx);
662 #ifdef CONFIG_STREAM_FLASH_ERASE
663 erase_offset_old = ctx.last_erased_page_start_offset;
664 #endif
665
666 rc = stream_flash_progress_load(&ctx, progress_key);
667 zassert_equal(rc, 0, "expected success");
668
669 bytes_written = stream_flash_bytes_written(&ctx);
670 zassert_equal(bytes_written, bytes_written_old,
671 "expected bytes_written to be unchanged");
672
673 #ifdef CONFIG_STREAM_FLASH_ERASE
674 erase_offset = ctx.last_erased_page_start_offset;
675 zassert_equal(erase_offset, erase_offset_old,
676 "expected erase offset to be unchanged");
677 #endif
678 }
679
lib_stream_flash_before(void * data)680 void lib_stream_flash_before(void *data)
681 {
682 zassume_true(device_is_ready(fdev), "Device is not ready");
683
684 api = fdev->api;
685 api->page_layout(fdev, &layout, &layout_size);
686
687 page_size = layout->pages_size;
688 zassume_true((page_size > BUF_LEN), "page size is not enough");
689 }
690
691 ZTEST_SUITE(lib_stream_flash, NULL, NULL, lib_stream_flash_before, NULL, NULL);
692