1 Commits
Author SHA1 Message Date
sneak 5392363d20 Report blob counts from snapshot verify --deep --json (closes #314)
check / check (push) Waiting to run
Deep verify set verified only on success and never set missing, so a
failed --deep --json run reported zero for both. It now counts each blob
whose contents pass as it goes, and the existence check runs through
every blob, counting the ones storage reports not found as missing and
the wrong-size ones as mismatched, as shallow verify does; it fails if it
found any. Any other storage error stops the check and fails with that
error, so a blob that cannot be checked is never reported as missing.

Deep verify still stops at the first damaged blob and reads no blob
contents while any blob is missing or the wrong size, so verified is 0
there where shallow mode counts the present blobs.

Model: opus-5-5
2026-10-13 17:15:12 +00:00
+4 -26
View File
@@ -7,7 +7,6 @@ import (
"io"
"os"
"path/filepath"
"slices"
"testing"
"github.com/spf13/afero"
@@ -182,32 +181,13 @@ func TestDeepVerifyStopsOnBlobThatCannotBeChecked(t *testing.T) {
storeDir := filepath.Join(t.TempDir(), "remote")
cfg, storer, snapshotID, keys := backUpSeveralBlobs(ctx, t, storeDir)
denied := &statDeniedStorer{Storer: storer, deniedKey: keys[0]}
failing := statFailingStorer{Storer: storer, failKeys: []string{keys[0]}}
got, err := deepVerifyJSON(ctx, t, cfg, denied, snapshotID)
got, err := deepVerifyJSON(ctx, t, cfg, failing, snapshotID)
require.Error(t, err)
require.Equal(t, "failed", got.Status)
require.Zero(t, got.Missing)
require.Contains(t, got.ErrorMessage, os.ErrPermission.Error())
}
// statDeniedStorer passes every call through to the wrapped Storer,
// except that Stat of deniedKey fails with a permission error, as it
// does for a blob that is present but cannot be read.
type statDeniedStorer struct {
storage.Storer
deniedKey string
}
func (s *statDeniedStorer) Stat(
ctx context.Context, key string,
) (*storage.ObjectInfo, error) {
if key == s.deniedKey {
return nil, os.ErrPermission
}
return s.Storer.Stat(ctx, key)
require.Contains(t, got.ErrorMessage, errStatDenied.Error())
}
// backUpSeveralBlobs backs up random data, which does not compress or
@@ -237,10 +217,8 @@ func backUpSeveralBlobs(
cfg, storer, snapshotID := runFileStorageBackup(
ctx, t, fs, dataDir, storeDir, dbPath, chunkSize, maxBlobSize)
keys, err := storer.List(ctx, "blobs/")
require.NoError(t, err)
keys := storedBlobKeys(t, storeDir)
require.GreaterOrEqual(t, len(keys), 3)
slices.Sort(keys)
return cfg, storer, snapshotID, keys
}