github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_decoder_native_interface_test.go (about) 1 package jzon 2 3 import ( 4 "errors" 5 "io" 6 "reflect" 7 "runtime/debug" 8 "testing" 9 "unsafe" 10 11 "github.com/stretchr/testify/require" 12 ) 13 14 type testIface interface { 15 Foo() 16 } 17 18 type testIfaceImpl struct { 19 field string 20 } 21 22 func (testIfaceImpl) Foo() { 23 } 24 25 func copyValue(t *testing.T, in interface{}) (out interface{}) { 26 if in == nil { 27 return nil 28 } 29 typ := reflect.TypeOf(in) 30 switch k := typ.Kind(); k { 31 case reflect.String, 32 reflect.Int, 33 reflect.Uint8: 34 return in 35 case reflect.Map: 36 v := reflect.ValueOf(in) 37 newV := reflect.MakeMap(typ) 38 if !v.IsNil() { 39 iter := v.MapRange() 40 for iter.Next() { 41 k := copyValue(t, iter.Key().Interface()) 42 v := copyValue(t, iter.Value().Interface()) 43 newV.SetMapIndex(reflect.ValueOf(k), 44 reflect.ValueOf(v)) 45 } 46 } 47 return newV.Interface() 48 case reflect.Ptr: 49 ptrValue := reflect.ValueOf(in) 50 if ptrValue.IsNil() { 51 newV := reflect.NewAt(typ.Elem(), nil) 52 return newV.Interface() 53 } 54 elem := ptrValue.Elem() 55 copied := copyValue(t, elem.Interface()) 56 newV := reflect.New(elem.Type()) 57 if copied != nil { 58 newV.Elem().Set(reflect.ValueOf(copied)) 59 } 60 return newV.Interface() 61 case reflect.Struct: 62 oldV := reflect.ValueOf(in) 63 newV := reflect.New(typ).Elem() 64 for i := 0; i < oldV.NumField(); i++ { 65 field := oldV.Field(i) 66 if field.CanInterface() { 67 copiedV := copyValue(t, field.Interface()) 68 newV.Field(i).Set(reflect.ValueOf(copiedV)) 69 } 70 } 71 return newV.Interface() 72 case reflect.Slice: 73 v := reflect.ValueOf(in) 74 l := v.Len() 75 newV := reflect.MakeSlice(typ, l, l) 76 for i := 0; i < l; i++ { 77 copied := copyValue(t, v.Index(i).Interface()) 78 newV.Index(i).Set(reflect.ValueOf(copied)) 79 } 80 return newV.Interface() 81 case reflect.Interface: 82 v := reflect.ValueOf(in) 83 newV := reflect.New(typ) 84 if !v.IsNil() { 85 copiedV := v.Elem().Interface() 86 newV.Elem().Set(reflect.ValueOf(copiedV)) 87 } 88 return newV.Elem() 89 default: 90 t.Fatalf("%v(%s) not supported", typ, k.String()) 91 panic("should not reach here") 92 } 93 } 94 95 func TestValDecoder_Native_Interface(t *testing.T) { 96 f := func(t *testing.T, data string, ex error, p1, p2 interface{}) { 97 t.Log(">>>>> initValues >>>>>") 98 printValue(t, "p1", p1) 99 printValue(t, "p2", p2) 100 t.Log(">>>>>>>>>>>>>>>>>>>>>>") 101 checkDecodeWithStandard(t, DefaultDecoderConfig, data, ex, p1, p2) 102 t.Log("<<<<< initValues <<<<<") 103 printValue(t, "p1", p1) 104 printValue(t, "p2", p2) 105 t.Log("<<<<<<<<<<<<<<<<<<<<<<") 106 } 107 f2 := func(t *testing.T, data string, ex error, initValues ...interface{}) { 108 var v1 interface{} 109 var v2 interface{} 110 var p1 *interface{} 111 var p2 *interface{} 112 if len(initValues) != 0 { 113 if len(initValues) == 1 { 114 v1 = copyValue(t, initValues[0]) 115 v2 = copyValue(t, initValues[0]) 116 } else { 117 v1 = initValues[0] 118 v2 = initValues[1] 119 } 120 require.Equal(t, v1, v2) 121 p1 = &v1 122 p2 = &v2 123 } 124 f(t, data, ex, p1, p2) 125 } 126 f3 := func(t *testing.T, data string, ex error) { 127 f2(t, data, ex, "dummy") 128 } 129 130 // eface 131 t.Run("nil pointer", func(t *testing.T) { 132 f2(t, "null", ErrNilPointerReceiver) 133 }) 134 t.Run("eof", func(t *testing.T) { 135 f3(t, "", io.EOF) 136 }) 137 t.Run("invalid first byte", func(t *testing.T) { 138 f2(t, `+`, UnexpectedByteError{}, nil) 139 }) 140 t.Run("nil init value", func(t *testing.T) { 141 f2(t, `{"a":"b"}`, nil, nil) 142 }) 143 t.Run("nil typed pointer 1", func(t *testing.T) { 144 f2(t, `{"a":"b"}`, nil, (*int)(nil)) 145 }) 146 t.Run("nil typed pointer 2", func(t *testing.T) { 147 f2(t, `{"a":"b"}`, nil, (**int)(nil)) 148 }) 149 t.Run("nil typed pointer 3", func(t *testing.T) { 150 f2(t, `{"a":"b"}`, nil, (***int)(nil)) 151 }) 152 t.Run("non compatible value", func(t *testing.T) { 153 f2(t, `{"a":"b"}`, nil, 1) 154 }) 155 t.Run("non compatible value 2", func(t *testing.T) { 156 f2(t, `{"a":"b"}`, nil, testJSONUnmarshaler{ 157 data: "123", 158 err: errors.New("test"), 159 }, testJSONUnmarshaler{ 160 data: "123", 161 err: errors.New("test"), 162 }) 163 }) 164 t.Run("eof 2", func(t *testing.T) { 165 f2(t, ``, io.EOF, &testJSONUnmarshaler{ 166 data: "123", 167 err: errors.New("test error"), 168 }, &testJSONUnmarshaler{ 169 data: "123", 170 err: errors.New("test error"), 171 }) 172 }) 173 t.Run("non compatible value 3", func(t *testing.T) { 174 ex := errors.New("test error") 175 f2(t, `{"a":"b"}`, ex, 176 &testJSONUnmarshaler{ 177 data: "123", 178 err: ex, 179 }, &testJSONUnmarshaler{ 180 data: "123", 181 err: ex, 182 }) 183 }) 184 t.Run("null on non nil init value", func(t *testing.T) { 185 f2(t, `null`, nil, "1") 186 }) 187 t.Run("different type with non nil init value", func(t *testing.T) { 188 f2(t, `123`, nil, "1") 189 }) 190 t.Run("null with nil pointer init value", func(t *testing.T) { 191 f2(t, `null`, nil, (*int)(nil)) 192 }) 193 t.Run("null with nil pointer init value 2", func(t *testing.T) { 194 f2(t, `null`, nil, (**int)(nil)) 195 }) 196 t.Run("invalid null with non nil pointer init value", func(t *testing.T) { 197 i := 1 198 f2(t, `nul`, io.EOF, &i) 199 }) 200 t.Run("null with non nil pointer init value", func(t *testing.T) { 201 i := 1 202 f2(t, `null`, nil, &i) 203 }) 204 t.Run("non null with non nil pointer init value", func(t *testing.T) { 205 i := 1 206 f2(t, `"test"`, InvalidDigitError{}, &i) 207 }) 208 t.Run("null with pt", func(t *testing.T) { 209 var v interface{} 210 pv := &v // *interface{} 211 var ppv interface{} = &pv // **interface{} 212 f2(t, `null`, nil, ppv) 213 }) 214 t.Run("null with ptr 2", func(t *testing.T) { 215 // var v interface{} 216 // pv := &v // *interface{} 217 // var ppv interface{} = &pv // **interface{} 218 f2(t, `null`, nil, (**interface{})(nil)) 219 }) 220 t.Run("non null with ptr 2", func(t *testing.T) { 221 f2(t, `"test"`, nil, (**interface{})(nil)) 222 }) 223 t.Run("null with ptr 3-1", func(t *testing.T) { 224 var v interface{} 225 pv := &v // *interface{} 226 f2(t, `null`, nil, &pv) // **interface{} 227 }) 228 t.Run("non null with ptr 3-1", func(t *testing.T) { 229 var v interface{} 230 pv := &v // *interface{} 231 f2(t, `24`, nil, &pv) // **interface{} 232 }) 233 t.Run("null with ptr 3-2", func(t *testing.T) { 234 var v interface{} 235 pv := &v 236 ppv := &pv 237 var pppv interface{} = &ppv 238 f2(t, `null`, nil, &pppv) 239 }) 240 t.Run("non null with ptr 3-2", func(t *testing.T) { 241 var v interface{} 242 pv := &v 243 ppv := &pv 244 var pppv interface{} = &ppv 245 f2(t, `"test"`, nil, &pppv) 246 }) 247 248 // iface 249 t.Run("iface eof", func(t *testing.T) { 250 var um1 testIface 251 var um2 testIface 252 f(t, ``, io.EOF, &um1, &um2) 253 }) 254 t.Run("iface invalid null", func(t *testing.T) { 255 var um1 testIface 256 var um2 testIface 257 f(t, `nul`, io.EOF, &um1, &um2) 258 }) 259 t.Run("iface null 1", func(t *testing.T) { 260 var um1 testIface 261 var um2 testIface 262 f(t, `null`, nil, &um1, &um2) 263 }) 264 t.Run("iface null 2", func(t *testing.T) { 265 var um1 testIface = testIfaceImpl{ 266 field: "test", 267 } 268 var um2 testIface = testIfaceImpl{ 269 field: "test", 270 } 271 f(t, `null`, nil, &um1, &um2) 272 }) 273 t.Run("iface null 3", func(t *testing.T) { 274 var um1 testIface = &testIfaceImpl{ 275 field: "test", 276 } 277 var um2 testIface = &testIfaceImpl{ 278 field: "test", 279 } 280 f(t, `null`, nil, &um1, &um2) 281 }) 282 t.Run("iface not null 1", func(t *testing.T) { 283 var um1 testIface 284 var um2 testIface 285 f(t, `{}`, ErrEmptyIFace, &um1, &um2) 286 }) 287 t.Run("iface not null 2", func(t *testing.T) { 288 var um1 testIface = testIfaceImpl{ 289 field: "test", 290 } 291 var um2 testIface = testIfaceImpl{ 292 field: "test", 293 } 294 f(t, `{}`, ErrPointerReceiver, &um1, &um2) 295 }) 296 t.Run("iface not null 3", func(t *testing.T) { 297 var um1 testIface = &testIfaceImpl{ 298 field: "test", 299 } 300 var um2 testIface = &testIfaceImpl{ 301 field: "test", 302 } 303 f(t, `{}`, nil, &um1, &um2) 304 }) 305 debug.FreeOSMemory() 306 } 307 308 type testIfaceDecoder struct { 309 } 310 311 func (*testIfaceDecoder) Decode(ptr unsafe.Pointer, it *Iterator, _ *DecOpts) error { 312 o, err := it.Read() 313 if err != nil { 314 return err 315 } 316 *(*interface{})(ptr) = o 317 return nil 318 } 319 320 func TestValDecoder_Native_Interface_Loop(t *testing.T) { 321 f := func(t *testing.T, data string, ex error, p1, p2 interface{}) { 322 t.Log(">>>>> initValues >>>>>") 323 printValue(t, "p1", p1) 324 printValue(t, "p2", p2) 325 t.Log(">>>>>>>>>>>>>>>>>>>>>>") 326 checkDecodeWithStandard(t, DefaultDecoderConfig, data, ex, p1, p2) 327 t.Log("<<<<< initValues <<<<<") 328 printValue(t, "p1", p1) 329 printValue(t, "p2", p2) 330 t.Log("<<<<<<<<<<<<<<<<<<<<<<") 331 } 332 /* 333 * See comment of efaceDecoder 334 */ 335 t.Run("compatible with standard", func(t *testing.T) { 336 // we have different behavior with standard library for this test 337 skipTest(t, "eface looping") 338 var o1 interface{} 339 o1 = &o1 340 var o2 interface{} 341 o2 = &o2 342 f(t, `1`, nil, o1, o2) 343 }) 344 t.Run("loop 1", func(t *testing.T) { 345 type iface interface{} 346 var o1 iface 347 o1 = &o1 348 err := DefaultDecoderConfig.Unmarshal([]byte(`1`), o1) 349 checkError(t, ErrEfaceLooping, err) 350 }) 351 t.Run("loop 2", func(t *testing.T) { 352 // the standard lib does not deal with cross nested 353 type crossIface interface{} 354 var o1 interface{} 355 var o1o crossIface 356 o1 = &o1o 357 o1o = &o1 358 err := DefaultDecoderConfig.Unmarshal([]byte(`1`), o1) 359 checkError(t, ErrEfaceLooping, err) 360 }) 361 } 362 363 func TestValDecoder_Native_Interface_Loop_WithDecoderConfig(t *testing.T) { 364 t.Run("eface decoder", func(t *testing.T) { 365 type crossIface interface{} 366 var o1 interface{} 367 var o1o crossIface 368 o1 = &o1o 369 o1o = &o1 370 decCfg := NewDecoderConfig(&DecoderOption{ 371 ValDecoders: map[reflect.Type]ValDecoder{ 372 reflect.TypeOf((*interface{})(nil)).Elem(): (*testIfaceDecoder)(nil), 373 }, 374 }) 375 err := decCfg.Unmarshal([]byte(`"abc"`), o1) 376 require.NoError(t, err) 377 printValue(t, ">>", o1) 378 require.Equal(t, "abc", o1) 379 }) 380 t.Run("eface decoder 2", func(t *testing.T) { 381 type crossIface interface{} 382 var o1 interface{} 383 var o1o crossIface 384 o1 = &o1o 385 o1o = &o1 386 decCfg := NewDecoderConfig(&DecoderOption{ 387 ValDecoders: map[reflect.Type]ValDecoder{ 388 reflect.TypeOf((*crossIface)(nil)).Elem(): (*testIfaceDecoder)(nil), 389 }, 390 }) 391 err := decCfg.Unmarshal([]byte(`"abc"`), o1) 392 require.NoError(t, err) 393 printValue(t, ">>", o1) 394 require.Equal(t, "abc", o1o) 395 }) 396 debug.FreeOSMemory() 397 }