2
2
mirror of https://github.com/octoleo/restic.git synced 2024-06-01 08:30:49 +00:00

Implement test suite for backend tests

This commit is contained in:
Alexander Neumann 2017-05-01 22:23:46 +02:00
parent a963052d64
commit 6f5fd72738
5 changed files with 157 additions and 254 deletions

View File

@ -1,87 +0,0 @@
// DO NOT EDIT, AUTOMATICALLY GENERATED
package test_test
import (
"testing"
"restic/backend/test"
)
var SkipMessage string
func TestTestBackendCreate(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestCreate(t)
}
func TestTestBackendOpen(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestOpen(t)
}
func TestTestBackendCreateWithConfig(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestCreateWithConfig(t)
}
func TestTestBackendLocation(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestLocation(t)
}
func TestTestBackendConfig(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestConfig(t)
}
func TestTestBackendLoad(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestLoad(t)
}
func TestTestBackendSave(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestSave(t)
}
func TestTestBackendSaveFilenames(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestSaveFilenames(t)
}
func TestTestBackendBackend(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestBackend(t)
}
func TestTestBackendDelete(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestDelete(t)
}
func TestTestBackendCleanup(t *testing.T) {
if SkipMessage != "" {
t.Skip(SkipMessage)
}
test.TestCleanup(t)
}

View File

@ -0,0 +1,20 @@
// DO NOT EDIT, AUTOMATICALLY GENERATED
package test
import (
"testing"
)
var TestFunctions = []struct {
Name string
Fn func(t testing.TB, suite *Suite)
}{
{"CreateWithConfig", TestCreateWithConfig},
{"Location", TestLocation},
{"Config", TestConfig},
{"Load", TestLoad},
{"Save", TestSave},
{"SaveFilenames", TestSaveFilenames},
{"Backend", TestBackend},
{"Delete", TestDelete},
}

View File

