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  }