summaryrefslogtreecommitdiff
path: root/misc/cgo
diff options
context:
space:
mode:
Diffstat (limited to 'misc/cgo')
-rw-r--r--misc/cgo/stdio/Makefile3
-rw-r--r--misc/cgo/stdio/hello.go20
-rw-r--r--misc/cgo/test/Makefile23
-rw-r--r--misc/cgo/test/align.go (renamed from misc/cgo/stdio/align.go)18
-rw-r--r--misc/cgo/test/basic.go (renamed from misc/cgo/stdio/test.go)36
-rw-r--r--misc/cgo/test/callback.go136
-rw-r--r--misc/cgo/test/callback_c.c12
-rw-r--r--misc/cgo/test/cgo_test.go5
-rw-r--r--misc/cgo/test/issue1222.go (renamed from misc/cgo/stdio/test1.go)2
-rw-r--r--misc/cgo/test/issue1328.go30
-rw-r--r--misc/cgo/test/issue1560.go46
-rw-r--r--misc/cgo/test/runtime.c21
12 files changed, 294 insertions, 58 deletions
diff --git a/misc/cgo/stdio/Makefile b/misc/cgo/stdio/Makefile
index fc925e607..3f7a4c01c 100644
--- a/misc/cgo/stdio/Makefile
+++ b/misc/cgo/stdio/Makefile
@@ -6,10 +6,7 @@ include ../../../src/Make.inc
TARG=stdio
CGOFILES=\
- align.go\
file.go\
- test.go\
- test1.go\
CLEANFILES+=hello fib chain run.out
diff --git a/misc/cgo/stdio/hello.go b/misc/cgo/stdio/hello.go
index 9cb6e6884..58fc6d574 100644
--- a/misc/cgo/stdio/hello.go
+++ b/misc/cgo/stdio/hello.go
@@ -4,26 +4,8 @@
package main
-import (
- "os"
- "stdio"
-)
+import "stdio"
func main() {
stdio.Stdout.WriteString(stdio.Greeting + "\n")
-
- l := stdio.Atol("123")
- if l != 123 {
- println("Atol 123: ", l)
- panic("bad atol")
- }
-
- n, err := stdio.Strtol("asdf", 123)
- if n != 0 || err != os.EINVAL {
- println("Strtol: ", n, err)
- panic("bad atoi2")
- }
-
- stdio.TestAlign()
- stdio.TestEnum()
}
diff --git a/misc/cgo/test/Makefile b/misc/cgo/test/Makefile
new file mode 100644
index 000000000..893540d97
--- /dev/null
+++ b/misc/cgo/test/Makefile
@@ -0,0 +1,23 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../../src/Make.inc
+
+TARG=runtime/cgotest
+
+CGOFILES=\
+ align.go\
+ basic.go\
+ callback.go\
+ issue1222.go\
+ issue1328.go\
+ issue1560.go\
+
+CGO_OFILES=\
+ callback_c.o\
+
+OFILES=\
+ runtime.$O\
+
+include ../../../src/Make.pkg
diff --git a/misc/cgo/stdio/align.go b/misc/cgo/test/align.go
index 6cdfd902f..2d2979595 100644
--- a/misc/cgo/stdio/align.go
+++ b/misc/cgo/test/align.go
@@ -1,4 +1,4 @@
-package stdio
+package cgotest
/*
#include <stdio.h>
@@ -55,24 +55,18 @@ void cTest(SDL_KeyboardEvent *event) {
import "C"
import (
- "fmt"
- "syscall"
+ "testing"
)
-func TestAlign() {
- if syscall.ARCH == "amd64" {
- // alignment is known to be broken on amd64.
- // http://code.google.com/p/go/issues/detail?id=609
- return
- }
+func TestAlign(t *testing.T) {
var evt C.SDL_KeyboardEvent
C.makeEvent(&evt)
if C.same(&evt, evt.typ, evt.which, evt.state, evt.keysym.scancode, evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) == 0 {
- fmt.Println("*** bad alignment")
+ t.Error("*** bad alignment")
C.cTest(&evt)
- fmt.Printf("Go: %#x %#x %#x %#x %#x %#x %#x\n",
+ t.Errorf("Go: %#x %#x %#x %#x %#x %#x %#x\n",
evt.typ, evt.which, evt.state, evt.keysym.scancode,
evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode)
- fmt.Println(evt)
+ t.Error(evt)
}
}
diff --git a/misc/cgo/stdio/test.go b/misc/cgo/test/basic.go
index 8f21603ca..a94074c52 100644
--- a/misc/cgo/stdio/test.go
+++ b/misc/cgo/test/basic.go
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// This file contains test cases for cgo.
+// Basic test cases for cgo.
-package stdio
+package cgotest
/*
#include <stdio.h>
@@ -52,6 +52,7 @@ struct ibv_context {
import "C"
import (
"os"
+ "testing"
"unsafe"
)
@@ -89,38 +90,35 @@ func Atol(s string) int {
return int(n)
}
-func TestConst() {
+func TestConst(t *testing.T) {
C.myConstFunc(nil, 0, nil)
}
-func TestEnum() {
+func TestEnum(t *testing.T) {
if C.Enum1 != 1 || C.Enum2 != 2 {
- println("bad enum", C.Enum1, C.Enum2)
+ t.Error("bad enum", C.Enum1, C.Enum2)
}
}
-func TestAtol() {
+func TestAtol(t *testing.T) {
l := Atol("123")
if l != 123 {
- println("Atol 123: ", l)
- panic("bad atol")
+ t.Error("Atol 123: ", l)
}
}
-func TestErrno() {
+func TestErrno(t *testing.T) {
n, err := Strtol("asdf", 123)
if n != 0 || err != os.EINVAL {
- println("Strtol: ", n, err)
- panic("bad strtol")
+ t.Error("Strtol: ", n, err)
}
}
-func TestMultipleAssign() {
- p := C.CString("123")
+func TestMultipleAssign(t *testing.T) {
+ p := C.CString("234")
n, m := C.strtol(p, nil, 345), C.strtol(p, nil, 10)
if n != 0 || m != 234 {
- println("Strtol x2: ", n, m)
- panic("bad strtol x2")
+ t.Fatal("Strtol x2: ", n, m)
}
C.free(unsafe.Pointer(p))
}
@@ -134,11 +132,3 @@ var (
type Context struct {
ctx *C.struct_ibv_context
}
-
-func Test() {
- TestAlign()
- TestAtol()
- TestEnum()
- TestErrno()
- TestConst()
-}
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
new file mode 100644
index 000000000..450a7cbf2
--- /dev/null
+++ b/misc/cgo/test/callback.go
@@ -0,0 +1,136 @@
+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)
+ }
+ }
+ })
+}
diff --git a/misc/cgo/test/callback_c.c b/misc/cgo/test/callback_c.c
new file mode 100644
index 000000000..5983a5e11
--- /dev/null
+++ b/misc/cgo/test/callback_c.c
@@ -0,0 +1,12 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <sys/types.h>
+#include "_cgo_export.h"
+
+void
+callback(void *f)
+{
+ goCallback(f);
+}
diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go
new file mode 100644
index 000000000..967dc0e92
--- /dev/null
+++ b/misc/cgo/test/cgo_test.go
@@ -0,0 +1,5 @@
+package cgotest
+
+// dummy file so gotest thinks there are tests.
+// the actual tests are in the main go files, next
+// to the code they test.
diff --git a/misc/cgo/stdio/test1.go b/misc/cgo/test/issue1222.go
index dce2ef83c..c396a0c41 100644
--- a/misc/cgo/stdio/test1.go
+++ b/misc/cgo/test/issue1222.go
@@ -4,7 +4,7 @@
// This file contains test cases for cgo.
-package stdio
+package cgotest
/*
// issue 1222
diff --git a/misc/cgo/test/issue1328.go b/misc/cgo/test/issue1328.go
new file mode 100644
index 000000000..f29d7057e
--- /dev/null
+++ b/misc/cgo/test/issue1328.go
@@ -0,0 +1,30 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cgotest
+
+import "testing"
+
+// extern void BackIntoGo(void);
+// void IntoC() { BackIntoGo(); }
+import "C"
+
+//export BackIntoGo
+func BackIntoGo() {
+ x := 1
+
+ for i := 0; i < 10000; i++ {
+ xvariadic(x)
+ if x != 1 {
+ panic("x is not 1?")
+ }
+ }
+}
+
+func xvariadic(x ...interface{}) {
+}
+
+func Test1328(t *testing.T) {
+ C.IntoC()
+}
diff --git a/misc/cgo/test/issue1560.go b/misc/cgo/test/issue1560.go
new file mode 100644
index 000000000..75d31c035
--- /dev/null
+++ b/misc/cgo/test/issue1560.go
@@ -0,0 +1,46 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cgotest
+
+/*
+#include <unistd.h>
+
+extern void BackgroundSleep(int);
+void twoSleep(int n) {
+ BackgroundSleep(n);
+ sleep(n);
+}
+*/
+import "C"
+
+import (
+ "testing"
+ "time"
+)
+
+var sleepDone = make(chan bool)
+
+func parallelSleep(n int) {
+ C.twoSleep(C.int(n))
+ <-sleepDone
+}
+
+//export BackgroundSleep
+func BackgroundSleep(n int) {
+ go func() {
+ C.sleep(C.uint(n))
+ sleepDone <- true
+ }()
+}
+
+func TestParallelSleep(t *testing.T) {
+ dt := -time.Nanoseconds()
+ parallelSleep(1)
+ dt += time.Nanoseconds()
+ // bug used to run sleeps in serial, producing a 2-second delay.
+ if dt >= 1.3e9 {
+ t.Fatalf("parallel 1-second sleeps slept for %f seconds", float64(dt)/1e9)
+ }
+}
diff --git a/misc/cgo/test/runtime.c b/misc/cgo/test/runtime.c
new file mode 100644
index 000000000..e087c7622
--- /dev/null
+++ b/misc/cgo/test/runtime.c
@@ -0,0 +1,21 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Expose some runtime functions for testing.
+
+typedef char bool;
+
+bool runtime·lockedOSThread(void);
+
+static void
+FLUSH(void*)
+{
+}
+
+void
+·lockedOSThread(bool b)
+{
+ b = runtime·lockedOSThread();
+ FLUSH(&b);
+}