From b5bc87ce5958188748cb9efdb6b8c2b445fd9a9b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Jul 2015 00:04:50 -0400 Subject: [PATCH] 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/12170 Reviewed-by: Rob Pike --- src/cmd/go/build.go | 8 +-- src/cmd/go/testflag.go | 156 ++++++++++++++++++++--------------------- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index 68fdb98b7a..93aa454666 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -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) { diff --git a/src/cmd/go/testflag.go b/src/cmd/go/testflag.go index 03416d582e..ee4ab187e0 100644 --- a/src/cmd/go/testflag.go +++ b/src/cmd/go/testflag.go @@ -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) -- 2.48.1