Implement test suite for backend tests
This commit is contained in:
parent
a963052d64
commit
6f5fd72738
5 changed files with 157 additions and 254 deletions
|
@ -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)
|
|
||||||
}
|
|
20
src/restic/backend/test/funcs.go
Normal file
20
src/restic/backend/test/funcs.go
Normal 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},
|
||||||
|
}
|
|
@ -19,7 +19,6 @@ import (
|
||||||
|
|
||||||
var data struct {
|
var data struct {
|
||||||
Package string
|
Package string
|
||||||
PackagePrefix string
|
|
||||||
Funcs []string
|
Funcs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
// RunTests executes all defined tests as subtests of t.
|
||||||
t.Fatalf("CreateFn not set")
|
func (s *Suite) RunTests(t *testing.T) {
|
||||||
}
|
|
||||||
|
|
||||||
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
|
var err error
|
||||||
but, err = OpenFn()
|
s.Config, err = s.NewConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Open returned unexpected error: %+v", err)
|
t.Fatal(err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return but
|
// test create/open functions first
|
||||||
}
|
be := s.create(t)
|
||||||
|
s.close(t, be)
|
||||||
|
|
||||||
func close(t testing.TB) {
|
for _, test := range TestFunctions {
|
||||||
if but == nil {
|
t.Run(test.Name, func(t *testing.T) {
|
||||||
t.Fatalf("trying to close non-existing backend")
|
test.Fn(t, s)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
err := but.Close()
|
if !test.TestCleanupTempDirs {
|
||||||
if err != nil {
|
t.Logf("not cleaning up backend")
|
||||||
t.Fatalf("Close returned unexpected error: %+v", err)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
but = nil
|
if err = s.Cleanup(s.Config); err != nil {
|
||||||
}
|
t.Fatal(err)
|
||||||
|
|
||||||
// TestCreate creates a backend.
|
|
||||||
func TestCreate(t testing.TB) {
|
|
||||||
if CreateFn == nil {
|
|
||||||
t.Fatalf("CreateFn not set!")
|
|
||||||
}
|
|
||||||
|
|
||||||
be, err := CreateFn()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Create returned error: %+v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
butInitialized = true
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue