github.com/jxskiss/gopkg/v2@v2.14.9-0.20240514120614-899f3e7952b4/unsafe/forceexport/function_test.go (about) 1 package forceexport 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 9 "github.com/jxskiss/gopkg/v2/unsafe/forceexport/testpkg" 10 ) 11 12 func TestGetPrivateFunc(t *testing.T) { 13 var pi = 3.14 14 got1 := testpkg.Floor(pi) 15 assert.Equal(t, 3.0, got1) 16 17 var privateFloorFunc func(x float64) float64 18 assert.NotPanics(t, func() { 19 GetFunc(&privateFloorFunc, "github.com/jxskiss/gopkg/v2/unsafe/forceexport/testpkg.floor") 20 }) 21 got2 := privateFloorFunc(pi) 22 23 assert.Equal(t, got1, got2) 24 } 25 26 // Note that we need to disable inlining here, or else the function won't be 27 // compiled into the binary. We also need to call it from the test so that the 28 // compiler doesn't remove it because it's unused. 29 // 30 //go:noinline 31 func addOne(x int) int { 32 return x + 1 33 } 34 35 func TestAddOne(t *testing.T) { 36 assert.Equal(t, 4, addOne(3)) 37 38 var addOneFunc func(x int) int 39 assert.NotPanics(t, func() { 40 GetFunc(&addOneFunc, "github.com/jxskiss/gopkg/v2/unsafe/forceexport.addOne") 41 }) 42 assert.Equal(t, 4, addOneFunc(3)) 43 } 44 45 func TestGetSelf(t *testing.T) { 46 var getFunc func(any, string) 47 assert.NotPanics(t, func() { 48 GetFunc(&getFunc, "github.com/jxskiss/gopkg/v2/unsafe/forceexport.GetFunc") 49 }) 50 51 _p := func(fn any) string { return fmt.Sprintf("%p", fn) } 52 53 // The two functions should share the same code pointer, so they should 54 // have the same string representation. 55 assert.Equal(t, _p(getFunc), _p(GetFunc)) 56 57 // Call it again on itself! 58 assert.NotPanics(t, func() { 59 getFunc(&getFunc, "github.com/jxskiss/gopkg/v2/unsafe/forceexport.GetFunc") 60 }) 61 assert.Equal(t, _p(getFunc), _p(GetFunc)) 62 } 63 64 func TestInvalidFunc(t *testing.T) { 65 var invalidFunc func() 66 assert.Panics(t, func() { 67 GetFunc(&invalidFunc, "invalidpackage.invalidfunction") 68 }) 69 assert.Nil(t, invalidFunc) 70 }