github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/thrift/generic/value_test.go (about)

     1  /**
     2   * Copyright 2023 CloudWeGo Authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package generic
    18  
    19  import (
    20  	"context"
    21  	"encoding/binary"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math"
    25  	"math/rand"
    26  	"reflect"
    27  	"testing"
    28  
    29  	"github.com/cloudwego/dynamicgo/meta"
    30  	"github.com/cloudwego/dynamicgo/testdata/kitex_gen/example2"
    31  	"github.com/cloudwego/dynamicgo/testdata/sample"
    32  	"github.com/cloudwego/dynamicgo/thrift"
    33  	"github.com/stretchr/testify/assert"
    34  	"github.com/stretchr/testify/require"
    35  )
    36  
    37  const (
    38  	exampleIDLPath         = "../../testdata/idl/example2.thrift"
    39  	exampleThriftPath      = "../../testdata/data/example2.bin"
    40  	exampleSuperThriftPath = "../../testdata/data/example2super.bin"
    41  )
    42  
    43  func GetSampleTree(v Value) PathNode {
    44  	return PathNode{
    45  		Node: v.Node,
    46  		Next: []PathNode{
    47  			{
    48  				Path: NewPathFieldId(1),
    49  			},
    50  			{
    51  				Path: NewPathFieldId(3),
    52  				Next: []PathNode{
    53  					{
    54  						Path: NewPathFieldId(1),
    55  					},
    56  					{
    57  						Path: NewPathFieldId(8),
    58  					},
    59  					{
    60  						Path: NewPathFieldId(9),
    61  					},
    62  				},
    63  			},
    64  			{
    65  				Path: NewPathFieldId(255),
    66  				Next: []PathNode{
    67  					{
    68  						Path: NewPathFieldId(5),
    69  					},
    70  				},
    71  			},
    72  		},
    73  	}
    74  }
    75  
    76  func GetSampleTreeById(v Value) PathNode {
    77  	return PathNode{
    78  		Node: v.Node,
    79  		Next: []PathNode{
    80  			{
    81  				Path: NewPathFieldId(1),
    82  			},
    83  			{
    84  				Path: NewPathFieldId(3),
    85  				Next: []PathNode{
    86  					{
    87  						Path: NewPathFieldId(1),
    88  					},
    89  					{
    90  						Path: NewPathFieldId(8),
    91  					},
    92  					{
    93  						Path: NewPathFieldId(9),
    94  					},
    95  				},
    96  			},
    97  			{
    98  				Path: NewPathFieldId(255),
    99  				Next: []PathNode{
   100  					{
   101  						Path: NewPathFieldId(4),
   102  					},
   103  				},
   104  			},
   105  		},
   106  	}
   107  }
   108  
   109  func TestCount(t *testing.T) {
   110  	desc := getExampleDesc()
   111  	data := getExampleData()
   112  	fmt.Printf("data len: %d\n", len(data))
   113  	v := NewValue(desc, data)
   114  	children := make([]PathNode, 0, 4)
   115  	opts := Options{}
   116  	if err := v.Children(&children, true, &opts); err != nil {
   117  		t.Fatal(err)
   118  	}
   119  	count := 1
   120  	countHelper(&count, children)
   121  	fmt.Printf("nodes count: %d", count)
   122  }
   123  
   124  func countHelper(count *int, ps []PathNode) {
   125  	*count += len(ps)
   126  	for _, p := range ps {
   127  		countHelper(count, p.Next)
   128  	}
   129  }
   130  
   131  func getExampleDesc() *thrift.TypeDescriptor {
   132  	svc, err := thrift.NewDescritorFromPath(context.Background(), exampleIDLPath)
   133  	if err != nil {
   134  		panic(err)
   135  	}
   136  	return svc.Functions()["ExampleMethod"].Request().Struct().FieldByKey("req").Type()
   137  }
   138  
   139  func getExamplePartialDesc() *thrift.TypeDescriptor {
   140  	svc, err := thrift.NewDescritorFromPath(context.Background(), exampleIDLPath)
   141  	if err != nil {
   142  		panic(err)
   143  	}
   144  	return svc.Functions()["ExamplePartialMethod"].Request().Struct().FieldByKey("req").Type()
   145  }
   146  
   147  func getExampleData() []byte {
   148  	out, err := ioutil.ReadFile(exampleThriftPath)
   149  	if err != nil {
   150  		panic(err)
   151  	}
   152  	return out
   153  }
   154  
   155  func getExampleSuperData() []byte {
   156  	out, err := ioutil.ReadFile(exampleSuperThriftPath)
   157  	if err != nil {
   158  		panic(err)
   159  	}
   160  	return out
   161  }
   162  
   163  func empty(v interface{}) interface{} {
   164  	et := reflect.TypeOf(v)
   165  	if et.Kind() == reflect.Ptr {
   166  		et = et.Elem()
   167  	}
   168  	return reflect.New(et).Interface()
   169  }
   170  
   171  func checkHelper(t *testing.T, exp interface{}, act Node, api string) {
   172  	v := reflect.ValueOf(act)
   173  	f := v.MethodByName(api)
   174  	if f.Kind() != reflect.Func {
   175  		t.Fatalf("method %s not found", api)
   176  	}
   177  	var args []reflect.Value
   178  	if api == "List" || api == "StrMap" || api == "IntMap" || api == "Interface" {
   179  		args = make([]reflect.Value, 1)
   180  		args[0] = reflect.ValueOf(&Options{})
   181  	} else {
   182  		args = make([]reflect.Value, 0)
   183  	}
   184  	rets := f.Call(args)
   185  	if len(rets) != 2 {
   186  		t.Fatal("wrong number of return values")
   187  	}
   188  	require.Nil(t, rets[1].Interface())
   189  	switch api {
   190  	case "List":
   191  		vs := rets[0]
   192  		if vs.Kind() != reflect.Slice {
   193  			t.Fatal("wrong type")
   194  		}
   195  		es := reflect.ValueOf(exp)
   196  		if es.Kind() != reflect.Slice {
   197  			t.Fatal("wrong type")
   198  		}
   199  		for i := 0; i < vs.Len(); i++ {
   200  			vv := vs.Index(i)
   201  			require.Equal(t, cast(es.Index(i).Interface(), vv.Type().Name() == "byte"), vv.Interface())
   202  		}
   203  	case "StrMap":
   204  		vs := rets[0]
   205  		if vs.Kind() != reflect.Map {
   206  			t.Fatal("wrong type")
   207  		}
   208  		es := reflect.ValueOf(exp)
   209  		if es.Kind() != reflect.Map {
   210  			t.Fatal("wrong type")
   211  		}
   212  		ks := vs.MapKeys()
   213  		for i := 0; i < len(ks); i++ {
   214  			vv := vs.MapIndex(ks[i])
   215  			require.Equal(t, cast(es.MapIndex(ks[i]).Interface(), vv.Type().Name() == "byte"), vv.Interface())
   216  		}
   217  	default:
   218  		require.Equal(t, exp, rets[0].Interface())
   219  	}
   220  }
   221  
   222  func cast(ev interface{}, b bool) interface{} {
   223  	switch ev.(type) {
   224  	case int8:
   225  		if b {
   226  			return byte(ev.(int8))
   227  		}
   228  		return int(ev.(int8))
   229  	case int16:
   230  		return int(ev.(int16))
   231  	case int32:
   232  		return int(ev.(int32))
   233  	case int64:
   234  		return int(ev.(int64))
   235  	case float32:
   236  		return float64(ev.(float32))
   237  	default:
   238  		return ev
   239  	}
   240  }
   241  
   242  func TestGet(t *testing.T) {
   243  	desc := getExampleDesc()
   244  	data := getExampleData()
   245  
   246  	exp := example2.NewExampleReq()
   247  	v := NewValue(desc, data)
   248  	_, err := exp.FastRead(data)
   249  	require.Nil(t, err)
   250  
   251  	t.Run("GetByStr()", func(t *testing.T) {
   252  		v := v.GetByPath(PathExampleMapStringString...)
   253  		require.Nil(t, v.Check())
   254  		v1, err := v.GetByStr("b").String()
   255  		require.NoError(t, err)
   256  		require.Equal(t, sample.Example2Obj.InnerBase.MapStringString["b"], v1)
   257  		v2, err := v.GetByStr("aa").String()
   258  		require.Error(t, err)
   259  		require.Equal(t, meta.ErrNotFound, err.(Node).ErrCode())
   260  		require.Equal(t, sample.Example2Obj.InnerBase.MapStringString["aa"], v2)
   261  	})
   262  
   263  	t.Run("GetByInt()", func(t *testing.T) {
   264  		v := v.GetByPath(PathExampleMapInt32String...)
   265  		require.Nil(t, v.Check())
   266  		v1, err := v.GetByInt(1).String()
   267  		require.NoError(t, err)
   268  		require.Equal(t, sample.Example2Obj.InnerBase.MapInt32String[1], v1)
   269  		v2, err := v.GetByInt(999).String()
   270  		require.Error(t, err)
   271  		require.Equal(t, meta.ErrNotFound, err.(Node).ErrCode())
   272  		require.Equal(t, sample.Example2Obj.InnerBase.MapInt32String[999], v2)
   273  	})
   274  
   275  	t.Run("Index()", func(t *testing.T) {
   276  		v := v.GetByPath(PathExampleListInt32...)
   277  		require.Nil(t, v.Check())
   278  		v1, err := v.Index(1).Int()
   279  		require.NoError(t, err)
   280  		require.Equal(t, int(sample.Example2Obj.InnerBase.ListInt32[1]), v1)
   281  		v2 := v.Index(999)
   282  		require.Error(t, v2)
   283  		require.Equal(t, meta.ErrInvalidParam, v2.ErrCode())
   284  	})
   285  
   286  	t.Run("FieldByName()", func(t *testing.T) {
   287  		_, err := v.FieldByName("Msg2").String()
   288  		require.NotNil(t, err)
   289  		s, err := v.FieldByName("Msg").String()
   290  		require.Equal(t, *exp.Msg, s)
   291  	})
   292  
   293  	t.Run("Field()", func(t *testing.T) {
   294  		xx, err := v.Field(222).Int()
   295  		require.NotNil(t, err)
   296  		require.Equal(t, int(0), xx)
   297  		a := v.Field(3)
   298  		b, err := a.Field(1).Bool()
   299  		require.Nil(t, err)
   300  		require.Equal(t, exp.InnerBase.Bool, b)
   301  		c, err := a.Field(2).Byte()
   302  		require.Nil(t, err)
   303  		require.Equal(t, byte(exp.InnerBase.Byte), c)
   304  		d, err := a.Field(3).Int()
   305  		require.Nil(t, err)
   306  		require.Equal(t, exp.InnerBase.Int16, int16(d))
   307  		e, err := a.Field(4).Int()
   308  		require.Nil(t, err)
   309  		require.Equal(t, exp.InnerBase.Int32, int32(e))
   310  		f, err := a.Field(5).Int()
   311  		require.Nil(t, err)
   312  		require.Equal(t, exp.InnerBase.Int64, int64(f))
   313  		g, err := a.Field(6).Float64()
   314  		require.Nil(t, err)
   315  		require.Equal(t, exp.InnerBase.Double, float64(g))
   316  		h, err := a.Field(7).String()
   317  		require.Nil(t, err)
   318  		require.Equal(t, exp.InnerBase.String_, string(h))
   319  		list := a.Field(8)
   320  		checkHelper(t, exp.InnerBase.ListInt32, list.Node, "List")
   321  		list1, err := a.Field(8).Index(1).Int()
   322  		require.Nil(t, err)
   323  		require.Equal(t, exp.InnerBase.ListInt32[1], int32(list1))
   324  		mp := a.Field(9)
   325  		checkHelper(t, exp.InnerBase.MapStringString, mp.Node, "StrMap")
   326  		mp1, err := a.Field(9).GetByStr("b").String()
   327  		require.Nil(t, err)
   328  		require.Equal(t, exp.InnerBase.MapStringString["b"], (mp1))
   329  		sp := a.Field(10)
   330  		checkHelper(t, exp.InnerBase.SetInt32_, sp.Node, "List")
   331  		i, err := a.Field(11).Int()
   332  		require.Nil(t, err)
   333  		require.Equal(t, int64(exp.InnerBase.Foo), int64(i))
   334  		mp2, err := a.Field(12).GetByInt(2).String()
   335  		require.Nil(t, err)
   336  		require.Equal(t, exp.InnerBase.MapInt32String[2], (mp2))
   337  	})
   338  
   339  	t.Run("GetByPath()", func(t *testing.T) {
   340  		exp := sample.Example2Obj.InnerBase.ListInt32[1]
   341  
   342  		v1 := v.GetByPath(NewPathFieldId(thrift.FieldID(3)), NewPathFieldId(8), NewPathIndex(1))
   343  		if v1.Error() != "" {
   344  			t.Fatal(v1.Error())
   345  		}
   346  		act, err := v1.Int()
   347  		require.NoError(t, err)
   348  		require.Equal(t, int(exp), act)
   349  
   350  		v2 := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(1))
   351  		if v2.Error() != "" {
   352  			t.Fatal(v2.Error())
   353  		}
   354  		require.Equal(t, v1, v2)
   355  		v3 := v.GetByPath(NewPathFieldId(thrift.FieldID(3)), NewPathFieldName("ListInt32"), NewPathIndex(1))
   356  		if v3.Error() != "" {
   357  			t.Fatal(v3.Error())
   358  		}
   359  		require.Equal(t, v1, v3)
   360  		v4 := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldId(8), NewPathIndex(1))
   361  		if v4.Error() != "" {
   362  			t.Fatal(v4.Error())
   363  		}
   364  		require.Equal(t, v1, v4)
   365  
   366  		exp2 := sample.Example2Obj.InnerBase.MapInt32String[2]
   367  		v5 := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldId(12), NewPathIntKey(2))
   368  		if v5.Error() != "" {
   369  			t.Fatal(v5.Error())
   370  		}
   371  		act2, err := v5.String()
   372  		require.NoError(t, err)
   373  		require.Equal(t, exp2, act2)
   374  
   375  		v6 := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapInt32String"), NewPathIntKey(2))
   376  		if v6.Error() != "" {
   377  			t.Fatal(v6.Error())
   378  		}
   379  		require.Equal(t, v5, v6)
   380  
   381  		exp3 := sample.Example2Obj.InnerBase.MapStringString["b"]
   382  		v7 := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldId(9), NewPathStrKey("b"))
   383  		if v5.Error() != "" {
   384  			t.Fatal(v7.Error())
   385  		}
   386  		act3, err := v7.String()
   387  		require.NoError(t, err)
   388  		require.Equal(t, exp3, act3)
   389  
   390  		v8 := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapStringString"), NewPathStrKey("b"))
   391  		if v6.Error() != "" {
   392  			t.Fatal(v8.Error())
   393  		}
   394  		require.Equal(t, v8, v7)
   395  	})
   396  }
   397  
   398  func handlePartialMapStringString2(p map[int]interface{}) {
   399  	delete(p, 127)
   400  	if f18 := p[18]; f18 != nil {
   401  		for i := range f18.([]interface{}) {
   402  			pv := f18.([]interface{})[i].(map[int]interface{})
   403  			handlePartialMapStringString2(pv)
   404  		}
   405  	}
   406  	if f19 := p[19]; f19 != nil {
   407  		for k := range f19.(map[interface{}]interface{}) {
   408  			handlePartialMapStringString2(*(k.(*map[int]interface{})))
   409  			vv := f19.(map[interface{}]interface{})[k].(map[int]interface{})
   410  			handlePartialMapStringString2(vv)
   411  		}
   412  	}
   413  }
   414  
   415  func TestMarshalTo(t *testing.T) {
   416  	desc := getExampleDesc()
   417  	data := getExampleData()
   418  	partial := getExamplePartialDesc()
   419  
   420  	exp := example2.NewExampleReq()
   421  	v := NewValue(desc, data)
   422  	_, err := exp.FastRead(data)
   423  	require.Nil(t, err)
   424  
   425  	t.Run("ById", func(t *testing.T) {
   426  		t.Run("WriteDefault", func(t *testing.T) {
   427  			opts := &Options{WriteDefault: true}
   428  			buf, err := v.MarshalTo(partial, opts)
   429  			require.Nil(t, err)
   430  			ep := example2.NewExampleReqPartial()
   431  			_, err = ep.FastRead(buf)
   432  			require.Nil(t, err)
   433  			act := toInterface(ep)
   434  			exp := toInterface(exp)
   435  			require.False(t, DeepEqual(act, exp))
   436  			handlePartialMapStringString2(act.(map[int]interface{})[3].(map[int]interface{}))
   437  			require.True(t, DeepEqual(act, exp))
   438  			require.NotNil(t, ep.InnerBase.MapStringString2)
   439  		})
   440  		t.Run("NotWriteDefault", func(t *testing.T) {
   441  			opts := &Options{}
   442  			buf, err := v.MarshalTo(partial, opts)
   443  			require.Nil(t, err)
   444  			ep := example2.NewExampleReqPartial()
   445  			_, err = ep.FastRead(buf)
   446  			require.Nil(t, err)
   447  			act := toInterface(ep)
   448  			exp := toInterface(exp)
   449  			require.False(t, DeepEqual(act, exp))
   450  			handlePartialMapStringString2(act.(map[int]interface{})[3].(map[int]interface{}))
   451  			require.True(t, DeepEqual(act, exp))
   452  			require.Nil(t, ep.InnerBase.MapStringString2)
   453  		})
   454  	})
   455  
   456  	t.Run("unknown", func(t *testing.T) {
   457  		n := NewNode(thrift.STRUCT, data)
   458  		exist, err := n.SetByPath(NewNodeString("Insert"), NewPathFieldId(1024))
   459  		require.Nil(t, err)
   460  		require.False(t, exist)
   461  		data = n.raw()
   462  		v.Node = NewNode(thrift.STRUCT, data)
   463  		t.Run("allow unknown", func(t *testing.T) {
   464  			opts := &Options{DisallowUnknow: false}
   465  			buf, err := v.MarshalTo(partial, opts)
   466  			require.NoError(t, err)
   467  			ep := example2.NewExampleReqPartial()
   468  			_, err = ep.FastRead(buf)
   469  			require.Nil(t, err)
   470  			act := toInterface(ep)
   471  			exp := toInterface(exp)
   472  			require.False(t, DeepEqual(act, exp))
   473  			handlePartialMapStringString2(act.(map[int]interface{})[3].(map[int]interface{}))
   474  			require.True(t, DeepEqual(act, exp))
   475  		})
   476  		t.Run("disallow unknown", func(t *testing.T) {
   477  			opts := &Options{DisallowUnknow: true}
   478  			_, err := v.MarshalTo(partial, opts)
   479  			require.Error(t, err)
   480  		})
   481  	})
   482  
   483  	// t.Run("ByName", func(t *testing.T) {
   484  	// 	opts := &Options{WriteDefault: true}
   485  	// 	// opts.FieldByName = true
   486  	// 	buf, err := v.MarshalTo(partial, opts)
   487  	// 	require.Nil(t, err)
   488  	// 	ep := example2.NewExampleReqPartial()
   489  	// 	_, err = ep.FastRead(buf)
   490  	// 	require.Nil(t, err)
   491  	// 	checkHelper3(t, exp, ep)
   492  	// 	require.NotNil(t, ep.InnerBase.MapStringString2)
   493  	// })
   494  }
   495  
   496  func checkHelper3(t *testing.T, exp, act interface{}) {
   497  	ev := reflect.ValueOf(exp)
   498  	av := reflect.ValueOf(act)
   499  	if ev.Kind() != av.Kind() {
   500  		t.Fatalf("%v != %v", ev.Kind(), av.Kind())
   501  	}
   502  	if ev.Kind() == reflect.Ptr || av.Kind() == reflect.Ptr {
   503  		ev = ev.Elem()
   504  		av = av.Elem()
   505  		checkHelper3(t, ev.Interface(), av.Interface())
   506  		return
   507  	}
   508  	switch av.Kind() {
   509  	case reflect.Struct:
   510  		for i := 0; i < ev.NumField(); i++ {
   511  			ef := ev.Type().Field(i)
   512  			af := av.FieldByName(ef.Name)
   513  			if reflect.DeepEqual(af, reflect.Value{}) {
   514  				continue
   515  			}
   516  			checkHelper3(t, ev.Field(i).Interface(), af.Interface())
   517  		}
   518  	default:
   519  		assert.Equal(t, exp, act)
   520  	}
   521  }
   522  
   523  func TestSetMany(t *testing.T) {
   524  	desc := getExampleDesc()
   525  	data := getExampleData()
   526  	opts := &Options{
   527  		UseNativeSkip: true,
   528  	}
   529  
   530  	r := NewValue(desc, data)
   531  	d1 := desc.Struct().FieldByKey("Msg").Type()
   532  	d2 := desc.Struct().FieldByKey("Subfix").Type()
   533  
   534  	t.Run("insert", func(t *testing.T) {
   535  		v := r.Fork()
   536  		exp1 := int32(-1024)
   537  		n1 := NewNodeInt32(exp1)
   538  		err := v.SetMany([]PathNode{
   539  			{
   540  				Path: NewPathFieldId(2),
   541  				Node: n1,
   542  			},
   543  		}, opts)
   544  		require.Nil(t, err)
   545  		v1 := v.GetByPath(NewPathFieldName("A"))
   546  		act1, err := v1.Int()
   547  		require.NoError(t, err)
   548  		require.Equal(t, exp1, int32(act1))
   549  
   550  		exp21 := int32(math.MinInt32)
   551  		exp22 := int32(math.MaxInt32)
   552  		n21 := NewNodeInt32(exp21)
   553  		n22 := NewNodeInt32(exp22)
   554  		vv := v.GetByPath(PathExampleListInt32...)
   555  		l2, err := vv.Len()
   556  		require.NoError(t, err)
   557  		err = vv.SetMany([]PathNode{
   558  			{
   559  				Path: NewPathIndex(1024),
   560  				Node: n21,
   561  			},
   562  			{
   563  				Path: NewPathIndex(1024),
   564  				Node: n22,
   565  			},
   566  		}, opts)
   567  		require.NoError(t, err)
   568  		v21 := vv.GetByPath(NewPathIndex(0))
   569  		act21, err := v21.Int()
   570  		require.NoError(t, err)
   571  		require.Equal(t, exp21, int32(act21))
   572  		v22 := vv.GetByPath(NewPathIndex(1))
   573  		act22, err := v22.Int()
   574  		require.NoError(t, err)
   575  		require.Equal(t, exp22, int32(act22))
   576  		ll2, err := vv.Len()
   577  		require.Nil(t, err)
   578  		require.Equal(t, l2+2, ll2)
   579  	})
   580  
   581  	t.Run("replace", func(t *testing.T) {
   582  		v := r.Fork()
   583  		exp1 := "exp1"
   584  		exp2 := float64(-255.0001)
   585  		p := thrift.NewBinaryProtocolBuffer()
   586  		p.WriteString(exp1)
   587  
   588  		v1 := NewValue(d1, []byte(string(p.Buf)))
   589  		p.Buf = p.Buf[:0]
   590  		p.WriteDouble(exp2)
   591  		v2 := NewValue(d2, []byte(string(p.Buf)))
   592  		err := v.SetMany([]PathNode{
   593  			{
   594  				Path: NewPathFieldId(1),
   595  				Node: v1.Node,
   596  			},
   597  			{
   598  				Path: NewPathFieldId(32767),
   599  				Node: v2.Node,
   600  			},
   601  		}, opts)
   602  		require.Nil(t, err)
   603  
   604  		exp := example2.NewExampleReq()
   605  		if _, err := exp.FastRead(v.Raw()); err != nil {
   606  			t.Fatal(err)
   607  		}
   608  		require.Equal(t, *exp.Msg, exp1)
   609  		require.Equal(t, exp.Subfix, exp2)
   610  
   611  		vx := v.GetByPath(NewPathFieldName("Base"))
   612  		vv := vx
   613  		err = vv.SetMany([]PathNode{
   614  			{
   615  				Path: NewPathFieldId(1),
   616  				Node: v.FieldByName("Base").FieldByName("LogID").Node,
   617  			},
   618  			{
   619  				Path: NewPathFieldId(2),
   620  				Node: v.FieldByName("Base").FieldByName("Caller").Node,
   621  			},
   622  			{
   623  				Path: NewPathFieldId(3),
   624  				Node: v.FieldByName("Base").FieldByName("Addr").Node,
   625  			},
   626  			{
   627  				Path: NewPathFieldId(4),
   628  				Node: v.FieldByName("Base").FieldByName("Client").Node,
   629  			},
   630  			{
   631  				Path: NewPathFieldId(5),
   632  				Node: v.FieldByName("Base").FieldByName("TrafficEnv").Node,
   633  			},
   634  			{
   635  				Path: NewPathFieldId(6),
   636  				Node: v.FieldByName("Base").FieldByName("Extra").Node,
   637  			},
   638  		}, opts)
   639  		require.Nil(t, err)
   640  		require.Equal(t, vx.raw(), vv.raw())
   641  
   642  		inner := v.GetByPath(NewPathFieldName("InnerBase"))
   643  		p = thrift.NewBinaryProtocolBuffer()
   644  		e1 := false
   645  		p.WriteBool(e1)
   646  		v1 = NewValue(d1, []byte(string(p.Buf)))
   647  		p.Buf = p.Buf[:0]
   648  		e2 := float64(-255.0001)
   649  		p.WriteDouble(e2)
   650  		v2 = NewValue(d1, []byte(string(p.Buf)))
   651  		p.Buf = p.Buf[:0]
   652  		err = inner.SetMany([]PathNode{
   653  			{
   654  				Path: NewPathFieldId(1),
   655  				Node: v1.Node,
   656  			},
   657  			{
   658  				Path: NewPathFieldId(6),
   659  				Node: v2.Node,
   660  			},
   661  			{
   662  				Path: NewPathFieldId(255),
   663  				Node: vx.Node,
   664  			},
   665  		}, opts)
   666  		require.Nil(t, err)
   667  		// spew.Dump(inner.Raw())
   668  		expx := example2.NewInnerBase()
   669  		if _, err := expx.FastRead(inner.Raw()); err != nil {
   670  			t.Fatal(err)
   671  		}
   672  		require.Equal(t, expx.Bool, e1)
   673  		require.Equal(t, expx.Double, e2)
   674  		require.Equal(t, expx.Base, exp.Base)
   675  	})
   676  
   677  }
   678  
   679  func TestUnsetByPath(t *testing.T) {
   680  	desc := getExampleDesc()
   681  	data := getExampleData()
   682  	r := NewValue(desc, data)
   683  
   684  	v := r.Fork()
   685  	err := v.UnsetByPath()
   686  	require.Nil(t, err)
   687  	require.True(t, v.IsEmpty())
   688  
   689  	v = r.Fork()
   690  	n := v.GetByPath(NewPathFieldName("Base"), NewPathFieldName("Caller"))
   691  	require.False(t, n.IsError())
   692  	err = v.UnsetByPath(NewPathFieldName("Base"), NewPathFieldName("Caller"))
   693  	require.NoError(t, err)
   694  	n = v.GetByPath(NewPathFieldName("Base"), NewPathFieldName("Caller"))
   695  	require.True(t, n.IsErrNotFound())
   696  
   697  	v = r.Fork()
   698  	l, err := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32")).Len()
   699  	require.NoError(t, err)
   700  	n = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(l-1))
   701  	require.False(t, n.IsError())
   702  	err = v.UnsetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(l-1))
   703  	require.NoError(t, err)
   704  	n = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(l-1))
   705  	require.True(t, n.IsErrNotFound())
   706  	ll, err := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32")).Len()
   707  	require.NoError(t, err)
   708  	require.Equal(t, l-1, ll)
   709  
   710  	v = r.Fork()
   711  	l, err = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapStringString")).Len()
   712  	require.NoError(t, err)
   713  	n = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapStringString"), NewPathStrKey("a"))
   714  	require.False(t, n.IsError())
   715  	err = v.UnsetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapStringString"), NewPathStrKey("a"))
   716  	require.NoError(t, err)
   717  	n = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapStringString"), NewPathStrKey("a"))
   718  	require.True(t, n.IsErrNotFound())
   719  	ll, err = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapStringString")).Len()
   720  	require.NoError(t, err)
   721  	require.Equal(t, l-1, ll)
   722  
   723  	v = r.Fork()
   724  	l, err = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapInt32String")).Len()
   725  	require.NoError(t, err)
   726  	n = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapInt32String"), NewPathIntKey(1))
   727  	require.False(t, n.IsError())
   728  	err = v.UnsetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapInt32String"), NewPathIntKey(1))
   729  	require.NoError(t, err)
   730  	n = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapInt32String"), NewPathIntKey(1))
   731  	require.True(t, n.IsErrNotFound())
   732  	ll, err = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("MapInt32String")).Len()
   733  	require.NoError(t, err)
   734  	require.Equal(t, l-1, ll)
   735  }
   736  
   737  func TestSetByPath(t *testing.T) {
   738  	desc := getExampleDesc()
   739  	data := getExampleData()
   740  	v := NewValue(desc, data)
   741  	ds := desc.Struct().FieldByKey("Subfix").Type()
   742  	d2 := desc.Struct().FieldByKey("Base").Type().Struct().FieldByKey("Extra").Type().Elem()
   743  	d3 := desc.Struct().FieldByKey("InnerBase").Type().Struct().FieldByKey("ListInt32").Type().Elem()
   744  
   745  	e, err := v.SetByPath(v)
   746  	require.True(t, e)
   747  	require.Nil(t, err)
   748  
   749  	t.Run("replace", func(t *testing.T) {
   750  		s := v.GetByPath(NewPathFieldName("Subfix"))
   751  		require.Empty(t, s.Error())
   752  		f, _ := s.Float64()
   753  		require.Equal(t, math.MaxFloat64, f)
   754  		exp := float64(-0.1)
   755  		buf := make([]byte, 8)
   756  		binary.BigEndian.PutUint64(buf, math.Float64bits(exp))
   757  		e, err := v.SetByPath(NewValue(ds, buf), NewPathFieldName("Subfix"))
   758  		require.True(t, e)
   759  		require.Nil(t, err)
   760  		s = v.GetByPath(NewPathFieldName("Subfix"))
   761  		require.Empty(t, s.Error())
   762  		f, _ = s.Float64()
   763  		require.Equal(t, exp, f)
   764  
   765  		exp2 := "中文"
   766  		p := thrift.NewBinaryProtocolBuffer()
   767  		p.WriteString(exp2)
   768  		e, err2 := v.SetByPath(NewValue(d2, p.Buf), NewPathFieldName("Base"), NewPathFieldName("Extra"), NewPathStrKey("b"))
   769  		require.True(t, e)
   770  		require.Nil(t, err2)
   771  		s2 := v.GetByPath(NewPathFieldName("Base"), NewPathFieldName("Extra"), NewPathStrKey("b"))
   772  		require.Empty(t, s2.Error())
   773  		f2, _ := s2.String()
   774  		require.Equal(t, exp2, f2)
   775  		e, err2 = v.SetByPath(NewValue(d2, p.Buf), NewPathFieldName("Base"), NewPathFieldName("Extra"), NewPathStrKey("b"))
   776  		require.True(t, e)
   777  		require.Nil(t, err2)
   778  		s2 = v.GetByPath(NewPathFieldName("Base"), NewPathFieldName("Extra"), NewPathStrKey("b"))
   779  		require.Empty(t, s2.Error())
   780  		f2, _ = s2.String()
   781  		require.Equal(t, exp2, f2)
   782  
   783  		exp3 := int32(math.MinInt32) + 1
   784  		v3 := Value{NewNodeInt32(exp3), d3}
   785  		ps := []Path{NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(2)}
   786  		parent := v.GetByPath(ps[:len(ps)-1]...)
   787  		l3, err := parent.Len()
   788  		require.Nil(t, err)
   789  		e, err = v.SetByPath(v3, ps...)
   790  		require.True(t, e)
   791  		require.Nil(t, err)
   792  		s3 := v.GetByPath(ps...)
   793  		act3, _ := s3.Int()
   794  		require.Equal(t, exp3, int32(act3))
   795  		parent = v.GetByPath(ps[:len(ps)-1]...)
   796  		l3a, err := parent.Len()
   797  		require.Nil(t, err)
   798  		require.Equal(t, l3, l3a)
   799  	})
   800  
   801  	t.Run("insert", func(t *testing.T) {
   802  		s := v.GetByPath(NewPathFieldName("A"))
   803  		require.True(t, s.IsErrNotFound())
   804  		exp := int32(-1024)
   805  		v1 := Value{NewNodeInt32(exp), d3}
   806  		e, err := v.SetByPath(v1, NewPathFieldName("A"))
   807  		require.False(t, e)
   808  		require.Nil(t, err)
   809  		s = v.GetByPath(NewPathFieldName("A"))
   810  		require.Empty(t, s.Error())
   811  		act, _ := s.Int()
   812  		require.Equal(t, exp, int32(act))
   813  
   814  		s2 := v.GetByPath(NewPathFieldName("Base"), NewPathFieldName("Extra"), NewPathStrKey("x"))
   815  		require.True(t, s2.IsErrNotFound())
   816  		exp2 := "中文\bb"
   817  		v2 := Value{NewNodeString(exp2), d3}
   818  		e, err2 := v.SetByPath(v2, NewPathFieldName("Base"), NewPathFieldName("Extra"), NewPathStrKey("x"))
   819  		require.False(t, e)
   820  		require.Nil(t, err2)
   821  		s2 = v.GetByPath(NewPathFieldName("Base"), NewPathFieldName("Extra"), NewPathStrKey("x"))
   822  		require.Empty(t, s2.Error())
   823  		act2, _ := s2.String()
   824  		require.Equal(t, exp2, act2)
   825  
   826  		parent := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"))
   827  		l3, err := parent.Len()
   828  		require.Nil(t, err)
   829  		s3 := v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(1024))
   830  		require.True(t, s3.IsErrNotFound())
   831  		exp3 := rand.Int31()
   832  		v3 := Value{NewNodeInt32(exp3), d3}
   833  		e, err = v.SetByPath(v3, NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(1024))
   834  		require.False(t, e)
   835  		require.NoError(t, err)
   836  		s3 = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(0))
   837  		act3, _ := s3.Int()
   838  		require.Equal(t, exp3, int32(act3))
   839  		parent = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"))
   840  		l3a, err := parent.Len()
   841  		require.Nil(t, err)
   842  		require.Equal(t, l3+1, l3a)
   843  		exp3 = rand.Int31()
   844  		v3 = Value{NewNodeInt32(exp3), d3}
   845  		e, err = v.SetByPath(v3, NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(1024))
   846  		require.False(t, e)
   847  		require.NoError(t, err)
   848  		s3 = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"), NewPathIndex(0))
   849  		act3, _ = s3.Int()
   850  		require.Equal(t, exp3, int32(act3))
   851  		parent = v.GetByPath(NewPathFieldName("InnerBase"), NewPathFieldName("ListInt32"))
   852  		l3a, err = parent.Len()
   853  		require.Nil(t, err)
   854  		require.Equal(t, l3+2, l3a)
   855  	})
   856  }