restic: tighten RunCheck lock sniff + RunStats zero-snapshot test
Narrow the LockPresent predicate from bare "locked" (too broad) to "stale lock" and "already locked" — the two phrases restic actually emits. Replace TestRunCheckParsesLock with table-driven TestRunCheckLockSniff covering both trigger phrases and a benign "locked-file" line that must not set LockPresent. Add TestRunStatsZeroSnapshots to pin that RunStats accepts zero-snapshot JSON without error.
This commit is contained in:
@@ -367,7 +367,7 @@ func (e Env) RunCheck(ctx context.Context, subsetPct int, handle LineHandler) (C
|
||||
var res CheckResult
|
||||
sniff := func(stream, line string, ev any) {
|
||||
if stream == "stderr" {
|
||||
if strings.Contains(line, "Found stale lock") || strings.Contains(line, "locked") {
|
||||
if strings.Contains(line, "stale lock") || strings.Contains(line, "already locked") {
|
||||
res.LockPresent = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,18 +54,34 @@ func TestRunPruneInvokesPrune(t *testing.T) {
|
||||
|
||||
// --- B2: RunCheck ---
|
||||
|
||||
func TestRunCheckParsesLock(t *testing.T) {
|
||||
bin := setupScriptBin(t, `echo "Found stale lock" >&2`)
|
||||
env := Env{Bin: bin}
|
||||
res, err := env.RunCheck(context.Background(), 0, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("RunCheck returned unexpected error: %v", err)
|
||||
func TestRunCheckLockSniff(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
stderrLine string
|
||||
wantLocked bool
|
||||
}{
|
||||
{"stale lock", "Found stale lock from PID 1234", true},
|
||||
{"already locked", "repository is already locked exclusively", true},
|
||||
{"benign mention", "subdir/locked-file ok", false},
|
||||
{"empty", "", false},
|
||||
}
|
||||
if !res.LockPresent {
|
||||
t.Fatal("expected LockPresent=true")
|
||||
}
|
||||
if res.ErrorsFound {
|
||||
t.Fatal("expected ErrorsFound=false")
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
// Script emits the line on stderr, then exits 0.
|
||||
script := fmt.Sprintf(`printf '%%s\n' %q >&2`, c.stderrLine)
|
||||
bin := setupScriptBin(t, script)
|
||||
env := Env{Bin: bin}
|
||||
res, err := env.RunCheck(context.Background(), 0, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("RunCheck returned unexpected error: %v", err)
|
||||
}
|
||||
if res.LockPresent != c.wantLocked {
|
||||
t.Fatalf("LockPresent: got %v, want %v (line: %q)", res.LockPresent, c.wantLocked, c.stderrLine)
|
||||
}
|
||||
if res.ErrorsFound {
|
||||
t.Fatal("expected ErrorsFound=false")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,3 +165,21 @@ func TestRunStatsErrorsWithoutJSON(t *testing.T) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunStatsZeroSnapshots(t *testing.T) {
|
||||
// Confirms RunStats succeeds and returns a valid *RepoStats when the
|
||||
// repo has no snapshots (snapshots_count=0). A regression that
|
||||
// re-added a "SnapshotsCount > 0" guard would return an error here.
|
||||
bin := setupScriptBin(t, `echo '{"total_size":0,"total_uncompressed_size":0,"snapshots_count":0,"total_file_count":0,"total_blob_count":0}'`)
|
||||
env := Env{Bin: bin}
|
||||
stats, err := env.RunStats(context.Background(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("RunStats with zero snapshots returned unexpected error: %v", err)
|
||||
}
|
||||
if stats == nil {
|
||||
t.Fatal("expected non-nil *RepoStats, got nil")
|
||||
}
|
||||
if stats.SnapshotsCount != 0 {
|
||||
t.Fatalf("SnapshotsCount: got %d, want 0", stats.SnapshotsCount)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user