From 99bcedf5411e47380739c8999a6ae3fdd0739fa3 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Fri, 16 Jan 2015 11:24:28 -0800 Subject: Fix unit tests to include Type() method in custom types This was broken by commit 463bdc838f2b35 ("Adding Type() method to the values.") which added the method to the interface but did not update the custom types in unit tests. Signed-off-by: Filipe Brandenburger --- example_test.go | 4 ++++ flag_test.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/example_test.go b/example_test.go index 03ebeaa..6aaed3c 100644 --- a/example_test.go +++ b/example_test.go @@ -29,6 +29,10 @@ func (i *interval) String() string { return fmt.Sprint(*i) } +func (i *interval) Type() string { + return "interval" +} + // Set is the method to set the flag value, part of the flag.Value interface. // Set's argument is a string to be parsed to set the flag. // It's a comma-separated list, so we split it. diff --git a/flag_test.go b/flag_test.go index 4d95b15..47865bd 100644 --- a/flag_test.go +++ b/flag_test.go @@ -245,6 +245,10 @@ func (f *flagVar) Set(value string) error { return nil } +func (f *flagVar) Type() string { + return "flagVar" +} + func TestUserDefined(t *testing.T) { var flags FlagSet flags.Init("test", ContinueOnError) -- cgit v1.2.3 From c75d600940b76354bc18d26d10c0ecd03b31f758 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Fri, 16 Jan 2015 10:43:36 -0800 Subject: Add support for custom boolean flags through IsBoolFlag() This is consistent with Go's native flag parsing module and can be used to implement custom boolean/tri-state flags. Signed-off-by: Filipe Brandenburger --- bool.go | 9 +++++++++ flag.go | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/bool.go b/bool.go index 010576c..70e2e0a 100644 --- a/bool.go +++ b/bool.go @@ -5,6 +5,13 @@ import ( "strconv" ) +// optional interface to indicate boolean flags that can be +// supplied without "=value" text +type boolFlag interface { + Value + IsBoolFlag() bool +} + // -- bool Value type boolValue bool @@ -25,6 +32,8 @@ func (b *boolValue) Type() string { func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) } +func (b *boolValue) IsBoolFlag() bool { return true } + // BoolVar defines a bool flag with specified name, default value, and usage string. // The argument p points to a bool variable in which to store the value of the flag. func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) { diff --git a/flag.go b/flag.go index 47761a0..2e4cac0 100644 --- a/flag.go +++ b/flag.go @@ -466,7 +466,7 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) return } if len(split) == 1 { - if _, ok := flag.Value.(*boolValue); !ok { + if bv, ok := flag.Value.(boolFlag); !ok || !bv.IsBoolFlag() { err = f.failf("flag needs an argument: %s", s) return } @@ -500,7 +500,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) } } if alreadythere { - if _, ok := flag.Value.(*boolValue); ok { + if bv, ok := flag.Value.(boolFlag); ok && bv.IsBoolFlag() { f.setFlag(flag, "true", s) continue } -- cgit v1.2.3 From 376ea2fc4b79bc6fbca80f585898271e7890d6b5 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Fri, 16 Jan 2015 11:12:25 -0800 Subject: Add unit test case for IsBoolValue() implementing a tri-state flag (true/false/maybe) Signed-off-by: Filipe Brandenburger --- bool_test.go | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 bool_test.go diff --git a/bool_test.go b/bool_test.go new file mode 100644 index 0000000..72a12be --- /dev/null +++ b/bool_test.go @@ -0,0 +1,163 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package pflag_test + +import ( + "fmt" + "strconv" + "testing" + + . "github.com/ogier/pflag" +) + +// This value can be a boolean ("true", "false") or "maybe" +type triStateValue int + +const ( + triStateFalse triStateValue = 0 + triStateTrue triStateValue = 1 + triStateMaybe triStateValue = 2 +) + +const strTriStateMaybe = "maybe" + +func (v *triStateValue) IsBoolFlag() bool { + return true +} + +func (v *triStateValue) Get() interface{} { + return triStateValue(*v) +} + +func (v *triStateValue) Set(s string) error { + if s == strTriStateMaybe { + *v = triStateMaybe + return nil + } + boolVal, err := strconv.ParseBool(s) + if boolVal { + *v = triStateTrue + } else { + *v = triStateFalse + } + return err +} + +func (v *triStateValue) String() string { + if *v == triStateMaybe { + return strTriStateMaybe + } + return fmt.Sprintf("%v", bool(*v == triStateTrue)) +} + +// The type of the flag as requred by the pflag.Value interface +func (v *triStateValue) Type() string { + return "version" +} + +func setUpFlagSet(tristate *triStateValue) *FlagSet { + f := NewFlagSet("test", ContinueOnError) + *tristate = triStateFalse + f.VarP(tristate, "tristate", "t", "tristate value (true, maybe or false)") + return f +} + +func TestExplicitTrue(t *testing.T) { + var tristate triStateValue + f := setUpFlagSet(&tristate) + err := f.Parse([]string{"--tristate=true"}) + if err != nil { + t.Fatal("expected no error; got", err) + } + if tristate != triStateTrue { + t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") + } +} + +func TestImplicitTrue(t *testing.T) { + var tristate triStateValue + f := setUpFlagSet(&tristate) + err := f.Parse([]string{"--tristate"}) + if err != nil { + t.Fatal("expected no error; got", err) + } + if tristate != triStateTrue { + t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") + } +} + +func TestShortFlag(t *testing.T) { + var tristate triStateValue + f := setUpFlagSet(&tristate) + err := f.Parse([]string{"-t"}) + if err != nil { + t.Fatal("expected no error; got", err) + } + if tristate != triStateTrue { + t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") + } +} + +func TestShortFlagExtraArgument(t *testing.T) { + var tristate triStateValue + f := setUpFlagSet(&tristate) + // The"maybe"turns into an arg, since short boolean options will only do true/false + err := f.Parse([]string{"-t", "maybe"}) + if err != nil { + t.Fatal("expected no error; got", err) + } + if tristate != triStateTrue { + t.Fatal("expected", triStateTrue, "(triStateTrue) but got", tristate, "instead") + } + args := f.Args() + if len(args) != 1 || args[0] != "maybe" { + t.Fatal("expected an extra 'maybe' argument to stick around") + } +} + +func TestExplicitMaybe(t *testing.T) { + var tristate triStateValue + f := setUpFlagSet(&tristate) + err := f.Parse([]string{"--tristate=maybe"}) + if err != nil { + t.Fatal("expected no error; got", err) + } + if tristate != triStateMaybe { + t.Fatal("expected", triStateMaybe, "(triStateMaybe) but got", tristate, "instead") + } +} + +func TestExplicitFalse(t *testing.T) { + var tristate triStateValue + f := setUpFlagSet(&tristate) + err := f.Parse([]string{"--tristate=false"}) + if err != nil { + t.Fatal("expected no error; got", err) + } + if tristate != triStateFalse { + t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead") + } +} + +func TestImplicitFalse(t *testing.T) { + var tristate triStateValue + f := setUpFlagSet(&tristate) + err := f.Parse([]string{}) + if err != nil { + t.Fatal("expected no error; got", err) + } + if tristate != triStateFalse { + t.Fatal("expected", triStateFalse, "(triStateFalse) but got", tristate, "instead") + } +} + +func TestInvalidValue(t *testing.T) { + var tristate triStateValue + f := setUpFlagSet(&tristate) + err := f.Parse([]string{"--tristate=invalid"}) + if err == nil { + t.Fatal("expected an error but did not get any, tristate has value", tristate) + } +} -- cgit v1.2.3