github.com/xmidt-org/webpa-common@v1.11.9/xerrors/xerrors_test.go (about) 1 package xerrors 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "github.com/stretchr/testify/assert" 8 "net/http" 9 "net/http/httptest" 10 "net/url" 11 "testing" 12 "time" 13 ) 14 15 type subError struct { 16 err error 17 str string 18 } 19 20 func (err subError) Error() string { 21 return fmt.Sprintf("%s(%s)", err.str, err.err.Error()) 22 } 23 24 type subErrorPtr struct { 25 err *error 26 str string 27 } 28 29 func (err subErrorPtr) Error() string { 30 return fmt.Sprintf("%s(%s)", err.str, (*err.err).Error()) 31 } 32 33 func TestGetErrorInt(t *testing.T) { 34 assert := assert.New(t) 35 36 assert.Equal(nil, getError(5)) 37 38 } 39 func TestGetErrorString(t *testing.T) { 40 assert := assert.New(t) 41 42 assert.Equal(nil, getError("hi")) 43 } 44 func TestGetErrorNil(t *testing.T) { 45 assert := assert.New(t) 46 47 assert.Equal(nil, getError(nil)) 48 } 49 50 func TestGetErrorError(t *testing.T) { 51 assert := assert.New(t) 52 53 expected := errors.New("hi") 54 assert.Equal(expected, getError(expected)) 55 } 56 func TestGetErrorErrorPTR(t *testing.T) { 57 assert := assert.New(t) 58 59 expected := errors.New("hi") 60 assert.Equal(expected, getError(&expected)) 61 } 62 63 func TestGetErrorErrorComplex(t *testing.T) { 64 assert := assert.New(t) 65 type testA struct { 66 error 67 str string 68 } 69 expected := testA{errors.New("hi"), "bye"} 70 assert.Equal(expected, getError(expected)) 71 } 72 73 func TestGetErrorErrorComplexWithPointer(t *testing.T) { 74 assert := assert.New(t) 75 type testA struct { 76 error 77 str string 78 } 79 expected := testA{errors.New("hi"), "bye"} 80 assert.Equal(expected, getError(&expected)) 81 } 82 83 func TestGetErrorNoError(t *testing.T) { 84 assert := assert.New(t) 85 type testA struct { 86 str string 87 } 88 expected := testA{"bye"} 89 assert.Nil(getError(&expected)) 90 } 91 92 func TestFirstCauseCustomSubError(t *testing.T) { 93 assert := assert.New(t) 94 type testA struct { 95 error 96 str string 97 } 98 exectedErr := errors.New("testA") 99 test := testA{exectedErr, "cool"} 100 assert.Equal(exectedErr, FirstCause(subError{test, "neat"})) 101 } 102 103 func TestFirstCauseNil(t *testing.T) { 104 assert := assert.New(t) 105 106 assert.Nil(FirstCause(nil)) 107 } 108 109 func TestFirstCauseChainSubError(t *testing.T) { 110 assert := assert.New(t) 111 112 exectedErr := errors.New("expected error") 113 test := subError{ 114 subError{ 115 subError{ 116 subErrorPtr{&exectedErr, "cool"}, 117 "c", 118 }, 119 "b", 120 }, 121 "a", 122 } 123 assert.Equal(exectedErr, FirstCause(subError{test, "root"})) 124 } 125 126 func TestGetErrorSubError(t *testing.T) { 127 assert := assert.New(t) 128 129 expected := subError{errors.New("hi"), "bye"} 130 assert.Equal(expected, getError(&expected)) 131 } 132 133 func TestFirstCauseBasic(t *testing.T) { 134 assert := assert.New(t) 135 136 err := errors.New("my bad") 137 assert.Equal(err, FirstCause(err)) 138 } 139 140 func testFirstCauseHTTPHandler(t *testing.T, serverSleep time.Duration, contextDeadline time.Duration, timeout time.Duration, useDefer bool) { 141 assert := assert.New(t) 142 143 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 144 time.Sleep(serverSleep) 145 fmt.Fprintln(w, "Hello, client") 146 })) 147 defer ts.Close() 148 149 client := http.Client{Timeout: timeout} 150 req, err := http.NewRequest(http.MethodGet, ts.URL, nil) 151 assert.NoError(err) 152 153 ctx, cancel := context.WithTimeout(context.Background(), contextDeadline) 154 if useDefer { 155 defer cancel() 156 } else { 157 cancel() // cancel() is a hook to cancel the deadline 158 } 159 160 reqWithDeadline := req.WithContext(ctx) 161 162 _, clientErr := client.Do(reqWithDeadline) 163 164 if !assert.Error(clientErr) { 165 assert.FailNow("clientErr can not be nil to continue") 166 } 167 168 xerr := FirstCause(clientErr) 169 assert.Equal(clientErr.(*url.Error).Err, xerr) 170 } 171 172 func TestFirstCauseHTTP(t *testing.T) { 173 174 testData := []struct { 175 name string 176 serverSleep time.Duration 177 contextDeadline time.Duration 178 timeout time.Duration 179 useDefer bool 180 }{ 181 {"client-timeout", time.Second, 500 * time.Millisecond, time.Millisecond, true}, 182 {"context-cancel", time.Nanosecond, 500 * time.Millisecond, time.Millisecond, false}, 183 {"context-timeout", time.Second, time.Millisecond, 500 * time.Millisecond, true}, 184 } 185 186 for _, record := range testData { 187 t.Run(fmt.Sprintf("handle/%s", record.name), func(t *testing.T) { 188 testFirstCauseHTTPHandler(t, record.serverSleep, record.contextDeadline, record.timeout, record.useDefer) 189 }) 190 } 191 }