Skip to content

Commit 08d39cf

Browse files
committed
Add delta roundtrip edge-case coverage
F/2271
1 parent fb9faff commit 08d39cf

1 file changed

Lines changed: 196 additions & 31 deletions

File tree

tools/unit-tests/unit-delta.c

Lines changed: 196 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -302,54 +302,213 @@ static void initialize_buffers(uint8_t *src_a, uint8_t *src_b, size_t size)
302302

303303
}
304304

305-
START_TEST(test_wb_patch_and_diff)
305+
static uint8_t pattern_byte(uint32_t seed, size_t index)
306+
{
307+
uint32_t value = seed ^ (uint32_t)index;
308+
309+
value *= 1664525U;
310+
value += 1013904223U;
311+
value ^= (uint32_t)(index >> 8);
312+
value ^= (uint32_t)(index >> 16);
313+
314+
if ((uint8_t)value == ESC) {
315+
value ^= 0x55U;
316+
}
317+
return (uint8_t)value;
318+
}
319+
320+
static void fill_pattern(uint8_t *dst, size_t size, uint32_t seed)
321+
{
322+
size_t i;
323+
324+
for (i = 0; i < size; ++i) {
325+
dst[i] = pattern_byte(seed, i);
326+
}
327+
}
328+
329+
static uint32_t run_roundtrip_case(const uint8_t *src_a, uint32_t size_a,
330+
const uint8_t *src_b, uint32_t size_b, uint32_t patch_capacity)
306331
{
307332
WB_DIFF_CTX diff_ctx;
308333
WB_PATCH_CTX patch_ctx;
309-
uint8_t src_a[SRC_SIZE];
310-
uint8_t src_b[SRC_SIZE];
311-
uint8_t patch[PATCH_SIZE];
312-
uint8_t patched_dst[DST_SIZE];
313-
int ret;
314-
int i;
334+
uint8_t *src_a_copy;
335+
uint8_t *patch;
336+
uint8_t *patched_dst;
337+
uint8_t *new_patch;
338+
uint8_t block[DELTA_BLOCK_SIZE] = {0};
315339
uint32_t p_written = 0;
340+
uint32_t dst_written = 0;
341+
int ret;
316342

343+
src_a_copy = malloc(size_a);
344+
patch = malloc(patch_capacity);
345+
patched_dst = malloc(size_b);
346+
ck_assert_ptr_nonnull(src_a_copy);
347+
ck_assert_ptr_nonnull(patch);
348+
ck_assert_ptr_nonnull(patched_dst);
317349

318-
initialize_buffers(src_a, src_b, SRC_SIZE);
350+
memcpy(src_a_copy, src_a, size_a);
319351

320-
ret = wb_diff_init(&diff_ctx, src_a, SRC_SIZE, src_b, SRC_SIZE);
352+
ret = wb_diff_init(&diff_ctx, src_a_copy, size_a, (uint8_t *)src_b, size_b);
321353
ck_assert_int_eq(ret, 0);
322354

323-
/* Create the patch */
324-
for (i = 0; i < SRC_SIZE; i += DELTA_BLOCK_SIZE) {
325-
ret = wb_diff(&diff_ctx, patch + p_written, DELTA_BLOCK_SIZE);
326-
ck_assert_int_ge(ret, 0); /* Should not be 0 until patch is over*/
327-
if (ret == 0)
355+
for (;;) {
356+
uint32_t remaining = patch_capacity - p_written;
357+
358+
ck_assert_uint_ge(remaining, BLOCK_HDR_SIZE);
359+
ret = wb_diff(&diff_ctx, patch + p_written,
360+
remaining > DELTA_BLOCK_SIZE ? DELTA_BLOCK_SIZE : remaining);
361+
ck_assert_int_ge(ret, 0);
362+
if (ret == 0) {
363+
if (diff_ctx.off_b < size_b) {
364+
patch_capacity += DELTA_BLOCK_SIZE;
365+
new_patch = realloc(patch, patch_capacity);
366+
ck_assert_ptr_nonnull(new_patch);
367+
patch = new_patch;
368+
continue;
369+
}
328370
break;
329-
p_written += ret;
371+
}
372+
p_written += (uint32_t)ret;
373+
ck_assert_uint_le(p_written, patch_capacity);
330374
}
331-
ck_assert_int_gt(p_written, 0); /* Should not be 0 */
332375

333-
printf("patch size: %u\n", p_written);
334-
ret = wb_patch_init(&patch_ctx, src_a, SRC_SIZE, patch, p_written);
376+
ck_assert_uint_eq(diff_ctx.off_b, size_b);
377+
ck_assert_uint_gt(p_written, 0);
378+
379+
ret = wb_patch_init(&patch_ctx, src_a_copy, size_a, patch, p_written);
335380
ck_assert_int_eq(ret, 0);
336381

337-
/* Apply the patch */
338-
for (i = 0; i < SRC_SIZE;)
339-
{
340-
ret = wb_patch(&patch_ctx, patched_dst + i, DELTA_BLOCK_SIZE);
341-
ck_assert_int_ge(ret, 0); /* Should not be 0 until patch is over*/
342-
if (ret == 0)
382+
for (;;) {
383+
ret = wb_patch(&patch_ctx, block, sizeof(block));
384+
ck_assert_int_ge(ret, 0);
385+
if (ret == 0) {
343386
break;
344-
i += ret;
387+
}
388+
ck_assert_uint_le(dst_written + (uint32_t)ret, size_b);
389+
memcpy(patched_dst + dst_written, block, (uint32_t)ret);
390+
dst_written += (uint32_t)ret;
345391
}
346-
ck_assert_int_gt(i, 0); /* Should not be 0 */
347-
ck_assert_int_eq(i, SRC_SIZE); // The patched length should match the buffer size
348392

349-
/* Verify that the patched destination matches src_b */
350-
for (i = 0; i < SRC_SIZE; ++i) {
351-
ck_assert_uint_eq(patched_dst[i], src_b[i]);
352-
}
393+
ck_assert_uint_eq(dst_written, size_b);
394+
ck_assert_int_eq(memcmp(patched_dst, src_b, size_b), 0);
395+
396+
free(patched_dst);
397+
free(patch);
398+
free(src_a_copy);
399+
return p_written;
400+
}
401+
402+
START_TEST(test_wb_patch_and_diff)
403+
{
404+
uint8_t src_a[SRC_SIZE];
405+
uint8_t src_b[SRC_SIZE];
406+
uint32_t p_written = 0;
407+
408+
initialize_buffers(src_a, src_b, SRC_SIZE);
409+
410+
p_written = run_roundtrip_case(src_a, SRC_SIZE, src_b, SRC_SIZE, PATCH_SIZE);
411+
printf("patch size: %u\n", p_written);
412+
}
413+
END_TEST
414+
415+
START_TEST(test_wb_patch_and_diff_identical_images)
416+
{
417+
uint8_t src_a[SRC_SIZE];
418+
uint32_t p_written;
419+
420+
fill_pattern(src_a, sizeof(src_a), 0x12345678U);
421+
422+
p_written = run_roundtrip_case(src_a, sizeof(src_a), src_a, sizeof(src_a),
423+
PATCH_SIZE);
424+
ck_assert_uint_lt(p_written, 64);
425+
}
426+
END_TEST
427+
428+
START_TEST(test_wb_patch_and_diff_completely_different_images)
429+
{
430+
uint8_t src_a[SRC_SIZE];
431+
uint8_t src_b[SRC_SIZE];
432+
433+
fill_pattern(src_a, sizeof(src_a), 0x11111111U);
434+
fill_pattern(src_b, sizeof(src_b), 0x22222222U);
435+
436+
(void)run_roundtrip_case(src_a, sizeof(src_a), src_b, sizeof(src_b),
437+
sizeof(src_b) + DELTA_BLOCK_SIZE);
438+
}
439+
END_TEST
440+
441+
START_TEST(test_wb_patch_and_diff_all_escape_images)
442+
{
443+
uint8_t src_a[SRC_SIZE];
444+
uint8_t src_b[SRC_SIZE];
445+
446+
memset(src_a, ESC, sizeof(src_a));
447+
memset(src_b, ESC, sizeof(src_b));
448+
449+
(void)run_roundtrip_case(src_a, sizeof(src_a), src_b, sizeof(src_b),
450+
PATCH_SIZE);
451+
}
452+
END_TEST
453+
454+
START_TEST(test_wb_patch_and_diff_multi_sector_images)
455+
{
456+
int sector_size_ret;
457+
uint32_t size;
458+
uint8_t *src_a;
459+
uint8_t *src_b;
460+
461+
sector_size_ret = wb_diff_get_sector_size();
462+
ck_assert_int_gt(sector_size_ret, BLOCK_HDR_SIZE);
463+
size = (uint32_t)(3 * sector_size_ret + 37);
464+
465+
src_a = malloc(size);
466+
src_b = malloc(size);
467+
ck_assert_ptr_nonnull(src_a);
468+
ck_assert_ptr_nonnull(src_b);
469+
470+
fill_pattern(src_a, size, 0xA5A5A5A5U);
471+
memcpy(src_b, src_a, size);
472+
src_b[sector_size_ret - 1] ^= 0x11;
473+
src_b[sector_size_ret] ^= 0x22;
474+
src_b[(2 * sector_size_ret) + 5] = ESC;
475+
476+
(void)run_roundtrip_case(src_a, size, src_b, size, size + DELTA_BLOCK_SIZE);
477+
478+
free(src_b);
479+
free(src_a);
480+
}
481+
END_TEST
482+
483+
START_TEST(test_wb_patch_and_diff_size_changing_update)
484+
{
485+
uint8_t src_a[2048];
486+
uint8_t src_b[3077];
487+
488+
fill_pattern(src_a, sizeof(src_a), 0x31415926U);
489+
fill_pattern(src_b, sizeof(src_b), 0x27182818U);
490+
memcpy(src_b + 512, src_a, sizeof(src_a));
491+
src_b[0] = ESC;
492+
src_b[sizeof(src_b) - 1] ^= 0x5A;
493+
494+
(void)run_roundtrip_case(src_a, sizeof(src_a), src_b, sizeof(src_b),
495+
sizeof(src_b) + DELTA_BLOCK_SIZE);
496+
}
497+
END_TEST
498+
499+
START_TEST(test_wb_patch_and_diff_single_byte_difference)
500+
{
501+
uint8_t src_a[SRC_SIZE];
502+
uint8_t src_b[SRC_SIZE];
503+
uint32_t p_written;
504+
505+
fill_pattern(src_a, sizeof(src_a), 0x0BADB002U);
506+
memcpy(src_b, src_a, sizeof(src_a));
507+
src_b[1537] ^= 0x01;
508+
509+
p_written = run_roundtrip_case(src_a, sizeof(src_a), src_b, sizeof(src_b),
510+
PATCH_SIZE);
511+
ck_assert_uint_lt(p_written, 64);
353512
}
354513
END_TEST
355514

@@ -376,6 +535,12 @@ Suite *patch_diff_suite(void)
376535
tcase_add_test(tc_wolfboot_delta, test_wb_diff_preserves_main_loop_header_margin_for_escape);
377536
tcase_add_test(tc_wolfboot_delta, test_wb_diff_rejects_match_offsets_beyond_24_bits);
378537
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff);
538+
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff_identical_images);
539+
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff_completely_different_images);
540+
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff_all_escape_images);
541+
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff_multi_sector_images);
542+
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff_size_changing_update);
543+
tcase_add_test(tc_wolfboot_delta, test_wb_patch_and_diff_single_byte_difference);
379544
suite_add_tcase(s, tc_wolfboot_delta);
380545

381546
return s;

0 commit comments

Comments
 (0)