assertions.go (60730B)
1 package assert 2 3 import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "math" 10 "os" 11 "reflect" 12 "regexp" 13 "runtime" 14 "runtime/debug" 15 "strings" 16 "time" 17 "unicode" 18 "unicode/utf8" 19 20 "github.com/davecgh/go-spew/spew" 21 "github.com/pmezard/go-difflib/difflib" 22 "gopkg.in/yaml.v3" 23 ) 24 25 //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" 26 27 // TestingT is an interface wrapper around *testing.T 28 type TestingT interface { 29 Errorf(format string, args ...interface{}) 30 } 31 32 // ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful 33 // for table driven tests. 34 type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool 35 36 // ValueAssertionFunc is a common function prototype when validating a single value. Can be useful 37 // for table driven tests. 38 type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool 39 40 // BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful 41 // for table driven tests. 42 type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool 43 44 // ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful 45 // for table driven tests. 46 type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool 47 48 // Comparison is a custom function that returns true on success and false on failure 49 type Comparison func() (success bool) 50 51 /* 52 Helper functions 53 */ 54 55 // ObjectsAreEqual determines if two objects are considered equal. 56 // 57 // This function does no assertion of any kind. 58 func ObjectsAreEqual(expected, actual interface{}) bool { 59 if expected == nil || actual == nil { 60 return expected == actual 61 } 62 63 exp, ok := expected.([]byte) 64 if !ok { 65 return reflect.DeepEqual(expected, actual) 66 } 67 68 act, ok := actual.([]byte) 69 if !ok { 70 return false 71 } 72 if exp == nil || act == nil { 73 return exp == nil && act == nil 74 } 75 return bytes.Equal(exp, act) 76 } 77 78 // copyExportedFields iterates downward through nested data structures and creates a copy 79 // that only contains the exported struct fields. 80 func copyExportedFields(expected interface{}) interface{} { 81 if isNil(expected) { 82 return expected 83 } 84 85 expectedType := reflect.TypeOf(expected) 86 expectedKind := expectedType.Kind() 87 expectedValue := reflect.ValueOf(expected) 88 89 switch expectedKind { 90 case reflect.Struct: 91 result := reflect.New(expectedType).Elem() 92 for i := 0; i < expectedType.NumField(); i++ { 93 field := expectedType.Field(i) 94 isExported := field.IsExported() 95 if isExported { 96 fieldValue := expectedValue.Field(i) 97 if isNil(fieldValue) || isNil(fieldValue.Interface()) { 98 continue 99 } 100 newValue := copyExportedFields(fieldValue.Interface()) 101 result.Field(i).Set(reflect.ValueOf(newValue)) 102 } 103 } 104 return result.Interface() 105 106 case reflect.Ptr: 107 result := reflect.New(expectedType.Elem()) 108 unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface()) 109 result.Elem().Set(reflect.ValueOf(unexportedRemoved)) 110 return result.Interface() 111 112 case reflect.Array, reflect.Slice: 113 var result reflect.Value 114 if expectedKind == reflect.Array { 115 result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() 116 } else { 117 result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) 118 } 119 for i := 0; i < expectedValue.Len(); i++ { 120 index := expectedValue.Index(i) 121 if isNil(index) { 122 continue 123 } 124 unexportedRemoved := copyExportedFields(index.Interface()) 125 result.Index(i).Set(reflect.ValueOf(unexportedRemoved)) 126 } 127 return result.Interface() 128 129 case reflect.Map: 130 result := reflect.MakeMap(expectedType) 131 for _, k := range expectedValue.MapKeys() { 132 index := expectedValue.MapIndex(k) 133 unexportedRemoved := copyExportedFields(index.Interface()) 134 result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved)) 135 } 136 return result.Interface() 137 138 default: 139 return expected 140 } 141 } 142 143 // ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are 144 // considered equal. This comparison of only exported fields is applied recursively to nested data 145 // structures. 146 // 147 // This function does no assertion of any kind. 148 // 149 // Deprecated: Use [EqualExportedValues] instead. 150 func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { 151 expectedCleaned := copyExportedFields(expected) 152 actualCleaned := copyExportedFields(actual) 153 return ObjectsAreEqualValues(expectedCleaned, actualCleaned) 154 } 155 156 // ObjectsAreEqualValues gets whether two objects are equal, or if their 157 // values are equal. 158 func ObjectsAreEqualValues(expected, actual interface{}) bool { 159 if ObjectsAreEqual(expected, actual) { 160 return true 161 } 162 163 expectedValue := reflect.ValueOf(expected) 164 actualValue := reflect.ValueOf(actual) 165 if !expectedValue.IsValid() || !actualValue.IsValid() { 166 return false 167 } 168 169 expectedType := expectedValue.Type() 170 actualType := actualValue.Type() 171 if !expectedType.ConvertibleTo(actualType) { 172 return false 173 } 174 175 if !isNumericType(expectedType) || !isNumericType(actualType) { 176 // Attempt comparison after type conversion 177 return reflect.DeepEqual( 178 expectedValue.Convert(actualType).Interface(), actual, 179 ) 180 } 181 182 // If BOTH values are numeric, there are chances of false positives due 183 // to overflow or underflow. So, we need to make sure to always convert 184 // the smaller type to a larger type before comparing. 185 if expectedType.Size() >= actualType.Size() { 186 return actualValue.Convert(expectedType).Interface() == expected 187 } 188 189 return expectedValue.Convert(actualType).Interface() == actual 190 } 191 192 // isNumericType returns true if the type is one of: 193 // int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, 194 // float32, float64, complex64, complex128 195 func isNumericType(t reflect.Type) bool { 196 return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128 197 } 198 199 /* CallerInfo is necessary because the assert functions use the testing object 200 internally, causing it to print the file:line of the assert method, rather than where 201 the problem actually occurred in calling code.*/ 202 203 // CallerInfo returns an array of strings containing the file and line number 204 // of each stack frame leading from the current test to the assert call that 205 // failed. 206 func CallerInfo() []string { 207 208 var pc uintptr 209 var ok bool 210 var file string 211 var line int 212 var name string 213 214 callers := []string{} 215 for i := 0; ; i++ { 216 pc, file, line, ok = runtime.Caller(i) 217 if !ok { 218 // The breaks below failed to terminate the loop, and we ran off the 219 // end of the call stack. 220 break 221 } 222 223 // This is a huge edge case, but it will panic if this is the case, see #180 224 if file == "<autogenerated>" { 225 break 226 } 227 228 f := runtime.FuncForPC(pc) 229 if f == nil { 230 break 231 } 232 name = f.Name() 233 234 // testing.tRunner is the standard library function that calls 235 // tests. Subtests are called directly by tRunner, without going through 236 // the Test/Benchmark/Example function that contains the t.Run calls, so 237 // with subtests we should break when we hit tRunner, without adding it 238 // to the list of callers. 239 if name == "testing.tRunner" { 240 break 241 } 242 243 parts := strings.Split(file, "/") 244 if len(parts) > 1 { 245 filename := parts[len(parts)-1] 246 dir := parts[len(parts)-2] 247 if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" { 248 callers = append(callers, fmt.Sprintf("%s:%d", file, line)) 249 } 250 } 251 252 // Drop the package 253 segments := strings.Split(name, ".") 254 name = segments[len(segments)-1] 255 if isTest(name, "Test") || 256 isTest(name, "Benchmark") || 257 isTest(name, "Example") { 258 break 259 } 260 } 261 262 return callers 263 } 264 265 // Stolen from the `go test` tool. 266 // isTest tells whether name looks like a test (or benchmark, according to prefix). 267 // It is a Test (say) if there is a character after Test that is not a lower-case letter. 268 // We don't want TesticularCancer. 269 func isTest(name, prefix string) bool { 270 if !strings.HasPrefix(name, prefix) { 271 return false 272 } 273 if len(name) == len(prefix) { // "Test" is ok 274 return true 275 } 276 r, _ := utf8.DecodeRuneInString(name[len(prefix):]) 277 return !unicode.IsLower(r) 278 } 279 280 func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { 281 if len(msgAndArgs) == 0 || msgAndArgs == nil { 282 return "" 283 } 284 if len(msgAndArgs) == 1 { 285 msg := msgAndArgs[0] 286 if msgAsStr, ok := msg.(string); ok { 287 return msgAsStr 288 } 289 return fmt.Sprintf("%+v", msg) 290 } 291 if len(msgAndArgs) > 1 { 292 return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) 293 } 294 return "" 295 } 296 297 // Aligns the provided message so that all lines after the first line start at the same location as the first line. 298 // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). 299 // The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the 300 // basis on which the alignment occurs). 301 func indentMessageLines(message string, longestLabelLen int) string { 302 outBuf := new(bytes.Buffer) 303 304 for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { 305 // no need to align first line because it starts at the correct location (after the label) 306 if i != 0 { 307 // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab 308 outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") 309 } 310 outBuf.WriteString(scanner.Text()) 311 } 312 313 return outBuf.String() 314 } 315 316 type failNower interface { 317 FailNow() 318 } 319 320 // FailNow fails test 321 func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { 322 if h, ok := t.(tHelper); ok { 323 h.Helper() 324 } 325 Fail(t, failureMessage, msgAndArgs...) 326 327 // We cannot extend TestingT with FailNow() and 328 // maintain backwards compatibility, so we fallback 329 // to panicking when FailNow is not available in 330 // TestingT. 331 // See issue #263 332 333 if t, ok := t.(failNower); ok { 334 t.FailNow() 335 } else { 336 panic("test failed and t is missing `FailNow()`") 337 } 338 return false 339 } 340 341 // Fail reports a failure through 342 func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { 343 if h, ok := t.(tHelper); ok { 344 h.Helper() 345 } 346 content := []labeledContent{ 347 {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, 348 {"Error", failureMessage}, 349 } 350 351 // Add test name if the Go version supports it 352 if n, ok := t.(interface { 353 Name() string 354 }); ok { 355 content = append(content, labeledContent{"Test", n.Name()}) 356 } 357 358 message := messageFromMsgAndArgs(msgAndArgs...) 359 if len(message) > 0 { 360 content = append(content, labeledContent{"Messages", message}) 361 } 362 363 t.Errorf("\n%s", ""+labeledOutput(content...)) 364 365 return false 366 } 367 368 type labeledContent struct { 369 label string 370 content string 371 } 372 373 // labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: 374 // 375 // \t{{label}}:{{align_spaces}}\t{{content}}\n 376 // 377 // The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. 378 // If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this 379 // alignment is achieved, "\t{{content}}\n" is added for the output. 380 // 381 // If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. 382 func labeledOutput(content ...labeledContent) string { 383 longestLabel := 0 384 for _, v := range content { 385 if len(v.label) > longestLabel { 386 longestLabel = len(v.label) 387 } 388 } 389 var output string 390 for _, v := range content { 391 output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" 392 } 393 return output 394 } 395 396 // Implements asserts that an object is implemented by the specified interface. 397 // 398 // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) 399 func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { 400 if h, ok := t.(tHelper); ok { 401 h.Helper() 402 } 403 interfaceType := reflect.TypeOf(interfaceObject).Elem() 404 405 if object == nil { 406 return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) 407 } 408 if !reflect.TypeOf(object).Implements(interfaceType) { 409 return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) 410 } 411 412 return true 413 } 414 415 // NotImplements asserts that an object does not implement the specified interface. 416 // 417 // assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) 418 func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { 419 if h, ok := t.(tHelper); ok { 420 h.Helper() 421 } 422 interfaceType := reflect.TypeOf(interfaceObject).Elem() 423 424 if object == nil { 425 return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...) 426 } 427 if reflect.TypeOf(object).Implements(interfaceType) { 428 return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...) 429 } 430 431 return true 432 } 433 434 // IsType asserts that the specified objects are of the same type. 435 func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { 436 if h, ok := t.(tHelper); ok { 437 h.Helper() 438 } 439 440 if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { 441 return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) 442 } 443 444 return true 445 } 446 447 // Equal asserts that two objects are equal. 448 // 449 // assert.Equal(t, 123, 123) 450 // 451 // Pointer variable equality is determined based on the equality of the 452 // referenced values (as opposed to the memory addresses). Function equality 453 // cannot be determined and will always fail. 454 func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 455 if h, ok := t.(tHelper); ok { 456 h.Helper() 457 } 458 if err := validateEqualArgs(expected, actual); err != nil { 459 return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", 460 expected, actual, err), msgAndArgs...) 461 } 462 463 if !ObjectsAreEqual(expected, actual) { 464 diff := diff(expected, actual) 465 expected, actual = formatUnequalValues(expected, actual) 466 return Fail(t, fmt.Sprintf("Not equal: \n"+ 467 "expected: %s\n"+ 468 "actual : %s%s", expected, actual, diff), msgAndArgs...) 469 } 470 471 return true 472 473 } 474 475 // validateEqualArgs checks whether provided arguments can be safely used in the 476 // Equal/NotEqual functions. 477 func validateEqualArgs(expected, actual interface{}) error { 478 if expected == nil && actual == nil { 479 return nil 480 } 481 482 if isFunction(expected) || isFunction(actual) { 483 return errors.New("cannot take func type as argument") 484 } 485 return nil 486 } 487 488 // Same asserts that two pointers reference the same object. 489 // 490 // assert.Same(t, ptr1, ptr2) 491 // 492 // Both arguments must be pointer variables. Pointer variable sameness is 493 // determined based on the equality of both type and value. 494 func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 495 if h, ok := t.(tHelper); ok { 496 h.Helper() 497 } 498 499 if !samePointers(expected, actual) { 500 return Fail(t, fmt.Sprintf("Not same: \n"+ 501 "expected: %p %#v\n"+ 502 "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...) 503 } 504 505 return true 506 } 507 508 // NotSame asserts that two pointers do not reference the same object. 509 // 510 // assert.NotSame(t, ptr1, ptr2) 511 // 512 // Both arguments must be pointer variables. Pointer variable sameness is 513 // determined based on the equality of both type and value. 514 func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 515 if h, ok := t.(tHelper); ok { 516 h.Helper() 517 } 518 519 if samePointers(expected, actual) { 520 return Fail(t, fmt.Sprintf( 521 "Expected and actual point to the same object: %p %#v", 522 expected, expected), msgAndArgs...) 523 } 524 return true 525 } 526 527 // samePointers compares two generic interface objects and returns whether 528 // they point to the same object 529 func samePointers(first, second interface{}) bool { 530 firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second) 531 if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr { 532 return false 533 } 534 535 firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second) 536 if firstType != secondType { 537 return false 538 } 539 540 // compare pointer addresses 541 return first == second 542 } 543 544 // formatUnequalValues takes two values of arbitrary types and returns string 545 // representations appropriate to be presented to the user. 546 // 547 // If the values are not of like type, the returned strings will be prefixed 548 // with the type name, and the value will be enclosed in parentheses similar 549 // to a type conversion in the Go grammar. 550 func formatUnequalValues(expected, actual interface{}) (e string, a string) { 551 if reflect.TypeOf(expected) != reflect.TypeOf(actual) { 552 return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)), 553 fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual)) 554 } 555 switch expected.(type) { 556 case time.Duration: 557 return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual) 558 } 559 return truncatingFormat(expected), truncatingFormat(actual) 560 } 561 562 // truncatingFormat formats the data and truncates it if it's too long. 563 // 564 // This helps keep formatted error messages lines from exceeding the 565 // bufio.MaxScanTokenSize max line length that the go testing framework imposes. 566 func truncatingFormat(data interface{}) string { 567 value := fmt.Sprintf("%#v", data) 568 max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed. 569 if len(value) > max { 570 value = value[0:max] + "<... truncated>" 571 } 572 return value 573 } 574 575 // EqualValues asserts that two objects are equal or convertible to the same types 576 // and equal. 577 // 578 // assert.EqualValues(t, uint32(123), int32(123)) 579 func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 580 if h, ok := t.(tHelper); ok { 581 h.Helper() 582 } 583 584 if !ObjectsAreEqualValues(expected, actual) { 585 diff := diff(expected, actual) 586 expected, actual = formatUnequalValues(expected, actual) 587 return Fail(t, fmt.Sprintf("Not equal: \n"+ 588 "expected: %s\n"+ 589 "actual : %s%s", expected, actual, diff), msgAndArgs...) 590 } 591 592 return true 593 594 } 595 596 // EqualExportedValues asserts that the types of two objects are equal and their public 597 // fields are also equal. This is useful for comparing structs that have private fields 598 // that could potentially differ. 599 // 600 // type S struct { 601 // Exported int 602 // notExported int 603 // } 604 // assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true 605 // assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false 606 func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 607 if h, ok := t.(tHelper); ok { 608 h.Helper() 609 } 610 611 aType := reflect.TypeOf(expected) 612 bType := reflect.TypeOf(actual) 613 614 if aType != bType { 615 return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) 616 } 617 618 if aType.Kind() == reflect.Ptr { 619 aType = aType.Elem() 620 } 621 if bType.Kind() == reflect.Ptr { 622 bType = bType.Elem() 623 } 624 625 if aType.Kind() != reflect.Struct { 626 return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) 627 } 628 629 if bType.Kind() != reflect.Struct { 630 return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) 631 } 632 633 expected = copyExportedFields(expected) 634 actual = copyExportedFields(actual) 635 636 if !ObjectsAreEqualValues(expected, actual) { 637 diff := diff(expected, actual) 638 expected, actual = formatUnequalValues(expected, actual) 639 return Fail(t, fmt.Sprintf("Not equal (comparing only exported fields): \n"+ 640 "expected: %s\n"+ 641 "actual : %s%s", expected, actual, diff), msgAndArgs...) 642 } 643 644 return true 645 } 646 647 // Exactly asserts that two objects are equal in value and type. 648 // 649 // assert.Exactly(t, int32(123), int64(123)) 650 func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 651 if h, ok := t.(tHelper); ok { 652 h.Helper() 653 } 654 655 aType := reflect.TypeOf(expected) 656 bType := reflect.TypeOf(actual) 657 658 if aType != bType { 659 return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) 660 } 661 662 return Equal(t, expected, actual, msgAndArgs...) 663 664 } 665 666 // NotNil asserts that the specified object is not nil. 667 // 668 // assert.NotNil(t, err) 669 func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 670 if !isNil(object) { 671 return true 672 } 673 if h, ok := t.(tHelper); ok { 674 h.Helper() 675 } 676 return Fail(t, "Expected value not to be nil.", msgAndArgs...) 677 } 678 679 // isNil checks if a specified object is nil or not, without Failing. 680 func isNil(object interface{}) bool { 681 if object == nil { 682 return true 683 } 684 685 value := reflect.ValueOf(object) 686 switch value.Kind() { 687 case 688 reflect.Chan, reflect.Func, 689 reflect.Interface, reflect.Map, 690 reflect.Ptr, reflect.Slice, reflect.UnsafePointer: 691 692 return value.IsNil() 693 } 694 695 return false 696 } 697 698 // Nil asserts that the specified object is nil. 699 // 700 // assert.Nil(t, err) 701 func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 702 if isNil(object) { 703 return true 704 } 705 if h, ok := t.(tHelper); ok { 706 h.Helper() 707 } 708 return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) 709 } 710 711 // isEmpty gets whether the specified object is considered empty or not. 712 func isEmpty(object interface{}) bool { 713 714 // get nil case out of the way 715 if object == nil { 716 return true 717 } 718 719 objValue := reflect.ValueOf(object) 720 721 switch objValue.Kind() { 722 // collection types are empty when they have no element 723 case reflect.Chan, reflect.Map, reflect.Slice: 724 return objValue.Len() == 0 725 // pointers are empty if nil or if the value they point to is empty 726 case reflect.Ptr: 727 if objValue.IsNil() { 728 return true 729 } 730 deref := objValue.Elem().Interface() 731 return isEmpty(deref) 732 // for all other types, compare against the zero value 733 // array types are empty when they match their zero-initialized state 734 default: 735 zero := reflect.Zero(objValue.Type()) 736 return reflect.DeepEqual(object, zero.Interface()) 737 } 738 } 739 740 // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either 741 // a slice or a channel with len == 0. 742 // 743 // assert.Empty(t, obj) 744 func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 745 pass := isEmpty(object) 746 if !pass { 747 if h, ok := t.(tHelper); ok { 748 h.Helper() 749 } 750 Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) 751 } 752 753 return pass 754 755 } 756 757 // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either 758 // a slice or a channel with len == 0. 759 // 760 // if assert.NotEmpty(t, obj) { 761 // assert.Equal(t, "two", obj[1]) 762 // } 763 func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 764 pass := !isEmpty(object) 765 if !pass { 766 if h, ok := t.(tHelper); ok { 767 h.Helper() 768 } 769 Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) 770 } 771 772 return pass 773 774 } 775 776 // getLen tries to get the length of an object. 777 // It returns (0, false) if impossible. 778 func getLen(x interface{}) (length int, ok bool) { 779 v := reflect.ValueOf(x) 780 defer func() { 781 ok = recover() == nil 782 }() 783 return v.Len(), true 784 } 785 786 // Len asserts that the specified object has specific length. 787 // Len also fails if the object has a type that len() not accept. 788 // 789 // assert.Len(t, mySlice, 3) 790 func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { 791 if h, ok := t.(tHelper); ok { 792 h.Helper() 793 } 794 l, ok := getLen(object) 795 if !ok { 796 return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...) 797 } 798 799 if l != length { 800 return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) 801 } 802 return true 803 } 804 805 // True asserts that the specified value is true. 806 // 807 // assert.True(t, myBool) 808 func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { 809 if !value { 810 if h, ok := t.(tHelper); ok { 811 h.Helper() 812 } 813 return Fail(t, "Should be true", msgAndArgs...) 814 } 815 816 return true 817 818 } 819 820 // False asserts that the specified value is false. 821 // 822 // assert.False(t, myBool) 823 func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { 824 if value { 825 if h, ok := t.(tHelper); ok { 826 h.Helper() 827 } 828 return Fail(t, "Should be false", msgAndArgs...) 829 } 830 831 return true 832 833 } 834 835 // NotEqual asserts that the specified values are NOT equal. 836 // 837 // assert.NotEqual(t, obj1, obj2) 838 // 839 // Pointer variable equality is determined based on the equality of the 840 // referenced values (as opposed to the memory addresses). 841 func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 842 if h, ok := t.(tHelper); ok { 843 h.Helper() 844 } 845 if err := validateEqualArgs(expected, actual); err != nil { 846 return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", 847 expected, actual, err), msgAndArgs...) 848 } 849 850 if ObjectsAreEqual(expected, actual) { 851 return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) 852 } 853 854 return true 855 856 } 857 858 // NotEqualValues asserts that two objects are not equal even when converted to the same type 859 // 860 // assert.NotEqualValues(t, obj1, obj2) 861 func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 862 if h, ok := t.(tHelper); ok { 863 h.Helper() 864 } 865 866 if ObjectsAreEqualValues(expected, actual) { 867 return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) 868 } 869 870 return true 871 } 872 873 // containsElement try loop over the list check if the list includes the element. 874 // return (false, false) if impossible. 875 // return (true, false) if element was not found. 876 // return (true, true) if element was found. 877 func containsElement(list interface{}, element interface{}) (ok, found bool) { 878 879 listValue := reflect.ValueOf(list) 880 listType := reflect.TypeOf(list) 881 if listType == nil { 882 return false, false 883 } 884 listKind := listType.Kind() 885 defer func() { 886 if e := recover(); e != nil { 887 ok = false 888 found = false 889 } 890 }() 891 892 if listKind == reflect.String { 893 elementValue := reflect.ValueOf(element) 894 return true, strings.Contains(listValue.String(), elementValue.String()) 895 } 896 897 if listKind == reflect.Map { 898 mapKeys := listValue.MapKeys() 899 for i := 0; i < len(mapKeys); i++ { 900 if ObjectsAreEqual(mapKeys[i].Interface(), element) { 901 return true, true 902 } 903 } 904 return true, false 905 } 906 907 for i := 0; i < listValue.Len(); i++ { 908 if ObjectsAreEqual(listValue.Index(i).Interface(), element) { 909 return true, true 910 } 911 } 912 return true, false 913 914 } 915 916 // Contains asserts that the specified string, list(array, slice...) or map contains the 917 // specified substring or element. 918 // 919 // assert.Contains(t, "Hello World", "World") 920 // assert.Contains(t, ["Hello", "World"], "World") 921 // assert.Contains(t, {"Hello": "World"}, "Hello") 922 func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { 923 if h, ok := t.(tHelper); ok { 924 h.Helper() 925 } 926 927 ok, found := containsElement(s, contains) 928 if !ok { 929 return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) 930 } 931 if !found { 932 return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...) 933 } 934 935 return true 936 937 } 938 939 // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the 940 // specified substring or element. 941 // 942 // assert.NotContains(t, "Hello World", "Earth") 943 // assert.NotContains(t, ["Hello", "World"], "Earth") 944 // assert.NotContains(t, {"Hello": "World"}, "Earth") 945 func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { 946 if h, ok := t.(tHelper); ok { 947 h.Helper() 948 } 949 950 ok, found := containsElement(s, contains) 951 if !ok { 952 return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) 953 } 954 if found { 955 return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...) 956 } 957 958 return true 959 960 } 961 962 // Subset asserts that the specified list(array, slice...) or map contains all 963 // elements given in the specified subset list(array, slice...) or map. 964 // 965 // assert.Subset(t, [1, 2, 3], [1, 2]) 966 // assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) 967 func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { 968 if h, ok := t.(tHelper); ok { 969 h.Helper() 970 } 971 if subset == nil { 972 return true // we consider nil to be equal to the nil set 973 } 974 975 listKind := reflect.TypeOf(list).Kind() 976 if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { 977 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) 978 } 979 980 subsetKind := reflect.TypeOf(subset).Kind() 981 if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { 982 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) 983 } 984 985 if subsetKind == reflect.Map && listKind == reflect.Map { 986 subsetMap := reflect.ValueOf(subset) 987 actualMap := reflect.ValueOf(list) 988 989 for _, k := range subsetMap.MapKeys() { 990 ev := subsetMap.MapIndex(k) 991 av := actualMap.MapIndex(k) 992 993 if !av.IsValid() { 994 return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) 995 } 996 if !ObjectsAreEqual(ev.Interface(), av.Interface()) { 997 return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) 998 } 999 } 1000 1001 return true 1002 } 1003 1004 subsetList := reflect.ValueOf(subset) 1005 for i := 0; i < subsetList.Len(); i++ { 1006 element := subsetList.Index(i).Interface() 1007 ok, found := containsElement(list, element) 1008 if !ok { 1009 return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...) 1010 } 1011 if !found { 1012 return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...) 1013 } 1014 } 1015 1016 return true 1017 } 1018 1019 // NotSubset asserts that the specified list(array, slice...) or map does NOT 1020 // contain all elements given in the specified subset list(array, slice...) or 1021 // map. 1022 // 1023 // assert.NotSubset(t, [1, 3, 4], [1, 2]) 1024 // assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) 1025 func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { 1026 if h, ok := t.(tHelper); ok { 1027 h.Helper() 1028 } 1029 if subset == nil { 1030 return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) 1031 } 1032 1033 listKind := reflect.TypeOf(list).Kind() 1034 if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { 1035 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) 1036 } 1037 1038 subsetKind := reflect.TypeOf(subset).Kind() 1039 if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { 1040 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) 1041 } 1042 1043 if subsetKind == reflect.Map && listKind == reflect.Map { 1044 subsetMap := reflect.ValueOf(subset) 1045 actualMap := reflect.ValueOf(list) 1046 1047 for _, k := range subsetMap.MapKeys() { 1048 ev := subsetMap.MapIndex(k) 1049 av := actualMap.MapIndex(k) 1050 1051 if !av.IsValid() { 1052 return true 1053 } 1054 if !ObjectsAreEqual(ev.Interface(), av.Interface()) { 1055 return true 1056 } 1057 } 1058 1059 return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) 1060 } 1061 1062 subsetList := reflect.ValueOf(subset) 1063 for i := 0; i < subsetList.Len(); i++ { 1064 element := subsetList.Index(i).Interface() 1065 ok, found := containsElement(list, element) 1066 if !ok { 1067 return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) 1068 } 1069 if !found { 1070 return true 1071 } 1072 } 1073 1074 return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) 1075 } 1076 1077 // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified 1078 // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, 1079 // the number of appearances of each of them in both lists should match. 1080 // 1081 // assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) 1082 func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { 1083 if h, ok := t.(tHelper); ok { 1084 h.Helper() 1085 } 1086 if isEmpty(listA) && isEmpty(listB) { 1087 return true 1088 } 1089 1090 if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) { 1091 return false 1092 } 1093 1094 extraA, extraB := diffLists(listA, listB) 1095 1096 if len(extraA) == 0 && len(extraB) == 0 { 1097 return true 1098 } 1099 1100 return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...) 1101 } 1102 1103 // isList checks that the provided value is array or slice. 1104 func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) { 1105 kind := reflect.TypeOf(list).Kind() 1106 if kind != reflect.Array && kind != reflect.Slice { 1107 return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind), 1108 msgAndArgs...) 1109 } 1110 return true 1111 } 1112 1113 // diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B. 1114 // If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and 1115 // 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored. 1116 func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) { 1117 aValue := reflect.ValueOf(listA) 1118 bValue := reflect.ValueOf(listB) 1119 1120 aLen := aValue.Len() 1121 bLen := bValue.Len() 1122 1123 // Mark indexes in bValue that we already used 1124 visited := make([]bool, bLen) 1125 for i := 0; i < aLen; i++ { 1126 element := aValue.Index(i).Interface() 1127 found := false 1128 for j := 0; j < bLen; j++ { 1129 if visited[j] { 1130 continue 1131 } 1132 if ObjectsAreEqual(bValue.Index(j).Interface(), element) { 1133 visited[j] = true 1134 found = true 1135 break 1136 } 1137 } 1138 if !found { 1139 extraA = append(extraA, element) 1140 } 1141 } 1142 1143 for j := 0; j < bLen; j++ { 1144 if visited[j] { 1145 continue 1146 } 1147 extraB = append(extraB, bValue.Index(j).Interface()) 1148 } 1149 1150 return 1151 } 1152 1153 func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string { 1154 var msg bytes.Buffer 1155 1156 msg.WriteString("elements differ") 1157 if len(extraA) > 0 { 1158 msg.WriteString("\n\nextra elements in list A:\n") 1159 msg.WriteString(spewConfig.Sdump(extraA)) 1160 } 1161 if len(extraB) > 0 { 1162 msg.WriteString("\n\nextra elements in list B:\n") 1163 msg.WriteString(spewConfig.Sdump(extraB)) 1164 } 1165 msg.WriteString("\n\nlistA:\n") 1166 msg.WriteString(spewConfig.Sdump(listA)) 1167 msg.WriteString("\n\nlistB:\n") 1168 msg.WriteString(spewConfig.Sdump(listB)) 1169 1170 return msg.String() 1171 } 1172 1173 // Condition uses a Comparison to assert a complex condition. 1174 func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { 1175 if h, ok := t.(tHelper); ok { 1176 h.Helper() 1177 } 1178 result := comp() 1179 if !result { 1180 Fail(t, "Condition failed!", msgAndArgs...) 1181 } 1182 return result 1183 } 1184 1185 // PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics 1186 // methods, and represents a simple func that takes no arguments, and returns nothing. 1187 type PanicTestFunc func() 1188 1189 // didPanic returns true if the function passed to it panics. Otherwise, it returns false. 1190 func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) { 1191 didPanic = true 1192 1193 defer func() { 1194 message = recover() 1195 if didPanic { 1196 stack = string(debug.Stack()) 1197 } 1198 }() 1199 1200 // call the target function 1201 f() 1202 didPanic = false 1203 1204 return 1205 } 1206 1207 // Panics asserts that the code inside the specified PanicTestFunc panics. 1208 // 1209 // assert.Panics(t, func(){ GoCrazy() }) 1210 func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { 1211 if h, ok := t.(tHelper); ok { 1212 h.Helper() 1213 } 1214 1215 if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic { 1216 return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) 1217 } 1218 1219 return true 1220 } 1221 1222 // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that 1223 // the recovered panic value equals the expected panic value. 1224 // 1225 // assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) 1226 func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { 1227 if h, ok := t.(tHelper); ok { 1228 h.Helper() 1229 } 1230 1231 funcDidPanic, panicValue, panickedStack := didPanic(f) 1232 if !funcDidPanic { 1233 return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) 1234 } 1235 if panicValue != expected { 1236 return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...) 1237 } 1238 1239 return true 1240 } 1241 1242 // PanicsWithError asserts that the code inside the specified PanicTestFunc 1243 // panics, and that the recovered panic value is an error that satisfies the 1244 // EqualError comparison. 1245 // 1246 // assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) 1247 func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { 1248 if h, ok := t.(tHelper); ok { 1249 h.Helper() 1250 } 1251 1252 funcDidPanic, panicValue, panickedStack := didPanic(f) 1253 if !funcDidPanic { 1254 return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) 1255 } 1256 panicErr, ok := panicValue.(error) 1257 if !ok || panicErr.Error() != errString { 1258 return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...) 1259 } 1260 1261 return true 1262 } 1263 1264 // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. 1265 // 1266 // assert.NotPanics(t, func(){ RemainCalm() }) 1267 func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { 1268 if h, ok := t.(tHelper); ok { 1269 h.Helper() 1270 } 1271 1272 if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic { 1273 return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...) 1274 } 1275 1276 return true 1277 } 1278 1279 // WithinDuration asserts that the two times are within duration delta of each other. 1280 // 1281 // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) 1282 func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { 1283 if h, ok := t.(tHelper); ok { 1284 h.Helper() 1285 } 1286 1287 dt := expected.Sub(actual) 1288 if dt < -delta || dt > delta { 1289 return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) 1290 } 1291 1292 return true 1293 } 1294 1295 // WithinRange asserts that a time is within a time range (inclusive). 1296 // 1297 // assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) 1298 func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool { 1299 if h, ok := t.(tHelper); ok { 1300 h.Helper() 1301 } 1302 1303 if end.Before(start) { 1304 return Fail(t, "Start should be before end", msgAndArgs...) 1305 } 1306 1307 if actual.Before(start) { 1308 return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...) 1309 } else if actual.After(end) { 1310 return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...) 1311 } 1312 1313 return true 1314 } 1315 1316 func toFloat(x interface{}) (float64, bool) { 1317 var xf float64 1318 xok := true 1319 1320 switch xn := x.(type) { 1321 case uint: 1322 xf = float64(xn) 1323 case uint8: 1324 xf = float64(xn) 1325 case uint16: 1326 xf = float64(xn) 1327 case uint32: 1328 xf = float64(xn) 1329 case uint64: 1330 xf = float64(xn) 1331 case int: 1332 xf = float64(xn) 1333 case int8: 1334 xf = float64(xn) 1335 case int16: 1336 xf = float64(xn) 1337 case int32: 1338 xf = float64(xn) 1339 case int64: 1340 xf = float64(xn) 1341 case float32: 1342 xf = float64(xn) 1343 case float64: 1344 xf = xn 1345 case time.Duration: 1346 xf = float64(xn) 1347 default: 1348 xok = false 1349 } 1350 1351 return xf, xok 1352 } 1353 1354 // InDelta asserts that the two numerals are within delta of each other. 1355 // 1356 // assert.InDelta(t, math.Pi, 22/7.0, 0.01) 1357 func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { 1358 if h, ok := t.(tHelper); ok { 1359 h.Helper() 1360 } 1361 1362 af, aok := toFloat(expected) 1363 bf, bok := toFloat(actual) 1364 1365 if !aok || !bok { 1366 return Fail(t, "Parameters must be numerical", msgAndArgs...) 1367 } 1368 1369 if math.IsNaN(af) && math.IsNaN(bf) { 1370 return true 1371 } 1372 1373 if math.IsNaN(af) { 1374 return Fail(t, "Expected must not be NaN", msgAndArgs...) 1375 } 1376 1377 if math.IsNaN(bf) { 1378 return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) 1379 } 1380 1381 dt := af - bf 1382 if dt < -delta || dt > delta { 1383 return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) 1384 } 1385 1386 return true 1387 } 1388 1389 // InDeltaSlice is the same as InDelta, except it compares two slices. 1390 func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { 1391 if h, ok := t.(tHelper); ok { 1392 h.Helper() 1393 } 1394 if expected == nil || actual == nil || 1395 reflect.TypeOf(actual).Kind() != reflect.Slice || 1396 reflect.TypeOf(expected).Kind() != reflect.Slice { 1397 return Fail(t, "Parameters must be slice", msgAndArgs...) 1398 } 1399 1400 actualSlice := reflect.ValueOf(actual) 1401 expectedSlice := reflect.ValueOf(expected) 1402 1403 for i := 0; i < actualSlice.Len(); i++ { 1404 result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) 1405 if !result { 1406 return result 1407 } 1408 } 1409 1410 return true 1411 } 1412 1413 // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. 1414 func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { 1415 if h, ok := t.(tHelper); ok { 1416 h.Helper() 1417 } 1418 if expected == nil || actual == nil || 1419 reflect.TypeOf(actual).Kind() != reflect.Map || 1420 reflect.TypeOf(expected).Kind() != reflect.Map { 1421 return Fail(t, "Arguments must be maps", msgAndArgs...) 1422 } 1423 1424 expectedMap := reflect.ValueOf(expected) 1425 actualMap := reflect.ValueOf(actual) 1426 1427 if expectedMap.Len() != actualMap.Len() { 1428 return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) 1429 } 1430 1431 for _, k := range expectedMap.MapKeys() { 1432 ev := expectedMap.MapIndex(k) 1433 av := actualMap.MapIndex(k) 1434 1435 if !ev.IsValid() { 1436 return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) 1437 } 1438 1439 if !av.IsValid() { 1440 return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) 1441 } 1442 1443 if !InDelta( 1444 t, 1445 ev.Interface(), 1446 av.Interface(), 1447 delta, 1448 msgAndArgs..., 1449 ) { 1450 return false 1451 } 1452 } 1453 1454 return true 1455 } 1456 1457 func calcRelativeError(expected, actual interface{}) (float64, error) { 1458 af, aok := toFloat(expected) 1459 bf, bok := toFloat(actual) 1460 if !aok || !bok { 1461 return 0, fmt.Errorf("Parameters must be numerical") 1462 } 1463 if math.IsNaN(af) && math.IsNaN(bf) { 1464 return 0, nil 1465 } 1466 if math.IsNaN(af) { 1467 return 0, errors.New("expected value must not be NaN") 1468 } 1469 if af == 0 { 1470 return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") 1471 } 1472 if math.IsNaN(bf) { 1473 return 0, errors.New("actual value must not be NaN") 1474 } 1475 1476 return math.Abs(af-bf) / math.Abs(af), nil 1477 } 1478 1479 // InEpsilon asserts that expected and actual have a relative error less than epsilon 1480 func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { 1481 if h, ok := t.(tHelper); ok { 1482 h.Helper() 1483 } 1484 if math.IsNaN(epsilon) { 1485 return Fail(t, "epsilon must not be NaN", msgAndArgs...) 1486 } 1487 actualEpsilon, err := calcRelativeError(expected, actual) 1488 if err != nil { 1489 return Fail(t, err.Error(), msgAndArgs...) 1490 } 1491 if actualEpsilon > epsilon { 1492 return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ 1493 " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) 1494 } 1495 1496 return true 1497 } 1498 1499 // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. 1500 func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { 1501 if h, ok := t.(tHelper); ok { 1502 h.Helper() 1503 } 1504 1505 if expected == nil || actual == nil { 1506 return Fail(t, "Parameters must be slice", msgAndArgs...) 1507 } 1508 1509 expectedSlice := reflect.ValueOf(expected) 1510 actualSlice := reflect.ValueOf(actual) 1511 1512 if expectedSlice.Type().Kind() != reflect.Slice { 1513 return Fail(t, "Expected value must be slice", msgAndArgs...) 1514 } 1515 1516 expectedLen := expectedSlice.Len() 1517 if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) { 1518 return false 1519 } 1520 1521 for i := 0; i < expectedLen; i++ { 1522 if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) { 1523 return false 1524 } 1525 } 1526 1527 return true 1528 } 1529 1530 /* 1531 Errors 1532 */ 1533 1534 // NoError asserts that a function returned no error (i.e. `nil`). 1535 // 1536 // actualObj, err := SomeFunction() 1537 // if assert.NoError(t, err) { 1538 // assert.Equal(t, expectedObj, actualObj) 1539 // } 1540 func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { 1541 if err != nil { 1542 if h, ok := t.(tHelper); ok { 1543 h.Helper() 1544 } 1545 return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) 1546 } 1547 1548 return true 1549 } 1550 1551 // Error asserts that a function returned an error (i.e. not `nil`). 1552 // 1553 // actualObj, err := SomeFunction() 1554 // if assert.Error(t, err) { 1555 // assert.Equal(t, expectedError, err) 1556 // } 1557 func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { 1558 if err == nil { 1559 if h, ok := t.(tHelper); ok { 1560 h.Helper() 1561 } 1562 return Fail(t, "An error is expected but got nil.", msgAndArgs...) 1563 } 1564 1565 return true 1566 } 1567 1568 // EqualError asserts that a function returned an error (i.e. not `nil`) 1569 // and that it is equal to the provided error. 1570 // 1571 // actualObj, err := SomeFunction() 1572 // assert.EqualError(t, err, expectedErrorString) 1573 func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { 1574 if h, ok := t.(tHelper); ok { 1575 h.Helper() 1576 } 1577 if !Error(t, theError, msgAndArgs...) { 1578 return false 1579 } 1580 expected := errString 1581 actual := theError.Error() 1582 // don't need to use deep equals here, we know they are both strings 1583 if expected != actual { 1584 return Fail(t, fmt.Sprintf("Error message not equal:\n"+ 1585 "expected: %q\n"+ 1586 "actual : %q", expected, actual), msgAndArgs...) 1587 } 1588 return true 1589 } 1590 1591 // ErrorContains asserts that a function returned an error (i.e. not `nil`) 1592 // and that the error contains the specified substring. 1593 // 1594 // actualObj, err := SomeFunction() 1595 // assert.ErrorContains(t, err, expectedErrorSubString) 1596 func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool { 1597 if h, ok := t.(tHelper); ok { 1598 h.Helper() 1599 } 1600 if !Error(t, theError, msgAndArgs...) { 1601 return false 1602 } 1603 1604 actual := theError.Error() 1605 if !strings.Contains(actual, contains) { 1606 return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...) 1607 } 1608 1609 return true 1610 } 1611 1612 // matchRegexp return true if a specified regexp matches a string. 1613 func matchRegexp(rx interface{}, str interface{}) bool { 1614 1615 var r *regexp.Regexp 1616 if rr, ok := rx.(*regexp.Regexp); ok { 1617 r = rr 1618 } else { 1619 r = regexp.MustCompile(fmt.Sprint(rx)) 1620 } 1621 1622 return (r.FindStringIndex(fmt.Sprint(str)) != nil) 1623 1624 } 1625 1626 // Regexp asserts that a specified regexp matches a string. 1627 // 1628 // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") 1629 // assert.Regexp(t, "start...$", "it's not starting") 1630 func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { 1631 if h, ok := t.(tHelper); ok { 1632 h.Helper() 1633 } 1634 1635 match := matchRegexp(rx, str) 1636 1637 if !match { 1638 Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) 1639 } 1640 1641 return match 1642 } 1643 1644 // NotRegexp asserts that a specified regexp does not match a string. 1645 // 1646 // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") 1647 // assert.NotRegexp(t, "^start", "it's not starting") 1648 func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { 1649 if h, ok := t.(tHelper); ok { 1650 h.Helper() 1651 } 1652 match := matchRegexp(rx, str) 1653 1654 if match { 1655 Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) 1656 } 1657 1658 return !match 1659 1660 } 1661 1662 // Zero asserts that i is the zero value for its type. 1663 func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { 1664 if h, ok := t.(tHelper); ok { 1665 h.Helper() 1666 } 1667 if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { 1668 return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) 1669 } 1670 return true 1671 } 1672 1673 // NotZero asserts that i is not the zero value for its type. 1674 func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { 1675 if h, ok := t.(tHelper); ok { 1676 h.Helper() 1677 } 1678 if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { 1679 return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) 1680 } 1681 return true 1682 } 1683 1684 // FileExists checks whether a file exists in the given path. It also fails if 1685 // the path points to a directory or there is an error when trying to check the file. 1686 func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { 1687 if h, ok := t.(tHelper); ok { 1688 h.Helper() 1689 } 1690 info, err := os.Lstat(path) 1691 if err != nil { 1692 if os.IsNotExist(err) { 1693 return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) 1694 } 1695 return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) 1696 } 1697 if info.IsDir() { 1698 return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) 1699 } 1700 return true 1701 } 1702 1703 // NoFileExists checks whether a file does not exist in a given path. It fails 1704 // if the path points to an existing _file_ only. 1705 func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { 1706 if h, ok := t.(tHelper); ok { 1707 h.Helper() 1708 } 1709 info, err := os.Lstat(path) 1710 if err != nil { 1711 return true 1712 } 1713 if info.IsDir() { 1714 return true 1715 } 1716 return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...) 1717 } 1718 1719 // DirExists checks whether a directory exists in the given path. It also fails 1720 // if the path is a file rather a directory or there is an error checking whether it exists. 1721 func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { 1722 if h, ok := t.(tHelper); ok { 1723 h.Helper() 1724 } 1725 info, err := os.Lstat(path) 1726 if err != nil { 1727 if os.IsNotExist(err) { 1728 return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) 1729 } 1730 return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) 1731 } 1732 if !info.IsDir() { 1733 return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) 1734 } 1735 return true 1736 } 1737 1738 // NoDirExists checks whether a directory does not exist in the given path. 1739 // It fails if the path points to an existing _directory_ only. 1740 func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { 1741 if h, ok := t.(tHelper); ok { 1742 h.Helper() 1743 } 1744 info, err := os.Lstat(path) 1745 if err != nil { 1746 if os.IsNotExist(err) { 1747 return true 1748 } 1749 return true 1750 } 1751 if !info.IsDir() { 1752 return true 1753 } 1754 return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...) 1755 } 1756 1757 // JSONEq asserts that two JSON strings are equivalent. 1758 // 1759 // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) 1760 func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { 1761 if h, ok := t.(tHelper); ok { 1762 h.Helper() 1763 } 1764 var expectedJSONAsInterface, actualJSONAsInterface interface{} 1765 1766 if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { 1767 return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) 1768 } 1769 1770 if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { 1771 return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) 1772 } 1773 1774 return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) 1775 } 1776 1777 // YAMLEq asserts that two YAML strings are equivalent. 1778 func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { 1779 if h, ok := t.(tHelper); ok { 1780 h.Helper() 1781 } 1782 var expectedYAMLAsInterface, actualYAMLAsInterface interface{} 1783 1784 if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil { 1785 return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) 1786 } 1787 1788 if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { 1789 return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) 1790 } 1791 1792 return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...) 1793 } 1794 1795 func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { 1796 t := reflect.TypeOf(v) 1797 k := t.Kind() 1798 1799 if k == reflect.Ptr { 1800 t = t.Elem() 1801 k = t.Kind() 1802 } 1803 return t, k 1804 } 1805 1806 // diff returns a diff of both values as long as both are of the same type and 1807 // are a struct, map, slice, array or string. Otherwise it returns an empty string. 1808 func diff(expected interface{}, actual interface{}) string { 1809 if expected == nil || actual == nil { 1810 return "" 1811 } 1812 1813 et, ek := typeAndKind(expected) 1814 at, _ := typeAndKind(actual) 1815 1816 if et != at { 1817 return "" 1818 } 1819 1820 if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { 1821 return "" 1822 } 1823 1824 var e, a string 1825 1826 switch et { 1827 case reflect.TypeOf(""): 1828 e = reflect.ValueOf(expected).String() 1829 a = reflect.ValueOf(actual).String() 1830 case reflect.TypeOf(time.Time{}): 1831 e = spewConfigStringerEnabled.Sdump(expected) 1832 a = spewConfigStringerEnabled.Sdump(actual) 1833 default: 1834 e = spewConfig.Sdump(expected) 1835 a = spewConfig.Sdump(actual) 1836 } 1837 1838 diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ 1839 A: difflib.SplitLines(e), 1840 B: difflib.SplitLines(a), 1841 FromFile: "Expected", 1842 FromDate: "", 1843 ToFile: "Actual", 1844 ToDate: "", 1845 Context: 1, 1846 }) 1847 1848 return "\n\nDiff:\n" + diff 1849 } 1850 1851 func isFunction(arg interface{}) bool { 1852 if arg == nil { 1853 return false 1854 } 1855 return reflect.TypeOf(arg).Kind() == reflect.Func 1856 } 1857 1858 var spewConfig = spew.ConfigState{ 1859 Indent: " ", 1860 DisablePointerAddresses: true, 1861 DisableCapacities: true, 1862 SortKeys: true, 1863 DisableMethods: true, 1864 MaxDepth: 10, 1865 } 1866 1867 var spewConfigStringerEnabled = spew.ConfigState{ 1868 Indent: " ", 1869 DisablePointerAddresses: true, 1870 DisableCapacities: true, 1871 SortKeys: true, 1872 MaxDepth: 10, 1873 } 1874 1875 type tHelper interface { 1876 Helper() 1877 } 1878 1879 // Eventually asserts that given condition will be met in waitFor time, 1880 // periodically checking target function each tick. 1881 // 1882 // assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) 1883 func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { 1884 if h, ok := t.(tHelper); ok { 1885 h.Helper() 1886 } 1887 1888 ch := make(chan bool, 1) 1889 1890 timer := time.NewTimer(waitFor) 1891 defer timer.Stop() 1892 1893 ticker := time.NewTicker(tick) 1894 defer ticker.Stop() 1895 1896 for tick := ticker.C; ; { 1897 select { 1898 case <-timer.C: 1899 return Fail(t, "Condition never satisfied", msgAndArgs...) 1900 case <-tick: 1901 tick = nil 1902 go func() { ch <- condition() }() 1903 case v := <-ch: 1904 if v { 1905 return true 1906 } 1907 tick = ticker.C 1908 } 1909 } 1910 } 1911 1912 // CollectT implements the TestingT interface and collects all errors. 1913 type CollectT struct { 1914 errors []error 1915 } 1916 1917 // Errorf collects the error. 1918 func (c *CollectT) Errorf(format string, args ...interface{}) { 1919 c.errors = append(c.errors, fmt.Errorf(format, args...)) 1920 } 1921 1922 // FailNow panics. 1923 func (*CollectT) FailNow() { 1924 panic("Assertion failed") 1925 } 1926 1927 // Deprecated: That was a method for internal usage that should not have been published. Now just panics. 1928 func (*CollectT) Reset() { 1929 panic("Reset() is deprecated") 1930 } 1931 1932 // Deprecated: That was a method for internal usage that should not have been published. Now just panics. 1933 func (*CollectT) Copy(TestingT) { 1934 panic("Copy() is deprecated") 1935 } 1936 1937 // EventuallyWithT asserts that given condition will be met in waitFor time, 1938 // periodically checking target function each tick. In contrast to Eventually, 1939 // it supplies a CollectT to the condition function, so that the condition 1940 // function can use the CollectT to call other assertions. 1941 // The condition is considered "met" if no errors are raised in a tick. 1942 // The supplied CollectT collects all errors from one tick (if there are any). 1943 // If the condition is not met before waitFor, the collected errors of 1944 // the last tick are copied to t. 1945 // 1946 // externalValue := false 1947 // go func() { 1948 // time.Sleep(8*time.Second) 1949 // externalValue = true 1950 // }() 1951 // assert.EventuallyWithT(t, func(c *assert.CollectT) { 1952 // // add assertions as needed; any assertion failure will fail the current tick 1953 // assert.True(c, externalValue, "expected 'externalValue' to be true") 1954 // }, 1*time.Second, 10*time.Second, "external state has not changed to 'true'; still false") 1955 func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { 1956 if h, ok := t.(tHelper); ok { 1957 h.Helper() 1958 } 1959 1960 var lastFinishedTickErrs []error 1961 ch := make(chan []error, 1) 1962 1963 timer := time.NewTimer(waitFor) 1964 defer timer.Stop() 1965 1966 ticker := time.NewTicker(tick) 1967 defer ticker.Stop() 1968 1969 for tick := ticker.C; ; { 1970 select { 1971 case <-timer.C: 1972 for _, err := range lastFinishedTickErrs { 1973 t.Errorf("%v", err) 1974 } 1975 return Fail(t, "Condition never satisfied", msgAndArgs...) 1976 case <-tick: 1977 tick = nil 1978 go func() { 1979 collect := new(CollectT) 1980 defer func() { 1981 ch <- collect.errors 1982 }() 1983 condition(collect) 1984 }() 1985 case errs := <-ch: 1986 if len(errs) == 0 { 1987 return true 1988 } 1989 // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. 1990 lastFinishedTickErrs = errs 1991 tick = ticker.C 1992 } 1993 } 1994 } 1995 1996 // Never asserts that the given condition doesn't satisfy in waitFor time, 1997 // periodically checking the target function each tick. 1998 // 1999 // assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) 2000 func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { 2001 if h, ok := t.(tHelper); ok { 2002 h.Helper() 2003 } 2004 2005 ch := make(chan bool, 1) 2006 2007 timer := time.NewTimer(waitFor) 2008 defer timer.Stop() 2009 2010 ticker := time.NewTicker(tick) 2011 defer ticker.Stop() 2012 2013 for tick := ticker.C; ; { 2014 select { 2015 case <-timer.C: 2016 return true 2017 case <-tick: 2018 tick = nil 2019 go func() { ch <- condition() }() 2020 case v := <-ch: 2021 if v { 2022 return Fail(t, "Condition satisfied", msgAndArgs...) 2023 } 2024 tick = ticker.C 2025 } 2026 } 2027 } 2028 2029 // ErrorIs asserts that at least one of the errors in err's chain matches target. 2030 // This is a wrapper for errors.Is. 2031 func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { 2032 if h, ok := t.(tHelper); ok { 2033 h.Helper() 2034 } 2035 if errors.Is(err, target) { 2036 return true 2037 } 2038 2039 var expectedText string 2040 if target != nil { 2041 expectedText = target.Error() 2042 } 2043 2044 chain := buildErrorChainString(err) 2045 2046 return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+ 2047 "expected: %q\n"+ 2048 "in chain: %s", expectedText, chain, 2049 ), msgAndArgs...) 2050 } 2051 2052 // NotErrorIs asserts that at none of the errors in err's chain matches target. 2053 // This is a wrapper for errors.Is. 2054 func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { 2055 if h, ok := t.(tHelper); ok { 2056 h.Helper() 2057 } 2058 if !errors.Is(err, target) { 2059 return true 2060 } 2061 2062 var expectedText string 2063 if target != nil { 2064 expectedText = target.Error() 2065 } 2066 2067 chain := buildErrorChainString(err) 2068 2069 return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ 2070 "found: %q\n"+ 2071 "in chain: %s", expectedText, chain, 2072 ), msgAndArgs...) 2073 } 2074 2075 // ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. 2076 // This is a wrapper for errors.As. 2077 func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool { 2078 if h, ok := t.(tHelper); ok { 2079 h.Helper() 2080 } 2081 if errors.As(err, target) { 2082 return true 2083 } 2084 2085 chain := buildErrorChainString(err) 2086 2087 return Fail(t, fmt.Sprintf("Should be in error chain:\n"+ 2088 "expected: %q\n"+ 2089 "in chain: %s", target, chain, 2090 ), msgAndArgs...) 2091 } 2092 2093 func buildErrorChainString(err error) string { 2094 if err == nil { 2095 return "" 2096 } 2097 2098 e := errors.Unwrap(err) 2099 chain := fmt.Sprintf("%q", err.Error()) 2100 for e != nil { 2101 chain += fmt.Sprintf("\n\t%q", e.Error()) 2102 e = errors.Unwrap(e) 2103 } 2104 return chain 2105 }