github.com/goplus/reflectx@v1.2.2/method_test.go (about)

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