aboutsummaryrefslogtreecommitdiff
path: root/object/storer/loose/write_test.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-25 14:34:50 +0000
committerGravatar Runxi Yu2026-03-25 14:34:50 +0000
commite4a7aa0742f5070299d37e8421c99d67f0af3f90 (patch)
tree36d89781476a92e61280c5ff232a2773e4092c0e /object/storer/loose/write_test.go
parent*: delta -> packfile/delta (diff)
signatureNo signature
*: object/store -> object/storer v0.1.107
Diffstat (limited to 'object/storer/loose/write_test.go')
-rw-r--r--object/storer/loose/write_test.go137
1 files changed, 137 insertions, 0 deletions
diff --git a/object/storer/loose/write_test.go b/object/storer/loose/write_test.go
new file mode 100644
index 00000000..30d8dbdb
--- /dev/null
+++ b/object/storer/loose/write_test.go
@@ -0,0 +1,137 @@
+package loose_test
+
+import (
+ "bytes"
+ "testing"
+
+ "codeberg.org/lindenii/furgit/internal/testgit"
+ objectheader "codeberg.org/lindenii/furgit/object/header"
+ objectid "codeberg.org/lindenii/furgit/object/id"
+ objecttype "codeberg.org/lindenii/furgit/object/type"
+)
+
+func TestLooseStoreWriteReaderContentAgainstGit(t *testing.T) {
+ t.Parallel()
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
+ testRepo := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true})
+ store := openLooseStore(t, testRepo, algo)
+
+ content := []byte("written-by-content-reader\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.WriteReaderContent(objecttype.TypeBlob, int64(len(content)), bytes.NewReader(content))
+ if err != nil {
+ t.Fatalf("WriteReaderContent: %v", err)
+ }
+
+ if writtenID != expectedID {
+ t.Fatalf("WriteReaderContent 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.
+ writtenID2, err := store.WriteReaderContent(objecttype.TypeBlob, int64(len(content)), bytes.NewReader(content))
+ if err != nil {
+ t.Fatalf("WriteReaderContent second: %v", err)
+ }
+
+ if writtenID2 != expectedID {
+ t.Fatalf("WriteReaderContent second id = %s, want %s", writtenID2, expectedID)
+ }
+ })
+}
+
+func TestLooseStoreWriteReaderFullAgainstGit(t *testing.T) {
+ t.Parallel()
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
+ testRepo := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true})
+ store := openLooseStore(t, testRepo, algo)
+
+ body := []byte("full-reader-body\n")
+
+ header, ok := objectheader.Encode(objecttype.TypeBlob, int64(len(body)))
+ if !ok {
+ t.Fatalf("objectheader.Encode failed")
+ }
+
+ raw := make([]byte, len(header)+len(body))
+ copy(raw, header)
+ copy(raw[len(header):], body)
+
+ wantID := algo.Sum(raw)
+
+ gotID, err := store.WriteReaderFull(bytes.NewReader(raw))
+ if err != nil {
+ t.Fatalf("WriteReaderFull: %v", err)
+ }
+
+ if gotID != wantID {
+ t.Fatalf("WriteReaderFull id = %s, want %s", gotID, wantID)
+ }
+
+ gotBody := testRepo.CatFile(t, "blob", gotID)
+ if !bytes.Equal(gotBody, body) {
+ t.Fatalf("git cat-file body mismatch")
+ }
+ })
+}
+
+func TestLooseStoreReaderValidationErrors(t *testing.T) {
+ t.Parallel()
+ testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper
+ t.Run("content overflow", func(t *testing.T) {
+ t.Parallel()
+ testRepo := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true})
+ store := openLooseStore(t, testRepo, algo)
+
+ _, err := store.WriteReaderContent(objecttype.TypeBlob, 1, bytes.NewReader([]byte("hello")))
+ if err == nil {
+ t.Fatalf("expected error after overflow")
+ }
+ })
+
+ t.Run("content short", func(t *testing.T) {
+ t.Parallel()
+ testRepo := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true})
+ store := openLooseStore(t, testRepo, algo)
+
+ _, err := store.WriteReaderContent(objecttype.TypeBlob, 5, bytes.NewReader([]byte("x")))
+ if err == nil {
+ t.Fatalf("expected error for short content")
+ }
+ })
+
+ t.Run("full malformed header", func(t *testing.T) {
+ t.Parallel()
+ testRepo := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true})
+ store := openLooseStore(t, testRepo, algo)
+
+ _, err := store.WriteReaderFull(bytes.NewReader([]byte("not-a-header")))
+ if err == nil {
+ t.Fatalf("expected error for malformed header")
+ }
+ })
+
+ t.Run("full size mismatch", func(t *testing.T) {
+ t.Parallel()
+ testRepo := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true})
+ store := openLooseStore(t, testRepo, algo)
+
+ raw := []byte("blob 1\x00hello")
+
+ _, err := store.WriteReaderFull(bytes.NewReader(raw))
+ if err == nil {
+ t.Fatalf("expected error after mismatch")
+ }
+ })
+ })
+}