github.com/cloudwego/kitex@v0.9.0/pkg/kerrors/kerrors_test.go (about) 1 /* 2 * Copyright 2021 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package kerrors 18 19 import ( 20 "errors" 21 "fmt" 22 "io" 23 "os" 24 "runtime/debug" 25 "strings" 26 "testing" 27 28 "github.com/cloudwego/kitex/internal/test" 29 ) 30 31 func TestIsKitexError(t *testing.T) { 32 errs := []error{ 33 ErrInternalException, 34 ErrServiceDiscovery, 35 ErrGetConnection, 36 ErrLoadbalance, 37 ErrRPCTimeout, 38 ErrACL, 39 ErrCircuitBreak, 40 ErrRemoteOrNetwork, 41 ErrOverlimit, 42 ErrNotSupported, 43 ErrNoResolver, 44 ErrNoDestService, 45 ErrNoDestAddress, 46 ErrNoConnection, 47 ErrNoMoreInstance, 48 ErrConnOverLimit, 49 ErrQPSOverLimit, 50 } 51 for _, e := range errs { 52 test.Assert(t, IsKitexError(e)) 53 } 54 55 e := errors.New("any error") 56 test.Assert(t, !IsKitexError(e)) 57 58 e = ErrInternalException.WithCause(e) 59 test.Assert(t, IsKitexError(e)) 60 } 61 62 func TestIs(t *testing.T) { 63 any := errors.New("any error") 64 65 test.Assert(t, !errors.Is(any, ErrACL)) 66 67 var e error 68 e = ErrACL 69 test.Assert(t, errors.Is(e, ErrACL)) 70 71 e = ErrACL.WithCause(any) 72 test.Assert(t, errors.Is(e, ErrACL)) 73 test.Assert(t, errors.Is(e, any)) 74 } 75 76 func TestError(t *testing.T) { 77 basic := "basic" 78 extra := "extra" 79 be := &basicError{basic} 80 test.Assert(t, be.Error() == basic) 81 detailedMsg := appendErrMsg(basic, extra) 82 test.Assert(t, (&DetailedError{basic: be, extraMsg: extra}).Error() == detailedMsg) 83 } 84 85 func TestWithCause(t *testing.T) { 86 ae := errors.New("any error") 87 be := &basicError{"basic"} 88 de := be.WithCause(ae) 89 90 test.Assert(t, be.Error() == "basic") 91 test.Assert(t, strings.HasPrefix(de.Error(), be.Error())) 92 test.Assert(t, strings.HasSuffix(de.Error(), ae.Error())) 93 94 xe, ok := de.(interface{ ErrorType() error }) 95 test.Assert(t, ok) 96 test.Assert(t, xe.ErrorType() == be) 97 98 ye, ok := de.(interface{ Unwrap() error }) 99 test.Assert(t, ok) 100 test.Assert(t, ye.Unwrap() == ae) 101 } 102 103 func TestWithCauseAndStack(t *testing.T) { 104 ae := errors.New("any error") 105 be := &basicError{"basic"} 106 stack := string(debug.Stack()) 107 de := be.WithCauseAndStack(ae, stack) 108 109 test.Assert(t, be.Error() == "basic") 110 test.Assert(t, strings.HasPrefix(de.Error(), be.Error())) 111 test.Assert(t, strings.HasSuffix(de.Error(), ae.Error())) 112 113 xe, ok := de.(interface{ ErrorType() error }) 114 test.Assert(t, ok) 115 test.Assert(t, xe.ErrorType() == be) 116 117 ye, ok := de.(interface{ Unwrap() error }) 118 test.Assert(t, ok) 119 test.Assert(t, ye.Unwrap() == ae) 120 121 se, ok := de.(interface{ Stack() string }) 122 test.Assert(t, ok) 123 test.Assert(t, se.Stack() == stack) 124 } 125 126 type timeoutError struct{} 127 128 func (te *timeoutError) Error() string { return "timeout" } 129 func (te *timeoutError) Timeout() bool { return true } 130 131 func TestTimeout(t *testing.T) { 132 var ae, ke error 133 ae = errors.New("any error") 134 osCheck := func(err error) bool { 135 return os.IsTimeout(err) 136 } 137 138 ke = &basicError{"non-timeout"} 139 TimeoutCheckFunc = osCheck 140 test.Assert(t, !IsTimeoutError(ke)) 141 TimeoutCheckFunc = nil 142 test.Assert(t, !IsTimeoutError(ke)) 143 144 ke = ErrRPCTimeout 145 TimeoutCheckFunc = osCheck 146 test.Assert(t, IsTimeoutError(ke)) 147 TimeoutCheckFunc = nil 148 test.Assert(t, IsTimeoutError(ke)) 149 150 ke = ErrRPCTimeout.WithCause(ae) 151 TimeoutCheckFunc = osCheck 152 test.Assert(t, IsTimeoutError(ke)) 153 TimeoutCheckFunc = nil 154 test.Assert(t, IsTimeoutError(ke)) 155 156 ke = ErrOverlimit.WithCause(ae) 157 TimeoutCheckFunc = osCheck 158 test.Assert(t, !IsTimeoutError(ke)) 159 TimeoutCheckFunc = nil 160 test.Assert(t, !IsTimeoutError(ke)) 161 162 ae = &timeoutError{} 163 TimeoutCheckFunc = osCheck 164 test.Assert(t, IsTimeoutError(ae)) 165 TimeoutCheckFunc = nil 166 test.Assert(t, !IsTimeoutError(ae)) 167 168 ke = ErrOverlimit.WithCause(ae) 169 TimeoutCheckFunc = osCheck 170 test.Assert(t, IsTimeoutError(ke)) 171 TimeoutCheckFunc = nil 172 test.Assert(t, !IsTimeoutError(ke)) 173 } 174 175 func TestWithCause1(t *testing.T) { 176 ae := &basicError{"basic"} 177 be := ErrRPCTimeout.WithCause(ae) 178 if e2, ok := be.(*DetailedError); ok { 179 e2.WithExtraMsg("retry circuite break") 180 } 181 test.Assert(t, be.Error() == "rpc timeout[retry circuite break]: basic", be) 182 } 183 184 type _err struct { 185 error 186 } 187 188 // Format the error. 189 func (de *_err) Format(s fmt.State, verb rune) { 190 switch verb { 191 case 'v': 192 if s.Flag('+') { 193 _, _ = io.WriteString(s, "some message only when v+") 194 return 195 } 196 fallthrough 197 case 's', 'q': 198 _, _ = io.WriteString(s, de.Error()) 199 } 200 } 201 202 func TestFormat(t *testing.T) { 203 businessError := &_err{ 204 error: errors.New("some_business_error"), 205 } 206 basicErr := &basicError{ 207 message: "fake_msg", 208 } 209 err := basicErr.WithCause(businessError) 210 got := fmt.Sprintf("%+v", err) 211 test.Assert(t, got == "fake_msg: some message only when v+") 212 213 got = fmt.Sprintf("%v", err) 214 test.Assert(t, got == "fake_msg: some_business_error") 215 } 216 217 func BenchmarkWithCause3(b *testing.B) { 218 b.ReportAllocs() 219 b.ResetTimer() 220 for i := 0; i < b.N; i++ { 221 ae := &basicError{"basic"} 222 be := ErrRPCTimeout.WithCause(ae) 223 if e2, ok := be.(*DetailedError); ok { 224 e2.WithExtraMsg("测试") 225 } 226 } 227 }