diff options
Diffstat (limited to 'misc/cgo/test/callback.go')
-rw-r--r-- | misc/cgo/test/callback.go | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go index a7f1a3ecd..44167e6e9 100644 --- a/misc/cgo/test/callback.go +++ b/misc/cgo/test/callback.go @@ -10,6 +10,9 @@ void callGoFoo(void); void callGoStackCheck(void); void callPanic(void); void callCgoAllocate(void); +int callGoReturnVal(void); +int returnAfterGrow(void); +int returnAfterGrowFromGo(void); */ import "C" @@ -212,6 +215,48 @@ func testAllocateFromC(t *testing.T) { C.callCgoAllocate() // crashes or exits on failure } +// Test that C code can return a value if it calls a Go function that +// causes a stack copy. +func testReturnAfterGrow(t *testing.T) { + // Use a new goroutine so that we get a small stack. + c := make(chan int) + go func() { + c <- int(C.returnAfterGrow()) + }() + if got, want := <-c, 123456; got != want { + t.Errorf("got %d want %d", got, want) + } +} + +// Test that we can return a value from Go->C->Go if the Go code +// causes a stack copy. +func testReturnAfterGrowFromGo(t *testing.T) { + // Use a new goroutine so that we get a small stack. + c := make(chan int) + go func() { + c <- int(C.returnAfterGrowFromGo()) + }() + if got, want := <-c, 129*128/2; got != want { + t.Errorf("got %d want %d", got, want) + } +} + +//export goReturnVal +func goReturnVal() (r C.int) { + // Force a stack copy. + var f func(int) int + f = func(i int) int { + var buf [256]byte + use(buf[:]) + if i == 0 { + return 0 + } + return i + f(i-1) + } + r = C.int(f(128)) + return +} + func testCallbackStack(t *testing.T) { // Make cgo call and callback with different amount of stack stack available. // We do not do any explicit checks, just ensure that it does not crash. |