github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/terror/terror_test.go (about) 1 // Copyright 2019 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package terror 15 16 import ( 17 "errors" 18 "fmt" 19 "strings" 20 "testing" 21 22 perrors "github.com/pingcap/errors" 23 "github.com/stretchr/testify/require" 24 ) 25 26 func TestTError(t *testing.T) { 27 t.Parallel() 28 29 var ( 30 code = codeDBBadConn 31 class = ClassDatabase 32 scope = ScopeUpstream 33 level = LevelMedium 34 message = "bad connection" 35 workaround = "please check your network connection" 36 messageArgs = "message with args: %s" 37 commonErr = errors.New("common error") 38 errFormat = errBaseFormat + ", Message: %s, Workaround: %s" 39 errFormatWithArg = errBaseFormat + ", Message: %s: %s, Workaround: %s" 40 errFormatWithRawCause = errBaseFormat + ", Message: %s, RawCause: %s, Workaround: %s" 41 ) 42 43 require.Equal(t, errClass2Str[ClassDatabase], ClassDatabase.String()) 44 require.Equal(t, "unknown error class: 10000", ErrClass(10000).String()) 45 46 require.Equal(t, errScope2Str[ScopeUpstream], ScopeUpstream.String()) 47 require.Equal(t, "unknown error scope: 10000", ErrScope(10000).String()) 48 49 require.Equal(t, errLevel2Str[LevelHigh], LevelHigh.String()) 50 require.Equal(t, "unknown error level: 10000", ErrLevel(10000).String()) 51 52 // test Error basic API 53 err := New(code, class, scope, level, message, workaround) 54 require.Equal(t, code, err.code) 55 require.Equal(t, class, err.Class()) 56 require.Equal(t, scope, err.scope) 57 require.Equal(t, level, err.level) 58 require.Equal(t, workaround, err.workaround) 59 require.Equal(t, fmt.Sprintf(errFormat, code, class, scope, level, err.getMsg(), workaround), err.Error()) 60 61 setMsgErr := err.SetMessage(messageArgs) 62 require.Equal(t, messageArgs, setMsgErr.getMsg()) 63 setMsgErr.args = []interface{}{"1062"} 64 require.Equal(t, fmt.Sprintf(messageArgs, setMsgErr.args...), setMsgErr.getMsg()) 65 66 // test Error Generate/Generatef 67 err2 := err.Generate("1063") 68 require.True(t, err.Equal(err2)) 69 require.Equal(t, fmt.Sprintf(errFormat, code, class, scope, level, "bad connection%!(EXTRA string=1063)", workaround), err2.Error()) 70 71 err3 := err.Generatef("new message format: %s", "1064") 72 require.True(t, err.Equal(err3)) 73 require.Equal(t, fmt.Sprintf(errFormatWithArg, code, class, scope, level, "new message format", "1064", workaround), err3.Error()) 74 75 // test Error Delegate 76 require.Nil(t, err.Delegate(nil, "nil")) 77 err4 := err.Delegate(commonErr) 78 require.True(t, err.Equal(err4)) 79 require.Equal(t, fmt.Sprintf(errFormatWithRawCause, code, class, scope, level, message, commonErr, workaround), err4.Error()) 80 require.Equal(t, commonErr, perrors.Cause(err4)) 81 82 argsErr := New(code, class, scope, level, messageArgs, workaround) 83 err4 = argsErr.Delegate(commonErr, "1065") 84 require.True(t, argsErr.Equal(err4)) 85 require.Equal(t, fmt.Sprintf(errFormatWithRawCause, code, class, scope, level, "message with args: 1065", commonErr, workaround), err4.Error()) 86 87 // test Error AnnotateDelegate 88 require.Nil(t, err.AnnotateDelegate(nil, "message", "args")) 89 err5 := err.AnnotateDelegate(commonErr, "annotate delegate error: %d", 1066) 90 require.True(t, err.Equal(err5)) 91 require.Equal(t, fmt.Sprintf(errFormatWithRawCause, code, class, scope, level, "annotate delegate error: 1066", commonErr, workaround), err5.Error()) 92 93 // test Error Annotate 94 oldMsg := err.getMsg() 95 err6 := Annotate(err, "annotate error") 96 require.True(t, err.Equal(err6)) 97 require.Equal(t, fmt.Sprintf(errFormatWithArg, code, class, scope, level, "annotate error", oldMsg, workaround), err6.Error()) 98 99 require.Nil(t, Annotate(nil, "")) 100 annotateErr := Annotate(commonErr, "annotate") 101 _, ok := annotateErr.(*Error) 102 require.False(t, ok) 103 require.Equal(t, commonErr, perrors.Cause(annotateErr)) 104 105 // test Error Annotatef 106 oldMsg = err.getMsg() 107 err7 := Annotatef(err, "annotatef error %s", "1067") 108 require.True(t, err.Equal(err7)) 109 require.Equal(t, fmt.Sprintf(errFormatWithArg, code, class, scope, level, "annotatef error 1067", oldMsg, workaround), err7.Error()) 110 111 require.Nil(t, Annotatef(nil, "")) 112 annotateErr = Annotatef(commonErr, "annotatef %s", "1068") 113 _, ok = annotateErr.(*Error) 114 require.False(t, ok) 115 require.Equal(t, commonErr, perrors.Cause(annotateErr)) 116 117 // test format 118 require.Equal(t, fmt.Sprintf("%q", err.Error()), fmt.Sprintf("%q", err)) 119 // err has no stack trace 120 require.Equal(t, err.Error(), fmt.Sprintf("%+v", err)) 121 require.Equal(t, err.Error(), fmt.Sprintf("%v", err)) 122 123 // err2 has stack trace 124 verbose := strings.Split(fmt.Sprintf("%+v", err2), "\n") 125 require.True(t, len(verbose) > 5) 126 require.Equal(t, err2.Error(), verbose[0]) 127 require.Regexp(t, ".*\\(\\*Error\\)\\.Generate", verbose[1]) 128 require.Equal(t, err2.Error(), fmt.Sprintf("%v", err2)) 129 130 // test Message function 131 require.Equal(t, "", Message(nil)) 132 require.Equal(t, commonErr.Error(), Message(commonErr)) 133 require.Equal(t, err.getMsg(), Message(err)) 134 } 135 136 func TestTErrorStackTrace(t *testing.T) { 137 t.Parallel() 138 139 err := ErrDBUnExpect 140 141 testCases := []struct { 142 fn string 143 message string 144 args []interface{} 145 stackFingerprint string 146 }{ 147 {"new", "new error", nil, ".*\\(\\*Error\\)\\.New"}, 148 {"generate", "", []interface{}{"parma1"}, ".*\\(\\*Error\\)\\.Generate"}, 149 {"generatef", "generatef error %s %d", []interface{}{"param1", 12}, ".*\\(\\*Error\\)\\.Generatef"}, 150 } 151 152 for _, tc := range testCases { 153 var err2 error 154 switch tc.fn { 155 case "new": 156 err2 = err.New(tc.message) 157 case "generate": 158 err2 = err.Generate(tc.args...) 159 case "generatef": 160 err2 = err.Generatef(tc.message, tc.args...) 161 } 162 verbose := strings.Split(fmt.Sprintf("%+v", err2), "\n") 163 require.True(t, len(verbose) > 5) 164 require.Equal(t, err2.Error(), verbose[0]) 165 require.Regexp(t, tc.stackFingerprint, verbose[1]) 166 } 167 } 168 169 func TestTerrorWithOperate(t *testing.T) { 170 t.Parallel() 171 172 var ( 173 code = codeDBBadConn 174 class = ClassDatabase 175 scope = ScopeUpstream 176 level = LevelMedium 177 message = "message with args: %s" 178 workaround = "please check your connection" 179 err = New(code, class, scope, level, message, workaround) 180 arg = "arg" 181 commonErr = perrors.New("common error") 182 errFormatWithArg = errBaseFormat + ", Message: %s: %s, Workaround: %s" 183 ) 184 185 // test WithScope 186 newScope := ScopeDownstream 187 require.Nil(t, WithScope(nil, newScope)) 188 require.Equal(t, fmt.Sprintf("error scope: %s: common error", newScope), WithScope(commonErr, newScope).Error()) 189 err1 := WithScope(err.Generate(arg), newScope) 190 require.True(t, err.Equal(err1)) 191 require.Equal(t, fmt.Sprintf(errFormatWithArg, code, class, newScope, level, "message with args", arg, workaround), err1.Error()) 192 193 // test WithClass 194 newClass := ClassFunctional 195 require.Nil(t, WithClass(nil, newClass)) 196 require.Equal(t, fmt.Sprintf("error class: %s: common error", newClass), WithClass(commonErr, newClass).Error()) 197 err2 := WithClass(err.Generate(arg), newClass) 198 require.True(t, err.Equal(err2)) 199 require.Equal(t, fmt.Sprintf(errFormatWithArg, code, newClass, scope, level, "message with args", arg, workaround), err2.Error()) 200 } 201 202 func TestTerrorCodeMap(t *testing.T) { 203 t.Parallel() 204 205 err, ok := ErrorFromCode(codeDBDriverError) 206 require.True(t, ok) 207 require.True(t, ErrDBDriverError.Equal(err)) 208 209 _, ok = ErrorFromCode(1000) 210 require.False(t, ok) 211 }