348 |
350 |
349 return true |
351 return true |
350 |
352 |
351 } |
353 } |
352 |
354 |
|
355 // validateEqualArgs checks whether provided arguments can be safely used in the |
|
356 // Equal/NotEqual functions. |
|
357 func 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. |
|
374 func 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. |
|
394 func 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 |
|
409 func 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 |
353 // formatUnequalValues takes two values of arbitrary types and returns string |
424 // formatUnequalValues takes two values of arbitrary types and returns string |
354 // representations appropriate to be presented to the user. |
425 // representations appropriate to be presented to the user. |
355 // |
426 // |
356 // If the values are not of like type, the returned strings will be prefixed |
427 // If the values are not of like type, the returned strings will be prefixed |
357 // with the type name, and the value will be enclosed in parenthesis similar |
428 // with the type name, and the value will be enclosed in parenthesis similar |
358 // to a type conversion in the Go grammar. |
429 // to a type conversion in the Go grammar. |
359 func formatUnequalValues(expected, actual interface{}) (e string, a string) { |
430 func formatUnequalValues(expected, actual interface{}) (e string, a string) { |
360 if reflect.TypeOf(expected) != reflect.TypeOf(actual) { |
431 if reflect.TypeOf(expected) != reflect.TypeOf(actual) { |
361 return fmt.Sprintf("%T(%#v)", expected, expected), |
432 return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)), |
362 fmt.Sprintf("%T(%#v)", actual, actual) |
433 fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual)) |
363 } |
434 } |
364 |
435 switch expected.(type) { |
365 return fmt.Sprintf("%#v", expected), |
436 case time.Duration: |
366 fmt.Sprintf("%#v", actual) |
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. |
|
446 func 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 |
367 } |
453 } |
368 |
454 |
369 // EqualValues asserts that two objects are equal or convertable to the same types |
455 // EqualValues asserts that two objects are equal or convertable to the same types |
370 // and equal. |
456 // and equal. |
371 // |
457 // |
477 |
563 |
478 switch objValue.Kind() { |
564 switch objValue.Kind() { |
479 // collection types are empty when they have no element |
565 // collection types are empty when they have no element |
480 case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: |
566 case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: |
481 return objValue.Len() == 0 |
567 return objValue.Len() == 0 |
482 // pointers are empty if nil or if the value they point to is empty |
568 // pointers are empty if nil or if the value they point to is empty |
483 case reflect.Ptr: |
569 case reflect.Ptr: |
484 if objValue.IsNil() { |
570 if objValue.IsNil() { |
485 return true |
571 return true |
486 } |
572 } |
487 deref := objValue.Elem().Interface() |
573 deref := objValue.Elem().Interface() |
488 return isEmpty(deref) |
574 return isEmpty(deref) |
489 // for all other types, compare against the zero value |
575 // for all other types, compare against the zero value |
490 default: |
576 default: |
491 zero := reflect.Zero(objValue.Type()) |
577 zero := reflect.Zero(objValue.Type()) |
492 return reflect.DeepEqual(object, zero.Interface()) |
578 return reflect.DeepEqual(object, zero.Interface()) |
493 } |
579 } |
494 } |
580 } |
496 // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either |
582 // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either |
497 // a slice or a channel with len == 0. |
583 // a slice or a channel with len == 0. |
498 // |
584 // |
499 // assert.Empty(t, obj) |
585 // assert.Empty(t, obj) |
500 func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { |
586 func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { |
501 if h, ok := t.(tHelper); ok { |
|
502 h.Helper() |
|
503 } |
|
504 |
|
505 pass := isEmpty(object) |
587 pass := isEmpty(object) |
506 if !pass { |
588 if !pass { |
|
589 if h, ok := t.(tHelper); ok { |
|
590 h.Helper() |
|
591 } |
507 Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) |
592 Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) |
508 } |
593 } |
509 |
594 |
510 return pass |
595 return pass |
511 |
596 |
516 // |
601 // |
517 // if assert.NotEmpty(t, obj) { |
602 // if assert.NotEmpty(t, obj) { |
518 // assert.Equal(t, "two", obj[1]) |
603 // assert.Equal(t, "two", obj[1]) |
519 // } |
604 // } |
520 func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { |
605 func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { |
521 if h, ok := t.(tHelper); ok { |
|
522 h.Helper() |
|
523 } |
|
524 |
|
525 pass := !isEmpty(object) |
606 pass := !isEmpty(object) |
526 if !pass { |
607 if !pass { |
|
608 if h, ok := t.(tHelper); ok { |
|
609 h.Helper() |
|
610 } |
527 Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) |
611 Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) |
528 } |
612 } |
529 |
613 |
530 return pass |
614 return pass |
531 |
615 |
618 return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) |
695 return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) |
619 } |
696 } |
620 |
697 |
621 return true |
698 return true |
622 |
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) |
|
705 func 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 |
623 } |
715 } |
624 |
716 |
625 // containsElement try loop over the list check if the list includes the element. |
717 // containsElement try loop over the list check if the list includes the element. |
626 // return (false, false) if impossible. |
718 // return (false, false) if impossible. |
627 // return (true, false) if element was not found. |
719 // return (true, false) if element was not found. |
628 // return (true, true) if element was found. |
720 // return (true, true) if element was found. |
629 func includeElement(list interface{}, element interface{}) (ok, found bool) { |
721 func includeElement(list interface{}, element interface{}) (ok, found bool) { |
630 |
722 |
631 listValue := reflect.ValueOf(list) |
723 listValue := reflect.ValueOf(list) |
632 elementValue := reflect.ValueOf(element) |
724 listKind := reflect.TypeOf(list).Kind() |
633 defer func() { |
725 defer func() { |
634 if e := recover(); e != nil { |
726 if e := recover(); e != nil { |
635 ok = false |
727 ok = false |
636 found = false |
728 found = false |
637 } |
729 } |
638 }() |
730 }() |
639 |
731 |
640 if reflect.TypeOf(list).Kind() == reflect.String { |
732 if listKind == reflect.String { |
|
733 elementValue := reflect.ValueOf(element) |
641 return true, strings.Contains(listValue.String(), elementValue.String()) |
734 return true, strings.Contains(listValue.String(), elementValue.String()) |
642 } |
735 } |
643 |
736 |
644 if reflect.TypeOf(list).Kind() == reflect.Map { |
737 if listKind == reflect.Map { |
645 mapKeys := listValue.MapKeys() |
738 mapKeys := listValue.MapKeys() |
646 for i := 0; i < len(mapKeys); i++ { |
739 for i := 0; i < len(mapKeys); i++ { |
647 if ObjectsAreEqual(mapKeys[i].Interface(), element) { |
740 if ObjectsAreEqual(mapKeys[i].Interface(), element) { |
648 return true, true |
741 return true, true |
649 } |
742 } |
805 } |
898 } |
806 if isEmpty(listA) && isEmpty(listB) { |
899 if isEmpty(listA) && isEmpty(listB) { |
807 return true |
900 return true |
808 } |
901 } |
809 |
902 |
810 aKind := reflect.TypeOf(listA).Kind() |
903 if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) { |
811 bKind := reflect.TypeOf(listB).Kind() |
904 return false |
812 |
905 } |
813 if aKind != reflect.Array && aKind != reflect.Slice { |
906 |
814 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...) |
907 extraA, extraB := diffLists(listA, listB) |
815 } |
908 |
816 |
909 if len(extraA) == 0 && len(extraB) == 0 { |
817 if bKind != reflect.Array && bKind != reflect.Slice { |
910 return true |
818 return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...) |
911 } |
819 } |
912 |
820 |
913 return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...) |
|
914 } |
|
915 |
|
916 // isList checks that the provided value is array or slice. |
|
917 func 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. |
|
929 func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) { |
821 aValue := reflect.ValueOf(listA) |
930 aValue := reflect.ValueOf(listA) |
822 bValue := reflect.ValueOf(listB) |
931 bValue := reflect.ValueOf(listB) |
823 |
932 |
824 aLen := aValue.Len() |
933 aLen := aValue.Len() |
825 bLen := bValue.Len() |
934 bLen := bValue.Len() |
826 |
|
827 if aLen != bLen { |
|
828 return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...) |
|
829 } |
|
830 |
935 |
831 // Mark indexes in bValue that we already used |
936 // Mark indexes in bValue that we already used |
832 visited := make([]bool, bLen) |
937 visited := make([]bool, bLen) |
833 for i := 0; i < aLen; i++ { |
938 for i := 0; i < aLen; i++ { |
834 element := aValue.Index(i).Interface() |
939 element := aValue.Index(i).Interface() |
842 found = true |
947 found = true |
843 break |
948 break |
844 } |
949 } |
845 } |
950 } |
846 if !found { |
951 if !found { |
847 return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...) |
952 extraA = append(extraA, element) |
848 } |
953 } |
849 } |
954 } |
850 |
955 |
851 return true |
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 |
|
966 func 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() |
852 } |
984 } |
853 |
985 |
854 // Condition uses a Comparison to assert a complex condition. |
986 // Condition uses a Comparison to assert a complex condition. |
855 func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { |
987 func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { |
856 if h, ok := t.(tHelper); ok { |
988 if h, ok := t.(tHelper); ok { |
866 // PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics |
998 // PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics |
867 // methods, and represents a simple func that takes no arguments, and returns nothing. |
999 // methods, and represents a simple func that takes no arguments, and returns nothing. |
868 type PanicTestFunc func() |
1000 type PanicTestFunc func() |
869 |
1001 |
870 // didPanic returns true if the function passed to it panics. Otherwise, it returns false. |
1002 // didPanic returns true if the function passed to it panics. Otherwise, it returns false. |
871 func didPanic(f PanicTestFunc) (bool, interface{}) { |
1003 func didPanic(f PanicTestFunc) (bool, interface{}, string) { |
872 |
1004 |
873 didPanic := false |
1005 didPanic := false |
874 var message interface{} |
1006 var message interface{} |
|
1007 var stack string |
875 func() { |
1008 func() { |
876 |
1009 |
877 defer func() { |
1010 defer func() { |
878 if message = recover(); message != nil { |
1011 if message = recover(); message != nil { |
879 didPanic = true |
1012 didPanic = true |
|
1013 stack = string(debug.Stack()) |
880 } |
1014 } |
881 }() |
1015 }() |
882 |
1016 |
883 // call the target function |
1017 // call the target function |
884 f() |
1018 f() |
885 |
1019 |
886 }() |
1020 }() |
887 |
1021 |
888 return didPanic, message |
1022 return didPanic, message, stack |
889 |
1023 |
890 } |
1024 } |
891 |
1025 |
892 // Panics asserts that the code inside the specified PanicTestFunc panics. |
1026 // Panics asserts that the code inside the specified PanicTestFunc panics. |
893 // |
1027 // |
911 func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { |
1045 func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { |
912 if h, ok := t.(tHelper); ok { |
1046 if h, ok := t.(tHelper); ok { |
913 h.Helper() |
1047 h.Helper() |
914 } |
1048 } |
915 |
1049 |
916 funcDidPanic, panicValue := didPanic(f) |
1050 funcDidPanic, panicValue, panickedStack := didPanic(f) |
917 if !funcDidPanic { |
1051 if !funcDidPanic { |
918 return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) |
1052 return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) |
919 } |
1053 } |
920 if panicValue != expected { |
1054 if panicValue != expected { |
921 return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v", f, expected, panicValue), msgAndArgs...) |
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() }) |
|
1066 func 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...) |
922 } |
1078 } |
923 |
1079 |
924 return true |
1080 return true |
925 } |
1081 } |
926 |
1082 |
1093 func calcRelativeError(expected, actual interface{}) (float64, error) { |
1251 func calcRelativeError(expected, actual interface{}) (float64, error) { |
1094 af, aok := toFloat(expected) |
1252 af, aok := toFloat(expected) |
1095 if !aok { |
1253 if !aok { |
1096 return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) |
1254 return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) |
1097 } |
1255 } |
|
1256 if math.IsNaN(af) { |
|
1257 return 0, errors.New("expected value must not be NaN") |
|
1258 } |
1098 if af == 0 { |
1259 if af == 0 { |
1099 return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") |
1260 return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") |
1100 } |
1261 } |
1101 bf, bok := toFloat(actual) |
1262 bf, bok := toFloat(actual) |
1102 if !bok { |
1263 if !bok { |
1103 return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) |
1264 return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) |
1104 } |
1265 } |
|
1266 if math.IsNaN(bf) { |
|
1267 return 0, errors.New("actual value must not be NaN") |
|
1268 } |
1105 |
1269 |
1106 return math.Abs(af-bf) / math.Abs(af), nil |
1270 return math.Abs(af-bf) / math.Abs(af), nil |
1107 } |
1271 } |
1108 |
1272 |
1109 // InEpsilon asserts that expected and actual have a relative error less than epsilon |
1273 // InEpsilon asserts that expected and actual have a relative error less than epsilon |
1110 func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { |
1274 func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { |
1111 if h, ok := t.(tHelper); ok { |
1275 if h, ok := t.(tHelper); ok { |
1112 h.Helper() |
1276 h.Helper() |
|
1277 } |
|
1278 if math.IsNaN(epsilon) { |
|
1279 return Fail(t, "epsilon must not be NaN") |
1113 } |
1280 } |
1114 actualEpsilon, err := calcRelativeError(expected, actual) |
1281 actualEpsilon, err := calcRelativeError(expected, actual) |
1115 if err != nil { |
1282 if err != nil { |
1116 return Fail(t, err.Error(), msgAndArgs...) |
1283 return Fail(t, err.Error(), msgAndArgs...) |
1117 } |
1284 } |
1156 // actualObj, err := SomeFunction() |
1323 // actualObj, err := SomeFunction() |
1157 // if assert.NoError(t, err) { |
1324 // if assert.NoError(t, err) { |
1158 // assert.Equal(t, expectedObj, actualObj) |
1325 // assert.Equal(t, expectedObj, actualObj) |
1159 // } |
1326 // } |
1160 func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { |
1327 func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { |
1161 if h, ok := t.(tHelper); ok { |
|
1162 h.Helper() |
|
1163 } |
|
1164 if err != nil { |
1328 if err != nil { |
|
1329 if h, ok := t.(tHelper); ok { |
|
1330 h.Helper() |
|
1331 } |
1165 return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) |
1332 return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) |
1166 } |
1333 } |
1167 |
1334 |
1168 return true |
1335 return true |
1169 } |
1336 } |
1297 return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) |
1464 return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) |
1298 } |
1465 } |
1299 return true |
1466 return true |
1300 } |
1467 } |
1301 |
1468 |
1302 // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. |
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. |
|
1471 func 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. |
1303 func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { |
1487 func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { |
1304 if h, ok := t.(tHelper); ok { |
1488 if h, ok := t.(tHelper); ok { |
1305 h.Helper() |
1489 h.Helper() |
1306 } |
1490 } |
1307 info, err := os.Lstat(path) |
1491 info, err := os.Lstat(path) |
1315 return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) |
1499 return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) |
1316 } |
1500 } |
1317 return true |
1501 return true |
1318 } |
1502 } |
1319 |
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. |
|
1506 func 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 |
1320 // JSONEq asserts that two JSON strings are equivalent. |
1523 // JSONEq asserts that two JSON strings are equivalent. |
1321 // |
1524 // |
1322 // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) |
1525 // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) |
1323 func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { |
1526 func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { |
1324 if h, ok := t.(tHelper); ok { |
1527 if h, ok := t.(tHelper); ok { |
1333 if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { |
1536 if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { |
1334 return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) |
1537 return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) |
1335 } |
1538 } |
1336 |
1539 |
1337 return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) |
1540 return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) |
|
1541 } |
|
1542 |
|
1543 // YAMLEq asserts that two YAML strings are equivalent. |
|
1544 func 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...) |
1338 } |
1559 } |
1339 |
1560 |
1340 func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { |
1561 func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { |
1341 t := reflect.TypeOf(v) |
1562 t := reflect.TypeOf(v) |
1342 k := t.Kind() |
1563 k := t.Kind() |
1407 var spewConfig = spew.ConfigState{ |
1619 var spewConfig = spew.ConfigState{ |
1408 Indent: " ", |
1620 Indent: " ", |
1409 DisablePointerAddresses: true, |
1621 DisablePointerAddresses: true, |
1410 DisableCapacities: true, |
1622 DisableCapacities: true, |
1411 SortKeys: true, |
1623 SortKeys: true, |
|
1624 DisableMethods: true, |
|
1625 MaxDepth: 10, |
1412 } |
1626 } |
1413 |
1627 |
1414 type tHelper interface { |
1628 type tHelper interface { |
1415 Helper() |
1629 Helper() |
1416 } |
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) |
|
1636 func 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) |
|
1669 func 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. |
|
1700 func 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. |
|
1723 func 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. |
|
1746 func 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 |
|
1762 func 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 } |