reftable/stack: test compaction with already-locked tables

We're lacking test coverage for compacting tables when some of the tables that we are about to compact are locked. Add two tests that exercise this, one for auto-compaction and one for full compaction. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Aug 8, 2024 at 16:06 UTC 8030100bdafc508eaa7900ebcfd67a2d6b02749e
1 file changed +77
reftable/stack_test.c
+77
@@ -891,6 +891,45 @@ static void test_reftable_stack_auto_compaction(void)
891 clear_dir(dir);
892 }
893
894 +static void test_reftable_stack_auto_compaction_with_locked_tables(void)
895 +{
896 + struct reftable_write_options opts = {
897 + .disable_auto_compact = 1,
898 + };
899 + struct reftable_stack *st = NULL;
900 + struct strbuf buf = STRBUF_INIT;
901 + char *dir = get_tmp_dir(__LINE__);
902 + int err;
903 +
904 + err = reftable_new_stack(&st, dir, &opts);
905 + EXPECT_ERR(err);
906 +
907 + write_n_ref_tables(st, 5);
908 + EXPECT(st->merged->stack_len == 5);
909 +
910 + /*
911 + * Given that all tables we have written should be roughly the same
912 + * size, we expect that auto-compaction will want to compact all of the
913 + * tables. Locking any of the tables will keep it from doing so.
914 + */
915 + strbuf_reset(&buf);
916 + strbuf_addf(&buf, "%s/%s.lock", dir, st->readers[2]->name);
917 + write_file_buf(buf.buf, "", 0);
918 +
919 + /*
920 + * Ideally, we'd handle the situation where any of the tables is locked
921 + * gracefully. We don't (yet) do this though and thus fail.
922 + */
923 + err = reftable_stack_auto_compact(st);
924 + EXPECT(err == REFTABLE_LOCK_ERROR);
925 + EXPECT(st->stats.failures == 1);
926 + EXPECT(st->merged->stack_len == 5);
927 +
928 + reftable_stack_destroy(st);
929 + strbuf_release(&buf);
930 + clear_dir(dir);
931 +}
932 +
933 static void test_reftable_stack_add_performs_auto_compaction(void)
934 {
935 struct reftable_write_options opts = { 0 };
@@ -939,6 +978,42 @@ static void test_reftable_stack_add_performs_auto_compaction(void)
978 clear_dir(dir);
979 }
980
981 +static void test_reftable_stack_compaction_with_locked_tables(void)
982 +{
983 + struct reftable_write_options opts = {
984 + .disable_auto_compact = 1,
985 + };
986 + struct reftable_stack *st = NULL;
987 + struct strbuf buf = STRBUF_INIT;
988 + char *dir = get_tmp_dir(__LINE__);
989 + int err;
990 +
991 + err = reftable_new_stack(&st, dir, &opts);
992 + EXPECT_ERR(err);
993 +
994 + write_n_ref_tables(st, 3);
995 + EXPECT(st->merged->stack_len == 3);
996 +
997 + /* Lock one of the tables that we're about to compact. */
998 + strbuf_reset(&buf);
999 + strbuf_addf(&buf, "%s/%s.lock", dir, st->readers[1]->name);
1000 + write_file_buf(buf.buf, "", 0);
1001 +
1002 + /*
1003 + * Compaction is expected to fail given that we were not able to
1004 + * compact all tables.
1005 + */
1006 + err = reftable_stack_compact_all(st, NULL);
1007 + EXPECT(err == REFTABLE_LOCK_ERROR);
1008 + /* TODO: this is wrong, we should get notified about the failure. */
1009 + EXPECT(st->stats.failures == 0);
1010 + EXPECT(st->merged->stack_len == 3);
1011 +
1012 + reftable_stack_destroy(st);
1013 + strbuf_release(&buf);
1014 + clear_dir(dir);
1015 +}
1016 +
1017 static void test_reftable_stack_compaction_concurrent(void)
1018 {
1019 struct reftable_write_options opts = { 0 };
@@ -1016,9 +1091,11 @@ int stack_test_main(int argc, const char *argv[])
1091 RUN_TEST(test_reftable_stack_add);
1092 RUN_TEST(test_reftable_stack_add_one);
1093 RUN_TEST(test_reftable_stack_auto_compaction);
1094 + RUN_TEST(test_reftable_stack_auto_compaction_with_locked_tables);
1095 RUN_TEST(test_reftable_stack_add_performs_auto_compaction);
1096 RUN_TEST(test_reftable_stack_compaction_concurrent);
1097 RUN_TEST(test_reftable_stack_compaction_concurrent_clean);
1098 + RUN_TEST(test_reftable_stack_compaction_with_locked_tables);
1099 RUN_TEST(test_reftable_stack_hash_id);
1100 RUN_TEST(test_reftable_stack_lock_failure);
1101 RUN_TEST(test_reftable_stack_log_normalize);