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
;
69 uint32_t crcs
[num_blocks(len1
, block_size
)];
71 crc_of_blocks(buffer1
, len1
, block_size
, 32, crcs
);
74 ctx
= crc_context_new(block_size
, 32, crcs
, ARRAY_SIZE(crcs
));
77 for (used
= 0, i
= 0; used
< len2
; used
+= ret
) {
78 ret
= crc_read_block(ctx
, &result
, buffer2
+used
, len2
-used
);
79 check_result(result
, &curr_literal
, results
, num_results
, &i
);
82 while ((result
= crc_read_flush(ctx
)) != 0)
83 check_result(result
, &curr_literal
, results
, num_results
, &i
);
85 check_finalized_result(curr_literal
, results
, num_results
, &i
);
87 /* We must have achieved everything we expected. */
88 ok1(i
== num_results
);
89 crc_context_free(ctx
);
91 /* Byte-at-a-time method. */
92 ctx
= crc_context_new(block_size
, 32, crcs
, ARRAY_SIZE(crcs
));
95 for (used
= 0, i
= 0; used
< len2
; used
+= ret
) {
96 ret
= crc_read_block(ctx
, &result
, buffer2
+used
, 1);
98 check_result(result
, &curr_literal
, results
, num_results
, &i
);
101 while ((result
= crc_read_flush(ctx
)) != 0)
102 check_result(result
, &curr_literal
, results
, num_results
, &i
);
104 check_finalized_result(curr_literal
, results
, num_results
, &i
);
106 /* We must have achieved everything we expected. */
107 ok1(i
== num_results
);
108 crc_context_free(ctx
);
111 int main(int argc
, char *argv
[])
113 char *buffer1
, *buffer2
;
115 uint32_t crcs1
[12], crcs2
[12];
119 buffer1
= calloc(1024, 1);
120 buffer2
= calloc(1024, 1);
122 /* Truncated end block test. */
123 crcs1
[11] = 0xdeadbeef;
124 crc_of_blocks(buffer1
, 1024, 100, 32, crcs1
);
125 ok1(crcs1
[11] == 0xdeadbeef);
126 crc_of_blocks(buffer2
, 1024, 100, 32, crcs2
);
127 ok1(memcmp(crcs1
, crcs2
, sizeof(crcs1
[0])*11) == 0);
129 /* Fill with non-zero pattern, retest. */
130 for (i
= 0; i
< 1024; i
++)
131 buffer1
[i
] = buffer2
[i
] = i
+ i
/128;
133 crcs1
[11] = 0xdeadbeef;
134 crc_of_blocks(buffer1
, 1024, 100, 32, crcs1
);
135 ok1(crcs1
[11] == 0xdeadbeef);
136 crc_of_blocks(buffer2
, 1024, 100, 32, crcs2
);
137 ok1(memcmp(crcs1
, crcs2
, sizeof(crcs1
[0])*11) == 0);
139 /* Check that it correctly masks bits. */
140 crc_of_blocks(buffer1
, 1024, 128, 32, crcs1
);
141 crc_of_blocks(buffer2
, 1024, 128, 8, crcs2
);
142 for (i
= 0; i
< 1024/128; i
++)
143 ok1(crcs2
[i
] == (crcs1
[i
] & 0xFF));
145 /* Now test the "exact match" "round blocks" case. */
147 struct result res
[] = {
156 test_sync(buffer1
, 1024, buffer2
, 1024, 128,
157 res
, ARRAY_SIZE(res
));
160 /* Now test the "exact match" with end block case. */
162 struct result res
[] = {
174 test_sync(buffer1
, 1024, buffer2
, 1024, 100,
175 res
, ARRAY_SIZE(res
));
178 /* Now test the "one byte append" "round blocks" case. */
180 struct result res
[] = {
189 test_sync(buffer1
, 1024-128, buffer2
, 1024-127, 128,
190 res
, ARRAY_SIZE(res
));
193 /* Now test the "one byte append" with end block case. */
195 struct result res
[] = {
208 test_sync(buffer1
, 1023, buffer2
, 1024, 100,
209 res
, ARRAY_SIZE(res
));
212 /* Now try changing one block at a time, check we get right results. */
213 for (i
= 0; i
< 1024/128; i
++) {
215 struct result res
[8];
217 /* Mess with block. */
218 memcpy(buffer2
, buffer1
, 1024);
221 for (j
= 0; j
< ARRAY_SIZE(res
); j
++) {
223 res
[j
].type
= LITERAL
;
231 test_sync(buffer1
, 1024, buffer2
, 1024, 128,
232 res
, ARRAY_SIZE(res
));
235 /* Now try shrinking one block at a time, check we get right results. */
236 for (i
= 0; i
< 1024/128; i
++) {
238 struct result res
[8];
241 memcpy(buffer2
, buffer1
, i
* 128 + 64);
242 memcpy(buffer2
+ i
* 128 + 64, buffer1
+ i
* 128 + 65,
243 1024 - (i
* 128 + 65));
245 for (j
= 0; j
< ARRAY_SIZE(res
); j
++) {
247 res
[j
].type
= LITERAL
;
255 test_sync(buffer1
, 1024, buffer2
, 1023, 128,
256 res
, ARRAY_SIZE(res
));
259 /* Now try shrinking one block at a time, check we get right results. */
260 for (i
= 0; i
< 1024/128; i
++) {
262 struct result res
[8];
265 memcpy(buffer2
, buffer1
, i
* 128 + 64);
266 memcpy(buffer2
+ i
* 128 + 64, buffer1
+ i
* 128 + 65,
267 1024 - (i
* 128 + 65));
269 for (j
= 0; j
< ARRAY_SIZE(res
); j
++) {
271 res
[j
].type
= LITERAL
;
279 test_sync(buffer1
, 1024, buffer2
, 1023, 128,
280 res
, ARRAY_SIZE(res
));
283 return exit_status();