mirror of
https://github.com/golang/go
synced 2024-11-19 10:24:43 -07:00
f985638b94
The new gotest ignores Test functions outside *_test.go files (the old shell script allowed them), so replace one clumsy hack with another. The root problem is that the package makefiles only know how to run cgo for source files in the package proper, not for test files. Making it work for test files is probably more trouble than it's worth. R=bradfitz CC=golang-dev https://golang.org/cl/4452060
137 lines
2.6 KiB
Go
137 lines
2.6 KiB
Go
package cgotest
|
|
|
|
/*
|
|
void callback(void *f);
|
|
void callGoFoo(void) {
|
|
extern void goFoo(void);
|
|
goFoo();
|
|
}
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"runtime"
|
|
"testing"
|
|
"unsafe"
|
|
)
|
|
|
|
// nestedCall calls into C, back into Go, and finally to f.
|
|
func nestedCall(f func()) {
|
|
// NOTE: Depends on representation of f.
|
|
// callback(x) calls goCallback(x)
|
|
C.callback(*(*unsafe.Pointer)(unsafe.Pointer(&f)))
|
|
}
|
|
|
|
//export goCallback
|
|
func goCallback(p unsafe.Pointer) {
|
|
(*(*func())(unsafe.Pointer(&p)))()
|
|
}
|
|
|
|
func testCallback(t *testing.T) {
|
|
var x = false
|
|
nestedCall(func() { x = true })
|
|
if !x {
|
|
t.Fatal("nestedCall did not call func")
|
|
}
|
|
}
|
|
|
|
func testCallbackGC(t *testing.T) {
|
|
nestedCall(runtime.GC)
|
|
}
|
|
|
|
func lockedOSThread() bool // in runtime.c
|
|
|
|
func testCallbackPanic(t *testing.T) {
|
|
// Make sure panic during callback unwinds properly.
|
|
if lockedOSThread() {
|
|
t.Fatal("locked OS thread on entry to TestCallbackPanic")
|
|
}
|
|
defer func() {
|
|
s := recover()
|
|
if s == nil {
|
|
t.Fatal("did not panic")
|
|
}
|
|
if s.(string) != "callback panic" {
|
|
t.Fatal("wrong panic:", s)
|
|
}
|
|
if lockedOSThread() {
|
|
t.Fatal("locked OS thread on exit from TestCallbackPanic")
|
|
}
|
|
}()
|
|
nestedCall(func() { panic("callback panic") })
|
|
panic("nestedCall returned")
|
|
}
|
|
|
|
func testCallbackPanicLoop(t *testing.T) {
|
|
// Make sure we don't blow out m->g0 stack.
|
|
for i := 0; i < 100000; i++ {
|
|
TestCallbackPanic(t)
|
|
}
|
|
}
|
|
|
|
func testCallbackPanicLocked(t *testing.T) {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
|
|
if !lockedOSThread() {
|
|
t.Fatal("runtime.LockOSThread didn't")
|
|
}
|
|
defer func() {
|
|
s := recover()
|
|
if s == nil {
|
|
t.Fatal("did not panic")
|
|
}
|
|
if s.(string) != "callback panic" {
|
|
t.Fatal("wrong panic:", s)
|
|
}
|
|
if !lockedOSThread() {
|
|
t.Fatal("lost lock on OS thread after panic")
|
|
}
|
|
}()
|
|
nestedCall(func() { panic("callback panic") })
|
|
panic("nestedCall returned")
|
|
}
|
|
|
|
// Callback with zero arguments used to make the stack misaligned,
|
|
// which broke the garbage collector and other things.
|
|
func testZeroArgCallback(t *testing.T) {
|
|
defer func() {
|
|
s := recover()
|
|
if s != nil {
|
|
t.Fatal("panic during callback:", s)
|
|
}
|
|
}()
|
|
C.callGoFoo()
|
|
}
|
|
|
|
//export goFoo
|
|
func goFoo() {
|
|
x := 1
|
|
for i := 0; i < 10000; i++ {
|
|
// variadic call mallocs + writes to
|
|
variadic(x, x, x)
|
|
if x != 1 {
|
|
panic("bad x")
|
|
}
|
|
}
|
|
}
|
|
|
|
func variadic(x ...interface{}) {}
|
|
|
|
func testBlocking(t *testing.T) {
|
|
c := make(chan int)
|
|
go func() {
|
|
for i := 0; i < 10; i++ {
|
|
c <- <-c
|
|
}
|
|
}()
|
|
nestedCall(func() {
|
|
for i := 0; i < 10; i++ {
|
|
c <- i
|
|
if j := <-c; j != i {
|
|
t.Errorf("out of sync %d != %d", j, i)
|
|
}
|
|
}
|
|
})
|
|
}
|