diff --git a/tests/odb/backend/backend_helpers.c b/tests/odb/backend/backend_helpers.c new file mode 100644 index 000000000..26537029d --- /dev/null +++ b/tests/odb/backend/backend_helpers.c @@ -0,0 +1,132 @@ +#include "clar_libgit2.h" +#include "git2/sys/odb_backend.h" +#include "backend_helpers.h" + +static int search_object(const fake_object **out, fake_backend *fake, const git_oid *oid, size_t len) +{ + const fake_object *obj = fake->objects; + + while (obj && obj->oid) { + git_oid current_oid; + + git_oid_fromstr(¤t_oid, obj->oid); + + if (git_oid_ncmp(¤t_oid, oid, len) == 0) { + if (out) + *out = obj; + return 0; + } + + obj++; + } + + return GIT_ENOTFOUND; +} + +static int fake_backend__exists(git_odb_backend *backend, const git_oid *oid) +{ + fake_backend *fake; + + fake = (fake_backend *)backend; + + fake->exists_calls++; + + return search_object(NULL, fake, oid, GIT_OID_RAWSZ) == GIT_OK; +} + +static int fake_backend__read( + void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) +{ + const fake_object *obj; + fake_backend *fake; + + fake = (fake_backend *)backend; + + fake->read_calls++; + + if (search_object(&obj, fake, oid, GIT_OID_RAWSZ) == 0) { + *len_p = strlen(obj->content); + *buffer_p = git__strdup(obj->content); + *type_p = GIT_OBJ_BLOB; + return 0; + } + + return GIT_ENOTFOUND; +} + +static int fake_backend__read_header( + size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *oid) +{ + const fake_object *obj; + fake_backend *fake; + + fake = (fake_backend *)backend; + + fake->read_header_calls++; + + if (search_object(&obj, fake, oid, GIT_OID_RAWSZ) == 0) { + *len_p = strlen(obj->content); + *type_p = GIT_OBJ_BLOB; + return 0; + } + + return GIT_ENOTFOUND; +} + +static int fake_backend__read_prefix( + git_oid *out_oid, void **buffer_p, size_t *len_p, git_otype *type_p, + git_odb_backend *backend, const git_oid *short_oid, size_t len) +{ + const fake_object *obj; + fake_backend *fake; + + fake = (fake_backend *)backend; + + fake->read_prefix_calls++; + + if (search_object(&obj, fake, short_oid, len) == 0) { + git_oid_fromstr(out_oid, obj->oid); + *len_p = strlen(obj->content); + *buffer_p = git__strdup(obj->content); + *type_p = GIT_OBJ_BLOB; + return 0; + } + + return GIT_ENOTFOUND; +} + +static void fake_backend__free(git_odb_backend *_backend) +{ + fake_backend *backend; + + backend = (fake_backend *)_backend; + + git__free(backend); +} + +int build_fake_backend( + git_odb_backend **out, + const fake_object *objects) +{ + fake_backend *backend; + + backend = git__calloc(1, sizeof(fake_backend)); + GITERR_CHECK_ALLOC(backend); + + backend->parent.version = GIT_ODB_BACKEND_VERSION; + + backend->parent.refresh = NULL; + backend->objects = objects; + + backend->parent.read = fake_backend__read; + backend->parent.read_prefix = fake_backend__read_prefix; + backend->parent.read_header = fake_backend__read_header; + backend->parent.exists = fake_backend__exists; + backend->parent.free = &fake_backend__free; + + *out = (git_odb_backend *)backend; + + return 0; +} diff --git a/tests/odb/backend/backend_helpers.h b/tests/odb/backend/backend_helpers.h new file mode 100644 index 000000000..6cc1ce90d --- /dev/null +++ b/tests/odb/backend/backend_helpers.h @@ -0,0 +1,21 @@ +#include "git2/sys/odb_backend.h" + +typedef struct { + const char *oid; + const char *content; +} fake_object; + +typedef struct { + git_odb_backend parent; + + int exists_calls; + int read_calls; + int read_header_calls; + int read_prefix_calls; + + const fake_object *objects; +} fake_backend; + +int build_fake_backend( + git_odb_backend **out, + const fake_object *objects); diff --git a/tests/odb/backend/multiple.c b/tests/odb/backend/multiple.c new file mode 100644 index 000000000..1c6068df3 --- /dev/null +++ b/tests/odb/backend/multiple.c @@ -0,0 +1,121 @@ +#include "clar_libgit2.h" +#include "repository.h" +#include "backend_helpers.h" + +#define EXISTING_HASH "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" + +static git_repository *_repo; +static git_odb_object *_obj; +static fake_backend *_fake_empty; +static fake_backend *_fake_filled; + +static git_oid _existing_oid; + +static const fake_object _objects_filled[] = { + { EXISTING_HASH, "" }, + { NULL, NULL } +}; + +static const fake_object _objects_empty[] = { + { NULL, NULL } +}; + +void test_odb_backend_multiple__initialize(void) +{ + git_odb_backend *backend; + + git_oid_fromstr(&_existing_oid, EXISTING_HASH); + + _obj = NULL; + _repo = cl_git_sandbox_init("testrepo.git"); + + cl_git_pass(build_fake_backend(&backend, _objects_filled)); + _fake_filled = (fake_backend *)backend; + + cl_git_pass(build_fake_backend(&backend, _objects_empty)); + _fake_empty = (fake_backend *)backend; +} + +void test_odb_backend_multiple__cleanup(void) +{ + git_odb_object_free(_obj); + cl_git_sandbox_cleanup(); +} + +void test_odb_backend_multiple__read_with_empty_first_succeeds(void) +{ + git_odb *odb; + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_filled, 10)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_empty, 50)); + + cl_git_pass(git_odb_read(&_obj, odb, &_existing_oid)); + + cl_assert_equal_i(1, _fake_filled->read_calls); + cl_assert_equal_i(1, _fake_empty->read_calls); +} + +void test_odb_backend_multiple__read_with_first_matching_stops(void) +{ + git_odb *odb; + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_empty, 10)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_filled, 50)); + + cl_git_pass(git_odb_read(&_obj, odb, &_existing_oid)); + + cl_assert_equal_i(1, _fake_filled->read_calls); + cl_assert_equal_i(0, _fake_empty->read_calls); +} + +void test_odb_backend_multiple__read_prefix_with_first_empty_succeeds(void) +{ + git_odb *odb; + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_filled, 10)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_empty, 50)); + + cl_git_pass(git_odb_read_prefix(&_obj, odb, &_existing_oid, 7)); + + cl_assert_equal_i(1, _fake_filled->read_prefix_calls); + cl_assert_equal_i(1, _fake_empty->read_prefix_calls); +} + +void test_odb_backend_multiple__read_prefix_with_first_matching_reads_both(void) +{ + git_odb *odb; + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_empty, -10)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_filled, 50)); + + cl_git_pass(git_odb_read_prefix(&_obj, odb, &_existing_oid, 7)); + + cl_assert_equal_i(1, _fake_filled->read_prefix_calls); + cl_assert_equal_i(1, _fake_empty->read_prefix_calls); +} + +void test_odb_backend_multiple__read_prefix_with_first_matching_succeeds_without_hash_verification(void) +{ + git_odb *odb; + + git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 0); + + cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_empty, -10)); + cl_git_pass(git_odb_add_backend(odb, (git_odb_backend *)_fake_filled, 50)); + + cl_git_pass(git_odb_read_prefix(&_obj, odb, &_existing_oid, 7)); + + /* + * Both backends should be checked as we have to check + * for collisions + */ + cl_assert_equal_i(1, _fake_filled->read_prefix_calls); + cl_assert_equal_i(1, _fake_empty->read_prefix_calls); + + git_libgit2_opts(GIT_OPT_ENABLE_STRICT_HASH_VERIFICATION, 1); +} diff --git a/tests/odb/backend/nonrefreshing.c b/tests/odb/backend/nonrefreshing.c index f12ac741c..6abc0c6d2 100644 --- a/tests/odb/backend/nonrefreshing.c +++ b/tests/odb/backend/nonrefreshing.c @@ -1,153 +1,41 @@ #include "clar_libgit2.h" -#include "git2/sys/odb_backend.h" #include "repository.h" - -typedef struct fake_backend { - git_odb_backend parent; - - git_error_code error_code; - - int exists_calls; - int read_calls; - int read_header_calls; - int read_prefix_calls; -} fake_backend; +#include "backend_helpers.h" static git_repository *_repo; static fake_backend *_fake; -static git_oid _oid; -#define HASH "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" -#define EMPTY_HASH "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" +#define NONEXISTING_HASH "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" +#define EXISTING_HASH "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" -static int fake_backend__exists(git_odb_backend *backend, const git_oid *oid) -{ - fake_backend *fake; +static const fake_object _objects[] = { + { EXISTING_HASH, "" }, + { NULL, NULL } +}; - GIT_UNUSED(oid); +static git_oid _nonexisting_oid; +static git_oid _existing_oid; - fake = (fake_backend *)backend; - - fake->exists_calls++; - - return (fake->error_code == GIT_OK); -} - -static int fake_backend__read( - void **buffer_p, size_t *len_p, git_otype *type_p, - git_odb_backend *backend, const git_oid *oid) -{ - fake_backend *fake; - - GIT_UNUSED(buffer_p); - GIT_UNUSED(len_p); - GIT_UNUSED(type_p); - GIT_UNUSED(oid); - - fake = (fake_backend *)backend; - - fake->read_calls++; - - *len_p = 0; - *buffer_p = NULL; - *type_p = GIT_OBJ_BLOB; - - return fake->error_code; -} - -static int fake_backend__read_header( - size_t *len_p, git_otype *type_p, - git_odb_backend *backend, const git_oid *oid) -{ - fake_backend *fake; - - GIT_UNUSED(len_p); - GIT_UNUSED(type_p); - GIT_UNUSED(oid); - - fake = (fake_backend *)backend; - - fake->read_header_calls++; - - *len_p = 0; - *type_p = GIT_OBJ_BLOB; - - return fake->error_code; -} - -static int fake_backend__read_prefix( - git_oid *out_oid, void **buffer_p, size_t *len_p, git_otype *type_p, - git_odb_backend *backend, const git_oid *short_oid, size_t len) -{ - fake_backend *fake; - - GIT_UNUSED(buffer_p); - GIT_UNUSED(len_p); - GIT_UNUSED(type_p); - GIT_UNUSED(short_oid); - GIT_UNUSED(len); - - fake = (fake_backend *)backend; - - fake->read_prefix_calls++; - - git_oid_cpy(out_oid, &_oid); - *len_p = 0; - *buffer_p = NULL; - *type_p = GIT_OBJ_BLOB; - - return fake->error_code; -} - -static void fake_backend__free(git_odb_backend *_backend) -{ - fake_backend *backend; - - backend = (fake_backend *)_backend; - - git__free(backend); -} - -static int build_fake_backend( - git_odb_backend **out, - git_error_code error_code) -{ - fake_backend *backend; - - backend = git__calloc(1, sizeof(fake_backend)); - GITERR_CHECK_ALLOC(backend); - - backend->parent.version = GIT_ODB_BACKEND_VERSION; - - backend->parent.refresh = NULL; - backend->error_code = error_code; - - backend->parent.read = fake_backend__read; - backend->parent.read_prefix = fake_backend__read_prefix; - backend->parent.read_header = fake_backend__read_header; - backend->parent.exists = fake_backend__exists; - backend->parent.free = &fake_backend__free; - - *out = (git_odb_backend *)backend; - - return 0; -} - -static void setup_repository_and_backend(git_error_code error_code, const char *hash) +static void setup_repository_and_backend(void) { git_odb *odb = NULL; git_odb_backend *backend = NULL; _repo = cl_git_sandbox_init("testrepo.git"); - cl_git_pass(build_fake_backend(&backend, error_code)); + cl_git_pass(build_fake_backend(&backend, _objects)); cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); cl_git_pass(git_odb_add_backend(odb, backend, 10)); _fake = (fake_backend *)backend; +} - cl_git_pass(git_oid_fromstr(&_oid, hash)); +void test_odb_backend_nonrefreshing__initialize(void) +{ + git_oid_fromstr(&_nonexisting_oid, NONEXISTING_HASH); + git_oid_fromstr(&_existing_oid, EXISTING_HASH); + setup_repository_and_backend(); } void test_odb_backend_nonrefreshing__cleanup(void) @@ -159,10 +47,8 @@ void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_failure(void) { git_odb *odb; - setup_repository_and_backend(GIT_ENOTFOUND, HASH); - cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); - cl_assert_equal_b(false, git_odb_exists(odb, &_oid)); + cl_assert_equal_b(false, git_odb_exists(odb, &_nonexisting_oid)); cl_assert_equal_i(1, _fake->exists_calls); } @@ -171,10 +57,8 @@ void test_odb_backend_nonrefreshing__read_is_invoked_once_on_failure(void) { git_object *obj; - setup_repository_and_backend(GIT_ENOTFOUND, HASH); - cl_git_fail_with( - git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY), + git_object_lookup(&obj, _repo, &_nonexisting_oid, GIT_OBJ_ANY), GIT_ENOTFOUND); cl_assert_equal_i(1, _fake->read_calls); @@ -184,10 +68,8 @@ void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_failure(void) { git_object *obj; - setup_repository_and_backend(GIT_ENOTFOUND, HASH); - cl_git_fail_with( - git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY), + git_object_lookup_prefix(&obj, _repo, &_nonexisting_oid, 7, GIT_OBJ_ANY), GIT_ENOTFOUND); cl_assert_equal_i(1, _fake->read_prefix_calls); @@ -199,12 +81,10 @@ void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_failure(void) size_t len; git_otype type; - setup_repository_and_backend(GIT_ENOTFOUND, HASH); - cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); cl_git_fail_with( - git_odb_read_header(&len, &type, odb, &_oid), + git_odb_read_header(&len, &type, odb, &_nonexisting_oid), GIT_ENOTFOUND); cl_assert_equal_i(1, _fake->read_header_calls); @@ -214,10 +94,8 @@ void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_success(void) { git_odb *odb; - setup_repository_and_backend(GIT_OK, HASH); - cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); - cl_assert_equal_b(true, git_odb_exists(odb, &_oid)); + cl_assert_equal_b(true, git_odb_exists(odb, &_existing_oid)); cl_assert_equal_i(1, _fake->exists_calls); } @@ -226,9 +104,7 @@ void test_odb_backend_nonrefreshing__read_is_invoked_once_on_success(void) { git_object *obj; - setup_repository_and_backend(GIT_OK, EMPTY_HASH); - - cl_git_pass(git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY)); + cl_git_pass(git_object_lookup(&obj, _repo, &_existing_oid, GIT_OBJ_ANY)); cl_assert_equal_i(1, _fake->read_calls); @@ -239,9 +115,7 @@ void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_success(void) { git_object *obj; - setup_repository_and_backend(GIT_OK, EMPTY_HASH); - - cl_git_pass(git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY)); + cl_git_pass(git_object_lookup_prefix(&obj, _repo, &_existing_oid, 7, GIT_OBJ_ANY)); cl_assert_equal_i(1, _fake->read_prefix_calls); @@ -254,11 +128,9 @@ void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_success(void) size_t len; git_otype type; - setup_repository_and_backend(GIT_OK, HASH); - cl_git_pass(git_repository_odb__weakptr(&odb, _repo)); - cl_git_pass(git_odb_read_header(&len, &type, odb, &_oid)); + cl_git_pass(git_odb_read_header(&len, &type, odb, &_existing_oid)); cl_assert_equal_i(1, _fake->read_header_calls); } @@ -267,8 +139,6 @@ void test_odb_backend_nonrefreshing__read_is_invoked_once_when_revparsing_a_full { git_object *obj; - setup_repository_and_backend(GIT_ENOTFOUND, HASH); - cl_git_fail_with( git_revparse_single(&obj, _repo, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"), GIT_ENOTFOUND);