Skip to content

Commit 76a89d6

Browse files
Bryan C. Millsdmitshur
Bryan C. Mills
authored andcommitted
[release-branch.go1.15] cmd/go/internal/test: keep looking for go command flags after ambiguous test flag
Updates #40763 Fixes #40802 Change-Id: I275970d1f8561414571a5b93e368d68fa052c60f Reviewed-on: https://go-review.googlesource.com/c/go/+/248618 Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Jay Conrod <[email protected]> (cherry picked from commit 797124f) Reviewed-on: https://go-review.googlesource.com/c/go/+/248726
1 parent 60fdbce commit 76a89d6

File tree

2 files changed

+54
-10
lines changed

2 files changed

+54
-10
lines changed

src/cmd/go/internal/test/testflag.go

+25-4
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,13 @@ func testFlags(args []string) (packageNames, passToTest []string) {
214214

215215
explicitArgs := make([]string, 0, len(args))
216216
inPkgList := false
217+
afterFlagWithoutValue := false
217218
for len(args) > 0 {
218219
f, remainingArgs, err := cmdflag.ParseOne(&CmdTest.Flag, args)
219220

221+
wasAfterFlagWithoutValue := afterFlagWithoutValue
222+
afterFlagWithoutValue = false // provisionally
223+
220224
if errors.Is(err, flag.ErrHelp) {
221225
exitWithUsage()
222226
}
@@ -233,10 +237,24 @@ func testFlags(args []string) (packageNames, passToTest []string) {
233237
if nf := (cmdflag.NonFlagError{}); errors.As(err, &nf) {
234238
if !inPkgList && packageNames != nil {
235239
// We already saw the package list previously, and this argument is not
236-
// a flag, so it — and everything after it — must be a literal argument
237-
// to the test binary.
238-
explicitArgs = append(explicitArgs, args...)
239-
break
240+
// a flag, so it — and everything after it — must be either a value for
241+
// a preceding flag or a literal argument to the test binary.
242+
if wasAfterFlagWithoutValue {
243+
// This argument could syntactically be a flag value, so
244+
// optimistically assume that it is and keep looking for go command
245+
// flags after it.
246+
//
247+
// (If we're wrong, we'll at least be consistent with historical
248+
// behavior; see https://golang.org/issue/40763.)
249+
explicitArgs = append(explicitArgs, nf.RawArg)
250+
args = remainingArgs
251+
continue
252+
} else {
253+
// This argument syntactically cannot be a flag value, so it must be a
254+
// positional argument, and so must everything after it.
255+
explicitArgs = append(explicitArgs, args...)
256+
break
257+
}
240258
}
241259

242260
inPkgList = true
@@ -272,6 +290,9 @@ func testFlags(args []string) (packageNames, passToTest []string) {
272290

273291
explicitArgs = append(explicitArgs, nd.RawArg)
274292
args = remainingArgs
293+
if !nd.HasValue {
294+
afterFlagWithoutValue = true
295+
}
275296
continue
276297
}
277298

src/cmd/go/testdata/script/test_flags.txt

+29-6
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,30 @@ stdout '\Aok\s+example.com/x\s+[0-9.s]+\n\z'
1010
! stderr .
1111

1212
# For backward-compatibility with previous releases of the 'go' command,
13-
# arguments that appear after unrecognized flags should not be treated
13+
# arguments that appear after unrecognized flags should not be treated
1414
# as packages, even if they are unambiguously not arguments to flags.
1515
# Even though ./x looks like a package path, the real package should be
1616
# the implicit '.'.
1717
! go test --answer=42 ./x
1818
stderr '^no Go files in .+$'
1919
! stderr '/x'
2020

21+
# However, *flags* that appear after unrecognized flags should still be
22+
# interpreted as flags, under the (possibly-erroneous) assumption that
23+
# unrecognized flags are non-boolean.
24+
25+
go test -v -x ./x -timeout 24h -boolflag=true foo -timeout 25h
26+
stdout 'args: foo -timeout 25h'
27+
stdout 'timeout: 24h0m0s$' # -timeout is unambiguously not a flag, so the real flag wins.
28+
29+
go test -v -x ./x -timeout 24h -boolflag foo -timeout 25h
30+
stdout 'args: foo -test\.timeout=25h0m0s' # For legacy reasons, '-timeout ' is erroneously rewritten to -test.timeout; see https://golang.org/issue/40763.
31+
stdout 'timeout: 24h0m0s$' # Actual flag wins.
32+
33+
go test -v -x ./x -timeout 24h -stringflag foo -timeout 25h
34+
stdout 'args: $'
35+
stdout 'timeout: 25h0m0s$' # Later flag wins.
36+
2137
# An explicit '-outputdir=' argument should set test.outputdir
2238
# to the 'go' command's working directory, not zero it out
2339
# for the test binary.
@@ -30,23 +46,23 @@ exists ./cover.out
3046
# with the 'test.' prefix in the GOFLAGS entry...
3147
env GOFLAGS='-test.timeout=24h0m0s -count=1'
3248
go test -v -x ./x
33-
stdout '.*: 24h0m0s$'
49+
stdout 'timeout: 24h0m0s$'
3450
stderr '-test.count=1'
3551

3652
# ...or without.
3753
env GOFLAGS='-timeout=24h0m0s -count=1'
3854
go test -v -x ./x
39-
stdout '.*: 24h0m0s$'
55+
stdout 'timeout: 24h0m0s$'
4056
stderr '-test.count=1'
4157

4258
# Arguments from the command line should override GOFLAGS...
4359
go test -v -x -timeout=25h0m0s ./x
44-
stdout '.*: 25h0m0s$'
60+
stdout 'timeout: 25h0m0s$'
4561
stderr '-test.count=1'
4662

4763
# ...even if they use a different flag name.
4864
go test -v -x -test.timeout=26h0m0s ./x
49-
stdout '.*: 26h0m0s$'
65+
stdout 'timeout: 26h0m0s$'
5066
stderr '-test\.timeout=26h0m0s'
5167
! stderr 'timeout=24h0m0s'
5268
stderr '-test.count=1'
@@ -99,11 +115,18 @@ package x
99115

100116
import (
101117
"flag"
118+
"strings"
102119
"testing"
103120
)
104121

105122
var _ = flag.String("usage_message", "", "dummy flag to check usage message")
123+
var boolflag = flag.Bool("boolflag", false, "ignored boolean flag")
124+
var stringflag = flag.String("stringflag", "", "ignored string flag")
106125

107126
func TestLogTimeout(t *testing.T) {
108-
t.Log(flag.Lookup("test.timeout").Value)
127+
t.Logf("timeout: %v", flag.Lookup("test.timeout").Value)
128+
}
129+
130+
func TestLogArgs(t *testing.T) {
131+
t.Logf("args: %s", strings.Join(flag.Args(), " "))
109132
}

0 commit comments

Comments
 (0)