From d8388ff71e27cb0ef25c91f34a17a9ece1e06568 Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Fri, 3 Dec 2021 18:21:11 +0200 Subject: [PATCH] Test config opts retrieval functions --- utils/options_test.go | 386 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 utils/options_test.go diff --git a/utils/options_test.go b/utils/options_test.go new file mode 100644 index 000000000..422c5da5c --- /dev/null +++ b/utils/options_test.go @@ -0,0 +1,386 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package utils + +import ( + "reflect" + "testing" + "time" + + "github.com/ericlagergren/decimal" +) + +func TestOptionsGetFloat64Opts(t *testing.T) { + + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + if rcv, err := GetFloat64Opts(ev, 1.2, "optionName"); err != nil { + t.Error(err) + } else if rcv != 1.2 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 1.2, rcv) + } + + // option key populated with valid input, get its value + ev.APIOpts["optionName"] = 0.11 + if rcv, err := GetFloat64Opts(ev, 1.2, "optionName"); err != nil { + t.Error(err) + } else if rcv != 0.11 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 0.11, rcv) + } + + // option key populated with invalid input, receive error + expectedErr := `strconv.ParseFloat: parsing "invalid": invalid syntax` + ev.APIOpts["optionName"] = "invalid" + if _, err := GetFloat64Opts(ev, 1.2, "optionName"); err == nil || + err.Error() != expectedErr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", expectedErr, err) + } +} + +func TestOptionsGetDurationOpts(t *testing.T) { + + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + if rcv, err := GetDurationOpts(ev, time.Minute, "optionName"); err != nil { + t.Error(err) + } else if rcv != time.Minute { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", time.Minute, rcv) + } + + // option key populated with valid input, get its value + ev.APIOpts["optionName"] = 2 * time.Second + if rcv, err := GetDurationOpts(ev, time.Minute, "optionName"); err != nil { + t.Error(err) + } else if rcv != 2*time.Second { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 2*time.Second, rcv) + } + ev.APIOpts["optionName"] = 600 + if rcv, err := GetDurationOpts(ev, time.Minute, "optionName"); err != nil { + t.Error(err) + } else if rcv != 600 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 600, rcv) + } + ev.APIOpts["optionName"] = "2m0s" + if rcv, err := GetDurationOpts(ev, time.Minute, "optionName"); err != nil { + t.Error(err) + } else if rcv != 2*time.Minute { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 2*time.Minute, rcv) + } + + // option key populated with invalid input, receive error + expectedErr := `time: invalid duration "invalid"` + ev.APIOpts["optionName"] = "invalid" + if _, err := GetDurationOpts(ev, time.Minute, "optionName"); err == nil || + err.Error() != expectedErr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", expectedErr, err) + } +} + +func TestOptionsGetStringOpts(t *testing.T) { + + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + if rcv := GetStringOpts(ev, "default", "optionName"); rcv != "default" { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", "default", rcv) + } + + // option key populated, get its value + ev.APIOpts["optionName"] = "optionValue" + if rcv := GetStringOpts(ev, "default", "optionName"); rcv != "optionValue" { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", "optionValue", rcv) + } + ev.APIOpts["optionName"] = false + if rcv := GetStringOpts(ev, "default", "optionName"); rcv != "false" { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", "false", rcv) + } + ev.APIOpts["optionName"] = 5 * time.Minute + if rcv := GetStringOpts(ev, "default", "optionName"); rcv != "5m0s" { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", "5m0s", rcv) + } + ev.APIOpts["optionName"] = 12.34 + if rcv := GetStringOpts(ev, "default", "optionName"); rcv != "12.34" { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", "12.34", rcv) + } +} + +func TestOptionsGetStringSliceOpts(t *testing.T) { + + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + defaultValue := []string{"default"} + if rcv, err := GetStringSliceOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(rcv, defaultValue) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", defaultValue, rcv) + } + + // option key populated with valid input, get its value + optValue := []string{"optValue"} + ev.APIOpts["optionName"] = optValue + if rcv, err := GetStringSliceOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(rcv, optValue) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", optValue, rcv) + } + optValue2 := []string{"true", "false"} + ev.APIOpts["optionName"] = []bool{true, false} + if rcv, err := GetStringSliceOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(rcv, optValue2) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", optValue2, rcv) + } + optValue3 := []string{"12.34", "3"} + ev.APIOpts["optionName"] = []float64{12.34, 3} + if rcv, err := GetStringSliceOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(rcv, optValue3) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", optValue3, rcv) + } + + // option key populated with invalid input, receive error + expectedErr := `cannot convert field: string to []string` + ev.APIOpts["optionName"] = "invalid" + if _, err := GetStringSliceOpts(ev, defaultValue, "optionName"); err == nil || + err.Error() != expectedErr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", expectedErr, err) + } +} + +func TestOptionsGetIntOpts(t *testing.T) { + + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + if rcv, err := GetIntOpts(ev, 5, "optionName"); err != nil { + t.Error(err) + } else if rcv != 5 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 5, rcv) + } + + // option key populated with valid input, get its value + ev.APIOpts["optionName"] = 12 + if rcv, err := GetIntOpts(ev, 5, "optionName"); err != nil { + t.Error(err) + } else if rcv != 12 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 12, rcv) + } + ev.APIOpts["optionName"] = 12.7 + if rcv, err := GetIntOpts(ev, 5, "optionName"); err != nil { + t.Error(err) + } else if rcv != 12 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 12, rcv) + } + + // option key populated with invalid input, receive error + expectedErr := `strconv.ParseInt: parsing "invalid": invalid syntax` + ev.APIOpts["optionName"] = "invalid" + if _, err := GetIntOpts(ev, 5, "optionName"); err == nil || + err.Error() != expectedErr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", expectedErr, err) + } +} + +func TestOptionsGetBoolOpts(t *testing.T) { + + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + if rcv, err := GetBoolOpts(ev, false, "optionName"); err != nil { + t.Error(err) + } else if rcv != false { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", false, rcv) + } + + // option key populated with valid input, get its value + ev.APIOpts["optionName"] = true + if rcv, err := GetBoolOpts(ev, false, "optionName"); err != nil { + t.Error(err) + } else if rcv != true { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", true, rcv) + } + ev.APIOpts["optionName"] = 5 + if rcv, err := GetBoolOpts(ev, false, "optionName"); err != nil { + t.Error(err) + } else if rcv != true { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", true, rcv) + } + ev.APIOpts["optionName"] = "true" + if rcv, err := GetBoolOpts(ev, false, "optionName"); err != nil { + t.Error(err) + } else if rcv != true { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", true, rcv) + } + + // option key populated with invalid input, receive error + expectedErr := `strconv.ParseBool: parsing "invalid": invalid syntax` + ev.APIOpts["optionName"] = "invalid" + if _, err := GetBoolOpts(ev, false, "optionName"); err == nil || + err.Error() != expectedErr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", expectedErr, err) + } +} + +func TestOptionsGetInterfaceOpts(t *testing.T) { + + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + if rcv := GetInterfaceOpts(ev, "default", "optionName"); rcv != "default" { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", "default", rcv) + } + + // option key populated, get its value + ev.APIOpts["optionName"] = 0.11 + if rcv := GetInterfaceOpts(ev, "default", "optionName"); rcv != 0.11 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 0.11, rcv) + } + ev.APIOpts["optionName"] = true + if rcv := GetInterfaceOpts(ev, "default", "optionName"); rcv != true { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", true, rcv) + } + ev.APIOpts["optionName"] = 5 * time.Minute + if rcv := GetInterfaceOpts(ev, "default", "optionName"); rcv != 5*time.Minute { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 5*time.Minute, rcv) + } +} + +func TestOptionsGetIntPointerOpts(t *testing.T) { + defaultValue := IntPointer(5) + + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + if rcv, err := GetIntPointerOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv == nil || rcv != defaultValue { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", defaultValue, rcv) + } + + // option key populated with valid input, get its value + ev.APIOpts["optionName"] = 12 + if rcv, err := GetIntPointerOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv == nil || *rcv != 12 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 12, rcv) + } + ev.APIOpts["optionName"] = 12.7 + if rcv, err := GetIntPointerOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv == nil || *rcv != 12 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 12, rcv) + } + + // option key populated with invalid input, receive error + expectedErr := `strconv.ParseInt: parsing "invalid": invalid syntax` + ev.APIOpts["optionName"] = "invalid" + if _, err := GetIntPointerOpts(ev, defaultValue, "optionName"); err == nil || + err.Error() != expectedErr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", expectedErr, err) + } +} + +func TestOptionsGetDurationPointerOpts(t *testing.T) { + defaultValue := DurationPointer(time.Minute) + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + if rcv, err := GetDurationPointerOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv == nil || rcv != defaultValue { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", defaultValue, rcv) + } + + // option key populated with valid input, get its value + ev.APIOpts["optionName"] = 2 * time.Second + if rcv, err := GetDurationPointerOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv == nil || *rcv != 2*time.Second { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 2*time.Second, rcv) + } + ev.APIOpts["optionName"] = 600 + if rcv, err := GetDurationPointerOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv == nil || *rcv != 600 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 600, rcv) + } + ev.APIOpts["optionName"] = "2m0s" + if rcv, err := GetDurationPointerOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv == nil || *rcv != 2*time.Minute { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", 2*time.Minute, rcv) + } + + // option key populated with invalid input, receive error + expectedErr := `time: invalid duration "invalid"` + ev.APIOpts["optionName"] = "invalid" + if _, err := GetDurationPointerOpts(ev, defaultValue, "optionName"); err == nil || + err.Error() != expectedErr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", expectedErr, err) + } +} + +func TestOptionsGetDecimalBigOpts(t *testing.T) { + defaultValue := decimal.New(1234, 3) + + // option key not populated, retrieve default value + ev := &CGREvent{ + APIOpts: make(map[string]interface{}), + } + if rcv, err := GetDecimalBigOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv.Cmp(defaultValue) != 0 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", defaultValue, rcv) + } + + // option key populated with valid input, get its value + optValue := decimal.New(15, 1) + ev.APIOpts["optionName"] = 1.5 + if rcv, err := GetDecimalBigOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv.Cmp(optValue) != 0 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", optValue, rcv) + } + ev.APIOpts["optionName"] = "1.5" + if rcv, err := GetDecimalBigOpts(ev, defaultValue, "optionName"); err != nil { + t.Error(err) + } else if rcv.Cmp(optValue) != 0 { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", optValue, rcv) + } + + // option key populated with invalid input, receive error + expectedErr := `can't convert to decimal` + ev.APIOpts["optionName"] = "invalid" + if _, err := GetDecimalBigOpts(ev, defaultValue, "optionName"); err == nil || + err.Error() != expectedErr { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", expectedErr, err) + } +}