summaryrefslogtreecommitdiff
path: root/misc/cgo/test
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-09-13 13:13:40 +0200
committerOndřej Surý <ondrej@sury.org>2011-09-13 13:13:40 +0200
commit5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch)
treec0650497e988f47be9c6f2324fa692a52dea82e1 /misc/cgo/test
parent80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff)
downloadgolang-upstream/60.tar.gz
Imported Upstream version 60upstream/60
Diffstat (limited to 'misc/cgo/test')
-rw-r--r--misc/cgo/test/Makefile26
-rw-r--r--misc/cgo/test/align.go72
-rw-r--r--misc/cgo/test/basic.go134
-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.go28
-rw-r--r--misc/cgo/test/duplicate_symbol.go21
-rw-r--r--misc/cgo/test/env.go32
-rw-r--r--misc/cgo/test/exports.go12
-rw-r--r--misc/cgo/test/issue1222.go29
-rw-r--r--misc/cgo/test/issue1328.go30
-rw-r--r--misc/cgo/test/issue1560.go46
-rw-r--r--misc/cgo/test/runtime.c21
13 files changed, 599 insertions, 0 deletions
diff --git a/misc/cgo/test/Makefile b/misc/cgo/test/Makefile
new file mode 100644
index 000000000..d4309be3c
--- /dev/null
+++ b/misc/cgo/test/Makefile
@@ -0,0 +1,26 @@
+# 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\
+ env.go\
+ exports.go\
+ issue1222.go\
+ issue1328.go\
+ issue1560.go\
+ duplicate_symbol.go\
+
+CGO_OFILES=\
+ callback_c.o\
+
+OFILES=\
+ runtime.$O\
+
+include ../../../src/Make.pkg
diff --git a/misc/cgo/test/align.go b/misc/cgo/test/align.go
new file mode 100644
index 000000000..07ab9ef50
--- /dev/null
+++ b/misc/cgo/test/align.go
@@ -0,0 +1,72 @@
+package cgotest
+
+/*
+#include <stdio.h>
+
+typedef unsigned char Uint8;
+typedef unsigned short Uint16;
+
+typedef enum {
+ MOD1 = 0x0000,
+ MODX = 0x8000
+} SDLMod;
+
+typedef enum {
+ A = 1,
+ B = 322,
+ SDLK_LAST
+} SDLKey;
+
+typedef struct SDL_keysym {
+ Uint8 scancode;
+ SDLKey sym;
+ SDLMod mod;
+ Uint16 unicode;
+} SDL_keysym;
+
+typedef struct SDL_KeyboardEvent {
+ Uint8 typ;
+ Uint8 which;
+ Uint8 state;
+ SDL_keysym keysym;
+} SDL_KeyboardEvent;
+
+void makeEvent(SDL_KeyboardEvent *event) {
+ unsigned char *p;
+ int i;
+
+ p = (unsigned char*)event;
+ for (i=0; i<sizeof *event; i++) {
+ p[i] = i;
+ }
+}
+
+int same(SDL_KeyboardEvent* e, Uint8 typ, Uint8 which, Uint8 state, Uint8 scan, SDLKey sym, SDLMod mod, Uint16 uni) {
+ return e->typ == typ && e->which == which && e->state == state && e->keysym.scancode == scan && e->keysym.sym == sym && e->keysym.mod == mod && e->keysym.unicode == uni;
+}
+
+void cTest(SDL_KeyboardEvent *event) {
+ printf("C: %#x %#x %#x %#x %#x %#x %#x\n", event->typ, event->which, event->state,
+ event->keysym.scancode, event->keysym.sym, event->keysym.mod, event->keysym.unicode);
+ fflush(stdout);
+}
+
+*/
+import "C"
+
+import (
+ "testing"
+)
+
+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 {
+ t.Error("*** bad alignment")
+ C.cTest(&evt)
+ 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)
+ t.Error(evt)
+ }
+}
diff --git a/misc/cgo/test/basic.go b/misc/cgo/test/basic.go
new file mode 100644
index 000000000..b9d0953bd
--- /dev/null
+++ b/misc/cgo/test/basic.go
@@ -0,0 +1,134 @@
+// Copyright 2010 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.
+
+// Basic test cases for cgo.
+
+package cgotest
+
+/*
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#define SHIFT(x, y) ((x)<<(y))
+#define KILO SHIFT(1, 10)
+
+enum E {
+ Enum1 = 1,
+ Enum2 = 2,
+};
+
+typedef unsigned char uuid_t[20];
+
+void uuid_generate(uuid_t x) {
+ x[0] = 0;
+}
+
+struct S {
+ int x;
+};
+
+extern enum E myConstFunc(struct S* const ctx, int const id, struct S **const filter);
+
+enum E myConstFunc(struct S *const ctx, int const id, struct S **const filter) { return 0; }
+
+// issue 1222
+typedef union {
+ long align;
+} xxpthread_mutex_t;
+
+struct ibv_async_event {
+ union {
+ int x;
+ } element;
+};
+
+struct ibv_context {
+ xxpthread_mutex_t mutex;
+};
+*/
+import "C"
+import (
+ "os"
+ "testing"
+ "unsafe"
+)
+
+const EINVAL = C.EINVAL /* test #define */
+
+var KILO = C.KILO
+
+func uuidgen() {
+ var uuid C.uuid_t
+ C.uuid_generate(&uuid[0])
+}
+
+func Size(name string) (int64, os.Error) {
+ var st C.struct_stat
+ p := C.CString(name)
+ _, err := C.stat(p, &st)
+ C.free(unsafe.Pointer(p))
+ if err != nil {
+ return 0, err
+ }
+ return int64(C.ulong(st.st_size)), nil
+}
+
+func Strtol(s string, base int) (int, os.Error) {
+ p := C.CString(s)
+ n, err := C.strtol(p, nil, C.int(base))
+ C.free(unsafe.Pointer(p))
+ return int(n), err
+}
+
+func Atol(s string) int {
+ p := C.CString(s)
+ n := C.atol(p)
+ C.free(unsafe.Pointer(p))
+ return int(n)
+}
+
+func testConst(t *testing.T) {
+ C.myConstFunc(nil, 0, nil)
+}
+
+func testEnum(t *testing.T) {
+ if C.Enum1 != 1 || C.Enum2 != 2 {
+ t.Error("bad enum", C.Enum1, C.Enum2)
+ }
+}
+
+func testAtol(t *testing.T) {
+ l := Atol("123")
+ if l != 123 {
+ t.Error("Atol 123: ", l)
+ }
+}
+
+func testErrno(t *testing.T) {
+ n, err := Strtol("asdf", 123)
+ if n != 0 || err != os.EINVAL {
+ t.Error("Strtol: ", n, err)
+ }
+}
+
+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 {
+ t.Fatal("Strtol x2: ", n, m)
+ }
+ C.free(unsafe.Pointer(p))
+}
+
+var (
+ uint = (C.uint)(0)
+ ulong C.ulong
+ char C.char
+)
+
+type Context struct {
+ ctx *C.struct_ibv_context
+}
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
new file mode 100644
index 000000000..3edee9758
--- /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..94fba15db
--- /dev/null
+++ b/misc/cgo/test/cgo_test.go
@@ -0,0 +1,28 @@
+// 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"
+
+// The actual test functions are in non-_test.go files
+// so that they can use cgo (import "C").
+// These wrappers are here for gotest to find.
+
+func TestAlign(t *testing.T) { testAlign(t) }
+func TestConst(t *testing.T) { testConst(t) }
+func TestEnum(t *testing.T) { testEnum(t) }
+func TestAtol(t *testing.T) { testAtol(t) }
+func TestErrno(t *testing.T) { testErrno(t) }
+func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }
+func TestCallback(t *testing.T) { testCallback(t) }
+func TestCallbackGC(t *testing.T) { testCallbackGC(t) }
+func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) }
+func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) }
+func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
+func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
+func TestBlocking(t *testing.T) { testBlocking(t) }
+func Test1328(t *testing.T) { test1328(t) }
+func TestParallelSleep(t *testing.T) { testParallelSleep(t) }
+func TestSetEnv(t *testing.T) { testSetEnv(t) }
diff --git a/misc/cgo/test/duplicate_symbol.go b/misc/cgo/test/duplicate_symbol.go
new file mode 100644
index 000000000..69600de9c
--- /dev/null
+++ b/misc/cgo/test/duplicate_symbol.go
@@ -0,0 +1,21 @@
+// Copyright 2010 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.
+
+// This file contains test cases for cgo.
+
+package cgotest
+
+/*
+int base_symbol = 0;
+
+#define alias_one base_symbol
+#define alias_two base_symbol
+*/
+import "C"
+
+import "fmt"
+
+func duplicateSymbols() {
+ fmt.Printf("%v %v %v\n", C.base_symbol, C.alias_one, C.alias_two)
+}
diff --git a/misc/cgo/test/env.go b/misc/cgo/test/env.go
new file mode 100644
index 000000000..1fb4e684c
--- /dev/null
+++ b/misc/cgo/test/env.go
@@ -0,0 +1,32 @@
+// 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 <stdlib.h>
+*/
+import "C"
+import (
+ "os"
+ "testing"
+ "unsafe"
+)
+
+// This is really an os package test but here for convenience.
+func testSetEnv(t *testing.T) {
+ const key = "CGO_OS_TEST_KEY"
+ const val = "CGO_OS_TEST_VALUE"
+ os.Setenv(key, val)
+ keyc := C.CString(key)
+ defer C.free(unsafe.Pointer(keyc))
+ v := C.getenv(keyc)
+ if v == (*C.char)(unsafe.Pointer(uintptr(0))) {
+ t.Fatal("getenv returned NULL")
+ }
+ vs := C.GoString(v)
+ if vs != val {
+ t.Fatalf("getenv() = %q; want %q", vs, val)
+ }
+}
diff --git a/misc/cgo/test/exports.go b/misc/cgo/test/exports.go
new file mode 100644
index 000000000..f96c60b00
--- /dev/null
+++ b/misc/cgo/test/exports.go
@@ -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.
+
+package cgotest
+
+import "C"
+
+//export ReturnIntLong
+func ReturnIntLong() (int, C.long) {
+ return 1, 2
+}
diff --git a/misc/cgo/test/issue1222.go b/misc/cgo/test/issue1222.go
new file mode 100644
index 000000000..c396a0c41
--- /dev/null
+++ b/misc/cgo/test/issue1222.go
@@ -0,0 +1,29 @@
+// Copyright 2010 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.
+
+// This file contains test cases for cgo.
+
+package cgotest
+
+/*
+// issue 1222
+typedef union {
+ long align;
+} xxpthread_mutex_t;
+
+struct ibv_async_event {
+ union {
+ int x;
+ } element;
+};
+
+struct ibv_context {
+ xxpthread_mutex_t mutex;
+};
+*/
+import "C"
+
+type AsyncEvent struct {
+ event C.struct_ibv_async_event
+}
diff --git a/misc/cgo/test/issue1328.go b/misc/cgo/test/issue1328.go
new file mode 100644
index 000000000..e01207dd9
--- /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..e534cce47
--- /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);
+}