github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/internal/ekaclike/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 ekaclike_test 7 8 import ( 9 "runtime" 10 "testing" 11 "unsafe" 12 13 "github.com/qioalice/ekago/v3/internal/ekaclike" 14 15 "github.com/stretchr/testify/assert" 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 o := newT(10) 37 38 var ( 39 typedFoo *typeFoo 40 typedBar *typeBar 41 ) 42 { 43 addrFoo := o.Foo 44 typedFoo = &addrFoo 45 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 = ekaclike.TakeCallableAddr(o.Foo) 58 ptrBar = ekaclike.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 o := newT(10) 74 foo := o.Foo 75 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 customNilError := (*CustomError)(nil) 91 customNotNilError := new(CustomError) 92 93 var legacyNilError error = customNilError 94 var legacyNotNilError error = customNotNilError 95 96 assert.True(t, ekaclike.TakeRealAddr(customNilError) == nil) 97 assert.True(t, ekaclike.TakeRealAddr(legacyNilError) == nil) 98 99 assert.True(t, ekaclike.TakeRealAddr(customNotNilError) != nil) 100 assert.True(t, ekaclike.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 f := func(x int32) int32 { 109 return x 110 } 111 112 z := (*(*func(float32) int32)(ekaclike.TakeCallableAddr(f)))(-1 * 12345678e-4) 113 assert.Equal(t, int32(-996519381), z) 114 }