forked from TrueCloudLab/restic
test: add helper to capture stdout for integration tests
This commit is contained in:
parent
675a49a95b
commit
cebce52c16
12 changed files with 93 additions and 133 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]+) `)
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue