1package assert 2 3import ( 4 "bufio" 5 "bytes" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "math" 10 "os" 11 "reflect" 12 "regexp" 13 "runtime" 14 "strings" 15 "time" 16 "unicode" 17 "unicode/utf8" 18 19 "github.com/davecgh/go-spew/spew" 20 "github.com/pmezard/go-difflib/difflib" 21 yaml "gopkg.in/yaml.v2" 22) 23 24//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl 25 26// TestingT is an interface wrapper around *testing.T 27type TestingT interface { 28 Errorf(format string, args ...interface{}) 29} 30 31// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful 32// for table driven tests. 33type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool 34 35// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful 36// for table driven tests. 37type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool 38 39// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful 40// for table driven tests. 41type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool 42 43// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful 44// for table driven tests. 45type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool 46 47// Comparison a custom function that returns true on success and false on failure 48type Comparison func() (success bool) 49 50/* 51 Helper functions 52*/ 53 54// ObjectsAreEqual determines if two objects are considered equal. 55// 56// This function does no assertion of any kind. 57func ObjectsAreEqual(expected, actual interface{}) bool { 58 if expected == nil || actual == nil { 59 return expected == actual 60 } 61 62 exp, ok := expected.([]byte) 63 if !ok { 64 return reflect.DeepEqual(expected, actual) 65 } 66 67 act, ok := actual.([]byte) 68 if !ok { 69 return false 70 } 71 if exp == nil || act == nil { 72 return exp == nil && act == nil 73 } 74 return bytes.Equal(exp, act) 75} 76 77// ObjectsAreEqualValues gets whether two objects are equal, or if their 78// values are equal. 79func ObjectsAreEqualValues(expected, actual interface{}) bool { 80 if ObjectsAreEqual(expected, actual) { 81 return true 82 } 83 84 actualType := reflect.TypeOf(actual) 85 if actualType == nil { 86 return false 87 } 88 expectedValue := reflect.ValueOf(expected) 89 if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { 90 // Attempt comparison after type conversion 91 return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) 92 } 93 94 return false 95} 96 97/* CallerInfo is necessary because the assert functions use the testing object 98internally, causing it to print the file:line of the assert method, rather than where 99the problem actually occurred in calling code.*/ 100 101// CallerInfo returns an array of strings containing the file and line number 102// of each stack frame leading from the current test to the assert call that 103// failed. 104func CallerInfo() []string { 105 106 pc := uintptr(0) 107 file := "" 108 line := 0 109 ok := false 110 name := "" 111 112 callers := []string{} 113 for i := 0; ; i++ { 114 pc, file, line, ok = runtime.Caller(i) 115 if !ok { 116 // The breaks below failed to terminate the loop, and we ran off the 117 // end of the call stack. 118 break 119 } 120 121 // This is a huge edge case, but it will panic if this is the case, see #180 122 if file == "<autogenerated>" { 123 break 124 } 125 126 f := runtime.FuncForPC(pc) 127 if f == nil { 128 break 129 } 130 name = f.Name() 131 132 // testing.tRunner is the standard library function that calls 133 // tests. Subtests are called directly by tRunner, without going through 134 // the Test/Benchmark/Example function that contains the t.Run calls, so 135 // with subtests we should break when we hit tRunner, without adding it 136 // to the list of callers. 137 if name == "testing.tRunner" { 138 break 139 } 140 141 parts := strings.Split(file, "/") 142 file = parts[len(parts)-1] 143 if len(parts) > 1 { 144 dir := parts[len(parts)-2] 145 if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { 146 callers = append(callers, fmt.Sprintf("%s:%d", file, line)) 147 } 148 } 149 150 // Drop the package 151 segments := strings.Split(name, ".") 152 name = segments[len(segments)-1] 153 if isTest(name, "Test") || 154 isTest(name, "Benchmark") || 155 isTest(name, "Example") { 156 break 157 } 158 } 159 160 return callers 161} 162 163// Stolen from the `go test` tool. 164// isTest tells whether name looks like a test (or benchmark, according to prefix). 165// It is a Test (say) if there is a character after Test that is not a lower-case letter. 166// We don't want TesticularCancer. 167func isTest(name, prefix string) bool { 168 if !strings.HasPrefix(name, prefix) { 169 return false 170 } 171 if len(name) == len(prefix) { // "Test" is ok 172 return true 173 } 174 rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) 175 return !unicode.IsLower(rune) 176} 177 178func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { 179 if len(msgAndArgs) == 0 || msgAndArgs == nil { 180 return "" 181 } 182 if len(msgAndArgs) == 1 { 183 msg := msgAndArgs[0] 184 if msgAsStr, ok := msg.(string); ok { 185 return msgAsStr 186 } 187 return fmt.Sprintf("%+v", msg) 188 } 189 if len(msgAndArgs) > 1 { 190 return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) 191 } 192 return "" 193} 194 195// Aligns the provided message so that all lines after the first line start at the same location as the first line. 196// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). 197// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the 198// basis on which the alignment occurs). 199func indentMessageLines(message string, longestLabelLen int) string { 200 outBuf := new(bytes.Buffer) 201 202 for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { 203 // no need to align first line because it starts at the correct location (after the label) 204 if i != 0 { 205 // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab 206 outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") 207 } 208 outBuf.WriteString(scanner.Text()) 209 } 210 211 return outBuf.String() 212} 213 214type failNower interface { 215 FailNow() 216} 217 218// FailNow fails test 219func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { 220 if h, ok := t.(tHelper); ok { 221 h.Helper() 222 } 223 Fail(t, failureMessage, msgAndArgs...) 224 225 // We cannot extend TestingT with FailNow() and 226 // maintain backwards compatibility, so we fallback 227 // to panicking when FailNow is not available in 228 // TestingT. 229 // See issue #263 230 231 if t, ok := t.(failNower); ok { 232 t.FailNow() 233 } else { 234 panic("test failed and t is missing `FailNow()`") 235 } 236 return false 237} 238 239// Fail reports a failure through 240func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { 241 if h, ok := t.(tHelper); ok { 242 h.Helper() 243 } 244 content := []labeledContent{ 245 {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, 246 {"Error", failureMessage}, 247 } 248 249 // Add test name if the Go version supports it 250 if n, ok := t.(interface { 251 Name() string 252 }); ok { 253 content = append(content, labeledContent{"Test", n.Name()}) 254 } 255 256 message := messageFromMsgAndArgs(msgAndArgs...) 257 if len(message) > 0 { 258 content = append(content, labeledContent{"Messages", message}) 259 } 260 261 t.Errorf("\n%s", ""+labeledOutput(content...)) 262 263 return false 264} 265 266type labeledContent struct { 267 label string 268 content string 269} 270 271// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: 272// 273// \t{{label}}:{{align_spaces}}\t{{content}}\n 274// 275// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. 276// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this 277// alignment is achieved, "\t{{content}}\n" is added for the output. 278// 279// 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. 280func labeledOutput(content ...labeledContent) string { 281 longestLabel := 0 282 for _, v := range content { 283 if len(v.label) > longestLabel { 284 longestLabel = len(v.label) 285 } 286 } 287 var output string 288 for _, v := range content { 289 output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" 290 } 291 return output 292} 293 294// Implements asserts that an object is implemented by the specified interface. 295// 296// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) 297func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { 298 if h, ok := t.(tHelper); ok { 299 h.Helper() 300 } 301 interfaceType := reflect.TypeOf(interfaceObject).Elem() 302 303 if object == nil { 304 return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) 305 } 306 if !reflect.TypeOf(object).Implements(interfaceType) { 307 return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) 308 } 309 310 return true 311} 312 313// IsType asserts that the specified objects are of the same type. 314func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { 315 if h, ok := t.(tHelper); ok { 316 h.Helper() 317 } 318 319 if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { 320 return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) 321 } 322 323 return true 324} 325 326// Equal asserts that two objects are equal. 327// 328// assert.Equal(t, 123, 123) 329// 330// Pointer variable equality is determined based on the equality of the 331// referenced values (as opposed to the memory addresses). Function equality 332// cannot be determined and will always fail. 333func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 334 if h, ok := t.(tHelper); ok { 335 h.Helper() 336 } 337 if err := validateEqualArgs(expected, actual); err != nil { 338 return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", 339 expected, actual, err), msgAndArgs...) 340 } 341 342 if !ObjectsAreEqual(expected, actual) { 343 diff := diff(expected, actual) 344 expected, actual = formatUnequalValues(expected, actual) 345 return Fail(t, fmt.Sprintf("Not equal: \n"+ 346 "expected: %s\n"+ 347 "actual : %s%s", expected, actual, diff), msgAndArgs...) 348 } 349 350 return true 351 352} 353 354// Same asserts that two pointers reference the same object. 355// 356// assert.Same(t, ptr1, ptr2) 357// 358// Both arguments must be pointer variables. Pointer variable sameness is 359// determined based on the equality of both type and value. 360func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 361 if h, ok := t.(tHelper); ok { 362 h.Helper() 363 } 364 365 expectedPtr, actualPtr := reflect.ValueOf(expected), reflect.ValueOf(actual) 366 if expectedPtr.Kind() != reflect.Ptr || actualPtr.Kind() != reflect.Ptr { 367 return Fail(t, "Invalid operation: both arguments must be pointers", msgAndArgs...) 368 } 369 370 expectedType, actualType := reflect.TypeOf(expected), reflect.TypeOf(actual) 371 if expectedType != actualType { 372 return Fail(t, fmt.Sprintf("Pointer expected to be of type %v, but was %v", 373 expectedType, actualType), msgAndArgs...) 374 } 375 376 if expected != actual { 377 return Fail(t, fmt.Sprintf("Not same: \n"+ 378 "expected: %p %#v\n"+ 379 "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...) 380 } 381 382 return true 383} 384 385// formatUnequalValues takes two values of arbitrary types and returns string 386// representations appropriate to be presented to the user. 387// 388// If the values are not of like type, the returned strings will be prefixed 389// with the type name, and the value will be enclosed in parenthesis similar 390// to a type conversion in the Go grammar. 391func formatUnequalValues(expected, actual interface{}) (e string, a string) { 392 if reflect.TypeOf(expected) != reflect.TypeOf(actual) { 393 return fmt.Sprintf("%T(%#v)", expected, expected), 394 fmt.Sprintf("%T(%#v)", actual, actual) 395 } 396 397 return fmt.Sprintf("%#v", expected), 398 fmt.Sprintf("%#v", actual) 399} 400 401// EqualValues asserts that two objects are equal or convertable to the same types 402// and equal. 403// 404// assert.EqualValues(t, uint32(123), int32(123)) 405func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 406 if h, ok := t.(tHelper); ok { 407 h.Helper() 408 } 409 410 if !ObjectsAreEqualValues(expected, actual) { 411 diff := diff(expected, actual) 412 expected, actual = formatUnequalValues(expected, actual) 413 return Fail(t, fmt.Sprintf("Not equal: \n"+ 414 "expected: %s\n"+ 415 "actual : %s%s", expected, actual, diff), msgAndArgs...) 416 } 417 418 return true 419 420} 421 422// Exactly asserts that two objects are equal in value and type. 423// 424// assert.Exactly(t, int32(123), int64(123)) 425func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 426 if h, ok := t.(tHelper); ok { 427 h.Helper() 428 } 429 430 aType := reflect.TypeOf(expected) 431 bType := reflect.TypeOf(actual) 432 433 if aType != bType { 434 return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) 435 } 436 437 return Equal(t, expected, actual, msgAndArgs...) 438 439} 440 441// NotNil asserts that the specified object is not nil. 442// 443// assert.NotNil(t, err) 444func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 445 if h, ok := t.(tHelper); ok { 446 h.Helper() 447 } 448 if !isNil(object) { 449 return true 450 } 451 return Fail(t, "Expected value not to be nil.", msgAndArgs...) 452} 453 454// containsKind checks if a specified kind in the slice of kinds. 455func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { 456 for i := 0; i < len(kinds); i++ { 457 if kind == kinds[i] { 458 return true 459 } 460 } 461 462 return false 463} 464 465// isNil checks if a specified object is nil or not, without Failing. 466func isNil(object interface{}) bool { 467 if object == nil { 468 return true 469 } 470 471 value := reflect.ValueOf(object) 472 kind := value.Kind() 473 isNilableKind := containsKind( 474 []reflect.Kind{ 475 reflect.Chan, reflect.Func, 476 reflect.Interface, reflect.Map, 477 reflect.Ptr, reflect.Slice}, 478 kind) 479 480 if isNilableKind && value.IsNil() { 481 return true 482 } 483 484 return false 485} 486 487// Nil asserts that the specified object is nil. 488// 489// assert.Nil(t, err) 490func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 491 if h, ok := t.(tHelper); ok { 492 h.Helper() 493 } 494 if isNil(object) { 495 return true 496 } 497 return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) 498} 499 500// isEmpty gets whether the specified object is considered empty or not. 501func isEmpty(object interface{}) bool { 502 503 // get nil case out of the way 504 if object == nil { 505 return true 506 } 507 508 objValue := reflect.ValueOf(object) 509 510 switch objValue.Kind() { 511 // collection types are empty when they have no element 512 case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: 513 return objValue.Len() == 0 514 // pointers are empty if nil or if the value they point to is empty 515 case reflect.Ptr: 516 if objValue.IsNil() { 517 return true 518 } 519 deref := objValue.Elem().Interface() 520 return isEmpty(deref) 521 // for all other types, compare against the zero value 522 default: 523 zero := reflect.Zero(objValue.Type()) 524 return reflect.DeepEqual(object, zero.Interface()) 525 } 526} 527 528// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either 529// a slice or a channel with len == 0. 530// 531// assert.Empty(t, obj) 532func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 533 if h, ok := t.(tHelper); ok { 534 h.Helper() 535 } 536 537 pass := isEmpty(object) 538 if !pass { 539 Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) 540 } 541 542 return pass 543 544} 545 546// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either 547// a slice or a channel with len == 0. 548// 549// if assert.NotEmpty(t, obj) { 550// assert.Equal(t, "two", obj[1]) 551// } 552func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { 553 if h, ok := t.(tHelper); ok { 554 h.Helper() 555 } 556 557 pass := !isEmpty(object) 558 if !pass { 559 Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) 560 } 561 562 return pass 563 564} 565 566// getLen try to get length of object. 567// return (false, 0) if impossible. 568func getLen(x interface{}) (ok bool, length int) { 569 v := reflect.ValueOf(x) 570 defer func() { 571 if e := recover(); e != nil { 572 ok = false 573 } 574 }() 575 return true, v.Len() 576} 577 578// Len asserts that the specified object has specific length. 579// Len also fails if the object has a type that len() not accept. 580// 581// assert.Len(t, mySlice, 3) 582func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { 583 if h, ok := t.(tHelper); ok { 584 h.Helper() 585 } 586 ok, l := getLen(object) 587 if !ok { 588 return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) 589 } 590 591 if l != length { 592 return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) 593 } 594 return true 595} 596 597// True asserts that the specified value is true. 598// 599// assert.True(t, myBool) 600func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { 601 if h, ok := t.(tHelper); ok { 602 h.Helper() 603 } 604 if h, ok := t.(interface { 605 Helper() 606 }); ok { 607 h.Helper() 608 } 609 610 if value != true { 611 return Fail(t, "Should be true", msgAndArgs...) 612 } 613 614 return true 615 616} 617 618// False asserts that the specified value is false. 619// 620// assert.False(t, myBool) 621func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { 622 if h, ok := t.(tHelper); ok { 623 h.Helper() 624 } 625 626 if value != false { 627 return Fail(t, "Should be false", msgAndArgs...) 628 } 629 630 return true 631 632} 633 634// NotEqual asserts that the specified values are NOT equal. 635// 636// assert.NotEqual(t, obj1, obj2) 637// 638// Pointer variable equality is determined based on the equality of the 639// referenced values (as opposed to the memory addresses). 640func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { 641 if h, ok := t.(tHelper); ok { 642 h.Helper() 643 } 644 if err := validateEqualArgs(expected, actual); err != nil { 645 return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", 646 expected, actual, err), msgAndArgs...) 647 } 648 649 if ObjectsAreEqual(expected, actual) { 650 return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) 651 } 652 653 return true 654 655} 656 657// containsElement try loop over the list check if the list includes the element. 658// return (false, false) if impossible. 659// return (true, false) if element was not found. 660// return (true, true) if element was found. 661func includeElement(list interface{}, element interface{}) (ok, found bool) { 662 663 listValue := reflect.ValueOf(list) 664 listKind := reflect.TypeOf(list).Kind() 665 defer func() { 666 if e := recover(); e != nil { 667 ok = false 668 found = false 669 } 670 }() 671 672 if listKind == reflect.String { 673 elementValue := reflect.ValueOf(element) 674 return true, strings.Contains(listValue.String(), elementValue.String()) 675 } 676 677 if listKind == reflect.Map { 678 mapKeys := listValue.MapKeys() 679 for i := 0; i < len(mapKeys); i++ { 680 if ObjectsAreEqual(mapKeys[i].Interface(), element) { 681 return true, true 682 } 683 } 684 return true, false 685 } 686 687 for i := 0; i < listValue.Len(); i++ { 688 if ObjectsAreEqual(listValue.Index(i).Interface(), element) { 689 return true, true 690 } 691 } 692 return true, false 693 694} 695 696// Contains asserts that the specified string, list(array, slice...) or map contains the 697// specified substring or element. 698// 699// assert.Contains(t, "Hello World", "World") 700// assert.Contains(t, ["Hello", "World"], "World") 701// assert.Contains(t, {"Hello": "World"}, "Hello") 702func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { 703 if h, ok := t.(tHelper); ok { 704 h.Helper() 705 } 706 707 ok, found := includeElement(s, contains) 708 if !ok { 709 return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) 710 } 711 if !found { 712 return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) 713 } 714 715 return true 716 717} 718 719// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the 720// specified substring or element. 721// 722// assert.NotContains(t, "Hello World", "Earth") 723// assert.NotContains(t, ["Hello", "World"], "Earth") 724// assert.NotContains(t, {"Hello": "World"}, "Earth") 725func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { 726 if h, ok := t.(tHelper); ok { 727 h.Helper() 728 } 729 730 ok, found := includeElement(s, contains) 731 if !ok { 732 return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) 733 } 734 if found { 735 return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) 736 } 737 738 return true 739 740} 741 742// Subset asserts that the specified list(array, slice...) contains all 743// elements given in the specified subset(array, slice...). 744// 745// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") 746func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { 747 if h, ok := t.(tHelper); ok { 748 h.Helper() 749 } 750 if subset == nil { 751 return true // we consider nil to be equal to the nil set 752 } 753 754 subsetValue := reflect.ValueOf(subset) 755 defer func() { 756 if e := recover(); e != nil { 757 ok = false 758 } 759 }() 760 761 listKind := reflect.TypeOf(list).Kind() 762 subsetKind := reflect.TypeOf(subset).Kind() 763 764 if listKind != reflect.Array && listKind != reflect.Slice { 765 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) 766 } 767 768 if subsetKind != reflect.Array && subsetKind != reflect.Slice { 769 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) 770 } 771 772 for i := 0; i < subsetValue.Len(); i++ { 773 element := subsetValue.Index(i).Interface() 774 ok, found := includeElement(list, element) 775 if !ok { 776 return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) 777 } 778 if !found { 779 return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...) 780 } 781 } 782 783 return true 784} 785 786// NotSubset asserts that the specified list(array, slice...) contains not all 787// elements given in the specified subset(array, slice...). 788// 789// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") 790func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { 791 if h, ok := t.(tHelper); ok { 792 h.Helper() 793 } 794 if subset == nil { 795 return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) 796 } 797 798 subsetValue := reflect.ValueOf(subset) 799 defer func() { 800 if e := recover(); e != nil { 801 ok = false 802 } 803 }() 804 805 listKind := reflect.TypeOf(list).Kind() 806 subsetKind := reflect.TypeOf(subset).Kind() 807 808 if listKind != reflect.Array && listKind != reflect.Slice { 809 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) 810 } 811 812 if subsetKind != reflect.Array && subsetKind != reflect.Slice { 813 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) 814 } 815 816 for i := 0; i < subsetValue.Len(); i++ { 817 element := subsetValue.Index(i).Interface() 818 ok, found := includeElement(list, element) 819 if !ok { 820 return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) 821 } 822 if !found { 823 return true 824 } 825 } 826 827 return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) 828} 829 830// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified 831// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, 832// the number of appearances of each of them in both lists should match. 833// 834// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) 835func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { 836 if h, ok := t.(tHelper); ok { 837 h.Helper() 838 } 839 if isEmpty(listA) && isEmpty(listB) { 840 return true 841 } 842 843 aKind := reflect.TypeOf(listA).Kind() 844 bKind := reflect.TypeOf(listB).Kind() 845 846 if aKind != reflect.Array && aKind != reflect.Slice { 847 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...) 848 } 849 850 if bKind != reflect.Array && bKind != reflect.Slice { 851 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...) 852 } 853 854 aValue := reflect.ValueOf(listA) 855 bValue := reflect.ValueOf(listB) 856 857 aLen := aValue.Len() 858 bLen := bValue.Len() 859 860 if aLen != bLen { 861 return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...) 862 } 863 864 // Mark indexes in bValue that we already used 865 visited := make([]bool, bLen) 866 for i := 0; i < aLen; i++ { 867 element := aValue.Index(i).Interface() 868 found := false 869 for j := 0; j < bLen; j++ { 870 if visited[j] { 871 continue 872 } 873 if ObjectsAreEqual(bValue.Index(j).Interface(), element) { 874 visited[j] = true 875 found = true 876 break 877 } 878 } 879 if !found { 880 return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...) 881 } 882 } 883 884 return true 885} 886 887// Condition uses a Comparison to assert a complex condition. 888func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { 889 if h, ok := t.(tHelper); ok { 890 h.Helper() 891 } 892 result := comp() 893 if !result { 894 Fail(t, "Condition failed!", msgAndArgs...) 895 } 896 return result 897} 898 899// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics 900// methods, and represents a simple func that takes no arguments, and returns nothing. 901type PanicTestFunc func() 902 903// didPanic returns true if the function passed to it panics. Otherwise, it returns false. 904func didPanic(f PanicTestFunc) (bool, interface{}) { 905 906 didPanic := false 907 var message interface{} 908 func() { 909 910 defer func() { 911 if message = recover(); message != nil { 912 didPanic = true 913 } 914 }() 915 916 // call the target function 917 f() 918 919 }() 920 921 return didPanic, message 922 923} 924 925// Panics asserts that the code inside the specified PanicTestFunc panics. 926// 927// assert.Panics(t, func(){ GoCrazy() }) 928func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { 929 if h, ok := t.(tHelper); ok { 930 h.Helper() 931 } 932 933 if funcDidPanic, panicValue := didPanic(f); !funcDidPanic { 934 return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) 935 } 936 937 return true 938} 939 940// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that 941// the recovered panic value equals the expected panic value. 942// 943// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) 944func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { 945 if h, ok := t.(tHelper); ok { 946 h.Helper() 947 } 948 949 funcDidPanic, panicValue := didPanic(f) 950 if !funcDidPanic { 951 return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) 952 } 953 if panicValue != expected { 954 return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...) 955 } 956 957 return true 958} 959 960// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. 961// 962// assert.NotPanics(t, func(){ RemainCalm() }) 963func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { 964 if h, ok := t.(tHelper); ok { 965 h.Helper() 966 } 967 968 if funcDidPanic, panicValue := didPanic(f); funcDidPanic { 969 return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v", f, panicValue), msgAndArgs...) 970 } 971 972 return true 973} 974 975// WithinDuration asserts that the two times are within duration delta of each other. 976// 977// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) 978func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { 979 if h, ok := t.(tHelper); ok { 980 h.Helper() 981 } 982 983 dt := expected.Sub(actual) 984 if dt < -delta || dt > delta { 985 return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) 986 } 987 988 return true 989} 990 991func toFloat(x interface{}) (float64, bool) { 992 var xf float64 993 xok := true 994 995 switch xn := x.(type) { 996 case uint8: 997 xf = float64(xn) 998 case uint16: 999 xf = float64(xn) 1000 case uint32: 1001 xf = float64(xn) 1002 case uint64: 1003 xf = float64(xn) 1004 case int: 1005 xf = float64(xn) 1006 case int8: 1007 xf = float64(xn) 1008 case int16: 1009 xf = float64(xn) 1010 case int32: 1011 xf = float64(xn) 1012 case int64: 1013 xf = float64(xn) 1014 case float32: 1015 xf = float64(xn) 1016 case float64: 1017 xf = float64(xn) 1018 case time.Duration: 1019 xf = float64(xn) 1020 default: 1021 xok = false 1022 } 1023 1024 return xf, xok 1025} 1026 1027// InDelta asserts that the two numerals are within delta of each other. 1028// 1029// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) 1030func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { 1031 if h, ok := t.(tHelper); ok { 1032 h.Helper() 1033 } 1034 1035 af, aok := toFloat(expected) 1036 bf, bok := toFloat(actual) 1037 1038 if !aok || !bok { 1039 return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) 1040 } 1041 1042 if math.IsNaN(af) { 1043 return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...) 1044 } 1045 1046 if math.IsNaN(bf) { 1047 return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) 1048 } 1049 1050 dt := af - bf 1051 if dt < -delta || dt > delta { 1052 return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) 1053 } 1054 1055 return true 1056} 1057 1058// InDeltaSlice is the same as InDelta, except it compares two slices. 1059func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { 1060 if h, ok := t.(tHelper); ok { 1061 h.Helper() 1062 } 1063 if expected == nil || actual == nil || 1064 reflect.TypeOf(actual).Kind() != reflect.Slice || 1065 reflect.TypeOf(expected).Kind() != reflect.Slice { 1066 return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) 1067 } 1068 1069 actualSlice := reflect.ValueOf(actual) 1070 expectedSlice := reflect.ValueOf(expected) 1071 1072 for i := 0; i < actualSlice.Len(); i++ { 1073 result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) 1074 if !result { 1075 return result 1076 } 1077 } 1078 1079 return true 1080} 1081 1082// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. 1083func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { 1084 if h, ok := t.(tHelper); ok { 1085 h.Helper() 1086 } 1087 if expected == nil || actual == nil || 1088 reflect.TypeOf(actual).Kind() != reflect.Map || 1089 reflect.TypeOf(expected).Kind() != reflect.Map { 1090 return Fail(t, "Arguments must be maps", msgAndArgs...) 1091 } 1092 1093 expectedMap := reflect.ValueOf(expected) 1094 actualMap := reflect.ValueOf(actual) 1095 1096 if expectedMap.Len() != actualMap.Len() { 1097 return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) 1098 } 1099 1100 for _, k := range expectedMap.MapKeys() { 1101 ev := expectedMap.MapIndex(k) 1102 av := actualMap.MapIndex(k) 1103 1104 if !ev.IsValid() { 1105 return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) 1106 } 1107 1108 if !av.IsValid() { 1109 return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) 1110 } 1111 1112 if !InDelta( 1113 t, 1114 ev.Interface(), 1115 av.Interface(), 1116 delta, 1117 msgAndArgs..., 1118 ) { 1119 return false 1120 } 1121 } 1122 1123 return true 1124} 1125 1126func calcRelativeError(expected, actual interface{}) (float64, error) { 1127 af, aok := toFloat(expected) 1128 if !aok { 1129 return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) 1130 } 1131 if af == 0 { 1132 return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") 1133 } 1134 bf, bok := toFloat(actual) 1135 if !bok { 1136 return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) 1137 } 1138 1139 return math.Abs(af-bf) / math.Abs(af), nil 1140} 1141 1142// InEpsilon asserts that expected and actual have a relative error less than epsilon 1143func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { 1144 if h, ok := t.(tHelper); ok { 1145 h.Helper() 1146 } 1147 actualEpsilon, err := calcRelativeError(expected, actual) 1148 if err != nil { 1149 return Fail(t, err.Error(), msgAndArgs...) 1150 } 1151 if actualEpsilon > epsilon { 1152 return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ 1153 " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) 1154 } 1155 1156 return true 1157} 1158 1159// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. 1160func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { 1161 if h, ok := t.(tHelper); ok { 1162 h.Helper() 1163 } 1164 if expected == nil || actual == nil || 1165 reflect.TypeOf(actual).Kind() != reflect.Slice || 1166 reflect.TypeOf(expected).Kind() != reflect.Slice { 1167 return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) 1168 } 1169 1170 actualSlice := reflect.ValueOf(actual) 1171 expectedSlice := reflect.ValueOf(expected) 1172 1173 for i := 0; i < actualSlice.Len(); i++ { 1174 result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) 1175 if !result { 1176 return result 1177 } 1178 } 1179 1180 return true 1181} 1182 1183/* 1184 Errors 1185*/ 1186 1187// NoError asserts that a function returned no error (i.e. `nil`). 1188// 1189// actualObj, err := SomeFunction() 1190// if assert.NoError(t, err) { 1191// assert.Equal(t, expectedObj, actualObj) 1192// } 1193func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { 1194 if h, ok := t.(tHelper); ok { 1195 h.Helper() 1196 } 1197 if err != nil { 1198 return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) 1199 } 1200 1201 return true 1202} 1203 1204// Error asserts that a function returned an error (i.e. not `nil`). 1205// 1206// actualObj, err := SomeFunction() 1207// if assert.Error(t, err) { 1208// assert.Equal(t, expectedError, err) 1209// } 1210func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { 1211 if h, ok := t.(tHelper); ok { 1212 h.Helper() 1213 } 1214 1215 if err == nil { 1216 return Fail(t, "An error is expected but got nil.", msgAndArgs...) 1217 } 1218 1219 return true 1220} 1221 1222// EqualError asserts that a function returned an error (i.e. not `nil`) 1223// and that it is equal to the provided error. 1224// 1225// actualObj, err := SomeFunction() 1226// assert.EqualError(t, err, expectedErrorString) 1227func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { 1228 if h, ok := t.(tHelper); ok { 1229 h.Helper() 1230 } 1231 if !Error(t, theError, msgAndArgs...) { 1232 return false 1233 } 1234 expected := errString 1235 actual := theError.Error() 1236 // don't need to use deep equals here, we know they are both strings 1237 if expected != actual { 1238 return Fail(t, fmt.Sprintf("Error message not equal:\n"+ 1239 "expected: %q\n"+ 1240 "actual : %q", expected, actual), msgAndArgs...) 1241 } 1242 return true 1243} 1244 1245// matchRegexp return true if a specified regexp matches a string. 1246func matchRegexp(rx interface{}, str interface{}) bool { 1247 1248 var r *regexp.Regexp 1249 if rr, ok := rx.(*regexp.Regexp); ok { 1250 r = rr 1251 } else { 1252 r = regexp.MustCompile(fmt.Sprint(rx)) 1253 } 1254 1255 return (r.FindStringIndex(fmt.Sprint(str)) != nil) 1256 1257} 1258 1259// Regexp asserts that a specified regexp matches a string. 1260// 1261// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") 1262// assert.Regexp(t, "start...$", "it's not starting") 1263func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { 1264 if h, ok := t.(tHelper); ok { 1265 h.Helper() 1266 } 1267 1268 match := matchRegexp(rx, str) 1269 1270 if !match { 1271 Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) 1272 } 1273 1274 return match 1275} 1276 1277// NotRegexp asserts that a specified regexp does not match a string. 1278// 1279// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") 1280// assert.NotRegexp(t, "^start", "it's not starting") 1281func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { 1282 if h, ok := t.(tHelper); ok { 1283 h.Helper() 1284 } 1285 match := matchRegexp(rx, str) 1286 1287 if match { 1288 Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) 1289 } 1290 1291 return !match 1292 1293} 1294 1295// Zero asserts that i is the zero value for its type. 1296func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { 1297 if h, ok := t.(tHelper); ok { 1298 h.Helper() 1299 } 1300 if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { 1301 return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) 1302 } 1303 return true 1304} 1305 1306// NotZero asserts that i is not the zero value for its type. 1307func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { 1308 if h, ok := t.(tHelper); ok { 1309 h.Helper() 1310 } 1311 if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { 1312 return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) 1313 } 1314 return true 1315} 1316 1317// FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. 1318func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { 1319 if h, ok := t.(tHelper); ok { 1320 h.Helper() 1321 } 1322 info, err := os.Lstat(path) 1323 if err != nil { 1324 if os.IsNotExist(err) { 1325 return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) 1326 } 1327 return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) 1328 } 1329 if info.IsDir() { 1330 return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) 1331 } 1332 return true 1333} 1334 1335// DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. 1336func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { 1337 if h, ok := t.(tHelper); ok { 1338 h.Helper() 1339 } 1340 info, err := os.Lstat(path) 1341 if err != nil { 1342 if os.IsNotExist(err) { 1343 return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) 1344 } 1345 return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) 1346 } 1347 if !info.IsDir() { 1348 return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) 1349 } 1350 return true 1351} 1352 1353// JSONEq asserts that two JSON strings are equivalent. 1354// 1355// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) 1356func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { 1357 if h, ok := t.(tHelper); ok { 1358 h.Helper() 1359 } 1360 var expectedJSONAsInterface, actualJSONAsInterface interface{} 1361 1362 if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { 1363 return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) 1364 } 1365 1366 if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { 1367 return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) 1368 } 1369 1370 return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) 1371} 1372 1373// YAMLEq asserts that two YAML strings are equivalent. 1374func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { 1375 if h, ok := t.(tHelper); ok { 1376 h.Helper() 1377 } 1378 var expectedYAMLAsInterface, actualYAMLAsInterface interface{} 1379 1380 if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil { 1381 return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) 1382 } 1383 1384 if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { 1385 return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) 1386 } 1387 1388 return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...) 1389} 1390 1391func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { 1392 t := reflect.TypeOf(v) 1393 k := t.Kind() 1394 1395 if k == reflect.Ptr { 1396 t = t.Elem() 1397 k = t.Kind() 1398 } 1399 return t, k 1400} 1401 1402// diff returns a diff of both values as long as both are of the same type and 1403// are a struct, map, slice, array or string. Otherwise it returns an empty string. 1404func diff(expected interface{}, actual interface{}) string { 1405 if expected == nil || actual == nil { 1406 return "" 1407 } 1408 1409 et, ek := typeAndKind(expected) 1410 at, _ := typeAndKind(actual) 1411 1412 if et != at { 1413 return "" 1414 } 1415 1416 if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { 1417 return "" 1418 } 1419 1420 var e, a string 1421 if et != reflect.TypeOf("") { 1422 e = spewConfig.Sdump(expected) 1423 a = spewConfig.Sdump(actual) 1424 } else { 1425 e = reflect.ValueOf(expected).String() 1426 a = reflect.ValueOf(actual).String() 1427 } 1428 1429 diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ 1430 A: difflib.SplitLines(e), 1431 B: difflib.SplitLines(a), 1432 FromFile: "Expected", 1433 FromDate: "", 1434 ToFile: "Actual", 1435 ToDate: "", 1436 Context: 1, 1437 }) 1438 1439 return "\n\nDiff:\n" + diff 1440} 1441 1442// validateEqualArgs checks whether provided arguments can be safely used in the 1443// Equal/NotEqual functions. 1444func validateEqualArgs(expected, actual interface{}) error { 1445 if isFunction(expected) || isFunction(actual) { 1446 return errors.New("cannot take func type as argument") 1447 } 1448 return nil 1449} 1450 1451func isFunction(arg interface{}) bool { 1452 if arg == nil { 1453 return false 1454 } 1455 return reflect.TypeOf(arg).Kind() == reflect.Func 1456} 1457 1458var spewConfig = spew.ConfigState{ 1459 Indent: " ", 1460 DisablePointerAddresses: true, 1461 DisableCapacities: true, 1462 SortKeys: true, 1463} 1464 1465type tHelper interface { 1466 Helper() 1467} 1468 1469// Eventually asserts that given condition will be met in waitFor time, 1470// periodically checking target function each tick. 1471// 1472// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) 1473func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { 1474 if h, ok := t.(tHelper); ok { 1475 h.Helper() 1476 } 1477 1478 timer := time.NewTimer(waitFor) 1479 ticker := time.NewTicker(tick) 1480 checkPassed := make(chan bool) 1481 defer timer.Stop() 1482 defer ticker.Stop() 1483 defer close(checkPassed) 1484 for { 1485 select { 1486 case <-timer.C: 1487 return Fail(t, "Condition never satisfied", msgAndArgs...) 1488 case result := <-checkPassed: 1489 if result { 1490 return true 1491 } 1492 case <-ticker.C: 1493 go func() { 1494 checkPassed <- condition() 1495 }() 1496 } 1497 } 1498} 1499