mirror of
https://github.com/restic/restic.git
synced 2024-08-21 11:53:22 +02:00
232 lines
6.7 KiB
Go
232 lines
6.7 KiB
Go
|
// Copyright 2017, The Go Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE.md file.
|
||
|
|
||
|
package cmp
|
||
|
|
||
|
import (
|
||
|
"io"
|
||
|
"reflect"
|
||
|
"strings"
|
||
|
"testing"
|
||
|
|
||
|
ts "github.com/google/go-cmp/cmp/internal/teststructs"
|
||
|
)
|
||
|
|
||
|
// Test that the creation of Option values with non-sensible inputs produces
|
||
|
// a run-time panic with a decent error message
|
||
|
func TestOptionPanic(t *testing.T) {
|
||
|
type myBool bool
|
||
|
tests := []struct {
|
||
|
label string // Test description
|
||
|
fnc interface{} // Option function to call
|
||
|
args []interface{} // Arguments to pass in
|
||
|
wantPanic string // Expected panic message
|
||
|
}{{
|
||
|
label: "AllowUnexported",
|
||
|
fnc: AllowUnexported,
|
||
|
args: []interface{}{},
|
||
|
}, {
|
||
|
label: "AllowUnexported",
|
||
|
fnc: AllowUnexported,
|
||
|
args: []interface{}{1},
|
||
|
wantPanic: "invalid struct type",
|
||
|
}, {
|
||
|
label: "AllowUnexported",
|
||
|
fnc: AllowUnexported,
|
||
|
args: []interface{}{ts.StructA{}},
|
||
|
}, {
|
||
|
label: "AllowUnexported",
|
||
|
fnc: AllowUnexported,
|
||
|
args: []interface{}{ts.StructA{}, ts.StructB{}, ts.StructA{}},
|
||
|
}, {
|
||
|
label: "AllowUnexported",
|
||
|
fnc: AllowUnexported,
|
||
|
args: []interface{}{ts.StructA{}, &ts.StructB{}, ts.StructA{}},
|
||
|
wantPanic: "invalid struct type",
|
||
|
}, {
|
||
|
label: "Comparer",
|
||
|
fnc: Comparer,
|
||
|
args: []interface{}{5},
|
||
|
wantPanic: "invalid comparer function",
|
||
|
}, {
|
||
|
label: "Comparer",
|
||
|
fnc: Comparer,
|
||
|
args: []interface{}{func(x, y interface{}) bool { return true }},
|
||
|
}, {
|
||
|
label: "Comparer",
|
||
|
fnc: Comparer,
|
||
|
args: []interface{}{func(x, y io.Reader) bool { return true }},
|
||
|
}, {
|
||
|
label: "Comparer",
|
||
|
fnc: Comparer,
|
||
|
args: []interface{}{func(x, y io.Reader) myBool { return true }},
|
||
|
wantPanic: "invalid comparer function",
|
||
|
}, {
|
||
|
label: "Comparer",
|
||
|
fnc: Comparer,
|
||
|
args: []interface{}{func(x string, y interface{}) bool { return true }},
|
||
|
wantPanic: "invalid comparer function",
|
||
|
}, {
|
||
|
label: "Comparer",
|
||
|
fnc: Comparer,
|
||
|
args: []interface{}{(func(int, int) bool)(nil)},
|
||
|
wantPanic: "invalid comparer function",
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"", 0},
|
||
|
wantPanic: "invalid transformer function",
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"", func(int) int { return 0 }},
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"", func(bool) bool { return true }},
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"", func(int) bool { return true }},
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"", func(int, int) bool { return true }},
|
||
|
wantPanic: "invalid transformer function",
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"", (func(int) uint)(nil)},
|
||
|
wantPanic: "invalid transformer function",
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"Func", func(Path) Path { return nil }},
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"世界", func(int) bool { return true }},
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"/*", func(int) bool { return true }},
|
||
|
wantPanic: "invalid name",
|
||
|
}, {
|
||
|
label: "Transformer",
|
||
|
fnc: Transformer,
|
||
|
args: []interface{}{"_", func(int) bool { return true }},
|
||
|
wantPanic: "invalid name",
|
||
|
}, {
|
||
|
label: "FilterPath",
|
||
|
fnc: FilterPath,
|
||
|
args: []interface{}{(func(Path) bool)(nil), Ignore()},
|
||
|
wantPanic: "invalid path filter function",
|
||
|
}, {
|
||
|
label: "FilterPath",
|
||
|
fnc: FilterPath,
|
||
|
args: []interface{}{func(Path) bool { return true }, Ignore()},
|
||
|
}, {
|
||
|
label: "FilterPath",
|
||
|
fnc: FilterPath,
|
||
|
args: []interface{}{func(Path) bool { return true }, &defaultReporter{}},
|
||
|
wantPanic: "invalid option type",
|
||
|
}, {
|
||
|
label: "FilterPath",
|
||
|
fnc: FilterPath,
|
||
|
args: []interface{}{func(Path) bool { return true }, Options{Ignore(), Ignore()}},
|
||
|
}, {
|
||
|
label: "FilterPath",
|
||
|
fnc: FilterPath,
|
||
|
args: []interface{}{func(Path) bool { return true }, Options{Ignore(), &defaultReporter{}}},
|
||
|
wantPanic: "invalid option type",
|
||
|
}, {
|
||
|
label: "FilterValues",
|
||
|
fnc: FilterValues,
|
||
|
args: []interface{}{0, Ignore()},
|
||
|
wantPanic: "invalid values filter function",
|
||
|
}, {
|
||
|
label: "FilterValues",
|
||
|
fnc: FilterValues,
|
||
|
args: []interface{}{func(x, y int) bool { return true }, Ignore()},
|
||
|
}, {
|
||
|
label: "FilterValues",
|
||
|
fnc: FilterValues,
|
||
|
args: []interface{}{func(x, y interface{}) bool { return true }, Ignore()},
|
||
|
}, {
|
||
|
label: "FilterValues",
|
||
|
fnc: FilterValues,
|
||
|
args: []interface{}{func(x, y interface{}) myBool { return true }, Ignore()},
|
||
|
wantPanic: "invalid values filter function",
|
||
|
}, {
|
||
|
label: "FilterValues",
|
||
|
fnc: FilterValues,
|
||
|
args: []interface{}{func(x io.Reader, y interface{}) bool { return true }, Ignore()},
|
||
|
wantPanic: "invalid values filter function",
|
||
|
}, {
|
||
|
label: "FilterValues",
|
||
|
fnc: FilterValues,
|
||
|
args: []interface{}{(func(int, int) bool)(nil), Ignore()},
|
||
|
wantPanic: "invalid values filter function",
|
||
|
}, {
|
||
|
label: "FilterValues",
|
||
|
fnc: FilterValues,
|
||
|
args: []interface{}{func(int, int) bool { return true }, &defaultReporter{}},
|
||
|
wantPanic: "invalid option type",
|
||
|
}, {
|
||
|
label: "FilterValues",
|
||
|
fnc: FilterValues,
|
||
|
args: []interface{}{func(int, int) bool { return true }, Options{Ignore(), Ignore()}},
|
||
|
}, {
|
||
|
label: "FilterValues",
|
||
|
fnc: FilterValues,
|
||
|
args: []interface{}{func(int, int) bool { return true }, Options{Ignore(), &defaultReporter{}}},
|
||
|
wantPanic: "invalid option type",
|
||
|
}}
|
||
|
|
||
|
for _, tt := range tests {
|
||
|
tRun(t, tt.label, func(t *testing.T) {
|
||
|
var gotPanic string
|
||
|
func() {
|
||
|
defer func() {
|
||
|
if ex := recover(); ex != nil {
|
||
|
if s, ok := ex.(string); ok {
|
||
|
gotPanic = s
|
||
|
} else {
|
||
|
panic(ex)
|
||
|
}
|
||
|
}
|
||
|
}()
|
||
|
var vargs []reflect.Value
|
||
|
for _, arg := range tt.args {
|
||
|
vargs = append(vargs, reflect.ValueOf(arg))
|
||
|
}
|
||
|
reflect.ValueOf(tt.fnc).Call(vargs)
|
||
|
}()
|
||
|
if tt.wantPanic == "" {
|
||
|
if gotPanic != "" {
|
||
|
t.Fatalf("unexpected panic message: %s", gotPanic)
|
||
|
}
|
||
|
} else {
|
||
|
if !strings.Contains(gotPanic, tt.wantPanic) {
|
||
|
t.Fatalf("panic message:\ngot: %s\nwant: %s", gotPanic, tt.wantPanic)
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TODO: Delete this hack when we drop Go1.6 support.
|
||
|
func tRun(t *testing.T, name string, f func(t *testing.T)) {
|
||
|
type runner interface {
|
||
|
Run(string, func(t *testing.T)) bool
|
||
|
}
|
||
|
var ti interface{} = t
|
||
|
if r, ok := ti.(runner); ok {
|
||
|
r.Run(name, f)
|
||
|
} else {
|
||
|
t.Logf("Test: %s", name)
|
||
|
f(t)
|
||
|
}
|
||
|
}
|