github.com/integration-system/go-cmp@v0.0.0-20190131081942-ac5582987a2f/cmp/options_test.go (about) 1 // Copyright 2017, The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE.md file. 4 5 package cmp 6 7 import ( 8 "io" 9 "reflect" 10 "strings" 11 "testing" 12 13 ts "github.com/integration-system/go-cmp/cmp/internal/teststructs" 14 ) 15 16 // Test that the creation of Option values with non-sensible inputs produces 17 // a run-time panic with a decent error message 18 func TestOptionPanic(t *testing.T) { 19 type myBool bool 20 tests := []struct { 21 label string // Test description 22 fnc interface{} // Option function to call 23 args []interface{} // Arguments to pass in 24 wantPanic string // Expected panic message 25 }{{ 26 label: "AllowUnexported", 27 fnc: AllowUnexported, 28 args: []interface{}{}, 29 }, { 30 label: "AllowUnexported", 31 fnc: AllowUnexported, 32 args: []interface{}{1}, 33 wantPanic: "invalid struct type", 34 }, { 35 label: "AllowUnexported", 36 fnc: AllowUnexported, 37 args: []interface{}{ts.StructA{}}, 38 }, { 39 label: "AllowUnexported", 40 fnc: AllowUnexported, 41 args: []interface{}{ts.StructA{}, ts.StructB{}, ts.StructA{}}, 42 }, { 43 label: "AllowUnexported", 44 fnc: AllowUnexported, 45 args: []interface{}{ts.StructA{}, &ts.StructB{}, ts.StructA{}}, 46 wantPanic: "invalid struct type", 47 }, { 48 label: "Comparer", 49 fnc: Comparer, 50 args: []interface{}{5}, 51 wantPanic: "invalid comparer function", 52 }, { 53 label: "Comparer", 54 fnc: Comparer, 55 args: []interface{}{func(x, y interface{}) bool { return true }}, 56 }, { 57 label: "Comparer", 58 fnc: Comparer, 59 args: []interface{}{func(x, y io.Reader) bool { return true }}, 60 }, { 61 label: "Comparer", 62 fnc: Comparer, 63 args: []interface{}{func(x, y io.Reader) myBool { return true }}, 64 wantPanic: "invalid comparer function", 65 }, { 66 label: "Comparer", 67 fnc: Comparer, 68 args: []interface{}{func(x string, y interface{}) bool { return true }}, 69 wantPanic: "invalid comparer function", 70 }, { 71 label: "Comparer", 72 fnc: Comparer, 73 args: []interface{}{(func(int, int) bool)(nil)}, 74 wantPanic: "invalid comparer function", 75 }, { 76 label: "Transformer", 77 fnc: Transformer, 78 args: []interface{}{"", 0}, 79 wantPanic: "invalid transformer function", 80 }, { 81 label: "Transformer", 82 fnc: Transformer, 83 args: []interface{}{"", func(int) int { return 0 }}, 84 }, { 85 label: "Transformer", 86 fnc: Transformer, 87 args: []interface{}{"", func(bool) bool { return true }}, 88 }, { 89 label: "Transformer", 90 fnc: Transformer, 91 args: []interface{}{"", func(int) bool { return true }}, 92 }, { 93 label: "Transformer", 94 fnc: Transformer, 95 args: []interface{}{"", func(int, int) bool { return true }}, 96 wantPanic: "invalid transformer function", 97 }, { 98 label: "Transformer", 99 fnc: Transformer, 100 args: []interface{}{"", (func(int) uint)(nil)}, 101 wantPanic: "invalid transformer function", 102 }, { 103 label: "Transformer", 104 fnc: Transformer, 105 args: []interface{}{"Func", func(Path) Path { return nil }}, 106 }, { 107 label: "Transformer", 108 fnc: Transformer, 109 args: []interface{}{"世界", func(int) bool { return true }}, 110 }, { 111 label: "Transformer", 112 fnc: Transformer, 113 args: []interface{}{"/*", func(int) bool { return true }}, 114 wantPanic: "invalid name", 115 }, { 116 label: "Transformer", 117 fnc: Transformer, 118 args: []interface{}{"_", func(int) bool { return true }}, 119 wantPanic: "invalid name", 120 }, { 121 label: "FilterPath", 122 fnc: FilterPath, 123 args: []interface{}{(func(Path) bool)(nil), Ignore()}, 124 wantPanic: "invalid path filter function", 125 }, { 126 label: "FilterPath", 127 fnc: FilterPath, 128 args: []interface{}{func(Path) bool { return true }, Ignore()}, 129 }, { 130 label: "FilterPath", 131 fnc: FilterPath, 132 args: []interface{}{func(Path) bool { return true }, &defaultReporter{}}, 133 wantPanic: "invalid option type", 134 }, { 135 label: "FilterPath", 136 fnc: FilterPath, 137 args: []interface{}{func(Path) bool { return true }, Options{Ignore(), Ignore()}}, 138 }, { 139 label: "FilterPath", 140 fnc: FilterPath, 141 args: []interface{}{func(Path) bool { return true }, Options{Ignore(), &defaultReporter{}}}, 142 wantPanic: "invalid option type", 143 }, { 144 label: "FilterValues", 145 fnc: FilterValues, 146 args: []interface{}{0, Ignore()}, 147 wantPanic: "invalid values filter function", 148 }, { 149 label: "FilterValues", 150 fnc: FilterValues, 151 args: []interface{}{func(x, y int) bool { return true }, Ignore()}, 152 }, { 153 label: "FilterValues", 154 fnc: FilterValues, 155 args: []interface{}{func(x, y interface{}) bool { return true }, Ignore()}, 156 }, { 157 label: "FilterValues", 158 fnc: FilterValues, 159 args: []interface{}{func(x, y interface{}) myBool { return true }, Ignore()}, 160 wantPanic: "invalid values filter function", 161 }, { 162 label: "FilterValues", 163 fnc: FilterValues, 164 args: []interface{}{func(x io.Reader, y interface{}) bool { return true }, Ignore()}, 165 wantPanic: "invalid values filter function", 166 }, { 167 label: "FilterValues", 168 fnc: FilterValues, 169 args: []interface{}{(func(int, int) bool)(nil), Ignore()}, 170 wantPanic: "invalid values filter function", 171 }, { 172 label: "FilterValues", 173 fnc: FilterValues, 174 args: []interface{}{func(int, int) bool { return true }, &defaultReporter{}}, 175 wantPanic: "invalid option type", 176 }, { 177 label: "FilterValues", 178 fnc: FilterValues, 179 args: []interface{}{func(int, int) bool { return true }, Options{Ignore(), Ignore()}}, 180 }, { 181 label: "FilterValues", 182 fnc: FilterValues, 183 args: []interface{}{func(int, int) bool { return true }, Options{Ignore(), &defaultReporter{}}}, 184 wantPanic: "invalid option type", 185 }} 186 187 for _, tt := range tests { 188 t.Run(tt.label, func(t *testing.T) { 189 var gotPanic string 190 func() { 191 defer func() { 192 if ex := recover(); ex != nil { 193 if s, ok := ex.(string); ok { 194 gotPanic = s 195 } else { 196 panic(ex) 197 } 198 } 199 }() 200 var vargs []reflect.Value 201 for _, arg := range tt.args { 202 vargs = append(vargs, reflect.ValueOf(arg)) 203 } 204 reflect.ValueOf(tt.fnc).Call(vargs) 205 }() 206 if tt.wantPanic == "" { 207 if gotPanic != "" { 208 t.Fatalf("unexpected panic message: %s", gotPanic) 209 } 210 } else { 211 if !strings.Contains(gotPanic, tt.wantPanic) { 212 t.Fatalf("panic message:\ngot: %s\nwant: %s", gotPanic, tt.wantPanic) 213 } 214 } 215 }) 216 } 217 }