From ef9c9ba7e56cd0168ad1a656fe1beb6dde7af13e Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Fri, 16 Aug 2024 18:38:05 +0530 Subject: [PATCH 01/11] t: move reftable/block_test.c to the unit testing framework reftable/block_test.c exercises the functions defined in reftable/block.{c, h}. Migrate reftable/block_test.c to the unit testing framework. Migration involves refactoring the tests to use the unit testing framework instead of reftable's test framework and renaming the tests to follow the unit-tests' naming conventions. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- Makefile | 2 +- reftable/reftable-tests.h | 1 - t/helper/test-reftable.c | 1 - .../unit-tests/t-reftable-block.c | 45 +++++++++---------- 4 files changed, 22 insertions(+), 27 deletions(-) rename reftable/block_test.c => t/unit-tests/t-reftable-block.c (76%) diff --git a/Makefile b/Makefile index 13890710f80852..a30cd636f810bd 100644 --- a/Makefile +++ b/Makefile @@ -1340,6 +1340,7 @@ UNIT_TEST_PROGRAMS += t-oidmap UNIT_TEST_PROGRAMS += t-oidtree UNIT_TEST_PROGRAMS += t-prio-queue UNIT_TEST_PROGRAMS += t-reftable-basics +UNIT_TEST_PROGRAMS += t-reftable-block UNIT_TEST_PROGRAMS += t-reftable-merged UNIT_TEST_PROGRAMS += t-reftable-pq UNIT_TEST_PROGRAMS += t-reftable-record @@ -2681,7 +2682,6 @@ REFTABLE_OBJS += reftable/stack.o REFTABLE_OBJS += reftable/tree.o REFTABLE_OBJS += reftable/writer.o -REFTABLE_TEST_OBJS += reftable/block_test.o REFTABLE_TEST_OBJS += reftable/dump.o REFTABLE_TEST_OBJS += reftable/readwrite_test.o REFTABLE_TEST_OBJS += reftable/stack_test.o diff --git a/reftable/reftable-tests.h b/reftable/reftable-tests.h index 4b666810af568f..3d9118b91b84b7 100644 --- a/reftable/reftable-tests.h +++ b/reftable/reftable-tests.h @@ -10,7 +10,6 @@ license that can be found in the LICENSE file or at #define REFTABLE_TESTS_H int basics_test_main(int argc, const char **argv); -int block_test_main(int argc, const char **argv); int record_test_main(int argc, const char **argv); int readwrite_test_main(int argc, const char **argv); int stack_test_main(int argc, const char **argv); diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c index 623cf3f0f5ebaa..7bdd18430b29fb 100644 --- a/t/helper/test-reftable.c +++ b/t/helper/test-reftable.c @@ -5,7 +5,6 @@ int cmd__reftable(int argc, const char **argv) { /* test from simple to complex. */ - block_test_main(argc, argv); readwrite_test_main(argc, argv); stack_test_main(argc, argv); return 0; diff --git a/reftable/block_test.c b/t/unit-tests/t-reftable-block.c similarity index 76% rename from reftable/block_test.c rename to t/unit-tests/t-reftable-block.c index 90aecd5a7c6f43..f2b9a8a6f4231f 100644 --- a/reftable/block_test.c +++ b/t/unit-tests/t-reftable-block.c @@ -6,17 +6,13 @@ license that can be found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd */ -#include "block.h" +#include "test-lib.h" +#include "reftable/block.h" +#include "reftable/blocksource.h" +#include "reftable/constants.h" +#include "reftable/reftable-error.h" -#include "system.h" -#include "blocksource.h" -#include "basics.h" -#include "constants.h" -#include "record.h" -#include "test_framework.h" -#include "reftable-tests.h" - -static void test_block_read_write(void) +static void t_block_read_write(void) { const int header_off = 21; /* random */ char *names[30]; @@ -45,7 +41,7 @@ static void test_block_read_write(void) rec.u.ref.refname = (char *) ""; rec.u.ref.value_type = REFTABLE_REF_DELETION; n = block_writer_add(&bw, &rec); - EXPECT(n == REFTABLE_API_ERROR); + check_int(n, ==, REFTABLE_API_ERROR); for (i = 0; i < N; i++) { char name[100]; @@ -59,11 +55,11 @@ static void test_block_read_write(void) n = block_writer_add(&bw, &rec); rec.u.ref.refname = NULL; rec.u.ref.value_type = REFTABLE_REF_DELETION; - EXPECT(n == 0); + check_int(n, ==, 0); } n = block_writer_finish(&bw); - EXPECT(n > 0); + check_int(n, >, 0); block_writer_release(&bw); @@ -73,11 +69,11 @@ static void test_block_read_write(void) while (1) { int r = block_iter_next(&it, &rec); - EXPECT(r >= 0); + check_int(r, >=, 0); if (r > 0) { break; } - EXPECT_STREQ(names[j], rec.u.ref.refname); + check_str(names[j], rec.u.ref.refname); j++; } @@ -90,20 +86,20 @@ static void test_block_read_write(void) strbuf_addstr(&want, names[i]); n = block_iter_seek_key(&it, &br, &want); - EXPECT(n == 0); + check_int(n, ==, 0); n = block_iter_next(&it, &rec); - EXPECT(n == 0); + check_int(n, ==, 0); - EXPECT_STREQ(names[i], rec.u.ref.refname); + check_str(names[i], rec.u.ref.refname); want.len--; n = block_iter_seek_key(&it, &br, &want); - EXPECT(n == 0); + check_int(n, ==, 0); n = block_iter_next(&it, &rec); - EXPECT(n == 0); - EXPECT_STREQ(names[10 * (i / 10)], rec.u.ref.refname); + check_int(n, ==, 0); + check_str(names[10 * (i / 10)], rec.u.ref.refname); block_iter_close(&it); } @@ -116,8 +112,9 @@ static void test_block_read_write(void) } } -int block_test_main(int argc, const char *argv[]) +int cmd_main(int argc, const char *argv[]) { - RUN_TEST(test_block_read_write); - return 0; + TEST(t_block_read_write(), "read-write operations on blocks work"); + + return test_done(); } From 303a78fe066a249343b991d87db5d4d89ec8d635 Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Fri, 16 Aug 2024 18:45:22 +0530 Subject: [PATCH 02/11] t: harmonize t-reftable-block.c with coding guidelines Harmonize the newly ported test unit-tests/t-reftable-block.c with the following guidelines: - Single line 'for' statements must omit curly braces. - Structs must be 0-initialized with '= { 0 }' instead of '= { NULL }'. - Array sizes and indices should preferably be of type 'size_t'and not 'int'. - Return code variable should preferably be named 'ret', not 'n'. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 52 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index f2b9a8a6f4231f..b1b238ac2a5d99 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -16,20 +16,20 @@ static void t_block_read_write(void) { const int header_off = 21; /* random */ char *names[30]; - const int N = ARRAY_SIZE(names); - const int block_size = 1024; - struct reftable_block block = { NULL }; + const size_t N = ARRAY_SIZE(names); + 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, }; - int i = 0; - int n; + size_t i = 0; + int ret; struct block_reader br = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - int j = 0; + size_t j = 0; struct strbuf want = STRBUF_INIT; REFTABLE_CALLOC_ARRAY(block.data, block_size); @@ -40,26 +40,26 @@ static void t_block_read_write(void) rec.u.ref.refname = (char *) ""; rec.u.ref.value_type = REFTABLE_REF_DELETION; - n = block_writer_add(&bw, &rec); - check_int(n, ==, REFTABLE_API_ERROR); + ret = block_writer_add(&bw, &rec); + check_int(ret, ==, REFTABLE_API_ERROR); for (i = 0; i < N; i++) { char name[100]; - snprintf(name, sizeof(name), "branch%02d", i); + snprintf(name, sizeof(name), "branch%02"PRIuMAX, (uintmax_t)i); rec.u.ref.refname = name; rec.u.ref.value_type = REFTABLE_REF_VAL1; memset(rec.u.ref.value.val1, i, GIT_SHA1_RAWSZ); names[i] = xstrdup(name); - n = block_writer_add(&bw, &rec); + ret = block_writer_add(&bw, &rec); rec.u.ref.refname = NULL; rec.u.ref.value_type = REFTABLE_REF_DELETION; - check_int(n, ==, 0); + check_int(ret, ==, 0); } - n = block_writer_finish(&bw); - check_int(n, >, 0); + ret = block_writer_finish(&bw); + check_int(ret, >, 0); block_writer_release(&bw); @@ -68,9 +68,10 @@ static void t_block_read_write(void) block_iter_seek_start(&it, &br); while (1) { - int r = block_iter_next(&it, &rec); - check_int(r, >=, 0); - if (r > 0) { + ret = block_iter_next(&it, &rec); + check_int(ret, >=, 0); + if (ret > 0) { + check_int(i, ==, N); break; } check_str(names[j], rec.u.ref.refname); @@ -85,20 +86,20 @@ static void t_block_read_write(void) strbuf_reset(&want); strbuf_addstr(&want, names[i]); - n = block_iter_seek_key(&it, &br, &want); - check_int(n, ==, 0); + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); - n = block_iter_next(&it, &rec); - check_int(n, ==, 0); + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); check_str(names[i], rec.u.ref.refname); want.len--; - n = block_iter_seek_key(&it, &br, &want); - check_int(n, ==, 0); + ret = block_iter_seek_key(&it, &br, &want); + check_int(ret, ==, 0); - n = block_iter_next(&it, &rec); - check_int(n, ==, 0); + ret = block_iter_next(&it, &rec); + check_int(ret, ==, 0); check_str(names[10 * (i / 10)], rec.u.ref.refname); block_iter_close(&it); @@ -107,9 +108,8 @@ static void t_block_read_write(void) reftable_record_release(&rec); reftable_block_done(&br.block); strbuf_release(&want); - for (i = 0; i < N; i++) { + for (i = 0; i < N; i++) reftable_free(names[i]); - } } int cmd_main(int argc, const char *argv[]) From a66822cfb484cf2297cbac3ff8438deb54c69f3d Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Fri, 14 Jun 2024 13:55:26 +0530 Subject: [PATCH 03/11] t-reftable-block: release used block reader Used block readers must be released using block_reader_release() to prevent the occurence of a memory leak. Make test_block_read_write() conform to this statement. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 1 + 1 file changed, 1 insertion(+) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index b1b238ac2a5d99..eafe1fdee9b609 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -105,6 +105,7 @@ static void t_block_read_write(void) block_iter_close(&it); } + block_reader_release(&br); reftable_record_release(&rec); reftable_block_done(&br.block); strbuf_release(&want); From 334574f42338c30ee297422169adf8d9c4bc4959 Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Mon, 10 Jun 2024 20:25:58 +0530 Subject: [PATCH 04/11] t-reftable-block: use reftable_record_equal() instead of check_str() In the current testing setup, operations like read and write for reftable blocks as defined by reftable/block.{c, h} are verified by comparing only the keys of input and output reftable records. This is not ideal because there can exist inequal reftable records with the same key. Use the dedicated function for record comparison, reftable_record_equal(), instead of key-based comparison. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index eafe1fdee9b609..b106d3c1e478ed 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -15,8 +15,8 @@ license that can be found in the LICENSE file or at static void t_block_read_write(void) { const int header_off = 21; /* random */ - char *names[30]; - const size_t N = ARRAY_SIZE(names); + 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 = { @@ -47,11 +47,11 @@ static void t_block_read_write(void) char name[100]; snprintf(name, sizeof(name), "branch%02"PRIuMAX, (uintmax_t)i); - rec.u.ref.refname = name; + rec.u.ref.refname = xstrdup(name); rec.u.ref.value_type = REFTABLE_REF_VAL1; memset(rec.u.ref.value.val1, i, GIT_SHA1_RAWSZ); - names[i] = xstrdup(name); + recs[i] = rec; ret = block_writer_add(&bw, &rec); rec.u.ref.refname = NULL; rec.u.ref.value_type = REFTABLE_REF_DELETION; @@ -74,7 +74,7 @@ static void t_block_read_write(void) check_int(i, ==, N); break; } - check_str(names[j], rec.u.ref.refname); + check(reftable_record_equal(&recs[j], &rec, GIT_SHA1_RAWSZ)); j++; } @@ -84,7 +84,7 @@ static void t_block_read_write(void) for (i = 0; i < N; i++) { struct block_iter it = BLOCK_ITER_INIT; strbuf_reset(&want); - strbuf_addstr(&want, names[i]); + strbuf_addstr(&want, recs[i].u.ref.refname); ret = block_iter_seek_key(&it, &br, &want); check_int(ret, ==, 0); @@ -92,7 +92,7 @@ static void t_block_read_write(void) ret = block_iter_next(&it, &rec); check_int(ret, ==, 0); - check_str(names[i], rec.u.ref.refname); + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); want.len--; ret = block_iter_seek_key(&it, &br, &want); @@ -100,7 +100,7 @@ static void t_block_read_write(void) ret = block_iter_next(&it, &rec); check_int(ret, ==, 0); - check_str(names[10 * (i / 10)], rec.u.ref.refname); + check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ)); block_iter_close(&it); } @@ -110,7 +110,7 @@ static void t_block_read_write(void) reftable_block_done(&br.block); strbuf_release(&want); for (i = 0; i < N; i++) - reftable_free(names[i]); + reftable_record_release(&recs[i]); } int cmd_main(int argc, const char *argv[]) From 7a84242c06fc52d5ba072627c4b3b3fbbf57022e Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Thu, 13 Jun 2024 12:06:14 +0530 Subject: [PATCH 05/11] t-reftable-block: use reftable_record_key() instead of strbuf_addstr() In the current testing setup, the record key required for many block iterator functions is manually stored in a strbuf struct and then passed to these functions. This is not ideal when there exists a dedicated function to encode a record's key into a strbuf, namely reftable_record_key(). Use this function instead of manual encoding. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index b106d3c1e478ed..5887e9205d9d92 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -83,8 +83,7 @@ static void t_block_read_write(void) for (i = 0; i < N; i++) { struct block_iter it = BLOCK_ITER_INIT; - strbuf_reset(&want); - strbuf_addstr(&want, recs[i].u.ref.refname); + reftable_record_key(&recs[i], &want); ret = block_iter_seek_key(&it, &br, &want); check_int(ret, ==, 0); From 15698469a55e66f95dbaf6d51a05f10ddcb6ddad Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Thu, 13 Jun 2024 14:00:40 +0530 Subject: [PATCH 06/11] t-reftable-block: use block_iter_reset() instead of block_iter_close() block_iter_reset() restores a block iterator to its state at the time of initialization without freeing any memory while block_iter_close() deallocates the memory for the iterator. In the current testing setup, a block iterator is allocated and deallocated for every iteration of a loop, which hurts performance. Improve upon this by using block_iter_reset() at the start of each iteration instead. This has the added benifit of testing block_iter_reset(), which currently remains untested. Similarly, remove reftable_record_release() for a reftable record that is still in use. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index 5887e9205d9d92..ad3d128ea72086 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -78,11 +78,8 @@ static void t_block_read_write(void) j++; } - reftable_record_release(&rec); - block_iter_close(&it); - for (i = 0; i < N; i++) { - struct block_iter it = BLOCK_ITER_INIT; + block_iter_reset(&it); reftable_record_key(&recs[i], &want); ret = block_iter_seek_key(&it, &br, &want); @@ -100,11 +97,10 @@ static void t_block_read_write(void) ret = block_iter_next(&it, &rec); check_int(ret, ==, 0); check(reftable_record_equal(&recs[10 * (i / 10)], &rec, GIT_SHA1_RAWSZ)); - - block_iter_close(&it); } block_reader_release(&br); + block_iter_close(&it); reftable_record_release(&rec); reftable_block_done(&br.block); strbuf_release(&want); From d1b6f6dd4a1d8e6f95b15ebaa985538d058ca87d Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Tue, 18 Jun 2024 19:06:49 +0530 Subject: [PATCH 07/11] t-reftable-block: use xstrfmt() instead of xstrdup() Use xstrfmt() to assign a formatted string to a ref record's refname instead of xstrdup(). This helps save the overhead of a local 'char' buffer as well as makes the test more compact. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index ad3d128ea72086..81484bc646b376 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -44,10 +44,7 @@ static void t_block_read_write(void) check_int(ret, ==, REFTABLE_API_ERROR); for (i = 0; i < N; i++) { - char name[100]; - snprintf(name, sizeof(name), "branch%02"PRIuMAX, (uintmax_t)i); - - rec.u.ref.refname = xstrdup(name); + 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); From 7bae0c30c790fe6945c1e484b97ab943e981aeb6 Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Tue, 11 Jun 2024 19:41:49 +0530 Subject: [PATCH 08/11] t-reftable-block: remove unnecessary variable 'j' Currently, there are two variables for array indices, 'i' and 'j'. The variable 'j' is used only once and can be easily replaced with 'i'. Get rid of 'j' and replace its occurence with 'i'. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index 81484bc646b376..6aa86a3edf45af 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -29,7 +29,6 @@ static void t_block_read_write(void) int ret; struct block_reader br = { 0 }; struct block_iter it = BLOCK_ITER_INIT; - size_t j = 0; struct strbuf want = STRBUF_INIT; REFTABLE_CALLOC_ARRAY(block.data, block_size); @@ -64,15 +63,14 @@ static void t_block_read_write(void) block_iter_seek_start(&it, &br); - while (1) { + 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[j], &rec, GIT_SHA1_RAWSZ)); - j++; + check(reftable_record_equal(&recs[i], &rec, GIT_SHA1_RAWSZ)); } for (i = 0; i < N; i++) { From 4cd198101676cb5f9a6809d0de2c7aa279190f47 Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Wed, 12 Jun 2024 11:01:23 +0530 Subject: [PATCH 09/11] t-reftable-block: add tests for log blocks In the current testing setup, block operations are only exercised for ref blocks. Add another test that exercises these operations for log blocks as well. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 93 ++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index 6aa86a3edf45af..4c4fb39ab44c4b 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -12,7 +12,7 @@ license that can be found in the LICENSE file or at #include "reftable/constants.h" #include "reftable/reftable-error.h" -static void t_block_read_write(void) +static void t_ref_block_read_write(void) { const int header_off = 21; /* random */ struct reftable_record recs[30]; @@ -103,9 +103,98 @@ static void t_block_read_write(void) 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]); +} + int cmd_main(int argc, const char *argv[]) { - TEST(t_block_read_write(), "read-write operations on blocks work"); + TEST(t_log_block_read_write(), "read-write operations on log blocks work"); + TEST(t_ref_block_read_write(), "read-write operations on ref blocks work"); return test_done(); } From 4e9752e72a684c555e8f0dba5402fd13caa37d5a Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Wed, 12 Jun 2024 13:34:52 +0530 Subject: [PATCH 10/11] t-reftable-block: add tests for obj blocks In the current testing setup, block operations are left unexercised for obj blocks. Add a test that exercises these operations for obj blocks. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 82 +++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index 4c4fb39ab44c4b..beb2d6f81b4949 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -191,9 +191,91 @@ static void t_log_block_read_write(void) 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]); +} + int cmd_main(int argc, const char *argv[]) { 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(); From db62f23594f3e42f37a303446005e852503213a0 Mon Sep 17 00:00:00 2001 From: Chandra Pratap Date: Thu, 13 Jun 2024 11:32:20 +0530 Subject: [PATCH 11/11] t-reftable-block: add tests for index blocks In the current testing setup, block operations are left unexercised for index blocks. Add a test that exercises these operations for index blocks. Mentored-by: Patrick Steinhardt Mentored-by: Christian Couder Signed-off-by: Chandra Pratap --- t/unit-tests/t-reftable-block.c | 88 +++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/t/unit-tests/t-reftable-block.c b/t/unit-tests/t-reftable-block.c index beb2d6f81b4949..582a8e6036735e 100644 --- a/t/unit-tests/t-reftable-block.c +++ b/t/unit-tests/t-reftable-block.c @@ -272,8 +272,96 @@ static void t_obj_block_read_write(void) 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, const char *argv[]) { + 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");