From cebce52c16d55fe93a33aadf6ce625fc63037feb Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sun, 7 May 2023 22:06:39 +0200 Subject: [PATCH] test: add helper to capture stdout for integration tests --- cmd/restic/cmd_backup_integration_test.go | 27 ++++++++++--------- cmd/restic/cmd_check_integration_test.go | 22 +++++---------- cmd/restic/cmd_diff_integration_test.go | 21 +++++---------- cmd/restic/cmd_find_integration_test.go | 19 +++++-------- cmd/restic/cmd_key_integration_test.go | 14 +++------- cmd/restic/cmd_list_integration_test.go | 13 +++------ cmd/restic/cmd_ls_integration_test.go | 21 +++++---------- .../cmd_repair_index_integration_test.go | 27 +++++++++---------- cmd/restic/cmd_restore_integration_test.go | 11 ++++---- cmd/restic/cmd_snapshots_integration_test.go | 18 +++++-------- cmd/restic/global_test.go | 15 +++-------- cmd/restic/integration_helpers_test.go | 18 +++++++++++++ 12 files changed, 93 insertions(+), 133 deletions(-) diff --git a/cmd/restic/cmd_backup_integration_test.go b/cmd/restic/cmd_backup_integration_test.go index b6491dfbf..769a60c03 100644 --- a/cmd/restic/cmd_backup_integration_test.go +++ b/cmd/restic/cmd_backup_integration_test.go @@ -205,22 +205,23 @@ func TestBackupNonExistingFile(t *testing.T) { defer cleanup() testSetupBackupData(t, env) - globalOptions.stderr = io.Discard - defer func() { - globalOptions.stderr = os.Stderr - }() - p := filepath.Join(env.testdata, "0", "0", "9") - dirs := []string{ - filepath.Join(p, "0"), - filepath.Join(p, "1"), - filepath.Join(p, "nonexisting"), - filepath.Join(p, "5"), - } + withRestoreGlobalOptions(func() error { + globalOptions.stderr = io.Discard - opts := BackupOptions{} + p := filepath.Join(env.testdata, "0", "0", "9") + dirs := []string{ + filepath.Join(p, "0"), + filepath.Join(p, "1"), + filepath.Join(p, "nonexisting"), + filepath.Join(p, "5"), + } - testRunBackup(t, "", dirs, opts, env.gopts) + opts := BackupOptions{} + + testRunBackup(t, "", dirs, opts, env.gopts) + return nil + }) } func TestBackupSelfHealing(t *testing.T) { diff --git a/cmd/restic/cmd_check_integration_test.go b/cmd/restic/cmd_check_integration_test.go index 05bc436c4..9eb4fec62 100644 --- a/cmd/restic/cmd_check_integration_test.go +++ b/cmd/restic/cmd_check_integration_test.go @@ -1,9 +1,7 @@ package main import ( - "bytes" "context" - "os" "testing" rtest "github.com/restic/restic/internal/test" @@ -25,18 +23,12 @@ func testRunCheckMustFail(t testing.TB, gopts GlobalOptions) { } func testRunCheckOutput(gopts GlobalOptions, checkUnused bool) (string, error) { - buf := bytes.NewBuffer(nil) - - globalOptions.stdout = buf - defer func() { - globalOptions.stdout = os.Stdout - }() - - opts := CheckOptions{ - ReadData: true, - CheckUnused: checkUnused, - } - - err := runCheck(context.TODO(), opts, gopts, nil) + buf, err := withCaptureStdout(func() error { + opts := CheckOptions{ + ReadData: true, + CheckUnused: checkUnused, + } + return runCheck(context.TODO(), opts, gopts, nil) + }) return buf.String(), err } diff --git a/cmd/restic/cmd_diff_integration_test.go b/cmd/restic/cmd_diff_integration_test.go index ae145fedf..c46f00f4f 100644 --- a/cmd/restic/cmd_diff_integration_test.go +++ b/cmd/restic/cmd_diff_integration_test.go @@ -2,7 +2,6 @@ package main import ( "bufio" - "bytes" "context" "encoding/json" "io" @@ -16,20 +15,14 @@ import ( ) func testRunDiffOutput(gopts GlobalOptions, firstSnapshotID string, secondSnapshotID string) (string, error) { - buf := bytes.NewBuffer(nil) + buf, err := withCaptureStdout(func() error { + gopts.stdout = globalOptions.stdout - globalOptions.stdout = buf - oldStdout := gopts.stdout - gopts.stdout = buf - defer func() { - globalOptions.stdout = os.Stdout - gopts.stdout = oldStdout - }() - - opts := DiffOptions{ - ShowMetadata: false, - } - err := runDiff(context.TODO(), opts, gopts, []string{firstSnapshotID, secondSnapshotID}) + opts := DiffOptions{ + ShowMetadata: false, + } + return runDiff(context.TODO(), opts, gopts, []string{firstSnapshotID, secondSnapshotID}) + }) return buf.String(), err } diff --git a/cmd/restic/cmd_find_integration_test.go b/cmd/restic/cmd_find_integration_test.go index 0ee8839e7..236721154 100644 --- a/cmd/restic/cmd_find_integration_test.go +++ b/cmd/restic/cmd_find_integration_test.go @@ -1,10 +1,8 @@ package main import ( - "bytes" "context" "encoding/json" - "os" "strings" "testing" "time" @@ -13,18 +11,13 @@ import ( ) func testRunFind(t testing.TB, wantJSON bool, gopts GlobalOptions, pattern string) []byte { - buf := bytes.NewBuffer(nil) - globalOptions.stdout = buf - globalOptions.JSON = wantJSON - defer func() { - globalOptions.stdout = os.Stdout - globalOptions.JSON = false - }() - - opts := FindOptions{} - - rtest.OK(t, runFind(context.TODO(), opts, gopts, []string{pattern})) + buf, err := withCaptureStdout(func() error { + globalOptions.JSON = wantJSON + opts := FindOptions{} + return runFind(context.TODO(), opts, gopts, []string{pattern}) + }) + rtest.OK(t, err) return buf.Bytes() } diff --git a/cmd/restic/cmd_key_integration_test.go b/cmd/restic/cmd_key_integration_test.go index 9e327d16c..9ea5795ba 100644 --- a/cmd/restic/cmd_key_integration_test.go +++ b/cmd/restic/cmd_key_integration_test.go @@ -2,9 +2,7 @@ package main import ( "bufio" - "bytes" "context" - "os" "regexp" "testing" @@ -14,14 +12,10 @@ import ( ) func testRunKeyListOtherIDs(t testing.TB, gopts GlobalOptions) []string { - buf := bytes.NewBuffer(nil) - - globalOptions.stdout = buf - defer func() { - globalOptions.stdout = os.Stdout - }() - - rtest.OK(t, runKey(context.TODO(), gopts, []string{"list"})) + buf, err := withCaptureStdout(func() error { + return runKey(context.TODO(), gopts, []string{"list"}) + }) + rtest.OK(t, err) scanner := bufio.NewScanner(buf) exp := regexp.MustCompile(`^ ([a-f0-9]+) `) diff --git a/cmd/restic/cmd_list_integration_test.go b/cmd/restic/cmd_list_integration_test.go index ce8ee4909..4140a3ea8 100644 --- a/cmd/restic/cmd_list_integration_test.go +++ b/cmd/restic/cmd_list_integration_test.go @@ -2,10 +2,8 @@ package main import ( "bufio" - "bytes" "context" "io" - "os" "testing" "github.com/restic/restic/internal/restic" @@ -13,13 +11,10 @@ import ( ) func testRunList(t testing.TB, tpe string, opts GlobalOptions) restic.IDs { - buf := bytes.NewBuffer(nil) - globalOptions.stdout = buf - defer func() { - globalOptions.stdout = os.Stdout - }() - - rtest.OK(t, runList(context.TODO(), cmdList, opts, []string{tpe})) + buf, err := withCaptureStdout(func() error { + return runList(context.TODO(), cmdList, opts, []string{tpe}) + }) + rtest.OK(t, err) return parseIDsFromReader(t, buf) } diff --git a/cmd/restic/cmd_ls_integration_test.go b/cmd/restic/cmd_ls_integration_test.go index 0d2fd85db..a93092f58 100644 --- a/cmd/restic/cmd_ls_integration_test.go +++ b/cmd/restic/cmd_ls_integration_test.go @@ -1,9 +1,7 @@ package main import ( - "bytes" "context" - "os" "strings" "testing" @@ -11,18 +9,11 @@ import ( ) func testRunLs(t testing.TB, gopts GlobalOptions, snapshotID string) []string { - buf := bytes.NewBuffer(nil) - globalOptions.stdout = buf - quiet := globalOptions.Quiet - globalOptions.Quiet = true - defer func() { - globalOptions.stdout = os.Stdout - globalOptions.Quiet = quiet - }() - - opts := LsOptions{} - - rtest.OK(t, runLs(context.TODO(), opts, gopts, []string{snapshotID})) - + buf, err := withCaptureStdout(func() error { + globalOptions.Quiet = true + opts := LsOptions{} + return runLs(context.TODO(), opts, gopts, []string{snapshotID}) + }) + rtest.OK(t, err) return strings.Split(buf.String(), "\n") } diff --git a/cmd/restic/cmd_repair_index_integration_test.go b/cmd/restic/cmd_repair_index_integration_test.go index a5711da84..f451173a3 100644 --- a/cmd/restic/cmd_repair_index_integration_test.go +++ b/cmd/restic/cmd_repair_index_integration_test.go @@ -3,7 +3,6 @@ package main import ( "context" "io" - "os" "path/filepath" "strings" "sync" @@ -16,12 +15,10 @@ import ( ) func testRunRebuildIndex(t testing.TB, gopts GlobalOptions) { - globalOptions.stdout = io.Discard - defer func() { - globalOptions.stdout = os.Stdout - }() - - rtest.OK(t, runRebuildIndex(context.TODO(), RepairIndexOptions{}, gopts)) + rtest.OK(t, withRestoreGlobalOptions(func() error { + globalOptions.stdout = io.Discard + return runRebuildIndex(context.TODO(), RepairIndexOptions{}, gopts) + })) } func testRebuildIndex(t *testing.T, backendTestHook backendWrapper) { @@ -127,15 +124,15 @@ func TestRebuildIndexFailsOnAppendOnly(t *testing.T) { datafile := filepath.Join("..", "..", "internal", "checker", "testdata", "duplicate-packs-in-index-test-repo.tar.gz") rtest.SetupTarTestFixture(t, env.base, datafile) - globalOptions.stdout = io.Discard - defer func() { - globalOptions.stdout = os.Stdout - }() + err := withRestoreGlobalOptions(func() error { + globalOptions.stdout = io.Discard + + env.gopts.backendTestHook = func(r restic.Backend) (restic.Backend, error) { + return &appendOnlyBackend{r}, nil + } + return runRebuildIndex(context.TODO(), RepairIndexOptions{}, env.gopts) + }) - env.gopts.backendTestHook = func(r restic.Backend) (restic.Backend, error) { - return &appendOnlyBackend{r}, nil - } - err := runRebuildIndex(context.TODO(), RepairIndexOptions{}, env.gopts) if err == nil { t.Error("expected rebuildIndex to fail") } diff --git a/cmd/restic/cmd_restore_integration_test.go b/cmd/restic/cmd_restore_integration_test.go index 266b0c2f6..74fddd347 100644 --- a/cmd/restic/cmd_restore_integration_test.go +++ b/cmd/restic/cmd_restore_integration_test.go @@ -205,12 +205,11 @@ func TestRestoreWithPermissionFailure(t *testing.T) { snapshots := testListSnapshots(t, env.gopts, 1) - globalOptions.stderr = io.Discard - defer func() { - globalOptions.stderr = os.Stderr - }() - - testRunRestore(t, env.gopts, filepath.Join(env.base, "restore"), snapshots[0]) + _ = withRestoreGlobalOptions(func() error { + globalOptions.stderr = io.Discard + testRunRestore(t, env.gopts, filepath.Join(env.base, "restore"), snapshots[0]) + return nil + }) // make sure that all files have been restored, regardless of any // permission errors diff --git a/cmd/restic/cmd_snapshots_integration_test.go b/cmd/restic/cmd_snapshots_integration_test.go index 607f0bf6b..ba284a9e9 100644 --- a/cmd/restic/cmd_snapshots_integration_test.go +++ b/cmd/restic/cmd_snapshots_integration_test.go @@ -1,10 +1,8 @@ package main import ( - "bytes" "context" "encoding/json" - "os" "testing" "github.com/restic/restic/internal/restic" @@ -12,17 +10,13 @@ import ( ) func testRunSnapshots(t testing.TB, gopts GlobalOptions) (newest *Snapshot, snapmap map[restic.ID]Snapshot) { - buf := bytes.NewBuffer(nil) - globalOptions.stdout = buf - globalOptions.JSON = true - defer func() { - globalOptions.stdout = os.Stdout - globalOptions.JSON = gopts.JSON - }() + buf, err := withCaptureStdout(func() error { + globalOptions.JSON = true - opts := SnapshotOptions{} - - rtest.OK(t, runSnapshots(context.TODO(), opts, globalOptions, []string{})) + opts := SnapshotOptions{} + return runSnapshots(context.TODO(), opts, gopts, []string{}) + }) + rtest.OK(t, err) snapshots := []Snapshot{} rtest.OK(t, json.Unmarshal(buf.Bytes(), &snapshots)) diff --git a/cmd/restic/global_test.go b/cmd/restic/global_test.go index 7d2699a22..4f5c29e9a 100644 --- a/cmd/restic/global_test.go +++ b/cmd/restic/global_test.go @@ -1,7 +1,6 @@ package main import ( - "bytes" "os" "path/filepath" "testing" @@ -10,22 +9,16 @@ import ( ) func Test_PrintFunctionsRespectsGlobalStdout(t *testing.T) { - gopts := globalOptions - defer func() { - globalOptions = gopts - }() - - buf := bytes.NewBuffer(nil) - globalOptions.stdout = buf - for _, p := range []func(){ func() { Println("message") }, func() { Print("message\n") }, func() { Printf("mes%s\n", "sage") }, } { - p() + buf, _ := withCaptureStdout(func() error { + p() + return nil + }) rtest.Equals(t, "message\n", buf.String()) - buf.Reset() } } diff --git a/cmd/restic/integration_helpers_test.go b/cmd/restic/integration_helpers_test.go index 59d9e30d3..cdafd8c98 100644 --- a/cmd/restic/integration_helpers_test.go +++ b/cmd/restic/integration_helpers_test.go @@ -338,3 +338,21 @@ func testFileSize(filename string, size int64) error { return nil } + +func withRestoreGlobalOptions(inner func() error) error { + gopts := globalOptions + defer func() { + globalOptions = gopts + }() + return inner() +} + +func withCaptureStdout(inner func() error) (*bytes.Buffer, error) { + buf := bytes.NewBuffer(nil) + err := withRestoreGlobalOptions(func() error { + globalOptions.stdout = buf + return inner() + }) + + return buf, err +}