From: Junio C Hamano Date: Tue, 3 Sep 2024 16:15:02 +0000 (-0700) Subject: Merge branch 'ps/reftable-concurrent-compaction' X-Git-Tag: v2.47.0-rc0~75 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=17636cdf3b0bf344a2e3090fd8bf254cf3ec0a2f;p=thirdparty%2Fgit.git Merge branch 'ps/reftable-concurrent-compaction' The code path for compacting reftable files saw some bugfixes against concurrent operation. * ps/reftable-concurrent-compaction: reftable/stack: fix segfault when reload with reused readers fails reftable/stack: reorder swapping in the reloaded stack contents reftable/reader: keep readers alive during iteration reftable/reader: introduce refcounting reftable/stack: fix broken refnames in `write_n_ref_tables()` reftable/reader: inline `reader_close()` reftable/reader: inline `init_reader()` reftable/reader: rename `reftable_new_reader()` reftable/stack: inline `stack_compact_range_stats()` reftable/blocksource: drop malloc block source --- 17636cdf3b0bf344a2e3090fd8bf254cf3ec0a2f diff --cc reftable/stack_test.c index 311ad759d2,6809bf9d30..89cb2be19f --- a/reftable/stack_test.c +++ b/reftable/stack_test.c @@@ -1077,7 -1077,113 +1077,113 @@@ static void test_reftable_stack_compact clear_dir(dir); } + static void test_reftable_stack_read_across_reload(void) + { + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st1 = NULL, *st2 = NULL; + struct reftable_ref_record rec = { 0 }; + struct reftable_iterator it = { 0 }; + char *dir = get_tmp_dir(__LINE__); + int err; + + /* Create a first stack and set up an iterator for it. */ + err = reftable_new_stack(&st1, dir, &opts); + EXPECT_ERR(err); + write_n_ref_tables(st1, 2); + EXPECT(st1->merged->readers_len == 2); + reftable_stack_init_ref_iterator(st1, &it); + err = reftable_iterator_seek_ref(&it, ""); + EXPECT_ERR(err); + + /* Set up a second stack for the same directory and compact it. */ + err = reftable_new_stack(&st2, dir, &opts); + EXPECT_ERR(err); + EXPECT(st2->merged->readers_len == 2); + err = reftable_stack_compact_all(st2, NULL); + EXPECT_ERR(err); + EXPECT(st2->merged->readers_len == 1); + + /* + * Verify that we can continue to use the old iterator even after we + * have reloaded its stack. + */ + err = reftable_stack_reload(st1); + EXPECT_ERR(err); + EXPECT(st1->merged->readers_len == 1); + err = reftable_iterator_next_ref(&it, &rec); + EXPECT_ERR(err); + EXPECT(!strcmp(rec.refname, "refs/heads/branch-0000")); + err = reftable_iterator_next_ref(&it, &rec); + EXPECT_ERR(err); + EXPECT(!strcmp(rec.refname, "refs/heads/branch-0001")); + err = reftable_iterator_next_ref(&it, &rec); + EXPECT(err > 0); + + reftable_ref_record_release(&rec); + reftable_iterator_destroy(&it); + reftable_stack_destroy(st1); + reftable_stack_destroy(st2); + clear_dir(dir); + } + + static void test_reftable_stack_reload_with_missing_table(void) + { + struct reftable_write_options opts = { 0 }; + struct reftable_stack *st = NULL; + struct reftable_ref_record rec = { 0 }; + struct reftable_iterator it = { 0 }; + struct strbuf table_path = STRBUF_INIT, content = STRBUF_INIT; + char *dir = get_tmp_dir(__LINE__); + int err; + + /* Create a first stack and set up an iterator for it. */ + err = reftable_new_stack(&st, dir, &opts); + EXPECT_ERR(err); + write_n_ref_tables(st, 2); + EXPECT(st->merged->readers_len == 2); + reftable_stack_init_ref_iterator(st, &it); + err = reftable_iterator_seek_ref(&it, ""); + EXPECT_ERR(err); + + /* + * Update the tables.list file with some garbage data, while reusing + * our old readers. This should trigger a partial reload of the stack, + * where we try to reuse our old readers. + */ + strbuf_addf(&content, "%s\n", st->readers[0]->name); + strbuf_addf(&content, "%s\n", st->readers[1]->name); + strbuf_addstr(&content, "garbage\n"); + strbuf_addf(&table_path, "%s.lock", st->list_file); + write_file_buf(table_path.buf, content.buf, content.len); + err = rename(table_path.buf, st->list_file); + EXPECT_ERR(err); + + err = reftable_stack_reload(st); + EXPECT(err == -4); + EXPECT(st->merged->readers_len == 2); + + /* + * Even though the reload has failed, we should be able to continue + * using the iterator. + */ + err = reftable_iterator_next_ref(&it, &rec); + EXPECT_ERR(err); + EXPECT(!strcmp(rec.refname, "refs/heads/branch-0000")); + err = reftable_iterator_next_ref(&it, &rec); + EXPECT_ERR(err); + EXPECT(!strcmp(rec.refname, "refs/heads/branch-0001")); + err = reftable_iterator_next_ref(&it, &rec); + EXPECT(err > 0); + + reftable_ref_record_release(&rec); + reftable_iterator_destroy(&it); + reftable_stack_destroy(st); + strbuf_release(&table_path); + strbuf_release(&content); + clear_dir(dir); + } + -int stack_test_main(int argc, const char *argv[]) +int stack_test_main(int argc UNUSED, const char *argv[] UNUSED) { RUN_TEST(test_empty_add); RUN_TEST(test_read_file); diff --cc t/unit-tests/t-reftable-block.c index f0124fc3d0,0000000000..f1a49485e2 mode 100644,000000..100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@@ -1,370 -1,0 +1,371 @@@ +/* +Copyright 2020 Google LLC + +Use of this source code is governed by a BSD-style +license that can be found in the LICENSE file or at +https://developers.google.com/open-source/licenses/bsd +*/ + +#include "test-lib.h" +#include "reftable/block.h" +#include "reftable/blocksource.h" +#include "reftable/constants.h" +#include "reftable/reftable-error.h" + +static void t_ref_block_read_write(void) +{ + const int header_off = 21; /* random */ + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 1024; + struct reftable_block block = { 0 }; + struct block_writer bw = { + .last_key = STRBUF_INIT, + }; + struct reftable_record rec = { + .type = BLOCK_TYPE_REF, + }; + size_t i = 0; + int ret; + struct block_reader br = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; - struct strbuf want = STRBUF_INIT; ++ struct strbuf want = STRBUF_INIT, buf = STRBUF_INIT; + + REFTABLE_CALLOC_ARRAY(block.data, block_size); + block.len = block_size; - block.source = malloc_block_source(); ++ block_source_from_strbuf(&block.source ,&buf); + block_writer_init(&bw, BLOCK_TYPE_REF, block.data, block_size, + header_off, hash_size(GIT_SHA1_FORMAT_ID)); + + rec.u.ref.refname = (char *) ""; + rec.u.ref.value_type = REFTABLE_REF_DELETION; + ret = block_writer_add(&bw, &rec); + check_int(ret, ==, REFTABLE_API_ERROR); + + for (i = 0; i < N; i++) { + rec.u.ref.refname = xstrfmt("branch%02"PRIuMAX, (uintmax_t)i); + rec.u.ref.value_type = REFTABLE_REF_VAL1; + memset(rec.u.ref.value.val1, i, GIT_SHA1_RAWSZ); + + recs[i] = rec; + ret = block_writer_add(&bw, &rec); + rec.u.ref.refname = NULL; + rec.u.ref.value_type = REFTABLE_REF_DELETION; + check_int(ret, ==, 0); + } + + ret = block_writer_finish(&bw); + check_int(ret, >, 0); + + block_writer_release(&bw); + + block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); + + block_iter_seek_start(&it, &br); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + check_int(ret, >=, 0); + if (ret > 0) { + check_int(i, ==, N); + break; + } + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); + } + + for (i = 0; i < N; i++) { + block_iter_reset(&it); + reftable_record_key(&recs[i], &want); + + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); + + want.len--; + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ)); + } + + block_reader_release(&br); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_block_done(&br.block); + strbuf_release(&want); ++ strbuf_release(&buf); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +static void t_log_block_read_write(void) +{ + const int header_off = 21; + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 2048; + struct reftable_block block = { 0 }; + struct block_writer bw = { + .last_key = STRBUF_INIT, + }; + struct reftable_record rec = { + .type = BLOCK_TYPE_LOG, + }; + size_t i = 0; + int ret; + struct block_reader br = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct strbuf want = STRBUF_INIT, buf = STRBUF_INIT; + + REFTABLE_CALLOC_ARRAY(block.data, block_size); + block.len = block_size; + block_source_from_strbuf(&block.source ,&buf); + block_writer_init(&bw, BLOCK_TYPE_LOG, block.data, block_size, + header_off, hash_size(GIT_SHA1_FORMAT_ID)); + + for (i = 0; i < N; i++) { + rec.u.log.refname = xstrfmt("branch%02"PRIuMAX , (uintmax_t)i); + rec.u.log.update_index = i; + rec.u.log.value_type = REFTABLE_LOG_UPDATE; + + recs[i] = rec; + ret = block_writer_add(&bw, &rec); + rec.u.log.refname = NULL; + rec.u.log.value_type = REFTABLE_LOG_DELETION; + check_int(ret, ==, 0); + } + + ret = block_writer_finish(&bw); + check_int(ret, >, 0); + + block_writer_release(&bw); + + block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); + + block_iter_seek_start(&it, &br); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + check_int(ret, >=, 0); + if (ret > 0) { + check_int(i, ==, N); + break; + } + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); + } + + for (i = 0; i < N; i++) { + block_iter_reset(&it); + strbuf_reset(&want); + strbuf_addstr(&want, recs[i].u.log.refname); + + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); + + want.len--; + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ)); + } + + block_reader_release(&br); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_block_done(&br.block); + strbuf_release(&want); + strbuf_release(&buf); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +static void t_obj_block_read_write(void) +{ + const int header_off = 21; + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 1024; + struct reftable_block block = { 0 }; + struct block_writer bw = { + .last_key = STRBUF_INIT, + }; + struct reftable_record rec = { + .type = BLOCK_TYPE_OBJ, + }; + size_t i = 0; + int ret; + struct block_reader br = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct strbuf want = STRBUF_INIT, buf = STRBUF_INIT; + + REFTABLE_CALLOC_ARRAY(block.data, block_size); + block.len = block_size; + block_source_from_strbuf(&block.source, &buf); + block_writer_init(&bw, BLOCK_TYPE_OBJ, block.data, block_size, + header_off, hash_size(GIT_SHA1_FORMAT_ID)); + + for (i = 0; i < N; i++) { + uint8_t bytes[] = { i, i + 1, i + 2, i + 3, i + 5 }, *allocated; + DUP_ARRAY(allocated, bytes, ARRAY_SIZE(bytes)); + + rec.u.obj.hash_prefix = allocated; + rec.u.obj.hash_prefix_len = 5; + + recs[i] = rec; + ret = block_writer_add(&bw, &rec); + rec.u.obj.hash_prefix = NULL; + rec.u.obj.hash_prefix_len = 0; + check_int(ret, ==, 0); + } + + ret = block_writer_finish(&bw); + check_int(ret, >, 0); + + block_writer_release(&bw); + + block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); + + block_iter_seek_start(&it, &br); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + check_int(ret, >=, 0); + if (ret > 0) { + check_int(i, ==, N); + break; + } + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); + } + + for (i = 0; i < N; i++) { + block_iter_reset(&it); + reftable_record_key(&recs[i], &want); + + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); + } + + block_reader_release(&br); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_block_done(&br.block); + strbuf_release(&want); + strbuf_release(&buf); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +static void t_index_block_read_write(void) +{ + const int header_off = 21; + struct reftable_record recs[30]; + const size_t N = ARRAY_SIZE(recs); + const size_t block_size = 1024; + struct reftable_block block = { 0 }; + struct block_writer bw = { + .last_key = STRBUF_INIT, + }; + struct reftable_record rec = { + .type = BLOCK_TYPE_INDEX, + .u.idx.last_key = STRBUF_INIT, + }; + size_t i = 0; + int ret; + struct block_reader br = { 0 }; + struct block_iter it = BLOCK_ITER_INIT; + struct strbuf want = STRBUF_INIT, buf = STRBUF_INIT; + + REFTABLE_CALLOC_ARRAY(block.data, block_size); + block.len = block_size; + block_source_from_strbuf(&block.source, &buf); + block_writer_init(&bw, BLOCK_TYPE_INDEX, block.data, block_size, + header_off, hash_size(GIT_SHA1_FORMAT_ID)); + + for (i = 0; i < N; i++) { + strbuf_init(&recs[i].u.idx.last_key, 9); + + recs[i].type = BLOCK_TYPE_INDEX; + strbuf_addf(&recs[i].u.idx.last_key, "branch%02"PRIuMAX, (uintmax_t)i); + recs[i].u.idx.offset = i; + + ret = block_writer_add(&bw, &recs[i]); + check_int(ret, ==, 0); + } + + ret = block_writer_finish(&bw); + check_int(ret, >, 0); + + block_writer_release(&bw); + + block_reader_init(&br, &block, header_off, block_size, GIT_SHA1_RAWSZ); + + block_iter_seek_start(&it, &br); + + for (i = 0; ; i++) { + ret = block_iter_next(&it, &rec); + check_int(ret, >=, 0); + if (ret > 0) { + check_int(i, ==, N); + break; + } + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); + } + + for (i = 0; i < N; i++) { + block_iter_reset(&it); + reftable_record_key(&recs[i], &want); + + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); + + want.len--; + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); + + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ)); + } + + block_reader_release(&br); + block_iter_close(&it); + reftable_record_release(&rec); + reftable_block_done(&br.block); + strbuf_release(&want); + strbuf_release(&buf); + for (i = 0; i < N; i++) + reftable_record_release(&recs[i]); +} + +int cmd_main(int argc UNUSED, const char *argv[] UNUSED) +{ + TEST(t_index_block_read_write(), "read-write operations on index blocks work"); + TEST(t_log_block_read_write(), "read-write operations on log blocks work"); + TEST(t_obj_block_read_write(), "read-write operations on obj blocks work"); + TEST(t_ref_block_read_write(), "read-write operations on ref blocks work"); + + return test_done(); +} diff --cc t/unit-tests/t-reftable-readwrite.c index 1eae36cc60,0494e7955a..b4d7e7e76b --- a/t/unit-tests/t-reftable-readwrite.c +++ b/t/unit-tests/t-reftable-readwrite.c @@@ -200,13 -190,13 +200,13 @@@ static void t_log_write_read(void struct reftable_write_options opts = { .block_size = 256, }; - struct reftable_ref_record ref = { NULL }; + struct reftable_ref_record ref = { 0 }; int i = 0; - struct reftable_log_record log = { NULL }; + struct reftable_log_record log = { 0 }; int n; - struct reftable_iterator it = { NULL }; + struct reftable_iterator it = { 0 }; - struct reftable_reader rd = { 0 }; + struct reftable_reader *reader; - struct reftable_block_source source = { NULL }; + struct reftable_block_source source = { 0 }; struct strbuf buf = STRBUF_INIT; struct reftable_writer *w = reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts); @@@ -246,16 -236,16 +246,16 @@@ block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.log"); + err = reftable_reader_new(&reader, &source, "file.log"); - EXPECT_ERR(err); + check(!err); - reftable_reader_init_ref_iterator(&rd, &it); + reftable_reader_init_ref_iterator(reader, &it); err = reftable_iterator_seek_ref(&it, names[N - 1]); - EXPECT_ERR(err); + check(!err); err = reftable_iterator_next_ref(&it, &ref); - EXPECT_ERR(err); + check(!err); /* end of iteration. */ err = reftable_iterator_next_ref(&it, &ref); @@@ -264,18 -254,22 +264,18 @@@ reftable_iterator_destroy(&it); reftable_ref_record_release(&ref); - reftable_reader_init_log_iterator(&rd, &it); + reftable_reader_init_log_iterator(reader, &it); err = reftable_iterator_seek_log(&it, ""); - EXPECT_ERR(err); + check(!err); - i = 0; - while (1) { + for (i = 0; ; i++) { int err = reftable_iterator_next_log(&it, &log); - if (err > 0) { + if (err > 0) break; - } - - EXPECT_ERR(err); - EXPECT_STREQ(names[i], log.refname); - EXPECT(i == log.update_index); - i++; + check(!err); + check_str(names[i], log.refname); + check_int(i, ==, log.update_index); reftable_log_record_release(&log); } @@@ -285,10 -279,10 +285,10 @@@ /* cleanup. */ strbuf_release(&buf); free_names(names); - reader_close(&rd); + reftable_reader_decref(reader); } -static void test_log_zlib_corruption(void) +static void t_log_zlib_corruption(void) { struct reftable_write_options opts = { .block_size = 256, @@@ -337,28 -331,28 +337,28 @@@ block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.log"); + err = reftable_reader_new(&reader, &source, "file.log"); - EXPECT_ERR(err); + check(!err); - reftable_reader_init_log_iterator(&rd, &it); + reftable_reader_init_log_iterator(reader, &it); err = reftable_iterator_seek_log(&it, "refname"); - EXPECT(err == REFTABLE_ZLIB_ERROR); + check_int(err, ==, REFTABLE_ZLIB_ERROR); reftable_iterator_destroy(&it); /* cleanup. */ + reftable_reader_decref(reader); strbuf_release(&buf); - reader_close(&rd); } -static void test_table_read_write_sequential(void) +static void t_table_read_write_sequential(void) { char **names; struct strbuf buf = STRBUF_INIT; int N = 50; - struct reftable_iterator it = { NULL }; - struct reftable_block_source source = { NULL }; + struct reftable_iterator it = { 0 }; + struct reftable_block_source source = { 0 }; - struct reftable_reader rd = { 0 }; + struct reftable_reader *reader; int err = 0; int j = 0; @@@ -366,32 -360,35 +366,32 @@@ block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.ref"); + err = reftable_reader_new(&reader, &source, "file.ref"); - EXPECT_ERR(err); + check(!err); - reftable_reader_init_ref_iterator(&rd, &it); + reftable_reader_init_ref_iterator(reader, &it); err = reftable_iterator_seek_ref(&it, ""); - EXPECT_ERR(err); + check(!err); - while (1) { - struct reftable_ref_record ref = { NULL }; + for (j = 0; ; j++) { + struct reftable_ref_record ref = { 0 }; int r = reftable_iterator_next_ref(&it, &ref); - EXPECT(r >= 0); - if (r > 0) { + check_int(r, >=, 0); + if (r > 0) break; - } - EXPECT(0 == strcmp(names[j], ref.refname)); - EXPECT(update_index == ref.update_index); - - j++; + check_str(names[j], ref.refname); + check_int(update_index, ==, ref.update_index); reftable_ref_record_release(&ref); } - EXPECT(j == N); + check_int(j, ==, N); + reftable_iterator_destroy(&it); + reftable_reader_decref(reader); strbuf_release(&buf); free_names(names); - - reader_close(&rd); } -static void test_table_write_small_table(void) +static void t_table_write_small_table(void) { char **names; struct strbuf buf = STRBUF_INIT; @@@ -407,30 -404,34 +407,30 @@@ static void t_table_read_api(void char **names; struct strbuf buf = STRBUF_INIT; int N = 50; - struct reftable_reader rd = { 0 }; + struct reftable_reader *reader; - struct reftable_block_source source = { NULL }; + struct reftable_block_source source = { 0 }; int err; - int i; - struct reftable_log_record log = { NULL }; - struct reftable_iterator it = { NULL }; + struct reftable_log_record log = { 0 }; + struct reftable_iterator it = { 0 }; write_table(&names, &buf, N, 256, GIT_SHA1_FORMAT_ID); block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.ref"); + err = reftable_reader_new(&reader, &source, "file.ref"); - EXPECT_ERR(err); + check(!err); - reftable_reader_init_ref_iterator(&rd, &it); + reftable_reader_init_ref_iterator(reader, &it); err = reftable_iterator_seek_ref(&it, names[0]); - EXPECT_ERR(err); + check(!err); err = reftable_iterator_next_log(&it, &log); - EXPECT(err == REFTABLE_API_ERROR); + check_int(err, ==, REFTABLE_API_ERROR); strbuf_release(&buf); - for (i = 0; i < N; i++) { - reftable_free(names[i]); - } + free_names(names); reftable_iterator_destroy(&it); - reader_close(&rd); - reftable_free(names); + reftable_reader_decref(reader); strbuf_release(&buf); } @@@ -439,8 -440,8 +439,8 @@@ static void t_table_read_write_seek(in char **names; struct strbuf buf = STRBUF_INIT; int N = 50; - struct reftable_reader rd = { 0 }; + struct reftable_reader *reader; - struct reftable_block_source source = { NULL }; + struct reftable_block_source source = { 0 }; int err; int i = 0; @@@ -452,24 -453,25 +452,25 @@@ block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.ref"); + err = reftable_reader_new(&reader, &source, "file.ref"); - EXPECT_ERR(err); - EXPECT(hash_id == reftable_reader_hash_id(reader)); + check(!err); - check_int(hash_id, ==, reftable_reader_hash_id(&rd)); ++ check_int(hash_id, ==, reftable_reader_hash_id(reader)); - if (!index) - rd.ref_offsets.index_offset = 0; - else - check_int(rd.ref_offsets.index_offset, >, 0); + if (!index) { + reader->ref_offsets.index_offset = 0; + } else { - EXPECT(reader->ref_offsets.index_offset > 0); ++ check_int(reader->ref_offsets.index_offset, >, 0); + } for (i = 1; i < N; i++) { - reftable_reader_init_ref_iterator(&rd, &it); + reftable_reader_init_ref_iterator(reader, &it); err = reftable_iterator_seek_ref(&it, names[i]); - EXPECT_ERR(err); + check(!err); err = reftable_iterator_next_ref(&it, &ref); - EXPECT_ERR(err); - EXPECT(0 == strcmp(names[i], ref.refname)); - EXPECT(REFTABLE_REF_VAL1 == ref.value_type); - EXPECT(i == ref.value.val1[0]); + check(!err); + check_str(names[i], ref.refname); + check_int(REFTABLE_REF_VAL1, ==, ref.value_type); + check_int(i, ==, ref.value.val1[0]); reftable_ref_record_release(&ref); reftable_iterator_destroy(&it); @@@ -478,40 -480,43 +479,40 @@@ strbuf_addstr(&pastLast, names[N - 1]); strbuf_addstr(&pastLast, "/"); - reftable_reader_init_ref_iterator(&rd, &it); + reftable_reader_init_ref_iterator(reader, &it); err = reftable_iterator_seek_ref(&it, pastLast.buf); if (err == 0) { - struct reftable_ref_record ref = { NULL }; + struct reftable_ref_record ref = { 0 }; int err = reftable_iterator_next_ref(&it, &ref); - EXPECT(err > 0); + check_int(err, >, 0); } else { - EXPECT(err > 0); + check_int(err, >, 0); } strbuf_release(&pastLast); reftable_iterator_destroy(&it); strbuf_release(&buf); - for (i = 0; i < N; i++) { - reftable_free(names[i]); - } - reftable_free(names); + free_names(names); - reader_close(&rd); + reftable_reader_decref(reader); } -static void test_table_read_write_seek_linear(void) +static void t_table_read_write_seek_linear(void) { - test_table_read_write_seek(0, GIT_SHA1_FORMAT_ID); + t_table_read_write_seek(0, GIT_SHA1_FORMAT_ID); } -static void test_table_read_write_seek_linear_sha256(void) +static void t_table_read_write_seek_linear_sha256(void) { - test_table_read_write_seek(0, GIT_SHA256_FORMAT_ID); + t_table_read_write_seek(0, GIT_SHA256_FORMAT_ID); } -static void test_table_read_write_seek_index(void) +static void t_table_read_write_seek_index(void) { - test_table_read_write_seek(1, GIT_SHA1_FORMAT_ID); + t_table_read_write_seek(1, GIT_SHA1_FORMAT_ID); } -static void test_table_refs_for(int indexed) +static void t_table_refs_for(int indexed) { int N = 50; char **want_names = reftable_calloc(N + 1, sizeof(*want_names)); @@@ -525,8 -530,8 +526,8 @@@ int i = 0; int n; int err; - struct reftable_reader rd; + struct reftable_reader *reader; - struct reftable_block_source source = { NULL }; + struct reftable_block_source source = { 0 }; struct strbuf buf = STRBUF_INIT; struct reftable_writer *w = @@@ -573,47 -579,52 +574,47 @@@ block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.ref"); + err = reftable_reader_new(&reader, &source, "file.ref"); - EXPECT_ERR(err); - if (!indexed) { + check(!err); + if (!indexed) - rd.obj_offsets.is_present = 0; + reader->obj_offsets.is_present = 0; - } - reftable_reader_init_ref_iterator(&rd, &it); + reftable_reader_init_ref_iterator(reader, &it); err = reftable_iterator_seek_ref(&it, ""); - EXPECT_ERR(err); + check(!err); reftable_iterator_destroy(&it); - err = reftable_reader_refs_for(&rd, &it, want_hash); + err = reftable_reader_refs_for(reader, &it, want_hash); - EXPECT_ERR(err); + check(!err); - j = 0; - while (1) { + for (j = 0; ; j++) { int err = reftable_iterator_next_ref(&it, &ref); - EXPECT(err >= 0); - if (err > 0) { + check_int(err, >=, 0); + if (err > 0) break; - } - - EXPECT(j < want_names_len); - EXPECT(0 == strcmp(ref.refname, want_names[j])); - j++; + check_int(j, <, want_names_len); + check_str(ref.refname, want_names[j]); reftable_ref_record_release(&ref); } - EXPECT(j == want_names_len); + check_int(j, ==, want_names_len); strbuf_release(&buf); free_names(want_names); reftable_iterator_destroy(&it); - reader_close(&rd); + reftable_reader_decref(reader); } -static void test_table_refs_for_no_index(void) +static void t_table_refs_for_no_index(void) { - test_table_refs_for(0); + t_table_refs_for(0); } -static void test_table_refs_for_obj_index(void) +static void t_table_refs_for_obj_index(void) { - test_table_refs_for(1); + t_table_refs_for(1); } -static void test_write_empty_table(void) +static void t_write_empty_table(void) { struct reftable_write_options opts = { 0 }; struct strbuf buf = STRBUF_INIT; @@@ -635,18 -646,18 +636,18 @@@ block_source_from_strbuf(&source, &buf); - err = reftable_new_reader(&rd, &source, "filename"); + err = reftable_reader_new(&rd, &source, "filename"); - EXPECT_ERR(err); + check(!err); reftable_reader_init_ref_iterator(rd, &it); err = reftable_iterator_seek_ref(&it, ""); - EXPECT_ERR(err); + check(!err); err = reftable_iterator_next_ref(&it, &rec); - EXPECT(err > 0); + check_int(err, >, 0); reftable_iterator_destroy(&it); - reftable_reader_free(rd); + reftable_reader_decref(rd); strbuf_release(&buf); } @@@ -839,13 -845,13 +840,13 @@@ static void t_write_multiple_indices(vo * for each of the block types. */ stats = reftable_writer_stats(writer); - EXPECT(stats->ref_stats.index_offset > 0); - EXPECT(stats->obj_stats.index_offset > 0); - EXPECT(stats->log_stats.index_offset > 0); + check_int(stats->ref_stats.index_offset, >, 0); + check_int(stats->obj_stats.index_offset, >, 0); + check_int(stats->log_stats.index_offset, >, 0); block_source_from_strbuf(&source, &writer_buf); - err = reftable_new_reader(&reader, &source, "filename"); + err = reftable_reader_new(&reader, &source, "filename"); - EXPECT_ERR(err); + check(!err); /* * Seeking the log uses the log index now. In case there is any @@@ -898,11 -904,11 +899,11 @@@ static void t_write_multi_level_index(v * multi-level index. */ stats = reftable_writer_stats(writer); - EXPECT(stats->ref_stats.max_index_level == 2); + check_int(stats->ref_stats.max_index_level, ==, 2); block_source_from_strbuf(&source, &writer_buf); - err = reftable_new_reader(&reader, &source, "filename"); + err = reftable_reader_new(&reader, &source, "filename"); - EXPECT_ERR(err); + check(!err); /* * Seeking the last ref should work as expected. @@@ -918,30 -924,31 +919,31 @@@ strbuf_release(&buf); } -static void test_corrupt_table_empty(void) +static void t_corrupt_table_empty(void) { struct strbuf buf = STRBUF_INIT; - struct reftable_block_source source = { NULL }; + struct reftable_block_source source = { 0 }; - struct reftable_reader rd = { 0 }; + struct reftable_reader *reader; int err; block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.log"); + err = reftable_reader_new(&reader, &source, "file.log"); - EXPECT(err == REFTABLE_FORMAT_ERROR); + check_int(err, ==, REFTABLE_FORMAT_ERROR); } -static void test_corrupt_table(void) +static void t_corrupt_table(void) { uint8_t zeros[1024] = { 0 }; struct strbuf buf = STRBUF_INIT; - struct reftable_block_source source = { NULL }; + struct reftable_block_source source = { 0 }; - struct reftable_reader rd = { 0 }; + struct reftable_reader *reader; int err; strbuf_add(&buf, zeros, sizeof(zeros)); block_source_from_strbuf(&source, &buf); - err = init_reader(&rd, &source, "file.log"); + err = reftable_reader_new(&reader, &source, "file.log"); - EXPECT(err == REFTABLE_FORMAT_ERROR); + check_int(err, ==, REFTABLE_FORMAT_ERROR); + strbuf_release(&buf); }