...

Source file src/github.com/google/go-cmp/cmp/options_test.go

Documentation: github.com/google/go-cmp/cmp

     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 file.
     4  
     5  package cmp
     6  
     7  import (
     8  	"io"
     9  	"reflect"
    10  	"strings"
    11  	"testing"
    12  
    13  	ts "github.com/google/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  	}, {
   120  		label:     "FilterPath",
   121  		fnc:       FilterPath,
   122  		args:      []interface{}{(func(Path) bool)(nil), Ignore()},
   123  		wantPanic: "invalid path filter function",
   124  	}, {
   125  		label: "FilterPath",
   126  		fnc:   FilterPath,
   127  		args:  []interface{}{func(Path) bool { return true }, Ignore()},
   128  	}, {
   129  		label:     "FilterPath",
   130  		fnc:       FilterPath,
   131  		args:      []interface{}{func(Path) bool { return true }, Reporter(&defaultReporter{})},
   132  		wantPanic: "invalid option type",
   133  	}, {
   134  		label: "FilterPath",
   135  		fnc:   FilterPath,
   136  		args:  []interface{}{func(Path) bool { return true }, Options{Ignore(), Ignore()}},
   137  	}, {
   138  		label:     "FilterPath",
   139  		fnc:       FilterPath,
   140  		args:      []interface{}{func(Path) bool { return true }, Options{Ignore(), Reporter(&defaultReporter{})}},
   141  		wantPanic: "invalid option type",
   142  	}, {
   143  		label:     "FilterValues",
   144  		fnc:       FilterValues,
   145  		args:      []interface{}{0, Ignore()},
   146  		wantPanic: "invalid values filter function",
   147  	}, {
   148  		label: "FilterValues",
   149  		fnc:   FilterValues,
   150  		args:  []interface{}{func(x, y int) bool { return true }, Ignore()},
   151  	}, {
   152  		label: "FilterValues",
   153  		fnc:   FilterValues,
   154  		args:  []interface{}{func(x, y interface{}) bool { return true }, Ignore()},
   155  	}, {
   156  		label:     "FilterValues",
   157  		fnc:       FilterValues,
   158  		args:      []interface{}{func(x, y interface{}) myBool { return true }, Ignore()},
   159  		wantPanic: "invalid values filter function",
   160  	}, {
   161  		label:     "FilterValues",
   162  		fnc:       FilterValues,
   163  		args:      []interface{}{func(x io.Reader, y interface{}) bool { return true }, Ignore()},
   164  		wantPanic: "invalid values filter function",
   165  	}, {
   166  		label:     "FilterValues",
   167  		fnc:       FilterValues,
   168  		args:      []interface{}{(func(int, int) bool)(nil), Ignore()},
   169  		wantPanic: "invalid values filter function",
   170  	}, {
   171  		label:     "FilterValues",
   172  		fnc:       FilterValues,
   173  		args:      []interface{}{func(int, int) bool { return true }, Reporter(&defaultReporter{})},
   174  		wantPanic: "invalid option type",
   175  	}, {
   176  		label: "FilterValues",
   177  		fnc:   FilterValues,
   178  		args:  []interface{}{func(int, int) bool { return true }, Options{Ignore(), Ignore()}},
   179  	}, {
   180  		label:     "FilterValues",
   181  		fnc:       FilterValues,
   182  		args:      []interface{}{func(int, int) bool { return true }, Options{Ignore(), Reporter(&defaultReporter{})}},
   183  		wantPanic: "invalid option type",
   184  	}}
   185  
   186  	for _, tt := range tests {
   187  		t.Run(tt.label, func(t *testing.T) {
   188  			var gotPanic string
   189  			func() {
   190  				defer func() {
   191  					if ex := recover(); ex != nil {
   192  						if s, ok := ex.(string); ok {
   193  							gotPanic = s
   194  						} else {
   195  							panic(ex)
   196  						}
   197  					}
   198  				}()
   199  				var vargs []reflect.Value
   200  				for _, arg := range tt.args {
   201  					vargs = append(vargs, reflect.ValueOf(arg))
   202  				}
   203  				reflect.ValueOf(tt.fnc).Call(vargs)
   204  			}()
   205  			if tt.wantPanic == "" {
   206  				if gotPanic != "" {
   207  					t.Fatalf("unexpected panic message: %s", gotPanic)
   208  				}
   209  			} else {
   210  				if !strings.Contains(gotPanic, tt.wantPanic) {
   211  					t.Fatalf("panic message:\ngot:  %s\nwant: %s", gotPanic, tt.wantPanic)
   212  				}
   213  			}
   214  		})
   215  	}
   216  }
   217  

View as plain text