1 #include "crcsync/crcsync.h"
2 #include "../crcsync.c"
9 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
15 /* Block number, or length of literal. */
19 static inline size_t num_blocks(size_t len, size_t block_size)
21 return (len + block_size - 1) / block_size;
24 static void check_finalized_result(size_t curr_literal,
25 const struct result results[],
29 if (curr_literal == 0)
31 ok1(*curr_result < num_results);
32 ok1(results[*curr_result].type == LITERAL);
33 ok1(results[*curr_result].val == curr_literal);
37 static void check_result(long result,
39 const struct result results[], size_t num_results,
42 /* We append multiple literals into one. */
44 *curr_literal += result;
48 /* Check outstanding literals. */
50 check_finalized_result(*curr_literal, results, num_results,
55 ok1(*curr_result < num_results);
56 ok1(results[*curr_result].type == BLOCK);
57 ok1(results[*curr_result].val == -result - 1);
61 /* Start with buffer1 and sync to buffer2. */
62 static void test_sync(const char *buffer1, size_t len1,
63 const char *buffer2, size_t len2,
65 const struct result results[], size_t num_results)
67 struct crc_context *ctx;
68 size_t used, ret, i, curr_literal, finalsize;
70 uint32_t crcs[num_blocks(len1, block_size)];
72 crc_of_blocks(buffer1, len1, block_size, 32, crcs);
74 finalsize = len1 % block_size ?: block_size;
77 ctx = crc_context_new(block_size, 32, crcs, ARRAY_SIZE(crcs),
81 for (used = 0, i = 0; used < len2; used += ret) {
82 ret = crc_read_block(ctx, &result, buffer2+used, len2-used);
83 check_result(result, &curr_literal, results, num_results, &i);
86 while ((result = crc_read_flush(ctx)) != 0)
87 check_result(result, &curr_literal, results, num_results, &i);
89 check_finalized_result(curr_literal, results, num_results, &i);
91 /* We must have achieved everything we expected. */
92 ok1(i == num_results);
93 crc_context_free(ctx);
95 /* Byte-at-a-time method. */
96 ctx = crc_context_new(block_size, 32, crcs, ARRAY_SIZE(crcs),
100 for (used = 0, i = 0; used < len2; used += ret) {
101 ret = crc_read_block(ctx, &result, buffer2+used, 1);
103 check_result(result, &curr_literal, results, num_results, &i);
106 while ((result = crc_read_flush(ctx)) != 0)
107 check_result(result, &curr_literal, results, num_results, &i);
109 check_finalized_result(curr_literal, results, num_results, &i);
111 /* We must have achieved everything we expected. */
112 ok1(i == num_results);
113 crc_context_free(ctx);
116 int main(int argc, char *argv[])
118 char *buffer1, *buffer2;
120 uint32_t crcs1[12], crcs2[12];
124 buffer1 = calloc(1024, 1);
125 buffer2 = calloc(1024, 1);
127 /* Truncated end block test. */
128 crcs1[11] = 0xdeadbeef;
129 crc_of_blocks(buffer1, 1024, 100, 32, crcs1);
130 ok1(crcs1[11] == 0xdeadbeef);
131 crc_of_blocks(buffer2, 1024, 100, 32, crcs2);
132 ok1(memcmp(crcs1, crcs2, sizeof(crcs1[0])*11) == 0);
134 /* Fill with non-zero pattern, retest. */
135 for (i = 0; i < 1024; i++)
136 buffer1[i] = buffer2[i] = i + i/128;
138 crcs1[11] = 0xdeadbeef;
139 crc_of_blocks(buffer1, 1024, 100, 32, crcs1);
140 ok1(crcs1[11] == 0xdeadbeef);
141 crc_of_blocks(buffer2, 1024, 100, 32, crcs2);
142 ok1(memcmp(crcs1, crcs2, sizeof(crcs1[0])*11) == 0);
144 /* Check that it correctly masks bits. */
145 crc_of_blocks(buffer1, 1024, 128, 32, crcs1);
146 crc_of_blocks(buffer2, 1024, 128, 8, crcs2);
147 for (i = 0; i < 1024/128; i++)
148 ok1(crcs2[i] == (crcs1[i] & 0xFF));
150 /* Now test the "exact match" "round blocks" case. */
152 struct result res[] = {
161 test_sync(buffer1, 1024, buffer2, 1024, 128,
162 res, ARRAY_SIZE(res));
165 /* Now test the "exact match" with end block case. */
167 struct result res[] = {
179 test_sync(buffer1, 1024, buffer2, 1024, 100,
180 res, ARRAY_SIZE(res));
183 /* Now test the "one byte append" "round blocks" case. */
185 struct result res[] = {
194 test_sync(buffer1, 1024-128, buffer2, 1024-127, 128,
195 res, ARRAY_SIZE(res));
198 /* Now test the "one byte append" with end block case. */
200 struct result res[] = {
213 test_sync(buffer1, 1023, buffer2, 1024, 100,
214 res, ARRAY_SIZE(res));
217 /* Now try changing one block at a time, check we get right results. */
218 for (i = 0; i < 1024/128; i++) {
220 struct result res[8];
222 /* Mess with block. */
223 memcpy(buffer2, buffer1, 1024);
226 for (j = 0; j < ARRAY_SIZE(res); j++) {
228 res[j].type = LITERAL;
236 test_sync(buffer1, 1024, buffer2, 1024, 128,
237 res, ARRAY_SIZE(res));
240 /* Now try shrinking one block at a time, check we get right results. */
241 for (i = 0; i < 1024/128; i++) {
243 struct result res[8];
246 memcpy(buffer2, buffer1, i * 128 + 64);
247 memcpy(buffer2 + i * 128 + 64, buffer1 + i * 128 + 65,
248 1024 - (i * 128 + 65));
250 for (j = 0; j < ARRAY_SIZE(res); j++) {
252 res[j].type = LITERAL;
260 test_sync(buffer1, 1024, buffer2, 1023, 128,
261 res, ARRAY_SIZE(res));
264 /* Now try shrinking one block at a time, check we get right results. */
265 for (i = 0; i < 1024/128; i++) {
267 struct result res[8];
270 memcpy(buffer2, buffer1, i * 128 + 64);
271 memcpy(buffer2 + i * 128 + 64, buffer1 + i * 128 + 65,
272 1024 - (i * 128 + 65));
274 for (j = 0; j < ARRAY_SIZE(res); j++) {
276 res[j].type = LITERAL;
284 test_sync(buffer1, 1024, buffer2, 1023, 128,
285 res, ARRAY_SIZE(res));
288 return exit_status();