@ -18,9 +18,8 @@ import (
)
var data struct {
Package string
PackagePrefix string
Funcs []string
Package string
Funcs []string
}
var testTemplate = `
@ -29,24 +28,20 @@ package {{ .Package }}
import (
"testing"
"restic/backend/test"
)
var SkipMessage string
{{ $prefix := .PackagePrefix }}
{{ range $f := .Funcs }}
func Test{{ $prefix }}{{ $f }}(t *testing.T){
if SkipMessage != "" { t.Skip(SkipMessage) }
test.Test{{ $f }}(t)
}
var TestFunctions = []struct {
Name string
Fn func(t testing.TB, suite *Suite)
}{
{{ range $f := .Funcs -}}
{"{{ $f }}", Test{{ $f }},},
{{ end }}
}
`
var testFile = flag.String("testfile", "../test/tests.go", "file to search test functions in")
var outputFile = flag.String("output", "backend_test.go", "output file to write generated code to")
var testFile = flag.String("testfile", "tests.go", "file to search test functions in")
var outputFile = flag.String("output", "funcs.go", "output file to write generated code to")
var packageName = flag.String("package", "", "the package name to use")
var prefix = flag.String("prefix", "", "test function prefix")
var quiet = flag.Bool("quiet", false, "be quiet")
@ -123,12 +118,7 @@ func main() {
f, err := os.Create(*outputFile)
errx(err)
data.Package = pkg + "_test"
if *prefix != "" {
data.PackagePrefix = *prefix
} else {
data.PackagePrefix = packageTestFunctionPrefix(pkg) + "Backend"
}
data.Package = pkg
data.Funcs = findTestFunctions()
generateOutput(f, data)

View File

@ -19,115 +19,88 @@ import (
"restic/backend"
)
// CreateFn is a function that creates a temporary repository for the tests.
var CreateFn func() (restic.Backend, error)
// Suite implements a test suite for restic backends.
type Suite struct {
Config interface{}
// OpenFn is a function that opens a previously created temporary repository.
var OpenFn func() (restic.Backend, error)
// NewConfig returns a config for a new temporary backend that will be used in tests.
NewConfig func() (interface{}, error)
// CleanupFn removes temporary files and directories created during the tests.
var CleanupFn func() error
// CreateFn is a function that creates a temporary repository for the tests.
Create func(cfg interface{}) (restic.Backend, error)
// MinimalData instructs the tests to not use excessive data.
var MinimalData = false
// OpenFn is a function that opens a previously created temporary repository.
Open func(cfg interface{}) (restic.Backend, error)
var but restic.Backend // backendUnderTest
var butInitialized bool
// CleanupFn removes data created during the tests.
Cleanup func(cfg interface{}) error
func open(t testing.TB) restic.Backend {
if OpenFn == nil {
t.Fatal("OpenFn not set")
}
if CreateFn == nil {
t.Fatalf("CreateFn not set")
}
if !butInitialized {
be, err := CreateFn()
if err != nil {
t.Fatalf("Create returned unexpected error: %+v", err)
}
but = be
butInitialized = true
}
if but == nil {
var err error
but, err = OpenFn()
if err != nil {
t.Fatalf("Open returned unexpected error: %+v", err)
}
}
return but
// MinimalData instructs the tests to not use excessive data.
MinimalData bool
}
func close(t testing.TB) {
if but == nil {
t.Fatalf("trying to close non-existing backend")
}
err := but.Close()
// RunTests executes all defined tests as subtests of t.
func (s *Suite) RunTests(t *testing.T) {
var err error
s.Config, err = s.NewConfig()
if err != nil {
t.Fatalf("Close returned unexpected error: %+v", err)
t.Fatal(err)
}
but = nil
}
// test create/open functions first
be := s.create(t)
s.close(t, be)
// TestCreate creates a backend.
func TestCreate(t testing.TB) {
if CreateFn == nil {
t.Fatalf("CreateFn not set!")
for _, test := range TestFunctions {
t.Run(test.Name, func(t *testing.T) {
test.Fn(t, s)
})
}
be, err := CreateFn()
if err != nil {
t.Fatalf("Create returned error: %+v", err)
if !test.TestCleanupTempDirs {
t.Logf("not cleaning up backend")
return
}
butInitialized = true
err = be.Close()
if err != nil {
t.Fatalf("Close returned error: %+v", err)
if err = s.Cleanup(s.Config); err != nil {
t.Fatal(err)
}
}
// TestOpen opens a previously created backend.
func TestOpen(t testing.TB) {
if OpenFn == nil {
t.Fatalf("OpenFn not set!")
}
be, err := OpenFn()
func (s *Suite) create(t testing.TB) restic.Backend {
be, err := s.Create(s.Config)
if err != nil {
t.Fatalf("Open returned error: %+v", err)
t.Fatal(err)
}
return be
}
err = be.Close()
func (s *Suite) open(t testing.TB) restic.Backend {
be, err := s.Open(s.Config)
if err != nil {
t.Fatalf("Close returned error: %+v", err)
t.Fatal(err)
}
return be
}
func (s *Suite) close(t testing.TB, be restic.Backend) {
err := be.Close()
if err != nil {
t.Fatal(err)
}
}
// TestCreateWithConfig tests that creating a backend in a location which already
// has a config file fails.
func TestCreateWithConfig(t testing.TB) {
if CreateFn == nil {
t.Fatalf("CreateFn not set")
}
b := open(t)
defer close(t)
func TestCreateWithConfig(t testing.TB, s *Suite) {
b := s.open(t)
defer s.close(t, b)
// save a config
store(t, b, restic.ConfigFile, []byte("test config"))
// now create the backend again, this must fail
_, err := CreateFn()
_, err := s.Create(s.Config)
if err == nil {
t.Fatalf("expected error not found for creating a backend with an existing config file")
}
@ -140,9 +113,9 @@ func TestCreateWithConfig(t testing.TB) {
}
// TestLocation tests that a location string is returned.
func TestLocation(t testing.TB) {
b := open(t)
defer close(t)
func TestLocation(t testing.TB, s *Suite) {
b := s.open(t)
defer s.close(t, b)
l := b.Location()
if l == "" {
@ -151,9 +124,9 @@ func TestLocation(t testing.TB) {
}
// TestConfig saves and loads a config from the backend.
func TestConfig(t testing.TB) {
b := open(t)
defer close(t)
func TestConfig(t testing.TB, s *Suite) {
b := s.open(t)
defer s.close(t, b)
var testString = "Config"
@ -184,9 +157,9 @@ func TestConfig(t testing.TB) {
}
// TestLoad tests the backend's Load function.
func TestLoad(t testing.TB) {
b := open(t)
defer close(t)
func TestLoad(t testing.TB, s *Suite) {
b := s.open(t)
defer s.close(t, b)
_, err := b.Load(restic.Handle{}, 0, 0)
if err == nil {
@ -219,7 +192,7 @@ func TestLoad(t testing.TB) {
}
loadTests := 50
if MinimalData {
if s.MinimalData {
loadTests = 10
}
@ -312,13 +285,13 @@ func (ec errorCloser) Close() error {
}
// TestSave tests saving data in the backend.
func TestSave(t testing.TB) {
b := open(t)
defer close(t)
func TestSave(t testing.TB, s *Suite) {
b := s.open(t)
defer s.close(t, b)
var id restic.ID
saveTests := 10
if MinimalData {
if s.MinimalData {
saveTests = 2
}
@ -412,9 +385,9 @@ var filenameTests = []struct {
}
// TestSaveFilenames tests saving data with various file names in the backend.
func TestSaveFilenames(t testing.TB) {
b := open(t)
defer close(t)
func TestSaveFilenames(t testing.TB, s *Suite) {
b := s.open(t)
defer s.close(t, b)
for i, test := range filenameTests {
h := restic.Handle{Name: test.name, Type: restic.DataFile}
@ -461,9 +434,9 @@ func store(t testing.TB, b restic.Backend, tpe restic.FileType, data []byte) res
}
// TestBackend tests all functions of the backend.
func TestBackend(t testing.TB) {
b := open(t)
defer close(t)
func TestBackend(t testing.TB, s *Suite) {
b := s.open(t)
defer s.close(t, b)
for _, tpe := range []restic.FileType{
restic.DataFile, restic.KeyFile, restic.LockFile,
@ -595,9 +568,13 @@ func TestBackend(t testing.TB) {
}
// TestDelete tests the Delete function.
func TestDelete(t testing.TB) {
b := open(t)
defer close(t)
func TestDelete(t testing.TB, s *Suite) {
if !test.TestCleanupTempDirs {
t.Skipf("not removing backend, TestCleanupTempDirs is false")
}
b := s.open(t)
defer s.close(t, b)
be, ok := b.(restic.Deleter)
if !ok {
@ -609,21 +586,3 @@ func TestDelete(t testing.TB) {
t.Fatalf("error deleting backend: %+v", err)
}
}
// TestCleanup runs the cleanup function after all tests are run.
func TestCleanup(t testing.TB) {
if CleanupFn == nil {
t.Log("CleanupFn function not set")
return
}
if !test.TestCleanupTempDirs {
t.Logf("not cleaning up backend")
return
}
err := CleanupFn()
if err != nil {
t.Fatalf("Cleanup returned error: %+v", err)
}
}

View File

@ -2,38 +2,59 @@ package test_test
import (
"restic"
"restic/errors"
"testing"
"restic/backend/mem"
"restic/backend/test"
)
var be restic.Backend
//go:generate go run generate_test_list.go
//go:generate go run ../test/generate_backend_tests.go
func init() {
test.CreateFn = func() (restic.Backend, error) {
if be != nil {
return nil, errors.New("temporary memory backend dir already exists")
}
be = mem.New()
return be, nil
}
test.OpenFn = func() (restic.Backend, error) {
if be == nil {
return nil, errors.New("repository not initialized")
}
return be, nil
}
test.CleanupFn = func() error {
be = nil
return nil
}
type memConfig struct {
be restic.Backend
}
func TestSuiteBackendMem(t *testing.T) {
suite := test.Suite{
// NewConfig returns a config for a new temporary backend that will be used in tests.
NewConfig: func() (interface{}, error) {
return &memConfig{}, nil
},
// CreateFn is a function that creates a temporary repository for the tests.
Create: func(cfg interface{}) (restic.Backend, error) {
c := cfg.(*memConfig)
if c.be != nil {
ok, err := c.be.Test(restic.Handle{Type: restic.ConfigFile})
if err != nil {
return nil, err
}
if ok {
return nil, errors.New("config already exists")
}
}
c.be = mem.New()
return c.be, nil
},
// OpenFn is a function that opens a previously created temporary repository.
Open: func(cfg interface{}) (restic.Backend, error) {
c := cfg.(*memConfig)
if c.be == nil {
c.be = mem.New()
}
return c.be, nil
},
// CleanupFn removes data created during the tests.
Cleanup: func(cfg interface{}) error {
// no cleanup needed
return nil
},
}
suite.RunTests(t)
}