From 5c6cba514253315ffebe001a6afc91d8cffb6225 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 22 Jul 2025 13:00:37 +0200 Subject: [PATCH] tests: wire up reftable tests Wire up reftable tests so that they can be executed by setting the `CLAR_REF_FORMAT` environment variable. This only catches tests that use `cl_git_sandbox_init()`, but that should cover most of our tests. So this infrastructure isn't perfect, but for now it's good enough. We may want to iterate on it in the future. --- deps/clar/clar_libgit2.c | 41 +++++++++++-- tests/libgit2/iterator/workdir.c | 13 ++++- tests/libgit2/refs/basic.c | 5 +- tests/libgit2/refs/create.c | 5 +- tests/libgit2/refs/foreachglob.c | 11 +--- tests/libgit2/refs/namespaces.c | 12 +++- tests/libgit2/refs/reflog/reflog.c | 9 ++- tests/libgit2/refs/revparse.c | 92 ++++++++++++------------------ tests/libgit2/refs/shorthand.c | 5 +- tests/libgit2/refs/transactions.c | 2 + tests/libgit2/threads/refdb.c | 18 +++++- 11 files changed, 128 insertions(+), 85 deletions(-) diff --git a/deps/clar/clar_libgit2.c b/deps/clar/clar_libgit2.c index afea57f25..de3cab5c0 100644 --- a/deps/clar/clar_libgit2.c +++ b/deps/clar/clar_libgit2.c @@ -172,13 +172,42 @@ static git_repository *_cl_repo = NULL; git_repository *cl_git_sandbox_init(const char *sandbox) { - /* Get the name of the sandbox folder which will be created */ - const char *basename = cl_fixture_basename(sandbox); + const char *basename; + char *ref_format; - /* Copy the whole sandbox folder from our fixtures to our test sandbox - * area. After this it can be accessed with `./sandbox` - */ - cl_fixture_sandbox(sandbox); + /* Get the name of the sandbox folder which will be created */ + basename = cl_fixture_basename(sandbox); + + ref_format = cl_getenv("CLAR_REF_FORMAT"); + if (!ref_format || !strcmp(ref_format, "files")) { + /* + * Copy the whole sandbox folder from our fixtures to our + * test sandbox area. After this it can be accessed with + * `./sandbox` + */ + cl_fixture_sandbox(sandbox); + } else if (!strcmp(ref_format, "reftable")) { + struct git_str reftable_sandbox = GIT_STR_INIT; + + cl_git_pass(git_str_joinpath(&reftable_sandbox, "reftable", sandbox)); + if (!git_fs_path_isdir(cl_fixture(reftable_sandbox.ptr))) { + git_str_dispose(&reftable_sandbox); + _cl_sandbox = NULL; + _cl_repo = NULL; + cl_fail("no seed for reftable repository"); + } + + /* + * Copy over the sandbox and rename it so that the basename + * matches the originally requested basename. + */ + cl_fixture_sandbox(reftable_sandbox.ptr); + git_str_dispose(&reftable_sandbox); + } else { + cl_fail("Unexpected ref format"); + } + + git__free(ref_format); _cl_sandbox = sandbox; cl_git_pass(p_chdir(basename)); diff --git a/tests/libgit2/iterator/workdir.c b/tests/libgit2/iterator/workdir.c index 59feb4546..7aed7c397 100644 --- a/tests/libgit2/iterator/workdir.c +++ b/tests/libgit2/iterator/workdir.c @@ -608,7 +608,7 @@ void test_iterator_workdir__filesystem(void) void test_iterator_workdir__filesystem2(void) { git_iterator *i; - static const char *expect_base[] = { + static const char *expect_files[] = { "heads/br2", "heads/dir", "heads/executable", @@ -626,14 +626,21 @@ void test_iterator_workdir__filesystem2(void) "tags/foo/foo/bar", "tags/point_to_blob", "tags/test", - NULL, + }; + static const char *expect_reftable[] = { + "heads", }; g_repo = cl_git_sandbox_init("testrepo"); cl_git_pass(git_iterator_for_filesystem( &i, "testrepo/.git/refs", NULL)); - expect_iterator_items(i, 17, expect_base, 17, expect_base); + if (cl_repo_has_ref_format(g_repo, "files")) + expect_iterator_items(i, ARRAY_SIZE(expect_files), expect_files, + ARRAY_SIZE(expect_files), expect_files); + else + expect_iterator_items(i, ARRAY_SIZE(expect_reftable), expect_reftable, + ARRAY_SIZE(expect_reftable), expect_reftable); git_iterator_free(i); } diff --git a/tests/libgit2/refs/basic.c b/tests/libgit2/refs/basic.c index b1f770b99..25952f4ed 100644 --- a/tests/libgit2/refs/basic.c +++ b/tests/libgit2/refs/basic.c @@ -76,7 +76,10 @@ void test_refs_basic__longpaths(void) /* Adding one more character gives us a path that is too long. */ cl_git_pass(git_str_putc(&refname, 'z')); - cl_git_fail(git_reference_create(&two, g_repo, refname.ptr, &id, 0, NULL)); + if (cl_repo_has_ref_format(g_repo, "files")) + cl_git_fail(git_reference_create(&two, g_repo, refname.ptr, &id, 0, NULL)); + else + cl_git_pass(git_reference_create(&two, g_repo, refname.ptr, &id, 0, NULL)); git_reference_free(one); git_reference_free(two); diff --git a/tests/libgit2/refs/create.c b/tests/libgit2/refs/create.c index 42c43e519..9ff140eb3 100644 --- a/tests/libgit2/refs/create.c +++ b/tests/libgit2/refs/create.c @@ -281,7 +281,10 @@ static void test_win32_name(const char *name) ret = git_reference_create(&new_reference, g_repo, name, &id, 0, NULL); #ifdef GIT_WIN32 - cl_assert_equal_i(GIT_EINVALIDSPEC, ret); + if (cl_repo_has_ref_format(g_repo, "files")) + cl_assert_equal_i(GIT_EINVALIDSPEC, ret); + else + cl_git_pass(ret); #else cl_git_pass(ret); #endif diff --git a/tests/libgit2/refs/foreachglob.c b/tests/libgit2/refs/foreachglob.c index 4f0b91325..227aa74fd 100644 --- a/tests/libgit2/refs/foreachglob.c +++ b/tests/libgit2/refs/foreachglob.c @@ -8,10 +8,9 @@ void test_refs_foreachglob__initialize(void) { git_oid id; - cl_fixture_sandbox("testrepo.git"); - cl_git_pass(git_repository_open(&repo, "testrepo.git")); + repo = cl_git_sandbox_init("testrepo.git"); - cl_git_pass(git_oid_from_string(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644", GIT_OID_SHA1)); + cl_git_pass(git_oid_fromstr(&id, "be3563ae3f795b2b4353bcce3a527ad0a4f7f644")); cl_git_pass(git_reference_create(&fake_remote, repo, "refs/remotes/nulltoken/master", &id, 0, NULL)); } @@ -19,11 +18,7 @@ void test_refs_foreachglob__cleanup(void) { git_reference_free(fake_remote); fake_remote = NULL; - - git_repository_free(repo); - repo = NULL; - - cl_fixture_cleanup("testrepo.git"); + cl_git_sandbox_cleanup(); } static int count_cb(const char *reference_name, void *payload) diff --git a/tests/libgit2/refs/namespaces.c b/tests/libgit2/refs/namespaces.c index 19456b5a4..351978a5e 100644 --- a/tests/libgit2/refs/namespaces.c +++ b/tests/libgit2/refs/namespaces.c @@ -27,10 +27,16 @@ void test_refs_namespaces__get_and_set(void) void test_refs_namespaces__namespace_doesnt_show_normal_refs(void) { - static git_strarray ref_list; + static git_strarray ref_list = { 0 }; cl_git_pass(git_repository_set_namespace(g_repo, "namespace")); - cl_git_pass(git_reference_list(&ref_list, g_repo)); - cl_assert_equal_i(0, ref_list.count); + + if (cl_repo_has_ref_format(g_repo, "reftable")) { + cl_git_fail(git_reference_list(&ref_list, g_repo)); + } else { + cl_git_pass(git_reference_list(&ref_list, g_repo)); + cl_assert_equal_i(0, ref_list.count); + } + git_strarray_dispose(&ref_list); } diff --git a/tests/libgit2/refs/reflog/reflog.c b/tests/libgit2/refs/reflog/reflog.c index ff61a27a2..b57396676 100644 --- a/tests/libgit2/refs/reflog/reflog.c +++ b/tests/libgit2/refs/reflog/reflog.c @@ -285,6 +285,9 @@ void test_refs_reflog_reflog__cannot_write_a_moved_reflog(void) git_str master_log_path = GIT_STR_INIT, moved_log_path = GIT_STR_INIT; git_reflog *reflog; + if (!cl_repo_has_ref_format(g_repo, "files")) + cl_skip(); + cl_git_pass(git_reference_lookup(&master, g_repo, "refs/heads/master")); cl_git_pass(git_reflog_read(&reflog, g_repo, "refs/heads/master")); @@ -332,8 +335,12 @@ void test_refs_reflog_reflog__write_when_explicitly_active(void) git_reference *ref; git_oid id; + if (!cl_repo_has_ref_format(g_repo, "files")) + cl_skip(); + git_oid_from_string(&id, current_master_tip, GIT_OID_SHA1); - git_reference_ensure_log(g_repo, "refs/tags/foo"); + + cl_git_pass(git_reference_ensure_log(g_repo, "refs/tags/foo")); cl_git_pass(git_reference_create(&ref, g_repo, "refs/tags/foo", &id, 1, NULL)); git_reference_free(ref); diff --git a/tests/libgit2/refs/revparse.c b/tests/libgit2/refs/revparse.c index 46d5a7a1f..2c8f9f3ae 100644 --- a/tests/libgit2/refs/revparse.c +++ b/tests/libgit2/refs/revparse.c @@ -131,12 +131,12 @@ static void test_invalid_revspec(const char* invalid_spec) void test_refs_revparse__initialize(void) { - cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); + g_repo = cl_git_sandbox_init("testrepo.git"); } void test_refs_revparse__cleanup(void) { - git_repository_free(g_repo); + cl_git_sandbox_cleanup(); } void test_refs_revparse__nonexistant_object(void) @@ -346,7 +346,8 @@ static void create_fake_stash_reference_and_reflog(git_repository *repo) cl_git_pass(git_reference_rename(&new_master, master, "refs/fakestash", 0, NULL)); git_reference_free(master); - cl_assert_equal_i(true, git_fs_path_isfile(git_str_cstr(&log_path))); + if (cl_repo_has_ref_format(g_repo, "files")) + cl_assert_equal_i(true, git_fs_path_isfile(git_str_cstr(&log_path))); git_str_dispose(&log_path); git_reference_free(new_master); @@ -354,11 +355,9 @@ static void create_fake_stash_reference_and_reflog(git_repository *repo) void test_refs_revparse__reflog_of_a_ref_under_refs(void) { - git_repository *repo = cl_git_sandbox_init("testrepo.git"); + test_object_inrepo("refs/fakestash", NULL, g_repo); - test_object_inrepo("refs/fakestash", NULL, repo); - - create_fake_stash_reference_and_reflog(repo); + create_fake_stash_reference_and_reflog(g_repo); /* * $ git reflog -1 refs/fakestash @@ -373,12 +372,10 @@ void test_refs_revparse__reflog_of_a_ref_under_refs(void) * $ git reflog -1 fakestash@{0} * a65fedf fakestash@{0}: commit: checking in */ - test_object_inrepo("refs/fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - test_object_inrepo("refs/fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - test_object_inrepo("fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - test_object_inrepo("fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - - cl_git_sandbox_cleanup(); + test_object_inrepo("refs/fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", g_repo); + test_object_inrepo("refs/fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", g_repo); + test_object_inrepo("fakestash", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", g_repo); + test_object_inrepo("fakestash@{0}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", g_repo); } void test_refs_revparse__revwalk(void) @@ -593,6 +590,7 @@ void test_refs_revparse__a_not_precise_enough_objectid_returns_EAMBIGUOUS(void) git_index *index; git_object *obj; + cl_git_sandbox_cleanup(); repo = cl_git_sandbox_init("testrepo"); cl_git_mkfile("testrepo/one.txt", "aabqhq\n"); @@ -613,37 +611,33 @@ void test_refs_revparse__a_not_precise_enough_objectid_returns_EAMBIGUOUS(void) void test_refs_revparse__issue_994(void) { - git_repository *repo; git_reference *head, *with_at; git_object *target; - repo = cl_git_sandbox_init("testrepo.git"); + cl_assert_equal_i(GIT_ENOTFOUND, + git_revparse_single(&target, g_repo, "origin/bim_with_3d@11296")); cl_assert_equal_i(GIT_ENOTFOUND, - git_revparse_single(&target, repo, "origin/bim_with_3d@11296")); - - cl_assert_equal_i(GIT_ENOTFOUND, - git_revparse_single(&target, repo, "refs/remotes/origin/bim_with_3d@11296")); + git_revparse_single(&target, g_repo, "refs/remotes/origin/bim_with_3d@11296")); - cl_git_pass(git_repository_head(&head, repo)); + cl_git_pass(git_repository_head(&head, g_repo)); cl_git_pass(git_reference_create( &with_at, - repo, + g_repo, "refs/remotes/origin/bim_with_3d@11296", git_reference_target(head), 0, NULL)); - cl_git_pass(git_revparse_single(&target, repo, "origin/bim_with_3d@11296")); + cl_git_pass(git_revparse_single(&target, g_repo, "origin/bim_with_3d@11296")); git_object_free(target); - cl_git_pass(git_revparse_single(&target, repo, "refs/remotes/origin/bim_with_3d@11296")); + cl_git_pass(git_revparse_single(&target, g_repo, "refs/remotes/origin/bim_with_3d@11296")); git_object_free(target); git_reference_free(with_at); git_reference_free(head); - cl_git_sandbox_cleanup(); } /** @@ -660,25 +654,21 @@ void test_refs_revparse__issue_994(void) */ void test_refs_revparse__try_to_retrieve_branch_before_described_tag(void) { - git_repository *repo; git_reference *branch; git_object *target; char sha[GIT_OID_SHA1_HEXSIZE + 1]; - repo = cl_git_sandbox_init("testrepo.git"); + test_object_inrepo("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd", g_repo); - test_object_inrepo("blah-7-gc47800c", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo); - - cl_git_pass(git_revparse_single(&target, repo, "HEAD~3")); - cl_git_pass(git_branch_create(&branch, repo, "blah-7-gc47800c", (git_commit *)target, 0)); + cl_git_pass(git_revparse_single(&target, g_repo, "HEAD~3")); + cl_git_pass(git_branch_create(&branch, g_repo, "blah-7-gc47800c", (git_commit *)target, 0)); git_oid_tostr(sha, GIT_OID_SHA1_HEXSIZE + 1, git_object_id(target)); - test_object_inrepo("blah-7-gc47800c", sha, repo); + test_object_inrepo("blah-7-gc47800c", sha, g_repo); git_reference_free(branch); git_object_free(target); - cl_git_sandbox_cleanup(); } /** @@ -698,26 +688,22 @@ void test_refs_revparse__try_to_retrieve_branch_before_described_tag(void) */ void test_refs_revparse__try_to_retrieve_sha_before_branch(void) { - git_repository *repo; git_reference *branch; git_object *target; char sha[GIT_OID_SHA1_HEXSIZE + 1]; - repo = cl_git_sandbox_init("testrepo.git"); + test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", g_repo); - test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - - cl_git_pass(git_revparse_single(&target, repo, "HEAD~3")); - cl_git_pass(git_branch_create(&branch, repo, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", (git_commit *)target, 0)); + cl_git_pass(git_revparse_single(&target, g_repo, "HEAD~3")); + cl_git_pass(git_branch_create(&branch, g_repo, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", (git_commit *)target, 0)); git_oid_tostr(sha, GIT_OID_SHA1_HEXSIZE + 1, git_object_id(target)); - test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", repo); - test_object_inrepo("heads/a65fedf39aefe402d3bb6e24df4d4f5fe4547750", sha, repo); + test_object_inrepo("a65fedf39aefe402d3bb6e24df4d4f5fe4547750", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", g_repo); + test_object_inrepo("heads/a65fedf39aefe402d3bb6e24df4d4f5fe4547750", sha, g_repo); git_reference_free(branch); git_object_free(target); - cl_git_sandbox_cleanup(); } /** @@ -734,45 +720,37 @@ void test_refs_revparse__try_to_retrieve_sha_before_branch(void) */ void test_refs_revparse__try_to_retrieve_branch_before_abbrev_sha(void) { - git_repository *repo; git_reference *branch; git_object *target; char sha[GIT_OID_SHA1_HEXSIZE + 1]; - repo = cl_git_sandbox_init("testrepo.git"); + test_object_inrepo("c47800", "c47800c7266a2be04c571c04d5a6614691ea99bd", g_repo); - test_object_inrepo("c47800", "c47800c7266a2be04c571c04d5a6614691ea99bd", repo); - - cl_git_pass(git_revparse_single(&target, repo, "HEAD~3")); - cl_git_pass(git_branch_create(&branch, repo, "c47800", (git_commit *)target, 0)); + cl_git_pass(git_revparse_single(&target, g_repo, "HEAD~3")); + cl_git_pass(git_branch_create(&branch, g_repo, "c47800", (git_commit *)target, 0)); git_oid_tostr(sha, GIT_OID_SHA1_HEXSIZE + 1, git_object_id(target)); - test_object_inrepo("c47800", sha, repo); + test_object_inrepo("c47800", sha, g_repo); git_reference_free(branch); git_object_free(target); - cl_git_sandbox_cleanup(); } void test_refs_revparse__at_at_end_of_refname(void) { - git_repository *repo; git_reference *branch; git_object *target; - repo = cl_git_sandbox_init("testrepo.git"); - - cl_git_pass(git_revparse_single(&target, repo, "HEAD")); - cl_git_pass(git_branch_create(&branch, repo, "master@", (git_commit *)target, 0)); + cl_git_pass(git_revparse_single(&target, g_repo, "HEAD")); + cl_git_pass(git_branch_create(&branch, g_repo, "master@", (git_commit *)target, 0)); git_object_free(target); - test_id_inrepo("master@", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVSPEC_SINGLE, repo); + test_id_inrepo("master@", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVSPEC_SINGLE, g_repo); - cl_git_fail_with(GIT_ENOTFOUND, git_revparse_single(&target, repo, "foo@")); + cl_git_fail_with(GIT_ENOTFOUND, git_revparse_single(&target, g_repo, "foo@")); git_reference_free(branch); - cl_git_sandbox_cleanup(); } void test_refs_revparse__range(void) diff --git a/tests/libgit2/refs/shorthand.c b/tests/libgit2/refs/shorthand.c index e008adc74..6cf1d002b 100644 --- a/tests/libgit2/refs/shorthand.c +++ b/tests/libgit2/refs/shorthand.c @@ -15,13 +15,12 @@ void test_refs_shorthand__0(void) { git_repository *repo; - cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); - + repo = cl_git_sandbox_init("testrepo.git"); assert_shorthand(repo, "refs/heads/master", "master"); assert_shorthand(repo, "refs/tags/test", "test"); assert_shorthand(repo, "refs/remotes/test/master", "test/master"); assert_shorthand(repo, "refs/notes/fanout", "notes/fanout"); - git_repository_free(repo); + cl_git_sandbox_cleanup(); } diff --git a/tests/libgit2/refs/transactions.c b/tests/libgit2/refs/transactions.c index 17c0b22ed..37d4f2238 100644 --- a/tests/libgit2/refs/transactions.c +++ b/tests/libgit2/refs/transactions.c @@ -8,6 +8,8 @@ void test_refs_transactions__initialize(void) { g_repo = cl_git_sandbox_init("testrepo"); cl_git_pass(git_transaction_new(&g_tx, g_repo)); + if (!cl_repo_has_ref_format(g_repo, "files")) + cl_skip(); } void test_refs_transactions__cleanup(void) diff --git a/tests/libgit2/threads/refdb.c b/tests/libgit2/threads/refdb.c index a4630df6a..3b481d779 100644 --- a/tests/libgit2/threads/refdb.c +++ b/tests/libgit2/threads/refdb.c @@ -90,7 +90,7 @@ static void *create_refs(void *arg) cl_git_thread_pass(data, git_repository_refdb(&refdb, repo)); do { error = git_refdb_compress(refdb); - } while (error == GIT_ELOCKED); + } while (error == GIT_ELOCKED || error == GIT_EMODIFIED); cl_git_thread_pass(data, error); git_refdb_free(refdb); } @@ -136,7 +136,7 @@ static void *delete_refs(void *arg) cl_git_thread_pass(data, git_repository_refdb(&refdb, repo)); do { error = git_refdb_compress(refdb); - } while (error == GIT_ELOCKED); + } while (error == GIT_ELOCKED || error == GIT_EMODIFIED); cl_git_thread_pass(data, error); git_refdb_free(refdb); } @@ -162,6 +162,20 @@ void test_threads_refdb__edit_while_iterate(void) g_repo = cl_git_sandbox_init("testrepo2"); +#ifdef GIT_WIN32 + /* + * On Windows we still have issues with renaming the "table.list" file + * into place. This will require a bit of a rework of how we open files + * so that they are always opened with `FILE_SHARE_DELETE`. + * Furthermore, we'll have to start using POSIX-semantics when renaming + * files. + * + * For now, we just accept that this doesn't yet work. + */ + if (cl_repo_has_ref_format(g_repo, "reftable")) + cl_skip(); +#endif + cl_git_pass(git_reference_name_to_id(&head, g_repo, "HEAD")); /* make a bunch of references */