forked from TrueCloudLab/restic
tests: Add BenchmarkLoadFile
This commit is contained in:
parent
f142b1c22f
commit
77ebb95d3d
6 changed files with 202 additions and 124 deletions
59
src/restic/backend/test/benchmarks.go
Normal file
59
src/restic/backend/test/benchmarks.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"restic"
|
||||
"restic/test"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// BackendBenchmarkLoad benchmarks the backend's Load function.
|
||||
func BackendBenchmarkLoadFile(t *testing.B, s *Suite) {
|
||||
be := s.open(t)
|
||||
defer s.close(t, be)
|
||||
|
||||
length := 1<<24 + 2123
|
||||
data := test.Random(23, length)
|
||||
id := restic.Hash(data)
|
||||
handle := restic.Handle{Type: restic.DataFile, Name: id.String()}
|
||||
if err := be.Save(handle, bytes.NewReader(data)); err != nil {
|
||||
t.Fatalf("Save() error: %+v", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := be.Remove(handle); err != nil {
|
||||
t.Fatalf("Remove() returned error: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
buf := make([]byte, length)
|
||||
|
||||
t.SetBytes(int64(length))
|
||||
t.ResetTimer()
|
||||
|
||||
for i := 0; i < t.N; i++ {
|
||||
rd, err := be.Load(handle, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
n, err := io.ReadFull(rd, buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = rd.Close(); err != nil {
|
||||
t.Fatalf("Close() returned error: %v", err)
|
||||
}
|
||||
|
||||
if n != length {
|
||||
t.Fatalf("wrong number of bytes read: want %v, got %v", length, n)
|
||||
}
|
||||
|
||||
if !bytes.Equal(data, buf) {
|
||||
t.Fatalf("wrong bytes returned")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
var testFunctions = []struct {
|
||||
Name string
|
||||
Fn func(t testing.TB, suite *Suite)
|
||||
Fn func(testing.TB, *Suite)
|
||||
}{
|
||||
{"CreateWithConfig", BackendTestCreateWithConfig},
|
||||
{"Location", BackendTestLocation},
|
||||
|
@ -22,5 +22,7 @@ var testFunctions = []struct {
|
|||
|
||||
var benchmarkFunctions = []struct {
|
||||
Name string
|
||||
Fn func(t testing.TB, suite *Suite)
|
||||
}{}
|
||||
Fn func(*testing.B, *Suite)
|
||||
}{
|
||||
{"LoadFile", BackendBenchmarkLoadFile},
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
@ -35,7 +36,7 @@ import (
|
|||
|
||||
var testFunctions = []struct {
|
||||
Name string
|
||||
Fn func(t testing.TB, suite *Suite)
|
||||
Fn func(testing.TB, *Suite)
|
||||
}{
|
||||
{{ range $f := .TestFuncs -}}
|
||||
{"{{ $f }}", BackendTest{{ $f }},},
|
||||
|
@ -44,7 +45,7 @@ var testFunctions = []struct {
|
|||
|
||||
var benchmarkFunctions = []struct {
|
||||
Name string
|
||||
Fn func(t testing.TB, suite *Suite)
|
||||
Fn func(*testing.B, *Suite)
|
||||
}{
|
||||
{{ range $f := .BenchmarkFuncs -}}
|
||||
{"{{ $f }}", BackendBenchmark{{ $f }},},
|
||||
|
@ -52,7 +53,7 @@ var benchmarkFunctions = []struct {
|
|||
}
|
||||
`
|
||||
|
||||
var testFile = flag.String("testfile", "tests.go", "file to search test functions in")
|
||||
var testFiles = flag.String("testfiles", "tests.go,benchmarks.go", "files to search test functions in (comma separated)")
|
||||
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")
|
||||
|
@ -71,27 +72,30 @@ var testFuncRegex = regexp.MustCompile(`^func\s+BackendTest(.+)\s*\(`)
|
|||
var benchmarkFuncRegex = regexp.MustCompile(`^func\s+BackendBenchmark(.+)\s*\(`)
|
||||
|
||||
func findFunctions() (testFuncs, benchmarkFuncs []string) {
|
||||
f, err := os.Open(*testFile)
|
||||
errx(err)
|
||||
for _, filename := range strings.Split(*testFiles, ",") {
|
||||
f, err := os.Open(filename)
|
||||
errx(err)
|
||||
|
||||
sc := bufio.NewScanner(f)
|
||||
for sc.Scan() {
|
||||
match := testFuncRegex.FindStringSubmatch(sc.Text())
|
||||
if len(match) > 0 {
|
||||
testFuncs = append(testFuncs, match[1])
|
||||
sc := bufio.NewScanner(f)
|
||||
for sc.Scan() {
|
||||
match := testFuncRegex.FindStringSubmatch(sc.Text())
|
||||
if len(match) > 0 {
|
||||
testFuncs = append(testFuncs, match[1])
|
||||
}
|
||||
|
||||
match = benchmarkFuncRegex.FindStringSubmatch(sc.Text())
|
||||
if len(match) > 0 {
|
||||
benchmarkFuncs = append(benchmarkFuncs, match[1])
|
||||
}
|
||||
}
|
||||
|
||||
match = benchmarkFuncRegex.FindStringSubmatch(sc.Text())
|
||||
if len(match) > 0 {
|
||||
benchmarkFuncs = append(benchmarkFuncs, match[1])
|
||||
if err := sc.Err(); err != nil {
|
||||
log.Fatalf("Error scanning file: %v", err)
|
||||
}
|
||||
|
||||
errx(f.Close())
|
||||
}
|
||||
|
||||
if err := sc.Err(); err != nil {
|
||||
log.Fatalf("Error scanning file: %v", err)
|
||||
}
|
||||
|
||||
errx(f.Close())
|
||||
return testFuncs, benchmarkFuncs
|
||||
}
|
||||
|
||||
|
|
106
src/restic/backend/test/suite.go
Normal file
106
src/restic/backend/test/suite.go
Normal file
|
@ -0,0 +1,106 @@
|
|||
package test
|
||||
|
||||
import (
|
||||
"restic"
|
||||
"restic/test"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Suite implements a test suite for restic backends.
|
||||
type Suite struct {
|
||||
Config interface{}
|
||||
|
||||
// NewConfig returns a config for a new temporary backend that will be used in tests.
|
||||
NewConfig func() (interface{}, error)
|
||||
|
||||
// CreateFn is a function that creates a temporary repository for the tests.
|
||||
Create func(cfg interface{}) (restic.Backend, error)
|
||||
|
||||
// OpenFn is a function that opens a previously created temporary repository.
|
||||
Open func(cfg interface{}) (restic.Backend, error)
|
||||
|
||||
// CleanupFn removes data created during the tests.
|
||||
Cleanup func(cfg interface{}) error
|
||||
|
||||
// MinimalData instructs the tests to not use excessive data.
|
||||
MinimalData bool
|
||||
}
|
||||
|
||||
// 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.Fatal(err)
|
||||
}
|
||||
|
||||
// test create/open functions first
|
||||
be := s.create(t)
|
||||
s.close(t, be)
|
||||
|
||||
for _, test := range testFunctions {
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
test.Fn(t, s)
|
||||
})
|
||||
}
|
||||
|
||||
if !test.TestCleanupTempDirs {
|
||||
t.Logf("not cleaning up backend")
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.Cleanup(s.Config); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// RunBenchmarks executes all defined benchmarks as subtests of b.
|
||||
func (s *Suite) RunBenchmarks(b *testing.B) {
|
||||
var err error
|
||||
s.Config, err = s.NewConfig()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
// test create/open functions first
|
||||
be := s.create(b)
|
||||
s.close(b, be)
|
||||
|
||||
for _, test := range benchmarkFunctions {
|
||||
b.Run(test.Name, func(b *testing.B) {
|
||||
test.Fn(b, s)
|
||||
})
|
||||
}
|
||||
|
||||
if !test.TestCleanupTempDirs {
|
||||
b.Logf("not cleaning up backend")
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.Cleanup(s.Config); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Suite) create(t testing.TB) restic.Backend {
|
||||
be, err := s.Create(s.Config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return be
|
||||
}
|
||||
|
||||
func (s *Suite) open(t testing.TB) restic.Backend {
|
||||
be, err := s.Open(s.Config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return be
|
||||
}
|
||||
|
||||
func (s *Suite) close(t testing.TB, be restic.Backend) {
|
||||
err := be.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
|
@ -20,105 +20,6 @@ import (
|
|||
"restic/backend"
|
||||
)
|
||||
|
||||
// Suite implements a test suite for restic backends.
|
||||
type Suite struct {
|
||||
Config interface{}
|
||||
|
||||
// NewConfig returns a config for a new temporary backend that will be used in tests.
|
||||
NewConfig func() (interface{}, error)
|
||||
|
||||
// CreateFn is a function that creates a temporary repository for the tests.
|
||||
Create func(cfg interface{}) (restic.Backend, error)
|
||||
|
||||
// OpenFn is a function that opens a previously created temporary repository.
|
||||
Open func(cfg interface{}) (restic.Backend, error)
|
||||
|
||||
// CleanupFn removes data created during the tests.
|
||||
Cleanup func(cfg interface{}) error
|
||||
|
||||
// MinimalData instructs the tests to not use excessive data.
|
||||
MinimalData bool
|
||||
}
|
||||
|
||||
// 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.Fatal(err)
|
||||
}
|
||||
|
||||
// test create/open functions first
|
||||
be := s.create(t)
|
||||
s.close(t, be)
|
||||
|
||||
for _, test := range testFunctions {
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
test.Fn(t, s)
|
||||
})
|
||||
}
|
||||
|
||||
if !test.TestCleanupTempDirs {
|
||||
t.Logf("not cleaning up backend")
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.Cleanup(s.Config); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// RunBenchmarks executes all defined benchmarks as subtests of b.
|
||||
func (s *Suite) RunBenchmarks(b *testing.B) {
|
||||
var err error
|
||||
s.Config, err = s.NewConfig()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
// test create/open functions first
|
||||
be := s.create(b)
|
||||
s.close(b, be)
|
||||
|
||||
for _, test := range benchmarkFunctions {
|
||||
b.Run(test.Name, func(b *testing.B) {
|
||||
test.Fn(b, s)
|
||||
})
|
||||
}
|
||||
|
||||
if !test.TestCleanupTempDirs {
|
||||
b.Logf("not cleaning up backend")
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.Cleanup(s.Config); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Suite) create(t testing.TB) restic.Backend {
|
||||
be, err := s.Create(s.Config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return be
|
||||
}
|
||||
|
||||
func (s *Suite) open(t testing.TB) restic.Backend {
|
||||
be, err := s.Open(s.Config)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return be
|
||||
}
|
||||
|
||||
func (s *Suite) close(t testing.TB, be restic.Backend) {
|
||||
err := be.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// BackendTestCreateWithConfig tests that creating a backend in a location which already
|
||||
// has a config file fails.
|
||||
func BackendTestCreateWithConfig(t testing.TB, s *Suite) {
|
||||
|
|
|
@ -15,8 +15,8 @@ type memConfig struct {
|
|||
be restic.Backend
|
||||
}
|
||||
|
||||
func TestSuiteBackendMem(t *testing.T) {
|
||||
suite := test.Suite{
|
||||
func newTestSuite(t testing.TB) *test.Suite {
|
||||
return &test.Suite{
|
||||
// NewConfig returns a config for a new temporary backend that will be used in tests.
|
||||
NewConfig: func() (interface{}, error) {
|
||||
return &memConfig{}, nil
|
||||
|
@ -55,6 +55,12 @@ func TestSuiteBackendMem(t *testing.T) {
|
|||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
suite.RunTests(t)
|
||||
}
|
||||
|
||||
func TestSuiteBackendMem(t *testing.T) {
|
||||
newTestSuite(t).RunTests(t)
|
||||
}
|
||||
|
||||
func BenchmarkSuiteBackendMem(b *testing.B) {
|
||||
newTestSuite(b).RunBenchmarks(b)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue