github.com/xg0n/routine@v0.0.0-20240119033701-c364deb94aee/error_test.go (about) 1 package routine 2 3 import ( 4 "errors" 5 "strings" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 ) 10 11 func TestRuntimeError_Goid(t *testing.T) { 12 goid := Goid() 13 err := NewRuntimeError(nil) 14 assert.Equal(t, goid, err.Goid()) 15 task := GoWait(func(token CancelToken) { 16 assert.Equal(t, goid, err.Goid()) 17 assert.NotEqual(t, Goid(), err.Goid()) 18 }) 19 task.Get() 20 } 21 22 func TestRuntimeError_Gopc(t *testing.T) { 23 gopc := *getg().gopc 24 err := NewRuntimeError(nil) 25 assert.Equal(t, gopc, err.Gopc()) 26 task := GoWait(func(token CancelToken) { 27 assert.Equal(t, gopc, err.Gopc()) 28 assert.NotEqual(t, *getg().gopc, err.Gopc()) 29 }) 30 task.Get() 31 } 32 33 func TestRuntimeError_Message(t *testing.T) { 34 err := NewRuntimeError(nil) 35 assert.Equal(t, "", err.Message()) 36 37 err2 := NewRuntimeError("Hello") 38 assert.Equal(t, "Hello", err2.Message()) 39 40 err3 := NewRuntimeError(&person{Id: 1, Name: "Tim"}) 41 assert.Equal(t, "&{1 Tim}", err3.Message()) 42 } 43 44 func TestRuntimeError_StackTrace(t *testing.T) { 45 err := NewRuntimeError(nil) 46 stackTrace := err.StackTrace() 47 capturedStackTrace := captureStackTrace(0, 200) 48 for i := 1; i < len(stackTrace); i++ { 49 assert.Equal(t, capturedStackTrace[i], stackTrace[i]) 50 } 51 } 52 53 func TestRuntimeError_Panic_Panic(t *testing.T) { 54 defer func() { 55 cause := recover() 56 assert.NotNil(t, cause) 57 err := NewRuntimeError(cause) 58 lines := strings.Split(err.Error(), newLine) 59 assert.Equal(t, 6, len(lines)) 60 // 61 line := lines[0] 62 assert.Equal(t, "RuntimeError: 1", line) 63 // 64 line = lines[1] 65 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Panic_Panic.")) 66 assert.True(t, strings.HasSuffix(line, "error_test.go:74")) 67 // 68 line = lines[2] 69 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Panic_Panic()")) 70 assert.True(t, strings.HasSuffix(line, "error_test.go:77")) 71 }() 72 defer func() { 73 if cause := recover(); cause != nil { 74 panic(cause) 75 } 76 }() 77 panic(1) 78 } 79 80 func TestRuntimeError_Cause(t *testing.T) { 81 err := NewRuntimeError(nil) 82 assert.Nil(t, err.Cause()) 83 84 err2 := NewRuntimeError(errors.New("error")) 85 assert.Nil(t, err2.Cause()) 86 87 err3 := NewRuntimeError(&person{Id: 1, Name: "Tim"}) 88 assert.Nil(t, err3.Cause()) 89 90 err4 := NewRuntimeError(err) 91 assert.Same(t, err, err4.Cause()) 92 } 93 94 func TestRuntimeError_Error_EmptyMessage_NilError(t *testing.T) { 95 err := NewRuntimeErrorWithMessageCause("", nil) 96 lines := strings.Split(err.Error(), newLine) 97 assert.Equal(t, 5, len(lines)) 98 // 99 line := lines[0] 100 assert.Equal(t, "RuntimeError", line) 101 // 102 line = lines[1] 103 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Error_EmptyMessage_NilError() in ")) 104 assert.True(t, strings.HasSuffix(line, "error_test.go:95")) 105 // 106 line = lines[2] 107 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 108 // 109 line = lines[3] 110 assert.Equal(t, " --- End of error stack trace ---", line) 111 // 112 line = lines[4] 113 assert.True(t, strings.HasPrefix(line, " created by testing.(*T).Run() in ")) 114 } 115 116 func TestRuntimeError_Error_EmptyMessage_NormalError(t *testing.T) { 117 cause := NewRuntimeError("this is inner error") 118 err := NewRuntimeErrorWithMessageCause("", cause) 119 lines := strings.Split(err.Error(), newLine) 120 assert.Equal(t, 9, len(lines)) 121 // 122 line := lines[0] 123 assert.Equal(t, "RuntimeError", line) 124 // 125 line = lines[1] 126 assert.Equal(t, " ---> RuntimeError: this is inner error", line) 127 // 128 line = lines[2] 129 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Error_EmptyMessage_NormalError() in ")) 130 assert.True(t, strings.HasSuffix(line, "error_test.go:117")) 131 // 132 line = lines[3] 133 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 134 // 135 line = lines[4] 136 assert.Equal(t, " --- End of inner error stack trace ---", line) 137 // 138 line = lines[5] 139 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Error_EmptyMessage_NormalError() in ")) 140 assert.True(t, strings.HasSuffix(line, "error_test.go:118")) 141 // 142 line = lines[6] 143 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 144 // 145 line = lines[7] 146 assert.Equal(t, " --- End of error stack trace ---", line) 147 // 148 line = lines[8] 149 assert.True(t, strings.HasPrefix(line, " created by testing.(*T).Run() in ")) 150 } 151 152 func TestRuntimeError_Error_NormalMessage_NilError(t *testing.T) { 153 err := NewRuntimeErrorWithMessageCause("this is error message", nil) 154 lines := strings.Split(err.Error(), newLine) 155 assert.Equal(t, 5, len(lines)) 156 // 157 line := lines[0] 158 assert.Equal(t, "RuntimeError: this is error message", line) 159 // 160 line = lines[1] 161 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Error_NormalMessage_NilError() in ")) 162 assert.True(t, strings.HasSuffix(line, "error_test.go:153")) 163 // 164 line = lines[2] 165 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 166 // 167 line = lines[3] 168 assert.Equal(t, " --- End of error stack trace ---", line) 169 // 170 line = lines[4] 171 assert.True(t, strings.HasPrefix(line, " created by testing.(*T).Run() in ")) 172 } 173 174 func TestRuntimeError_Error_NormalMessage_NormalError(t *testing.T) { 175 cause := NewRuntimeError("this is inner error") 176 err := NewRuntimeErrorWithMessageCause("this is error message", cause) 177 lines := strings.Split(err.Error(), newLine) 178 assert.Equal(t, 9, len(lines)) 179 // 180 line := lines[0] 181 assert.Equal(t, "RuntimeError: this is error message", line) 182 // 183 line = lines[1] 184 assert.Equal(t, " ---> RuntimeError: this is inner error", line) 185 // 186 line = lines[2] 187 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Error_NormalMessage_NormalError() in ")) 188 assert.True(t, strings.HasSuffix(line, "error_test.go:175")) 189 // 190 line = lines[3] 191 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 192 // 193 line = lines[4] 194 assert.Equal(t, " --- End of inner error stack trace ---", line) 195 // 196 line = lines[5] 197 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Error_NormalMessage_NormalError() in ")) 198 assert.True(t, strings.HasSuffix(line, "error_test.go:176")) 199 // 200 line = lines[6] 201 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 202 // 203 line = lines[7] 204 assert.Equal(t, " --- End of error stack trace ---", line) 205 // 206 line = lines[8] 207 assert.True(t, strings.HasPrefix(line, " created by testing.(*T).Run() in ")) 208 } 209 210 func TestRuntimeError_Error_NilStackTrace(t *testing.T) { 211 cause := NewRuntimeError("this is inner error") 212 cause.(*runtimeError).stackTrace = nil 213 err := NewRuntimeErrorWithMessageCause("this is error message", cause) 214 err.(*runtimeError).stackTrace = nil 215 lines := strings.Split(err.Error(), newLine) 216 assert.Equal(t, 5, len(lines)) 217 // 218 line := lines[0] 219 assert.Equal(t, "RuntimeError: this is error message", line) 220 // 221 line = lines[1] 222 assert.Equal(t, " ---> RuntimeError: this is inner error", line) 223 // 224 line = lines[2] 225 assert.Equal(t, " --- End of inner error stack trace ---", line) 226 // 227 line = lines[3] 228 assert.Equal(t, " --- End of error stack trace ---", line) 229 // 230 line = lines[4] 231 assert.True(t, strings.HasPrefix(line, " created by testing.(*T).Run() in ")) 232 } 233 234 func TestRuntimeError_Error_MainGoid(t *testing.T) { 235 err := NewRuntimeErrorWithMessageCause("this is error message", nil) 236 err.(*runtimeError).goid = 1 237 lines := strings.Split(err.Error(), newLine) 238 assert.Equal(t, 3, len(lines)) 239 // 240 line := lines[0] 241 assert.Equal(t, "RuntimeError: this is error message", line) 242 // 243 line = lines[1] 244 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Error_MainGoid() in ")) 245 assert.True(t, strings.HasSuffix(line, "error_test.go:235")) 246 // 247 line = lines[2] 248 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 249 } 250 251 func TestRuntimeError_Error_ZeroGopc(t *testing.T) { 252 err := NewRuntimeErrorWithMessageCause("this is error message", nil) 253 err.(*runtimeError).gopc = 0 254 lines := strings.Split(err.Error(), newLine) 255 assert.Equal(t, 3, len(lines)) 256 // 257 line := lines[0] 258 assert.Equal(t, "RuntimeError: this is error message", line) 259 // 260 line = lines[1] 261 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestRuntimeError_Error_ZeroGopc() in ")) 262 assert.True(t, strings.HasSuffix(line, "error_test.go:252")) 263 // 264 line = lines[2] 265 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 266 } 267 268 func TestArgumentNilError_Goid(t *testing.T) { 269 goid := Goid() 270 err := NewArgumentNilError("number", nil) 271 assert.Equal(t, goid, err.Goid()) 272 task := GoWait(func(token CancelToken) { 273 assert.Equal(t, goid, err.Goid()) 274 assert.NotEqual(t, Goid(), err.Goid()) 275 }) 276 task.Get() 277 } 278 279 func TestArgumentNilError_Gopc(t *testing.T) { 280 gopc := *getg().gopc 281 err := NewArgumentNilError("number", nil) 282 assert.Equal(t, gopc, err.Gopc()) 283 task := GoWait(func(token CancelToken) { 284 assert.Equal(t, gopc, err.Gopc()) 285 assert.NotEqual(t, *getg().gopc, err.Gopc()) 286 }) 287 task.Get() 288 } 289 290 func TestArgumentNilError_Message(t *testing.T) { 291 err := NewArgumentNilError("", nil) 292 assert.Equal(t, "Value cannot be null.", err.Message()) 293 294 err2 := NewArgumentNilError("", "Hello") 295 assert.Equal(t, "Hello", err2.Message()) 296 297 err3 := NewArgumentNilError("number", nil) 298 assert.Equal(t, "Value cannot be null."+newLine+"Parameter name: number.", err3.Message()) 299 300 err4 := NewArgumentNilError("number", "Hello") 301 assert.Equal(t, "Hello"+newLine+"Parameter name: number.", err4.Message()) 302 } 303 304 func TestArgumentNilError_StackTrace(t *testing.T) { 305 err := NewArgumentNilError("", nil) 306 stackTrace := err.StackTrace() 307 capturedStackTrace := captureStackTrace(0, 200) 308 for i := 1; i < len(stackTrace); i++ { 309 assert.Equal(t, capturedStackTrace[i], stackTrace[i]) 310 } 311 } 312 313 func TestArgumentNilError_Panic_Panic(t *testing.T) { 314 defer func() { 315 cause := recover() 316 assert.NotNil(t, cause) 317 err := NewArgumentNilError("a", nil) 318 lines := strings.Split(err.Error(), newLine) 319 assert.Equal(t, 7, len(lines)) 320 // 321 line := lines[0] 322 assert.Equal(t, "ArgumentNilError: Value cannot be null.", line) 323 // 324 line = lines[1] 325 assert.Equal(t, "Parameter name: a.", line) 326 // 327 line = lines[2] 328 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestArgumentNilError_Panic_Panic.")) 329 assert.True(t, strings.HasSuffix(line, "error_test.go:337")) 330 // 331 line = lines[3] 332 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestArgumentNilError_Panic_Panic()")) 333 assert.True(t, strings.HasSuffix(line, "error_test.go:341")) 334 }() 335 defer func() { 336 if cause := recover(); cause != nil { 337 panic(cause) 338 } 339 }() 340 var a any 341 _ = a.(string) 342 } 343 344 func TestArgumentNilError_Cause(t *testing.T) { 345 err := NewArgumentNilError("", nil) 346 assert.Nil(t, err.Cause()) 347 348 err2 := NewArgumentNilError("", errors.New("error")) 349 assert.Nil(t, err2.Cause()) 350 351 err3 := NewArgumentNilError("", &person{Id: 1, Name: "Tim"}) 352 assert.Nil(t, err3.Cause()) 353 354 err4 := NewArgumentNilError("", err) 355 assert.Same(t, err, err4.Cause()) 356 } 357 358 func TestArgumentNilError_Error(t *testing.T) { 359 cause := NewRuntimeError("this is inner error") 360 err := NewArgumentNilError("number", cause) 361 lines := strings.Split(err.Error(), newLine) 362 assert.Equal(t, 10, len(lines)) 363 // 364 line := lines[0] 365 assert.Equal(t, "ArgumentNilError: Value cannot be null.", line) 366 // 367 line = lines[1] 368 assert.Equal(t, "Parameter name: number.", line) 369 // 370 line = lines[2] 371 assert.Equal(t, " ---> RuntimeError: this is inner error", line) 372 // 373 line = lines[3] 374 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestArgumentNilError_Error() in ")) 375 assert.True(t, strings.HasSuffix(line, "error_test.go:359")) 376 // 377 line = lines[4] 378 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 379 // 380 line = lines[5] 381 assert.Equal(t, " --- End of inner error stack trace ---", line) 382 // 383 line = lines[6] 384 assert.True(t, strings.HasPrefix(line, " at github.com/xg0n/routine.TestArgumentNilError_Error() in ")) 385 assert.True(t, strings.HasSuffix(line, "error_test.go:360")) 386 // 387 line = lines[7] 388 assert.True(t, strings.HasPrefix(line, " at testing.tRunner() in ")) 389 // 390 line = lines[8] 391 assert.Equal(t, " --- End of error stack trace ---", line) 392 // 393 line = lines[9] 394 assert.True(t, strings.HasPrefix(line, " created by testing.(*T).Run() in ")) 395 } 396 397 func TestArgumentNilError_ParamName(t *testing.T) { 398 err := NewArgumentNilError("", nil) 399 assert.Equal(t, "", err.ParamName()) 400 401 err2 := NewArgumentNilError("number", nil) 402 assert.Equal(t, "number", err2.ParamName()) 403 } 404 405 type ArgumentNilError struct { 406 goid int64 407 gopc uintptr 408 message string 409 stackTrace []uintptr 410 cause RuntimeError 411 paramName string 412 } 413 414 func (ae *ArgumentNilError) Goid() int64 { 415 return ae.goid 416 } 417 418 func (ae *ArgumentNilError) Gopc() uintptr { 419 return ae.gopc 420 } 421 422 func (ae *ArgumentNilError) Message() string { 423 builder := &strings.Builder{} 424 if len(ae.message) == 0 { 425 builder.WriteString("Value cannot be null.") 426 } else { 427 builder.WriteString(ae.message) 428 } 429 if len(ae.paramName) != 0 { 430 builder.WriteString(newLine) 431 builder.WriteString("Parameter name: ") 432 builder.WriteString(ae.paramName) 433 builder.WriteString(".") 434 } 435 return builder.String() 436 } 437 438 func (ae *ArgumentNilError) StackTrace() []uintptr { 439 return ae.stackTrace 440 } 441 442 func (ae *ArgumentNilError) Cause() RuntimeError { 443 return ae.cause 444 } 445 446 func (ae *ArgumentNilError) Error() string { 447 return runtimeErrorError(ae) 448 } 449 450 func (ae *ArgumentNilError) ParamName() string { 451 return ae.paramName 452 } 453 454 func NewArgumentNilError(paramName string, cause any) *ArgumentNilError { 455 goid, gopc, msg, stackTrace, innerErr := runtimeErrorNew(cause) 456 return &ArgumentNilError{goid: goid, gopc: gopc, message: msg, paramName: paramName, stackTrace: stackTrace, cause: innerErr} 457 }