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

     1  package reflectx_test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"reflect"
     7  	"testing"
     8  	"unsafe"
     9  
    10  	"github.com/goplusjs/reflectx"
    11  )
    12  
    13  type nPoint struct {
    14  	x int
    15  	y int
    16  }
    17  
    18  func TestFieldCanSet(t *testing.T) {
    19  	x := &nPoint{10, 20}
    20  	v := reflect.ValueOf(x).Elem()
    21  
    22  	sf := v.Field(0)
    23  	if sf.CanSet() {
    24  		t.Fatal("x unexport cannot set")
    25  	}
    26  
    27  	sf = reflectx.CanSet(sf)
    28  	if !sf.CanSet() {
    29  		t.Fatal("CanSet failed")
    30  	}
    31  
    32  	sf.Set(reflect.ValueOf(201))
    33  	if x.x != 201 {
    34  		t.Fatalf("x value %v", x.x)
    35  	}
    36  	sf.SetInt(202)
    37  	if x.x != 202 {
    38  		t.Fatalf("x value %v", x.x)
    39  	}
    40  }
    41  
    42  type Rect struct {
    43  	pt1 nPoint
    44  	pt2 *nPoint
    45  }
    46  
    47  func TestField(t *testing.T) {
    48  	x := &Rect{nPoint{1, 2}, &nPoint{3, 4}}
    49  	v := reflect.ValueOf(x).Elem()
    50  	reflectx.Field(v, 0).Set(reflect.ValueOf(nPoint{10, 20}))
    51  	if x.pt1.x != 10 || x.pt1.y != 20 {
    52  		t.Fatalf("pt1 %v", x.pt1)
    53  	}
    54  	reflectx.FieldByName(v, "pt2").Set(reflect.ValueOf(&nPoint{30, 40}))
    55  	if x.pt2.x != 30 || x.pt2.y != 40 {
    56  		t.Fatalf("pt2 %v", x.pt2)
    57  	}
    58  	reflectx.FieldByNameFunc(v, func(name string) bool {
    59  		return name == "pt2"
    60  	}).Set(reflect.ValueOf(&nPoint{50, 60}))
    61  	if x.pt2.x != 50 || x.pt2.y != 60 {
    62  		t.Fatalf("pt2 %v", x.pt2)
    63  	}
    64  	reflectx.FieldByIndex(v, []int{0, 1}).SetInt(100)
    65  	if x.pt1.y != 100 {
    66  		t.Fatalf("pt1.y %v", x.pt1)
    67  	}
    68  }
    69  
    70  func TestFieldX(t *testing.T) {
    71  	x := &Rect{nPoint{1, 2}, &nPoint{3, 4}}
    72  	v := reflect.ValueOf(x).Elem()
    73  	reflectx.FieldX(v, 0).Set(reflect.ValueOf(nPoint{10, 20}))
    74  	if x.pt1.x != 10 || x.pt1.y != 20 {
    75  		t.Fatalf("pt1 %v", x.pt1)
    76  	}
    77  	reflectx.FieldByNameX(v, "pt2").Set(reflect.ValueOf(&nPoint{30, 40}))
    78  	if x.pt2.x != 30 || x.pt2.y != 40 {
    79  		t.Fatalf("pt2 %v", x.pt2)
    80  	}
    81  	reflectx.FieldByNameFuncX(v, func(name string) bool {
    82  		return name == "pt2"
    83  	}).Set(reflect.ValueOf(&nPoint{50, 60}))
    84  	if x.pt2.x != 50 || x.pt2.y != 60 {
    85  		t.Fatalf("pt2 %v", x.pt2)
    86  	}
    87  	reflectx.FieldByIndexX(v, []int{0, 1}).SetInt(100)
    88  	if x.pt1.y != 100 {
    89  		t.Fatalf("pt1.y %v", x.pt1)
    90  	}
    91  }
    92  
    93  func TestStructOfUnderscore(t *testing.T) {
    94  	fs := []reflect.StructField{
    95  		reflect.StructField{
    96  			Name:    "_",
    97  			PkgPath: "main",
    98  			Type:    tyInt,
    99  		},
   100  		reflect.StructField{
   101  			Name:    "_",
   102  			PkgPath: "main",
   103  			Type:    tyInt,
   104  		},
   105  	}
   106  	typ := reflectx.NamedStructOf("main", "Point", fs)
   107  	if typ.Field(0).Name != "_" {
   108  		t.Fatalf("field name must underscore")
   109  	}
   110  	if typ.Field(1).Name != "_" {
   111  		t.Fatalf("field name must underscore")
   112  	}
   113  }
   114  
   115  func TestStructOfExport(t *testing.T) {
   116  	fs := []reflect.StructField{
   117  		reflect.StructField{
   118  			Name:    "x",
   119  			PkgPath: "main",
   120  			Type:    tyInt,
   121  		},
   122  		reflect.StructField{
   123  			Name:    "y",
   124  			PkgPath: "main",
   125  			Type:    tyInt,
   126  		},
   127  	}
   128  	typ := reflectx.NamedStructOf("main", "Point", fs)
   129  	v := reflect.New(typ).Elem()
   130  	reflectx.FieldByIndex(v, []int{0}).SetInt(100)
   131  	reflectx.FieldByIndex(v, []int{1}).SetInt(200)
   132  	if s := fmt.Sprint(v); s != "{100 200}" {
   133  		t.Fatalf("have %v, want {100 200}", s)
   134  	}
   135  }
   136  
   137  type Buffer struct {
   138  	*bytes.Buffer
   139  	size  int
   140  	value reflect.Value
   141  	*bytes.Reader
   142  }
   143  
   144  func TestStructOf(t *testing.T) {
   145  	defer func() {
   146  		v := recover()
   147  		if v != nil {
   148  			t.Fatalf("reflectx.StructOf %v", v)
   149  		}
   150  	}()
   151  	typ := reflect.TypeOf((*Buffer)(nil)).Elem()
   152  	var fs []reflect.StructField
   153  	for i := 0; i < typ.NumField(); i++ {
   154  		fs = append(fs, typ.Field(i))
   155  	}
   156  	dst := reflectx.StructOf(fs)
   157  	for i := 0; i < dst.NumField(); i++ {
   158  		if dst.Field(i).Anonymous != fs[i].Anonymous {
   159  			t.Errorf("error field %v", dst.Field(i))
   160  		}
   161  	}
   162  
   163  	v := reflect.New(dst)
   164  	v.Elem().Field(0).Set(reflect.ValueOf(bytes.NewBufferString("hello")))
   165  	reflectx.CanSet(v.Elem().Field(1)).SetInt(100)
   166  }
   167  
   168  func TestNamedStruct(t *testing.T) {
   169  	fs := []reflect.StructField{
   170  		reflect.StructField{Name: "X", Type: reflect.TypeOf(0)},
   171  		reflect.StructField{Name: "Y", Type: reflect.TypeOf(0)},
   172  	}
   173  	t1 := reflect.StructOf(fs)
   174  	t2 := reflect.StructOf(fs)
   175  	if t1 != t2 {
   176  		t.Fatalf("reflect.StructOf %v != %v", t1, t2)
   177  	}
   178  	t3 := reflectx.NamedStructOf("github.com/goplus/reflectx_test", "Point", fs)
   179  	t4 := reflectx.NamedStructOf("github.com/goplus/reflectx_test", "Point2", fs)
   180  	if t3 == t4 {
   181  		t.Fatalf("NamedStructOf %v == %v", t3, t4)
   182  	}
   183  	if t4.String() != "reflectx_test.Point2" {
   184  		t.Fatalf("t4.String=%v", t4.String())
   185  	}
   186  	if t4.Name() != "Point2" {
   187  		t.Fatalf("t4.Name=%v", t4.Name())
   188  	}
   189  	if t4.PkgPath() != "github.com/goplus/reflectx_test" {
   190  		t.Fatalf("t4.PkgPath=%v", t4.PkgPath())
   191  	}
   192  }
   193  
   194  var (
   195  	ch = make(chan bool)
   196  	fn = func(int, string) (bool, int) {
   197  		return true, 0
   198  	}
   199  	fn2 = func(*nPoint, int, bool, []byte) int {
   200  		return 0
   201  	}
   202  	testNamedValue = []interface{}{
   203  		true,
   204  		false,
   205  		int(2),
   206  		int8(3),
   207  		int16(4),
   208  		int32(5),
   209  		int64(6),
   210  		uint(7),
   211  		uint8(8),
   212  		uint16(9),
   213  		uint32(10),
   214  		uint64(11),
   215  		uintptr(12),
   216  		float32(13),
   217  		float64(14),
   218  		complex64(15),
   219  		complex128(16),
   220  		"hello",
   221  		unsafe.Pointer(nil),
   222  		unsafe.Pointer(&fn),
   223  		[]byte("hello"),
   224  		[]int{1, 2, 3},
   225  		[5]byte{'a', 'b', 'c', 'd', 'e'},
   226  		[5]int{1, 2, 3, 4, 5},
   227  		[]string{"a", "b"},
   228  		[]int{100, 200},
   229  		map[int]string{1: "hello", 2: "world"},
   230  		new(uint8),
   231  		&fn,
   232  		&fn2,
   233  		&ch,
   234  		ch,
   235  		fn,
   236  		fn2,
   237  	}
   238  )
   239  
   240  func TestNamedType(t *testing.T) {
   241  	pkgpath := "github.com/goplus/reflectx"
   242  	for i, v := range testNamedValue {
   243  		value := reflect.ValueOf(v)
   244  		typ := value.Type()
   245  		nt := reflectx.NamedTypeOf("github.com/goplus/reflectx", fmt.Sprintf("MyType%v", i), typ)
   246  		if nt.Kind() != typ.Kind() {
   247  			t.Errorf("kind: have %v, want %v", nt.Kind(), typ.Kind())
   248  		}
   249  		if nt == typ {
   250  			t.Errorf("same type, %v", typ)
   251  		}
   252  		name := fmt.Sprintf("My_Type%v", i)
   253  		nt2 := reflectx.NamedTypeOf(pkgpath, name, typ)
   254  		if nt == nt2 {
   255  			t.Errorf("same type, %v", nt)
   256  		}
   257  		nv := reflect.New(nt).Elem()
   258  		reflectx.SetValue(nv, value) //
   259  		s1 := fmt.Sprint((nv))
   260  		s2 := fmt.Sprint(v)
   261  		if s1 != s2 {
   262  			t.Errorf("%v: have %v, want %v", nt.Kind(), s1, s2)
   263  		}
   264  		if nt2.Name() != name {
   265  			t.Errorf("name: have %v, want %v", nt2.Name(), name)
   266  		}
   267  		if nt2.PkgPath() != pkgpath {
   268  			t.Errorf("pkgpath: have %v, want %v", nt2.PkgPath(), pkgpath)
   269  		}
   270  	}
   271  }
   272  
   273  var testInterfaceType = []reflect.Type{
   274  	reflect.TypeOf((*interface{})(nil)).Elem(),
   275  	reflect.TypeOf((*fmt.Stringer)(nil)).Elem(),
   276  	reflect.TypeOf((*interface {
   277  		Read(p []byte) (n int, err error)
   278  		Write(p []byte) (n int, err error)
   279  		Close() error
   280  	})(nil)),
   281  }
   282  
   283  func TestNamedInterface(t *testing.T) {
   284  	pkgpath := reflect.TypeOf((*interface{})(nil)).Elem().PkgPath()
   285  	for i, styp := range testInterfaceType {
   286  		name := fmt.Sprintf("T%v", i)
   287  		typ := reflectx.NamedTypeOf(pkgpath, name, styp)
   288  		if typ.Name() != name {
   289  			t.Errorf("name: have %v, want %v", typ.Name(), name)
   290  		}
   291  		if typ.PkgPath() != pkgpath {
   292  			t.Errorf("pkgpath: have %v, want %v", typ.PkgPath(), pkgpath)
   293  		}
   294  		if typ.NumMethod() != styp.NumMethod() {
   295  			t.Errorf("num method: have %v, want %v", typ.NumMethod(), styp.NumMethod())
   296  		}
   297  		for i := 0; i < typ.NumMethod(); i++ {
   298  			if typ.Method(i) != styp.Method(i) {
   299  				t.Errorf("method: have %v, want %v", typ.Method(i), styp.Method(i))
   300  			}
   301  		}
   302  		if !typ.ConvertibleTo(styp) {
   303  			t.Errorf("%v cannot ConvertibleTo %v", typ, styp)
   304  		}
   305  		if !styp.ConvertibleTo(typ) {
   306  			t.Errorf("%v cannot ConvertibleTo %v", styp, typ)
   307  		}
   308  	}
   309  }
   310  
   311  func TestNamedTypeStruct(t *testing.T) {
   312  	typ := reflect.TypeOf((*nPoint)(nil)).Elem()
   313  	pkgpath := typ.PkgPath()
   314  	nt := reflectx.NamedTypeOf(pkgpath, "MyPoint", typ)
   315  	nt2 := reflectx.NamedTypeOf(pkgpath, "MyPoint2", typ)
   316  	if nt.NumField() != typ.NumField() {
   317  		t.Fatal("NumField != 2", nt.NumField())
   318  	}
   319  	if nt.Name() != "MyPoint" {
   320  		t.Fatal("Name != MyPoint", nt.Name())
   321  	}
   322  	if nt == nt2 {
   323  		t.Fatalf("same type %v", nt)
   324  	}
   325  	v := reflect.New(nt).Elem()
   326  	reflectx.Field(v, 0).SetInt(100)
   327  	reflectx.Field(v, 1).SetInt(200)
   328  	if v.FieldByName("x").Int() != 100 || v.FieldByName("y").Int() != 200 {
   329  		t.Fatal("Value != {100 200},", v)
   330  	}
   331  }
   332  
   333  func _TestSetElem(t *testing.T) {
   334  	typ := reflectx.NamedTypeOf("main", "T", reflect.TypeOf(([]struct{})(nil)))
   335  	reflectx.SetElem(typ, typ)
   336  	v := reflect.MakeSlice(typ, 3, 3)
   337  	v.Index(0).Set(reflect.MakeSlice(typ, 1, 1))
   338  	v.Index(1).Set(reflect.MakeSlice(typ, 2, 2))
   339  	s := fmt.Sprintf("%v", v.Interface())
   340  	if s != "[[[]] [[] []] []]" {
   341  		t.Fatalf("failed SetElem s=%v", s)
   342  	}
   343  }