From f1aabdd293c5898f8e26f6e303030929f6a4a836 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sun, 23 Nov 2025 18:08:56 +0100 Subject: [PATCH] index: add test for pending blobs --- .../repository/index/master_index_test.go | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/internal/repository/index/master_index_test.go b/internal/repository/index/master_index_test.go index 98cfe9ac6..39837f53e 100644 --- a/internal/repository/index/master_index_test.go +++ b/internal/repository/index/master_index_test.go @@ -118,6 +118,85 @@ func TestMasterIndex(t *testing.T) { rtest.Assert(t, !found, "Expected no blobs when fetching with a random id") } +func TestMasterIndexAddPending(t *testing.T) { + mIdx := index.NewMasterIndex() + + // Test AddPending: successfully add a new blob + bhPending := restic.NewRandomBlobHandle() + added := mIdx.AddPending(bhPending, 100) + rtest.Equals(t, true, added) + + // Test AddPending: try to add the same blob again (should return false) + added = mIdx.AddPending(bhPending, 200) + rtest.Equals(t, false, added) + + // Test AddPending: try to add a blob that's already in an index (should return false) + bhInIndex := restic.NewRandomBlobHandle() + idx := index.NewIndex() + idx.StorePack(restic.NewRandomID(), []restic.Blob{{ + BlobHandle: bhInIndex, + Length: uint(crypto.CiphertextLength(50)), + Offset: 0, + UncompressedLength: 50, + }}) + mIdx.Insert(idx) + + added = mIdx.AddPending(bhInIndex, 100) + rtest.Equals(t, false, added) + + // Test LookupSize: returns pending blob size when blob is pending + size, found := mIdx.LookupSize(bhPending) + rtest.Equals(t, true, found) + rtest.Equals(t, uint(100), size) +} + +// noopSaver is a no-op implementation of SaverUnpacked for testing. +type noopSaver struct{} + +func (n *noopSaver) Connections() uint { + return 2 +} + +func (n *noopSaver) SaveUnpacked(_ context.Context, _ restic.FileType, buf []byte) (restic.ID, error) { + return restic.Hash(buf), nil +} + +func TestMasterIndexStorePackRemovesPending(t *testing.T) { + mIdx := index.NewMasterIndex() + + // Add a blob as pending + bhPending := restic.NewRandomBlobHandle() + added := mIdx.AddPending(bhPending, 75) + rtest.Equals(t, true, added) + + // Store the blob in a pack + packID := restic.NewRandomID() + blob := restic.Blob{ + BlobHandle: bhPending, + Length: uint(crypto.CiphertextLength(75)), + Offset: 0, + UncompressedLength: 75, + } + saver := &noopSaver{} + err := mIdx.StorePack(context.Background(), packID, []restic.Blob{blob}, saver) + rtest.OK(t, err) + + // Verify it is still found + size, found := mIdx.LookupSize(bhPending) + rtest.Equals(t, true, found) + rtest.Equals(t, uint(75), size) + + // Verify the blob can be found via Lookup from the index + blobs := mIdx.Lookup(bhPending) + rtest.Assert(t, len(blobs) > 0, "blob should be found in index after StorePack") + rtest.Equals(t, packID, blobs[0].PackID) + rtest.Equals(t, bhPending, blobs[0].BlobHandle) + + // Test that adding the same blob as pending again fails (it's now in index) + added = mIdx.AddPending(bhPending, 100) + rtest.Equals(t, false, added) +} + func TestMasterMergeFinalIndexes(t *testing.T) { bhInIdx1 := restic.NewRandomBlobHandle() bhInIdx2 := restic.NewRandomBlobHandle()