diff options
| author | 2026-03-08 12:03:26 +0800 | |
|---|---|---|
| committer | 2026-03-08 12:03:26 +0800 | |
| commit | ae5c818674e2c9ca950ca7a9bf93f1283e7411b7 (patch) | |
| tree | 25d1702260993a8066690c93b3da81adea6d4258 /format/pack/ingest/ingest_test.go | |
| parent | receivepack: Trivial caps (diff) | |
receivepack, format/pack/ingest: Two-stage ingestion
Diffstat (limited to 'format/pack/ingest/ingest_test.go')
| -rw-r--r-- | format/pack/ingest/ingest_test.go | 96 |
1 files changed, 90 insertions, 6 deletions
diff --git a/format/pack/ingest/ingest_test.go b/format/pack/ingest/ingest_test.go index 8a88eb7f..95b6643c 100644 --- a/format/pack/ingest/ingest_test.go +++ b/format/pack/ingest/ingest_test.go @@ -2,7 +2,9 @@ package ingest_test import ( "bytes" + "encoding/binary" "errors" + "io" "io/fs" "os" "path/filepath" @@ -26,6 +28,20 @@ func (r *noExtraReadReader) Read(p []byte) (int, error) { return r.reader.Read(p) } +func beginAndContinue( + src io.Reader, + packRoot *os.Root, + algo objectid.Algorithm, + opts ingest.Options, +) (ingest.Result, error) { + pending, err := ingest.Ingest(src, algo, opts) + if err != nil { + return ingest.Result{}, err + } + + return pending.Continue(packRoot) +} + // fixturePath returns one fixture file path for the selected algorithm. func fixturePath(t *testing.T, algo objectid.Algorithm, name string) string { t.Helper() @@ -173,7 +189,7 @@ func TestIngestNonThinPackWritesPackIdxRev(t *testing.T) { packRoot := receiver.OpenPackRoot(t) - result, err := ingest.Ingest(bytes.NewReader(packBytes), packRoot, algo, ingest.Options{ + result, err := beginAndContinue(bytes.NewReader(packBytes), packRoot, algo, ingest.Options{ WriteRev: true, RequireTrailingEOF: true, }) @@ -221,7 +237,7 @@ func TestIngestThinPackWithoutFixReturnsUnresolved(t *testing.T) { receiver := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true}) packRoot := receiver.OpenPackRoot(t) - _, err := ingest.Ingest(bytes.NewReader(thinPack), packRoot, algo, ingest.Options{ + _, err := beginAndContinue(bytes.NewReader(thinPack), packRoot, algo, ingest.Options{ WriteRev: true, RequireTrailingEOF: true, }) @@ -257,7 +273,7 @@ func TestIngestThinPackWithFixThin(t *testing.T) { packRoot := receiver.OpenPackRoot(t) - _, err := ingest.Ingest(bytes.NewReader(basePack), packRoot, algo, ingest.Options{ + _, err := beginAndContinue(bytes.NewReader(basePack), packRoot, algo, ingest.Options{ RequireTrailingEOF: true, }) if err != nil { @@ -266,7 +282,7 @@ func TestIngestThinPackWithFixThin(t *testing.T) { receiverRepo := receiver.OpenRepository(t) - result, err := ingest.Ingest(bytes.NewReader(thinPack), packRoot, algo, ingest.Options{ + result, err := beginAndContinue(bytes.NewReader(thinPack), packRoot, algo, ingest.Options{ FixThin: true, WriteRev: true, Base: receiverRepo.Objects(), @@ -301,7 +317,7 @@ func TestIngestPackTrailerMismatch(t *testing.T) { receiver := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true}) packRoot := receiver.OpenPackRoot(t) - _, err := ingest.Ingest(bytes.NewReader(packBytes), packRoot, algo, ingest.Options{ + _, err := beginAndContinue(bytes.NewReader(packBytes), packRoot, algo, ingest.Options{ WriteRev: true, RequireTrailingEOF: true, }) @@ -326,6 +342,74 @@ func TestIngestPackTrailerMismatch(t *testing.T) { }) } +func zeroObjectPackBytes(t *testing.T, algo objectid.Algorithm) []byte { + t.Helper() + + hashImpl, err := algo.New() + if err != nil { + t.Fatalf("algo.New: %v", err) + } + + var header [12]byte + copy(header[:4], []byte{'P', 'A', 'C', 'K'}) + binary.BigEndian.PutUint32(header[4:8], 2) + binary.BigEndian.PutUint32(header[8:12], 0) + + _, _ = hashImpl.Write(header[:]) + + return append(header[:], hashImpl.Sum(nil)...) +} + +func TestIngestDiscardZeroObjectPack(t *testing.T) { + t.Parallel() + + testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper + packBytes := zeroObjectPackBytes(t, algo) + + pending, err := ingest.Ingest(bytes.NewReader(packBytes), algo, ingest.Options{ + RequireTrailingEOF: true, + }) + if err != nil { + t.Fatalf("Ingest: %v", err) + } + + if pending.Header().ObjectCount != 0 { + t.Fatalf("ObjectCount = %d, want 0", pending.Header().ObjectCount) + } + + discarded, err := pending.Discard() + if err != nil { + t.Fatalf("Discard: %v", err) + } + + if discarded.ObjectCount != 0 { + t.Fatalf("Discard.ObjectCount = %d, want 0", discarded.ObjectCount) + } + }) +} + +func TestIngestContinueRejectsZeroObjectPack(t *testing.T) { + t.Parallel() + + testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { //nolint:thelper + packBytes := zeroObjectPackBytes(t, algo) + receiver := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true}) + packRoot := receiver.OpenPackRoot(t) + + pending, err := ingest.Ingest(bytes.NewReader(packBytes), algo, ingest.Options{ + RequireTrailingEOF: true, + }) + if err != nil { + t.Fatalf("Ingest: %v", err) + } + + _, err = pending.Continue(packRoot) + if !errors.Is(err, ingest.ErrZeroObjectContinue) { + t.Fatalf("Continue error = %v, want ErrZeroObjectContinue", err) + } + }) +} + func TestIngestCanFinishWithoutTrailingEOF(t *testing.T) { t.Parallel() @@ -336,7 +420,7 @@ func TestIngestCanFinishWithoutTrailingEOF(t *testing.T) { receiver := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: algo, Bare: true}) packRoot := receiver.OpenPackRoot(t) - result, err := ingest.Ingest(&noExtraReadReader{reader: bytes.NewReader(packBytes)}, packRoot, algo, ingest.Options{ + result, err := beginAndContinue(&noExtraReadReader{reader: bytes.NewReader(packBytes)}, packRoot, algo, ingest.Options{ WriteRev: true, }) if err != nil { |
