github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/reflectkit/func_code_test.go (about) 1 // Copyright 2020 Insolar Network Ltd. 2 // All rights reserved. 3 // This material is licensed under the Insolar License version 1.0, 4 // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md. 5 6 package reflectkit 7 8 import ( 9 "bytes" 10 "io" 11 "reflect" 12 "runtime" 13 "testing" 14 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestCodeOf(t *testing.T) { 19 var v interface{} 20 21 v = TestCodeOf 22 require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v)) 23 require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(reflect.ValueOf(v).Interface())) 24 25 v = bytes.NewBufferString("abc").Len 26 require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v)) 27 require.NotEqual(t, reflect.ValueOf(v).Pointer(), CodeOf(TestCodeOf)) 28 29 var vi io.Writer 30 vi = bytes.NewBufferString("abc") 31 v = vi.Write 32 require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v)) 33 require.NotEqual(t, reflect.ValueOf(v).Pointer(), CodeOf(TestCodeOf)) 34 35 v = (*bytes.Buffer).Len 36 require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v)) 37 require.NotEqual(t, reflect.ValueOf(v).Pointer(), CodeOf(TestCodeOf)) 38 39 v = io.Writer.Write 40 require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v)) 41 require.NotEqual(t, reflect.ValueOf(v).Pointer(), CodeOf(TestCodeOf)) 42 } 43 44 func TestCodeOfNegative(t *testing.T) { 45 require.Panics(t, func() { CodeOf(nil) }) 46 require.Panics(t, func() { CodeOf(1) }) 47 require.Panics(t, func() { CodeOf(bytes.NewBufferString("abc")) }) 48 require.Panics(t, func() { CodeOf(uintptr(0)) }) 49 require.Panics(t, func() { CodeOf(reflect.ValueOf(TestCodeOf)) }) 50 require.Panics(t, func() { CodeOf(reflect.ValueOf(TestCodeOf).Pointer()) }) 51 } 52 53 func BenchmarkCodeOf(t *testing.B) { 54 samples := [5]interface{}{TestCodeOf, bytes.NewBufferString("abc").Len, (*bytes.Buffer).Len, io.Writer.Write, 55 ((io.Writer)(bytes.NewBufferString("abc"))).Write, 56 } 57 58 count := t.N * 100000000 59 t.Run("baseline", func(b *testing.B) { 60 for i := count; i > 0; i-- { 61 if v := samples[i%len(samples)]; v == nil { 62 runtime.KeepAlive(i) 63 } 64 } 65 }) 66 67 t.Run("reflect", func(b *testing.B) { 68 for i := count; i > 0; i-- { 69 if v := reflect.ValueOf(samples[i%len(samples)]).Pointer(); v+1 == 0 { 70 runtime.KeepAlive(v) 71 } 72 } 73 }) 74 75 t.Run("direct", func(b *testing.B) { 76 for i := count; i > 0; i-- { 77 if v := CodeOf(samples[i%len(samples)]); v+1 == 0 { 78 runtime.KeepAlive(v) 79 } 80 } 81 }) 82 } 83 84 func TestIsNil(t *testing.T) { 85 require.True(t, IsNil(nil)) 86 require.False(t, IsNil("")) 87 require.False(t, IsNil(uintptr(0))) 88 require.False(t, IsNil(0)) 89 require.False(t, IsNil(1)) 90 require.False(t, IsNil(struct{}{})) 91 require.False(t, IsNil(&struct{}{})) 92 93 var p *string 94 require.True(t, IsNil(p)) 95 s := "x" 96 p = &s 97 var i interface{} = p 98 require.False(t, IsNil(&s)) 99 require.False(t, IsNil(p)) 100 require.False(t, IsNil(i)) 101 102 p = nil 103 i = p 104 require.True(t, IsNil(p)) 105 require.True(t, IsNil(i)) 106 } 107 108 func BenchmarkTestNil(t *testing.B) { 109 var pn *string 110 var n interface{} = pn 111 112 t.Run("reflect", func(b *testing.B) { 113 for i := b.N; i > 0; i-- { 114 if !reflectIsNil(n) { 115 b.Fail() 116 } 117 } 118 }) 119 120 t.Run("direct", func(b *testing.B) { 121 for i := b.N; i > 0; i-- { 122 if !IsNil(n) { 123 b.Fail() 124 } 125 } 126 }) 127 } 128 129 func reflectIsNil(v interface{}) bool { 130 if v == nil { 131 return true 132 } 133 switch rv := reflect.ValueOf(v); rv.Kind() { 134 case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: 135 return rv.IsNil() 136 } 137 return false 138 }