mirror of
https://github.com/golang/go
synced 2024-11-18 06:54:49 -07:00
cmd/go: ensure streaming test's stdout, stderr are same as cmd/go's
Fixes #18153 Change-Id: Ie8a32dd6fe306f00e51cde77dd4ea353f7109940 Reviewed-on: https://go-review.googlesource.com/34010 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
94a4485f70
commit
0be4ef3ea6
26
src/cmd/dist/test.go
vendored
26
src/cmd/dist/test.go
vendored
@ -15,6 +15,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -331,6 +332,10 @@ func (t *tester) registerRaceBenchTest(pkg string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stdOutErrAreTerminals is defined in test_linux.go, to report
|
||||||
|
// whether stdout & stderr are terminals.
|
||||||
|
var stdOutErrAreTerminals func() bool
|
||||||
|
|
||||||
func (t *tester) registerTests() {
|
func (t *tester) registerTests() {
|
||||||
if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-vetall") {
|
if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-vetall") {
|
||||||
// Run vet over std and cmd and call it quits.
|
// Run vet over std and cmd and call it quits.
|
||||||
@ -347,6 +352,27 @@ func (t *tester) registerTests() {
|
|||||||
return
|
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
|
// Fast path to avoid the ~1 second of `go list std cmd` when
|
||||||
// the caller lists specific tests to run. (as the continuous
|
// the caller lists specific tests to run. (as the continuous
|
||||||
// build coordinator does).
|
// build coordinator does).
|
||||||
|
27
src/cmd/dist/test_linux.go
vendored
Normal file
27
src/cmd/dist/test_linux.go
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,6 @@ import (
|
|||||||
"go/doc"
|
"go/doc"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
"io"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
@ -1122,12 +1121,8 @@ func (b *builder) runTest(a *action) error {
|
|||||||
cmd.Env = envForDir(cmd.Dir, origEnv)
|
cmd.Env = envForDir(cmd.Dir, origEnv)
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if testStreamOutput {
|
if testStreamOutput {
|
||||||
// The only way to keep the ordering of the messages and still
|
cmd.Stdout = os.Stdout
|
||||||
// intercept its contents. os/exec will share the same Pipe for
|
cmd.Stderr = os.Stderr
|
||||||
// both Stdout and Stderr when running the test program.
|
|
||||||
mw := io.MultiWriter(os.Stdout, &buf)
|
|
||||||
cmd.Stdout = mw
|
|
||||||
cmd.Stderr = mw
|
|
||||||
} else {
|
} else {
|
||||||
cmd.Stdout = &buf
|
cmd.Stdout = &buf
|
||||||
cmd.Stderr = &buf
|
cmd.Stderr = &buf
|
||||||
@ -1192,7 +1187,7 @@ func (b *builder) runTest(a *action) error {
|
|||||||
t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds())
|
t := fmt.Sprintf("%.3fs", time.Since(t0).Seconds())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
norun := ""
|
norun := ""
|
||||||
if testShowPass && !testStreamOutput {
|
if testShowPass {
|
||||||
a.testOutput.Write(out)
|
a.testOutput.Write(out)
|
||||||
}
|
}
|
||||||
if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
|
if bytes.HasPrefix(out, noTestsToRun[1:]) || bytes.Contains(out, noTestsToRun) {
|
||||||
@ -1204,9 +1199,7 @@ func (b *builder) runTest(a *action) error {
|
|||||||
|
|
||||||
setExitStatus(1)
|
setExitStatus(1)
|
||||||
if len(out) > 0 {
|
if len(out) > 0 {
|
||||||
if !testStreamOutput {
|
|
||||||
a.testOutput.Write(out)
|
a.testOutput.Write(out)
|
||||||
}
|
|
||||||
// assume printing the test binary's exit status is superfluous
|
// assume printing the test binary's exit status is superfluous
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(a.testOutput, "%s\n", err)
|
fmt.Fprintf(a.testOutput, "%s\n", err)
|
||||||
|
39
src/cmd/go/testdata/testterminal18153/terminal_test.go
vendored
Normal file
39
src/cmd/go/testdata/testterminal18153/terminal_test.go
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// 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")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user