libswarm-ng

C implementation of BMT hasher, Swarmhash and Single Owner Chunk for swarm
git clone git://git.defalsify.org/libswarm-ng.git
Info | Log | Files | Refs | Submodules | README

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 }