koding / multiconfig

Load configuration from multiple sources in Go
http://godoc.org/github.com/koding/multiconfig
MIT License
454 stars 64 forks source link

When working with glog,It gets flag provided but not defined: -alsologtostderr #41

Closed phpgao closed 6 years ago

phpgao commented 8 years ago

Because of the flagSet.Parse(args) ignored the flags defined by glog,I added flag.VisitAll before it.

Works fine.


    flag.VisitAll(func(ff *flag.Flag) {
        f.flagSet.Var(ff.Value, ff.Name, ff.Usage)
    })
hyacinthus commented 8 years ago

same problem in go test -v

peterbueschel commented 7 years ago

Hi,

I ran also into this issue via "go test -v". A workaround for me is to add:

import (
     "flag" // <-- added
     "testing"
)

func init() {
   flag.Set("test.v", "true") // or false, if you don't want to have the verbose output per default
}

// rest of your testing stuff

Then run "go test" (w/o "-v").

But, it enables the verbose output per default. If I run "go test -v", I will get the "flag provided but not defined: -test.v" error.

So, there is a kind of "race condition" parsing the flags.

rjeczalik commented 7 years ago

@l0wm4x Could you share your code to show how do you setup your multiconfig.MultiLoader? I'm not quite sure why the original report mentions glog package.

peterbueschel commented 7 years ago

Hi @rjeczalik,

here they are (the interesting parts):

my current test file:

package getdatapoints

import (
    "flag"
    "fmt"
    "reflect"
    "testing"
)

// workaround. Now verbose testing
// is default.
func init() {
    flag.Set("test.v", "true")
}

func Test_ParseTOML(t *testing.T) {
    type args struct {
        filename string
    }
    tests := []struct {
        name    string
        args    args
        want    Config
        wantErr bool
    }{
        {
            name: "positivTest",
            args: args{filename: "test_config.toml"},
            want: Config{
                Server{
                    Hostname: "blah.com",
                    Username: "user",
                    Password: "12345678",
                },
            },
            wantErr: false,
        },
    }
    for index, tt := range tests {
        tt := tt
        t.Run(fmt.Sprint(index), func(t *testing.T) {
            c := Config{}
            err := c.ParseTOML(tt.args.filename)
            if (err != nil) != tt.wantErr {
                t.Errorf("ParseTOML() error = %v, wantErr %v", err, tt.wantErr)
                return
            }
            if !reflect.DeepEqual(c, tt.want) {
                t.Errorf("ParseTOML() = %v, want %v", c, tt.want)
            }
        })
    }
}

my code:

// file configuration.go

package getdatapoints

import (
    "github.com/koding/multiconfig"
)

type (
    Config struct {
        Server Server
    }
    Server struct {
        Username string
        Password string
        Hostname string
    }
)

func (c *Config) ParseTOML(filename string) error {
    m := multiconfig.NewWithPath(filename)
    err := m.Load(c)
    if err != nil {
        return err
    }
    return nil
}

And the config file

[Server]
Username = "user"
Password = "12345678"
Hostname = "blah.com"

I hope that helps.

rjeczalik commented 7 years ago

@l0wm4x I haven't tried that code yet, but from the quick glance you probably do not want to mix os.Args with testing package, as it defines its own. Since NewWithPath uses FlagLoader (which reads os.Args), I'd either use TOMLLoader directly or set FlagLoader.Args to some fake values in your testing code.

peterbueschel commented 7 years ago

@rjeczalik : Great!! Using TOMLLoader directly, works for me :-). Thank you.