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
, tailsize
;
70 uint64_t crcs
[num_blocks(len1
, block_size
)];
72 crc_of_blocks(buffer1
, len1
, block_size
, 64, crcs
);
74 tailsize
= len1
% block_size
;
77 ctx
= crc_context_new(block_size
, 64, 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
, 64, 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 #define BUFFER_SIZE 512
117 #define BLOCK_SIZE 128
118 #define NUM_BLOCKS (BUFFER_SIZE / BLOCK_SIZE)
120 int main(int argc
, char *argv
[])
122 char *buffer1
, *buffer2
;
124 uint64_t crcs1
[NUM_BLOCKS
], crcs2
[NUM_BLOCKS
];
128 buffer1
= calloc(BUFFER_SIZE
, 1);
129 buffer2
= calloc(BUFFER_SIZE
, 1);
131 /* Truncated end block test. */
132 crcs1
[ARRAY_SIZE(crcs1
)-1] = 0xdeadbeef;
133 crc_of_blocks(buffer1
, BUFFER_SIZE
-BLOCK_SIZE
-1, BLOCK_SIZE
, 64, crcs1
);
134 ok1(crcs1
[ARRAY_SIZE(crcs1
)-1] == 0xdeadbeef);
135 crc_of_blocks(buffer2
, BUFFER_SIZE
-BLOCK_SIZE
-1, BLOCK_SIZE
, 64, crcs2
);
136 ok1(memcmp(crcs1
, crcs2
, sizeof(crcs1
[0])*(ARRAY_SIZE(crcs1
)-1)) == 0);
138 /* Fill with non-zero pattern, retest. */
139 for (i
= 0; i
< BUFFER_SIZE
; i
++)
140 buffer1
[i
] = buffer2
[i
] = i
+ i
/BLOCK_SIZE
;
142 crcs1
[ARRAY_SIZE(crcs1
)-1] = 0xdeadbeef;
143 crc_of_blocks(buffer1
, BUFFER_SIZE
-BLOCK_SIZE
-1, BLOCK_SIZE
, 64, crcs1
);
144 ok1(crcs1
[ARRAY_SIZE(crcs1
)-1] == 0xdeadbeef);
145 crc_of_blocks(buffer2
, BUFFER_SIZE
-BLOCK_SIZE
-1, BLOCK_SIZE
, 64, crcs2
);
146 ok1(memcmp(crcs1
, crcs2
, sizeof(crcs1
[0])*(ARRAY_SIZE(crcs1
)-1)) == 0);
148 /* Check that it correctly masks bits. */
149 crc_of_blocks(buffer1
, BUFFER_SIZE
, BLOCK_SIZE
, 64, crcs1
);
150 crc_of_blocks(buffer2
, BUFFER_SIZE
, BLOCK_SIZE
, 8, crcs2
);
151 for (i
= 0; i
< NUM_BLOCKS
; i
++)
152 ok1(crcs2
[i
] == (crcs1
[i
] & 0xFF00000000000000ULL
));
154 /* Now test the "exact match" "round blocks" case. */
156 struct result res
[NUM_BLOCKS
];
158 for (i
= 0; i
< ARRAY_SIZE(res
); i
++) {
162 test_sync(buffer1
, BUFFER_SIZE
, buffer2
,
163 BUFFER_SIZE
, BLOCK_SIZE
,
164 res
, ARRAY_SIZE(res
));
167 /* Now test the "exact match" with end block case. */
169 struct result res
[NUM_BLOCKS
+1];
170 for (i
= 0; i
< ARRAY_SIZE(res
); i
++) {
174 test_sync(buffer1
, BUFFER_SIZE
, buffer2
,
175 BUFFER_SIZE
, BLOCK_SIZE
-1,
176 res
, ARRAY_SIZE(res
));
179 /* Now test the "one byte append" "round blocks" case. */
181 struct result res
[NUM_BLOCKS
];
182 for (i
= 0; i
< ARRAY_SIZE(res
)-1; i
++) {
186 res
[i
].type
= LITERAL
;
189 test_sync(buffer1
, BUFFER_SIZE
-BLOCK_SIZE
,
190 buffer2
, BUFFER_SIZE
-BLOCK_SIZE
+1, BLOCK_SIZE
,
191 res
, ARRAY_SIZE(res
));
194 /* Now test the "one byte append" with end block case. */
196 struct result res
[NUM_BLOCKS
+2];
197 for (i
= 0; i
< ARRAY_SIZE(res
)-1; i
++) {
201 res
[i
].type
= LITERAL
;
204 test_sync(buffer1
, BUFFER_SIZE
-1,
205 buffer2
, BUFFER_SIZE
,
206 BLOCK_SIZE
- 1, res
, ARRAY_SIZE(res
));
209 /* Now try changing one block at a time, check we get right results. */
210 for (i
= 0; i
< NUM_BLOCKS
; i
++) {
212 struct result res
[NUM_BLOCKS
];
214 /* Mess with block. */
215 memcpy(buffer2
, buffer1
, BUFFER_SIZE
);
216 buffer2
[i
* BLOCK_SIZE
]++;
218 for (j
= 0; j
< ARRAY_SIZE(res
); j
++) {
220 res
[j
].type
= LITERAL
;
221 res
[j
].val
= BLOCK_SIZE
;
228 test_sync(buffer1
, BUFFER_SIZE
,
229 buffer2
, BUFFER_SIZE
,
230 BLOCK_SIZE
, res
, ARRAY_SIZE(res
));
233 /* Now try shrinking one block at a time, check we get right results. */
234 for (i
= 0; i
< NUM_BLOCKS
; i
++) {
236 struct result res
[NUM_BLOCKS
];
239 memcpy(buffer2
, buffer1
, i
* BLOCK_SIZE
+ BLOCK_SIZE
/2);
240 memcpy(buffer2
+ i
* BLOCK_SIZE
+ BLOCK_SIZE
/2,
241 buffer1
+ i
* BLOCK_SIZE
+ BLOCK_SIZE
/2 + 1,
242 BUFFER_SIZE
- (i
* BLOCK_SIZE
+ BLOCK_SIZE
/2 + 1));
244 for (j
= 0; j
< ARRAY_SIZE(res
); j
++) {
246 res
[j
].type
= LITERAL
;
247 res
[j
].val
= BLOCK_SIZE
-1;
254 test_sync(buffer1
, BUFFER_SIZE
,
255 buffer2
, BUFFER_SIZE
-1,
256 BLOCK_SIZE
, res
, ARRAY_SIZE(res
));
259 /* Finally, all possible combinations. */
260 for (i
= 0; i
< (1 << NUM_BLOCKS
); i
++) {
261 unsigned int j
, num_res
;
262 struct result res
[NUM_BLOCKS
];
264 memcpy(buffer2
, buffer1
, BUFFER_SIZE
);
265 for (j
= num_res
= 0; j
< ARRAY_SIZE(res
); j
++) {
267 res
[num_res
].type
= BLOCK
;
268 res
[num_res
].val
= j
;
271 /* Mess with block. */
272 buffer2
[j
* BLOCK_SIZE
]++;
273 if (num_res
&& res
[num_res
-1].type
== LITERAL
)
274 res
[num_res
-1].val
+= BLOCK_SIZE
;
276 res
[num_res
].type
= LITERAL
;
277 res
[num_res
].val
= BLOCK_SIZE
;
283 test_sync(buffer1
, BUFFER_SIZE
,
284 buffer2
, BUFFER_SIZE
,
285 BLOCK_SIZE
, res
, num_res
);
288 return exit_status();