@@ -66,6 +66,7 @@ import (
6666 "fmt"
6767 "strconv"
6868 "testing"
69+ "time"
6970 "unsafe"
7071
7172 "github.com/go-openapi/testify/v2/internal/spew"
@@ -957,6 +958,91 @@ func addErrorDumpTests() {
957958 addDumpTest (nv , "(*" + vt + ")(<nil>)\n " )
958959}
959960
961+ type (
962+ embeddedTime struct {
963+ time.Time
964+ }
965+ embeddedTimePtr struct { // this type is an example where the unsafeReflectValue does not work well
966+ * time.Time
967+ }
968+ redeclaredTime time.Time
969+ redeclaredTimePtr * time.Time
970+ aliasedTime = time.Time
971+ )
972+
973+ func addTimeDumpTests () {
974+ ts := time .Date (2006 , time .January , 2 , 15 , 4 , 5 , 999999999 , time .UTC )
975+ alias := aliasedTime (ts ) //nolint:unconvert // we want to prove here that aliased types don't matter
976+ tsAddr := fmt .Sprintf ("%p" , & ts )
977+ es := embeddedTime {
978+ Time : ts ,
979+ }
980+ ps := embeddedTimePtr {
981+ Time : & ts ,
982+ }
983+ var tptr * time.Time
984+ panick := embeddedTimePtr {
985+ Time : nil ,
986+ }
987+ rtptr := redeclaredTimePtr (& ts )
988+ ppts := ptr (ptr (ts ))
989+ ppAddr := fmt .Sprintf ("%p" , ppts )
990+ ppIAddr := fmt .Sprintf ("%p" , * ppts )
991+
992+ addDumpTest (
993+ // simple time.Time
994+ ts ,
995+ "(time.Time) 2006-01-02 15:04:05.999999999 +0000 UTC\n " ,
996+ )
997+ addDumpTest (
998+ // aliases are ignored at runtime
999+ alias ,
1000+ "(time.Time) 2006-01-02 15:04:05.999999999 +0000 UTC\n " ,
1001+ )
1002+ addDumpTest (
1003+ // pointer to time.Time
1004+ & ts ,
1005+ "(*time.Time)(" + tsAddr + ")(2006-01-02 15:04:05.999999999 +0000 UTC)\n " ,
1006+ )
1007+ addDumpTest (
1008+ // struct with embedded time.Time
1009+ es ,
1010+ "(spew_test.embeddedTime) 2006-01-02 15:04:05.999999999 +0000 UTC\n " ,
1011+ )
1012+ addDumpTest (
1013+ // struct with embedded pointer to time.Time
1014+ ps ,
1015+ "(spew_test.embeddedTimePtr) 2006-01-02 15:04:05.999999999 +0000 UTC\n " ,
1016+ )
1017+ addDumpTest (
1018+ // nil time.Time
1019+ tptr ,
1020+ "(*time.Time)(<nil>)\n " ,
1021+ )
1022+ addDumpTest (
1023+ // **time.Time
1024+ ppts ,
1025+ "(**time.Time)(" + ppAddr + "->" + ppIAddr + ")(2006-01-02 15:04:05.999999999 +0000 UTC)\n " ,
1026+ )
1027+ addDumpTest (
1028+ panick , // this is a stringer, but the inner member that implements String() string is nil
1029+ "(spew_test.embeddedTimePtr) (PANIC=runtime error: invalid memory address or nil pointer dereference){\n Time: (*time.Time)(<nil>)\n }\n " ,
1030+ )
1031+ addDumpTest (
1032+ // redeclared type convertible to time.Time
1033+ redeclaredTime (ts ),
1034+ "(spew_test.redeclaredTime) 2006-01-02 15:04:05.999999999 +0000 UTC\n " ,
1035+ )
1036+ addDumpTest (
1037+ // redeclared type convertible to *time.Time
1038+ //
1039+ // NOTE: the information about the original (redeclared) type is lost. This is due to
1040+ // how displaying pointer type information is displayed (i.e. using v.Elem().Type()).
1041+ rtptr ,
1042+ "(*time.Time)(" + tsAddr + ")(2006-01-02 15:04:05.999999999 +0000 UTC)\n " ,
1043+ )
1044+ }
1045+
9601046// TestDump executes all of the tests described by dumpTests.
9611047func TestDump (t * testing.T ) {
9621048 // Setup tests.
@@ -979,14 +1065,15 @@ func TestDump(t *testing.T) {
9791065 addPanicDumpTests ()
9801066 addErrorDumpTests ()
9811067 addCgoDumpTests ()
1068+ addTimeDumpTests ()
9821069
9831070 t .Logf ("Running %d tests" , len (dumpTests ))
9841071 for i , test := range dumpTests {
9851072 buf := new (bytes.Buffer )
9861073 spew .Fdump (buf , test .in )
9871074 s := buf .String ()
9881075 if testFailed (s , test .wants ) {
989- t .Errorf ("Dump #%d\n got: %s %s" , i , s , stringizeWants (test .wants ))
1076+ t .Errorf ("Dump #%d\n got: %s %s" , i , s , stringizeWants (test .wants ))
9901077 continue
9911078 }
9921079 }
@@ -1041,3 +1128,8 @@ func TestDumpSortedKeys(t *testing.T) {
10411128 }
10421129
10431130}
1131+
1132+ func ptr [T any ](value T ) * T {
1133+ v := value
1134+ return & v
1135+ }
0 commit comments