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  }