test: add helper to capture stdout for integration tests

This commit is contained in:
Michael Eischer 2023-05-07 22:06:39 +02:00
parent 675a49a95b
commit cebce52c16
12 changed files with 93 additions and 133 deletions

View file

@ -205,22 +205,23 @@ func TestBackupNonExistingFile(t *testing.T) {
defer cleanup() defer cleanup()
testSetupBackupData(t, env) testSetupBackupData(t, env)
globalOptions.stderr = io.Discard
defer func() {
globalOptions.stderr = os.Stderr
}()
p := filepath.Join(env.testdata, "0", "0", "9") withRestoreGlobalOptions(func() error {
dirs := []string{ globalOptions.stderr = io.Discard
filepath.Join(p, "0"),
filepath.Join(p, "1"),
filepath.Join(p, "nonexisting"),
filepath.Join(p, "5"),
}
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) { func TestBackupSelfHealing(t *testing.T) {

View file

@ -1,9 +1,7 @@
package main package main
import ( import (
"bytes"
"context" "context"
"os"
"testing" "testing"
rtest "github.com/restic/restic/internal/test" 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) { func testRunCheckOutput(gopts GlobalOptions, checkUnused bool) (string, error) {
buf := bytes.NewBuffer(nil) buf, err := withCaptureStdout(func() error {
opts := CheckOptions{
globalOptions.stdout = buf ReadData: true,
defer func() { CheckUnused: checkUnused,
globalOptions.stdout = os.Stdout }
}() return runCheck(context.TODO(), opts, gopts, nil)
})
opts := CheckOptions{
ReadData: true,
CheckUnused: checkUnused,
}
err := runCheck(context.TODO(), opts, gopts, nil)
return buf.String(), err return buf.String(), err
} }

View file

@ -2,7 +2,6 @@ package main
import ( import (
"bufio" "bufio"
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"io" "io"
@ -16,20 +15,14 @@ import (
) )
func testRunDiffOutput(gopts GlobalOptions, firstSnapshotID string, secondSnapshotID string) (string, error) { 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 opts := DiffOptions{
oldStdout := gopts.stdout ShowMetadata: false,
gopts.stdout = buf }
defer func() { return runDiff(context.TODO(), opts, gopts, []string{firstSnapshotID, secondSnapshotID})
globalOptions.stdout = os.Stdout })
gopts.stdout = oldStdout
}()
opts := DiffOptions{
ShowMetadata: false,
}
err := runDiff(context.TODO(), opts, gopts, []string{firstSnapshotID, secondSnapshotID})
return buf.String(), err return buf.String(), err
} }

View file

@ -1,10 +1,8 @@
package main package main
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"os"
"strings" "strings"
"testing" "testing"
"time" "time"
@ -13,18 +11,13 @@ import (
) )
func testRunFind(t testing.TB, wantJSON bool, gopts GlobalOptions, pattern string) []byte { func testRunFind(t testing.TB, wantJSON bool, gopts GlobalOptions, pattern string) []byte {
buf := bytes.NewBuffer(nil) buf, err := withCaptureStdout(func() error {
globalOptions.stdout = buf globalOptions.JSON = wantJSON
globalOptions.JSON = wantJSON
defer func() {
globalOptions.stdout = os.Stdout
globalOptions.JSON = false
}()
opts := FindOptions{}
rtest.OK(t, runFind(context.TODO(), opts, gopts, []string{pattern}))
opts := FindOptions{}
return runFind(context.TODO(), opts, gopts, []string{pattern})
})
rtest.OK(t, err)
return buf.Bytes() return buf.Bytes()
} }

View file

@ -2,9 +2,7 @@ package main
import ( import (
"bufio" "bufio"
"bytes"
"context" "context"
"os"
"regexp" "regexp"
"testing" "testing"
@ -14,14 +12,10 @@ import (
) )
func testRunKeyListOtherIDs(t testing.TB, gopts GlobalOptions) []string { func testRunKeyListOtherIDs(t testing.TB, gopts GlobalOptions) []string {
buf := bytes.NewBuffer(nil) buf, err := withCaptureStdout(func() error {
return runKey(context.TODO(), gopts, []string{"list"})
globalOptions.stdout = buf })
defer func() { rtest.OK(t, err)
globalOptions.stdout = os.Stdout
}()
rtest.OK(t, runKey(context.TODO(), gopts, []string{"list"}))
scanner := bufio.NewScanner(buf) scanner := bufio.NewScanner(buf)
exp := regexp.MustCompile(`^ ([a-f0-9]+) `) exp := regexp.MustCompile(`^ ([a-f0-9]+) `)

View file

@ -2,10 +2,8 @@ package main
import ( import (
"bufio" "bufio"
"bytes"
"context" "context"
"io" "io"
"os"
"testing" "testing"
"github.com/restic/restic/internal/restic" "github.com/restic/restic/internal/restic"
@ -13,13 +11,10 @@ import (
) )
func testRunList(t testing.TB, tpe string, opts GlobalOptions) restic.IDs { func testRunList(t testing.TB, tpe string, opts GlobalOptions) restic.IDs {
buf := bytes.NewBuffer(nil) buf, err := withCaptureStdout(func() error {
globalOptions.stdout = buf return runList(context.TODO(), cmdList, opts, []string{tpe})
defer func() { })
globalOptions.stdout = os.Stdout rtest.OK(t, err)
}()
rtest.OK(t, runList(context.TODO(), cmdList, opts, []string{tpe}))
return parseIDsFromReader(t, buf) return parseIDsFromReader(t, buf)
} }

View file

@ -1,9 +1,7 @@
package main package main
import ( import (
"bytes"
"context" "context"
"os"
"strings" "strings"
"testing" "testing"
@ -11,18 +9,11 @@ import (
) )
func testRunLs(t testing.TB, gopts GlobalOptions, snapshotID string) []string { func testRunLs(t testing.TB, gopts GlobalOptions, snapshotID string) []string {
buf := bytes.NewBuffer(nil) buf, err := withCaptureStdout(func() error {
globalOptions.stdout = buf globalOptions.Quiet = true
quiet := globalOptions.Quiet opts := LsOptions{}
globalOptions.Quiet = true return runLs(context.TODO(), opts, gopts, []string{snapshotID})
defer func() { })
globalOptions.stdout = os.Stdout rtest.OK(t, err)
globalOptions.Quiet = quiet
}()
opts := LsOptions{}
rtest.OK(t, runLs(context.TODO(), opts, gopts, []string{snapshotID}))
return strings.Split(buf.String(), "\n") return strings.Split(buf.String(), "\n")
} }

View file

@ -3,7 +3,6 @@ package main
import ( import (
"context" "context"
"io" "io"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
@ -16,12 +15,10 @@ import (
) )
func testRunRebuildIndex(t testing.TB, gopts GlobalOptions) { func testRunRebuildIndex(t testing.TB, gopts GlobalOptions) {
globalOptions.stdout = io.Discard rtest.OK(t, withRestoreGlobalOptions(func() error {
defer func() { globalOptions.stdout = io.Discard
globalOptions.stdout = os.Stdout return runRebuildIndex(context.TODO(), RepairIndexOptions{}, gopts)
}() }))
rtest.OK(t, runRebuildIndex(context.TODO(), RepairIndexOptions{}, gopts))
} }
func testRebuildIndex(t *testing.T, backendTestHook backendWrapper) { 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") datafile := filepath.Join("..", "..", "internal", "checker", "testdata", "duplicate-packs-in-index-test-repo.tar.gz")
rtest.SetupTarTestFixture(t, env.base, datafile) rtest.SetupTarTestFixture(t, env.base, datafile)
globalOptions.stdout = io.Discard err := withRestoreGlobalOptions(func() error {
defer func() { globalOptions.stdout = io.Discard
globalOptions.stdout = os.Stdout
}() 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 { if err == nil {
t.Error("expected rebuildIndex to fail") t.Error("expected rebuildIndex to fail")
} }

View file

@ -205,12 +205,11 @@ func TestRestoreWithPermissionFailure(t *testing.T) {
snapshots := testListSnapshots(t, env.gopts, 1) snapshots := testListSnapshots(t, env.gopts, 1)
globalOptions.stderr = io.Discard _ = withRestoreGlobalOptions(func() error {
defer func() { globalOptions.stderr = io.Discard
globalOptions.stderr = os.Stderr testRunRestore(t, env.gopts, filepath.Join(env.base, "restore"), snapshots[0])
}() return nil
})
testRunRestore(t, env.gopts, filepath.Join(env.base, "restore"), snapshots[0])
// make sure that all files have been restored, regardless of any // make sure that all files have been restored, regardless of any
// permission errors // permission errors

View file

@ -1,10 +1,8 @@
package main package main
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"os"
"testing" "testing"
"github.com/restic/restic/internal/restic" "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) { func testRunSnapshots(t testing.TB, gopts GlobalOptions) (newest *Snapshot, snapmap map[restic.ID]Snapshot) {
buf := bytes.NewBuffer(nil) buf, err := withCaptureStdout(func() error {
globalOptions.stdout = buf globalOptions.JSON = true
globalOptions.JSON = true
defer func() {
globalOptions.stdout = os.Stdout
globalOptions.JSON = gopts.JSON
}()
opts := SnapshotOptions{} opts := SnapshotOptions{}
return runSnapshots(context.TODO(), opts, gopts, []string{})
rtest.OK(t, runSnapshots(context.TODO(), opts, globalOptions, []string{})) })
rtest.OK(t, err)
snapshots := []Snapshot{} snapshots := []Snapshot{}
rtest.OK(t, json.Unmarshal(buf.Bytes(), &snapshots)) rtest.OK(t, json.Unmarshal(buf.Bytes(), &snapshots))

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"bytes"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -10,22 +9,16 @@ import (
) )
func Test_PrintFunctionsRespectsGlobalStdout(t *testing.T) { func Test_PrintFunctionsRespectsGlobalStdout(t *testing.T) {
gopts := globalOptions
defer func() {
globalOptions = gopts
}()
buf := bytes.NewBuffer(nil)
globalOptions.stdout = buf
for _, p := range []func(){ for _, p := range []func(){
func() { Println("message") }, func() { Println("message") },
func() { Print("message\n") }, func() { Print("message\n") },
func() { Printf("mes%s\n", "sage") }, func() { Printf("mes%s\n", "sage") },
} { } {
p() buf, _ := withCaptureStdout(func() error {
p()
return nil
})
rtest.Equals(t, "message\n", buf.String()) rtest.Equals(t, "message\n", buf.String())
buf.Reset()
} }
} }

View file

@ -338,3 +338,21 @@ func testFileSize(filename string, size int64) error {
return nil 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
}