"os/exec"
"path/filepath"
"regexp"
+ "runtime"
"strconv"
"strings"
"sync"
})
}
+// stdOutErrAreTerminals is defined in test_linux.go, to report
+// whether stdout & stderr are terminals.
+var stdOutErrAreTerminals func() bool
+
func (t *tester) registerTests() {
if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-vetall") {
// Run vet over std and cmd and call it quits.
return
}
+ // This test needs its stdout/stderr to be terminals, so we don't run it from cmd/go's tests.
+ // See issue 18153.
+ if runtime.GOOS == "linux" {
+ t.tests = append(t.tests, distTest{
+ name: "cmd_go_test_terminal",
+ heading: "cmd/go terminal test",
+ fn: func(dt *distTest) error {
+ t.runPending(dt)
+ if !stdOutErrAreTerminals() {
+ fmt.Println("skipping terminal test; stdout/stderr not terminals")
+ return nil
+ }
+ cmd := exec.Command("go", "test")
+ cmd.Dir = filepath.Join(os.Getenv("GOROOT"), "src/cmd/go/testdata/testterminal18153")
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ return cmd.Run()
+ },
+ })
+ }
+
// Fast path to avoid the ~1 second of `go list std cmd` when
// the caller lists specific tests to run. (as the continuous
// build coordinator does).
--- /dev/null
+// Copyright 2016 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 linux
+
+package main
+
+import (
+ "syscall"
+ "unsafe"
+)
+
+const ioctlReadTermios = syscall.TCGETS
+
+// isTerminal reports whether fd is a terminal.
+func isTerminal(fd uintptr) bool {
+ var termios syscall.Termios
+ _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
+ return err == 0
+}
+
+func init() {
+ stdOutErrAreTerminals = func() bool {
+ return isTerminal(1) && isTerminal(2)
+ }
+}
"go/doc"
"go/parser"
"go/token"
- "io"
"os"
"os/exec"
"path"
cmd.Env = envForDir(cmd.Dir, origEnv)
var buf bytes.Buffer
if testStreamOutput {
- // The only way to keep the ordering of the messages and still
- // intercept its contents. os/exec will share the same Pipe for
- // both Stdout and Stderr when running the test program.
- mw := io.MultiWriter(os.Stdout, &buf)
- cmd.Stdout = mw
- cmd.Stderr = mw
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
} else {
cmd.Stdout = &buf
cmd.Stderr = &buf
t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds())
if err == nil {
norun := ""
- if testShowPass && !testStreamOutput {
+ if testShowPass {
a.testOutput.Write(out)
}
if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
setExitStatus(1)
if len(out) > 0 {
- if !testStreamOutput {
- a.testOutput.Write(out)
- }
+ a.testOutput.Write(out)
// assume printing the test binary's exit status is superfluous
} else {
fmt.Fprintf(a.testOutput, "%s\n", err)
--- /dev/null
+// Copyright 2016 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 linux
+
+// This test is run by src/cmd/dist/test.go (cmd_go_test_terminal),
+// and not by cmd/go's tests. This is because this test requires that
+// that it be called with its stdout and stderr being a terminal.
+// dist doesn't run `cmd/go test` against this test directory if
+// dist's stdout/stderr aren't terminals.
+//
+// See issue 18153.
+
+package p
+
+import (
+ "syscall"
+ "testing"
+ "unsafe"
+)
+
+const ioctlReadTermios = syscall.TCGETS
+
+// isTerminal reports whether fd is a terminal.
+func isTerminal(fd uintptr) bool {
+ var termios syscall.Termios
+ _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0)
+ return err == 0
+}
+
+func TestIsTerminal(t *testing.T) {
+ if !isTerminal(1) {
+ t.Errorf("stdout is not a terminal")
+ }
+ if !isTerminal(2) {
+ t.Errorf("stderr is not a terminal")
+ }
+}