package test_helper import ( "bytes" "fmt" "io/ioutil" "math/rand" "os" "os/exec" "path/filepath" "reflect" "runtime" "testing" "github.com/restic/restic/backend" "github.com/restic/restic/backend/local" "github.com/restic/restic/repository" ) // Assert fails the test if the condition is false. func Assert(tb testing.TB, condition bool, msg string, v ...interface{}) { if !condition { _, file, line, _ := runtime.Caller(1) fmt.Printf("\033[31m%s:%d: "+msg+"\033[39m\n\n", append([]interface{}{filepath.Base(file), line}, v...)...) tb.FailNow() } } // OK fails the test if an err is not nil. func OK(tb testing.TB, err error) { if err != nil { _, file, line, _ := runtime.Caller(1) fmt.Printf("\033[31m%s:%d: unexpected error: %s\033[39m\n\n", filepath.Base(file), line, err.Error()) tb.FailNow() } } // OKs fails the test if any error from errs is not nil. func OKs(tb testing.TB, errs []error) { errFound := false for _, err := range errs { if err != nil { errFound = true _, file, line, _ := runtime.Caller(1) fmt.Printf("\033[31m%s:%d: unexpected error: %s\033[39m\n\n", filepath.Base(file), line, err.Error()) } } if errFound { tb.FailNow() } } // Equals fails the test if exp is not equal to act. func Equals(tb testing.TB, exp, act interface{}) { if !reflect.DeepEqual(exp, act) { _, file, line, _ := runtime.Caller(1) fmt.Printf("\033[31m%s:%d:\n\n\texp: %#v\n\n\tgot: %#v\033[39m\n\n", filepath.Base(file), line, exp, act) tb.FailNow() } } // ParseID parses s as a backend.ID and panics if that fails. func ParseID(s string) backend.ID { id, err := backend.ParseID(s) if err != nil { panic(err) } return id } // Random returns size bytes of pseudo-random data derived from the seed. func Random(seed, count int) []byte { buf := make([]byte, count) rnd := rand.New(rand.NewSource(int64(seed))) for i := 0; i < count; i++ { buf[i] = byte(rnd.Uint32()) } return buf } // RandomReader returns a reader that returns size bytes of pseudo-random data // derived from the seed. func RandomReader(seed, size int) *bytes.Reader { return bytes.NewReader(Random(seed, size)) } // SetupTarTestFixture extracts the tarFile to outputDir. func SetupTarTestFixture(t testing.TB, outputDir, tarFile string) { f, err := os.Open(tarFile) defer f.Close() OK(t, err) cmd := exec.Command("tar", "xzf", "-") cmd.Dir = outputDir cmd.Stdin = f cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr OK(t, cmd.Run()) } // WithTestEnvironment creates a test environment, extracts the repository // fixture and and calls f with the repository dir. func WithTestEnvironment(t testing.TB, repoFixture string, f func(repodir string)) { tempdir, err := ioutil.TempDir(TestTempDir, "restic-test-") OK(t, err) fd, err := os.Open(repoFixture) if err != nil { panic(err) } OK(t, fd.Close()) SetupTarTestFixture(t, tempdir, repoFixture) f(filepath.Join(tempdir, "repo")) if !TestCleanup { t.Logf("leaving temporary directory %v used for test", tempdir) return } RemoveAll(t, tempdir) } // OpenLocalRepo opens the local repository located at dir. func OpenLocalRepo(t testing.TB, dir string) *repository.Repository { be, err := local.Open(dir) OK(t, err) repo := repository.New(be) err = repo.SearchKey(TestPassword) OK(t, err) return repo } func isFile(fi os.FileInfo) bool { return fi.Mode()&(os.ModeType|os.ModeCharDevice) == 0 } // ResetReadOnly recursively resets the read-only flag recursively for dir. // This is mainly used for tests on Windows, which is unable to delete a file // set read-only. func ResetReadOnly(t testing.TB, dir string) { OK(t, filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { if fi.IsDir() { return os.Chmod(path, 0777) } if isFile(fi) { return os.Chmod(path, 0666) } return nil })) } // RemoveAll recursively resets the read-only flag of all files and dirs and // afterwards uses os.RemoveAll() to remove the path. func RemoveAll(t testing.TB, path string) { ResetReadOnly(t, path) OK(t, os.RemoveAll(path)) }