diff options
Diffstat (limited to 'misc/cgo')
| -rw-r--r-- | misc/cgo/stdio/Makefile | 3 | ||||
| -rw-r--r-- | misc/cgo/stdio/hello.go | 20 | ||||
| -rw-r--r-- | misc/cgo/test/Makefile | 23 | ||||
| -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.go | 136 | ||||
| -rw-r--r-- | misc/cgo/test/callback_c.c | 12 | ||||
| -rw-r--r-- | misc/cgo/test/cgo_test.go | 5 | ||||
| -rw-r--r-- | misc/cgo/test/issue1222.go (renamed from misc/cgo/stdio/test1.go) | 2 | ||||
| -rw-r--r-- | misc/cgo/test/issue1328.go | 30 | ||||
| -rw-r--r-- | misc/cgo/test/issue1560.go | 46 | ||||
| -rw-r--r-- | misc/cgo/test/runtime.c | 21 | 
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); +} | 
