Go version
go version go1.22.5 darwin/amd64
Output of go env
in your module/workspace:
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/Users/qiwang/Library/Caches/go-build'
GOENV='/Users/qiwang/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/qiwang/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/qiwang/go'
GOPRIVATE=''
GOPROXY='https://goproxy.cn,direct'
GOROOT='/usr/local/Cellar/go/1.22.5/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/Cellar/go/1.22.5/libexec/pkg/tool/darwin_amd64'
GOVCS=''
GOVERSION='go1.22.5'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/Users/qiwang/dev/aprilsh/go.mod'
GOWORK='/Users/qiwang/dev/go.work'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/ww/tyqfl83d24n5m09cng7ccb2m0000gn/T/go-build771410576=/tmp/go-build -gno-record-gcc-switches -fno-common'
What did you do?
run test terminal as follows:
package main
import (
"os"
"testing"
"golang.org/x/term"
)
func TestQT(t *testing.T) {
if tm := term.IsTerminal(int(os.Stdout.Fd())); !tm {
t.Fatalf("%s is not terminal\n", os.Stdout.Name())
}
}
What did you see happen?
test passed in local directory mode:
qiwang@Qi15Pro client % go test
PASS
ok github.com/ericwq/aprilsh/frontend/client 2.263s
test failed in package list mode:
qiwang@Qi15Pro client % go test .
--- FAIL: TestQT (0.00s)
client_test.go:627: /dev/stdout is not terminal
FAIL
FAIL github.com/ericwq/aprilsh/frontend/client 1.535s
FAIL
What did you expect to see?
test passed in package list mode.
Comment From: gabyhelp
Related Issues and Documentation
- cmd/go: all.bash tests fail on master (ab9d31da9e) in TestIsTerminal #52461 (closed)
- cmd/go: test in package list mode doesn't print unexpected "exit status" messages #56637 (closed)
- cmd/go: all.bash test failure in the terminal test from commit 1fba10c999 #34791 (closed)
- cmd/go: TestScript/gotoolchain_issue66175 fails on tip locally #67277 (closed)
- x/term: Why IsTerminal reports `true` on redirected `stdout`? [unrelated] #42003 (closed)
- cmd/go: TestScript/env_write failed #32503 (closed)
- cmd/go: go test -i doesn't work if there are no Go files in the current directory #38394 (closed)
- import/path: core #67494 (closed)
- cmd/go: output of go test varies by mode #23258 (closed)
- cmd/go/internal/test: compile error for `go test` on package with no test files does not output package-level "FAIL" error #64286
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
Comment From: ericwq
thanks, I checked the above posts. none of them is same issue. #34791 is the most similar but not same issue.
In different mode, go test treat os.Stdout differently. it doesn't make sense for me.
Comment From: ericwq
test.go, 1440 line, might be the key to answer the question.
var buf bytes.Buffer
if len(pkgArgs) == 0 || testBench != "" || testFuzz != "" {
// Stream test output (no buffering) when no package has
// been given on the command line (implicit current directory)
// or when benchmarking or fuzzing.
// No change to stdout.
} else {
// If we're only running a single package under test or if parallelism is
// set to 1, and if we're displaying all output (testShowPass), we can
// hurry the output along, echoing it as soon as it comes in.
// We still have to copy to &buf for caching the result. This special
// case was introduced in Go 1.5 and is intentionally undocumented:
// the exact details of output buffering are up to the go command and
// subject to change. It would be nice to remove this special case
// entirely, but it is surely very helpful to see progress being made
// when tests are run on slow single-CPU ARM systems.
//
// If we're showing JSON output, then display output as soon as
// possible even when multiple tests are being run: the JSON output
// events are attributed to specific package tests, so interlacing them
// is OK.
if testShowPass() && (len(pkgs) == 1 || cfg.BuildP == 1) || testJSON {
// Write both to stdout and buf, for possible saving
// to cache, and for looking for the "no tests to run" message.
stdout = io.MultiWriter(stdout, &buf)
} else {
stdout = &buf
}
}
Comment From: Zxilly
https://github.com/golang/go/issues/24929
https://github.com/golang/go/issues/46959
Seems like a intended behavior.
Comment From: ericwq
thanks, @Zxilly.
after check test.go. I am sure that the above code is the root cause of this issue. For package list mode, stdout is decorated with io.MultiWriter. io.MultiWriter is not a terminal anymore. For local directory mode, stdout is unchanged, it's still a terminal for the test.
can anyone know how to get the undecorated stdout?
anyway, In different mode, go test treat os.Stdout differently. it doesn't make sense for me.
Comment From: seankhliao
Duplicate of #34877
Comment From: ericwq
use /dev/tty
instead of os.Stdout. the following test will pass for both mode.
func TestQT(t *testing.T) {
f, _ := os.Open("/dev/tty")
if tm := term.IsTerminal(int(f.Fd())); !tm {
t.Errorf("%s is not terminal\n", f.Name())
}
f.Close()
}