diff options
Diffstat (limited to 'src/cmd/cgo/internal/teststdio')
-rw-r--r-- | src/cmd/cgo/internal/teststdio/stdio_test.go | 77 | ||||
-rw-r--r-- | src/cmd/cgo/internal/teststdio/testdata/chain.go | 46 | ||||
-rw-r--r-- | src/cmd/cgo/internal/teststdio/testdata/chain.out | 55 | ||||
-rw-r--r-- | src/cmd/cgo/internal/teststdio/testdata/fib.go | 50 | ||||
-rw-r--r-- | src/cmd/cgo/internal/teststdio/testdata/fib.out | 91 | ||||
-rw-r--r-- | src/cmd/cgo/internal/teststdio/testdata/hello.go | 13 | ||||
-rw-r--r-- | src/cmd/cgo/internal/teststdio/testdata/hello.out | 1 | ||||
-rw-r--r-- | src/cmd/cgo/internal/teststdio/testdata/stdio/file.go | 42 | ||||
-rw-r--r-- | src/cmd/cgo/internal/teststdio/testdata/stdio/stdio.go | 20 |
9 files changed, 395 insertions, 0 deletions
diff --git a/src/cmd/cgo/internal/teststdio/stdio_test.go b/src/cmd/cgo/internal/teststdio/stdio_test.go new file mode 100644 index 0000000..3883422 --- /dev/null +++ b/src/cmd/cgo/internal/teststdio/stdio_test.go @@ -0,0 +1,77 @@ +// Copyright 2019 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 stdio_test + +import ( + "bytes" + "cmd/cgo/internal/cgotest" + "internal/testenv" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +func TestMain(m *testing.M) { + log.SetFlags(log.Lshortfile) + os.Exit(testMain(m)) +} + +func testMain(m *testing.M) int { + GOPATH, err := os.MkdirTemp("", "cgostdio") + if err != nil { + log.Panic(err) + } + defer os.RemoveAll(GOPATH) + os.Setenv("GOPATH", GOPATH) + + // Copy testdata into GOPATH/src/cgostdio, along with a go.mod file + // declaring the same path. + modRoot := filepath.Join(GOPATH, "src", "cgostdio") + if err := cgotest.OverlayDir(modRoot, "testdata"); err != nil { + log.Panic(err) + } + if err := os.Chdir(modRoot); err != nil { + log.Panic(err) + } + os.Setenv("PWD", modRoot) + if err := os.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil { + log.Panic(err) + } + + return m.Run() +} + +// TestTestRun runs a cgo test that doesn't depend on non-standard libraries. +func TestTestRun(t *testing.T) { + testenv.MustHaveGoRun(t) + testenv.MustHaveCGO(t) + + for _, file := range [...]string{ + "chain.go", + "fib.go", + "hello.go", + } { + file := file + wantFile := strings.Replace(file, ".go", ".out", 1) + t.Run(file, func(t *testing.T) { + cmd := exec.Command("go", "run", file) + got, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("%v: %s\n%s", cmd, err, got) + } + got = bytes.ReplaceAll(got, []byte("\r\n"), []byte("\n")) + want, err := os.ReadFile(wantFile) + if err != nil { + t.Fatal("reading golden output:", err) + } + if !bytes.Equal(got, want) { + t.Errorf("'%v' output does not match expected in %s. Instead saw:\n%s", cmd, wantFile, got) + } + }) + } +} diff --git a/src/cmd/cgo/internal/teststdio/testdata/chain.go b/src/cmd/cgo/internal/teststdio/testdata/chain.go new file mode 100644 index 0000000..c7163f5 --- /dev/null +++ b/src/cmd/cgo/internal/teststdio/testdata/chain.go @@ -0,0 +1,46 @@ +// Copyright 2009 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. + +//go:build test_run + +// Pass numbers along a chain of threads. + +package main + +import ( + "runtime" + "strconv" + + "cgostdio/stdio" +) + +const N = 10 +const R = 5 + +func link(left chan<- int, right <-chan int) { + // Keep the links in dedicated operating system + // threads, so that this program tests coordination + // between pthreads and not just goroutines. + runtime.LockOSThread() + for { + v := <-right + stdio.Stdout.WriteString(strconv.Itoa(v) + "\n") + left <- 1 + v + } +} + +func main() { + leftmost := make(chan int) + var left chan int + right := leftmost + for i := 0; i < N; i++ { + left, right = right, make(chan int) + go link(left, right) + } + for i := 0; i < R; i++ { + right <- 0 + x := <-leftmost + stdio.Stdout.WriteString(strconv.Itoa(x) + "\n") + } +} diff --git a/src/cmd/cgo/internal/teststdio/testdata/chain.out b/src/cmd/cgo/internal/teststdio/testdata/chain.out new file mode 100644 index 0000000..963cf9b --- /dev/null +++ b/src/cmd/cgo/internal/teststdio/testdata/chain.out @@ -0,0 +1,55 @@ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 diff --git a/src/cmd/cgo/internal/teststdio/testdata/fib.go b/src/cmd/cgo/internal/teststdio/testdata/fib.go new file mode 100644 index 0000000..9617368 --- /dev/null +++ b/src/cmd/cgo/internal/teststdio/testdata/fib.go @@ -0,0 +1,50 @@ +// Copyright 2009 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. + +//go:build test_run + +// Compute Fibonacci numbers with two goroutines +// that pass integers back and forth. No actual +// concurrency, just threads and synchronization +// and foreign code on multiple pthreads. + +package main + +import ( + "runtime" + "strconv" + + "cgostdio/stdio" +) + +func fibber(c, out chan int64, i int64) { + // Keep the fibbers in dedicated operating system + // threads, so that this program tests coordination + // between pthreads and not just goroutines. + runtime.LockOSThread() + + if i == 0 { + c <- i + } + for { + j := <-c + stdio.Stdout.WriteString(strconv.FormatInt(j, 10) + "\n") + out <- j + <-out + i += j + c <- i + } +} + +func main() { + c := make(chan int64) + out := make(chan int64) + go fibber(c, out, 0) + go fibber(c, out, 1) + <-out + for i := 0; i < 90; i++ { + out <- 1 + <-out + } +} diff --git a/src/cmd/cgo/internal/teststdio/testdata/fib.out b/src/cmd/cgo/internal/teststdio/testdata/fib.out new file mode 100644 index 0000000..17ff503 --- /dev/null +++ b/src/cmd/cgo/internal/teststdio/testdata/fib.out @@ -0,0 +1,91 @@ +0 +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 +144 +233 +377 +610 +987 +1597 +2584 +4181 +6765 +10946 +17711 +28657 +46368 +75025 +121393 +196418 +317811 +514229 +832040 +1346269 +2178309 +3524578 +5702887 +9227465 +14930352 +24157817 +39088169 +63245986 +102334155 +165580141 +267914296 +433494437 +701408733 +1134903170 +1836311903 +2971215073 +4807526976 +7778742049 +12586269025 +20365011074 +32951280099 +53316291173 +86267571272 +139583862445 +225851433717 +365435296162 +591286729879 +956722026041 +1548008755920 +2504730781961 +4052739537881 +6557470319842 +10610209857723 +17167680177565 +27777890035288 +44945570212853 +72723460248141 +117669030460994 +190392490709135 +308061521170129 +498454011879264 +806515533049393 +1304969544928657 +2111485077978050 +3416454622906707 +5527939700884757 +8944394323791464 +14472334024676221 +23416728348467685 +37889062373143906 +61305790721611591 +99194853094755497 +160500643816367088 +259695496911122585 +420196140727489673 +679891637638612258 +1100087778366101931 +1779979416004714189 +2880067194370816120 diff --git a/src/cmd/cgo/internal/teststdio/testdata/hello.go b/src/cmd/cgo/internal/teststdio/testdata/hello.go new file mode 100644 index 0000000..c0b52bf --- /dev/null +++ b/src/cmd/cgo/internal/teststdio/testdata/hello.go @@ -0,0 +1,13 @@ +// Copyright 2009 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. + +//go:build test_run + +package main + +import "cgostdio/stdio" + +func main() { + stdio.Stdout.WriteString(stdio.Greeting + "\n") +} diff --git a/src/cmd/cgo/internal/teststdio/testdata/hello.out b/src/cmd/cgo/internal/teststdio/testdata/hello.out new file mode 100644 index 0000000..4b5fa63 --- /dev/null +++ b/src/cmd/cgo/internal/teststdio/testdata/hello.out @@ -0,0 +1 @@ +hello, world diff --git a/src/cmd/cgo/internal/teststdio/testdata/stdio/file.go b/src/cmd/cgo/internal/teststdio/testdata/stdio/file.go new file mode 100644 index 0000000..d97ee4c --- /dev/null +++ b/src/cmd/cgo/internal/teststdio/testdata/stdio/file.go @@ -0,0 +1,42 @@ +// Copyright 2009 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. + +/* +A trivial example of wrapping a C library in Go. +For a more complex example and explanation, +see misc/cgo/gmp/gmp.go. +*/ + +package stdio + +/* +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <errno.h> + +char* greeting = "hello, world"; +*/ +import "C" +import "unsafe" + +type File C.FILE + +// Test reference to library symbol. +// Stdout and stderr are too special to be a reliable test. +//var = C.environ + +func (f *File) WriteString(s string) { + p := C.CString(s) + C.fputs(p, (*C.FILE)(f)) + C.free(unsafe.Pointer(p)) + f.Flush() +} + +func (f *File) Flush() { + C.fflush((*C.FILE)(f)) +} + +var Greeting = C.GoString(C.greeting) +var Gbytes = C.GoBytes(unsafe.Pointer(C.greeting), C.int(len(Greeting))) diff --git a/src/cmd/cgo/internal/teststdio/testdata/stdio/stdio.go b/src/cmd/cgo/internal/teststdio/testdata/stdio/stdio.go new file mode 100644 index 0000000..08286d4 --- /dev/null +++ b/src/cmd/cgo/internal/teststdio/testdata/stdio/stdio.go @@ -0,0 +1,20 @@ +// Copyright 2009 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 stdio + +/* +#include <stdio.h> + +// on mingw, stderr and stdout are defined as &_iob[FILENO] +// on netbsd, they are defined as &__sF[FILENO] +// and cgo doesn't recognize them, so write a function to get them, +// instead of depending on internals of libc implementation. +FILE *getStdout(void) { return stdout; } +FILE *getStderr(void) { return stderr; } +*/ +import "C" + +var Stdout = (*File)(C.getStdout()) +var Stderr = (*File)(C.getStderr()) |