From f0fea43a418c3741eea87d2e591567ae711ba456 Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Fri, 6 Oct 2023 02:47:25 -0400 Subject: [PATCH] Update to new *strip data converter --- utils/consts.go | 1 + utils/dataconverter.go | 105 +++++++++----- utils/dataconverter_test.go | 276 ++++++++++++++++++++++++++++-------- 3 files changed, 283 insertions(+), 99 deletions(-) diff --git a/utils/consts.go b/utils/consts.go index 328fd8019..4758ce30f 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -1151,6 +1151,7 @@ const ( MetaString = "*string" MetaPrefix = "*prefix" MetaSuffix = "*suffix" + MetaBoth = "*both" MetaEmpty = "*empty" MetaExists = "*exists" MetaTimings = "*timings" diff --git a/utils/dataconverter.go b/utils/dataconverter.go index 555adab7d..f4c5f615b 100644 --- a/utils/dataconverter.go +++ b/utils/dataconverter.go @@ -589,7 +589,7 @@ func (jsnC JSONConverter) Convert(in any) (any, error) { return string(b), nil } -// StripConverter strips characters from the left or the right side of a string. +// StripConverter strips the prefix, the suffix or both from a string. type StripConverter struct { side string substr string @@ -597,42 +597,53 @@ type StripConverter struct { } // NewStripConverter creates a new StripConverter with the specified parameters. -// The input params string should have the format ":::", where: -// - 'type' must be "*strip". -// - 'side' specifies the side of the string to strip, and it must be either "*left" or "*right". -// - 'substr' is the substring to be removed from the string. -// - 'amount' is the optional number of times 'substr' should be removed from the specified side. -// -// If 'amount' is omitted, it defaults to 1. If it is -1, all instances of 'substr' will be removed from the -// chosen side. If 'substr' is "*any", 'amount' characters will be removed from the specified side -// regardless of their value. func NewStripConverter(params string) (DataConverter, error) { - sc := new(StripConverter) paramSlice := strings.Split(params, InInFieldSep) - switch len(paramSlice) { - case 3: - sc.amount = 1 - case 4: - var err error - sc.amount, err = strconv.Atoi(paramSlice[3]) - if err != nil { - return nil, err + if len(paramSlice) < 3 || len(paramSlice) > 5 { + return nil, errors.New("strip converter: invalid number of parameters (should have 3, 4 or 5)") + } + sc := StripConverter{ + side: paramSlice[1], + substr: paramSlice[2], + amount: -1, + } + var err error + switch sc.substr { + case EmptyString: + return nil, errors.New("strip converter: substr parameter cannot be empty") + case "*nil", "*space": + if sc.substr == "*nil" { + sc.substr = "\u0000" + } else { + sc.substr = " " + } + if len(paramSlice) == 4 { + sc.amount, err = strconv.Atoi(paramSlice[3]) + if err != nil { + return nil, fmt.Errorf("strip converter: invalid amount parameter (%w)", err) + } + sc.substr = strings.Repeat(sc.substr, sc.amount) + } + case "*char": + if len(paramSlice) < 4 { + return nil, errors.New("strip converter: usage of *char implies the need of 4 or 5 params") + } + sc.substr = paramSlice[3] // should probably return error if empty + if len(paramSlice) == 5 { + sc.amount, err = strconv.Atoi(paramSlice[4]) + if err != nil { + return nil, fmt.Errorf("strip converter: invalid amount parameter (%w)", err) + } + sc.substr = strings.Repeat(sc.substr, sc.amount) } default: - return nil, errors.New("strip converter: invalid number of parameters (should have 3 or 4)") + sc.amount, err = strconv.Atoi(paramSlice[2]) + if err != nil { + return nil, fmt.Errorf("strip converter: invalid amount parameter (%w)", err) + } + sc.substr = "" } - if sc.side = paramSlice[1]; !IsSliceMember([]string{MetaLeft, MetaRight}, sc.side) { - return nil, errors.New("strip converter: invalid side parameter") - } - - sc.substr = paramSlice[2] - if sc.substr == MetaAny && sc.amount == -1 { - return nil, errors.New("strip converter: invalid combination of substr and amount values") - } - if sc.substr != MetaAny && sc.amount != -1 { - sc.substr = strings.Repeat(paramSlice[2], sc.amount) - } return sc, nil } @@ -641,31 +652,47 @@ func NewStripConverter(params string) (DataConverter, error) { func (sc StripConverter) Convert(in any) (any, error) { str, ok := in.(string) if !ok { - return nil, ErrCastFailed + return nil, fmt.Errorf("strip converter: %w", ErrCastFailed) + } + if sc.amount <= 0 && sc.amount != -1 { + return str, nil } switch sc.side { - case MetaLeft: - if sc.substr == MetaAny { + case MetaPrefix: + if sc.substr == EmptyString { if sc.amount < len(str) { return str[sc.amount:], nil } - return str, nil + return EmptyString, nil } if sc.amount != -1 { return strings.TrimPrefix(str, sc.substr), nil } return strings.TrimLeft(str, sc.substr), nil - case MetaRight: - if sc.substr == MetaAny { + case MetaSuffix: + if sc.substr == EmptyString { if sc.amount < len(str) { return str[:len(str)-sc.amount], nil } - return str, nil + return EmptyString, nil } if sc.amount != -1 { return strings.TrimSuffix(str, sc.substr), nil } return strings.TrimRight(str, sc.substr), nil + case MetaBoth: + if sc.substr == EmptyString { + if sc.amount*2 < len(str) { + return str[sc.amount : len(str)-sc.amount], nil + } + return EmptyString, nil + } + if sc.amount != -1 { + str = strings.TrimPrefix(str, sc.substr) + return strings.TrimSuffix(str, sc.substr), nil + } + return strings.Trim(str, sc.substr), nil + default: + return EmptyString, errors.New("strip converter: invalid side parameter") } - return str, nil } diff --git a/utils/dataconverter_test.go b/utils/dataconverter_test.go index d89a65227..18b554c0b 100644 --- a/utils/dataconverter_test.go +++ b/utils/dataconverter_test.go @@ -1288,97 +1288,253 @@ func TestDataConverterConvertJSONOK(t *testing.T) { func TestStripConverter(t *testing.T) { tests := []struct { - name string - params string - input string - expected string - expectErr bool + name string + params string + input string + expected string + constructorErr bool + convertErr bool }{ + { - name: "Cut any leading 3 characters", - params: "*strip:*left:*any:3", - input: "000000435400", - expected: "000435400", - expectErr: false, + name: "Strip 5 leading characters", + params: "*strip:*prefix:5", + input: "12345TEST12345", + expected: "TEST12345", + constructorErr: false, + convertErr: false, }, { - name: "Cut leading '00' twice", - params: "*strip:*left:00:2", - input: "000000435400", - expected: "00435400", - expectErr: false, + name: "Strip 5 trailing characters", + params: "*strip:*suffix:5", + input: "12345TEST12345", + expected: "12345TEST", + constructorErr: false, + convertErr: false, }, { - name: "Cut leading '00' default", - params: "*strip:*left:00", - input: "000000435400", - expected: "0000435400", - expectErr: false, + name: "Strip 5 characters from both sides", + params: "*strip:*both:5", + input: "12345TEST12345", + expected: "TEST", + constructorErr: false, + convertErr: false, }, { - name: "Cut 8 trailing nils", - params: "*strip:*right:\u0000:8", - input: "password\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", - expected: "password", - expectErr: false, + name: "Strip all trailing nils", + params: "*strip:*suffix:*nil", + input: "TEST\u0000\u0000\u0000\u0000", + expected: "TEST", + constructorErr: false, + convertErr: false, }, { - name: "Cut 8 trailing escaped nils", - params: "*strip:*right:\\u0000:8", - input: "password\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000", - expected: "password", - expectErr: false, + name: "Strip all leading nils", + params: "*strip:*prefix:*nil", + input: "\u0000\u0000\u0000\u0000TEST", + expected: "TEST", + constructorErr: false, + convertErr: false, }, { - name: "Cut all trailing nils", - params: "*strip:*right:\u0000:-1", - input: "password\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", - expected: "password", - expectErr: false, + name: "Strip all nils from both sides", + params: "*strip:*both:*nil", + input: "\u0000\u0000TEST\u0000\u0000", + expected: "TEST", + constructorErr: false, + convertErr: false, }, { - name: "Cut all escaped trailing nils", - params: "*strip:*right:\\u0000:-1", - input: "password\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000\\u0000", - expected: "password", - expectErr: false, + name: "Strip 2 trailing nils", + params: "*strip:*suffix:*nil:2", + input: "TEST\u0000\u0000\u0000\u0000", + expected: "TEST\u0000\u0000", + constructorErr: false, + convertErr: false, }, { - name: "Invalid substr and amount value combination", - params: "*strip:*right:*any:-1", - input: "test", - expected: "", - expectErr: true, + name: "Strip 2 leading nils", + params: "*strip:*prefix:*nil:2", + input: "\u0000\u0000\u0000\u0000TEST", + expected: "\u0000\u0000TEST", + constructorErr: false, + convertErr: false, }, { - name: "Invalid nr of parameters", - params: "*strip:*right", - input: "test", - expected: "", - expectErr: true, + name: "Strip 1 nil from both sides", + params: "*strip:*both:*nil:1", + input: "\u0000\u0000TEST\u0000\u0000", + expected: "\u0000TEST\u0000", + constructorErr: false, + convertErr: false, }, { - name: "Invalid side parameter", - params: "*strip:*up:abc:2", - input: "test", - expected: "", - expectErr: true, + name: "Strip all trailing spaces", + params: "*strip:*suffix:*space", + input: "TEST ", + expected: "TEST", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip all leading spaces", + params: "*strip:*prefix:*space", + input: " TEST", + expected: "TEST", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip all spaces from both sides", + params: "*strip:*both:*space", + input: " TEST ", + expected: "TEST", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip 2 trailing spaces", + params: "*strip:*suffix:*space:2", + input: "TEST ", + expected: "TEST ", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip 2 leading spaces", + params: "*strip:*prefix:*space:2", + input: " TEST", + expected: " TEST", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip 1 space from both sides", + params: "*strip:*both:*space:1", + input: " TEST ", + expected: " TEST ", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip all trailing 'abcd' char groups", + params: "*strip:*suffix:*char:abcd", + input: "TESTabcdabcdabcdabcd", + expected: "TEST", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip all leading 'abcd' char groups", + params: "*strip:*prefix:*char:abcd", + input: "abcdabcdabcdabcdTEST", + expected: "TEST", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip all 'abcd' char groups from both sides", + params: "*strip:*both:*char:abcd", + input: "abcdabcdTESTabcdabcd", + expected: "TEST", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip 2 trailing 'abcd' char groups", + params: "*strip:*suffix:*char:abcd:2", + input: "TESTabcdabcdabcdabcd", + expected: "TESTabcdabcd", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip 2 leading 'abcd' char groups", + params: "*strip:*prefix:*char:abcd:2", + input: "abcdabcdabcdabcdTEST", + expected: "abcdabcdTEST", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip 1 'abcd' char group from both sides", + params: "*strip:*both:*char:abcd:1", + input: "abcdabcdTESTabcdabcd", + expected: "abcdTESTabcd", + constructorErr: false, + convertErr: false, + }, + { + name: "Empty third parameter", + params: "*strip:*prefix:", + input: "TEST", + expected: "", + constructorErr: true, + convertErr: false, + }, + { + name: "Invalid side parameter", + params: "*strip:*invalid:*nil", + input: "TEST", + expected: "", + constructorErr: false, + convertErr: true, + }, + { + name: "Invalid nr. of parameters", + params: "*strip:*prefix:*char:*nil:abc:3", + input: "TEST", + expected: "", + constructorErr: true, + convertErr: false, + }, + { + name: "Invalid amount parameter", + params: "*strip:*prefix:*char:0:three", + input: "000TEST", + expected: "", + constructorErr: true, + convertErr: false, + }, + { + name: "Strip a prefix longer than the value", + params: "*strip:*prefix:5", + input: "TEST", + expected: "", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip a suffix longer than the value", + params: "*strip:*suffix:5", + input: "TEST", + expected: "", + constructorErr: false, + convertErr: false, + }, + { + name: "Strip from both ends an amount of characters longer than the value", + params: "*strip:*both:3", + input: "TEST", + expected: "", + constructorErr: false, + convertErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { sc, err := NewDataConverter(tt.params) - if (err != nil) != tt.expectErr { - t.Errorf("NewStripConverter error = %v, expectErr %v", err, tt.expectErr) + if (err != nil) != tt.constructorErr { + t.Errorf("NewStripConverter error = %v, constructorErr %v", err, tt.constructorErr) return } - if tt.expectErr { + if tt.constructorErr { return } rcv, err := sc.Convert(tt.input) - if (err != nil) != tt.expectErr { - t.Errorf("Convert error = %v, expectErr %v", err, tt.expectErr) + if (err != nil) != tt.convertErr { + t.Errorf("Convert error = %v, convertErr %v", err, tt.convertErr) return } if rcv != tt.expected {