aboutsummaryrefslogtreecommitdiff
package packed_test

import (
	"bytes"
	"io"
	"testing"

	"lindenii.org/go/furgit/object/id"
	"lindenii.org/go/furgit/object/store/packed"
	"lindenii.org/go/furgit/object/typ"
)

func TestReadGitPack(t *testing.T) {
	t.Parallel()

	for _, objectFormat := range id.SupportedObjectFormats() {
		t.Run(objectFormat.String(), func(t *testing.T) {
			t.Parallel()

			repo, prefix, seeded := makeGitPack(t, objectFormat)
			requireDeltas(t, repo, prefix, objectFormat)

			packedStore := openPackedStore(t, prefix, objectFormat)

			groups := []struct {
				ty   typ.Type
				oids []id.ObjectID
			}{
				{ty: typ.Blob, oids: seeded.Blobs},
				{ty: typ.Tree, oids: seeded.Trees},
				{ty: typ.Commit, oids: seeded.Commits},
				{ty: typ.Tag, oids: seeded.Tags},
			}

			for _, group := range groups {
				for _, oid := range group.oids {
					wantContent, err := repo.CatFile(t, group.ty, oid)
					if err != nil {
						t.Fatalf("CatFile(%s): %v", oid, err)
					}

					ty, content, err := packedStore.ReadBytesContent(oid)
					if err != nil {
						t.Fatalf("ReadBytesContent(%s): %v", oid, err)
					}

					if ty != group.ty {
						t.Fatalf("ReadBytesContent(%s) type = %v, want %v", oid, ty, group.ty)
					}

					if !bytes.Equal(content, wantContent) {
						t.Fatalf("ReadBytesContent(%s) content mismatch", oid)
					}

					raw, err := packedStore.ReadBytesFull(oid)
					if err != nil {
						t.Fatalf("ReadBytesFull(%s): %v", oid, err)
					}

					if got := objectFormat.Sum(raw); got != oid {
						t.Fatalf("ReadBytesFull(%s) hashes to %s", oid, got)
					}

					ty, size, err := packedStore.ReadHeader(oid)
					if err != nil {
						t.Fatalf("ReadHeader(%s): %v", oid, err)
					}

					if ty != group.ty {
						t.Fatalf("ReadHeader(%s) type = %v, want %v", oid, ty, group.ty)
					}

					if size != len(wantContent) {
						t.Fatalf("ReadHeader(%s) size = %d, want %d", oid, size, len(wantContent))
					}

					size, err = packedStore.ReadSize(oid)
					if err != nil {
						t.Fatalf("ReadSize(%s): %v", oid, err)
					}

					if size != len(wantContent) {
						t.Fatalf("ReadSize(%s) = %d, want %d", oid, size, len(wantContent))
					}

					checkReaderContent(t, packedStore, oid, group.ty, wantContent)
					checkReaderFull(t, packedStore, oid, objectFormat)
				}
			}
		})
	}
}

func checkReaderContent(t *testing.T, packedStore *packed.Packed, oid id.ObjectID, wantType typ.Type, wantContent []byte) {
	t.Helper()

	ty, size, reader, err := packedStore.ReadReaderContent(oid)
	if err != nil {
		t.Fatalf("ReadReaderContent(%s): %v", oid, err)
	}

	defer func() { _ = reader.Close() }()

	if ty != wantType {
		t.Fatalf("ReadReaderContent(%s) type = %v, want %v", oid, ty, wantType)
	}

	if size != len(wantContent) {
		t.Fatalf("ReadReaderContent(%s) size = %d, want %d", oid, size, len(wantContent))
	}

	content, err := io.ReadAll(reader)
	if err != nil {
		t.Fatalf("ReadReaderContent(%s) read: %v", oid, err)
	}

	if !bytes.Equal(content, wantContent) {
		t.Fatalf("ReadReaderContent(%s) content mismatch", oid)
	}
}

func checkReaderFull(t *testing.T, packedStore *packed.Packed, oid id.ObjectID, objectFormat id.ObjectFormat) {
	t.Helper()

	reader, err := packedStore.ReadReaderFull(oid)
	if err != nil {
		t.Fatalf("ReadReaderFull(%s): %v", oid, err)
	}

	defer func() { _ = reader.Close() }()

	raw, err := io.ReadAll(reader)
	if err != nil {
		t.Fatalf("ReadReaderFull(%s) read: %v", oid, err)
	}

	if got := objectFormat.Sum(raw); got != oid {
		t.Fatalf("ReadReaderFull(%s) hashes to %s", oid, got)
	}
}