github.com/andeya/ameda@v1.5.3/value_test.go (about)

     1  package ameda
     2  
     3  import (
     4  	"reflect"
     5  	"runtime"
     6  	"testing"
     7  	"time"
     8  	"unsafe"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  
    12  	time2 "github.com/andeya/ameda/test/time"
    13  )
    14  
    15  func TestCheckGoVersion(t *testing.T) {
    16  	defer func() { errValueUsable = nil }()
    17  	errValueUsable = checkGoVersion(runtime.Version())
    18  	assert.NoError(t, errValueUsable)
    19  
    20  	errValueUsable = checkGoVersion("go1.15")
    21  	assert.NoError(t, errValueUsable)
    22  
    23  	errValueUsable = checkGoVersion("go1.15rc1")
    24  	assert.NoError(t, errValueUsable)
    25  
    26  	errValueUsable = checkGoVersion("devel go1.19-721e999423 Mon May 30 14:13:55 2022 +0800")
    27  	assert.NoError(t, errValueUsable)
    28  
    29  	errValueUsable = checkGoVersion("go2.15rc1")
    30  	assert.EqualError(t, errValueUsable, "ameda Value: required go<2.0, but current version is 'go2.15rc1'")
    31  
    32  	errValueUsable = checkGoVersion("devel go2.19-721e999423 Mon May 30 14:13:55 2022 +0800")
    33  	assert.EqualError(t, errValueUsable, "ameda Value: required go<2.0, but current version is 'devel go2.19-721e999423 Mon May 30 14:13:55 2022 +0800'")
    34  }
    35  
    36  func TestRuntimeTypeID(t *testing.T) {
    37  	arrayEqual(t,
    38  		RuntimeTypeIDOf(time.Time{}), RuntimeTypeID(reflect.TypeOf(time.Now())), ValueOf(time.Now()).RuntimeTypeID(), ValueFrom(reflect.ValueOf(time.Now())).RuntimeTypeID(),
    39  	)
    40  	arrayEqual(t,
    41  		RuntimeTypeIDOf(&time.Time{}), RuntimeTypeID(reflect.TypeOf(&time.Time{})), ValueOf(&time.Time{}).RuntimeTypeID(), ValueFrom(reflect.ValueOf(&time.Time{})).RuntimeTypeID(),
    42  	)
    43  	arrayEqual(t,
    44  		RuntimeTypeIDOf(time2.Time{}), RuntimeTypeID(reflect.TypeOf(time2.Time{S: 2})), ValueOf(time2.Time{S: 3}).RuntimeTypeID(), ValueFrom(reflect.ValueOf(time2.Time{S: 4})).RuntimeTypeID(),
    45  	)
    46  	arrayEqual(t,
    47  		RuntimeTypeIDOf(&time2.Time{}), RuntimeTypeID(reflect.TypeOf(&time2.Time{S: 2})), ValueOf(&time2.Time{S: 3}).RuntimeTypeID(), ValueFrom(reflect.ValueOf(&time2.Time{S: 4})).RuntimeTypeID(),
    48  	)
    49  	arrayNotEqual(t, RuntimeTypeIDOf(time.Time{}), RuntimeTypeIDOf(&time.Time{}), RuntimeTypeIDOf(time2.Time{}), RuntimeTypeIDOf(&time2.Time{}))
    50  }
    51  
    52  func arrayEqual(t assert.TestingT, expected interface{}, actual ...interface{}) {
    53  	if len(actual) == 0 {
    54  		actual = append(actual, nil)
    55  	}
    56  	for i, a := range actual {
    57  		assert.Equal(t, expected, a, i)
    58  	}
    59  }
    60  func arrayNotEqual(t assert.TestingT, values ...interface{}) {
    61  	if len(values) <= 1 {
    62  		return
    63  	}
    64  	for i, a := range values {
    65  		for ii, aa := range values[i+1:] {
    66  			assert.NotEqual(t, a, aa, []int{i, ii})
    67  		}
    68  	}
    69  }
    70  
    71  func TestRuntimeTypeIDOf(t *testing.T) {
    72  	type T1 struct {
    73  		_ int
    74  	}
    75  	tid := RuntimeTypeIDOf(new(T1))
    76  	t.Log(tid)
    77  	assert.Equal(t, RuntimeTypeID(reflect.TypeOf(new(T1))), tid)
    78  	tid2 := RuntimeTypeIDOf(T1{})
    79  	assert.NotEqual(t, tid, tid2)
    80  }
    81  
    82  func TestKind(t *testing.T) {
    83  	type X struct {
    84  		A int16
    85  		B string
    86  	}
    87  	var x X
    88  	if ValueOf(&x).Kind() != reflect.Ptr {
    89  		t.FailNow()
    90  	}
    91  
    92  	if ValueOf(&x).UnderlyingElem().Kind() != reflect.Struct {
    93  		t.FailNow()
    94  	}
    95  
    96  	if ValueOf(x).Kind() != reflect.Struct {
    97  		t.FailNow()
    98  	}
    99  	if ValueOf(x).UnderlyingElem().Kind() != reflect.Struct {
   100  		t.FailNow()
   101  	}
   102  
   103  	f := func() {}
   104  	if ValueOf(f).Kind() != reflect.Func {
   105  		t.FailNow()
   106  	}
   107  
   108  	if ValueOf(t.Name).Kind() != reflect.Func {
   109  		t.FailNow()
   110  	}
   111  	if ValueOf(nil).Kind() != reflect.Invalid {
   112  		t.FailNow()
   113  	}
   114  	if ValueOf(nil).CanAddr() {
   115  		t.FailNow()
   116  	}
   117  	if ValueOf(x).CanAddr() {
   118  		t.FailNow()
   119  	}
   120  	if ValueOf(&x).CanAddr() {
   121  		t.FailNow()
   122  	}
   123  	assert.True(t, ValueOf(&x).Elem().Elem().CanAddr())
   124  	assert.True(t, ValueFrom(reflect.ValueOf(&x)).Elem().CanAddr())
   125  	assert.True(t, ValueFrom(reflect.ValueOf(&x).Elem()).CanAddr())
   126  }
   127  
   128  func TestPointer(t *testing.T) {
   129  	type X struct {
   130  		A int16
   131  		B string
   132  	}
   133  	x := X{A: 12345, B: "test"}
   134  	if ValueOf(&x).Pointer() != reflect.ValueOf(&x).Pointer() {
   135  		t.FailNow()
   136  	}
   137  	elemPtr := ValueOf(x).Pointer()
   138  	a := *(*int16)(unsafe.Pointer(elemPtr))
   139  	if a != x.A {
   140  		t.FailNow()
   141  	}
   142  	b := *(*string)(unsafe.Pointer(elemPtr + unsafe.Offsetof(x.B)))
   143  	if b != x.B {
   144  		t.FailNow()
   145  	}
   146  
   147  	s := []string{""}
   148  	if ValueOf(s).Pointer() != reflect.ValueOf(s).Pointer() {
   149  		t.FailNow()
   150  	}
   151  
   152  	f := func() bool { return true }
   153  	prt := ValueOf(f).Pointer()
   154  	f = *(*func() bool)(unsafe.Pointer(&prt))
   155  	if !f() {
   156  		t.FailNow()
   157  	}
   158  	t.Log(ValueOf(f).FuncForPC().Name())
   159  	prt = ValueOf(t.Name).Pointer()
   160  	tName := *(*func() string)(unsafe.Pointer(&prt))
   161  	if tName() != "TestPointer" {
   162  		t.FailNow()
   163  	}
   164  	t.Log(ValueOf(t.Name).FuncForPC().Name())
   165  	t.Log(ValueOf(s).FuncForPC() == nil)
   166  
   167  }
   168  
   169  func TestElem(t *testing.T) {
   170  	type I interface{}
   171  	var i I
   172  	u := ValueFrom(reflect.ValueOf(i))
   173  	type X struct {
   174  		A int16
   175  		B string
   176  	}
   177  	x := &X{A: 12345, B: "test"}
   178  	xx := &x
   179  	var elemPtr uintptr
   180  	for _, v := range []interface{}{&xx, xx, x, *x} {
   181  		val := ValueOf(v).UnderlyingElem()
   182  		elemPtr = val.Pointer()
   183  		a := *(*int16)(unsafe.Pointer(elemPtr))
   184  		if !assert.Equal(t, x.A, a) {
   185  			t.FailNow()
   186  		}
   187  		b := *(*string)(unsafe.Pointer(elemPtr + unsafe.Offsetof(x.B)))
   188  		if !assert.Equal(t, x.B, b) {
   189  			t.FailNow()
   190  		}
   191  	}
   192  
   193  	var y *X
   194  	u = ValueOf(&y)
   195  	if !assert.False(t, u.IsNil()) {
   196  		t.FailNow()
   197  	}
   198  	u = u.UnderlyingElem()
   199  	if !assert.Equal(t, reflect.Struct, u.Kind()) {
   200  		t.FailNow()
   201  	}
   202  	if !assert.True(t, u.IsNil()) {
   203  		t.FailNow()
   204  	}
   205  }
   206  
   207  func TestEmptyStruct(t *testing.T) {
   208  	type P1 struct {
   209  		A *int
   210  	}
   211  	u := ValueOf(P1{})
   212  	if u.Pointer() != 0 {
   213  		t.FailNow()
   214  	}
   215  	if !u.IsNil() {
   216  		t.FailNow()
   217  	}
   218  
   219  	type P2 struct {
   220  		A *int
   221  		B *int
   222  	}
   223  	u = ValueOf(P2{})
   224  	if u.Pointer() == 0 {
   225  		t.FailNow()
   226  	}
   227  	if u.IsNil() {
   228  		t.FailNow()
   229  	}
   230  }
   231  
   232  func TestValueFrom(t *testing.T) {
   233  	type X struct {
   234  		A int16
   235  		B string
   236  	}
   237  	x := &X{A: 12345, B: "test"}
   238  	v := reflect.ValueOf(&x)
   239  	u := ValueFrom2(&v).Elem()
   240  	v = v.Elem()
   241  	if u.RuntimeTypeID() != RuntimeTypeID(v.Type()) {
   242  		t.FailNow()
   243  	}
   244  	elemPtr := u.Pointer()
   245  	a := *(*int16)(unsafe.Pointer(elemPtr))
   246  	if a != x.A {
   247  		t.FailNow()
   248  	}
   249  	b := *(*string)(unsafe.Pointer(elemPtr + unsafe.Offsetof(x.B)))
   250  	if b != x.B {
   251  		t.FailNow()
   252  	}
   253  	if u.Pointer() != reflect.ValueOf(x).Pointer() {
   254  		t.FailNow()
   255  	}
   256  }
   257  
   258  func Benchmark_ameda(b *testing.B) {
   259  	type T struct {
   260  		a int
   261  	}
   262  	t := new(T)
   263  	b.ReportAllocs()
   264  	b.ResetTimer()
   265  	u := ValueOf(t).Elem()
   266  	for i := 0; i < b.N; i++ {
   267  		_ = u.RuntimeTypeID()
   268  	}
   269  }
   270  
   271  func Benchmark_reflect(b *testing.B) {
   272  	type T struct {
   273  		a int
   274  	}
   275  	t := new(T)
   276  	b.ReportAllocs()
   277  	b.ResetTimer()
   278  	u := reflect.TypeOf(t).Elem()
   279  	for i := 0; i < b.N; i++ {
   280  		_ = u.String()
   281  	}
   282  }