1 #include "crcsync/crcsync.h"
8 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
14 /* Block number, or length of literal. */
18 static inline size_t num_blocks(size_t len, size_t block_size)
20 return (len + block_size - 1) / block_size;
23 static void check_finalized_result(size_t curr_literal,
24 const struct result results[],
28 if (curr_literal == 0)
30 ok1(*curr_result < num_results);
31 ok1(results[*curr_result].type == LITERAL);
32 ok1(results[*curr_result].val == curr_literal);
36 static void check_result(long result,
38 const struct result results[], size_t num_results,
41 /* We append multiple literals into one. */
43 *curr_literal += result;
47 /* Check outstanding literals. */
49 check_finalized_result(*curr_literal, results, num_results,
54 ok1(*curr_result < num_results);
55 ok1(results[*curr_result].type == BLOCK);
56 ok1(results[*curr_result].val == -result - 1);
60 /* Start with buffer1 and sync to buffer2. */
61 static void test_sync(const char *buffer1, size_t len1,
62 const char *buffer2, size_t len2,
64 const struct result results[], size_t num_results)
66 struct crc_context *ctx;
67 size_t used, ret, i, curr_literal = 0;
69 uint32_t crcs[num_blocks(len1, block_size)];
71 crc_of_blocks(buffer1, len1, block_size, 32, crcs);
72 ctx = crc_context_new(block_size, 32, crcs, ARRAY_SIZE(crcs));
74 for (used = 0, i = 0; used < len2; used += ret) {
75 ret = crc_read_block(ctx, &result, buffer2+used, len2-used);
77 check_result(result, &curr_literal, results, num_results, &i);
80 while ((result = crc_read_flush(ctx)) != 0)
81 check_result(result, &curr_literal, results, num_results, &i);
83 check_finalized_result(curr_literal, results, num_results, &i);
85 /* We must have achieved everything we expected. */
86 ok1(i == num_results);
87 crc_context_free(ctx);
90 int main(int argc, char *argv[])
92 char *buffer1, *buffer2;
94 uint32_t crcs1[12], crcs2[12];
98 buffer1 = calloc(1024, 1);
99 buffer2 = calloc(1024, 1);
101 /* Truncated end block test. */
102 crcs1[11] = 0xdeadbeef;
103 crc_of_blocks(buffer1, 1024, 100, 32, crcs1);
104 ok1(crcs1[11] == 0xdeadbeef);
105 crc_of_blocks(buffer2, 1024, 100, 32, crcs2);
106 ok1(memcmp(crcs1, crcs2, sizeof(crcs1[0])*11) == 0);
108 /* Fill with non-zero pattern, retest. */
109 for (i = 0; i < 1024; i++)
110 buffer1[i] = buffer2[i] = i + i/128;
112 crcs1[11] = 0xdeadbeef;
113 crc_of_blocks(buffer1, 1024, 100, 32, crcs1);
114 ok1(crcs1[11] == 0xdeadbeef);
115 crc_of_blocks(buffer2, 1024, 100, 32, crcs2);
116 ok1(memcmp(crcs1, crcs2, sizeof(crcs1[0])*11) == 0);
118 /* Check that it correctly masks bits. */
119 crc_of_blocks(buffer1, 1024, 128, 32, crcs1);
120 crc_of_blocks(buffer2, 1024, 128, 8, crcs2);
121 for (i = 0; i < 1024/128; i++)
122 ok1(crcs2[i] == (crcs1[i] & 0xFF));
124 /* Now test the "exact match" "round blocks" case. */
126 struct result res[] = {
135 test_sync(buffer1, 1024, buffer2, 1024, 128,
136 res, ARRAY_SIZE(res));
139 /* Now test the "exact match" with end block case. */
141 struct result res[] = {
153 test_sync(buffer1, 1024, buffer2, 1024, 100,
154 res, ARRAY_SIZE(res));
157 /* Now test the "one byte append" "round blocks" case. */
159 struct result res[] = {
168 test_sync(buffer1, 1024-128, buffer2, 1024-127, 128,
169 res, ARRAY_SIZE(res));
172 /* Now test the "one byte append" with end block case. */
174 struct result res[] = {
187 test_sync(buffer1, 1023, buffer2, 1024, 100,
188 res, ARRAY_SIZE(res));
191 /* Now try changing one block at a time, check we get right results. */
192 for (i = 0; i < 1024/128; i++) {
194 struct result res[8];
196 /* Mess with block. */
197 memcpy(buffer2, buffer1, 1024);
200 for (j = 0; j < ARRAY_SIZE(res); j++) {
202 res[j].type = LITERAL;
210 test_sync(buffer1, 1024, buffer2, 1024, 128,
211 res, ARRAY_SIZE(res));
214 /* Now try shrinking one block at a time, check we get right results. */
215 for (i = 0; i < 1024/128; i++) {
217 struct result res[8];
220 memcpy(buffer2, buffer1, i * 128 + 64);
221 memcpy(buffer2 + i * 128 + 64, buffer1 + i * 128 + 65,
222 1024 - (i * 128 + 65));
224 for (j = 0; j < ARRAY_SIZE(res); j++) {
226 res[j].type = LITERAL;
234 test_sync(buffer1, 1024, buffer2, 1023, 128,
235 res, ARRAY_SIZE(res));
238 /* Now try shrinking one block at a time, check we get right results. */
239 for (i = 0; i < 1024/128; i++) {
241 struct result res[8];
244 memcpy(buffer2, buffer1, i * 128 + 64);
245 memcpy(buffer2 + i * 128 + 64, buffer1 + i * 128 + 65,
246 1024 - (i * 128 + 65));
248 for (j = 0; j < ARRAY_SIZE(res); j++) {
250 res[j].type = LITERAL;
258 test_sync(buffer1, 1024, buffer2, 1023, 128,
259 res, ARRAY_SIZE(res));
262 return exit_status();