From 7fe83f0db0bbb78867729a52226c8a66bd6d672e Mon Sep 17 00:00:00 2001 From: Winfried Plappert Date: Sat, 15 Feb 2025 11:47:46 +0000 Subject: [PATCH] check: cmd_check, checker, checker_test: added test - rebase part 5: add checker_test cmd_check, checker: added error return checker_test: testing CheckWithSnapshots checker_test: fixed lint error for empty tree list --- cmd/restic/cmd_check.go | 3 ++ internal/checker/checker.go | 10 ++-- internal/checker/checker_test.go | 90 ++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 3 deletions(-) diff --git a/cmd/restic/cmd_check.go b/cmd/restic/cmd_check.go index 1579693c1..5018a05a2 100644 --- a/cmd/restic/cmd_check.go +++ b/cmd/restic/cmd_check.go @@ -264,6 +264,9 @@ func runCheck(ctx context.Context, opts CheckOptions, gopts GlobalOptions, args if err != nil { return err } + if len(selectedTrees) == 0 { + return errors.Fatal("snapshotfilter active but no snapshot selected.") + } } chkr := checker.New(repo, opts.CheckUnused) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 32ff2488b..daf5ac1c8 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -522,8 +522,8 @@ func (c *Checker) ReadPacks(ctx context.Context, packs map[restic.ID]int64, p *p } } -// CheckWithSnapshots will process snapshot IDs from command line and -// add to snapPacks so it contains only the selected packfiles via snapshotFilter +// CheckWithSnapshots will process snapshot IDs from 'selectedTrees' and +// add to snapPacks so it contains only the selected packfiles. func (c *Checker) CheckWithSnapshots(ctx context.Context, selectedTrees []restic.ID) error { // gather used blobs from all trees @@ -541,6 +541,10 @@ func (c *Checker) CheckWithSnapshots(ctx context.Context, selectedTrees []restic } } - c.packs = snapPacks + if len(snapPacks) > 0 { + c.packs = snapPacks + } else { + return errors.Fatal("no packfiles found for given snapshot trees") + } return nil } diff --git a/internal/checker/checker_test.go b/internal/checker/checker_test.go index 92bbb1da6..213011f5f 100644 --- a/internal/checker/checker_test.go +++ b/internal/checker/checker_test.go @@ -574,6 +574,96 @@ func TestCheckerBlobTypeConfusion(t *testing.T) { } } +// TestCheckRepoSnapshot: it is assumed here that restic.Snapshotfilter is +// working correctly: the output of the filter is fed into the test manually +func TestCheckRepoSnapshot(t *testing.T) { + repo, _, cleanup := repository.TestFromFixture(t, checkerTestData) + defer cleanup() + + chkr := checker.New(repo, false) + _, errs := chkr.LoadIndex(context.TODO(), nil) + if len(errs) > 0 { + t.Fatalf("expected no errors, got %v: %v", len(errs), errs) + } + + test.OKs(t, checkPacks(chkr)) + test.OKs(t, checkStruct(chkr)) + + snID := restic.TestParseID("f7d83db709977178c9d1a09e4009355e534cde1a135b8186b8b118a3fc4fcd41") + sn1, err := restic.LoadSnapshot(context.TODO(), repo, snID) + if err != nil { + t.Fatal(err) + } + selectedTrees := []restic.ID{*sn1.Tree} + test.OK(t, chkr.CheckWithSnapshots(context.TODO(), selectedTrees)) + + // size of packs (1) + lenPacks := chkr.CountPacks() + if lenPacks != 1 { + t.Fatalf("expected 1 packfile, got %v", lenPacks) + } + + _, errs = chkr.LoadIndex(context.TODO(), nil) + if len(errs) > 0 { + t.Fatalf("expected no errors, got %v: %v", len(errs), errs) + } + snID = restic.TestParseID("c2b53c5e6a16db92fbb9aa08bd2794c58b379d8724d661ee30d20898bdfdff22") + sn2, err := restic.LoadSnapshot(context.TODO(), repo, snID) + if err != nil { + t.Fatal(err) + } + selectedTrees = []restic.ID{*sn2.Tree} + test.OK(t, chkr.CheckWithSnapshots(context.TODO(), selectedTrees)) + + // size of packs (2) + lenPacks = chkr.CountPacks() + if lenPacks != 2 { + t.Fatalf("expected 2 packfiles, got %v", lenPacks) + } + + _, errs = chkr.LoadIndex(context.TODO(), nil) + if len(errs) > 0 { + t.Fatalf("expected no errors, got %v: %v", len(errs), errs) + } + snID = restic.TestParseID("a13c11e582b77a693dd75ab4e3a3ba96538a056594a4b9076e4cacebe6e06d43") + sn3, err := restic.LoadSnapshot(context.TODO(), repo, snID) + if err != nil { + t.Fatal(err) + } + selectedTrees = []restic.ID{*sn3.Tree} + test.OK(t, chkr.CheckWithSnapshots(context.TODO(), selectedTrees)) + + // size of packs (3) + lenPacks = chkr.CountPacks() + if lenPacks != 2 { + t.Fatalf("expected 2 packfiles, got %v", lenPacks) + } + + // size of packs (4) + _, errs = chkr.LoadIndex(context.TODO(), nil) + if len(errs) > 0 { + t.Fatalf("expected no errors, got %v: %v", len(errs), errs) + } + selectedTrees = []restic.ID{*sn1.Tree, *sn3.Tree} + test.OK(t, chkr.CheckWithSnapshots(context.TODO(), selectedTrees)) + lenPacks = chkr.CountPacks() + if lenPacks != 3 { + t.Fatalf("expected 3 packfiles, got %v", lenPacks) + } + + // size of packs (5): unmodified - filter empty + _, errs = chkr.LoadIndex(context.TODO(), nil) + if len(errs) > 0 { + t.Fatalf("expected no errors, got %v: %v", len(errs), errs) + } + + selectedTrees = []restic.ID{} + err = chkr.CheckWithSnapshots(context.TODO(), selectedTrees) + if err == nil { + t.Fatalf("expected an error, got no error") + } +} + func loadBenchRepository(t *testing.B) (*checker.Checker, restic.Repository, func()) { repo, _, cleanup := repository.TestFromFixture(t, checkerTestData)