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