1
0
mirror of https://github.com/restic/restic.git synced 2024-06-27 07:55:08 +02: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 { var data struct {
Package string Package string
PackagePrefix string Funcs []string
Funcs []string
} }
var testTemplate = ` var testTemplate = `
@ -29,24 +28,20 @@ package {{ .Package }}
import ( import (
"testing" "testing"
"restic/backend/test"
) )
var SkipMessage string var TestFunctions = []struct {
Name string
{{ $prefix := .PackagePrefix }} Fn func(t testing.TB, suite *Suite)
{{ range $f := .Funcs }} }{
func Test{{ $prefix }}{{ $f }}(t *testing.T){ {{ range $f := .Funcs -}}
if SkipMessage != "" { t.Skip(SkipMessage) } {"{{ $f }}", Test{{ $f }},},
test.Test{{ $f }}(t)
}
{{ end }} {{ end }}
}
` `
var testFile = flag.String("testfile", "../test/tests.go", "file to search test functions in") var testFile = flag.String("testfile", "tests.go", "file to search test functions in")
var outputFile = flag.String("output", "backend_test.go", "output file to write generated code to") 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 packageName = flag.String("package", "", "the package name to use")
var prefix = flag.String("prefix", "", "test function prefix") var prefix = flag.String("prefix", "", "test function prefix")
var quiet = flag.Bool("quiet", false, "be quiet") var quiet = flag.Bool("quiet", false, "be quiet")
@ -123,12 +118,7 @@ func main() {
f, err := os.Create(*outputFile) f, err := os.Create(*outputFile)
errx(err) errx(err)
data.Package = pkg + "_test" data.Package = pkg
if *prefix != "" {
data.PackagePrefix = *prefix
} else {
data.PackagePrefix = packageTestFunctionPrefix(pkg) + "Backend"
}
data.Funcs = findTestFunctions() data.Funcs = findTestFunctions()
generateOutput(f, data) generateOutput(f, data)

View File

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