...

Source file src/golang.org/x/xerrors/wrap_test.go

Documentation: golang.org/x/xerrors

     1  // Copyright 2018 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 xerrors_test
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"testing"
    11  
    12  	"golang.org/x/xerrors"
    13  )
    14  
    15  func TestIs(t *testing.T) {
    16  	err1 := xerrors.New("1")
    17  	erra := xerrors.Errorf("wrap 2: %w", err1)
    18  	errb := xerrors.Errorf("wrap 3: %w", erra)
    19  	erro := xerrors.Opaque(err1)
    20  	errco := xerrors.Errorf("opaque: %w", erro)
    21  	err3 := xerrors.New("3")
    22  
    23  	poser := &poser{"either 1 or 3", func(err error) bool {
    24  		return err == err1 || err == err3
    25  	}}
    26  
    27  	testCases := []struct {
    28  		err    error
    29  		target error
    30  		match  bool
    31  	}{
    32  		{nil, nil, true},
    33  		{nil, err1, false},
    34  		{err1, nil, false},
    35  		{err1, err1, true},
    36  		{erra, err1, true},
    37  		{errb, err1, true},
    38  		{errco, erro, true},
    39  		{errco, err1, false},
    40  		{erro, erro, true},
    41  		{err1, err3, false},
    42  		{erra, err3, false},
    43  		{errb, err3, false},
    44  		{poser, err1, true},
    45  		{poser, err3, true},
    46  		{poser, erra, false},
    47  		{poser, errb, false},
    48  		{poser, erro, false},
    49  		{poser, errco, false},
    50  		{errorUncomparable{}, errorUncomparable{}, true},
    51  		{errorUncomparable{}, &errorUncomparable{}, false},
    52  		{&errorUncomparable{}, errorUncomparable{}, true},
    53  		{&errorUncomparable{}, &errorUncomparable{}, false},
    54  		{errorUncomparable{}, err1, false},
    55  		{&errorUncomparable{}, err1, false},
    56  	}
    57  	for _, tc := range testCases {
    58  		t.Run("", func(t *testing.T) {
    59  			if got := xerrors.Is(tc.err, tc.target); got != tc.match {
    60  				t.Errorf("Is(%v, %v) = %v, want %v", tc.err, tc.target, got, tc.match)
    61  			}
    62  		})
    63  	}
    64  }
    65  
    66  type poser struct {
    67  	msg string
    68  	f   func(error) bool
    69  }
    70  
    71  func (p *poser) Error() string     { return p.msg }
    72  func (p *poser) Is(err error) bool { return p.f(err) }
    73  func (p *poser) As(err interface{}) bool {
    74  	switch x := err.(type) {
    75  	case **poser:
    76  		*x = p
    77  	case *errorT:
    78  		*x = errorT{}
    79  	case **os.PathError:
    80  		*x = &os.PathError{}
    81  	default:
    82  		return false
    83  	}
    84  	return true
    85  }
    86  
    87  func TestAs(t *testing.T) {
    88  	var errT errorT
    89  	var errP *os.PathError
    90  	var timeout interface{ Timeout() bool }
    91  	var p *poser
    92  	_, errF := os.Open("non-existing")
    93  
    94  	testCases := []struct {
    95  		err    error
    96  		target interface{}
    97  		match  bool
    98  	}{{
    99  		nil,
   100  		&errP,
   101  		false,
   102  	}, {
   103  		xerrors.Errorf("pittied the fool: %w", errorT{}),
   104  		&errT,
   105  		true,
   106  	}, {
   107  		errF,
   108  		&errP,
   109  		true,
   110  	}, {
   111  		xerrors.Opaque(errT),
   112  		&errT,
   113  		false,
   114  	}, {
   115  		errorT{},
   116  		&errP,
   117  		false,
   118  	}, {
   119  		errWrap{nil},
   120  		&errT,
   121  		false,
   122  	}, {
   123  		&poser{"error", nil},
   124  		&errT,
   125  		true,
   126  	}, {
   127  		&poser{"path", nil},
   128  		&errP,
   129  		true,
   130  	}, {
   131  		&poser{"oh no", nil},
   132  		&p,
   133  		true,
   134  	}, {
   135  		xerrors.New("err"),
   136  		&timeout,
   137  		false,
   138  	}, {
   139  		errF,
   140  		&timeout,
   141  		true,
   142  	}, {
   143  		xerrors.Errorf("path error: %w", errF),
   144  		&timeout,
   145  		true,
   146  	}}
   147  	for i, tc := range testCases {
   148  		name := fmt.Sprintf("%d:As(Errorf(..., %v), %v)", i, tc.err, tc.target)
   149  		t.Run(name, func(t *testing.T) {
   150  			match := xerrors.As(tc.err, tc.target)
   151  			if match != tc.match {
   152  				t.Fatalf("xerrors.As(%T, %T): got %v; want %v", tc.err, tc.target, match, tc.match)
   153  			}
   154  			if !match {
   155  				return
   156  			}
   157  			if tc.target == nil {
   158  				t.Fatalf("non-nil result after match")
   159  			}
   160  		})
   161  	}
   162  }
   163  
   164  func TestAsValidation(t *testing.T) {
   165  	var s string
   166  	testCases := []interface{}{
   167  		nil,
   168  		(*int)(nil),
   169  		"error",
   170  		&s,
   171  	}
   172  	err := xerrors.New("error")
   173  	for _, tc := range testCases {
   174  		t.Run(fmt.Sprintf("%T(%v)", tc, tc), func(t *testing.T) {
   175  			defer func() {
   176  				recover()
   177  			}()
   178  			if xerrors.As(err, tc) {
   179  				t.Errorf("As(err, %T(%v)) = true, want false", tc, tc)
   180  				return
   181  			}
   182  			t.Errorf("As(err, %T(%v)) did not panic", tc, tc)
   183  		})
   184  	}
   185  }
   186  
   187  func TestUnwrap(t *testing.T) {
   188  	err1 := xerrors.New("1")
   189  	erra := xerrors.Errorf("wrap 2: %w", err1)
   190  	erro := xerrors.Opaque(err1)
   191  
   192  	testCases := []struct {
   193  		err  error
   194  		want error
   195  	}{
   196  		{nil, nil},
   197  		{errWrap{nil}, nil},
   198  		{err1, nil},
   199  		{erra, err1},
   200  		{xerrors.Errorf("wrap 3: %w", erra), erra},
   201  
   202  		{erro, nil},
   203  		{xerrors.Errorf("opaque: %w", erro), erro},
   204  	}
   205  	for _, tc := range testCases {
   206  		if got := xerrors.Unwrap(tc.err); got != tc.want {
   207  			t.Errorf("Unwrap(%v) = %v, want %v", tc.err, got, tc.want)
   208  		}
   209  	}
   210  }
   211  
   212  func TestOpaque(t *testing.T) {
   213  	got := fmt.Sprintf("%v", xerrors.Errorf("foo: %v", xerrors.Opaque(errorT{})))
   214  	want := "foo: errorT"
   215  	if got != want {
   216  		t.Errorf("error without Format: got %v; want %v", got, want)
   217  	}
   218  
   219  	got = fmt.Sprintf("%v", xerrors.Errorf("foo: %v", xerrors.Opaque(errorD{})))
   220  	want = "foo: errorD"
   221  	if got != want {
   222  		t.Errorf("error with Format: got %v; want %v", got, want)
   223  	}
   224  }
   225  
   226  type errorT struct{}
   227  
   228  func (errorT) Error() string { return "errorT" }
   229  
   230  type errorD struct{}
   231  
   232  func (errorD) Error() string { return "errorD" }
   233  
   234  func (errorD) FormatError(p xerrors.Printer) error {
   235  	p.Print("errorD")
   236  	p.Detail()
   237  	p.Print("detail")
   238  	return nil
   239  }
   240  
   241  type errWrap struct{ error }
   242  
   243  func (errWrap) Error() string { return "wrapped" }
   244  
   245  func (errWrap) Unwrap() error { return nil }
   246  
   247  type errorUncomparable struct {
   248  	f []string
   249  }
   250  
   251  func (errorUncomparable) Error() string {
   252  	return "uncomparable error"
   253  }
   254  
   255  func (errorUncomparable) Is(target error) bool {
   256  	_, ok := target.(errorUncomparable)
   257  	return ok
   258  }
   259  

View as plain text