github.com/goplusjs/reflectx@v0.5.4/method_test.go (about)

     1  package reflectx_test
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"reflect"
     7  	"strconv"
     8  	"testing"
     9  
    10  	"github.com/goplusjs/reflectx"
    11  )
    12  
    13  var (
    14  	tyByte           = reflect.TypeOf(byte('a'))
    15  	tyBool           = reflect.TypeOf(true)
    16  	tyInt            = reflect.TypeOf(0)
    17  	tyString         = reflect.TypeOf("")
    18  	tyError          = reflect.TypeOf((*error)(nil)).Elem()
    19  	tyEmptyStruct    = reflect.TypeOf((*struct{})(nil)).Elem()
    20  	tyEmptyInterface = reflect.TypeOf((*interface{})(nil)).Elem()
    21  	emtpyStruct      struct{}
    22  )
    23  
    24  type Int int
    25  
    26  func (i Int) String() string {
    27  	return fmt.Sprintf("(%v)", int(i))
    28  }
    29  
    30  func (i *Int) Set(v int) {
    31  	*(*int)(i) = v
    32  }
    33  
    34  func (i Int) Append(v ...int) int {
    35  	sum := int(i)
    36  	for _, n := range v {
    37  		sum += n
    38  	}
    39  	return sum
    40  }
    41  
    42  func TestIntMethodOf(t *testing.T) {
    43  	// Int type
    44  	var i Int
    45  	i.Set(100)
    46  	if v := fmt.Sprint(i); v != "(100)" {
    47  		t.Fatalf("String(): have %v, want (100)", v)
    48  	}
    49  	if v := i.Append(200, 300, 400); v != 1000 {
    50  		t.Fatalf("Append(): have %v, want (1000)", v)
    51  	}
    52  	// make Int type
    53  	styp := reflectx.NamedTypeOf("main", "Int", tyInt)
    54  	typ := reflectx.NewMethodSet(styp, 2, 3)
    55  	mString := reflectx.MakeMethod(
    56  		"String",
    57  		"main",
    58  		false,
    59  		reflect.FuncOf(nil, []reflect.Type{tyString}, false),
    60  		func(args []reflect.Value) []reflect.Value {
    61  			v := args[0]
    62  			info := fmt.Sprintf("(%d)", v.Int())
    63  			return []reflect.Value{reflect.ValueOf(info)}
    64  		},
    65  	)
    66  	mSet := reflectx.MakeMethod(
    67  		"Set",
    68  		"main",
    69  		true,
    70  		reflect.FuncOf([]reflect.Type{tyInt}, nil, false),
    71  		func(args []reflect.Value) (result []reflect.Value) {
    72  			v := args[0].Elem()
    73  			v.SetInt(args[1].Int())
    74  			return
    75  		},
    76  	)
    77  	mAppend := reflectx.MakeMethod(
    78  		"Append",
    79  		"main",
    80  		false,
    81  		reflect.FuncOf([]reflect.Type{reflect.SliceOf(tyInt)}, []reflect.Type{tyInt}, true),
    82  		func(args []reflect.Value) (result []reflect.Value) {
    83  			var sum int64 = args[0].Int()
    84  			for i := 0; i < args[1].Len(); i++ {
    85  				sum += args[1].Index(i).Int()
    86  			}
    87  			return []reflect.Value{reflect.ValueOf(int(sum))}
    88  		},
    89  	)
    90  	reflectx.SetMethodSet(typ, []reflectx.Method{
    91  		mString,
    92  		mSet,
    93  		mAppend,
    94  	}, true)
    95  	ptrType := reflect.PtrTo(typ)
    96  
    97  	if n := typ.NumMethod(); n != 2 {
    98  		t.Fatal("typ.NumMethod()", n)
    99  	}
   100  	if n := ptrType.NumMethod(); n != 3 {
   101  		t.Fatal("ptrTyp.NumMethod()", n)
   102  	}
   103  
   104  	x := reflect.New(typ).Elem()
   105  	x.Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100)})
   106  
   107  	// String
   108  	if v := fmt.Sprint(x); v != "(100)" {
   109  		t.Fatalf("String(): have %v, want (100)", v)
   110  	}
   111  	if v := fmt.Sprint(x.Addr()); v != "(100)" {
   112  		t.Fatalf("ptrTyp String(): have %v, want (100)", v)
   113  	}
   114  
   115  	// Append
   116  	m, _ := reflectx.MethodByName(typ, "Append")
   117  	r := m.Func.Call([]reflect.Value{x, reflect.ValueOf(200), reflect.ValueOf(300), reflect.ValueOf(400)})
   118  	if v := r[0].Int(); v != 1000 {
   119  		t.Fatalf("typ reflectx.MethodByName Append: have %v, want 1000", v)
   120  	}
   121  	r = x.MethodByName("Append").Call([]reflect.Value{reflect.ValueOf(200), reflect.ValueOf(300), reflect.ValueOf(400)})
   122  	if v := r[0].Int(); v != 1000 {
   123  		t.Fatalf("typ value.MethodByName Append: have %v, want 1000", v)
   124  	}
   125  }
   126  
   127  type IntSlice []int
   128  
   129  func (i IntSlice) String() string {
   130  	return fmt.Sprintf("{%v}%v", len(i), ([]int)(i))
   131  }
   132  
   133  func (i *IntSlice) Set(v ...int) {
   134  	*i = v
   135  }
   136  
   137  func (i IntSlice) Append(v ...int) int {
   138  	var sum int
   139  	for _, n := range i {
   140  		sum += n
   141  	}
   142  	for _, n := range v {
   143  		sum += n
   144  	}
   145  	return sum
   146  }
   147  
   148  func TestSliceMethodOf(t *testing.T) {
   149  	// IntSlice type
   150  	var i IntSlice
   151  	i.Set(100, 200, 300)
   152  	if v := i.String(); v != "{3}[100 200 300]" {
   153  		t.Fatalf("have %v, want {3}[100 200 300]", v)
   154  	}
   155  	if v := i.Append(200, 300, 400); v != 1500 {
   156  		t.Fatalf("have %v, want 1500", v)
   157  	}
   158  	// make IntSlice type
   159  	intSliceTyp := reflect.TypeOf([]int{})
   160  	styp := reflectx.NamedTypeOf("main", "IntSlice", intSliceTyp)
   161  	typ := reflectx.NewMethodSet(styp, 2, 3)
   162  	mString := reflectx.MakeMethod(
   163  		"String",
   164  		"main",
   165  		false,
   166  		reflect.FuncOf(nil, []reflect.Type{tyString}, false),
   167  		func(args []reflect.Value) []reflect.Value {
   168  			v := args[0]
   169  			info := fmt.Sprintf("{%v}%v", v.Len(), v.Convert(intSliceTyp))
   170  			return []reflect.Value{reflect.ValueOf(info)}
   171  		},
   172  	)
   173  	mSet := reflectx.MakeMethod(
   174  		"Set",
   175  		"main",
   176  		true,
   177  		reflect.FuncOf([]reflect.Type{intSliceTyp}, nil, true),
   178  		func(args []reflect.Value) (result []reflect.Value) {
   179  			v := args[0].Elem()
   180  			v.Set(args[1])
   181  			return
   182  		},
   183  	)
   184  	mAppend := reflectx.MakeMethod(
   185  		"Append",
   186  		"main",
   187  		false,
   188  		reflect.FuncOf([]reflect.Type{reflect.SliceOf(tyInt)}, []reflect.Type{tyInt}, true),
   189  		func(args []reflect.Value) (result []reflect.Value) {
   190  			var sum int64
   191  			for i := 0; i < args[0].Len(); i++ {
   192  				sum += args[0].Index(i).Int()
   193  			}
   194  			for i := 0; i < args[1].Len(); i++ {
   195  				sum += args[1].Index(i).Int()
   196  			}
   197  			return []reflect.Value{reflect.ValueOf(int(sum))}
   198  		},
   199  	)
   200  	reflectx.SetMethodSet(typ, []reflectx.Method{
   201  		mString,
   202  		mSet,
   203  		mAppend,
   204  	}, true)
   205  	ptrType := reflect.PtrTo(typ)
   206  
   207  	if n := typ.NumMethod(); n != 2 {
   208  		t.Fatal("typ.NumMethod()", n)
   209  	}
   210  	if n := ptrType.NumMethod(); n != 3 {
   211  		t.Fatal("ptrTyp.NumMethod()", n)
   212  	}
   213  
   214  	x := reflect.New(typ).Elem()
   215  	x.Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100), reflect.ValueOf(200), reflect.ValueOf(300)})
   216  
   217  	// String
   218  	if v := fmt.Sprint(x); v != "{3}[100 200 300]" {
   219  		t.Fatalf("String(): have %v, want {3}[100 200 300]", v)
   220  	}
   221  	if v := fmt.Sprint(x.Addr()); v != "{3}[100 200 300]" {
   222  		t.Fatalf("ptrTyp String(): have %v, want {3}[100 200 300]", v)
   223  	}
   224  
   225  	// Append
   226  	m, _ := reflectx.MethodByName(typ, "Append")
   227  	r := m.Func.Call([]reflect.Value{x, reflect.ValueOf(200), reflect.ValueOf(300), reflect.ValueOf(400)})
   228  	if v := r[0].Int(); v != 1500 {
   229  		t.Fatalf("typ reflectx.MethodByName Append: have %v, want 1000", v)
   230  	}
   231  	r = x.MethodByName("Append").Call([]reflect.Value{reflect.ValueOf(200), reflect.ValueOf(300), reflect.ValueOf(400)})
   232  	if v := r[0].Int(); v != 1500 {
   233  		t.Fatalf("typ value.MethodByName Append: have %v, want 1000", v)
   234  	}
   235  }
   236  
   237  type IntArray [2]int
   238  
   239  func (i IntArray) String() string {
   240  	return fmt.Sprintf("(%v,%v)", i[0], i[1])
   241  }
   242  
   243  func (i *IntArray) Set(x, y int) {
   244  	*(*int)(&i[0]), *(*int)(&i[1]) = x, y
   245  }
   246  
   247  func (i IntArray) Get() (int, int) {
   248  	return i[0], i[1]
   249  }
   250  
   251  func (i IntArray) Scale(v int) IntArray {
   252  	return IntArray{i[0] * v, i[1] * v}
   253  }
   254  
   255  func TestArrayMethodOf(t *testing.T) {
   256  	// IntArray
   257  	var i IntArray
   258  	i.Set(100, 200)
   259  	if v := fmt.Sprint(i); v != "(100,200)" {
   260  		t.Fatalf("have %v, want (100,200)", v)
   261  	}
   262  	if v1, v2 := i.Get(); v1 != 100 || v2 != 200 {
   263  		t.Fatalf("have %v %v, want 100 200)", v1, v2)
   264  	}
   265  	if v := fmt.Sprint(i.Scale(5)); v != "(500,1000)" {
   266  		t.Fatalf("have %v, want (500,1000)", v)
   267  	}
   268  	styp := reflectx.NamedTypeOf("main", "IntArray", reflect.TypeOf([2]int{}))
   269  	// make IntArray
   270  	typ := reflectx.NewMethodSet(styp, 3, 4)
   271  
   272  	mString := reflectx.MakeMethod(
   273  		"String",
   274  		"main",
   275  		false,
   276  		reflect.FuncOf(nil, []reflect.Type{tyString}, false),
   277  		func(args []reflect.Value) []reflect.Value {
   278  			v := args[0]
   279  			info := fmt.Sprintf("(%v,%v)", v.Index(0), v.Index(1))
   280  			return []reflect.Value{reflect.ValueOf(info)}
   281  		},
   282  	)
   283  	mSet := reflectx.MakeMethod(
   284  		"Set",
   285  		"main",
   286  		true,
   287  		reflect.FuncOf([]reflect.Type{tyInt, tyInt}, nil, false),
   288  		func(args []reflect.Value) (result []reflect.Value) {
   289  			v := args[0].Elem()
   290  			v.Index(0).Set(args[1])
   291  			v.Index(1).Set(args[2])
   292  			return
   293  		},
   294  	)
   295  	mGet := reflectx.MakeMethod(
   296  		"Get",
   297  		"main",
   298  		false,
   299  		reflect.FuncOf(nil, []reflect.Type{tyInt, tyInt}, false),
   300  		func(args []reflect.Value) (result []reflect.Value) {
   301  			v := args[0]
   302  			return []reflect.Value{v.Index(0), v.Index(1)}
   303  		},
   304  	)
   305  	mScale := reflectx.MakeMethod(
   306  		"Scale",
   307  		"main",
   308  		false,
   309  		reflect.FuncOf([]reflect.Type{tyInt}, []reflect.Type{typ}, false),
   310  		func(args []reflect.Value) (result []reflect.Value) {
   311  			v := args[0]
   312  			s := args[1].Int()
   313  			r := reflect.New(typ).Elem()
   314  			r.Index(0).SetInt(v.Index(0).Int() * s)
   315  			r.Index(1).SetInt(v.Index(1).Int() * s)
   316  			return []reflect.Value{r}
   317  		},
   318  	)
   319  	reflectx.SetMethodSet(typ, []reflectx.Method{
   320  		mString,
   321  		mSet,
   322  		mGet,
   323  		mScale,
   324  	}, true)
   325  	ptrType := reflect.PtrTo(typ)
   326  
   327  	if n := typ.NumMethod(); n != 3 {
   328  		t.Fatal("typ.NumMethod()", n)
   329  	}
   330  	if n := ptrType.NumMethod(); n != 4 {
   331  		t.Fatal("ptrTyp.NumMethod()", n)
   332  	}
   333  
   334  	x := reflect.New(typ).Elem()
   335  	x.Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100), reflect.ValueOf(200)})
   336  
   337  	// String
   338  	if v := fmt.Sprint(x); v != "(100,200)" {
   339  		t.Fatalf("String(): have %v, want (100,200)", v)
   340  	}
   341  	if v := fmt.Sprint(x.Addr()); v != "(100,200)" {
   342  		t.Fatalf("ptrTyp String(): have %v, want (100,200)", v)
   343  	}
   344  
   345  	// Get
   346  	m, _ := reflectx.MethodByName(typ, "Get")
   347  	r := m.Func.Call([]reflect.Value{x})
   348  	if len(r) != 2 || r[0].Int() != 100 || r[1].Int() != 200 {
   349  		t.Fatalf("typ reflectx.MethodByName Get: have %v, want 100 200", r)
   350  	}
   351  	r = x.MethodByName("Get").Call(nil)
   352  	if len(r) != 2 || r[0].Int() != 100 || r[1].Int() != 200 {
   353  		t.Fatalf("typ value.MethodByName Get: have %v, want 100 200", r)
   354  	}
   355  
   356  	// Scale
   357  	m, _ = reflectx.MethodByName(typ, "Scale")
   358  	r = m.Func.Call([]reflect.Value{x, reflect.ValueOf(5)})
   359  	if v := fmt.Sprint(r[0]); v != "(500,1000)" {
   360  		t.Fatalf("typ reflectx.MethodByName Scale: have %v, want (500,1000)", v)
   361  	}
   362  	r = x.MethodByName("Scale").Call([]reflect.Value{reflect.ValueOf(5)})
   363  	if v := fmt.Sprint((r[0])); v != "(500,1000)" {
   364  		t.Fatalf("typ value.MethodByName Scale: have %v, want (500,1000)", v)
   365  	}
   366  }
   367  
   368  type Point struct {
   369  	X int
   370  	Y int
   371  }
   372  
   373  func (i Point) String() string {
   374  	return fmt.Sprintf("(%v,%v)", i.X, i.Y)
   375  }
   376  
   377  func (i Point) Add(v Point) Point {
   378  	return Point{i.X + v.X, i.Y + v.Y}
   379  }
   380  
   381  func (i *Point) Set(x, y int) {
   382  	i.X, i.Y = x, y
   383  }
   384  
   385  func (i Point) Scale(v ...int) (ar []Point) {
   386  	for _, n := range v {
   387  		ar = append(ar, Point{i.X * n, i.Y * n})
   388  	}
   389  	return
   390  }
   391  
   392  func (i Point) New() *Point {
   393  	return &Point{i.X, i.Y}
   394  }
   395  
   396  func makeDynamicPointType() reflect.Type {
   397  	fs := []reflect.StructField{
   398  		reflect.StructField{Name: "X", Type: reflect.TypeOf(0)},
   399  		reflect.StructField{Name: "Y", Type: reflect.TypeOf(0)},
   400  	}
   401  	styp := reflectx.NamedStructOf("main", "Point", fs)
   402  	//var typ reflect.Type
   403  	typ := reflectx.NewMethodSet(styp, 4, 5)
   404  	mString := reflectx.MakeMethod(
   405  		"String",
   406  		"main",
   407  		false,
   408  		reflect.FuncOf(nil, []reflect.Type{tyString}, false),
   409  		func(args []reflect.Value) []reflect.Value {
   410  			v := args[0]
   411  			info := fmt.Sprintf("(%v,%v)", v.Field(0), v.Field(1))
   412  			return []reflect.Value{reflect.ValueOf(info)}
   413  		},
   414  	)
   415  	mAdd := reflectx.MakeMethod(
   416  		"Add",
   417  		"main",
   418  		false,
   419  		reflect.FuncOf([]reflect.Type{typ}, []reflect.Type{typ}, false),
   420  		func(args []reflect.Value) []reflect.Value {
   421  			v := reflect.New(typ).Elem()
   422  			v.Field(0).SetInt(args[0].Field(0).Int() + args[1].Field(0).Int())
   423  			v.Field(1).SetInt(args[0].Field(1).Int() + args[1].Field(1).Int())
   424  			return []reflect.Value{v}
   425  		},
   426  	)
   427  	mSet := reflectx.MakeMethod(
   428  		"Set",
   429  		"main",
   430  		true,
   431  		reflect.FuncOf([]reflect.Type{tyInt, tyInt}, nil, false),
   432  		func(args []reflect.Value) (result []reflect.Value) {
   433  			v := args[0].Elem()
   434  			v.Field(0).Set(args[1])
   435  			v.Field(1).Set(args[2])
   436  			return
   437  		},
   438  	)
   439  	mScale := reflectx.MakeMethod(
   440  		"Scale",
   441  		"main",
   442  		false,
   443  		reflect.FuncOf([]reflect.Type{reflect.SliceOf(tyInt)}, []reflect.Type{reflect.SliceOf(typ)}, true),
   444  		func(args []reflect.Value) (result []reflect.Value) {
   445  			x, y := args[0].Field(0).Int(), args[0].Field(1).Int()
   446  			r := reflect.MakeSlice(reflect.SliceOf(typ), 0, 0)
   447  			for i := 0; i < args[1].Len(); i++ {
   448  				s := args[1].Index(i).Int()
   449  				v := reflect.New(typ).Elem()
   450  				v.Field(0).SetInt(x * s)
   451  				v.Field(1).SetInt(y * s)
   452  				r = reflect.Append(r, v)
   453  			}
   454  			return []reflect.Value{r}
   455  		},
   456  	)
   457  	mNew := reflectx.MakeMethod(
   458  		"New",
   459  		"main",
   460  		false,
   461  		reflect.FuncOf(nil, []reflect.Type{reflect.PtrTo(typ)}, false),
   462  		func(args []reflect.Value) (result []reflect.Value) {
   463  			v := reflect.New(typ).Elem()
   464  			v.Field(0).SetInt(args[0].Field(0).Int())
   465  			v.Field(1).SetInt(args[0].Field(1).Int())
   466  			return []reflect.Value{v.Addr()}
   467  		},
   468  	)
   469  	reflectx.SetMethodSet(typ, []reflectx.Method{
   470  		mAdd,
   471  		mString,
   472  		mSet,
   473  		mScale,
   474  		mNew,
   475  	}, true)
   476  	return typ
   477  }
   478  
   479  func TestStructMethodOf(t *testing.T) {
   480  	// Point
   481  	var i Point
   482  	i.Set(100, 200)
   483  	if v := fmt.Sprint(i); v != "(100,200)" {
   484  		t.Fatalf("have %v, want (100,200)", v)
   485  	}
   486  	if v := fmt.Sprint(i.Add(Point{1, 2})); v != "(101,202)" {
   487  		t.Fatalf("have %v, want (101,202)", v)
   488  	}
   489  	if v := fmt.Sprint(i.Scale(2, 3, 4)); v != "[(200,400) (300,600) (400,800)]" {
   490  		t.Fatalf("have %v, want [(200,400) (300,600) (400,800)]", v)
   491  	}
   492  	if v := fmt.Sprint(i.New()); v != "(100,200)" {
   493  		t.Fatalf("have %v, want (100,200)", v)
   494  	}
   495  	// make Point
   496  	typ := makeDynamicPointType()
   497  	ptrType := reflect.PtrTo(typ)
   498  
   499  	if n := typ.NumMethod(); n != 4 {
   500  		t.Fatal("typ.NumMethod()", n)
   501  	}
   502  	if n := ptrType.NumMethod(); n != 5 {
   503  		t.Fatal("ptrTyp.NumMethod()", n)
   504  	}
   505  
   506  	pt1 := reflect.New(typ).Elem()
   507  	pt1.Field(0).SetInt(100)
   508  	pt1.Field(1).SetInt(200)
   509  
   510  	pt2 := reflect.New(typ).Elem()
   511  	pt2.Field(0).SetInt(300)
   512  	pt2.Field(1).SetInt(400)
   513  
   514  	// String
   515  	if v := fmt.Sprint(pt1); v != "(100,200)" {
   516  		t.Fatalf("String(): have %v, want (100,200)", v)
   517  	}
   518  	if v := fmt.Sprint(pt1.Addr()); v != "(100,200)" {
   519  		t.Fatalf("ptrTyp String(): have %v, want (100,200)", v)
   520  	}
   521  
   522  	// typ Add
   523  	m, _ := reflectx.MethodByName(typ, "Add")
   524  	r := m.Func.Call([]reflect.Value{pt1, pt2})
   525  	if v := fmt.Sprint(r[0]); v != "(400,600)" {
   526  		t.Fatalf("type reflectx.MethodByName Add: have %v, want (400,600)", v)
   527  	}
   528  	r = pt1.MethodByName("Add").Call([]reflect.Value{pt2})
   529  	if v := fmt.Sprint(r[0]); v != "(400,600)" {
   530  		t.Fatalf("value.MethodByName Add: have %v, want (400,600)", v)
   531  	}
   532  
   533  	// ptrtyp Add
   534  	m, _ = reflectx.MethodByName(ptrType, "Add")
   535  	r = m.Func.Call([]reflect.Value{pt1.Addr(), pt2})
   536  	if v := fmt.Sprint(r[0]); v != "(400,600)" {
   537  		t.Fatalf("ptrType reflectx.MethodByName Add: have %v, want (400,600)", v)
   538  	}
   539  	r = pt1.Addr().MethodByName("Add").Call([]reflect.Value{pt2})
   540  	if v := fmt.Sprint(r[0]); v != "(400,600)" {
   541  		t.Fatalf("ptrType value.reflectx.MethodByName Add: have %v, want (400,600)", v)
   542  	}
   543  
   544  	// Set
   545  	m, _ = reflectx.MethodByName(ptrType, "Set")
   546  	m.Func.Call([]reflect.Value{pt1.Addr(), reflect.ValueOf(-100), reflect.ValueOf(-200)})
   547  	if v := fmt.Sprint(pt1); v != "(-100,-200)" {
   548  		t.Fatalf("ptrType reflectx.MethodByName Set: have %v, want (-100,-200)", v)
   549  	}
   550  	pt1.Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100), reflect.ValueOf(200)})
   551  	if v := fmt.Sprint(pt1); v != "(100,200)" {
   552  		t.Fatalf("ptrType reflectx.MethodByName Set: have %v, want (100,200)", v)
   553  	}
   554  
   555  	// Scale
   556  	m, _ = reflectx.MethodByName(typ, "Scale")
   557  	r = m.Func.Call([]reflect.Value{pt1, reflect.ValueOf(2), reflect.ValueOf(3), reflect.ValueOf(4)})
   558  	if v := fmt.Sprint(v2is(r[0])); v != "[(200,400) (300,600) (400,800)]" {
   559  		t.Fatalf("have %v, want [(200,400) (300,600) (400,800)]", v)
   560  	}
   561  	r = pt1.MethodByName("Scale").Call([]reflect.Value{reflect.ValueOf(2), reflect.ValueOf(3), reflect.ValueOf(4)})
   562  	if v := fmt.Sprint(v2is(r[0])); v != "[(200,400) (300,600) (400,800)]" {
   563  		t.Fatalf("have %v, want [(200,400) (300,600) (400,800)]", v)
   564  	}
   565  
   566  	// New
   567  	m, _ = reflectx.MethodByName(typ, "New")
   568  	r = m.Func.Call([]reflect.Value{pt1})
   569  	if v := fmt.Sprint(r[0]); v != "(100,200)" {
   570  		t.Fatalf("have %v, want (100,200)", v)
   571  	}
   572  	r = pt1.MethodByName("New").Call(nil)
   573  	if v := fmt.Sprint(r[0]); v != "(100,200)" {
   574  		t.Fatalf("have %v, want (100,200)", v)
   575  	}
   576  }
   577  
   578  func v2is(v reflect.Value) (is []interface{}) {
   579  	for i := 0; i < v.Len(); i++ {
   580  		is = append(is, v.Index(i).Interface())
   581  	}
   582  	return is
   583  }
   584  
   585  type testMethodStack struct {
   586  	name    string
   587  	pkgpath string
   588  	mtyp    reflect.Type
   589  	fun     func([]reflect.Value) []reflect.Value
   590  	args    []reflect.Value
   591  	result  []reflect.Value
   592  	pointer bool
   593  }
   594  
   595  var (
   596  	testMethodStacks = []testMethodStack{
   597  		testMethodStack{
   598  			"Empty",
   599  			"main",
   600  			reflect.FuncOf(nil, nil, false),
   601  			func(args []reflect.Value) []reflect.Value {
   602  				if len(args) != 1 {
   603  					panic(fmt.Errorf("args have %v, want nil", args[1:]))
   604  				}
   605  				return nil
   606  			},
   607  			nil,
   608  			nil,
   609  			false,
   610  		},
   611  		testMethodStack{
   612  			"Empty Struct",
   613  			"main",
   614  			reflect.FuncOf([]reflect.Type{tyEmptyStruct}, []reflect.Type{tyEmptyStruct}, false),
   615  			func(args []reflect.Value) []reflect.Value {
   616  				return []reflect.Value{args[1]}
   617  			},
   618  			[]reflect.Value{reflect.ValueOf(emtpyStruct)},
   619  			[]reflect.Value{reflect.ValueOf(emtpyStruct)},
   620  			false,
   621  		},
   622  		testMethodStack{
   623  			"Empty Struct2",
   624  			"main",
   625  			reflect.FuncOf([]reflect.Type{tyEmptyStruct, tyInt, tyEmptyStruct}, []reflect.Type{tyEmptyStruct, tyInt, tyEmptyStruct}, false),
   626  			func(args []reflect.Value) []reflect.Value {
   627  				return []reflect.Value{args[1], args[2], args[3]}
   628  			},
   629  			[]reflect.Value{reflect.ValueOf(emtpyStruct), reflect.ValueOf(100), reflect.ValueOf(emtpyStruct)},
   630  			[]reflect.Value{reflect.ValueOf(emtpyStruct), reflect.ValueOf(100), reflect.ValueOf(emtpyStruct)},
   631  			false,
   632  		},
   633  		testMethodStack{
   634  			"Empty Struct3",
   635  			"main",
   636  			reflect.FuncOf([]reflect.Type{tyEmptyStruct, tyEmptyStruct, tyInt, tyEmptyStruct}, []reflect.Type{tyInt}, false),
   637  			func(args []reflect.Value) []reflect.Value {
   638  				return []reflect.Value{args[3]}
   639  			},
   640  			[]reflect.Value{reflect.ValueOf(emtpyStruct), reflect.ValueOf(emtpyStruct), reflect.ValueOf(100), reflect.ValueOf(emtpyStruct)},
   641  			[]reflect.Value{reflect.ValueOf(100)},
   642  			false,
   643  		},
   644  		testMethodStack{
   645  			"Empty Struct4",
   646  			"main",
   647  			reflect.FuncOf([]reflect.Type{tyEmptyStruct, tyEmptyStruct, tyInt, tyEmptyStruct}, []reflect.Type{tyEmptyStruct, tyEmptyStruct, tyEmptyStruct, tyBool}, false),
   648  			func(args []reflect.Value) []reflect.Value {
   649  				return []reflect.Value{reflect.ValueOf(emtpyStruct), reflect.ValueOf(emtpyStruct), reflect.ValueOf(emtpyStruct), reflect.ValueOf(true)}
   650  			},
   651  			[]reflect.Value{reflect.ValueOf(emtpyStruct), reflect.ValueOf(emtpyStruct), reflect.ValueOf(100), reflect.ValueOf(emtpyStruct)},
   652  			[]reflect.Value{reflect.ValueOf(emtpyStruct), reflect.ValueOf(emtpyStruct), reflect.ValueOf(emtpyStruct), reflect.ValueOf(true)},
   653  			false,
   654  		},
   655  		testMethodStack{
   656  			"Bool_Nil",
   657  			"main",
   658  			reflect.FuncOf([]reflect.Type{tyBool}, nil, false),
   659  			func(args []reflect.Value) []reflect.Value {
   660  				return nil
   661  			},
   662  			[]reflect.Value{reflect.ValueOf(true)},
   663  			nil,
   664  			false,
   665  		},
   666  		testMethodStack{
   667  			"Bool_Bool",
   668  			"main",
   669  			reflect.FuncOf([]reflect.Type{tyBool}, []reflect.Type{tyBool}, false),
   670  			func(args []reflect.Value) []reflect.Value {
   671  				return []reflect.Value{args[1]}
   672  			},
   673  			[]reflect.Value{reflect.ValueOf(true)},
   674  			[]reflect.Value{reflect.ValueOf(true)},
   675  			false,
   676  		},
   677  		testMethodStack{
   678  			"Int_Int",
   679  			"main",
   680  			reflect.FuncOf([]reflect.Type{tyInt}, []reflect.Type{tyInt}, false),
   681  			func(args []reflect.Value) []reflect.Value {
   682  				v := 300 + args[1].Int()
   683  				return []reflect.Value{reflect.ValueOf(int(v))}
   684  			},
   685  			[]reflect.Value{reflect.ValueOf(-200)},
   686  			[]reflect.Value{reflect.ValueOf(100)},
   687  			false,
   688  		},
   689  		testMethodStack{
   690  			"Big Bytes_ByteInt",
   691  			"main",
   692  			reflect.FuncOf([]reflect.Type{reflect.TypeOf([4096]byte{})}, []reflect.Type{tyByte, tyInt, tyByte}, false),
   693  			func(args []reflect.Value) []reflect.Value {
   694  				return []reflect.Value{args[1].Index(1), reflect.ValueOf(args[1].Len()), args[1].Index(3)}
   695  			},
   696  			[]reflect.Value{reflect.ValueOf([4096]byte{'a', 'b', 'c', 'd', 'e'})},
   697  			[]reflect.Value{reflect.ValueOf('b'), reflect.ValueOf(4096), reflect.ValueOf('d')},
   698  			true,
   699  		},
   700  	}
   701  )
   702  
   703  func TestMethodStack(t *testing.T) {
   704  	// make Point
   705  	fs := []reflect.StructField{
   706  		reflect.StructField{Name: "X", Type: reflect.TypeOf(0)},
   707  		reflect.StructField{Name: "Y", Type: reflect.TypeOf(0)},
   708  	}
   709  	styp := reflectx.NamedStructOf("main", "Point", fs)
   710  	typ := reflectx.NewMethodSet(styp, len(testMethodStacks), len(testMethodStacks))
   711  	var methods []reflectx.Method
   712  	for _, m := range testMethodStacks {
   713  		mm := reflectx.MakeMethod(
   714  			m.name,
   715  			m.pkgpath,
   716  			m.pointer,
   717  			m.mtyp,
   718  			m.fun,
   719  		)
   720  		methods = append(methods, mm)
   721  	}
   722  	reflectx.SetMethodSet(typ, methods, true)
   723  	v := reflect.New(typ).Elem()
   724  	v.Field(0).SetInt(100)
   725  	v.Field(1).SetInt(200)
   726  	for _, m := range testMethodStacks {
   727  		var r []reflect.Value
   728  		if m.pointer {
   729  			r = v.Addr().MethodByName(m.name).Call(m.args)
   730  		} else {
   731  			r = v.MethodByName(m.name).Call(m.args)
   732  		}
   733  		if len(r) != len(m.result) {
   734  			t.Fatalf("failed %v %v, have %v want %v", m.name, m.mtyp, r, m.result)
   735  		}
   736  		for i := 0; i < len(r); i++ {
   737  			if fmt.Sprint(r[i]) != fmt.Sprint(m.result[i]) {
   738  				t.Fatalf("failed %v, have %v want %v", m.name, r[i], m.result[i])
   739  			}
   740  		}
   741  	}
   742  }
   743  
   744  func checkInterface(t *testing.T, typ, styp reflect.Type) {
   745  	if typ.NumMethod() != styp.NumMethod() {
   746  		t.Errorf("num method: have %v, want %v", typ.NumMethod(), styp.NumMethod())
   747  	}
   748  	for i := 0; i < typ.NumMethod(); i++ {
   749  		if typ.Method(i) != styp.Method(i) {
   750  			t.Errorf("method: have %v, want %v", typ.Method(i), styp.Method(i))
   751  		}
   752  	}
   753  	if !typ.ConvertibleTo(styp) {
   754  		t.Errorf("%v cannot ConvertibleTo %v", typ, styp)
   755  	}
   756  	if !styp.ConvertibleTo(typ) {
   757  		t.Errorf("%v cannot ConvertibleTo %v", styp, typ)
   758  	}
   759  }
   760  
   761  func TestInterfaceOf(t *testing.T) {
   762  	ms := []reflect.Method{
   763  		reflect.Method{
   764  			Name: "String",
   765  			Type: reflect.FuncOf(nil, []reflect.Type{tyString}, false),
   766  		},
   767  		reflect.Method{
   768  			Name: "Test",
   769  			Type: reflect.FuncOf(nil, []reflect.Type{tyBool}, false),
   770  		},
   771  	}
   772  	typ1 := reflectx.InterfaceOf(nil, ms)
   773  	typ2 := reflectx.InterfaceOf(nil, ms)
   774  	if typ1 != typ2 {
   775  		t.Fatalf("different type: %v %v", typ1, typ2)
   776  	}
   777  }
   778  
   779  func TestNamedInterfaceOf(t *testing.T) {
   780  	pkgpath := "github.com/goplus/reflectx"
   781  	typ := reflectx.NamedInterfaceOf(pkgpath, "Stringer", nil,
   782  		[]reflect.Method{
   783  			reflect.Method{
   784  				Name: "String",
   785  				Type: reflect.FuncOf(nil, []reflect.Type{tyString}, false),
   786  			},
   787  		},
   788  	)
   789  	checkInterface(t, typ, reflect.TypeOf((*fmt.Stringer)(nil)).Elem())
   790  
   791  	typ = reflectx.NamedInterfaceOf(pkgpath, "ReadWriteCloser",
   792  		[]reflect.Type{
   793  			reflect.TypeOf((*io.Reader)(nil)).Elem(),
   794  			reflect.TypeOf((*io.Writer)(nil)).Elem(),
   795  		},
   796  		[]reflect.Method{
   797  			reflect.Method{
   798  				Name: "Close",
   799  				Type: reflect.FuncOf(nil, []reflect.Type{tyError}, false),
   800  			},
   801  		},
   802  	)
   803  	checkInterface(t, typ, reflect.TypeOf((*io.ReadWriteCloser)(nil)).Elem())
   804  }
   805  
   806  func TestNamedInterfaceOf2(t *testing.T) {
   807  	pkgpath := "github.com/goplus/reflectx"
   808  	typ := reflectx.NewInterfaceType(pkgpath, "Stringer")
   809  	reflectx.SetInterfaceType(typ, nil,
   810  		[]reflect.Method{
   811  			reflect.Method{
   812  				Name: "String",
   813  				Type: reflect.FuncOf(nil, []reflect.Type{tyString}, false),
   814  			},
   815  		},
   816  	)
   817  	checkInterface(t, typ, reflect.TypeOf((*fmt.Stringer)(nil)).Elem())
   818  
   819  	typ = reflectx.NewInterfaceType(pkgpath, "ReadWriteCloser")
   820  	reflectx.SetInterfaceType(typ,
   821  		[]reflect.Type{
   822  			reflect.TypeOf((*io.Reader)(nil)).Elem(),
   823  			reflect.TypeOf((*io.Writer)(nil)).Elem(),
   824  		},
   825  		[]reflect.Method{
   826  			reflect.Method{
   827  				Name: "Close",
   828  				Type: reflect.FuncOf(nil, []reflect.Type{tyError}, false),
   829  			},
   830  		},
   831  	)
   832  	checkInterface(t, typ, reflect.TypeOf((*io.ReadWriteCloser)(nil)).Elem())
   833  }
   834  
   835  type MyPoint1 struct {
   836  	Point
   837  }
   838  
   839  type MyPoint2 struct {
   840  	*Point
   841  }
   842  
   843  type Setter interface {
   844  	Set(x int, y int)
   845  	String() string
   846  }
   847  
   848  type MyPoint3 struct {
   849  	Setter
   850  }
   851  
   852  type MyPoint4 struct {
   853  	*Point
   854  	index int
   855  }
   856  
   857  func (s *MyPoint4) SetIndex(n int) {
   858  	s.index = n
   859  }
   860  
   861  func (s MyPoint4) Index() int {
   862  	return s.index
   863  }
   864  
   865  func (s MyPoint4) String() string {
   866  	return fmt.Sprintf("%v#%v", s.index, s.Point)
   867  }
   868  
   869  func makeDynamicSetterType() reflect.Type {
   870  	return reflectx.NamedInterfaceOf("main", "Setter", nil,
   871  		[]reflect.Method{
   872  			reflect.Method{
   873  				Name: "Set",
   874  				Type: reflect.FuncOf([]reflect.Type{tyInt, tyInt}, nil, false),
   875  			},
   876  			reflect.Method{
   877  				Name: "String",
   878  				Type: reflect.FuncOf(nil, []reflect.Type{tyString}, false),
   879  			},
   880  		},
   881  	)
   882  }
   883  
   884  func TestEmbedMethods1(t *testing.T) {
   885  	// MyPoint1
   886  	typ := reflect.TypeOf((*MyPoint1)(nil)).Elem()
   887  	if v := typ.NumMethod(); v != 4 {
   888  		t.Fatalf("NumMethod have %v want 4", v)
   889  	}
   890  	if v := reflect.PtrTo(typ).NumMethod(); v != 5 {
   891  		t.Fatalf("NumMethod have %v want 5", v)
   892  	}
   893  	fnTest := func(t *testing.T, tyPoint reflect.Type) {
   894  		fs := []reflect.StructField{
   895  			reflect.StructField{
   896  				Name:      "Point",
   897  				Type:      tyPoint,
   898  				Anonymous: true,
   899  			},
   900  		}
   901  		typ := reflectx.NamedStructOf("main", "MyPoint1", fs)
   902  		typ = reflectx.StructToMethodSet(typ)
   903  		if v := typ.NumMethod(); v != 4 {
   904  			t.Errorf("NumMethod have %v want 4", v)
   905  		}
   906  		if v := reflect.PtrTo(typ).NumMethod(); v != 5 {
   907  			t.Errorf("NumMethod have %v want 5", v)
   908  		}
   909  		m := reflect.New(typ).Elem()
   910  		m.Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100), reflect.ValueOf(200)})
   911  		if v := fmt.Sprint(m); v != "(100,200)" {
   912  			t.Errorf("have %v want (100,200)", v)
   913  		}
   914  		if v := fmt.Sprint(m.Addr()); v != "(100,200)" {
   915  			t.Errorf("have %v want (100,200)", v)
   916  		}
   917  		m.Field(0).Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(-100), reflect.ValueOf(-200)})
   918  		if v := fmt.Sprint(m.Field(0)); v != "(-100,-200)" {
   919  			t.Errorf("have %v want (-100,-200)", v)
   920  		}
   921  		if v := fmt.Sprint(m.Field(0).Addr()); v != "(-100,-200)" {
   922  			t.Errorf("have %v want (-100,-200)", v)
   923  		}
   924  	}
   925  
   926  	// test mixed embed struct
   927  	fnTest(t, reflect.TypeOf((*Point)(nil)).Elem())
   928  	// test dynamic embed struct
   929  	fnTest(t, makeDynamicPointType())
   930  }
   931  
   932  func TestEmbedMethods2(t *testing.T) {
   933  	// MyPoint2
   934  	typ := reflect.TypeOf((*MyPoint2)(nil)).Elem()
   935  	if v := typ.NumMethod(); v != 5 {
   936  		t.Fatalf("NumMethod have %v want 5", v)
   937  	}
   938  	if v := reflect.PtrTo(typ).NumMethod(); v != 5 {
   939  		t.Fatalf("NumMethod have %v want 5", v)
   940  	}
   941  
   942  	// embbed ptr
   943  	fnTest := func(t *testing.T, tyPoint reflect.Type) {
   944  		fs := []reflect.StructField{
   945  			reflect.StructField{
   946  				Name:      "Point",
   947  				Type:      reflect.PtrTo(tyPoint),
   948  				Anonymous: true,
   949  			},
   950  		}
   951  		typ = reflectx.NamedStructOf("main", "MyPoint2", fs)
   952  		typ = reflectx.StructToMethodSet(typ)
   953  		if v := typ.NumMethod(); v != 5 {
   954  			t.Errorf("NumMethod have %v want 5", v)
   955  		}
   956  		if v := reflect.PtrTo(typ).NumMethod(); v != 5 {
   957  			t.Errorf("NumMethod have %v want 5", v)
   958  		}
   959  		m := reflect.New(typ).Elem()
   960  		m.Field(0).Set(reflect.New(tyPoint))
   961  		m.MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100), reflect.ValueOf(200)})
   962  		if v := fmt.Sprint((m)); v != "(100,200)" {
   963  			t.Errorf("have %v want (100,200)", v)
   964  		}
   965  		if v := fmt.Sprint(m.Addr()); v != "(100,200)" {
   966  			t.Errorf("have %v want (100,200)", v)
   967  		}
   968  		m.Field(0).MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(-100), reflect.ValueOf(-200)})
   969  		if v := fmt.Sprint(m); v != "(-100,-200)" {
   970  			t.Errorf("have %v want (-100,-200)", v)
   971  		}
   972  		if v := fmt.Sprint(m.Field(0)); v != "(-100,-200)" {
   973  			t.Errorf("have %v want (-100,-200)", v)
   974  		}
   975  		if v := fmt.Sprint(m.Field(0).Elem()); v != "(-100,-200)" {
   976  			t.Errorf("have %v want (-100,-200)", v)
   977  		}
   978  		m.Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(300), reflect.ValueOf(400)})
   979  		if v := fmt.Sprint(m); v != "(300,400)" {
   980  			t.Errorf("have %v want (300,400)", v)
   981  		}
   982  		if v := fmt.Sprint((m.Addr())); v != "(300,400)" {
   983  			t.Errorf("have %v want (300,400)", v)
   984  		}
   985  	}
   986  	// test mixed embed ptr
   987  	fnTest(t, reflect.TypeOf((*Point)(nil)).Elem())
   988  	// test dynamic embed ptr
   989  	fnTest(t, makeDynamicPointType())
   990  }
   991  
   992  func TestEmbedMethods3(t *testing.T) {
   993  	// MyPoint3
   994  	typ := reflect.TypeOf((*MyPoint3)(nil)).Elem()
   995  	if v := typ.NumMethod(); v != 2 {
   996  		t.Fatalf("NumMethod have %v want 2", v)
   997  	}
   998  	if v := reflect.PtrTo(typ).NumMethod(); v != 2 {
   999  		t.Fatalf("NumMethod have %v want 2", v)
  1000  	}
  1001  	var i MyPoint3
  1002  	i.Setter = &Point{}
  1003  	i.Set(100, 200)
  1004  	if v := fmt.Sprint(i); v != "(100,200)" {
  1005  		t.Fatalf("String have %v, want (100,200)", v)
  1006  	}
  1007  	(&i).Set(300, 400)
  1008  	if v := fmt.Sprint(i); v != "(300,400)" {
  1009  		t.Fatalf("String have %v, want (300,400)", v)
  1010  	}
  1011  
  1012  	// embbed interface
  1013  	fnTest := func(t *testing.T, setter reflect.Type, tyPoint reflect.Type) {
  1014  		fs := []reflect.StructField{
  1015  			reflect.StructField{
  1016  				Name:      "Setter",
  1017  				Type:      setter,
  1018  				Anonymous: true,
  1019  			},
  1020  		}
  1021  		typ := reflectx.NamedStructOf("main", "MyPoint3", fs)
  1022  		typ = reflectx.StructToMethodSet(typ)
  1023  		if v := typ.NumMethod(); v != 2 {
  1024  			t.Errorf("NumMethod have %v want 2", v)
  1025  		}
  1026  		if v := reflect.PtrTo(typ).NumMethod(); v != 2 {
  1027  			t.Errorf("NumMethod have %v want 2", v)
  1028  		}
  1029  		m := reflect.New(typ).Elem()
  1030  		m.Field(0).Set(reflect.New(tyPoint))
  1031  		m.MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100), reflect.ValueOf(200)})
  1032  		if v := fmt.Sprint((m)); v != "(100,200)" {
  1033  			t.Errorf("have %v want (100,200)", v)
  1034  		}
  1035  		m.Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(300), reflect.ValueOf(400)})
  1036  		if v := fmt.Sprint((m)); v != "(300,400)" {
  1037  			t.Errorf("have %v want (300,400)", v)
  1038  		}
  1039  	}
  1040  	// test mixed embed interface
  1041  	fnTest(t, reflect.TypeOf((*Setter)(nil)).Elem(), reflect.TypeOf((*Point)(nil)).Elem())
  1042  	fnTest(t, reflect.TypeOf((*Setter)(nil)).Elem(), makeDynamicPointType())
  1043  	// test dynamic embed interface
  1044  	fnTest(t, makeDynamicSetterType(), reflect.TypeOf((*Point)(nil)).Elem())
  1045  	fnTest(t, makeDynamicSetterType(), makeDynamicPointType())
  1046  }
  1047  
  1048  func TestEmbedMethods4(t *testing.T) {
  1049  	// MyPoint4
  1050  	typ := reflect.TypeOf((*MyPoint4)(nil)).Elem()
  1051  	if v := typ.NumMethod(); v != 6 {
  1052  		t.Fatalf("NumMethod have %v want 6", v)
  1053  	}
  1054  	if v := reflect.PtrTo(typ).NumMethod(); v != 7 {
  1055  		t.Fatalf("NumMethod have %v want 7", v)
  1056  	}
  1057  	var i MyPoint4
  1058  	i.Point = &Point{}
  1059  	i.Set(100, 200)
  1060  	if v := fmt.Sprint(i); v != "0#(100,200)" {
  1061  		t.Fatalf("String have %v, want 0#(100,200)", v)
  1062  	}
  1063  	i.SetIndex(1)
  1064  	i.Set(300, 400)
  1065  	if v := fmt.Sprint(i); v != "1#(300,400)" {
  1066  		t.Fatalf("String have %v, want 1#(300,400)", v)
  1067  	}
  1068  
  1069  	fnTest := func(t *testing.T, tyPoint reflect.Type) {
  1070  		// embbed ptr
  1071  		fs := []reflect.StructField{
  1072  			reflect.StructField{
  1073  				Name:      "Point",
  1074  				Type:      reflect.PtrTo(tyPoint),
  1075  				Anonymous: true,
  1076  			},
  1077  			reflect.StructField{
  1078  				Name:      "index",
  1079  				PkgPath:   "main",
  1080  				Type:      reflect.TypeOf(int(0)),
  1081  				Anonymous: false,
  1082  			},
  1083  		}
  1084  		mSetIndex := reflectx.MakeMethod(
  1085  			"SetIndex",
  1086  			"main",
  1087  			true,
  1088  			reflect.FuncOf([]reflect.Type{tyInt}, nil, false),
  1089  			func(args []reflect.Value) []reflect.Value {
  1090  				reflectx.Field(args[0].Elem(), 1).SetInt(args[1].Int())
  1091  				return nil
  1092  			},
  1093  		)
  1094  		mIndex := reflectx.MakeMethod(
  1095  			"Index",
  1096  			"main",
  1097  			false,
  1098  			reflect.FuncOf(nil, []reflect.Type{tyInt}, false),
  1099  			func(args []reflect.Value) []reflect.Value {
  1100  				return []reflect.Value{args[0].Field(1)}
  1101  			},
  1102  		)
  1103  		mString := reflectx.MakeMethod(
  1104  			"String",
  1105  			"main",
  1106  			false,
  1107  			reflect.FuncOf(nil, []reflect.Type{tyString}, false),
  1108  			func(args []reflect.Value) []reflect.Value {
  1109  				info := fmt.Sprintf("%v#%v", args[0].Field(1), args[0].Field(0))
  1110  				return []reflect.Value{reflect.ValueOf(info)}
  1111  			},
  1112  		)
  1113  		typ := reflectx.NamedStructOf("main", "MyPoint4", fs)
  1114  		typ = reflectx.NewMethodSet(typ, 2, 3)
  1115  		reflectx.SetMethodSet(typ, []reflectx.Method{
  1116  			mSetIndex,
  1117  			mIndex,
  1118  			mString,
  1119  		}, true)
  1120  		if v := typ.NumMethod(); v != 6 {
  1121  			t.Errorf("NumMethod have %v want 6", v)
  1122  		}
  1123  		if v := reflect.PtrTo(typ).NumMethod(); v != 7 {
  1124  			t.Errorf("NumMethod have %v want 7", v)
  1125  		}
  1126  		m := reflect.New(typ).Elem()
  1127  		m.Field(0).Set(reflect.New(tyPoint))
  1128  		m.MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100), reflect.ValueOf(200)})
  1129  		if v := fmt.Sprint(m); v != "0#(100,200)" {
  1130  			t.Errorf("have %v want 0#(100,200)", v)
  1131  		}
  1132  		m.Addr().MethodByName("SetIndex").Call([]reflect.Value{reflect.ValueOf(1)})
  1133  		m.Addr().MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(300), reflect.ValueOf(400)})
  1134  		if v := fmt.Sprint(m); v != "1#(300,400)" {
  1135  			t.Errorf("have %v want 1#(300,400)", v)
  1136  		}
  1137  	}
  1138  
  1139  	// test mixed embed ptr with methods
  1140  	fnTest(t, reflect.TypeOf((*Point)(nil)).Elem())
  1141  	// test dynamic embed ptr with methods
  1142  	fnTest(t, makeDynamicPointType())
  1143  }
  1144  
  1145  type itoaFunc func(i int) string
  1146  
  1147  func (f itoaFunc) Itoa(i int) string { return f(i) }
  1148  
  1149  type Itoa interface {
  1150  	Itoa(i int) string
  1151  }
  1152  
  1153  func _TestFunc(t *testing.T) {
  1154  	fn := itoaFunc(func(i int) string {
  1155  		return strconv.Itoa(i)
  1156  	})
  1157  	if fn(100) != "100" {
  1158  		t.Fail()
  1159  	}
  1160  	if Itoa(fn).Itoa(100) != "100" {
  1161  		t.Fail()
  1162  	}
  1163  	fnTyp := reflect.TypeOf((*itoaFunc)(nil)).Elem()
  1164  	fnValue := reflect.MakeFunc(fnTyp, func(args []reflect.Value) []reflect.Value {
  1165  		r := strconv.Itoa(int(args[0].Int()))
  1166  		return []reflect.Value{reflect.ValueOf(r)}
  1167  	})
  1168  	if i := fnValue.Interface().(Itoa); i.Itoa(100) != "100" {
  1169  		t.Fail()
  1170  	}
  1171  	styp := reflectx.NamedTypeOf("main", "itoaFunc", reflect.FuncOf([]reflect.Type{tyInt}, []reflect.Type{tyString}, false))
  1172  	typ := reflectx.NewMethodSet(styp, 1, 1)
  1173  	mItoa := reflectx.MakeMethod("Itoa", "main", false,
  1174  		reflect.FuncOf([]reflect.Type{tyInt}, []reflect.Type{tyString}, false),
  1175  		func(args []reflect.Value) []reflect.Value {
  1176  			return args[0].Call(args[1:])
  1177  		})
  1178  	err := reflectx.SetMethodSet(typ, []reflectx.Method{mItoa}, false)
  1179  	if err != nil {
  1180  		t.Errorf("SetMethodSet error: %v", err)
  1181  	}
  1182  	if typ.NumMethod() != 1 {
  1183  		t.Fail()
  1184  	}
  1185  	v := reflect.MakeFunc(typ, func(args []reflect.Value) []reflect.Value {
  1186  		r := strconv.Itoa(int(args[0].Int()))
  1187  		return []reflect.Value{reflect.ValueOf(r)}
  1188  	})
  1189  	if v.NumMethod() != 1 {
  1190  		t.Fail()
  1191  	}
  1192  	if r := v.Call([]reflect.Value{reflect.ValueOf(100)}); r[0].String() != "100" {
  1193  		t.Fail()
  1194  	}
  1195  	if r := reflectx.MethodByIndex(typ, 0).Func.Call([]reflect.Value{v, reflect.ValueOf(100)}); r[0].String() != "100" {
  1196  		t.Fail()
  1197  	}
  1198  	if r := v.Method(0).Call([]reflect.Value{reflect.ValueOf(100)}); r[0].String() != "100" {
  1199  		t.Fail()
  1200  	}
  1201  }