github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/standard_compatible_test.go (about) 1 package jzon 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "reflect" 8 "strings" 9 "testing" 10 "unsafe" 11 12 "github.com/stretchr/testify/require" 13 ) 14 15 var ( 16 compatibleOnError = os.Getenv("COMPATIBLE_ON_ERROR") == "1" 17 ) 18 19 func nestedArray1(count int) string { 20 return strings.Repeat(" [", count) + " [ ] " + 21 strings.Repeat("] ", count) 22 } 23 24 func nestedArray2(count int) string { 25 return strings.Repeat(" [ [ ], ", count) + " [ ] " + 26 strings.Repeat("] ", count) 27 } 28 29 func nestedArrayWithObject(count int) string { 30 return strings.Repeat(" [ { }, ", count) + " [ ] " + 31 strings.Repeat("] ", count) 32 } 33 34 func nestedObject(count int) string { 35 return strings.Repeat(` { "a" : { }, "b": `, count) + " { } " + 36 strings.Repeat("} ", count) 37 } 38 39 func nestedObjectWithArray(count int) string { 40 return strings.Repeat(` { "a" : [ ], "b": `, count) + " [ ] " + 41 strings.Repeat("} ", count) 42 } 43 44 type printValueKey struct { 45 rtype rtype 46 ptr uintptr 47 } 48 49 func (pk printValueKey) String() string { 50 return fmt.Sprintf("<%x %x>", pk.rtype, pk.ptr) 51 } 52 53 func printValue(t *testing.T, prefix string, o interface{}) { 54 prefix += " " 55 if o == nil { 56 t.Logf(prefix + "nil") 57 return 58 } 59 visited := map[printValueKey]bool{} 60 oV := reflect.ValueOf(o) 61 for indent := prefix; ; indent += " " { 62 i := oV.Interface() 63 ef := (*eface)(unsafe.Pointer(&i)) 64 vk := printValueKey{ef.rtype, uintptr(ef.data)} 65 66 k := oV.Kind() 67 t.Logf(indent+"%+v %+v %v", oV.Type(), oV, vk) 68 69 if k != reflect.Interface && k != reflect.Ptr { 70 break 71 } 72 if oV.IsNil() { 73 break 74 } 75 76 if visited[vk] { 77 t.Logf(indent + " visited...") 78 break 79 } 80 visited[vk] = true 81 82 oV = oV.Elem() 83 } 84 } 85 86 func checkDecodeWithStandard(t *testing.T, decCfg *DecoderConfig, data string, ex error, exp, got interface{}) { 87 b := []byte(data) 88 expErr := json.Unmarshal(b, exp) 89 gotErr := decCfg.Unmarshal(b, got) 90 t.Logf("\nexpErr: %+v\ngotErr: %+v", expErr, gotErr) 91 noError := expErr == nil 92 if noError { 93 printValue(t, "exp", reflect.ValueOf(exp).Elem().Interface()) 94 } 95 require.Equal(t, noError, gotErr == nil, 96 "exp %+v\ngot %+v", expErr, gotErr) 97 require.Equalf(t, noError, ex == nil, "exp err: %v\ngot err: %v", ex, gotErr) 98 if ex != nil { 99 checkError(t, ex, gotErr) 100 // if reflect.TypeOf(errors.New("")) == reflect.TypeOf(ex) { 101 // require.Equalf(t, ex, gotErr, "exp err:%v\ngot err:%v", ex, gotErr) 102 // } else { 103 // require.IsTypef(t, ex, gotErr, "exp err:%v\ngot err:%v", ex, gotErr) 104 // } 105 } 106 if !noError && !compatibleOnError { 107 return 108 } 109 if exp == nil { 110 require.Equal(t, nil, got) 111 return 112 } 113 expV := reflect.ValueOf(exp) 114 gotV := reflect.ValueOf(got) 115 if expV.IsNil() { 116 require.True(t, gotV.IsNil()) 117 return 118 } 119 expI := expV.Elem().Interface() 120 gotI := gotV.Elem().Interface() 121 printValue(t, "got", gotI) 122 require.Equalf(t, expI, gotI, "exp %+v\ngot %+v", expI, gotI) 123 } 124 125 func TestValid(t *testing.T) { 126 f := func(t *testing.T, s string) { 127 data := localStringToBytes(s) 128 require.Equal(t, json.Valid(data), Valid(data)) 129 } 130 t.Run("empty", func(t *testing.T) { 131 f(t, "") 132 }) 133 t.Run("empty object", func(t *testing.T) { 134 f(t, "{}") 135 }) 136 t.Run("data remained", func(t *testing.T) { 137 f(t, "{}1") 138 }) 139 } 140 141 func TestUnmarshal(t *testing.T) { 142 t.Run("data remained", func(t *testing.T) { 143 var i, i2 interface{} 144 checkDecodeWithStandard(t, DefaultDecoderConfig, "{}{", ErrDataRemained, &i, &i2) 145 }) 146 } 147 148 func TestMarshal(t *testing.T) { 149 b, err := Marshal("123") 150 require.NoError(t, err) 151 require.Equal(t, []byte(`"123"`), b) 152 }