From 9692cf438c493d8d16909d1c7fa74d376dadfe30 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 17 Jul 2020 15:09:41 +0300 Subject: [PATCH] Redesigned the Flags structure --- utils/map.go | 79 +++++++++++++++++++++++----------- utils/map_test.go | 105 ++++++++++++++++++++++------------------------ 2 files changed, 105 insertions(+), 79 deletions(-) diff --git a/utils/map.go b/utils/map.go index b166a68cc..f6fb95b54 100644 --- a/utils/map.go +++ b/utils/map.go @@ -19,7 +19,6 @@ along with this program. If not, see package utils import ( - "reflect" "strconv" "strings" ) @@ -222,44 +221,76 @@ func MapStringToInt64(in map[string]string) (out map[string]int64, err error) { } // FlagsWithParamsFromSlice construct a FlagsWithParams from the given slice -func FlagsWithParamsFromSlice(s []string) (FlagsWithParams, error) { - result := make(FlagsWithParams, len(s)) +func FlagsWithParamsFromSlice(s []string) (flags FlagsWithParams) { + flags = make(FlagsWithParams) for _, v := range s { - subsystemWithIDs := strings.Split(v, InInFieldSep) - result[subsystemWithIDs[0]] = []string{} - if len(subsystemWithIDs) == 2 { - result[subsystemWithIDs[0]] = strings.Split(subsystemWithIDs[1], INFIELD_SEP) - } else if len(subsystemWithIDs) > 2 { - return nil, ErrUnsupportedFormat + flag := strings.SplitN(v, InInFieldSep, 3) + if !flags.Has(flag[0]) { + flags[flag[0]] = make(FlagParams) } + flags[flag[0]].Add(flag[1:]) } - return result, nil + return } -// FlagsWithParams should store a list of profiles for each subsystem -type FlagsWithParams map[string][]string +// FlagParams stores the parameters for a flag +type FlagParams map[string][]string -// HasKey returns if the key was mentioned in flags -func (fWp FlagsWithParams) HasKey(key string) (has bool) { - _, has = fWp[key] +// Has returns if the key was mentioned in flags +func (fWp FlagParams) Has(opt string) (has bool) { + _, has = fWp[opt] + return +} + +// Add adds the options to the flag +func (fWp FlagParams) Add(opts []string) { + switch len(opts) { + case 0: + case 1: + fWp[opts[0]] = []string{} + default: // just in case we call this function with more elements than needed + fallthrough + case 2: + fWp[opts[0]] = InfieldSplit(opts[1]) + } return } // ParamsSlice returns the list of profiles for the subsystem -func (fWp FlagsWithParams) ParamsSlice(subs string) (ps []string) { +func (fWp FlagParams) ParamsSlice(opt string) (ps []string) { + return fWp[opt] // if it doesn't have the option it will return an empty slice +} + +// FlagsWithParams should store a list of flags for each subsystem +type FlagsWithParams map[string]FlagParams + +// Has returns if the key was mentioned in flags +func (fWp FlagsWithParams) Has(flag string) (has bool) { + _, has = fWp[flag] + return +} + +// ParamsSlice returns the list of profiles for the subsystem +func (fWp FlagsWithParams) ParamsSlice(subs, opt string) (ps []string) { if psIfc, has := fWp[subs]; has { - ps = psIfc + ps = psIfc.ParamsSlice(opt) } return } // SliceFlags converts from FlagsWithParams back to []string func (fWp FlagsWithParams) SliceFlags() (sls []string) { - for key := range fWp { - if prmSlice := fWp.ParamsSlice(key); !reflect.DeepEqual(prmSlice, []string{}) { - sls = append(sls, ConcatenatedKey(key, strings.Join(prmSlice, INFIELD_SEP))) - } else { + for key, sub := range fWp { + if len(sub) == 0 { // no option for these subsystem sls = append(sls, key) + continue + } + for opt, values := range sub { + if len(values) == 0 { // it's an option without values(e.g *derivedreply) + sls = append(sls, ConcatenatedKey(key, opt)) + continue + } + sls = append(sls, ConcatenatedKey(key, opt, strings.Join(values, INFIELD_SEP))) } } return @@ -267,12 +298,12 @@ func (fWp FlagsWithParams) SliceFlags() (sls []string) { // GetBool returns the flag as boolean func (fWp FlagsWithParams) GetBool(key string) (b bool) { - var v []string + var v FlagParams if v, b = fWp[key]; !b { return // not present means false } if v == nil || len(v) == 0 { - return true // empty slice + return true // empty map } - return v[0] == "true" // check only the first element + return !v.Has("*disabled") // check if has *disable param } diff --git a/utils/map_test.go b/utils/map_test.go index 8d7081821..9d4e288ca 100644 --- a/utils/map_test.go +++ b/utils/map_test.go @@ -197,93 +197,77 @@ func TestMapHasKey(t *testing.T) { } func TestMapSubsystemIDsFromSlice(t *testing.T) { - sls := []string{"*event", "*thresholds:ID1;ID2;ID3", "*attributes", "*stats:ID"} + sls := []string{"*event", "*thresholds:*ids:ID1;ID2;ID3", "*thresholds:*derivedreply", "*attributes:*disabled", "*stats:*ids:ID"} eMp := FlagsWithParams{ - "*event": []string{}, - "*thresholds": []string{"ID1", "ID2", "ID3"}, - "*attributes": []string{}, - "*stats": []string{"ID"}, + "*event": map[string][]string{}, + "*thresholds": map[string][]string{"*ids": {"ID1", "ID2", "ID3"}, MetaDerivedReply: {}}, + "*attributes": map[string][]string{"*disabled": {}}, + "*stats": map[string][]string{"*ids": {"ID"}}, } - if mp, err := FlagsWithParamsFromSlice(sls); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(mp, eMp) { + if mp := FlagsWithParamsFromSlice(sls); !reflect.DeepEqual(mp, eMp) { t.Errorf("Expecting: %+v, received: %+v", eMp, mp) } } -func TestMapSubsystemIDsFromSliceWithErr(t *testing.T) { - sls := []string{"*event", "*thresholds:ID1;ID2;ID3:error:", "*attributes", "*stats:ID"} - - if _, err := FlagsWithParamsFromSlice(sls); err != ErrUnsupportedFormat { - t.Error(err) - } -} - func TestMapSubsystemIDsHasKey(t *testing.T) { - sls := []string{"*event", "*thresholds:ID1;ID2;ID3", "*attributes", "*stats:ID"} + sls := []string{"*event", "*thresholds:*ids:ID1;ID2;ID3", "*attributes", "*stats:*ids:ID"} eMp := FlagsWithParams{ - "*event": []string{}, - "*thresholds": []string{"ID1", "ID2", "ID3"}, - "*attributes": []string{}, - "*stats": []string{"ID"}, + "*event": map[string][]string{}, + "*thresholds": map[string][]string{"*ids": {"ID1", "ID2", "ID3"}}, + "*attributes": map[string][]string{}, + "*stats": map[string][]string{"*ids": {"ID"}}, } - mp, err := FlagsWithParamsFromSlice(sls) - if err != nil { - t.Error(err) - } else if !reflect.DeepEqual(mp, eMp) { + mp := FlagsWithParamsFromSlice(sls) + if !reflect.DeepEqual(mp, eMp) { t.Errorf("Expecting: %+v, received: %+v", eMp, mp) } - if has := mp.HasKey("*event"); !has { + if has := mp.Has("*event"); !has { t.Errorf("Expecting: true, received: %+v", has) } - if has := mp.HasKey("*thresholds"); !has { + if has := mp.Has("*thresholds"); !has { t.Errorf("Expecting: true, received: %+v", has) } - if has := mp.HasKey("*resources"); has { + if has := mp.Has("*resources"); has { t.Errorf("Expecting: false, received: %+v", has) } } func TestMapSubsystemIDsGetIDs(t *testing.T) { - sls := []string{"*event", "*thresholds:ID1;ID2;ID3", "*attributes", "*stats:ID"} + sls := []string{"*event", "*thresholds:*ids:ID1;ID2;ID3", "*attributes", "*stats:*ids:ID"} eMp := FlagsWithParams{ - "*event": []string{}, - "*thresholds": []string{"ID1", "ID2", "ID3"}, - "*attributes": []string{}, - "*stats": []string{"ID"}, + "*event": map[string][]string{}, + "*thresholds": map[string][]string{"*ids": {"ID1", "ID2", "ID3"}}, + "*attributes": map[string][]string{}, + "*stats": map[string][]string{"*ids": {"ID"}}, } - mp, err := FlagsWithParamsFromSlice(sls) - if err != nil { - t.Error(err) - } else if !reflect.DeepEqual(mp, eMp) { + mp := FlagsWithParamsFromSlice(sls) + if !reflect.DeepEqual(mp, eMp) { t.Errorf("Expecting: %+v, received: %+v", eMp, mp) } eIDs := []string{"ID1", "ID2", "ID3"} - if ids := mp.ParamsSlice("*thresholds"); !reflect.DeepEqual(ids, eIDs) { - t.Errorf("Expecting: %+v, received: %+v", eIDs, ids) - } - eIDs = []string{} - if ids := mp.ParamsSlice("*event"); !reflect.DeepEqual(ids, eIDs) { + if ids := mp.ParamsSlice("*thresholds", "*ids"); !reflect.DeepEqual(ids, eIDs) { t.Errorf("Expecting: %+v, received: %+v", eIDs, ids) } eIDs = nil - if ids := mp.ParamsSlice("*test"); !reflect.DeepEqual(ids, eIDs) { + if ids := mp.ParamsSlice("*event", "*ids"); !reflect.DeepEqual(ids, eIDs) { + t.Errorf("Expecting: %+v, received: %+v", eIDs, ids) + } + if ids := mp.ParamsSlice("*test", "*ids"); !reflect.DeepEqual(ids, eIDs) { t.Errorf("Expecting: %+v, received: %+v", eIDs, ids) } } func TestFlagsToSlice(t *testing.T) { - sls := []string{"*event", "*thresholds:ID1;ID2;ID3", "*attributes", "*stats:ID"} + sls := []string{"*event", "*thresholds:*ids:ID1;ID2;ID3", "*attributes", "*stats:*ids:ID", "*routes:*derivedreply"} eMp := FlagsWithParams{ - "*event": []string{}, - "*thresholds": []string{"ID1", "ID2", "ID3"}, - "*attributes": []string{}, - "*stats": []string{"ID"}, + "*event": map[string][]string{}, + "*thresholds": map[string][]string{"*ids": {"ID1", "ID2", "ID3"}}, + "*attributes": map[string][]string{}, + "*stats": map[string][]string{"*ids": {"ID"}}, + "*routes": map[string][]string{MetaDerivedReply: {}}, } - mp, err := FlagsWithParamsFromSlice(sls) - if err != nil { - t.Error(err) - } else if !reflect.DeepEqual(mp, eMp) { + mp := FlagsWithParamsFromSlice(sls) + if !reflect.DeepEqual(mp, eMp) { t.Errorf("Expecting: %+v, received: %+v", eMp, mp) } sort.Strings(sls) @@ -296,9 +280,9 @@ func TestFlagsToSlice(t *testing.T) { func TestFlagsWithParamsGetBool(t *testing.T) { flagsWithParams := &FlagsWithParams{ - "test": []string{"string1", "string2"}, - "test2": []string{"true", "string2"}, - "empty": []string{}, + "test": map[string][]string{"*disabled": {}, "string2": {}}, + "test2": map[string][]string{"string2": {}}, + "empty": map[string][]string{}, } key := "notpresent" if rcv := flagsWithParams.GetBool(key); rcv != false { @@ -317,3 +301,14 @@ func TestFlagsWithParamsGetBool(t *testing.T) { t.Errorf("Expecting: true, received: %+v", ToJSON(rcv)) } } + +func TestFlagParamsAdd(t *testing.T) { + flgs := make(FlagParams) + exp := FlagParams{ + "*ids": []string{"id1", "id2"}, + } + flgs.Add([]string{"*ids", "id1;id2", "ignored"}) + if !reflect.DeepEqual(flgs, exp) { + t.Errorf("Expecting: %+v, received: %+v", exp, flgs) + } +}