aboutsummaryrefslogtreecommitdiff
path: root/objectstore/packed/read_test.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-02-21 05:35:12 +0800
committerGravatar Runxi Yu2026-02-21 11:15:18 +0800
commitae879b8cf5a87199802a33d6b15c76afafa8002b (patch)
treea93e9486a9610b78823e157c68b75e0724366217 /objectstore/packed/read_test.go
parentcache/lru: Add basic LRU (diff)
signatureNo signature
objectstore/packed: Add initial pack reading support
Diffstat (limited to 'objectstore/packed/read_test.go')
-rw-r--r--objectstore/packed/read_test.go149
1 files changed, 149 insertions, 0 deletions
diff --git a/objectstore/packed/read_test.go b/objectstore/packed/read_test.go
new file mode 100644
index 00000000..9244d573
--- /dev/null
+++ b/objectstore/packed/read_test.go
@@ -0,0 +1,149 @@
+package packed_test
+
+import (
+ "bytes"
+ "errors"
+ "os"
+ "strings"
+ "testing"
+
+ "codeberg.org/lindenii/furgit/internal/testgit"
+ "codeberg.org/lindenii/furgit/objectid"
+ "codeberg.org/lindenii/furgit/objectstore"
+ "codeberg.org/lindenii/furgit/objectstore/packed"
+)
+
+func TestPackedStoreReadAgainstGit(t *testing.T) {
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
+ testRepo, ids := createPackedFixtureRepo(t, algo)
+ store := openPackedStore(t, testRepo.Dir(), algo)
+
+ for _, id := range ids {
+ id := id
+ t.Run(id.String(), func(t *testing.T) {
+ wantType, wantBody, wantRaw := expectedRawObject(t, testRepo, id)
+
+ gotHeaderType, gotHeaderSize, err := store.ReadHeader(id)
+ if err != nil {
+ t.Fatalf("ReadHeader: %v", err)
+ }
+ if gotHeaderType != wantType {
+ t.Fatalf("ReadHeader type = %v, want %v", gotHeaderType, wantType)
+ }
+ if gotHeaderSize != int64(len(wantBody)) {
+ t.Fatalf("ReadHeader size = %d, want %d", gotHeaderSize, len(wantBody))
+ }
+
+ gotRaw, err := store.ReadBytesFull(id)
+ if err != nil {
+ t.Fatalf("ReadBytesFull: %v", err)
+ }
+ if !bytes.Equal(gotRaw, wantRaw) {
+ t.Fatalf("ReadBytesFull mismatch")
+ }
+
+ gotType, gotBody, err := store.ReadBytesContent(id)
+ if err != nil {
+ t.Fatalf("ReadBytesContent: %v", err)
+ }
+ if gotType != wantType {
+ t.Fatalf("ReadBytesContent type = %v, want %v", gotType, wantType)
+ }
+ if !bytes.Equal(gotBody, wantBody) {
+ t.Fatalf("ReadBytesContent mismatch")
+ }
+
+ fullReader, err := store.ReadReaderFull(id)
+ if err != nil {
+ t.Fatalf("ReadReaderFull: %v", err)
+ }
+ if got := mustReadAllAndClose(t, fullReader); !bytes.Equal(got, wantRaw) {
+ t.Fatalf("ReadReaderFull mismatch")
+ }
+
+ contentType, contentSize, contentReader, err := store.ReadReaderContent(id)
+ if err != nil {
+ t.Fatalf("ReadReaderContent: %v", err)
+ }
+ if contentType != wantType {
+ t.Fatalf("ReadReaderContent type = %v, want %v", contentType, wantType)
+ }
+ if contentSize != int64(len(wantBody)) {
+ t.Fatalf("ReadReaderContent size = %d, want %d", contentSize, len(wantBody))
+ }
+ if got := mustReadAllAndClose(t, contentReader); !bytes.Equal(got, wantBody) {
+ t.Fatalf("ReadReaderContent mismatch")
+ }
+ })
+ }
+ })
+}
+
+func TestPackedStoreErrors(t *testing.T) {
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
+ testRepo, _ := createPackedFixtureRepo(t, algo)
+ store := openPackedStore(t, testRepo.Dir(), algo)
+
+ notFoundID, err := objectid.ParseHex(algo, strings.Repeat("0", algo.HexLen()))
+ if err != nil {
+ t.Fatalf("ParseHex(notFound): %v", err)
+ }
+
+ if _, err := store.ReadBytesFull(notFoundID); !errors.Is(err, objectstore.ErrObjectNotFound) {
+ t.Fatalf("ReadBytesFull not-found error = %v", err)
+ }
+ if _, _, err := store.ReadBytesContent(notFoundID); !errors.Is(err, objectstore.ErrObjectNotFound) {
+ t.Fatalf("ReadBytesContent not-found error = %v", err)
+ }
+ if _, err := store.ReadReaderFull(notFoundID); !errors.Is(err, objectstore.ErrObjectNotFound) {
+ t.Fatalf("ReadReaderFull not-found error = %v", err)
+ }
+ if _, _, _, err := store.ReadReaderContent(notFoundID); !errors.Is(err, objectstore.ErrObjectNotFound) {
+ t.Fatalf("ReadReaderContent not-found error = %v", err)
+ }
+ if _, _, err := store.ReadHeader(notFoundID); !errors.Is(err, objectstore.ErrObjectNotFound) {
+ t.Fatalf("ReadHeader not-found error = %v", err)
+ }
+
+ var otherAlgo objectid.Algorithm
+ for _, candidate := range objectid.SupportedAlgorithms() {
+ if candidate != algo {
+ otherAlgo = candidate
+ break
+ }
+ }
+ if otherAlgo != objectid.AlgorithmUnknown {
+ mismatchID, err := objectid.ParseHex(otherAlgo, strings.Repeat("0", otherAlgo.HexLen()))
+ if err != nil {
+ t.Fatalf("ParseHex(mismatch): %v", err)
+ }
+ if _, err := store.ReadBytesFull(mismatchID); err == nil || !strings.Contains(err.Error(), "algorithm mismatch") {
+ t.Fatalf("ReadBytesFull algorithm-mismatch error = %v", err)
+ }
+ }
+ })
+}
+
+func TestPackedStoreNewValidation(t *testing.T) {
+ testRepo, _ := createPackedFixtureRepo(t, objectid.AlgorithmSHA1)
+ store := openPackedStore(t, testRepo.Dir(), objectid.AlgorithmSHA1)
+ if err := store.Close(); err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+ if err := store.Close(); err != nil {
+ t.Fatalf("Close second: %v", err)
+ }
+}
+
+func TestPackedStoreInvalidAlgorithm(t *testing.T) {
+ testRepo := testgit.NewBareRepo(t, objectid.AlgorithmSHA1)
+ root, err := os.OpenRoot(testRepo.Dir())
+ if err != nil {
+ t.Fatalf("OpenRoot(%q): %v", testRepo.Dir(), err)
+ }
+ t.Cleanup(func() { _ = root.Close() })
+
+ if _, err := packed.New(root, objectid.AlgorithmUnknown); !errors.Is(err, objectid.ErrInvalidAlgorithm) {
+ t.Fatalf("packed.New invalid algorithm error = %v", err)
+ }
+}