Commit b5bc87ce authored by Russ Cox's avatar Russ Cox

cmd/go: remove duplication of build flag info in testflag.go

Also adds to 'go test' all the build flags that were missing
due to inconsistency in the duplication (for example, -toolexec).

Fixes #10504.

Change-Id: I1935b5caa13d5e551a0483904adffa8877087df7
Reviewed-on: https://go-review.googlesource.com/12170Reviewed-by: default avatarRob Pike <r@golang.org>
parent 3585f215
......@@ -200,20 +200,20 @@ func addBuildFlags(cmd *Command) {
cmd.Flag.BoolVar(&buildA, "a", false, "")
cmd.Flag.BoolVar(&buildN, "n", false, "")
cmd.Flag.IntVar(&buildP, "p", buildP, "")
cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "")
cmd.Flag.BoolVar(&buildV, "v", false, "")
cmd.Flag.BoolVar(&buildX, "x", false, "")
cmd.Flag.BoolVar(&buildWork, "work", false, "")
cmd.Flag.Var((*stringsFlag)(&buildAsmflags), "asmflags", "")
cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "")
cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "")
cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "")
cmd.Flag.Var(buildCompiler{}, "compiler", "")
cmd.Flag.BoolVar(&buildRace, "race", false, "")
cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "")
cmd.Flag.StringVar(&buildBuildmode, "buildmode", "default", "")
cmd.Flag.BoolVar(&buildLinkshared, "linkshared", false, "")
cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "")
cmd.Flag.BoolVar(&buildWork, "work", false, "")
}
func addBuildFlagsNX(cmd *Command) {
......
......@@ -5,6 +5,7 @@
package main
import (
"flag"
"fmt"
"os"
"strconv"
......@@ -20,6 +21,7 @@ import (
type testFlagSpec struct {
name string
boolVar *bool
flagValue flag.Value
passToTest bool // pass to Test
multiOK bool // OK to have multiple instances
present bool // flag has been seen
......@@ -29,27 +31,11 @@ type testFlagSpec struct {
var testFlagDefn = []*testFlagSpec{
// local.
{name: "c", boolVar: &testC},
{name: "i", boolVar: &buildI},
{name: "o"},
{name: "cover", boolVar: &testCover},
{name: "covermode"},
{name: "coverpkg"},
{name: "o"},
// build flags.
{name: "a", boolVar: &buildA},
{name: "n", boolVar: &buildN},
{name: "p"},
{name: "x", boolVar: &buildX},
{name: "i", boolVar: &buildI},
{name: "work", boolVar: &buildWork},
{name: "gcflags"},
{name: "exec"},
{name: "ldflags"},
{name: "gccgoflags"},
{name: "tags"},
{name: "compiler"},
{name: "race", boolVar: &buildRace},
{name: "linkshared", boolVar: &buildLinkshared},
{name: "installsuffix"},
// passed to 6.out, adding a "test." prefix to the name if necessary: -v becomes -test.v.
{name: "bench", passToTest: true},
......@@ -72,6 +58,22 @@ var testFlagDefn = []*testFlagSpec{
{name: "v", boolVar: &testV, passToTest: true},
}
// add build flags to testFlagDefn
func init() {
var cmd Command
addBuildFlags(&cmd)
cmd.Flag.VisitAll(func(f *flag.Flag) {
if f.Name == "v" {
// test overrides the build -v flag
return
}
testFlagDefn = append(testFlagDefn, &testFlagSpec{
name: f.Name,
flagValue: f.Value,
})
})
}
// testFlags processes the command line, grabbing -x and -c, rewriting known flags
// to have "test" before them, and reading the command line for the 6.out.
// Unfortunately for us, we need to do our own flag processing because go test
......@@ -114,68 +116,55 @@ func testFlags(args []string) (packageNames, passToTest []string) {
passToTest = append(passToTest, args[i])
continue
}
var err error
switch f.name {
// bool flags.
case "a", "c", "i", "n", "x", "v", "race", "cover", "work", "linkshared":
setBoolFlag(f.boolVar, value)
case "o":
testO = value
testNeedBinary = true
case "p":
setIntFlag(&buildP, value)
case "exec":
execCmd, err = splitQuotedFields(value)
if err != nil {
if f.flagValue != nil {
if err := f.flagValue.Set(value); err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "gcflags":
buildGcflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "ldflags":
buildLdflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "gccgoflags":
buildGccgoflags, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "tags":
buildContext.BuildTags = strings.Fields(value)
case "compiler":
buildCompiler{}.Set(value)
case "bench":
// record that we saw the flag; don't care about the value
testBench = true
case "timeout":
testTimeout = value
case "blockprofile", "cpuprofile", "memprofile", "trace":
testProfile = true
testNeedBinary = true
case "coverpkg":
testCover = true
if value == "" {
testCoverPaths = nil
} else {
testCoverPaths = strings.Split(value, ",")
}
case "coverprofile":
testCover = true
testProfile = true
case "covermode":
switch value {
case "set", "count", "atomic":
testCoverMode = value
default:
fatalf("invalid flag argument for -covermode: %q", value)
} else {
// Test-only flags.
// Arguably should be handled by f.flagValue, but aren't.
var err error
switch f.name {
// bool flags.
case "c", "i", "v", "cover":
setBoolFlag(f.boolVar, value)
case "o":
testO = value
testNeedBinary = true
case "exec":
execCmd, err = splitQuotedFields(value)
if err != nil {
fatalf("invalid flag argument for -%s: %v", f.name, err)
}
case "bench":
// record that we saw the flag; don't care about the value
testBench = true
case "timeout":
testTimeout = value
case "blockprofile", "cpuprofile", "memprofile", "trace":
testProfile = true
testNeedBinary = true
case "coverpkg":
testCover = true
if value == "" {
testCoverPaths = nil
} else {
testCoverPaths = strings.Split(value, ",")
}
case "coverprofile":
testCover = true
testProfile = true
case "covermode":
switch value {
case "set", "count", "atomic":
testCoverMode = value
default:
fatalf("invalid flag argument for -covermode: %q", value)
}
testCover = true
case "outputdir":
outputDir = value
}
testCover = true
case "outputdir":
outputDir = value
}
if extraWord {
i++
......@@ -228,7 +217,7 @@ func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool)
for _, f = range testFlagDefn {
if name == f.name {
// Booleans are special because they have modes -x, -x=true, -x=false.
if f.boolVar != nil {
if f.boolVar != nil || isBoolFlag(f.flagValue) {
if equals < 0 { // otherwise, it's been set and will be verified in setBoolFlag
value = "true"
} else {
......@@ -255,6 +244,17 @@ func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool)
return
}
// isBoolFlag reports whether v is a bool flag.
func isBoolFlag(v flag.Value) bool {
vv, ok := v.(interface {
IsBoolFlag() bool
})
if ok {
return vv.IsBoolFlag()
}
return false
}
// setBoolFlag sets the addressed boolean to the value.
func setBoolFlag(flag *bool, value string) {
x, err := strconv.ParseBool(value)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment