func TestParseArgsPointerFlagUnderPointerFlag(t *testing.T) {
	config := newConfiguration()
	flagMap := make(map[string]reflect.StructField)
	if err := getTypesRecursive(reflect.ValueOf(config), flagMap, ""); err != nil {
		t.Fatal(err)
	}
	parsers := map[reflect.Type]parse.Parser{
		reflect.TypeOf([]ServerInfo{}): &sliceServerValue{},
	}
	var boolParser parse.BoolValue
	parsers[reflect.TypeOf(true)] = &boolParser
	var intParser parse.IntValue
	parsers[reflect.TypeOf(1)] = &intParser
	var int64Parser parse.Int64Value
	parsers[reflect.TypeOf(int64(1))] = &int64Parser
	var uintParser parse.UintValue
	parsers[reflect.TypeOf(uint(1))] = &uintParser
	var uint64Parser parse.Uint64Value
	parsers[reflect.TypeOf(uint64(1))] = &uint64Parser
	var stringParser parse.StringValue
	parsers[reflect.TypeOf("")] = &stringParser
	var float64Parser parse.Float64Value
	parsers[reflect.TypeOf(float64(1.5))] = &float64Parser
	var durationParser parse.Duration
	parsers[reflect.TypeOf(parse.Duration(time.Second))] = &durationParser
	var timeParser parse.TimeValue
	parsers[reflect.TypeOf(time.Now())] = &timeParser
	args := []string{
		"--db",
		"--db.watch",
		"--db.connectionmax64=900",
	}
	valMap, err := parseArgs(args, flagMap, parsers)
	if err != nil {
		t.Fatal(err)
	}
	check := map[string]parse.Parser{}
	boolParser.SetValue(true)
	check["db"] = &boolParser
	uint64Parser.SetValue(uint64(900))
	check["db.connectionmax64"] = &uint64Parser
	check["db.watch"] = &boolParser
	if len(check) != len(valMap) {
		t.Errorf("expected %d elements in valMap got %d", len(check), len(valMap))
	}
	for flag, parser := range valMap {
		if !reflect.DeepEqual(parser, check[flag]) {
			t.Errorf("Got %s expected %s\n", parser, check[flag])
		}
	}
}
Test ParseArgs with flag on pointer and flag under a pointer together
package flaeg
import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"reflect"
	"sort"
	"strings"
	"testing"
	"time"
	"github.com/containous/flaeg/parse"
	"github.com/ogier/pflag"
)
type ConfigurationWithRepeatedStruct struct {
	Repeated  *RepeatedStruct          `description:"Repeated struct"`
	Container *RepeatedStructContainer `description:"Container"`
}
type RepeatedStruct struct {
	Val string `description:"Value"`
}
type RepeatedStructContainer struct {
	Repeated *RepeatedStruct `description:"Repeated struct"`
}
type Configuration struct {
	Name     string          
	LogLevel string         `short:"l" description:"Log level"`       
	Timeout  parse.Duration `description:"Timeout duration"`          
	Db       *DatabaseInfo  `description:"Enable database"`           
	Owner    *OwnerInfo     `description:"Enable Owner description"`  
}
type ServerInfo struct {
	Watch  bool   `description:"Watch device"`       
	IP     string `description:"Server ip address"`  
	Load   int    `description:"Server load"`        
	Load64 int64  `description:"Server load"`        
}
type DatabaseInfo struct {
	ServerInfo              
	ConnectionMax   uint   `long:"comax" description:"Number max of connections on database"`  
	ConnectionMax64 uint64 `description:"Number max of connections on database"`               
}
type OwnerInfo struct {
	Name        *string      `description:"Owner name"`                      
	DateOfBirth time.Time    `long:"dob" description:"Owner date of birth"`  
	Rate        float64      `description:"Owner rate"`                      
	Servers     []ServerInfo `description:"Owner Server"`                    
}
func newDefaultPointersConfiguration() *Configuration {
	var db DatabaseInfo
	db.Watch = true
	db.IP = "192.168.1.2"
	db.Load = 32
	db.Load64 = 64
	db.ConnectionMax = 3200000000             
	db.ConnectionMax64 = 6400000000000000000  
	var own OwnerInfo
	str := "DefaultOwnerNamePointer"
	own.Name = &str
	own.DateOfBirth, _ = time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
	own.Rate = 0.111
	own.Servers = []ServerInfo{
		{IP: "192.168.1.2"},
		{IP: "192.168.1.3"},
		{IP: "192.168.1.4"},
	}
	return &Configuration{
		Db:    &db,
		Owner: &own,
	}
}
func newConfiguration() *Configuration {
	var own OwnerInfo
	str := "InitOwnerNamePointer"
	own.Name = &str
	own.DateOfBirth, _ = time.Parse(time.RFC3339, "1993-09-12T07:32:00Z")
	own.Rate = 0.999
	return &Configuration{
		Name:     "initName",
		LogLevel: "DEBUG",
		Timeout:  parse.Duration(time.Second),
		Owner:    &own,
	}
}
func TestGetTypesRecursive(t *testing.T) {
	config := newConfiguration()
	flagMap := make(map[string]reflect.StructField)
	if err := getTypesRecursive(reflect.ValueOf(config), flagMap, ""); err != nil {
		t.Fatal(err)
	}
	checkType := map[string]reflect.Type{
		"loglevel":           reflect.TypeOf(""),
		"timeout":            reflect.TypeOf(parse.Duration(time.Second)),
		"db":                 reflect.TypeOf(true),
		"db.watch":           reflect.TypeOf(true),
		"db.ip":              reflect.TypeOf(""),
		"db.load":            reflect.TypeOf(0),
		"db.load64":          reflect.TypeOf(int64(0)),
		"db.comax":           reflect.TypeOf(uint(0)),
		"db.connectionmax64": reflect.TypeOf(uint64(0)),
		"owner":              reflect.TypeOf(true),
		"owner.name":         reflect.TypeOf(true),
		"owner.dob":          reflect.TypeOf(time.Now()),
		"owner.rate":         reflect.TypeOf(float64(1.1)),
		"owner.servers":      reflect.TypeOf([]ServerInfo{}),
	}
	if len(checkType) != len(flagMap) {
		t.Fatalf("expected %d elements in flagMap got %d", len(checkType), len(flagMap))
	}
	for name, field := range flagMap {
		if checkType[name] != field.Type {
			t.Errorf("Tag : %s, got %s expected %s\n", name, field.Type, checkType[name])
		}
	}
}
func TestGetFlags(t *testing.T) {
	config := newConfiguration()
	flags, err := GetFlags(config)
	if err != nil {
		t.Fatal(err)
	}
	check := []string{
		"loglevel",
		"timeout",
		"db",
		"db.watch",
		"db.ip",
		"db.load",
		"db.load64",
		"db.comax",
		"db.connectionmax64",
		"owner",
		"owner.name",
		"owner.dob",
		"owner.rate",
		"owner.servers",
	}
	if len(check) != len(flags) {
		t.Errorf("expected %d elements in parsers got %d", len(check), len(flags))
	}
	sort.Strings(check)
	sort.Strings(flags)
	if !reflect.DeepEqual(flags, check) {
		t.Errorf("Got %s expected %s\n", flags, check)
	}
}
func TestGetBoolFlags(t *testing.T) {
	config := newConfiguration()
	flags, err := GetBoolFlags(config)
	if err != nil {
		t.Fatal(err)
	}
	check := []string{
		"db",
		"db.watch",
		"owner",
		"owner.name",
	}
	if len(check) != len(flags) {
		t.Errorf("expected %d elements in parsers got %d", len(check), len(flags))
	}
	sort.Strings(check)
	sort.Strings(flags)
	if !reflect.DeepEqual(flags, check) {
		t.Errorf("Got %s expected %s\n", flags, check)
	}
}
type sliceServerValue []ServerInfo
func (c *sliceServerValue) Set(s string) error {
	srv := ServerInfo{IP: s}
	*c = append(*c, srv)
	return nil
}
func (c *sliceServerValue) Get() interface{} { return []ServerInfo(*c) }
func (c *sliceServerValue) String() string { return fmt.Sprintf("%v", *c) }
func (c *sliceServerValue) SetValue(val interface{}) {
	*c = sliceServerValue(val.([]ServerInfo))
}
func TestLoadParsers(t *testing.T) {
	customParsers := map[reflect.Type]parse.Parser{
		reflect.TypeOf([]ServerInfo{}): &sliceServerValue{},
	}
	parsers, err := parse.LoadParsers(customParsers)
	if err != nil {
		t.Fatal(err)
	}
	check := map[reflect.Type]parse.Parser{
		reflect.TypeOf([]ServerInfo{}): &sliceServerValue{},
	}
	var boolParser parse.BoolValue
	check[reflect.TypeOf(true)] = &boolParser
	var intParser parse.IntValue
	check[reflect.TypeOf(1)] = &intParser
	var int64Parser parse.Int64Value
	check[reflect.TypeOf(int64(1))] = &int64Parser
	var uintParser parse.UintValue
	check[reflect.TypeOf(uint(1))] = &uintParser
	var uint64Parser parse.Uint64Value
	check[reflect.TypeOf(uint64(1))] = &uint64Parser
	var stringParser parse.StringValue
	check[reflect.TypeOf("")] = &stringParser
	var float64Parser parse.Float64Value
	check[reflect.TypeOf(float64(1.5))] = &float64Parser
	var durationParser parse.Duration
	check[reflect.TypeOf(parse.Duration(time.Second))] = &durationParser
	var timeParser parse.TimeValue
	check[reflect.TypeOf(time.Now())] = &timeParser
	if len(check) != len(parsers) {
		t.Errorf("expected %d elements in parsers got %d", len(check), len(parsers))
	}
	for typ, parser := range parsers {
		if !reflect.DeepEqual(parser, check[typ]) {
			t.Errorf("Got %s expected %s\n", parser, check[typ])
		}
	}
}
func TestParseArgsTrivialFlags(t *testing.T) {
	config := newConfiguration()
	flagMap := make(map[string]reflect.StructField)
	if err := getTypesRecursive(reflect.ValueOf(config), flagMap, ""); err != nil {
		t.Fatal(err)
	}
	parsers := map[reflect.Type]parse.Parser{
		reflect.TypeOf([]ServerInfo{}): &sliceServerValue{},
	}
	var boolParser parse.BoolValue
	parsers[reflect.TypeOf(true)] = &boolParser
	var intParser parse.IntValue
	parsers[reflect.TypeOf(1)] = &intParser
	var int64Parser parse.Int64Value
	parsers[reflect.TypeOf(int64(1))] = &int64Parser
	var uintParser parse.UintValue
	parsers[reflect.TypeOf(uint(1))] = &uintParser
	var uint64Parser parse.Uint64Value
	parsers[reflect.TypeOf(uint64(1))] = &uint64Parser
	var stringParser parse.StringValue
	parsers[reflect.TypeOf("")] = &stringParser
	var float64Parser parse.Float64Value
	parsers[reflect.TypeOf(float64(1.5))] = &float64Parser
	var durationParser parse.Duration
	parsers[reflect.TypeOf(parse.Duration(time.Second))] = &durationParser
	var timeParser parse.TimeValue
	parsers[reflect.TypeOf(time.Now())] = &timeParser
	args := []string{
		"--loglevel=OFF",
		"--timeout=9ms",
	}
	valMap, err := parseArgs(args, flagMap, parsers)
	if err != nil {
		t.Fatal(err)
	}
	check := map[string]parse.Parser{}
	stringParser.SetValue("OFF")
	check["loglevel"] = &stringParser
	durationParser.SetValue(parse.Duration(9 * time.Millisecond))
	check["timeout"] = &durationParser
	if len(check) != len(valMap) {
		t.Errorf("expected %d elements in valMap got %d", len(check), len(valMap))
	}
	for flag, parser := range valMap {
		if !reflect.DeepEqual(parser, check[flag]) {
			t.Errorf("Got %s expected %s\n", parser, check[flag])
		}
	}
}
func TestParseArgsShortFlags(t *testing.T) {
	config := newConfiguration()
	flagMap := make(map[string]reflect.StructField)
	if err := getTypesRecursive(reflect.ValueOf(config), flagMap, ""); err != nil {
		t.Fatal(err)
	}
	parsers := map[reflect.Type]parse.Parser{
		reflect.TypeOf([]ServerInfo{}): &sliceServerValue{},
	}
	var boolParser parse.BoolValue
	parsers[reflect.TypeOf(true)] = &boolParser
	var intParser parse.IntValue
	parsers[reflect.TypeOf(1)] = &intParser
	var int64Parser parse.Int64Value
	parsers[reflect.TypeOf(int64(1))] = &int64Parser
	var uintParser parse.UintValue
	parsers[reflect.TypeOf(uint(1))] = &uintParser
	var uint64Parser parse.Uint64Value
	parsers[reflect.TypeOf(uint64(1))] = &uint64Parser
	var stringParser parse.StringValue
	parsers[reflect.TypeOf("")] = &stringParser
	var float64Parser parse.Float64Value
	parsers[reflect.TypeOf(float64(1.5))] = &float64Parser
	var durationParser parse.Duration
	parsers[reflect.TypeOf(parse.Duration(time.Second))] = &durationParser
	var timeParser parse.TimeValue
	parsers[reflect.TypeOf(time.Now())] = &timeParser
	args := []string{
		"-lWARN",
	}
	valMap, err := parseArgs(args, flagMap, parsers)
	if err != nil {
		t.Fatal(err)
	}
	check := map[string]parse.Parser{}
	err = stringParser.Set("WARN")
	if err != nil {
		t.Fatal(err)
	}
	check["loglevel"] = &stringParser
	if len(check) != len(valMap) {
		t.Errorf("expected %d elements in valMap got %d", len(check), len(valMap))
	}
	for flag, parser := range valMap {
		if !reflect.DeepEqual(parser, check[flag]) {
			t.Errorf("Got %s expected %s\n", parser, check[flag])
		}
	}
}
func TestParseArgsPointerFlag(t *testing.T) {
	config := newConfiguration()
	flagMap := make(map[string]reflect.StructField)
	if err := getTypesRecursive(reflect.ValueOf(config), flagMap, ""); err != nil {
		t.Fatal(err)
	}
	parsers := map[reflect.Type]parse.Parser{
		reflect.TypeOf([]ServerInfo{}): &sliceServerValue{},
	}
	var boolParser parse.BoolValue
	parsers[reflect.TypeOf(true)] = &boolParser
	var intParser parse.IntValue
	parsers[reflect.TypeOf(1)] = &intParser
	var int64Parser parse.Int64Value
	parsers[reflect.TypeOf(int64(1))] = &int64Parser
	var uintParser parse.UintValue
	parsers[reflect.TypeOf(uint(1))] = &uintParser
	var uint64Parser parse.Uint64Value
	parsers[reflect.TypeOf(uint64(1))] = &uint64Parser
	var stringParser parse.StringValue
	parsers[reflect.TypeOf("")] = &stringParser
	var float64Parser parse.Float64Value
	parsers[reflect.TypeOf(float64(1.5))] = &float64Parser
	var durationParser parse.Duration
	parsers[reflect.TypeOf(parse.Duration(time.Second))] = &durationParser
	var timeParser parse.TimeValue
	parsers[reflect.TypeOf(time.Now())] = &timeParser
	args := []string{
		"--db",
		"--owner",
	}
	valmap, err := parseArgs(args, flagMap, parsers)
	if err != nil {
		t.Fatal(err)
	}
	check := map[string]parse.Parser{}
	checkDb := parse.BoolValue(true)
	check["db"] = &checkDb
	checkOwner := parse.BoolValue(true)
	check["owner"] = &checkOwner
	if len(check) != len(valmap) {
		t.Errorf("expected %d elements in valmap got %d", len(check), len(valmap))
	}
	for flag, parser := range valmap {
		if !reflect.DeepEqual(parser, check[flag]) {
			t.Errorf("Got %s expected %s\n", parser, check[flag])
		}
	}
}
func TestParseArgsUnderPointerFlag(t *testing.T) {
	config := newConfiguration()
	flagMap := make(map[string]reflect.StructField)
	if err := getTypesRecursive(reflect.ValueOf(config), flagMap, ""); err != nil {
		t.Fatal(err)
	}
	parsers := map[reflect.Type]parse.Parser{
		reflect.TypeOf([]ServerInfo{}): &sliceServerValue{},
	}
	var boolParser parse.BoolValue
	parsers[reflect.TypeOf(true)] = &boolParser
	var intParser parse.IntValue
	parsers[reflect.TypeOf(1)] = &intParser
	var int64Parser parse.Int64Value
	parsers[reflect.TypeOf(int64(1))] = &int64Parser
	var uintParser parse.UintValue
	parsers[reflect.TypeOf(uint(1))] = &uintParser
	var uint64Parser parse.Uint64Value
	parsers[reflect.TypeOf(uint64(1))] = &uint64Parser
	var stringParser parse.StringValue
	parsers[reflect.TypeOf("")] = &stringParser
	var float64Parser parse.Float64Value
	parsers[reflect.TypeOf(float64(1.5))] = &float64Parser
	var durationParser parse.Duration
	parsers[reflect.TypeOf(parse.Duration(time.Second))] = &durationParser
	var timeParser parse.TimeValue
	parsers[reflect.TypeOf(time.Now())] = &timeParser
	args := []string{
		"--owner.name",
		"--db.comax=5000000000",
	}
	valmap, err := parseArgs(args, flagMap, parsers)
	if err != nil {
		t.Fatal(err)
	}
	check := map[string]parse.Parser{}
	boolParser.SetValue(true)
	check["owner.name"] = &boolParser
	uintParser.SetValue(uint(5000000000))
	check["db.comax"] = &uintParser
	if len(check) != len(valmap) {
		t.Errorf("expected %d elements in valmap got %d", len(check), len(valmap))
	}
	for flag, parser := range valmap {
		if !reflect.DeepEqual(parser, check[flag]) {
			t.Errorf("Got %s expected %s\n", parser, check[flag])
		}
	}
}