Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: test terminal fail in package list mode, success in local directory mode #68851

Closed
ericwq opened this issue Aug 13, 2024 · 7 comments
Closed

Comments

@ericwq
Copy link

ericwq commented Aug 13, 2024

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.

@ericwq
Copy link
Author

ericwq commented Aug 13, 2024

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.

@ericwq
Copy link
Author

ericwq commented Aug 13, 2024

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
		}
	}

@Zxilly
Copy link
Member

Zxilly commented Aug 13, 2024

#24929

#46959

Seems like a intended behavior.

@ericwq
Copy link
Author

ericwq commented Aug 13, 2024

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.

@seankhliao
Copy link
Member

Duplicate of #34877

@seankhliao seankhliao marked this as a duplicate of #34877 Aug 13, 2024
@seankhliao seankhliao closed this as not planned Won't fix, can't repro, duplicate, stale Aug 13, 2024
@ericwq
Copy link
Author

ericwq commented Aug 13, 2024

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()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants