summaryrefslogtreecommitdiff
path: root/tests/odb
diff options
context:
space:
mode:
Diffstat (limited to 'tests/odb')
-rw-r--r--tests/odb/alternates.c80
-rw-r--r--tests/odb/backend/nonrefreshing.c274
-rw-r--r--tests/odb/foreach.c80
-rw-r--r--tests/odb/loose.c146
-rw-r--r--tests/odb/loose_data.h522
-rw-r--r--tests/odb/mixed.c93
-rw-r--r--tests/odb/pack_data.h151
-rw-r--r--tests/odb/pack_data_one.h19
-rw-r--r--tests/odb/packed.c79
-rw-r--r--tests/odb/packed_one.c60
-rw-r--r--tests/odb/sorting.c69
-rw-r--r--tests/odb/streamwrite.c56
12 files changed, 1629 insertions, 0 deletions
diff --git a/tests/odb/alternates.c b/tests/odb/alternates.c
new file mode 100644
index 000000000..c75f6feaa
--- /dev/null
+++ b/tests/odb/alternates.c
@@ -0,0 +1,80 @@
+#include "clar_libgit2.h"
+#include "odb.h"
+#include "filebuf.h"
+
+static git_buf destpath, filepath;
+static const char *paths[] = {
+ "A.git", "B.git", "C.git", "D.git", "E.git", "F.git", "G.git"
+};
+static git_filebuf file;
+static git_repository *repo;
+
+void test_odb_alternates__cleanup(void)
+{
+ size_t i;
+
+ git_buf_free(&destpath);
+ git_buf_free(&filepath);
+
+ for (i = 0; i < ARRAY_SIZE(paths); i++)
+ cl_fixture_cleanup(paths[i]);
+}
+
+static void init_linked_repo(const char *path, const char *alternate)
+{
+ git_buf_clear(&destpath);
+ git_buf_clear(&filepath);
+
+ cl_git_pass(git_repository_init(&repo, path, 1));
+ cl_git_pass(git_path_prettify(&destpath, alternate, NULL));
+ cl_git_pass(git_buf_joinpath(&destpath, destpath.ptr, "objects"));
+ cl_git_pass(git_buf_joinpath(&filepath, git_repository_path(repo), "objects/info"));
+ cl_git_pass(git_futils_mkdir(filepath.ptr, NULL, 0755, GIT_MKDIR_PATH));
+ cl_git_pass(git_buf_joinpath(&filepath, filepath.ptr , "alternates"));
+
+ cl_git_pass(git_filebuf_open(&file, git_buf_cstr(&filepath), 0, 0666));
+ git_filebuf_printf(&file, "%s\n", git_buf_cstr(&destpath));
+ cl_git_pass(git_filebuf_commit(&file));
+
+ git_repository_free(repo);
+}
+
+void test_odb_alternates__chained(void)
+{
+ git_commit *commit;
+ git_oid oid;
+
+ /* Set the alternate A -> testrepo.git */
+ init_linked_repo(paths[0], cl_fixture("testrepo.git"));
+
+ /* Set the alternate B -> A */
+ init_linked_repo(paths[1], paths[0]);
+
+ /* Now load B and see if we can find an object from testrepo.git */
+ cl_git_pass(git_repository_open(&repo, paths[1]));
+ git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
+ cl_git_pass(git_commit_lookup(&commit, repo, &oid));
+ git_commit_free(commit);
+ git_repository_free(repo);
+}
+
+void test_odb_alternates__long_chain(void)
+{
+ git_commit *commit;
+ git_oid oid;
+ size_t i;
+
+ /* Set the alternate A -> testrepo.git */
+ init_linked_repo(paths[0], cl_fixture("testrepo.git"));
+
+ /* Set up the five-element chain */
+ for (i = 1; i < ARRAY_SIZE(paths); i++) {
+ init_linked_repo(paths[i], paths[i-1]);
+ }
+
+ /* Now load the last one and see if we can find an object from testrepo.git */
+ cl_git_pass(git_repository_open(&repo, paths[ARRAY_SIZE(paths)-1]));
+ git_oid_fromstr(&oid, "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
+ cl_git_fail(git_commit_lookup(&commit, repo, &oid));
+ git_repository_free(repo);
+}
diff --git a/tests/odb/backend/nonrefreshing.c b/tests/odb/backend/nonrefreshing.c
new file mode 100644
index 000000000..b43529479
--- /dev/null
+++ b/tests/odb/backend/nonrefreshing.c
@@ -0,0 +1,274 @@
+#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;
+
+static git_repository *_repo;
+static fake_backend *_fake;
+static git_oid _oid;
+
+static int fake_backend__exists(git_odb_backend *backend, const git_oid *oid)
+{
+ fake_backend *fake;
+
+ GIT_UNUSED(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(out_oid);
+ 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++;
+
+ *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)
+{
+ 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(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, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
+}
+
+void test_odb_backend_nonrefreshing__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_failure(void)
+{
+ git_odb *odb;
+
+ setup_repository_and_backend(GIT_ENOTFOUND);
+
+ cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+ cl_assert_equal_b(false, git_odb_exists(odb, &_oid));
+
+ cl_assert_equal_i(1, _fake->exists_calls);
+}
+
+void test_odb_backend_nonrefreshing__read_is_invoked_once_on_failure(void)
+{
+ git_object *obj;
+
+ setup_repository_and_backend(GIT_ENOTFOUND);
+
+ cl_git_fail_with(
+ git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY),
+ GIT_ENOTFOUND);
+
+ cl_assert_equal_i(1, _fake->read_calls);
+}
+
+void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_failure(void)
+{
+ git_object *obj;
+
+ setup_repository_and_backend(GIT_ENOTFOUND);
+
+ cl_git_fail_with(
+ git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY),
+ GIT_ENOTFOUND);
+
+ cl_assert_equal_i(1, _fake->read_prefix_calls);
+}
+
+void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_failure(void)
+{
+ git_odb *odb;
+ size_t len;
+ git_otype type;
+
+ setup_repository_and_backend(GIT_ENOTFOUND);
+
+ cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+
+ cl_git_fail_with(
+ git_odb_read_header(&len, &type, odb, &_oid),
+ GIT_ENOTFOUND);
+
+ cl_assert_equal_i(1, _fake->read_header_calls);
+}
+
+void test_odb_backend_nonrefreshing__exists_is_invoked_once_on_success(void)
+{
+ git_odb *odb;
+
+ setup_repository_and_backend(GIT_OK);
+
+ cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+ cl_assert_equal_b(true, git_odb_exists(odb, &_oid));
+
+ cl_assert_equal_i(1, _fake->exists_calls);
+}
+
+void test_odb_backend_nonrefreshing__read_is_invoked_once_on_success(void)
+{
+ git_object *obj;
+
+ setup_repository_and_backend(GIT_OK);
+
+ cl_git_pass(git_object_lookup(&obj, _repo, &_oid, GIT_OBJ_ANY));
+
+ cl_assert_equal_i(1, _fake->read_calls);
+
+ git_object_free(obj);
+}
+
+void test_odb_backend_nonrefreshing__readprefix_is_invoked_once_on_success(void)
+{
+ git_object *obj;
+
+ setup_repository_and_backend(GIT_OK);
+
+ cl_git_pass(git_object_lookup_prefix(&obj, _repo, &_oid, 7, GIT_OBJ_ANY));
+
+ cl_assert_equal_i(1, _fake->read_prefix_calls);
+
+ git_object_free(obj);
+}
+
+void test_odb_backend_nonrefreshing__readheader_is_invoked_once_on_success(void)
+{
+ git_odb *odb;
+ size_t len;
+ git_otype type;
+
+ setup_repository_and_backend(GIT_OK);
+
+ cl_git_pass(git_repository_odb__weakptr(&odb, _repo));
+
+ cl_git_pass(git_odb_read_header(&len, &type, odb, &_oid));
+
+ cl_assert_equal_i(1, _fake->read_header_calls);
+}
+
+void test_odb_backend_nonrefreshing__read_is_invoked_once_when_revparsing_a_full_oid(void)
+{
+ git_object *obj;
+
+ setup_repository_and_backend(GIT_ENOTFOUND);
+
+ cl_git_fail_with(
+ git_revparse_single(&obj, _repo, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
+ GIT_ENOTFOUND);
+
+ cl_assert_equal_i(1, _fake->read_calls);
+}
diff --git a/tests/odb/foreach.c b/tests/odb/foreach.c
new file mode 100644
index 000000000..f643d9621
--- /dev/null
+++ b/tests/odb/foreach.c
@@ -0,0 +1,80 @@
+#include "clar_libgit2.h"
+#include "odb.h"
+#include "git2/odb_backend.h"
+#include "pack.h"
+
+static git_odb *_odb;
+static git_repository *_repo;
+static int nobj;
+
+void test_odb_foreach__cleanup(void)
+{
+ git_odb_free(_odb);
+ git_repository_free(_repo);
+
+ _odb = NULL;
+ _repo = NULL;
+}
+
+static int foreach_cb(const git_oid *oid, void *data)
+{
+ GIT_UNUSED(data);
+ GIT_UNUSED(oid);
+
+ nobj++;
+
+ return 0;
+}
+
+/*
+ * $ git --git-dir tests-clar/resources/testrepo.git count-objects --verbose
+ * count: 47
+ * size: 4
+ * in-pack: 1640
+ * packs: 3
+ * size-pack: 425
+ * prune-packable: 0
+ * garbage: 0
+ */
+void test_odb_foreach__foreach(void)
+{
+ cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
+ git_repository_odb(&_odb, _repo);
+
+ cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL));
+ cl_assert_equal_i(47 + 1640, nobj); /* count + in-pack */
+}
+
+void test_odb_foreach__one_pack(void)
+{
+ git_odb_backend *backend = NULL;
+
+ cl_git_pass(git_odb_new(&_odb));
+ cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx")));
+ cl_git_pass(git_odb_add_backend(_odb, backend, 1));
+ _repo = NULL;
+
+ nobj = 0;
+ cl_git_pass(git_odb_foreach(_odb, foreach_cb, NULL));
+ cl_assert(nobj == 1628);
+}
+
+static int foreach_stop_cb(const git_oid *oid, void *data)
+{
+ GIT_UNUSED(data);
+ GIT_UNUSED(oid);
+
+ nobj++;
+
+ return (nobj == 1000);
+}
+
+void test_odb_foreach__interrupt_foreach(void)
+{
+ nobj = 0;
+ cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git")));
+ git_repository_odb(&_odb, _repo);
+
+ cl_assert_equal_i(GIT_EUSER, git_odb_foreach(_odb, foreach_stop_cb, NULL));
+ cl_assert(nobj == 1000);
+}
diff --git a/tests/odb/loose.c b/tests/odb/loose.c
new file mode 100644
index 000000000..a85f1430d
--- /dev/null
+++ b/tests/odb/loose.c
@@ -0,0 +1,146 @@
+#include "clar_libgit2.h"
+#include "odb.h"
+#include "git2/odb_backend.h"
+#include "posix.h"
+#include "loose_data.h"
+
+#ifdef __ANDROID_API__
+# define S_IREAD S_IRUSR
+# define S_IWRITE S_IWUSR
+#endif
+
+static void write_object_files(object_data *d)
+{
+ int fd;
+
+ if (p_mkdir(d->dir, GIT_OBJECT_DIR_MODE) < 0)
+ cl_assert(errno == EEXIST);
+
+ cl_assert((fd = p_creat(d->file, S_IREAD | S_IWRITE)) >= 0);
+ cl_must_pass(p_write(fd, d->bytes, d->blen));
+
+ p_close(fd);
+}
+
+static void cmp_objects(git_rawobj *o, object_data *d)
+{
+ cl_assert(o->type == git_object_string2type(d->type));
+ cl_assert(o->len == d->dlen);
+
+ if (o->len > 0)
+ cl_assert(memcmp(o->data, d->data, o->len) == 0);
+}
+
+static void test_read_object(object_data *data)
+{
+ git_oid id;
+ git_odb_object *obj;
+ git_odb *odb;
+ git_rawobj tmp;
+
+ write_object_files(data);
+
+ cl_git_pass(git_odb_open(&odb, "test-objects"));
+ cl_git_pass(git_oid_fromstr(&id, data->id));
+ cl_git_pass(git_odb_read(&obj, odb, &id));
+
+ tmp.data = obj->buffer;
+ tmp.len = obj->cached.size;
+ tmp.type = obj->cached.type;
+
+ cmp_objects(&tmp, data);
+
+ git_odb_object_free(obj);
+ git_odb_free(odb);
+}
+
+void test_odb_loose__initialize(void)
+{
+ cl_must_pass(p_mkdir("test-objects", GIT_OBJECT_DIR_MODE));
+}
+
+void test_odb_loose__cleanup(void)
+{
+ cl_fixture_cleanup("test-objects");
+}
+
+void test_odb_loose__exists(void)
+{
+ git_oid id, id2;
+ git_odb *odb;
+
+ write_object_files(&one);
+ cl_git_pass(git_odb_open(&odb, "test-objects"));
+
+ cl_git_pass(git_oid_fromstr(&id, one.id));
+
+ cl_assert(git_odb_exists(odb, &id));
+
+ /* Test for a non-existant object */
+ cl_git_pass(git_oid_fromstr(&id2, "8b137891791fe96927ad78e64b0aad7bded08baa"));
+ cl_assert(!git_odb_exists(odb, &id2));
+
+ git_odb_free(odb);
+}
+
+void test_odb_loose__simple_reads(void)
+{
+ test_read_object(&commit);
+ test_read_object(&tree);
+ test_read_object(&tag);
+ test_read_object(&zero);
+ test_read_object(&one);
+ test_read_object(&two);
+ test_read_object(&some);
+}
+
+void test_write_object_permission(
+ mode_t dir_mode, mode_t file_mode,
+ mode_t expected_dir_mode, mode_t expected_file_mode)
+{
+ git_odb *odb;
+ git_odb_backend *backend;
+ git_oid oid;
+ struct stat statbuf;
+ mode_t mask, os_mask;
+
+ /* Windows does not return group/user bits from stat,
+ * files are never executable.
+ */
+#ifdef GIT_WIN32
+ os_mask = 0600;
+#else
+ os_mask = 0777;
+#endif
+
+ mask = p_umask(0);
+ p_umask(mask);
+
+ cl_git_pass(git_odb_new(&odb));
+ cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, 0, dir_mode, file_mode));
+ cl_git_pass(git_odb_add_backend(odb, backend, 1));
+ cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJ_BLOB));
+
+ cl_git_pass(p_stat("test-objects/67", &statbuf));
+ cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_dir_mode & ~mask) & os_mask);
+
+ cl_git_pass(p_stat("test-objects/67/b808feb36201507a77f85e6d898f0a2836e4a5", &statbuf));
+ cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_file_mode & ~mask) & os_mask);
+
+ git_odb_free(odb);
+}
+
+void test_odb_loose__permissions_standard(void)
+{
+ test_write_object_permission(0, 0, GIT_OBJECT_DIR_MODE, GIT_OBJECT_FILE_MODE);
+}
+
+void test_odb_loose_permissions_readonly(void)
+{
+ test_write_object_permission(0777, 0444, 0777, 0444);
+}
+
+void test_odb_loose__permissions_readwrite(void)
+{
+ test_write_object_permission(0777, 0666, 0777, 0666);
+}
diff --git a/tests/odb/loose_data.h b/tests/odb/loose_data.h
new file mode 100644
index 000000000..c10c9bc7f
--- /dev/null
+++ b/tests/odb/loose_data.h
@@ -0,0 +1,522 @@
+typedef struct object_data {
+ unsigned char *bytes; /* (compressed) bytes stored in object store */
+ size_t blen; /* length of data in object store */
+ char *id; /* object id (sha1) */
+ char *type; /* object type */
+ char *dir; /* object store (fan-out) directory name */
+ char *file; /* object store filename */
+ unsigned char *data; /* (uncompressed) object data */
+ size_t dlen; /* length of (uncompressed) object data */
+} object_data;
+
+/* one == 8b137891791fe96927ad78e64b0aad7bded08bdc */
+static unsigned char one_bytes[] = {
+ 0x31, 0x78, 0x9c, 0xe3, 0x02, 0x00, 0x00, 0x0b,
+ 0x00, 0x0b,
+};
+
+static unsigned char one_data[] = {
+ 0x0a,
+};
+
+static object_data one = {
+ one_bytes,
+ sizeof(one_bytes),
+ "8b137891791fe96927ad78e64b0aad7bded08bdc",
+ "blob",
+ "test-objects/8b",
+ "test-objects/8b/137891791fe96927ad78e64b0aad7bded08bdc",
+ one_data,
+ sizeof(one_data),
+};
+
+
+/* commit == 3d7f8a6af076c8c3f20071a8935cdbe8228594d1 */
+static unsigned char commit_bytes[] = {
+ 0x78, 0x01, 0x85, 0x50, 0xc1, 0x6a, 0xc3, 0x30,
+ 0x0c, 0xdd, 0xd9, 0x5f, 0xa1, 0xfb, 0x96, 0x12,
+ 0xbb, 0x29, 0x71, 0x46, 0x19, 0x2b, 0x3d, 0x97,
+ 0x1d, 0xd6, 0x7d, 0x80, 0x1d, 0xcb, 0x89, 0x21,
+ 0xb6, 0x82, 0xed, 0x40, 0xf3, 0xf7, 0xf3, 0x48,
+ 0x29, 0x3b, 0x6d, 0xd2, 0xe5, 0xbd, 0x27, 0xbd,
+ 0x27, 0x50, 0x4f, 0xde, 0xbb, 0x0c, 0xfb, 0x43,
+ 0xf3, 0x94, 0x23, 0x22, 0x18, 0x6b, 0x85, 0x51,
+ 0x5d, 0xad, 0xc5, 0xa1, 0x41, 0xae, 0x51, 0x4b,
+ 0xd9, 0x19, 0x6e, 0x4b, 0x0b, 0x29, 0x35, 0x72,
+ 0x59, 0xef, 0x5b, 0x29, 0x8c, 0x65, 0x6a, 0xc9,
+ 0x23, 0x45, 0x38, 0xc1, 0x17, 0x5c, 0x7f, 0xc0,
+ 0x71, 0x13, 0xde, 0xf1, 0xa6, 0xfc, 0x3c, 0xe1,
+ 0xae, 0x27, 0xff, 0x06, 0x5c, 0x88, 0x56, 0xf2,
+ 0x46, 0x74, 0x2d, 0x3c, 0xd7, 0xa5, 0x58, 0x51,
+ 0xcb, 0xb9, 0x8c, 0x11, 0xce, 0xf0, 0x01, 0x97,
+ 0x0d, 0x1e, 0x1f, 0xea, 0x3f, 0x6e, 0x76, 0x02,
+ 0x0a, 0x58, 0x4d, 0x2e, 0x20, 0x6c, 0x1e, 0x48,
+ 0x8b, 0xf7, 0x2a, 0xae, 0x8c, 0x5d, 0x47, 0x04,
+ 0x4d, 0x66, 0x05, 0xb2, 0x90, 0x0b, 0xbe, 0xcf,
+ 0x3d, 0xa6, 0xa4, 0x06, 0x7c, 0x29, 0x3c, 0x64,
+ 0xe5, 0x82, 0x0b, 0x03, 0xd8, 0x25, 0x96, 0x8d,
+ 0x08, 0x78, 0x9b, 0x27, 0x15, 0x54, 0x76, 0x14,
+ 0xd8, 0xdd, 0x35, 0x2f, 0x71, 0xa6, 0x84, 0x8f,
+ 0x90, 0x51, 0x85, 0x01, 0x13, 0xb8, 0x90, 0x23,
+ 0x99, 0xa5, 0x47, 0x03, 0x7a, 0xfd, 0x15, 0xbf,
+ 0x63, 0xec, 0xd3, 0x0d, 0x01, 0x4d, 0x45, 0xb6,
+ 0xd2, 0xeb, 0xeb, 0xdf, 0xef, 0x60, 0xdf, 0xef,
+ 0x1f, 0x78, 0x35,
+};
+
+static unsigned char commit_data[] = {
+ 0x74, 0x72, 0x65, 0x65, 0x20, 0x64, 0x66, 0x66,
+ 0x32, 0x64, 0x61, 0x39, 0x30, 0x62, 0x32, 0x35,
+ 0x34, 0x65, 0x31, 0x62, 0x65, 0x62, 0x38, 0x38,
+ 0x39, 0x64, 0x31, 0x66, 0x31, 0x66, 0x31, 0x32,
+ 0x38, 0x38, 0x62, 0x65, 0x31, 0x38, 0x30, 0x33,
+ 0x37, 0x38, 0x32, 0x64, 0x66, 0x0a, 0x61, 0x75,
+ 0x74, 0x68, 0x6f, 0x72, 0x20, 0x41, 0x20, 0x55,
+ 0x20, 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61,
+ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78,
+ 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
+ 0x6d, 0x3e, 0x20, 0x31, 0x32, 0x32, 0x37, 0x38,
+ 0x31, 0x34, 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30,
+ 0x30, 0x30, 0x30, 0x0a, 0x63, 0x6f, 0x6d, 0x6d,
+ 0x69, 0x74, 0x74, 0x65, 0x72, 0x20, 0x43, 0x20,
+ 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
+ 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+ 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
+ 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
+ 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
+ 0x30, 0x0a, 0x0a, 0x41, 0x20, 0x6f, 0x6e, 0x65,
+ 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x73, 0x75, 0x6d,
+ 0x6d, 0x61, 0x72, 0x79, 0x0a, 0x0a, 0x54, 0x68,
+ 0x65, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x20, 0x6f,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x6d, 0x6d, 0x69, 0x74, 0x20, 0x6d, 0x65, 0x73,
+ 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x63, 0x6f,
+ 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67,
+ 0x20, 0x66, 0x75, 0x72, 0x74, 0x68, 0x65, 0x72,
+ 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x6e, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x70, 0x75, 0x72, 0x70,
+ 0x6f, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67,
+ 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x72, 0x6f,
+ 0x64, 0x75, 0x63, 0x65, 0x64, 0x20, 0x62, 0x79,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x69, 0x74, 0x2e, 0x0a, 0x0a, 0x53, 0x69,
+ 0x67, 0x6e, 0x65, 0x64, 0x2d, 0x6f, 0x66, 0x2d,
+ 0x62, 0x79, 0x3a, 0x20, 0x41, 0x20, 0x55, 0x20,
+ 0x54, 0x68, 0x6f, 0x72, 0x20, 0x3c, 0x61, 0x75,
+ 0x74, 0x68, 0x6f, 0x72, 0x40, 0x65, 0x78, 0x61,
+ 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
+ 0x3e, 0x0a,
+};
+
+static object_data commit = {
+ commit_bytes,
+ sizeof(commit_bytes),
+ "3d7f8a6af076c8c3f20071a8935cdbe8228594d1",
+ "commit",
+ "test-objects/3d",
+ "test-objects/3d/7f8a6af076c8c3f20071a8935cdbe8228594d1",
+ commit_data,
+ sizeof(commit_data),
+};
+
+/* tree == dff2da90b254e1beb889d1f1f1288be1803782df */
+static unsigned char tree_bytes[] = {
+ 0x78, 0x01, 0x2b, 0x29, 0x4a, 0x4d, 0x55, 0x30,
+ 0x34, 0x32, 0x63, 0x30, 0x34, 0x30, 0x30, 0x33,
+ 0x31, 0x51, 0xc8, 0xcf, 0x4b, 0x65, 0xe8, 0x16,
+ 0xae, 0x98, 0x58, 0x29, 0xff, 0x32, 0x53, 0x7d,
+ 0x6d, 0xc5, 0x33, 0x6f, 0xae, 0xb5, 0xd5, 0xf7,
+ 0x2e, 0x74, 0xdf, 0x81, 0x4a, 0x17, 0xe7, 0xe7,
+ 0xa6, 0x32, 0xfc, 0x6d, 0x31, 0xd8, 0xd3, 0xe6,
+ 0xf3, 0xe7, 0xea, 0x47, 0xbe, 0xd0, 0x09, 0x3f,
+ 0x96, 0xb8, 0x3f, 0x90, 0x9e, 0xa2, 0xfd, 0x0f,
+ 0x2a, 0x5f, 0x52, 0x9e, 0xcf, 0x50, 0x31, 0x43,
+ 0x52, 0x29, 0xd1, 0x5a, 0xeb, 0x77, 0x82, 0x2a,
+ 0x8b, 0xfe, 0xb7, 0xbd, 0xed, 0x5d, 0x07, 0x67,
+ 0xfa, 0xb5, 0x42, 0xa5, 0xab, 0x52, 0x8b, 0xf2,
+ 0x19, 0x9e, 0xcd, 0x7d, 0x34, 0x7b, 0xd3, 0xc5,
+ 0x6b, 0xce, 0xde, 0xdd, 0x9a, 0xeb, 0xca, 0xa3,
+ 0x6e, 0x1c, 0x7a, 0xd2, 0x13, 0x3c, 0x11, 0x00,
+ 0xe2, 0xaa, 0x38, 0x57,
+};
+
+static unsigned char tree_data[] = {
+ 0x31, 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x6f,
+ 0x6e, 0x65, 0x00, 0x8b, 0x13, 0x78, 0x91, 0x79,
+ 0x1f, 0xe9, 0x69, 0x27, 0xad, 0x78, 0xe6, 0x4b,
+ 0x0a, 0xad, 0x7b, 0xde, 0xd0, 0x8b, 0xdc, 0x31,
+ 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x73, 0x6f,
+ 0x6d, 0x65, 0x00, 0xfd, 0x84, 0x30, 0xbc, 0x86,
+ 0x4c, 0xfc, 0xd5, 0xf1, 0x0e, 0x55, 0x90, 0xf8,
+ 0xa4, 0x47, 0xe0, 0x1b, 0x94, 0x2b, 0xfe, 0x31,
+ 0x30, 0x30, 0x36, 0x34, 0x34, 0x20, 0x74, 0x77,
+ 0x6f, 0x00, 0x78, 0x98, 0x19, 0x22, 0x61, 0x3b,
+ 0x2a, 0xfb, 0x60, 0x25, 0x04, 0x2f, 0xf6, 0xbd,
+ 0x87, 0x8a, 0xc1, 0x99, 0x4e, 0x85, 0x31, 0x30,
+ 0x30, 0x36, 0x34, 0x34, 0x20, 0x7a, 0x65, 0x72,
+ 0x6f, 0x00, 0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1,
+ 0xd6, 0x43, 0x4b, 0x8b, 0x29, 0xae, 0x77, 0x5a,
+ 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91,
+};
+
+static object_data tree = {
+ tree_bytes,
+ sizeof(tree_bytes),
+ "dff2da90b254e1beb889d1f1f1288be1803782df",
+ "tree",
+ "test-objects/df",
+ "test-objects/df/f2da90b254e1beb889d1f1f1288be1803782df",
+ tree_data,
+ sizeof(tree_data),
+};
+
+/* tag == 09d373e1dfdc16b129ceec6dd649739911541e05 */
+static unsigned char tag_bytes[] = {
+ 0x78, 0x01, 0x35, 0x4e, 0xcb, 0x0a, 0xc2, 0x40,
+ 0x10, 0xf3, 0xbc, 0x5f, 0x31, 0x77, 0xa1, 0xec,
+ 0xa3, 0xed, 0x6e, 0x41, 0x44, 0xf0, 0x2c, 0x5e,
+ 0xfc, 0x81, 0xe9, 0x76, 0xb6, 0xad, 0xb4, 0xb4,
+ 0x6c, 0x07, 0xd1, 0xbf, 0x77, 0x44, 0x0d, 0x39,
+ 0x84, 0x10, 0x92, 0x30, 0xf6, 0x60, 0xbc, 0xdb,
+ 0x2d, 0xed, 0x9d, 0x22, 0x83, 0xeb, 0x7c, 0x0a,
+ 0x58, 0x63, 0xd2, 0xbe, 0x8e, 0x21, 0xba, 0x64,
+ 0xb5, 0xf6, 0x06, 0x43, 0xe3, 0xaa, 0xd8, 0xb5,
+ 0x14, 0xac, 0x0d, 0x55, 0x53, 0x76, 0x46, 0xf1,
+ 0x6b, 0x25, 0x88, 0xcb, 0x3c, 0x8f, 0xac, 0x58,
+ 0x3a, 0x1e, 0xba, 0xd0, 0x85, 0xd8, 0xd8, 0xf7,
+ 0x94, 0xe1, 0x0c, 0x57, 0xb8, 0x8c, 0xcc, 0x22,
+ 0x0f, 0xdf, 0x90, 0xc8, 0x13, 0x3d, 0x71, 0x5e,
+ 0x27, 0x2a, 0xc4, 0x39, 0x82, 0xb1, 0xd6, 0x07,
+ 0x53, 0xda, 0xc6, 0xc3, 0x5e, 0x0b, 0x94, 0xba,
+ 0x0d, 0xe3, 0x06, 0x42, 0x1e, 0x08, 0x3e, 0x95,
+ 0xbf, 0x4b, 0x69, 0xc9, 0x90, 0x69, 0x22, 0xdc,
+ 0xe8, 0xbf, 0xf2, 0x06, 0x42, 0x9a, 0x36, 0xb1,
+};
+
+static unsigned char tag_data[] = {
+ 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x33,
+ 0x64, 0x37, 0x66, 0x38, 0x61, 0x36, 0x61, 0x66,
+ 0x30, 0x37, 0x36, 0x63, 0x38, 0x63, 0x33, 0x66,
+ 0x32, 0x30, 0x30, 0x37, 0x31, 0x61, 0x38, 0x39,
+ 0x33, 0x35, 0x63, 0x64, 0x62, 0x65, 0x38, 0x32,
+ 0x32, 0x38, 0x35, 0x39, 0x34, 0x64, 0x31, 0x0a,
+ 0x74, 0x79, 0x70, 0x65, 0x20, 0x63, 0x6f, 0x6d,
+ 0x6d, 0x69, 0x74, 0x0a, 0x74, 0x61, 0x67, 0x20,
+ 0x76, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x0a, 0x74,
+ 0x61, 0x67, 0x67, 0x65, 0x72, 0x20, 0x43, 0x20,
+ 0x4f, 0x20, 0x4d, 0x69, 0x74, 0x74, 0x65, 0x72,
+ 0x20, 0x3c, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74,
+ 0x74, 0x65, 0x72, 0x40, 0x65, 0x78, 0x61, 0x6d,
+ 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x3e,
+ 0x20, 0x31, 0x32, 0x32, 0x37, 0x38, 0x31, 0x34,
+ 0x32, 0x39, 0x37, 0x20, 0x2b, 0x30, 0x30, 0x30,
+ 0x30, 0x0a, 0x0a, 0x54, 0x68, 0x69, 0x73, 0x20,
+ 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74,
+ 0x61, 0x67, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63,
+ 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x72, 0x65,
+ 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x76, 0x30,
+ 0x2e, 0x30, 0x2e, 0x31, 0x0a,
+};
+
+static object_data tag = {
+ tag_bytes,
+ sizeof(tag_bytes),
+ "09d373e1dfdc16b129ceec6dd649739911541e05",
+ "tag",
+ "test-objects/09",
+ "test-objects/09/d373e1dfdc16b129ceec6dd649739911541e05",
+ tag_data,
+ sizeof(tag_data),
+};
+
+/* zero == e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 */
+static unsigned char zero_bytes[] = {
+ 0x78, 0x01, 0x4b, 0xca, 0xc9, 0x4f, 0x52, 0x30,
+ 0x60, 0x00, 0x00, 0x09, 0xb0, 0x01, 0xf0,
+};
+
+static unsigned char zero_data[] = {
+ 0x00 /* dummy data */
+};
+
+static object_data zero = {
+ zero_bytes,
+ sizeof(zero_bytes),
+ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+ "blob",
+ "test-objects/e6",
+ "test-objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+ zero_data,
+ 0,
+};
+
+/* two == 78981922613b2afb6025042ff6bd878ac1994e85 */
+static unsigned char two_bytes[] = {
+ 0x78, 0x01, 0x4b, 0xca, 0xc9, 0x4f, 0x52, 0x30,
+ 0x62, 0x48, 0xe4, 0x02, 0x00, 0x0e, 0x64, 0x02,
+ 0x5d,
+};
+
+static unsigned char two_data[] = {
+ 0x61, 0x0a,
+};
+
+static object_data two = {
+ two_bytes,
+ sizeof(two_bytes),
+ "78981922613b2afb6025042ff6bd878ac1994e85",
+ "blob",
+ "test-objects/78",
+ "test-objects/78/981922613b2afb6025042ff6bd878ac1994e85",
+ two_data,
+ sizeof(two_data),
+};
+
+/* some == fd8430bc864cfcd5f10e5590f8a447e01b942bfe */
+static unsigned char some_bytes[] = {
+ 0x78, 0x01, 0x7d, 0x54, 0xc1, 0x4e, 0xe3, 0x30,
+ 0x10, 0xdd, 0x33, 0x5f, 0x31, 0xc7, 0x5d, 0x94,
+ 0xa5, 0x84, 0xd5, 0x22, 0xad, 0x7a, 0x0a, 0x15,
+ 0x85, 0x48, 0xd0, 0x56, 0x49, 0x2a, 0xd4, 0xa3,
+ 0x13, 0x4f, 0x88, 0x85, 0x63, 0x47, 0xb6, 0x43,
+ 0xc9, 0xdf, 0xef, 0x8c, 0x69, 0x17, 0x56, 0x0b,
+ 0x7b, 0xaa, 0x62, 0x7b, 0xde, 0xbc, 0xf7, 0xe6,
+ 0x4d, 0x6b, 0x6d, 0x6b, 0x48, 0xd3, 0xcb, 0x5f,
+ 0x5f, 0x66, 0xa7, 0x27, 0x70, 0x0a, 0x55, 0xa7,
+ 0x3c, 0xb4, 0x4a, 0x23, 0xf0, 0xaf, 0x43, 0x04,
+ 0x6f, 0xdb, 0xb0, 0x17, 0x0e, 0xe7, 0x30, 0xd9,
+ 0x11, 0x1a, 0x61, 0xc0, 0xa1, 0x54, 0x3e, 0x38,
+ 0x55, 0x8f, 0x81, 0x9e, 0x05, 0x10, 0x46, 0xce,
+ 0xac, 0x83, 0xde, 0x4a, 0xd5, 0x4e, 0x0c, 0x42,
+ 0x67, 0xa3, 0x91, 0xe8, 0x20, 0x74, 0x08, 0x01,
+ 0x5d, 0xef, 0xc1, 0xb6, 0xf1, 0xe3, 0x66, 0xb5,
+ 0x85, 0x1b, 0x34, 0xe8, 0x84, 0x86, 0xcd, 0x58,
+ 0x6b, 0xd5, 0xc0, 0x9d, 0x6a, 0xd0, 0x78, 0x4c,
+ 0xe0, 0x19, 0x9d, 0x57, 0xd6, 0xc0, 0x45, 0xc2,
+ 0x18, 0xc2, 0xc3, 0xc0, 0x0f, 0x7c, 0x87, 0x12,
+ 0xea, 0x29, 0x56, 0x2f, 0x99, 0x4f, 0x79, 0xe0,
+ 0x03, 0x4b, 0x4b, 0x4d, 0x44, 0xa0, 0x92, 0x33,
+ 0x2a, 0xe0, 0x9a, 0xdc, 0x80, 0x90, 0x52, 0xf1,
+ 0x11, 0x04, 0x1b, 0x4b, 0x06, 0xea, 0xae, 0x3c,
+ 0xe3, 0x7a, 0x50, 0x74, 0x4a, 0x84, 0xfe, 0xc3,
+ 0x81, 0x41, 0xf8, 0x89, 0x18, 0x43, 0x67, 0x9d,
+ 0x87, 0x47, 0xf5, 0x8c, 0x51, 0xf6, 0x68, 0xb4,
+ 0xea, 0x55, 0x20, 0x2a, 0x6f, 0x80, 0xdc, 0x42,
+ 0x2b, 0xf3, 0x14, 0x2b, 0x1a, 0xdb, 0x0f, 0xe4,
+ 0x9a, 0x64, 0x84, 0xa3, 0x90, 0xa8, 0xf9, 0x8f,
+ 0x9d, 0x86, 0x9e, 0xd3, 0xab, 0x5a, 0x99, 0xc8,
+ 0xd9, 0xc3, 0x5e, 0x85, 0x0e, 0x2c, 0xb5, 0x73,
+ 0x30, 0x38, 0xfb, 0xe8, 0x44, 0xef, 0x5f, 0x95,
+ 0x1b, 0xc9, 0xd0, 0xef, 0x3c, 0x26, 0x32, 0x1e,
+ 0xff, 0x2d, 0xb6, 0x23, 0x7b, 0x3f, 0xd1, 0x3c,
+ 0x78, 0x1a, 0x0d, 0xcb, 0xe6, 0xf6, 0xd4, 0x44,
+ 0x99, 0x47, 0x1a, 0x9e, 0xed, 0x23, 0xb5, 0x91,
+ 0x6a, 0xdf, 0x53, 0x39, 0x03, 0xf8, 0x5a, 0xb1,
+ 0x0f, 0x1f, 0xce, 0x81, 0x11, 0xde, 0x01, 0x7a,
+ 0x90, 0x16, 0xc4, 0x30, 0xe8, 0x89, 0xed, 0x7b,
+ 0x65, 0x4b, 0xd7, 0x03, 0x36, 0xc1, 0xcf, 0xa1,
+ 0xa5, 0xb1, 0xe3, 0x8b, 0xe8, 0x07, 0x4d, 0xf3,
+ 0x23, 0x25, 0x13, 0x35, 0x27, 0xf5, 0x8c, 0x11,
+ 0xd3, 0xa0, 0x9a, 0xa8, 0xf5, 0x38, 0x7d, 0xce,
+ 0x55, 0xc2, 0x71, 0x79, 0x13, 0xc7, 0xa3, 0xda,
+ 0x77, 0x68, 0xc0, 0xd8, 0x10, 0xdd, 0x24, 0x8b,
+ 0x15, 0x59, 0xc5, 0x10, 0xe2, 0x20, 0x99, 0x8e,
+ 0xf0, 0x05, 0x9b, 0x31, 0x88, 0x5a, 0xe3, 0xd9,
+ 0x37, 0xba, 0xe2, 0xdb, 0xbf, 0x92, 0xfa, 0x66,
+ 0x16, 0x97, 0x47, 0xd9, 0x9d, 0x1d, 0x28, 0x7c,
+ 0x9d, 0x08, 0x1c, 0xc7, 0xbd, 0xd2, 0x1a, 0x6a,
+ 0x04, 0xf2, 0xa2, 0x1d, 0x75, 0x02, 0x14, 0x5d,
+ 0xc6, 0x78, 0xc8, 0xab, 0xdb, 0xf5, 0xb6, 0x82,
+ 0x6c, 0xb5, 0x83, 0x87, 0xac, 0x28, 0xb2, 0x55,
+ 0xb5, 0x9b, 0xc7, 0xc1, 0xb0, 0xb7, 0xf8, 0x4c,
+ 0xbc, 0x38, 0x0e, 0x8a, 0x04, 0x2a, 0x62, 0x41,
+ 0x6b, 0xe0, 0x84, 0x09, 0x13, 0xe9, 0xe1, 0xea,
+ 0xfb, 0xeb, 0x62, 0x71, 0x4b, 0x25, 0xd9, 0x55,
+ 0x7e, 0x97, 0x57, 0x3b, 0x20, 0x33, 0x96, 0x79,
+ 0xb5, 0xba, 0x2e, 0x4b, 0x58, 0xae, 0x0b, 0xc8,
+ 0x60, 0x93, 0x15, 0x55, 0xbe, 0xd8, 0xde, 0x65,
+ 0x05, 0x6c, 0xb6, 0xc5, 0x66, 0x5d, 0x5e, 0x93,
+ 0xf7, 0x25, 0x65, 0x98, 0x41, 0x29, 0x86, 0x0c,
+ 0xf2, 0xf1, 0x14, 0xa2, 0xb3, 0xbd, 0x75, 0x08,
+ 0x12, 0x83, 0x50, 0xda, 0x1f, 0x23, 0xbe, 0xa3,
+ 0x1d, 0xf4, 0x9d, 0x1d, 0xb5, 0x84, 0x4e, 0x50,
+ 0x38, 0x1d, 0x36, 0x48, 0x21, 0x95, 0xd1, 0xac,
+ 0x81, 0x99, 0x1d, 0xc1, 0x3f, 0x41, 0xe6, 0x9e,
+ 0x42, 0x5b, 0x0a, 0x48, 0xcc, 0x5f, 0xe0, 0x7d,
+ 0x3f, 0xc4, 0x6f, 0x0e, 0xfe, 0xc0, 0x2d, 0xfe,
+ 0x01, 0x2c, 0xd6, 0x9b, 0x5d, 0xbe, 0xba, 0x21,
+ 0xca, 0x79, 0xcb, 0xe3, 0x49, 0x60, 0xef, 0x68,
+ 0x05, 0x28, 0x9b, 0x8c, 0xc1, 0x12, 0x3e, 0xdb,
+ 0xc7, 0x04, 0x7e, 0xa6, 0x74, 0x29, 0xcc, 0x13,
+ 0xed, 0x07, 0x94, 0x81, 0xd6, 0x96, 0xaa, 0x97,
+ 0xaa, 0xa5, 0xc0, 0x2f, 0xb5, 0xb5, 0x2e, 0xe6,
+ 0xfc, 0xca, 0xfa, 0x60, 0x4d, 0x02, 0xf7, 0x19,
+ 0x9c, 0x5f, 0xa4, 0xe9, 0xf9, 0xf7, 0xf4, 0xc7,
+ 0x79, 0x9a, 0xc0, 0xb6, 0xcc, 0x58, 0xec, 0xec,
+ 0xe4, 0x37, 0x22, 0xfa, 0x8b, 0x53,
+};
+
+static unsigned char some_data[] = {
+ 0x2f, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68,
+ 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20,
+ 0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20,
+ 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+ 0x3b, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61,
+ 0x6e, 0x20, 0x72, 0x65, 0x64, 0x69, 0x73, 0x74,
+ 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x69,
+ 0x74, 0x20, 0x61, 0x6e, 0x64, 0x2f, 0x6f, 0x72,
+ 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x0a,
+ 0x20, 0x2a, 0x20, 0x69, 0x74, 0x20, 0x75, 0x6e,
+ 0x64, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x74, 0x65, 0x72, 0x6d, 0x73, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
+ 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+ 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+ 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x2c,
+ 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ 0x20, 0x32, 0x2c, 0x0a, 0x20, 0x2a, 0x20, 0x61,
+ 0x73, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73,
+ 0x68, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
+ 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+ 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x20, 0x2a, 0x0a,
+ 0x20, 0x2a, 0x20, 0x49, 0x6e, 0x20, 0x61, 0x64,
+ 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74,
+ 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x65,
+ 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e,
+ 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x47, 0x4e, 0x55, 0x20, 0x47, 0x65, 0x6e,
+ 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50, 0x75, 0x62,
+ 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69, 0x63, 0x65,
+ 0x6e, 0x73, 0x65, 0x2c, 0x0a, 0x20, 0x2a, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x61, 0x75, 0x74, 0x68,
+ 0x6f, 0x72, 0x73, 0x20, 0x67, 0x69, 0x76, 0x65,
+ 0x20, 0x79, 0x6f, 0x75, 0x20, 0x75, 0x6e, 0x6c,
+ 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x20, 0x70,
+ 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e,
+ 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f,
+ 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x0a, 0x20,
+ 0x2a, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+ 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69,
+ 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x69,
+ 0x6e, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x62,
+ 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74,
+ 0x68, 0x65, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x67,
+ 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0a, 0x20, 0x2a,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20,
+ 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75,
+ 0x74, 0x65, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65,
+ 0x20, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61,
+ 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x77, 0x69,
+ 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e,
+ 0x79, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72, 0x69,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x2a,
+ 0x20, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x20,
+ 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65,
+ 0x20, 0x75, 0x73, 0x65, 0x20, 0x6f, 0x66, 0x20,
+ 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
+ 0x65, 0x2e, 0x20, 0x20, 0x28, 0x54, 0x68, 0x65,
+ 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+ 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+ 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
+ 0x20, 0x2a, 0x20, 0x72, 0x65, 0x73, 0x74, 0x72,
+ 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20,
+ 0x64, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79,
+ 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x74, 0x68, 0x65,
+ 0x72, 0x20, 0x72, 0x65, 0x73, 0x70, 0x65, 0x63,
+ 0x74, 0x73, 0x3b, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c,
+ 0x20, 0x74, 0x68, 0x65, 0x79, 0x20, 0x63, 0x6f,
+ 0x76, 0x65, 0x72, 0x0a, 0x20, 0x2a, 0x20, 0x6d,
+ 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2c,
+ 0x20, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73,
+ 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f,
+ 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e,
+ 0x6f, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65,
+ 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x0a, 0x20,
+ 0x2a, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x62,
+ 0x69, 0x6e, 0x65, 0x64, 0x20, 0x65, 0x78, 0x65,
+ 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e,
+ 0x29, 0x0a, 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c,
+ 0x65, 0x20, 0x69, 0x73, 0x20, 0x64, 0x69, 0x73,
+ 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64,
+ 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x68, 0x6f, 0x70, 0x65, 0x20, 0x74, 0x68, 0x61,
+ 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c,
+ 0x6c, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65,
+ 0x66, 0x75, 0x6c, 0x2c, 0x20, 0x62, 0x75, 0x74,
+ 0x0a, 0x20, 0x2a, 0x20, 0x57, 0x49, 0x54, 0x48,
+ 0x4f, 0x55, 0x54, 0x20, 0x41, 0x4e, 0x59, 0x20,
+ 0x57, 0x41, 0x52, 0x52, 0x41, 0x4e, 0x54, 0x59,
+ 0x3b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75,
+ 0x74, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x69,
+ 0x65, 0x64, 0x20, 0x77, 0x61, 0x72, 0x72, 0x61,
+ 0x6e, 0x74, 0x79, 0x20, 0x6f, 0x66, 0x0a, 0x20,
+ 0x2a, 0x20, 0x4d, 0x45, 0x52, 0x43, 0x48, 0x41,
+ 0x4e, 0x54, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54,
+ 0x59, 0x20, 0x6f, 0x72, 0x20, 0x46, 0x49, 0x54,
+ 0x4e, 0x45, 0x53, 0x53, 0x20, 0x46, 0x4f, 0x52,
+ 0x20, 0x41, 0x20, 0x50, 0x41, 0x52, 0x54, 0x49,
+ 0x43, 0x55, 0x4c, 0x41, 0x52, 0x20, 0x50, 0x55,
+ 0x52, 0x50, 0x4f, 0x53, 0x45, 0x2e, 0x20, 0x20,
+ 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x47, 0x4e, 0x55, 0x0a, 0x20, 0x2a, 0x20, 0x47,
+ 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x50,
+ 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20, 0x4c, 0x69,
+ 0x63, 0x65, 0x6e, 0x73, 0x65, 0x20, 0x66, 0x6f,
+ 0x72, 0x20, 0x6d, 0x6f, 0x72, 0x65, 0x20, 0x64,
+ 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x2e, 0x0a,
+ 0x20, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x59, 0x6f,
+ 0x75, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
+ 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x72, 0x65,
+ 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x20, 0x61,
+ 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x47, 0x4e, 0x55,
+ 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c,
+ 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x20,
+ 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x0a,
+ 0x20, 0x2a, 0x20, 0x61, 0x6c, 0x6f, 0x6e, 0x67,
+ 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68,
+ 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
+ 0x61, 0x6d, 0x3b, 0x20, 0x73, 0x65, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65,
+ 0x20, 0x43, 0x4f, 0x50, 0x59, 0x49, 0x4e, 0x47,
+ 0x2e, 0x20, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f,
+ 0x74, 0x2c, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65,
+ 0x20, 0x74, 0x6f, 0x0a, 0x20, 0x2a, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x46, 0x72, 0x65, 0x65, 0x20,
+ 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
+ 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x35, 0x31, 0x20,
+ 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x6c, 0x69, 0x6e,
+ 0x20, 0x53, 0x74, 0x72, 0x65, 0x65, 0x74, 0x2c,
+ 0x20, 0x46, 0x69, 0x66, 0x74, 0x68, 0x20, 0x46,
+ 0x6c, 0x6f, 0x6f, 0x72, 0x2c, 0x0a, 0x20, 0x2a,
+ 0x20, 0x42, 0x6f, 0x73, 0x74, 0x6f, 0x6e, 0x2c,
+ 0x20, 0x4d, 0x41, 0x20, 0x30, 0x32, 0x31, 0x31,
+ 0x30, 0x2d, 0x31, 0x33, 0x30, 0x31, 0x2c, 0x20,
+ 0x55, 0x53, 0x41, 0x2e, 0x0a, 0x20, 0x2a, 0x2f,
+ 0x0a,
+};
+
+static object_data some = {
+ some_bytes,
+ sizeof(some_bytes),
+ "fd8430bc864cfcd5f10e5590f8a447e01b942bfe",
+ "blob",
+ "test-objects/fd",
+ "test-objects/fd/8430bc864cfcd5f10e5590f8a447e01b942bfe",
+ some_data,
+ sizeof(some_data),
+};
diff --git a/tests/odb/mixed.c b/tests/odb/mixed.c
new file mode 100644
index 000000000..51970ceec
--- /dev/null
+++ b/tests/odb/mixed.c
@@ -0,0 +1,93 @@
+#include "clar_libgit2.h"
+#include "odb.h"
+
+static git_odb *_odb;
+
+void test_odb_mixed__initialize(void)
+{
+ cl_git_pass(git_odb_open(&_odb, cl_fixture("duplicate.git/objects")));
+}
+
+void test_odb_mixed__cleanup(void)
+{
+ git_odb_free(_odb);
+ _odb = NULL;
+}
+
+void test_odb_mixed__dup_oid(void) {
+ const char hex[] = "ce013625030ba8dba906f756967f9e9ca394464a";
+ const char short_hex[] = "ce01362";
+ git_oid oid;
+ git_odb_object *obj;
+
+ cl_git_pass(git_oid_fromstr(&oid, hex));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, GIT_OID_HEXSZ));
+ git_odb_object_free(obj);
+ cl_git_pass(git_oid_fromstrn(&oid, short_hex, sizeof(short_hex) - 1));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, sizeof(short_hex) - 1));
+ git_odb_object_free(obj);
+}
+
+/* some known sha collisions of file content:
+ * 'aabqhq' and 'aaazvc' with prefix 'dea509d0' (+ '9' and + 'b')
+ * 'aaeufo' and 'aaaohs' with prefix '81b5bff5' (+ 'f' and + 'b')
+ * 'aafewy' and 'aaepta' with prefix '739e3c4c'
+ * 'aahsyn' and 'aadrjg' with prefix '0ddeaded' (+ '9' and + 'e')
+ */
+
+void test_odb_mixed__dup_oid_prefix_0(void) {
+ char hex[10];
+ git_oid oid;
+ git_odb_object *obj;
+
+ /* ambiguous in the same pack file */
+
+ strncpy(hex, "dea509d0", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_assert_equal_i(
+ GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+
+ strncpy(hex, "dea509d09", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ strncpy(hex, "dea509d0b", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ /* ambiguous in different pack files */
+
+ strncpy(hex, "81b5bff5", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_assert_equal_i(
+ GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+
+ strncpy(hex, "81b5bff5b", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ strncpy(hex, "81b5bff5f", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ /* ambiguous in pack file and loose */
+
+ strncpy(hex, "0ddeaded", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_assert_equal_i(
+ GIT_EAMBIGUOUS, git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+
+ strncpy(hex, "0ddeaded9", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+
+ strncpy(hex, "0ddeadede", sizeof(hex));
+ cl_git_pass(git_oid_fromstrn(&oid, hex, strlen(hex)));
+ cl_git_pass(git_odb_read_prefix(&obj, _odb, &oid, strlen(hex)));
+ git_odb_object_free(obj);
+}
diff --git a/tests/odb/pack_data.h b/tests/odb/pack_data.h
new file mode 100644
index 000000000..e6371beb1
--- /dev/null
+++ b/tests/odb/pack_data.h
@@ -0,0 +1,151 @@
+
+static const char *packed_objects[] = {
+ "0266163a49e280c4f5ed1e08facd36a2bd716bcf",
+ "53fc32d17276939fc79ed05badaef2db09990016",
+ "6336846bd5c88d32f93ae57d846683e61ab5c530",
+ "6dcf9bf7541ee10456529833502442f385010c3d",
+ "bed08a0b30b72a9d4aed7f1af8c8ca124e8d64b9",
+ "e90810b8df3e80c413d903f631643c716887138d",
+ "fc3c3a2083e9f6f89e6bd53e9420e70d1e357c9b",
+ "fc58168adf502d0c0ef614c3111a7038fc8c09c8",
+ "fd0ec0333948dfe23265ac46be0205a436a8c3a5",
+ "fd8430bc864cfcd5f10e5590f8a447e01b942bfe",
+ "fd899f45951c15c1c5f7c34b1c864e91bd6556c6",
+ "fda23b974899e7e1f938619099280bfda13bdca9",
+ "fdbec189efb657c8325962b494875987881a356b",
+ "fe1ca6bd22b5d8353ce6c2f3aba80805c438a7a5",
+ "fe3a6a42c87ff1239370c741a265f3997add87c1",
+ "deb106bfd2d36ecf9f0079224c12022201a39ad1",
+ "dec93efc79e60f2680de3e666755d335967eec30",
+ "def425bf8568b9c1e20879bf5be6f9c52b7361c4",
+ "df48000ac4f48570054e3a71a81916357997b680",
+ "dfae6ed8f6dd8acc3b40a31811ea316239223559",
+ "dff79e27d3d2cdc09790ded80fe2ea8ff5d61034",
+ "e00e46abe4c542e17c8bc83d72cf5be8018d7b0e",
+ "e01b107b4f77f8f98645adac0206a504f2d29d7c",
+ "e032d863f512c47b479bd984f8b6c8061f66b7d4",
+ "e044baa468a1c74f9f9da36805445f6888358b49",
+ "e04529998989ba8ae3419538dd57969af819b241",
+ "e0637ddfbea67c8d7f557c709e095af8906e9176",
+ "e0743ad4031231e71700abdc6fdbe94f189d20e5",
+ "cf33ac7a3d8b2b8f6bb266518aadbf59de397608",
+ "cf5f7235b9c9689b133f6ea12015720b411329bd",
+ "cf6cccf1297284833a9a03138a1f5738fa1c6c94",
+ "cf7992bde17ce7a79cab5f0c1fcbe8a0108721ed",
+ "cfe3a027ab12506d4144ee8a35669ae8fc4b7ab1",
+ "cfe96f31dfad7bab49977aa1df7302f7fafcb025",
+ "cff54d138945ef4de384e9d2759291d0c13ea90a",
+ "d01f7573ac34c2f502bd1cf18cde73480c741151",
+ "d03f567593f346a1ca96a57f8191def098d126e3",
+ "d047b47aadf88501238f36f5c17dd0a50dc62087",
+ "d0a0d63086fae3b0682af7261df21f7d0f7f066d",
+ "d0a44bd6ed0be21b725a96c0891bbc79bc1a540c",
+ "d0d7e736e536a41bcb885005f8bf258c61cad682",
+ "d0e7959d4b95ffec6198df6f5a7ae259b23a5f50",
+ "bf2fe2acca17d13356ce802ba9dc8343f710dfb7",
+ "bf55f407d6d9418e51f42ea7a3a6aadf17388349",
+ "bf92206f8b633b88a66dca4a911777630b06fbac",
+ "bfaf8c42eb8842abe206179fee864cfba87e3ca9",
+ "bfe05675d4e8f6b59d50932add8790f1a06b10ee",
+ "bff8618112330763327cfa6ce6e914db84f51ddf",
+ "bff873e9853ed99fed52c25f7ad29f78b27dcec2",
+ "c01c3fae7251098d7af1b459bcd0786e81d4616d",
+ "c0220fca67f48b8a5d4163d53b1486224be3a198",
+ "c02d0b160b82ee72469c269f13de4c26a7ea09cb",
+ "c059510ad1b45ab58390e042d7dee1ac46703854",
+ "c07204a1897aeeaa3c248d29dbfa9b033baf9755",
+ "c073337a4dd7276931b4b3fdbc3f0040e9441793",
+ "0fd7e4bfba5b3a82be88d1057757ca8b2c5e6d26",
+ "100746511cc45c9f1ad6721c4ef5be49222fee4d",
+ "1088490171d9b984d68b8b9be9ca003f4eafff59",
+ "1093c8ff4cb78fcf5f79dbbeedcb6e824bd4e253",
+ "10aa3fa72afab7ee31e116ae06442fe0f7b79df2",
+ "10b759e734e8299aa0dca08be935d95d886127b6",
+ "111d5ccf0bb010c4e8d7af3eedfa12ef4c5e265b",
+ "11261fbff21758444d426356ff6327ee01e90752",
+ "112998d425717bb922ce74e8f6f0f831d8dc4510",
+ "2ef4e5d838b6507bd61d457cf6466662b791c5c0",
+ "2ef4faa0f82efa00eeac6cae9e8b2abccc8566ee",
+ "2f06098183b0d7be350acbe39cdbaccff2df0c4a",
+ "2f1c5d509ac5bffb3c62f710a1c2c542e126dfd1",
+ "2f205b20fc16423c42b3ba51b2ea78d7b9ff3578",
+ "2f9b6b6e3d9250ba09360734aa47973a993b59d1",
+ "30c62a2d5a8d644f1311d4f7fe3f6a788e4c8188",
+ "31438e245492d85fd6da4d1406eba0fbde8332a4",
+ "3184a3abdfea231992254929ff4e275898e5bbf6",
+ "3188ffdbb3a3d52e0f78f30c484533899224436e",
+ "32581d0093429770d044a60eb0e9cc0462bedb13",
+ "32679a9544d83e5403202c4d5efb61ad02492847",
+ "4e7e9f60b7e2049b7f5697daf133161a18ef688f",
+ "4e8cda27ddc8be7db875ceb0f360c37734724c6d",
+ "4ea481c61c59ab55169b7cbaae536ad50b49d6f0",
+ "4f0adcd0e61eabe06fe32be66b16559537124b7a",
+ "4f1355c91100d12f9e7202f91b245df0c110867c",
+ "4f6eadeb08b9d0d1e8b1b3eac8a34940adf29a2d",
+ "4f9339df943c53117a5fc8e86e2f38716ff3a668",
+ "4fc3874b118752e40de556b1c3e7b4a9f1737d00",
+ "4ff1dd0992dd6baafdb5e166be6f9f23b59bdf87",
+ "5018a35e0b7e2eec7ce5050baf9c7343f3f74164",
+ "50298f44a45eda3a29dae82dbe911b5aa176ac07",
+ "502acd164fb115768d723144da2e7bb5a24891bb",
+ "50330c02bd4fd95c9db1fcf2f97f4218e42b7226",
+ "5052bf355d9f8c52446561a39733a8767bf31e37",
+ "6f2cd729ae42988c1dd43588d3a6661ba48ad7a0",
+ "6f4e2c42d9138bfbf3e0f908f1308828cc6f2178",
+ "6f6a17db05a83620cef4572761831c20a70ba9b9",
+ "6faad60901e36538634f0d8b8ff3f21f83503c71",
+ "6fc72e46de3df0c3842dab302bbacf697a63abab",
+ "6fdccd49f442a7204399ca9b418f017322dbded8",
+ "6fe7568fc3861c334cb008fd85d57d9647249ef5",
+ "700f55d91d7b55665594676a4bada1f1457a0598",
+ "702bd70595a7b19afc48a1f784a6505be68469d4",
+ "7033f9ee0e52b08cb5679cd49b7b7999eaf9eaf8",
+ "70957110ce446c4e250f865760fb3da513cdcc92",
+ "8ec696a4734f16479d091bc70574d23dd9fe7443",
+ "8ed341c55ed4d6f4cdc8bf4f0ca18a08c93f6962",
+ "8edc2805f1f11b63e44bf81f4557f8b473612b69",
+ "8ef9060a954118a698fc10e20acdc430566a100f",
+ "8f0c4b543f4bb6eb1518ecfc3d4699e43108d393",
+ "8fac94df3035405c2e60b3799153ce7c428af6b9",
+ "904c0ac12b23548de524adae712241b423d765a3",
+ "90bbaa9a809c3a768d873a9cc7d52b4f3bf3d1b9",
+ "90d4d2f0fc362beabbbf76b4ffda0828229c198d",
+ "90f9ff6755330b685feff6c3d81782ee3592ab04",
+ "91822c50ebe4f9bf5bbb8308ecf9f6557062775c",
+ "91d973263a55708fa8255867b3202d81ef9c2868",
+ "af292c99c6148d772af3315a1c74e83330e7ead7",
+ "af3b99d5be330dbbce0b9250c3a5fb05911908cc",
+ "af55d0cdeb280af2db8697e5afa506e081012719",
+ "af795e498d411142ddb073e8ca2c5447c3295a4c",
+ "afadc73a392f8cc8e2cc77dd62a7433dd3bafa8c",
+ "affd84ed8ec7ce67612fe3c12a80f8164b101f6a",
+ "b0941f9c70ffe67f0387a827b338e64ecf3190f0",
+ "b0a3077f9ef6e093f8d9869bdb0c07095bd722cb",
+ "b0a8568a7614806378a54db5706ee3b06ae58693",
+ "b0fb7372f242233d1d35ce7d8e74d3990cbc5841",
+ "b10489944b9ead17427551759d180d10203e06ba",
+ "b196a807b323f2748ffc6b1d42cd0812d04c9a40",
+ "b1bb1d888f0c5e19278536d49fa77db035fac7ae"
+};
+
+static const char *loose_objects[] = {
+ "45b983be36b73c0788dc9cbcb76cbb80fc7bb057",
+ "a8233120f6ad708f843d861ce2b7228ec4e3dec6",
+ "fd093bff70906175335656e6ce6ae05783708765",
+ "c47800c7266a2be04c571c04d5a6614691ea99bd",
+ "a71586c1dfe8a71c6cbf6c129f404c5642ff31bd",
+ "8496071c1b46c854b31185ea97743be6a8774479",
+ "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
+ "814889a078c031f61ed08ab5fa863aea9314344d",
+ "5b5b025afb0b4c913b4c338a42934a3863bf3644",
+ "1385f264afb75a56a5bec74243be9b367ba4ca08",
+ "f60079018b664e4e79329a7ef9559c8d9e0378d1",
+ "be3563ae3f795b2b4353bcce3a527ad0a4f7f644",
+ "75057dd4114e74cca1d750d0aee1647c903cb60a",
+ "fa49b077972391ad58037050f2a75f74e3671e92",
+ "9fd738e8f7967c078dceed8190330fc8648ee56a",
+ "1810dff58d8a660512d4832e740f692884338ccd",
+ "181037049a54a1eb5fab404658a3a250b44335d7",
+ "a4a7dce85cf63874e984719f4fdd239f5145052f",
+ "4a202b346bb0fb0db7eff3cffeb3c70babbd2045"
+};
diff --git a/tests/odb/pack_data_one.h b/tests/odb/pack_data_one.h
new file mode 100644
index 000000000..13570ba78
--- /dev/null
+++ b/tests/odb/pack_data_one.h
@@ -0,0 +1,19 @@
+/* Just a few to make sure it's working, the rest is tested already */
+static const char *packed_objects_one[] = {
+ "9fcf811e00fa469688943a9152c16d4ee90fb9a9",
+ "a93f42a5b5e9de40fa645a9ff1e276a021c9542b",
+ "12bf5f3e3470d90db177ccf1b5e8126409377fc6",
+ "ed1ea164cdbe3c4b200fb4fa19861ea90eaee222",
+ "dfae6ed8f6dd8acc3b40a31811ea316239223559",
+ "aefe66d192771201e369fde830530f4475beec30",
+ "775e4b4c1296e9e3104f2a36ca9cf9356a130959",
+ "412ec4e4a6a7419bc1be00561fe474e54cb499fe",
+ "236e7579fed7763be77209efb8708960982f3cb3",
+ "09fe9364461cf60dd1c46b0e9545b1e47bb1a297",
+ "d76d8a6390d1cf32138d98a91b1eb7e0275a12f5",
+ "d0fdf2dcff2f548952eec536ccc6d266550041bc",
+ "a20d733a9fa79fa5b4cbb9639864f93325ec27a6",
+ "785d3fe8e7db5ade2c2242fecd46c32a7f4dc59f",
+ "4d8d0fd9cb6045075385701c3f933ec13345e9c4",
+ "0cfd861bd547b6520d1fc2e190e8359e0a9c9b90"
+};
diff --git a/tests/odb/packed.c b/tests/odb/packed.c
new file mode 100644
index 000000000..b4f549b58
--- /dev/null
+++ b/tests/odb/packed.c
@@ -0,0 +1,79 @@
+#include "clar_libgit2.h"
+#include "odb.h"
+#include "pack_data.h"
+
+static git_odb *_odb;
+
+void test_odb_packed__initialize(void)
+{
+ cl_git_pass(git_odb_open(&_odb, cl_fixture("testrepo.git/objects")));
+}
+
+void test_odb_packed__cleanup(void)
+{
+ git_odb_free(_odb);
+ _odb = NULL;
+}
+
+void test_odb_packed__mass_read(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+
+ cl_git_pass(git_oid_fromstr(&id, packed_objects[i]));
+ cl_assert(git_odb_exists(_odb, &id) == 1);
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+
+ git_odb_object_free(obj);
+ }
+}
+
+void test_odb_packed__read_header_0(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(packed_objects); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+ size_t len;
+ git_otype type;
+
+ cl_git_pass(git_oid_fromstr(&id, packed_objects[i]));
+
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+ cl_git_pass(git_odb_read_header(&len, &type, _odb, &id));
+
+ cl_assert(obj->cached.size == len);
+ cl_assert(obj->cached.type == type);
+
+ git_odb_object_free(obj);
+ }
+}
+
+void test_odb_packed__read_header_1(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(loose_objects); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+ size_t len;
+ git_otype type;
+
+ cl_git_pass(git_oid_fromstr(&id, loose_objects[i]));
+
+ cl_assert(git_odb_exists(_odb, &id) == 1);
+
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+ cl_git_pass(git_odb_read_header(&len, &type, _odb, &id));
+
+ cl_assert(obj->cached.size == len);
+ cl_assert(obj->cached.type == type);
+
+ git_odb_object_free(obj);
+ }
+}
+
diff --git a/tests/odb/packed_one.c b/tests/odb/packed_one.c
new file mode 100644
index 000000000..0c6ed387b
--- /dev/null
+++ b/tests/odb/packed_one.c
@@ -0,0 +1,60 @@
+#include "clar_libgit2.h"
+#include "git2/odb_backend.h"
+
+#include "pack_data_one.h"
+#include "pack.h"
+
+static git_odb *_odb;
+
+void test_odb_packed_one__initialize(void)
+{
+ git_odb_backend *backend = NULL;
+
+ cl_git_pass(git_odb_new(&_odb));
+ cl_git_pass(git_odb_backend_one_pack(&backend, cl_fixture("testrepo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx")));
+ cl_git_pass(git_odb_add_backend(_odb, backend, 1));
+}
+
+void test_odb_packed_one__cleanup(void)
+{
+ git_odb_free(_odb);
+ _odb = NULL;
+}
+
+void test_odb_packed_one__mass_read(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(packed_objects_one); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+
+ cl_git_pass(git_oid_fromstr(&id, packed_objects_one[i]));
+ cl_assert(git_odb_exists(_odb, &id) == 1);
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+
+ git_odb_object_free(obj);
+ }
+}
+
+void test_odb_packed_one__read_header_0(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(packed_objects_one); ++i) {
+ git_oid id;
+ git_odb_object *obj;
+ size_t len;
+ git_otype type;
+
+ cl_git_pass(git_oid_fromstr(&id, packed_objects_one[i]));
+
+ cl_git_pass(git_odb_read(&obj, _odb, &id));
+ cl_git_pass(git_odb_read_header(&len, &type, _odb, &id));
+
+ cl_assert(obj->cached.size == len);
+ cl_assert(obj->cached.type == type);
+
+ git_odb_object_free(obj);
+ }
+}
diff --git a/tests/odb/sorting.c b/tests/odb/sorting.c
new file mode 100644
index 000000000..147a160c8
--- /dev/null
+++ b/tests/odb/sorting.c
@@ -0,0 +1,69 @@
+#include "clar_libgit2.h"
+#include "git2/sys/odb_backend.h"
+
+typedef struct {
+ git_odb_backend base;
+ size_t position;
+} fake_backend;
+
+static git_odb_backend *new_backend(size_t position)
+{
+ fake_backend *b;
+
+ b = git__calloc(1, sizeof(fake_backend));
+ if (b == NULL)
+ return NULL;
+
+ b->base.version = GIT_ODB_BACKEND_VERSION;
+ b->position = position;
+ return (git_odb_backend *)b;
+}
+
+static void check_backend_sorting(git_odb *odb)
+{
+ size_t i, max_i = git_odb_num_backends(odb);
+ fake_backend *internal;
+
+ for (i = 0; i < max_i; ++i) {
+ cl_git_pass(git_odb_get_backend((git_odb_backend **)&internal, odb, i));
+ cl_assert(internal != NULL);
+ cl_assert_equal_sz(i, internal->position);
+ }
+}
+
+static git_odb *_odb;
+
+void test_odb_sorting__initialize(void)
+{
+ cl_git_pass(git_odb_new(&_odb));
+}
+
+void test_odb_sorting__cleanup(void)
+{
+ git_odb_free(_odb);
+ _odb = NULL;
+}
+
+void test_odb_sorting__basic_backends_sorting(void)
+{
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(0), 5));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(2), 3));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(1), 4));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(3), 1));
+
+ check_backend_sorting(_odb);
+}
+
+void test_odb_sorting__alternate_backends_sorting(void)
+{
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(0), 5));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(2), 3));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(1), 4));
+ cl_git_pass(git_odb_add_backend(_odb, new_backend(3), 1));
+ cl_git_pass(git_odb_add_alternate(_odb, new_backend(4), 5));
+ cl_git_pass(git_odb_add_alternate(_odb, new_backend(6), 3));
+ cl_git_pass(git_odb_add_alternate(_odb, new_backend(5), 4));
+ cl_git_pass(git_odb_add_alternate(_odb, new_backend(7), 1));
+
+ check_backend_sorting(_odb);
+}
diff --git a/tests/odb/streamwrite.c b/tests/odb/streamwrite.c
new file mode 100644
index 000000000..591a20040
--- /dev/null
+++ b/tests/odb/streamwrite.c
@@ -0,0 +1,56 @@
+#include "clar_libgit2.h"
+#include "git2/odb_backend.h"
+
+static git_repository *repo;
+static git_odb *odb;
+static git_odb_stream *stream;
+
+void test_odb_streamwrite__initialize(void)
+{
+ repo = cl_git_sandbox_init("testrepo.git");
+ cl_git_pass(git_repository_odb(&odb, repo));
+
+ cl_git_pass(git_odb_open_wstream(&stream, odb, 14, GIT_OBJ_BLOB));
+ cl_assert_equal_sz(14, stream->declared_size);
+}
+
+void test_odb_streamwrite__cleanup(void)
+{
+ git_odb_stream_free(stream);
+ git_odb_free(odb);
+ cl_git_sandbox_cleanup();
+}
+
+void test_odb_streamwrite__can_accept_chunks(void)
+{
+ git_oid oid;
+
+ cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8));
+ cl_assert_equal_sz(8, stream->received_bytes);
+
+ cl_git_pass(git_odb_stream_write(stream, "deadbeef", 6));
+ cl_assert_equal_sz(8 + 6, stream->received_bytes);
+
+ cl_git_pass(git_odb_stream_finalize_write(&oid, stream));
+}
+
+void test_odb_streamwrite__can_detect_missing_bytes(void)
+{
+ git_oid oid;
+
+ cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8));
+ cl_assert_equal_sz(8, stream->received_bytes);
+
+ cl_git_pass(git_odb_stream_write(stream, "deadbeef", 4));
+ cl_assert_equal_sz(8 + 4, stream->received_bytes);
+
+ cl_git_fail(git_odb_stream_finalize_write(&oid, stream));
+}
+
+void test_odb_streamwrite__can_detect_additional_bytes(void)
+{
+ cl_git_pass(git_odb_stream_write(stream, "deadbeef", 8));
+ cl_assert_equal_sz(8, stream->received_bytes);
+
+ cl_git_fail(git_odb_stream_write(stream, "deadbeef", 7));
+}