github.com/inaneverb/ekacore/ekaunsafe/v4@v4.0.0/pointer_test.go (about) 1 // Copyright © 2020. All rights reserved. 2 // Author: Ilya Stroy. 3 // Contacts: iyuryevich@pm.me, https://github.com/qioalice 4 // License: https://opensource.org/licenses/MIT 5 6 package ekaunsafe_test 7 8 import ( 9 "runtime" 10 "testing" 11 "unsafe" 12 13 "github.com/stretchr/testify/assert" 14 15 "github.com/inaneverb/ekacore/ekaunsafe/v4" 16 ) 17 18 type t1 struct { 19 i int 20 } 21 22 func (v *t1) Foo() int { return v.i } 23 func (v *t1) Bar(newI int) int { v.i = newI; return v.i } 24 25 func newT(i int) t1 { return t1{i: i} } 26 27 func TestTakeCallableAddr(t *testing.T) { 28 29 type ( 30 typeFoo = func() int 31 typeBar = func(int) int 32 ) 33 34 var ptrFoo, ptrBar unsafe.Pointer 35 { 36 var o = newT(10) 37 38 var ( 39 typedFoo *typeFoo 40 typedBar *typeBar 41 ) 42 { 43 var addrFoo = o.Foo 44 typedFoo = &addrFoo 45 var addrBar = o.Bar 46 typedBar = &addrBar 47 } 48 49 runtime.GC() 50 51 assert.Equal(t, 10, (*(*typeFoo)(typedFoo))()) 52 assert.Equal(t, 20, (*(*typeBar)(typedBar))(20)) 53 assert.Equal(t, 20, (*(*typeFoo)(typedFoo))()) 54 55 o.Bar(10) 56 57 ptrFoo = ekaunsafe.TakeCallableAddr(o.Foo) 58 ptrBar = ekaunsafe.TakeCallableAddr(o.Bar) 59 } 60 61 runtime.GC() 62 63 assert.NotNil(t, ptrFoo) 64 assert.NotNil(t, ptrBar) 65 66 assert.Equal(t, 10, (*(*typeFoo)(ptrFoo))()) 67 assert.Equal(t, 20, (*(*typeBar)(ptrBar))(20)) 68 assert.Equal(t, 20, (*(*typeFoo)(ptrFoo))()) 69 } 70 71 func TestTakeCallableAddr2(t *testing.T) { 72 73 var o = newT(10) 74 var foo = o.Foo 75 var bar = o.Bar 76 77 runtime.GC() 78 79 assert.Equal(t, 10, foo()) 80 assert.Equal(t, 20, bar(20)) 81 assert.Equal(t, 20, foo()) 82 } 83 84 type CustomError struct{} 85 86 func (_ *CustomError) Error() string { return "<custom error>" } 87 88 func TestTakeRealAddrForError(t *testing.T) { 89 90 var customNilError = (*CustomError)(nil) 91 var customNotNilError = new(CustomError) 92 93 var legacyNilError error = customNilError 94 var legacyNotNilError error = customNotNilError 95 96 assert.True(t, ekaunsafe.TakeRealAddr(customNilError) == nil) 97 assert.True(t, ekaunsafe.TakeRealAddr(legacyNilError) == nil) 98 99 assert.True(t, ekaunsafe.TakeRealAddr(customNotNilError) != nil) 100 assert.True(t, ekaunsafe.TakeRealAddr(legacyNotNilError) != nil) 101 102 // This is why this test exists: 103 assert.True(t, legacyNilError != nil) 104 } 105 106 func TestTakeCallableAddr3(t *testing.T) { 107 108 const U8 = 0xAB 109 110 type tf1 = func(uint16) uint16 111 type tf2 = func(uint8, uint8) (uint8, uint8) 112 113 var f1 = tf1(func(u uint16) uint16 { return u }) 114 var f2 = *(*tf2)(ekaunsafe.TakeCallableAddr(f1)) 115 116 var r1, r2 = f2(U8, U8) 117 118 assert.EqualValues(t, U8, r1) 119 assert.EqualValues(t, U8, r2) 120 } 121 122 func BenchmarkTakeCallableAddr3(b *testing.B) { 123 b.ReportAllocs() 124 125 const U8 = 0xAB 126 127 type tf1 = func(uint16) uint16 128 type tf2 = func(uint8, uint8) (uint8, uint8) 129 130 var f1 = tf1(func(u uint16) uint16 { return u }) 131 132 for i := 0; i < b.N; i++ { 133 var f2 = *(*tf2)(ekaunsafe.TakeCallableAddr(f1)) 134 _, _ = f2(U8, U8) 135 } 136 }