From 3cb49556f56ee61bf87799404e5179f010c99066 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sun, 31 May 2026 22:39:16 +0200 Subject: [PATCH] repair index: replace full index handling integration test with unit test --- .../cmd_repair_index_integration_test.go | 10 ---- .../repository/index/master_index_test.go | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/cmd/restic/cmd_repair_index_integration_test.go b/cmd/restic/cmd_repair_index_integration_test.go index 0a56f4b7a..a93e3df10 100644 --- a/cmd/restic/cmd_repair_index_integration_test.go +++ b/cmd/restic/cmd_repair_index_integration_test.go @@ -11,7 +11,6 @@ import ( "github.com/restic/restic/internal/backend" "github.com/restic/restic/internal/errors" "github.com/restic/restic/internal/global" - "github.com/restic/restic/internal/repository/index" "github.com/restic/restic/internal/restic" rtest "github.com/restic/restic/internal/test" ) @@ -61,15 +60,6 @@ func TestRebuildIndex(t *testing.T) { testRebuildIndex(t, nil) } -func TestRebuildIndexAlwaysFull(t *testing.T) { - indexFull := index.Full - defer func() { - index.Full = indexFull - }() - index.Full = func(*index.Index) bool { return true } - testRebuildIndex(t, nil) -} - // indexErrorBackend modifies the first index after reading. type indexErrorBackend struct { backend.Backend diff --git a/internal/repository/index/master_index_test.go b/internal/repository/index/master_index_test.go index fb5344659..56d01a503 100644 --- a/internal/repository/index/master_index_test.go +++ b/internal/repository/index/master_index_test.go @@ -694,3 +694,62 @@ func TestRewriteSplitPacks(t *testing.T) { blobs := mi.Lookup(blobOther.BlobHandle) rtest.Equals(t, nil, blobs) } + +// TestRewriteFullPacks checks that Rewrite drops a duplicate full index for the same +// pack while keeping the other index files and blob lookups intact. Creates 3 indexes: +// - indexA: contains packA +// - indexB: contains packB +// - indexC: contains packB +// After the rewrite, indexC must be dropped. The other indexes must be kept. +func TestRewriteFullPacks(t *testing.T) { + originalFull := index.Full + defer func() { + index.Full = originalFull + }() + index.Full = func(*index.Index) bool { return true } + + repo, unpacked, _ := repository.TestRepositoryWithVersion(t, restic.StableRepoVersion) + + packA := restic.NewRandomID() + packB := restic.NewRandomID() + + blobA := restic.PackedBlob{ + PackID: packA, + Blob: restic.Blob{ + BlobHandle: restic.NewRandomBlobHandle(), + Length: uint(crypto.CiphertextLength(10)), + Offset: 0, + }, + } + blobB := restic.PackedBlob{ + PackID: packB, + Blob: restic.Blob{ + BlobHandle: restic.NewRandomBlobHandle(), + Length: uint(crypto.CiphertextLength(50)), + Offset: 0, + }, + } + + mi := index.NewMasterIndex() + rtest.OK(t, mi.StorePack(context.TODO(), packA, restic.Blobs{blobA.Blob}, unpacked)) + rtest.OK(t, mi.Flush(context.TODO(), unpacked)) + rtest.OK(t, mi.StorePack(context.TODO(), packB, restic.Blobs{blobB.Blob}, unpacked)) + rtest.OK(t, mi.Flush(context.TODO(), unpacked)) + rtest.OK(t, mi.StorePack(context.TODO(), packB, restic.Blobs{blobB.Blob}, unpacked)) + rtest.OK(t, mi.Flush(context.TODO(), unpacked)) + + indexIDs := mi.IDs() + rtest.Equals(t, 3, len(indexIDs)) + + rtest.OK(t, mi.Rewrite(context.TODO(), unpacked, nil, indexIDs, nil, index.MasterIndexRewriteOpts{})) + + mi2 := index.NewMasterIndex() + rtest.OK(t, mi2.Load(context.TODO(), repo, nil, nil)) + + afterRewrite := mi2.IDs() + rtest.Equals(t, 2, len(afterRewrite)) + rtest.Equals(t, 2, len(afterRewrite.Intersect(indexIDs))) + + rtest.Equals(t, []restic.PackedBlob{blobA}, mi2.Lookup(blobA.BlobHandle)) + rtest.Equals(t, []restic.PackedBlob{blobB}, mi2.Lookup(blobB.BlobHandle)) +}