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