Git fork
at reftables-rust 458 lines 13 kB view raw
1/* 2Copyright 2020 Google LLC 3 4Use of this source code is governed by a BSD-style 5license that can be found in the LICENSE file or at 6https://developers.google.com/open-source/licenses/bsd 7*/ 8 9#include "unit-test.h" 10#include "lib-reftable.h" 11#include "reftable/block.h" 12#include "reftable/blocksource.h" 13#include "reftable/constants.h" 14#include "reftable/reftable-error.h" 15#include "strbuf.h" 16 17void test_reftable_block__read_write(void) 18{ 19 const int header_off = 21; /* random */ 20 struct reftable_record recs[30]; 21 const size_t N = ARRAY_SIZE(recs); 22 const size_t block_size = 1024; 23 struct reftable_block_source source = { 0 }; 24 struct block_writer bw = { 25 .last_key = REFTABLE_BUF_INIT, 26 }; 27 struct reftable_record rec = { 28 .type = REFTABLE_BLOCK_TYPE_REF, 29 }; 30 size_t i = 0; 31 int ret; 32 struct reftable_block block = { 0 }; 33 struct block_iter it = BLOCK_ITER_INIT; 34 struct reftable_buf want = REFTABLE_BUF_INIT; 35 struct reftable_buf block_data = REFTABLE_BUF_INIT; 36 37 REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); 38 cl_assert(block_data.buf != NULL); 39 block_data.len = block_size; 40 41 ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_REF, 42 (uint8_t *) block_data.buf, block_size, 43 header_off, hash_size(REFTABLE_HASH_SHA1)); 44 cl_assert(!ret); 45 46 rec.u.ref.refname = (char *) ""; 47 rec.u.ref.value_type = REFTABLE_REF_DELETION; 48 ret = block_writer_add(&bw, &rec); 49 cl_assert_equal_i(ret, REFTABLE_API_ERROR); 50 51 for (i = 0; i < N; i++) { 52 rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); 53 rec.u.ref.value_type = REFTABLE_REF_VAL1; 54 memset(rec.u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); 55 56 recs[i] = rec; 57 ret = block_writer_add(&bw, &rec); 58 rec.u.ref.refname = NULL; 59 rec.u.ref.value_type = REFTABLE_REF_DELETION; 60 cl_assert_equal_i(ret, 0); 61 } 62 63 ret = block_writer_finish(&bw); 64 cl_assert(ret > 0); 65 66 block_writer_release(&bw); 67 68 block_source_from_buf(&source ,&block_data); 69 reftable_block_init(&block, &source, 0, header_off, block_size, 70 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF); 71 72 block_iter_init(&it, &block); 73 74 for (i = 0; ; i++) { 75 ret = block_iter_next(&it, &rec); 76 cl_assert(ret >= 0); 77 if (ret > 0) { 78 cl_assert_equal_i(i, N); 79 break; 80 } 81 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 82 } 83 84 for (i = 0; i < N; i++) { 85 reftable_record_key(&recs[i], &want); 86 87 ret = block_iter_seek_key(&it, &want); 88 cl_assert_equal_i(ret, 0); 89 90 ret = block_iter_next(&it, &rec); 91 cl_assert_equal_i(ret, 0); 92 93 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 94 95 want.len--; 96 ret = block_iter_seek_key(&it, &want); 97 cl_assert_equal_i(ret, 0); 98 99 ret = block_iter_next(&it, &rec); 100 cl_assert_equal_i(ret, 0); 101 cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 102 } 103 104 reftable_block_release(&block); 105 block_iter_close(&it); 106 reftable_record_release(&rec); 107 reftable_buf_release(&want); 108 reftable_buf_release(&block_data); 109 for (i = 0; i < N; i++) 110 reftable_record_release(&recs[i]); 111} 112 113void test_reftable_block__log_read_write(void) 114{ 115 const int header_off = 21; 116 struct reftable_record recs[30]; 117 const size_t N = ARRAY_SIZE(recs); 118 const size_t block_size = 2048; 119 struct reftable_block_source source = { 0 }; 120 struct block_writer bw = { 121 .last_key = REFTABLE_BUF_INIT, 122 }; 123 struct reftable_record rec = { 124 .type = REFTABLE_BLOCK_TYPE_LOG, 125 }; 126 size_t i = 0; 127 int ret; 128 struct reftable_block block = { 0 }; 129 struct block_iter it = BLOCK_ITER_INIT; 130 struct reftable_buf want = REFTABLE_BUF_INIT; 131 struct reftable_buf block_data = REFTABLE_BUF_INIT; 132 133 REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); 134 cl_assert(block_data.buf != NULL); 135 block_data.len = block_size; 136 137 ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_LOG, (uint8_t *) block_data.buf, block_size, 138 header_off, hash_size(REFTABLE_HASH_SHA1)); 139 cl_assert(!ret); 140 141 for (i = 0; i < N; i++) { 142 rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i); 143 rec.u.log.update_index = i; 144 rec.u.log.value_type = REFTABLE_LOG_UPDATE; 145 146 recs[i] = rec; 147 ret = block_writer_add(&bw, &rec); 148 rec.u.log.refname = NULL; 149 rec.u.log.value_type = REFTABLE_LOG_DELETION; 150 cl_assert_equal_i(ret, 0); 151 } 152 153 ret = block_writer_finish(&bw); 154 cl_assert(ret > 0); 155 156 block_writer_release(&bw); 157 158 block_source_from_buf(&source, &block_data); 159 reftable_block_init(&block, &source, 0, header_off, block_size, 160 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_LOG); 161 162 block_iter_init(&it, &block); 163 164 for (i = 0; ; i++) { 165 ret = block_iter_next(&it, &rec); 166 cl_assert(ret >= 0); 167 if (ret > 0) { 168 cl_assert_equal_i(i, N); 169 break; 170 } 171 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 172 } 173 174 for (i = 0; i < N; i++) { 175 reftable_buf_reset(&want); 176 cl_assert(reftable_buf_addstr(&want, recs[i].u.log.refname) == 0); 177 178 ret = block_iter_seek_key(&it, &want); 179 cl_assert_equal_i(ret, 0); 180 181 ret = block_iter_next(&it, &rec); 182 cl_assert_equal_i(ret, 0); 183 184 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 185 186 want.len--; 187 ret = block_iter_seek_key(&it, &want); 188 cl_assert_equal_i(ret, 0); 189 190 ret = block_iter_next(&it, &rec); 191 cl_assert_equal_i(ret, 0); 192 cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 193 } 194 195 reftable_block_release(&block); 196 block_iter_close(&it); 197 reftable_record_release(&rec); 198 reftable_buf_release(&want); 199 reftable_buf_release(&block_data); 200 for (i = 0; i < N; i++) 201 reftable_record_release(&recs[i]); 202} 203 204void test_reftable_block__obj_read_write(void) 205{ 206 const int header_off = 21; 207 struct reftable_record recs[30]; 208 const size_t N = ARRAY_SIZE(recs); 209 const size_t block_size = 1024; 210 struct reftable_block_source source = { 0 }; 211 struct block_writer bw = { 212 .last_key = REFTABLE_BUF_INIT, 213 }; 214 struct reftable_record rec = { 215 .type = REFTABLE_BLOCK_TYPE_OBJ, 216 }; 217 size_t i = 0; 218 int ret; 219 struct reftable_block block = { 0 }; 220 struct block_iter it = BLOCK_ITER_INIT; 221 struct reftable_buf want = REFTABLE_BUF_INIT; 222 struct reftable_buf block_data = REFTABLE_BUF_INIT; 223 224 REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); 225 cl_assert(block_data.buf != NULL); 226 block_data.len = block_size; 227 228 ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_OBJ, (uint8_t *) block_data.buf, block_size, 229 header_off, hash_size(REFTABLE_HASH_SHA1)); 230 cl_assert(!ret); 231 232 for (i = 0; i < N; i++) { 233 uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated; 234 DUP_ARRAY(allocated, bytes, ARRAY_SIZE(bytes)); 235 236 rec.u.obj.hash_prefix = allocated; 237 rec.u.obj.hash_prefix_len = 5; 238 239 recs[i] = rec; 240 ret = block_writer_add(&bw, &rec); 241 rec.u.obj.hash_prefix = NULL; 242 rec.u.obj.hash_prefix_len = 0; 243 cl_assert_equal_i(ret, 0); 244 } 245 246 ret = block_writer_finish(&bw); 247 cl_assert(ret > 0); 248 249 block_writer_release(&bw); 250 251 block_source_from_buf(&source, &block_data); 252 reftable_block_init(&block, &source, 0, header_off, block_size, 253 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_OBJ); 254 255 block_iter_init(&it, &block); 256 257 for (i = 0; ; i++) { 258 ret = block_iter_next(&it, &rec); 259 cl_assert(ret >= 0); 260 if (ret > 0) { 261 cl_assert_equal_i(i, N); 262 break; 263 } 264 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 265 } 266 267 for (i = 0; i < N; i++) { 268 reftable_record_key(&recs[i], &want); 269 270 ret = block_iter_seek_key(&it, &want); 271 cl_assert_equal_i(ret, 0); 272 273 ret = block_iter_next(&it, &rec); 274 cl_assert_equal_i(ret, 0); 275 276 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 277 } 278 279 reftable_block_release(&block); 280 block_iter_close(&it); 281 reftable_record_release(&rec); 282 reftable_buf_release(&want); 283 reftable_buf_release(&block_data); 284 for (i = 0; i < N; i++) 285 reftable_record_release(&recs[i]); 286} 287 288void test_reftable_block__ref_read_write(void) 289{ 290 const int header_off = 21; 291 struct reftable_record recs[30]; 292 const size_t N = ARRAY_SIZE(recs); 293 const size_t block_size = 1024; 294 struct reftable_block_source source = { 0 }; 295 struct block_writer bw = { 296 .last_key = REFTABLE_BUF_INIT, 297 }; 298 struct reftable_record rec = { 299 .type = REFTABLE_BLOCK_TYPE_INDEX, 300 .u.idx.last_key = REFTABLE_BUF_INIT, 301 }; 302 size_t i = 0; 303 int ret; 304 struct reftable_block block = { 0 }; 305 struct block_iter it = BLOCK_ITER_INIT; 306 struct reftable_buf want = REFTABLE_BUF_INIT; 307 struct reftable_buf block_data = REFTABLE_BUF_INIT; 308 309 REFTABLE_CALLOC_ARRAY(block_data.buf, block_size); 310 cl_assert(block_data.buf != NULL); 311 block_data.len = block_size; 312 313 ret = block_writer_init(&bw, REFTABLE_BLOCK_TYPE_INDEX, (uint8_t *) block_data.buf, block_size, 314 header_off, hash_size(REFTABLE_HASH_SHA1)); 315 cl_assert(!ret); 316 317 for (i = 0; i < N; i++) { 318 char buf[128]; 319 320 snprintf(buf, sizeof(buf), "branch%02"PRIuMAX, (uintmax_t)i); 321 322 reftable_buf_init(&recs[i].u.idx.last_key); 323 recs[i].type = REFTABLE_BLOCK_TYPE_INDEX; 324 cl_assert(!reftable_buf_addstr(&recs[i].u.idx.last_key, buf)); 325 recs[i].u.idx.offset = i; 326 327 ret = block_writer_add(&bw, &recs[i]); 328 cl_assert_equal_i(ret, 0); 329 } 330 331 ret = block_writer_finish(&bw); 332 cl_assert(ret > 0); 333 334 block_writer_release(&bw); 335 336 block_source_from_buf(&source, &block_data); 337 reftable_block_init(&block, &source, 0, header_off, block_size, 338 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_INDEX); 339 340 block_iter_init(&it, &block); 341 342 for (i = 0; ; i++) { 343 ret = block_iter_next(&it, &rec); 344 cl_assert(ret >= 0); 345 if (ret > 0) { 346 cl_assert_equal_i(i, N); 347 break; 348 } 349 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 350 } 351 352 for (i = 0; i < N; i++) { 353 reftable_record_key(&recs[i], &want); 354 355 ret = block_iter_seek_key(&it, &want); 356 cl_assert_equal_i(ret, 0); 357 358 ret = block_iter_next(&it, &rec); 359 cl_assert_equal_i(ret, 0); 360 361 cl_assert_equal_i(reftable_record_equal(&recs[i], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 362 363 want.len--; 364 ret = block_iter_seek_key(&it, &want); 365 cl_assert_equal_i(ret, 0); 366 367 ret = block_iter_next(&it, &rec); 368 cl_assert_equal_i(ret, 0); 369 cl_assert_equal_i(reftable_record_equal(&recs[10 * (i / 10)], &rec, REFTABLE_HASH_SIZE_SHA1), 1); 370 } 371 372 reftable_block_release(&block); 373 block_iter_close(&it); 374 reftable_record_release(&rec); 375 reftable_buf_release(&want); 376 reftable_buf_release(&block_data); 377 for (i = 0; i < N; i++) 378 reftable_record_release(&recs[i]); 379} 380 381void test_reftable_block__iterator(void) 382{ 383 struct reftable_block_source source = { 0 }; 384 struct block_writer writer = { 385 .last_key = REFTABLE_BUF_INIT, 386 }; 387 struct reftable_record expected_refs[20]; 388 struct reftable_ref_record ref = { 0 }; 389 struct reftable_iterator it = { 0 }; 390 struct reftable_block block = { 0 }; 391 struct reftable_buf data; 392 int err; 393 394 data.len = 1024; 395 REFTABLE_CALLOC_ARRAY(data.buf, data.len); 396 cl_assert(data.buf != NULL); 397 398 err = block_writer_init(&writer, REFTABLE_BLOCK_TYPE_REF, 399 (uint8_t *) data.buf, data.len, 400 0, hash_size(REFTABLE_HASH_SHA1)); 401 cl_assert(!err); 402 403 for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) { 404 expected_refs[i] = (struct reftable_record) { 405 .type = REFTABLE_BLOCK_TYPE_REF, 406 .u.ref = { 407 .value_type = REFTABLE_REF_VAL1, 408 .refname = xstrfmt("refs/heads/branch-%02"PRIuMAX, (uintmax_t)i), 409 }, 410 }; 411 memset(expected_refs[i].u.ref.value.val1, i, REFTABLE_HASH_SIZE_SHA1); 412 413 err = block_writer_add(&writer, &expected_refs[i]); 414 cl_assert_equal_i(err, 0); 415 } 416 417 err = block_writer_finish(&writer); 418 cl_assert(err > 0); 419 420 block_source_from_buf(&source, &data); 421 reftable_block_init(&block, &source, 0, 0, data.len, 422 REFTABLE_HASH_SIZE_SHA1, REFTABLE_BLOCK_TYPE_REF); 423 424 err = reftable_block_init_iterator(&block, &it); 425 cl_assert_equal_i(err, 0); 426 427 for (size_t i = 0; ; i++) { 428 err = reftable_iterator_next_ref(&it, &ref); 429 if (err > 0) { 430 cl_assert_equal_i(i, ARRAY_SIZE(expected_refs)); 431 break; 432 } 433 cl_assert_equal_i(err, 0); 434 435 cl_assert(reftable_ref_record_equal(&ref, 436 &expected_refs[i].u.ref, REFTABLE_HASH_SIZE_SHA1)); 437 } 438 439 err = reftable_iterator_seek_ref(&it, "refs/heads/does-not-exist"); 440 cl_assert_equal_i(err, 0); 441 err = reftable_iterator_next_ref(&it, &ref); 442 cl_assert_equal_i(err, 1); 443 444 err = reftable_iterator_seek_ref(&it, "refs/heads/branch-13"); 445 cl_assert_equal_i(err, 0); 446 err = reftable_iterator_next_ref(&it, &ref); 447 cl_assert_equal_i(err, 0); 448 cl_assert(reftable_ref_record_equal(&ref, 449 &expected_refs[13].u.ref,REFTABLE_HASH_SIZE_SHA1)); 450 451 for (size_t i = 0; i < ARRAY_SIZE(expected_refs); i++) 452 reftable_free(expected_refs[i].u.ref.refname); 453 reftable_ref_record_release(&ref); 454 reftable_iterator_destroy(&it); 455 reftable_block_release(&block); 456 block_writer_release(&writer); 457 reftable_buf_release(&data); 458}