check_file.c (8151B)
1 #include <check.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdio.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 8 #include "hex.h" 9 #include "swarmfile.h" 10 11 #include "common.h" 12 13 14 const char *callback_static_foo = "foo"; 15 int file_callback_serial = 0; 16 int file_callback_dir_fd = -1; 17 18 void file_callback(const unsigned char *hash, const unsigned char *data, const size_t data_length, void *callback_static) { 19 int fd; 20 unsigned char filename[32]; 21 22 sprintf(filename, "d%d", file_callback_serial); 23 fd = openat(file_callback_dir_fd, filename, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC | O_SYNC); 24 ck_assert_int_ge(fd, 2); 25 write(fd, data, data_length); 26 close(fd); 27 28 sprintf(filename, "h%d", file_callback_serial); 29 fd = openat(file_callback_dir_fd, filename, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC | O_SYNC); 30 ck_assert_int_ge(fd, 2); 31 write(fd, hash, SWARM_WORD_SIZE); 32 close(fd); 33 34 ck_assert_str_eq((unsigned char*)callback_static, callback_static_foo); 35 file_callback_serial++; 36 } 37 38 39 START_TEST(check_file_init) { 40 ck_assert_int_eq(SWARM_BATCH_SIZE, 128); 41 42 filehash_t fh; 43 int r; 44 45 filehash_init(&fh); 46 47 ck_assert_ptr_eq(fh.ptr[SWARM_LEVELS-1], fh.buf); 48 ck_assert_int_eq(fh.spans[1], SWARM_BATCH_SIZE * SWARM_BLOCK_SIZE); 49 } 50 END_TEST 51 52 START_TEST(check_file_single_write) { 53 filehash_t fh; 54 int r; 55 56 const unsigned char *data = "foo"; 57 58 filehash_init(&fh); 59 60 r = filehash_write(&fh, data, strlen(data)); 61 ck_assert_int_eq(r, 3); 62 ck_assert_int_eq(fh.writes[0], 1); 63 ck_assert_int_eq(fh.length, 3); 64 } 65 END_TEST 66 67 68 START_TEST(check_file_write_batch) { 69 filehash_t fh; 70 int r; 71 int i; 72 int j; 73 int v; 74 struct block_generator bg; 75 76 bg.v = 0; 77 bg.m = 255; 78 79 char buf[SWARM_BLOCK_SIZE]; 80 81 filehash_init(&fh); 82 83 for (i = 0; i < SWARM_BATCH_SIZE; i++) { 84 r = block_generate(&bg, buf, SWARM_BLOCK_SIZE); 85 ck_assert_int_eq(r, SWARM_BLOCK_SIZE); 86 r = filehash_write(&fh, buf, SWARM_BLOCK_SIZE); 87 ck_assert_int_eq(r, SWARM_BLOCK_SIZE); 88 } 89 ck_assert_int_eq(fh.writes[0], SWARM_BATCH_SIZE); 90 ck_assert_int_eq(fh.length, SWARM_BATCH_SIZE * SWARM_BLOCK_SIZE); 91 ck_assert_ptr_eq(fh.ptr[0], fh.ptr[1]); 92 ck_assert_ptr_eq(fh.ptr[1], fh.buf + SWARM_WORD_SIZE); 93 } 94 END_TEST 95 96 START_TEST(check_file_callback_data) { 97 filehash_t fh; 98 int r; 99 100 const unsigned char *data = "foo"; 101 unsigned char cbdir_template[] = "swarmfile_test_callback_data_XXXXXX"; 102 unsigned char *cbdir; 103 104 cbdir = mkdtemp(cbdir_template); 105 ck_assert_ptr_nonnull(cbdir); 106 107 file_callback_serial = 0; 108 file_callback_dir_fd = open(cbdir, O_DIRECTORY | O_SYNC); 109 110 filehash_init_callback(&fh, file_callback, "foo"); 111 112 r = filehash_write(&fh, data, strlen(data)); 113 ck_assert_int_eq(r, 3); 114 ck_assert_int_eq(fh.writes[0], 1); 115 ck_assert_int_eq(fh.length, 3); 116 close(file_callback_dir_fd); 117 118 } 119 END_TEST 120 121 START_TEST(check_file_callback_intermediate) { 122 filehash_t fh; 123 int i; 124 int r; 125 struct block_generator bg; 126 127 unsigned char buf[SWARM_BLOCK_SIZE * (SWARM_BATCH_SIZE + 1)]; 128 unsigned char cbdir_template[] = "swarmfile_test_callback_intermediate_XXXXXX"; 129 unsigned char *cbdir; 130 unsigned char cbfilename[1024]; 131 int cbfd; 132 unsigned char cbbuf[SWARM_BLOCK_SIZE]; 133 134 file_callback_serial = 0; 135 cbdir = mkdtemp(cbdir_template); 136 ck_assert_ptr_nonnull(cbdir); 137 138 file_callback_dir_fd = open(cbdir, O_DIRECTORY | O_SYNC); 139 140 filehash_init_callback(&fh, file_callback, (char*)callback_static_foo); 141 142 bg.v = 0; 143 bg.m = 255; 144 145 r = block_generate(&bg, buf, SWARM_BLOCK_SIZE * (SWARM_BATCH_SIZE + 1)); 146 ck_assert_int_eq(r, SWARM_BLOCK_SIZE * (SWARM_BATCH_SIZE + 1)); 147 for (i = 0; i < SWARM_BATCH_SIZE + 1; i++) { 148 r = filehash_write(&fh, buf + i * SWARM_BLOCK_SIZE, SWARM_BLOCK_SIZE); 149 ck_assert_int_eq(r, SWARM_BLOCK_SIZE); 150 151 if (i > 127) { 152 continue; 153 } 154 155 sprintf(cbfilename, "%s/d%d", cbdir, i); 156 cbfd = open(cbfilename, O_RDONLY); 157 ck_assert_int_gt(cbfd, 2); 158 159 r = read(cbfd, cbbuf, SWARM_BLOCK_SIZE); 160 ck_assert_int_eq(r, SWARM_BLOCK_SIZE); 161 ck_assert_mem_eq(cbbuf, buf + i * SWARM_BLOCK_SIZE, SWARM_BLOCK_SIZE); 162 close(cbfd); 163 } 164 165 sprintf(cbfilename, "%s/h128", cbdir); 166 //cbfd = openat(file_callback_dir_fd, cbfilename, O_RDONLY); 167 cbfd = open(cbfilename, O_RDONLY); 168 ck_assert_int_gt(cbfd, 2); 169 170 r = read(cbfd, cbbuf, SWARM_WORD_SIZE); 171 ck_assert_int_eq(r, SWARM_WORD_SIZE); 172 ck_assert_mem_eq(cbbuf, fh.buf, SWARM_WORD_SIZE); 173 close(cbfd); 174 175 r = filehash_sum(&fh); 176 ck_assert_int_eq(r, SWARM_BLOCK_SIZE * (SWARM_BATCH_SIZE + 1)); 177 sprintf(cbfilename, "%s/h130", cbdir); 178 cbfd = open(cbfilename, O_RDONLY); 179 ck_assert_int_gt(cbfd, 2); 180 181 r = read(cbfd, cbbuf, SWARM_WORD_SIZE); 182 ck_assert_mem_eq(cbbuf, fh.buf, SWARM_WORD_SIZE); 183 184 r = hex2bin("b8e1804e37a064d28d161ab5f256cc482b1423d5cd0a6b30fde7b0f51ece9199", cbbuf + SWARM_WORD_SIZE); 185 ck_assert_int_eq(r, SWARM_WORD_SIZE); 186 ck_assert_mem_eq(cbbuf, cbbuf + SWARM_WORD_SIZE, SWARM_WORD_SIZE); 187 close(cbfd); 188 189 close(file_callback_dir_fd); 190 file_callback_dir_fd = -1; 191 } 192 END_TEST 193 194 START_TEST(check_file_vectors) { 195 filehash_t fh; 196 int r; 197 int i; 198 int j; 199 int l; 200 int whole; 201 int part; 202 int writes; 203 unsigned char v_chk[SWARM_WORD_SIZE]; 204 struct block_generator bg; 205 unsigned char buf[SWARM_BLOCK_SIZE]; 206 207 int lengths[] = { 208 SWARM_BLOCK_SIZE, 209 SWARM_BLOCK_SIZE + SWARM_WORD_SIZE - 1, 210 SWARM_BLOCK_SIZE + SWARM_WORD_SIZE, 211 SWARM_BLOCK_SIZE + (SWARM_WORD_SIZE * 2) - 1, 212 SWARM_BLOCK_SIZE + (SWARM_WORD_SIZE * 2), 213 SWARM_BLOCK_SIZE * 2, 214 SWARM_BLOCK_SIZE * SWARM_BATCH_SIZE, 215 SWARM_BLOCK_SIZE * SWARM_BATCH_SIZE + SWARM_WORD_SIZE - 1, 216 SWARM_BLOCK_SIZE * SWARM_BATCH_SIZE + SWARM_WORD_SIZE, 217 SWARM_BLOCK_SIZE * SWARM_BATCH_SIZE + (SWARM_WORD_SIZE * 2), 218 SWARM_BLOCK_SIZE * (SWARM_BATCH_SIZE + 1), 219 SWARM_BLOCK_SIZE * (SWARM_BATCH_SIZE + 2), 220 SWARM_BLOCK_SIZE * SWARM_BATCH_SIZE * SWARM_BATCH_SIZE, 221 }; 222 223 unsigned char *vectors[] = { 224 "c10090961e7682a10890c334d759a28426647141213abda93b096b892824d2ef", 225 "91699c83ed93a1f87e326a29ccd8cc775323f9e7260035a5f014c975c5f3cd28", 226 "73759673a52c1f1707cbb61337645f4fcbd209cdc53d7e2cedaaa9f44df61285", 227 "db1313a727ffc184ae52a70012fbbf7235f551b9f2d2da04bf476abe42a3cb42", 228 "ade7af36ac0c7297dc1c11fd7b46981b629c6077bce75300f85b02a6153f161b", 229 "29a5fb121ce96194ba8b7b823a1f9c6af87e1791f824940a53b5a7efe3f790d9", 230 "3047d841077898c26bbe6be652a2ec590a5d9bd7cd45d290ea42511b48753c09", 231 "e5c76afa931e33ac94bce2e754b1bb6407d07f738f67856783d93934ca8fc576", 232 "485a526fc74c8a344c43a4545a5987d17af9ab401c0ef1ef63aefcc5c2c086df", 233 "624b2abb7aefc0978f891b2a56b665513480e5dc195b4a66cd8def074a6d2e94", 234 "b8e1804e37a064d28d161ab5f256cc482b1423d5cd0a6b30fde7b0f51ece9199", 235 "59de730bf6c67a941f3b2ffa2f920acfaa1713695ad5deea12b4a121e5f23fa1", 236 "522194562123473dcfd7a457b18ee7dee8b7db70ed3cfa2b73f348a992fdfd3b", 237 }; 238 239 filehash_init(&fh); 240 241 bg.m = 255; 242 243 for (i = 0; i < sizeof(vectors)/sizeof(vectors[0]); i++) { 244 bg.v = 0; 245 246 filehash_reset(&fh); 247 248 whole = lengths[i] / SWARM_BLOCK_SIZE; 249 part = lengths[i] % SWARM_BLOCK_SIZE; 250 writes = whole; 251 if (part > 0) { 252 writes++; 253 } 254 255 for (int j = 0; j < writes; j++) { 256 if (j < whole) { 257 l = SWARM_BLOCK_SIZE; 258 } else { 259 l = part; 260 } 261 r = block_generate(&bg, buf, l); 262 ck_assert_int_eq(r, l); 263 r = filehash_write(&fh, buf, l); 264 ck_assert_int_eq(r, l); 265 } 266 267 r = filehash_sum(&fh); 268 ck_assert_int_eq(r, lengths[i]); 269 270 r = hex2bin(vectors[i], v_chk); 271 ck_assert_mem_eq(fh.buf, v_chk, SWARM_WORD_SIZE); 272 } 273 } 274 END_TEST 275 276 277 278 279 Suite * common_suite(void) { 280 Suite *s; 281 TCase *tch; 282 TCase *tcc; 283 TCase *tcv; 284 285 s = suite_create("file"); 286 tch = tcase_create("hasher"); 287 tcc = tcase_create("callback"); 288 tcv = tcase_create("vectors"); 289 tcase_add_test(tch, check_file_init); 290 tcase_add_test(tch, check_file_single_write); 291 tcase_add_test(tch, check_file_write_batch); 292 suite_add_tcase(s, tch); 293 tcase_add_test(tcc, check_file_callback_data); 294 tcase_add_test(tcc, check_file_callback_intermediate); 295 suite_add_tcase(s, tcc); 296 tcase_add_test(tcv, check_file_vectors); 297 suite_add_tcase(s, tcv); 298 299 return s; 300 } 301 302 int main(void) { 303 int n_fail; 304 305 Suite *s; 306 SRunner *sr; 307 308 s = common_suite(); 309 sr = srunner_create(s); 310 311 srunner_run_all(sr, CK_VERBOSE); 312 n_fail = srunner_ntests_failed(sr); 313 srunner_free(sr); 314 315 return (n_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE; 316 }