aboutsummaryrefslogtreecommitdiff
path: root/objectstore/loose/write_test.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-02-21 04:55:02 +0800
committerGravatar Runxi Yu2026-02-21 04:55:02 +0800
commit564c8ecc84ed1bfc28ea3a0251020051906b8548 (patch)
tree1961ff46e328a997ffc2d2f19f53ee16f0952d3a /objectstore/loose/write_test.go
parentobjectstore/loose: Add loose writer in bytes (diff)
signatureNo signature
objectstore/loose: Add streaming writer
Diffstat (limited to 'objectstore/loose/write_test.go')
-rw-r--r--objectstore/loose/write_test.go145
1 files changed, 114 insertions, 31 deletions
diff --git a/objectstore/loose/write_test.go b/objectstore/loose/write_test.go
index 835d451f..0dcb3a5f 100644
--- a/objectstore/loose/write_test.go
+++ b/objectstore/loose/write_test.go
@@ -2,6 +2,7 @@ package loose_test
import (
"bytes"
+ "io"
"testing"
"codeberg.org/lindenii/furgit/internal/testgit"
@@ -10,47 +11,68 @@ import (
"codeberg.org/lindenii/furgit/objecttype"
)
-func TestLooseStoreWriteBytesContentAgainstGit(t *testing.T) {
+func TestLooseStoreWriteWriterContentAgainstGit(t *testing.T) {
testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
testRepo := testgit.NewBareRepo(t, algo)
store := openLooseStore(t, testRepo.Dir(), algo)
- content := []byte("written-by-loose-store\n")
+ content := []byte("written-by-content-writer\n")
expectedHex := testRepo.RunInput(t, content, "hash-object", "-t", "blob", "--stdin")
expectedID, err := objectid.ParseHex(algo, expectedHex)
if err != nil {
t.Fatalf("ParseHex(expected): %v", err)
}
- writtenID, err := store.WriteBytesContent(objecttype.TypeBlob, content)
+ writer, finalize, err := store.WriteWriterContent(objecttype.TypeBlob, int64(len(content)))
if err != nil {
- t.Fatalf("WriteBytesContent: %v", err)
+ t.Fatalf("WriteWriterContent: %v", err)
}
- if writtenID != expectedID {
- t.Fatalf("WriteBytesContent id = %s, want %s", writtenID, expectedID)
+ if _, err := io.Copy(writer, bytes.NewReader(content)); err != nil {
+ t.Fatalf("WriteWriterContent write: %v", err)
}
-
- gotBody := testRepo.CatFile(t, "blob", writtenID)
- if !bytes.Equal(gotBody, content) {
- t.Fatalf("git cat-file body mismatch")
+ if err := writer.Close(); err != nil {
+ t.Fatalf("WriteWriterContent close: %v", err)
}
-
- writtenID2, err := store.WriteBytesContent(objecttype.TypeBlob, content)
+ writtenID, err := finalize()
if err != nil {
- t.Fatalf("WriteBytesContent second write: %v", err)
+ t.Fatalf("WriteWriterContent finalize: %v", err)
}
- if writtenID2 != expectedID {
- t.Fatalf("WriteBytesContent second id = %s, want %s", writtenID2, expectedID)
+ if writtenID != expectedID {
+ t.Fatalf("WriteWriterContent id = %s, want %s", writtenID, expectedID)
}
- })
+
+ gotBody := testRepo.CatFile(t, "blob", writtenID)
+ if !bytes.Equal(gotBody, content) {
+ t.Fatalf("git cat-file body mismatch")
+ }
+
+ // Writing the same object again should succeed and return the same ID.
+ writer, finalize, err = store.WriteWriterContent(objecttype.TypeBlob, int64(len(content)))
+ if err != nil {
+ t.Fatalf("WriteWriterContent second: %v", err)
+ }
+ if _, err := io.Copy(writer, bytes.NewReader(content)); err != nil {
+ t.Fatalf("WriteWriterContent second write: %v", err)
+ }
+ if err := writer.Close(); err != nil {
+ t.Fatalf("WriteWriterContent second close: %v", err)
+ }
+ writtenID2, err := finalize()
+ if err != nil {
+ t.Fatalf("WriteWriterContent second finalize: %v", err)
+ }
+ if writtenID2 != expectedID {
+ t.Fatalf("WriteWriterContent second id = %s, want %s", writtenID2, expectedID)
+ }
+ })
}
-func TestLooseStoreWriteBytesFullAgainstGit(t *testing.T) {
+func TestLooseStoreWriteWriterFullAgainstGit(t *testing.T) {
testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
testRepo := testgit.NewBareRepo(t, algo)
store := openLooseStore(t, testRepo.Dir(), algo)
- body := []byte("full-write-body\n")
+ body := []byte("full-writer-body\n")
header, ok := objectheader.Encode(objecttype.TypeBlob, int64(len(body)))
if !ok {
t.Fatalf("objectheader.Encode failed")
@@ -60,12 +82,22 @@ func TestLooseStoreWriteBytesFullAgainstGit(t *testing.T) {
copy(raw[len(header):], body)
wantID := algo.Sum(raw)
- gotID, err := store.WriteBytesFull(raw)
+ writer, finalize, err := store.WriteWriterFull()
+ if err != nil {
+ t.Fatalf("WriteWriterFull: %v", err)
+ }
+ if _, err := io.Copy(writer, bytes.NewReader(raw)); err != nil {
+ t.Fatalf("WriteWriterFull write: %v", err)
+ }
+ if err := writer.Close(); err != nil {
+ t.Fatalf("WriteWriterFull close: %v", err)
+ }
+ gotID, err := finalize()
if err != nil {
- t.Fatalf("WriteBytesFull: %v", err)
+ t.Fatalf("WriteWriterFull finalize: %v", err)
}
if gotID != wantID {
- t.Fatalf("WriteBytesFull id = %s, want %s", gotID, wantID)
+ t.Fatalf("WriteWriterFull id = %s, want %s", gotID, wantID)
}
gotBody := testRepo.CatFile(t, "blob", gotID)
@@ -75,19 +107,70 @@ func TestLooseStoreWriteBytesFullAgainstGit(t *testing.T) {
})
}
-func TestLooseStoreWriteValidationErrors(t *testing.T) {
+func TestLooseStoreWriterValidationErrors(t *testing.T) {
testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) {
testRepo := testgit.NewBareRepo(t, algo)
store := openLooseStore(t, testRepo.Dir(), algo)
- if _, err := store.WriteBytesFull([]byte("blob 1\x00hello")); err == nil {
- t.Fatalf("WriteBytesFull expected size/content mismatch error")
- }
- if _, err := store.WriteBytesFull([]byte("not-a-header")); err == nil {
- t.Fatalf("WriteBytesFull expected malformed header error")
- }
- if _, err := store.WriteBytesContent(objecttype.TypeInvalid, []byte("x")); err == nil {
- t.Fatalf("WriteBytesContent expected invalid type error")
- }
+ t.Run("content overflow", func(t *testing.T) {
+ writer, finalize, err := store.WriteWriterContent(objecttype.TypeBlob, 1)
+ if err != nil {
+ t.Fatalf("WriteWriterContent: %v", err)
+ }
+ if _, err := writer.Write([]byte("hello")); err == nil {
+ t.Fatalf("expected overflow error")
+ }
+ _ = writer.Close()
+ if _, err := finalize(); err == nil {
+ t.Fatalf("expected finalize error after overflow")
+ }
+ })
+
+ t.Run("content short", func(t *testing.T) {
+ writer, finalize, err := store.WriteWriterContent(objecttype.TypeBlob, 5)
+ if err != nil {
+ t.Fatalf("WriteWriterContent: %v", err)
+ }
+ if _, err := writer.Write([]byte("x")); err != nil {
+ t.Fatalf("write short: %v", err)
+ }
+ if err := writer.Close(); err != nil {
+ t.Fatalf("close short: %v", err)
+ }
+ if _, err := finalize(); err == nil {
+ t.Fatalf("expected finalize error for short content")
+ }
+ })
+
+ t.Run("full malformed header", func(t *testing.T) {
+ writer, finalize, err := store.WriteWriterFull()
+ if err != nil {
+ t.Fatalf("WriteWriterFull: %v", err)
+ }
+ if _, err := writer.Write([]byte("not-a-header")); err != nil {
+ t.Fatalf("write malformed header bytes unexpectedly failed: %v", err)
+ }
+ if err := writer.Close(); err != nil {
+ t.Fatalf("close malformed header: %v", err)
+ }
+ if _, err := finalize(); err == nil {
+ t.Fatalf("expected finalize error for malformed header")
+ }
+ })
+
+ t.Run("full size mismatch", func(t *testing.T) {
+ writer, finalize, err := store.WriteWriterFull()
+ if err != nil {
+ t.Fatalf("WriteWriterFull: %v", err)
+ }
+ raw := []byte("blob 1\x00hello")
+ if _, err := io.Copy(writer, bytes.NewReader(raw)); err == nil {
+ t.Fatalf("expected overflow error")
+ }
+ _ = writer.Close()
+ if _, err := finalize(); err == nil {
+ t.Fatalf("expected finalize error after mismatch")
+ }
+ })
})
}