aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/testdata
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2015-12-21 10:29:21 -0500
committerRuss Cox <rsc@golang.org>2015-12-29 21:16:59 +0000
commit8d5ff2e182c52c4fa6af18e536dcef6e12ad8cb2 (patch)
tree5f5d3338d27a14b5e98af29ccb89d1a390ced3ea /src/runtime/testdata
parenta69932051266a817d950996c79927541ebdd26bb (diff)
downloadgo-8d5ff2e182c52c4fa6af18e536dcef6e12ad8cb2.tar.xz
runtime: move test programs out of source code, coalesce
Now there are just three programs to compile instead of many, and repeated tests can reuse the compilation result instead of rebuilding it. Combined, these changes reduce the time spent testing runtime during all.bash on my laptop from about 60 to about 30 seconds. (All.bash itself runs in 5½ minutes.) For #10571. Change-Id: Ie2c1798b847f1a635a860d11dcdab14375319ae9 Reviewed-on: https://go-review.googlesource.com/18085 Reviewed-by: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/testdata')
-rw-r--r--src/runtime/testdata/testprog/crash.go45
-rw-r--r--src/runtime/testdata/testprog/deadlock.go173
-rw-r--r--src/runtime/testdata/testprog/gc.go74
-rw-r--r--src/runtime/testdata/testprog/main.go35
-rw-r--r--src/runtime/testdata/testprog/stringconcat.go20
-rw-r--r--src/runtime/testdata/testprog/syscall_windows.go27
-rw-r--r--src/runtime/testdata/testprogcgo/callback.go89
-rw-r--r--src/runtime/testdata/testprogcgo/cgo.go80
-rw-r--r--src/runtime/testdata/testprogcgo/crash.go45
-rw-r--r--src/runtime/testdata/testprogcgo/dll_windows.go25
-rw-r--r--src/runtime/testdata/testprogcgo/main.go35
-rw-r--r--src/runtime/testdata/testprogcgo/threadpanic.go24
-rw-r--r--src/runtime/testdata/testprogcgo/threadpanic_unix.c26
-rw-r--r--src/runtime/testdata/testprogcgo/threadpanic_windows.c22
-rw-r--r--src/runtime/testdata/testprogcgo/threadprof.go93
-rw-r--r--src/runtime/testdata/testprogcgo/windows/win.go16
-rw-r--r--src/runtime/testdata/testprognet/main.go35
-rw-r--r--src/runtime/testdata/testprognet/net.go29
18 files changed, 893 insertions, 0 deletions
diff --git a/src/runtime/testdata/testprog/crash.go b/src/runtime/testdata/testprog/crash.go
new file mode 100644
index 0000000000..3d7c7c6aab
--- /dev/null
+++ b/src/runtime/testdata/testprog/crash.go
@@ -0,0 +1,45 @@
+// Copyright 2015 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 main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+func init() {
+ register("Crash", Crash)
+}
+
+func test(name string) {
+ defer func() {
+ if x := recover(); x != nil {
+ fmt.Printf(" recovered")
+ }
+ fmt.Printf(" done\n")
+ }()
+ fmt.Printf("%s:", name)
+ var s *string
+ _ = *s
+ fmt.Print("SHOULD NOT BE HERE")
+}
+
+func testInNewThread(name string) {
+ c := make(chan bool)
+ go func() {
+ runtime.LockOSThread()
+ test(name)
+ c <- true
+ }()
+ <-c
+}
+
+func Crash() {
+ runtime.LockOSThread()
+ test("main")
+ testInNewThread("new-thread")
+ testInNewThread("second-new-thread")
+ test("main-again")
+}
diff --git a/src/runtime/testdata/testprog/deadlock.go b/src/runtime/testdata/testprog/deadlock.go
new file mode 100644
index 0000000000..7f0a0cd1e0
--- /dev/null
+++ b/src/runtime/testdata/testprog/deadlock.go
@@ -0,0 +1,173 @@
+// Copyright 2015 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 main
+
+import (
+ "fmt"
+ "runtime"
+ "runtime/debug"
+ "time"
+)
+
+func init() {
+ registerInit("InitDeadlock", InitDeadlock)
+ registerInit("NoHelperGoroutines", NoHelperGoroutines)
+
+ register("SimpleDeadlock", SimpleDeadlock)
+ register("LockedDeadlock", LockedDeadlock)
+ register("LockedDeadlock2", LockedDeadlock2)
+ register("GoexitDeadlock", GoexitDeadlock)
+ register("StackOverflow", StackOverflow)
+ register("ThreadExhaustion", ThreadExhaustion)
+ register("RecursivePanic", RecursivePanic)
+ register("GoexitExit", GoexitExit)
+ register("GoNil", GoNil)
+ register("MainGoroutineID", MainGoroutineID)
+ register("Breakpoint", Breakpoint)
+ register("GoexitInPanic", GoexitInPanic)
+ register("PanicAfterGoexit", PanicAfterGoexit)
+ register("RecoveredPanicAfterGoexit", RecoveredPanicAfterGoexit)
+
+}
+
+func SimpleDeadlock() {
+ select {}
+ panic("not reached")
+}
+
+func InitDeadlock() {
+ select {}
+ panic("not reached")
+}
+
+func LockedDeadlock() {
+ runtime.LockOSThread()
+ select {}
+}
+
+func LockedDeadlock2() {
+ go func() {
+ runtime.LockOSThread()
+ select {}
+ }()
+ time.Sleep(time.Millisecond)
+ select {}
+}
+
+func GoexitDeadlock() {
+ F := func() {
+ for i := 0; i < 10; i++ {
+ }
+ }
+
+ go F()
+ go F()
+ runtime.Goexit()
+}
+
+func StackOverflow() {
+ var f func() byte
+ f = func() byte {
+ var buf [64 << 10]byte
+ return buf[0] + f()
+ }
+ debug.SetMaxStack(1474560)
+ f()
+}
+
+func ThreadExhaustion() {
+ debug.SetMaxThreads(10)
+ c := make(chan int)
+ for i := 0; i < 100; i++ {
+ go func() {
+ runtime.LockOSThread()
+ c <- 0
+ select {}
+ }()
+ <-c
+ }
+}
+
+func RecursivePanic() {
+ func() {
+ defer func() {
+ fmt.Println(recover())
+ }()
+ var x [8192]byte
+ func(x [8192]byte) {
+ defer func() {
+ if err := recover(); err != nil {
+ panic("wrap: " + err.(string))
+ }
+ }()
+ panic("bad")
+ }(x)
+ }()
+ panic("again")
+}
+
+func GoexitExit() {
+ go func() {
+ time.Sleep(time.Millisecond)
+ }()
+ i := 0
+ runtime.SetFinalizer(&i, func(p *int) {})
+ runtime.GC()
+ runtime.Goexit()
+}
+
+func GoNil() {
+ defer func() {
+ recover()
+ }()
+ var f func()
+ go f()
+ select {}
+}
+
+func MainGoroutineID() {
+ panic("test")
+}
+
+func NoHelperGoroutines() {
+ i := 0
+ runtime.SetFinalizer(&i, func(p *int) {})
+ time.AfterFunc(time.Hour, func() {})
+ panic("oops")
+}
+
+func Breakpoint() {
+ runtime.Breakpoint()
+}
+
+func GoexitInPanic() {
+ go func() {
+ defer func() {
+ runtime.Goexit()
+ }()
+ panic("hello")
+ }()
+ runtime.Goexit()
+}
+
+func PanicAfterGoexit() {
+ defer func() {
+ panic("hello")
+ }()
+ runtime.Goexit()
+}
+
+func RecoveredPanicAfterGoexit() {
+ defer func() {
+ defer func() {
+ r := recover()
+ if r == nil {
+ panic("bad recover")
+ }
+ }()
+ panic("hello")
+ }()
+ runtime.Goexit()
+}
diff --git a/src/runtime/testdata/testprog/gc.go b/src/runtime/testdata/testprog/gc.go
new file mode 100644
index 0000000000..9bb367c0d1
--- /dev/null
+++ b/src/runtime/testdata/testprog/gc.go
@@ -0,0 +1,74 @@
+// Copyright 2015 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 main
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "time"
+)
+
+func init() {
+ register("GCFairness", GCFairness)
+ register("GCSys", GCSys)
+}
+
+func GCSys() {
+ runtime.GOMAXPROCS(1)
+ memstats := new(runtime.MemStats)
+ runtime.GC()
+ runtime.ReadMemStats(memstats)
+ sys := memstats.Sys
+
+ runtime.MemProfileRate = 0 // disable profiler
+
+ itercount := 100000
+ for i := 0; i < itercount; i++ {
+ workthegc()
+ }
+
+ // Should only be using a few MB.
+ // We allocated 100 MB or (if not short) 1 GB.
+ runtime.ReadMemStats(memstats)
+ if sys > memstats.Sys {
+ sys = 0
+ } else {
+ sys = memstats.Sys - sys
+ }
+ if sys > 16<<20 {
+ fmt.Printf("using too much memory: %d bytes\n", sys)
+ return
+ }
+ fmt.Printf("OK\n")
+}
+
+func workthegc() []byte {
+ return make([]byte, 1029)
+}
+
+func GCFairness() {
+ runtime.GOMAXPROCS(1)
+ f, err := os.Open("/dev/null")
+ if os.IsNotExist(err) {
+ // This test tests what it is intended to test only if writes are fast.
+ // If there is no /dev/null, we just don't execute the test.
+ fmt.Println("OK")
+ return
+ }
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+ for i := 0; i < 2; i++ {
+ go func() {
+ for {
+ f.Write([]byte("."))
+ }
+ }()
+ }
+ time.Sleep(10 * time.Millisecond)
+ fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprog/main.go b/src/runtime/testdata/testprog/main.go
new file mode 100644
index 0000000000..5784865ea2
--- /dev/null
+++ b/src/runtime/testdata/testprog/main.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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 main
+
+import "os"
+
+var cmds = map[string]func(){}
+
+func register(name string, f func()) {
+ if cmds[name] != nil {
+ panic("duplicate registration: " + name)
+ }
+ cmds[name] = f
+}
+
+func registerInit(name string, f func()) {
+ if len(os.Args) >= 2 && os.Args[1] == name {
+ f()
+ }
+}
+
+func main() {
+ if len(os.Args) < 2 {
+ println("usage: "+os.Args[0]+" name-of-test")
+ return
+ }
+ f := cmds[os.Args[1]]
+ if f == nil {
+ println("unknown function: " + os.Args[1])
+ return
+ }
+ f()
+}
diff --git a/src/runtime/testdata/testprog/stringconcat.go b/src/runtime/testdata/testprog/stringconcat.go
new file mode 100644
index 0000000000..9dddf1969f
--- /dev/null
+++ b/src/runtime/testdata/testprog/stringconcat.go
@@ -0,0 +1,20 @@
+// Copyright 2015 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 main
+
+import "strings"
+
+func init() {
+ register("stringconcat", stringconcat)
+}
+
+func stringconcat() {
+ s0 := strings.Repeat("0", 1<<10)
+ s1 := strings.Repeat("1", 1<<10)
+ s2 := strings.Repeat("2", 1<<10)
+ s3 := strings.Repeat("3", 1<<10)
+ s := s0 + s1 + s2 + s3
+ panic(s)
+}
diff --git a/src/runtime/testdata/testprog/syscall_windows.go b/src/runtime/testdata/testprog/syscall_windows.go
new file mode 100644
index 0000000000..73165be187
--- /dev/null
+++ b/src/runtime/testdata/testprog/syscall_windows.go
@@ -0,0 +1,27 @@
+// Copyright 2015 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 main
+
+import "syscall"
+
+func init() {
+ register("RaiseException", RaiseException)
+ register("ZeroDivisionException", ZeroDivisionException)
+}
+
+func RaiseException() {
+ const EXCEPTION_NONCONTINUABLE = 1
+ mod := syscall.MustLoadDLL("kernel32.dll")
+ proc := mod.MustFindProc("RaiseException")
+ proc.Call(0xbad, EXCEPTION_NONCONTINUABLE, 0, 0)
+ println("RaiseException should not return")
+}
+
+func ZeroDivisionException() {
+ x := 1
+ y := 0
+ z := x / y
+ println(z)
+}
diff --git a/src/runtime/testdata/testprogcgo/callback.go b/src/runtime/testdata/testprogcgo/callback.go
new file mode 100644
index 0000000000..10e248a159
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/callback.go
@@ -0,0 +1,89 @@
+// Copyright 2015 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.
+
+// +build !plan9,!windows
+
+package main
+
+/*
+#include <pthread.h>
+
+void go_callback();
+
+static void *thr(void *arg) {
+ go_callback();
+ return 0;
+}
+
+static void foo() {
+ pthread_t th;
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setstacksize(&attr, 256 << 10);
+ pthread_create(&th, &attr, thr, 0);
+ pthread_join(th, 0);
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "runtime"
+)
+
+func init() {
+ register("CgoCallbackGC", CgoCallbackGC)
+}
+
+//export go_callback
+func go_callback() {
+ runtime.GC()
+ grow()
+ runtime.GC()
+}
+
+var cnt int
+
+func grow() {
+ x := 10000
+ sum := 0
+ if grow1(&x, &sum) == 0 {
+ panic("bad")
+ }
+}
+
+func grow1(x, sum *int) int {
+ if *x == 0 {
+ return *sum + 1
+ }
+ *x--
+ sum1 := *sum + *x
+ return grow1(x, &sum1)
+}
+
+func CgoCallbackGC() {
+ const P = 100
+ done := make(chan bool)
+ // allocate a bunch of stack frames and spray them with pointers
+ for i := 0; i < P; i++ {
+ go func() {
+ grow()
+ done <- true
+ }()
+ }
+ for i := 0; i < P; i++ {
+ <-done
+ }
+ // now give these stack frames to cgo callbacks
+ for i := 0; i < P; i++ {
+ go func() {
+ C.foo()
+ done <- true
+ }()
+ }
+ for i := 0; i < P; i++ {
+ <-done
+ }
+ fmt.Printf("OK\n")
+}
diff --git a/src/runtime/testdata/testprogcgo/cgo.go b/src/runtime/testdata/testprogcgo/cgo.go
new file mode 100644
index 0000000000..cf1af8268c
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/cgo.go
@@ -0,0 +1,80 @@
+// Copyright 2015 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 main
+
+/*
+void foo1(void) {}
+*/
+import "C"
+import (
+ "fmt"
+ "runtime"
+ "time"
+)
+
+func init() {
+ register("CgoSignalDeadlock", CgoSignalDeadlock)
+ register("CgoTraceback", CgoTraceback)
+}
+
+func CgoSignalDeadlock() {
+ runtime.GOMAXPROCS(100)
+ ping := make(chan bool)
+ go func() {
+ for i := 0; ; i++ {
+ runtime.Gosched()
+ select {
+ case done := <-ping:
+ if done {
+ ping <- true
+ return
+ }
+ ping <- true
+ default:
+ }
+ func() {
+ defer func() {
+ recover()
+ }()
+ var s *string
+ *s = ""
+ }()
+ }
+ }()
+ time.Sleep(time.Millisecond)
+ for i := 0; i < 64; i++ {
+ go func() {
+ runtime.LockOSThread()
+ select {}
+ }()
+ go func() {
+ runtime.LockOSThread()
+ select {}
+ }()
+ time.Sleep(time.Millisecond)
+ ping <- false
+ select {
+ case <-ping:
+ case <-time.After(time.Second):
+ fmt.Printf("HANG\n")
+ return
+ }
+ }
+ ping <- true
+ select {
+ case <-ping:
+ case <-time.After(time.Second):
+ fmt.Printf("HANG\n")
+ return
+ }
+ fmt.Printf("OK\n")
+}
+
+func CgoTraceback() {
+ C.foo1()
+ buf := make([]byte, 1)
+ runtime.Stack(buf, true)
+ fmt.Printf("OK\n")
+}
diff --git a/src/runtime/testdata/testprogcgo/crash.go b/src/runtime/testdata/testprogcgo/crash.go
new file mode 100644
index 0000000000..3d7c7c6aab
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/crash.go
@@ -0,0 +1,45 @@
+// Copyright 2015 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 main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+func init() {
+ register("Crash", Crash)
+}
+
+func test(name string) {
+ defer func() {
+ if x := recover(); x != nil {
+ fmt.Printf(" recovered")
+ }
+ fmt.Printf(" done\n")
+ }()
+ fmt.Printf("%s:", name)
+ var s *string
+ _ = *s
+ fmt.Print("SHOULD NOT BE HERE")
+}
+
+func testInNewThread(name string) {
+ c := make(chan bool)
+ go func() {
+ runtime.LockOSThread()
+ test(name)
+ c <- true
+ }()
+ <-c
+}
+
+func Crash() {
+ runtime.LockOSThread()
+ test("main")
+ testInNewThread("new-thread")
+ testInNewThread("second-new-thread")
+ test("main-again")
+}
diff --git a/src/runtime/testdata/testprogcgo/dll_windows.go b/src/runtime/testdata/testprogcgo/dll_windows.go
new file mode 100644
index 0000000000..a0647ef212
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/dll_windows.go
@@ -0,0 +1,25 @@
+// Copyright 2015 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 main
+
+/*
+#include <windows.h>
+
+DWORD getthread() {
+ return GetCurrentThreadId();
+}
+*/
+import "C"
+import "./windows"
+
+func init() {
+ register("CgoDLLImportsMain", CgoDLLImportsMain)
+}
+
+func CgoDLLImportsMain() {
+ C.getthread()
+ windows.GetThread()
+ println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/main.go b/src/runtime/testdata/testprogcgo/main.go
new file mode 100644
index 0000000000..5784865ea2
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/main.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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 main
+
+import "os"
+
+var cmds = map[string]func(){}
+
+func register(name string, f func()) {
+ if cmds[name] != nil {
+ panic("duplicate registration: " + name)
+ }
+ cmds[name] = f
+}
+
+func registerInit(name string, f func()) {
+ if len(os.Args) >= 2 && os.Args[1] == name {
+ f()
+ }
+}
+
+func main() {
+ if len(os.Args) < 2 {
+ println("usage: "+os.Args[0]+" name-of-test")
+ return
+ }
+ f := cmds[os.Args[1]]
+ if f == nil {
+ println("unknown function: " + os.Args[1])
+ return
+ }
+ f()
+}
diff --git a/src/runtime/testdata/testprogcgo/threadpanic.go b/src/runtime/testdata/testprogcgo/threadpanic.go
new file mode 100644
index 0000000000..3c9baba71a
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/threadpanic.go
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+// +build !plan9
+
+package main
+
+// void start(void);
+import "C"
+
+func init() {
+ register("CgoExternalThreadPanic", CgoExternalThreadPanic)
+}
+
+func CgoExternalThreadPanic() {
+ C.start()
+ select {}
+}
+
+//export gopanic
+func gopanic() {
+ panic("BOOM")
+}
diff --git a/src/runtime/testdata/testprogcgo/threadpanic_unix.c b/src/runtime/testdata/testprogcgo/threadpanic_unix.c
new file mode 100644
index 0000000000..dea8160365
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/threadpanic_unix.c
@@ -0,0 +1,26 @@
+// Copyright 2015 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.
+
+// +build !plan9,!windows
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+
+void gopanic(void);
+
+static void*
+die(void* x)
+{
+ gopanic();
+ return 0;
+}
+
+void
+start(void)
+{
+ pthread_t t;
+ if(pthread_create(&t, 0, die, 0) != 0)
+ printf("pthread_create failed\n");
+}
diff --git a/src/runtime/testdata/testprogcgo/threadpanic_windows.c b/src/runtime/testdata/testprogcgo/threadpanic_windows.c
new file mode 100644
index 0000000000..0a19ffaa12
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/threadpanic_windows.c
@@ -0,0 +1,22 @@
+// Copyright 2015 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 <stdlib.h>
+#include <stdio.h>
+
+void gopanic(void);
+
+static void*
+die(void* x)
+{
+ gopanic();
+ return 0;
+}
+
+void
+start(void)
+{
+ if(_beginthreadex(0, 0, die, 0, 0, 0) != 0)
+ printf("_beginthreadex failed\n");
+}
diff --git a/src/runtime/testdata/testprogcgo/threadprof.go b/src/runtime/testdata/testprogcgo/threadprof.go
new file mode 100644
index 0000000000..03e35d2a9e
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/threadprof.go
@@ -0,0 +1,93 @@
+// Copyright 2015 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.
+
+// +build !plan9,!windows
+
+package main
+
+/*
+#include <stdint.h>
+#include <signal.h>
+#include <pthread.h>
+
+volatile int32_t spinlock;
+
+static void *thread1(void *p) {
+ (void)p;
+ while (spinlock == 0)
+ ;
+ pthread_kill(pthread_self(), SIGPROF);
+ spinlock = 0;
+ return NULL;
+}
+__attribute__((constructor)) void issue9456() {
+ pthread_t tid;
+ pthread_create(&tid, 0, thread1, NULL);
+}
+
+void **nullptr;
+
+void *crash(void *p) {
+ *nullptr = p;
+ return 0;
+}
+
+int start_crashing_thread(void) {
+ pthread_t tid;
+ return pthread_create(&tid, 0, crash, 0);
+}
+*/
+import "C"
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "runtime"
+ "sync/atomic"
+ "time"
+ "unsafe"
+)
+
+func init() {
+ register("CgoExternalThreadSIGPROF", CgoExternalThreadSIGPROF)
+ register("CgoExternalThreadSignal", CgoExternalThreadSignal)
+}
+
+func CgoExternalThreadSIGPROF() {
+ // This test intends to test that sending SIGPROF to foreign threads
+ // before we make any cgo call will not abort the whole process, so
+ // we cannot make any cgo call here. See https://golang.org/issue/9456.
+ atomic.StoreInt32((*int32)(unsafe.Pointer(&C.spinlock)), 1)
+ for atomic.LoadInt32((*int32)(unsafe.Pointer(&C.spinlock))) == 1 {
+ runtime.Gosched()
+ }
+ println("OK")
+}
+
+func CgoExternalThreadSignal() {
+ if len(os.Args) > 2 && os.Args[2] == "crash" {
+ i := C.start_crashing_thread()
+ if i != 0 {
+ fmt.Println("pthread_create failed:", i)
+ // Exit with 0 because parent expects us to crash.
+ return
+ }
+
+ // We should crash immediately, but give it plenty of
+ // time before failing (by exiting 0) in case we are
+ // running on a slow system.
+ time.Sleep(5 * time.Second)
+ return
+ }
+
+ out, err := exec.Command(os.Args[0], "CgoExternalThreadSignal", "crash").CombinedOutput()
+ if err == nil {
+ fmt.Println("C signal did not crash as expected\n")
+ fmt.Printf("%s\n", out)
+ os.Exit(1)
+ }
+
+ fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/windows/win.go b/src/runtime/testdata/testprogcgo/windows/win.go
new file mode 100644
index 0000000000..f2eabb9548
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/windows/win.go
@@ -0,0 +1,16 @@
+package windows
+
+/*
+#cgo CFLAGS: -mnop-fun-dllimport
+
+#include <windows.h>
+
+DWORD agetthread() {
+ return GetCurrentThreadId();
+}
+*/
+import "C"
+
+func GetThread() uint32 {
+ return uint32(C.agetthread())
+}
diff --git a/src/runtime/testdata/testprognet/main.go b/src/runtime/testdata/testprognet/main.go
new file mode 100644
index 0000000000..5784865ea2
--- /dev/null
+++ b/src/runtime/testdata/testprognet/main.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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 main
+
+import "os"
+
+var cmds = map[string]func(){}
+
+func register(name string, f func()) {
+ if cmds[name] != nil {
+ panic("duplicate registration: " + name)
+ }
+ cmds[name] = f
+}
+
+func registerInit(name string, f func()) {
+ if len(os.Args) >= 2 && os.Args[1] == name {
+ f()
+ }
+}
+
+func main() {
+ if len(os.Args) < 2 {
+ println("usage: "+os.Args[0]+" name-of-test")
+ return
+ }
+ f := cmds[os.Args[1]]
+ if f == nil {
+ println("unknown function: " + os.Args[1])
+ return
+ }
+ f()
+}
diff --git a/src/runtime/testdata/testprognet/net.go b/src/runtime/testdata/testprognet/net.go
new file mode 100644
index 0000000000..c1a7f3f132
--- /dev/null
+++ b/src/runtime/testdata/testprognet/net.go
@@ -0,0 +1,29 @@
+// Copyright 2015 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 main
+
+import (
+ "fmt"
+ "net"
+)
+
+func init() {
+ registerInit("NetpollDeadlock", NetpollDeadlockInit)
+ register("NetpollDeadlock", NetpollDeadlock)
+}
+
+func NetpollDeadlockInit() {
+ fmt.Println("dialing")
+ c, err := net.Dial("tcp", "localhost:14356")
+ if err == nil {
+ c.Close()
+ } else {
+ fmt.Println("error: ", err)
+ }
+}
+
+func NetpollDeadlock() {
+ fmt.Println("done")
+}