/*
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 Affero 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>
*/
package utils

import (
	"math"
	"net"
	"reflect"
	"strings"
	"testing"
	"time"

	"github.com/nyaruka/phonenumbers"
)

func TestDataConvertersConvertString(t *testing.T) {
	dcs := &DataConverters{}
	if rcv, err := dcs.ConvertString(EmptyString); err != nil {
		t.Error(err)
	} else if rcv != EmptyString {
		t.Errorf("Expecting: <%+q>, received: <%+q>", EmptyString, rcv)
	}
	if rcv, err := dcs.ConvertString("test"); err != nil {
		t.Error(err)
	} else if rcv != "test" {
		t.Errorf("Expecting: <test>, received: <%+q>", rcv)
	}
}

func TestNewDataConverter(t *testing.T) {
	a, err := NewDataConverter(MetaDurationSeconds)
	if err != nil {
		t.Error(err)
	}
	b, err := NewDurationSecondsConverter(EmptyString)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}
	a, err = NewDataConverter(MetaDuration)
	if err != nil {
		t.Error(err)
	}
	b, err = NewDurationConverter(EmptyString)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}
	a, err = NewDataConverter(MetaDurationNanoseconds)
	if err != nil {
		t.Error(err)
	}
	b, err = NewDurationNanosecondsConverter(EmptyString)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}
	a, err = NewDataConverter(MetaRound)
	if err != nil {
		t.Error(err)
	}
	b, err = NewRoundConverter(EmptyString)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}
	a, err = NewDataConverter("*round:07")
	if err != nil {
		t.Error(err)
	}
	b, err = NewRoundConverter("7")
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}
	if _, err = NewDataConverter(MetaMultiply); err == nil || err != ErrMandatoryIeMissingNoCaps {
		t.Error(err)
	}
	a, err = NewDataConverter("*multiply:3.3")
	if err != nil {
		t.Error(err)
	}
	b, err = NewMultiplyConverter("3.3")
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}
	if _, err = NewDataConverter(MetaDivide); err == nil || err != ErrMandatoryIeMissingNoCaps {
		t.Error(err)
	}
	a, err = NewDataConverter("*divide:3.3")
	if err != nil {
		t.Error(err)
	}
	b, err = NewDivideConverter("3.3")
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}
	if _, err = NewDataConverter(MetaLibPhoneNumber); err == nil || err.Error() != "unsupported *libphonenumber converter parameters: <>" {
		t.Error(err)
	}
	a, err = NewDataConverter("*libphonenumber:US")
	if err != nil {
		t.Error(err)
	}
	b, err = NewPhoneNumberConverter("US")
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}
	if _, err = NewDataConverter("unsupported"); err == nil || err.Error() != "unsupported converter definition: <unsupported>" {
		t.Error(err)
	}

	hex, err := NewDataConverter(MetaString2Hex)
	if err != nil {
		t.Error(err)
	}
	exp := new(String2HexConverter)
	if !reflect.DeepEqual(hex, exp) {
		t.Errorf("Expected %+v received: %+v", exp, hex)
	}

	tm, err := NewDataConverter(MetaTimeString)
	if err != nil {
		t.Error(err)
	}
	expTime := NewTimeStringConverter(time.RFC3339)
	if !reflect.DeepEqual(tm, expTime) {
		t.Errorf("Expected %+v received: %+v", expTime, tm)
	}

	tm, err = NewDataConverter("*time_string:020106150400")
	if err != nil {
		t.Error(err)
	}
	expTime = NewTimeStringConverter("020106150400")
	if !reflect.DeepEqual(tm, expTime) {
		t.Errorf("Expected %+v received: %+v", expTime, tm)
	}
}

func TestNewDataConverterMustCompile(t *testing.T) {
	eOut, _ := NewDataConverter(MetaDurationSeconds)
	if rcv := NewDataConverterMustCompile(MetaDurationSeconds); rcv != eOut {
		t.Errorf("Expecting:  received: %+q", rcv)
	}
}

func TestNewDurationSecondsConverter(t *testing.T) {
	eOut := DurationSecondsConverter{}
	if rcv, err := NewDurationSecondsConverter("test"); err != nil {
		t.Error(err)
	} else if reflect.DeepEqual(rcv, eOut) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
}

func TestDurationSecondsConverterConvert(t *testing.T) {
	mS := &DurationSecondsConverter{}
	if _, err := mS.Convert("string"); err.Error() != "time: invalid duration \"string\"" {
		t.Error(err)
	}
}

func TestDurationNanosecondsConverterConvert(t *testing.T) {
	nS := &DurationNanosecondsConverter{}
	if _, err := nS.Convert("string"); err.Error() != "time: invalid duration \"string\"" {
		t.Error(err)
	}
}
func TestNewRoundConverter(t *testing.T) {
	if _, err := NewRoundConverter("test"); err == nil || err.Error() != "*round converter needs integer as decimals, have: <test>" {
		t.Error(err)
	}
	if _, err := NewRoundConverter(":test"); err == nil || err.Error() != "*round converter needs integer as decimals, have: <>" {
		t.Error(err)
	}
	if _, err := NewRoundConverter("test:"); err == nil || err.Error() != "*round converter needs integer as decimals, have: <test>" {
		t.Error(err)
	}
	eOut := &RoundConverter{
		Method: MetaRoundingMiddle,
	}
	if rcv, err := NewRoundConverter(EmptyString); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, eOut) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
	eOut = &RoundConverter{
		Decimals: 12,
		Method:   MetaRoundingUp,
	}
	if rcv, err := NewRoundConverter("12:*up"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, eOut) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
	eOut = &RoundConverter{
		Decimals: 12,
		Method:   MetaRoundingDown,
	}
	if rcv, err := NewRoundConverter("12:*down"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, eOut) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
	eOut = &RoundConverter{
		Decimals: 12,
		Method:   MetaRoundingMiddle,
	}
	if rcv, err := NewRoundConverter("12:*middle"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, eOut) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
	if rcv, err := NewRoundConverter("12:*middle:wrong_length"); err == nil || err.Error() != "unsupported *round converter parameters: <12:*middle:wrong_length>" {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, nil) {
		t.Errorf("Expected %+v received: %+v", nil, rcv)
	}

}

func TestRoundConverterConvert(t *testing.T) {
	rnd := &RoundConverter{}
	if rcv, err := rnd.Convert("string_test"); err == nil || err.Error() != `strconv.ParseFloat: parsing "string_test": invalid syntax` {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, nil) {
		t.Errorf("Expected %+v received: %+v", nil, rcv)
	}
	eOut := Round(18, rnd.Decimals, rnd.Method)
	if rcv, err := rnd.Convert(18); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
}

func TestNewMultiplyConverter(t *testing.T) {
	if rcv, err := NewMultiplyConverter(EmptyString); err == nil || err != ErrMandatoryIeMissingNoCaps {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, nil) {
		t.Errorf("Expected %+v received: %+v", nil, rcv)
	}
	if rcv, err := NewMultiplyConverter("string_test"); err == nil || err.Error() != `strconv.ParseFloat: parsing "string_test": invalid syntax` {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, nil) {
		t.Errorf("Expected %+v received: %+v", nil, rcv)
	}
	eOut := &MultiplyConverter{Value: 0.7}
	if rcv, err := NewMultiplyConverter("0.7"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, eOut) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
}

func TestMultiplyConverterConvert(t *testing.T) {
	m := &MultiplyConverter{}
	if rcv, err := m.Convert(EmptyString); err == nil || err.Error() != `strconv.ParseFloat: parsing "": invalid syntax` {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, nil) {
		t.Errorf("Expected %+v received: %+v", nil, rcv)
	}
	if rcv, err := m.Convert("string_test"); err == nil || err.Error() != `strconv.ParseFloat: parsing "string_test": invalid syntax` {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, nil) {
		t.Errorf("Expected %+v received: %+v", nil, rcv)
	}
	if rcv, err := m.Convert(3); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, 0.0) {
		t.Errorf("Expected %+v received: %+v", 0, rcv)
	}
}

func TestNewDivideConverter(t *testing.T) {
	if rcv, err := NewDivideConverter(EmptyString); err == nil || err != ErrMandatoryIeMissingNoCaps {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, nil) {
		t.Errorf("Expected %+v received: %+v", nil, rcv)
	}
	if rcv, err := NewDivideConverter("string_test"); err == nil || err.Error() != `strconv.ParseFloat: parsing "string_test": invalid syntax` {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, nil) {
		t.Errorf("Expected %+v received: %+v", nil, rcv)
	}
	eOut := &DivideConverter{Value: 0.7}
	if rcv, err := NewDivideConverter("0.7"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
}

func TestDivideConverterConvert(t *testing.T) {
	m := DivideConverter{}
	if rcv, err := m.Convert("string_test"); err == nil || err.Error() != `strconv.ParseFloat: parsing "string_test": invalid syntax` {
		t.Error(err)
	} else if !reflect.DeepEqual(rcv, nil) {
		t.Errorf("Expected %+v received: %+v", nil, rcv)
	}
	eOut := math.Inf(1)
	if rcv, err := m.Convert("96"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
	eOut = math.Inf(-1)
	if rcv, err := m.Convert("-96"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
	m = DivideConverter{Value: 0.7}
	eOut = 137.14285714285714
	if rcv, err := m.Convert("96"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
}

func TestNewDurationConverter(t *testing.T) {
	nS := &DurationConverter{}
	eOut := time.Duration(0)
	if rcv, err := nS.Convert(EmptyString); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
	eOut = 7 * time.Nanosecond
	if rcv, err := nS.Convert(7); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expected %+v received: %+v", eOut, rcv)
	}
}

func TestConvertFloatToSeconds(t *testing.T) {
	b, err := NewDataConverter(MetaDurationSeconds)
	if err != nil {
		t.Error(err.Error())
	}
	a, err := b.Convert(10*time.Second + 300*time.Millisecond)
	if err != nil {
		t.Error(err.Error())
	}
	expVal := 10.3
	if !reflect.DeepEqual(a, expVal) {
		t.Errorf("Expected %+v received: %+v", expVal, a)
	}
}

func TestConvertDurNanoseconds(t *testing.T) {
	d, err := NewDataConverter(MetaDurationNanoseconds)
	if err != nil {
		t.Error(err.Error())
	}
	expVal := int64(102)
	if i, err := d.Convert(102); err != nil {
		t.Error(err.Error())
	} else if expVal != i {
		t.Errorf("expecting: %d, received: %d", expVal, i)
	}
}

func TestRoundConverterFloat64(t *testing.T) {
	b, err := NewDataConverter("*round:2")
	if err != nil {
		t.Error(err.Error())
	}
	expData := &RoundConverter{
		Decimals: 2,
		Method:   MetaRoundingMiddle,
	}
	if !reflect.DeepEqual(b, expData) {
		t.Errorf("Expected %+v received: %+v", expData, b)
	}
	val, err := b.Convert(2.3456)
	if err != nil {
		t.Error(err.Error())
	}
	expV := 2.35
	if !reflect.DeepEqual(expV, val) {
		t.Errorf("Expected %+v received: %+v", expV, val)
	}
}

//testRoundconv string / float / int / time

func TestRoundConverterString(t *testing.T) {
	b, err := NewDataConverter("*round:2")
	if err != nil {
		t.Error(err.Error())
	}
	expData := &RoundConverter{
		Decimals: 2,
		Method:   MetaRoundingMiddle,
	}
	if !reflect.DeepEqual(b, expData) {
		t.Errorf("Expected %+v received: %+v", expData, b)
	}
	val, err := b.Convert("10.4295")
	if err != nil {
		t.Error(err.Error())
	}
	expV := 10.43
	if !reflect.DeepEqual(expV, val) {
		t.Errorf("Expected %+v received: %+v", expV, val)
	}
}

func TestRoundConverterInt64(t *testing.T) {
	b, err := NewDataConverter("*round:2")
	if err != nil {
		t.Error(err.Error())
	}
	expData := &RoundConverter{
		Decimals: 2,
		Method:   MetaRoundingMiddle,
	}
	if !reflect.DeepEqual(b, expData) {
		t.Errorf("Expected %+v received: %+v", expData, b)
	}
	val, err := b.Convert(int64(10))
	if err != nil {
		t.Error(err.Error())
	}
	expV := 10.0
	if !reflect.DeepEqual(expV, val) {
		t.Errorf("Expected %+v received: %+v", expV, val)
	}
}

func TestRoundConverterTime(t *testing.T) {
	b, err := NewDataConverter("*round:2")
	if err != nil {
		t.Error(err.Error())
	}
	expData := &RoundConverter{
		Decimals: 2,
		Method:   MetaRoundingMiddle,
	}
	if !reflect.DeepEqual(b, expData) {
		t.Errorf("Expected %+v received: %+v", expData, b)
	}
	val, err := b.Convert(123 * time.Nanosecond)
	if err != nil {
		t.Error(err.Error())
	}
	expV := 123.0
	if !reflect.DeepEqual(expV, val) {
		t.Errorf("Expected %+v received: %+v", expV, val)
	}
}

func TestMultiplyConverter(t *testing.T) {
	eMpl := &MultiplyConverter{1024.0}
	m, err := NewDataConverter("*multiply:1024.0")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eMpl, m) {
		t.Errorf("expecting: %+v, received: %+v", eMpl, m)
	}
	expOut := 2048.0
	if out, err := m.Convert(2); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expOut, out) {
		t.Errorf("expecting: %+v, received: %+v", expOut, out)
	}
	expOut = 1536.0
	if out, err := m.Convert(1.5); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expOut, out) {
		t.Errorf("expecting: %+v, received: %+v", expOut, out)
	}
}

func TestDivideConverter(t *testing.T) {
	eDvd := &DivideConverter{1024.0}
	d, err := NewDataConverter("*divide:1024.0")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eDvd, d) {
		t.Errorf("expecting: %+v, received: %+v", eDvd, d)
	}
	expOut := 2.0
	if out, err := d.Convert(2048); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expOut, out) {
		t.Errorf("expecting: %+v, received: %+v", expOut, out)
	}
	expOut = 1.5
	if out, err := d.Convert(1536.0); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expOut, out) {
		t.Errorf("expecting: %+v, received: %+v", expOut, out)
	}
	if _, err := eDvd.Convert("strionmg"); err == nil || err.Error() != `strconv.ParseFloat: parsing "strionmg": invalid syntax` {
		t.Error(err)
	}
}

func TestDurationConverter(t *testing.T) {
	d, err := NewDataConverter(MetaDuration)
	if err != nil {
		t.Error(err.Error())
	}
	expVal := 10 * time.Second
	if i, err := d.Convert(10000000000.0); err != nil {
		t.Error(err.Error())
	} else if expVal != i {
		t.Errorf("expecting: %d, received: %d", expVal, i)
	}
	if i, err := d.Convert(10000000000); err != nil {
		t.Error(err.Error())
	} else if expVal != i {
		t.Errorf("expecting: %d, received: %d", expVal, i)
	}
	if i, err := d.Convert(10 * time.Second); err != nil {
		t.Error(err.Error())
	} else if expVal != i {
		t.Errorf("expecting: %d, received: %d", expVal, i)
	}
	if i, err := d.Convert("10s"); err != nil {
		t.Error(err.Error())
	} else if expVal != i {
		t.Errorf("expecting: %d, received: %d", expVal, i)
	}
}

func TestPhoneNumberConverter(t *testing.T) {
	// test for error
	if rcv, err := NewDataConverter("*libphonenumber:US:1:2:error"); err == nil || err.Error() != "unsupported *libphonenumber converter parameters: <US:1:2:error>" {
		t.Error(err)
	} else if !reflect.DeepEqual(nil, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", nil, rcv)
	}
	if rcv, err := NewDataConverter("*libphonenumber:US:X"); err == nil || err.Error() != `strconv.Atoi: parsing "X": invalid syntax` {
		t.Error(err)
	} else if !reflect.DeepEqual(nil, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", nil, rcv)
	}
	eLc := &PhoneNumberConverter{CountryCode: "9786679", Format: phonenumbers.NATIONAL}
	if _, err := eLc.Convert("8976wedf"); err == nil || err.Error() != "invalid country code" {
		t.Errorf("Expecting: 'invalid country code', received: %+v", err)
	}

	// US/National
	eLc = &PhoneNumberConverter{CountryCode: "US", Format: phonenumbers.NATIONAL}
	d, err := NewDataConverter("*libphonenumber:US")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eLc, d) {
		t.Errorf("expecting: %+v, received: %+v", eLc, d)
	}
	// simulate an E164 number and Format it into a National number
	phoneNumberConverted, err := d.Convert("+14431234567")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(phoneNumberConverted, "(443) 123-4567") {
		t.Errorf("expecting: %+v, received: %+v", "(443) 123-4567", phoneNumberConverted)
	}
	//US/International
	eLc = &PhoneNumberConverter{CountryCode: "US", Format: phonenumbers.INTERNATIONAL}
	d, err = NewDataConverter("*libphonenumber:US:1")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eLc, d) {
		t.Errorf("expecting: %+v, received: %+v", eLc, d)
	}
	// simulate an E164 number and Format it into a National number
	phoneNumberConverted, err = d.Convert("+14431234567")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(phoneNumberConverted, "+1 443-123-4567") {
		t.Errorf("expecting: %+v, received: %+v", "+1 443-123-4567", phoneNumberConverted)
	}
	// DE/International
	eLc = &PhoneNumberConverter{CountryCode: "DE", Format: phonenumbers.INTERNATIONAL}
	d, err = NewDataConverter("*libphonenumber:DE:1")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eLc, d) {
		t.Errorf("expecting: %+v, received: %+v", eLc, d)
	}
	phoneNumberConverted, err = d.Convert("6502530000")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(phoneNumberConverted, "+49 6502 530000") {
		t.Errorf("expecting: %+v, received: %+v", "+49 6502 530000", phoneNumberConverted)
	}
	// DE/E164
	eLc = &PhoneNumberConverter{CountryCode: "DE", Format: phonenumbers.E164}
	d, err = NewDataConverter("*libphonenumber:DE:0")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(eLc, d) {
		t.Errorf("expecting: %+v, received: %+v", eLc, d)
	}
	phoneNumberConverted, err = d.Convert("6502530000")
	if err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(phoneNumberConverted, "+496502530000") {
		t.Errorf("expecting: %+v, received: %+v", "+496502530000", phoneNumberConverted)
	}
}

func TestHexConvertor(t *testing.T) {
	hx := new(IP2HexConverter)
	val := "127.0.0.1"
	expected := "0x7f000001"
	if rpl, err := hx.Convert(val); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}
	val2 := net.ParseIP("127.0.0.1")
	if rpl, err := hx.Convert(val2); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}

	val3 := []byte("127.0.0.1")
	if rpl, err := hx.Convert(val3); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}

	val = ""
	expected = ""
	if rpl, err := hx.Convert(val); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}

	val = "62.87.114.244"
	expected = "0x3e5772f4"
	if rpl, err := hx.Convert(val); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}
}

type testMockConverter struct{}

// Convert function to implement DataConverter
func (*testMockConverter) Convert(any) (any, error) { return nil, ErrNotFound }
func TestDataConvertersConvertString2(t *testing.T) {
	hex, err := NewDataConverter(MetaIP2Hex)
	if err != nil {
		t.Error(err)
	}

	host, err := NewDataConverter(MetaSIPURIHost)
	if err != nil {
		t.Error(err)
	}
	user, err := NewDataConverter(MetaSIPURIUser)
	if err != nil {
		t.Error(err)
	}
	method, err := NewDataConverter(MetaSIPURIMethod)
	if err != nil {
		t.Error(err)
	}

	dc := DataConverters{new(testMockConverter), hex, host, user, method}
	if _, err := dc.ConvertString(""); err != ErrNotFound {
		t.Errorf("Expected error %s ,received %v", ErrNotFound, err)
	}
}

func TestSIPURIConverter(t *testing.T) {
	host := new(SIPURIHostConverter)
	val := "INVITE sip:1002@192.168.58.203 SIP/2.0"
	expected := "192.168.58.203"
	if rply, err := host.Convert(val); err != nil {
		t.Error(err)
	} else if rply != expected {
		t.Errorf("Expected %q, received: %q", rply, expected)
	}

	method := new(SIPURIMethodConverter)
	expected = "INVITE"
	if rply, err := method.Convert(val); err != nil {
		t.Error(err)
	} else if rply != expected {
		t.Errorf("Expected %q, received: %q", rply, expected)
	}

	user := new(SIPURIUserConverter)
	expected = "1002"
	if rply, err := user.Convert(val); err != nil {
		t.Error(err)
	} else if rply != expected {
		t.Errorf("Expected %q, received: %q", rply, expected)
	}

}

func TestNewDataConverterMustCompile2(t *testing.T) {
	defer func() {
		expectedMessage := "parsing: <*multiply>, error: mandatory information missing"
		if r := recover(); r != expectedMessage {
			t.Errorf("Expected %q, received: %q", expectedMessage, r)
		}
	}()
	NewDataConverterMustCompile(MetaMultiply)
}

func TestNewTimeStringConverter(t *testing.T) {
	//empty
	eOut := &TimeStringConverter{Layout: EmptyString}
	if rcv := NewTimeStringConverter(EmptyString); !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
	}

	//default
	eOut = &TimeStringConverter{Layout: time.RFC3339}
	var rcv DataConverter
	if rcv = NewTimeStringConverter(time.RFC3339); !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
	}
	exp := "2015-07-07T14:52:08Z"
	if rcv, err := rcv.Convert("1436280728"); err != nil {
		t.Error(err)
	} else if rcv.(string) != exp {
		t.Errorf("Expecting: %+v, received: %+v", exp, rcv)
	}
	exp = "2013-07-30T19:33:10Z"
	if rcv, err := rcv.Convert("1375212790"); err != nil {
		t.Error(err)
	} else if rcv.(string) != exp {
		t.Errorf("Expecting: %+v, received: %+v", exp, rcv)
	}

	//other
	eOut = &TimeStringConverter{"020106150400"}
	if rcv = NewTimeStringConverter("020106150400"); !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
	}
	exp = "070715145200"
	if rcv, err := rcv.Convert("1436280728"); err != nil {
		t.Error(err)
	} else if rcv.(string) != exp {
		t.Errorf("Expecting: %+v, received: %+v", exp, rcv)
	}
	exp = "290720175900"
	if rcv, err := rcv.Convert("2020-07-29T17:59:59Z"); err != nil {
		t.Error(err)
	} else if rcv.(string) != exp {
		t.Errorf("Expecting: %+v, received: %+v", exp, rcv)
	}

	//wrong cases
	eOut = &TimeStringConverter{"not really a good time"}
	if rcv = NewTimeStringConverter("not really a good time"); !reflect.DeepEqual(eOut, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", eOut, rcv)
	}
	exp = "not really a good time"
	if rcv, err := rcv.Convert(EmptyString); err != nil {
		t.Error(err)
	} else if rcv.(string) != exp {
		t.Errorf("Expecting: %+v, received: %+v", exp, rcv)
	}
	if rcv, err := rcv.Convert("1375212790"); err != nil {
		t.Error(err)
	} else if rcv.(string) != exp {
		t.Errorf("Expecting: %+v, received: %+v", exp, rcv)
	}
	if _, err := rcv.Convert("137521s2790"); err == nil {
		t.Errorf("Expected error received: %v:", err)
	}
}

func TestStringHexConvertor(t *testing.T) {
	hx := new(String2HexConverter)
	val := "127.0.0.1"
	expected := "0x3132372e302e302e31"
	if rpl, err := hx.Convert(val); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}

	val3 := []byte("127.0.0.1")
	if rpl, err := hx.Convert(val3); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}

	val = ""
	expected = ""
	if rpl, err := hx.Convert(val); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}

	val3 = []byte{0x94, 0x71, 0x02, 0x31, 0x01, 0x59}
	expected = "0x947102310159"
	if rpl, err := hx.Convert(val3); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}

	val3 = []byte{0x88, 0x90, 0xa6}
	expected = "0x8890a6"
	if rpl, err := hx.Convert(val3); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rpl) {
		t.Errorf("expecting: %+v, received: %+v", expected, rpl)
	}
}

func TestUnixTimeConverter(t *testing.T) {
	exp := new(UnixTimeConverter)
	cnv, err := NewDataConverter(MetaUnixTime)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(exp, cnv) {
		t.Errorf("Expecting: %+v, received: %+v", exp, cnv)
	}

	expected := int64(1436280728)
	if rcv, err := cnv.Convert("2015-07-07T14:52:08Z"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if _, err := cnv.Convert("NotAValidTime"); err == nil {
		t.Errorf("Expected error received %v", err)
	}
}

func TestRandomConverter(t *testing.T) {
	exp := new(RandomConverter)
	if cnv, err := NewRandomConverter(EmptyString); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(exp, cnv) {
		t.Errorf("Expecting: %+v, received: %+v", exp, cnv)
	}

	if rcv, err := exp.Convert(nil); err != nil {
		t.Error(err)
	} else if rcv == 0 {
		t.Errorf("Expecting different than 0, received: %+v", rcv)
	}
	exp.begin = 10
	if rcv, err := exp.Convert(nil); err != nil {
		t.Error(err)
	} else if rcv.(int) < 10 {
		t.Errorf("Expecting bigger than 10, received: %+v", rcv)
	}
	exp.end = 20
	if rcv, err := exp.Convert(nil); err != nil {
		t.Error(err)
	} else if rcv.(int) < 10 || rcv.(int) > 20 {
		t.Errorf("Expecting bigger than 10 and smaller than 20, received: %+v", rcv)
	}
}

func TestDCNewDataConverterRandomPrefixEmpty(t *testing.T) {

	a, err := NewDataConverter(MetaRandom)
	if err != nil {
		t.Error(err)
	}
	b, err := NewRandomConverter(EmptyString)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}

}

func TestDCNewDataConverterRandomPrefix(t *testing.T) {
	params := "*random:1:2"
	a, err := NewDataConverter(params)
	if err != nil {
		t.Error(err)
	}

	b, err := NewRandomConverter(params[len(MetaRandom)+1:])
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(a, b) {
		t.Error("Error reflect")
	}
}

func TestDCNewRandomConverterCase2Begin(t *testing.T) {
	params := "test:15"

	_, err := NewRandomConverter(params)
	expected := "strconv.Atoi: parsing \"test\": invalid syntax"

	if err == nil || err.Error() != expected {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", expected, err.Error())
	}
}

func TestDCNewRandomConverterCase2End(t *testing.T) {
	params := "15:test"

	_, err := NewRandomConverter(params)
	expected := "strconv.Atoi: parsing \"test\": invalid syntax"

	if err == nil || err.Error() != expected {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", expected, err.Error())
	}
}

func TestDCNewRandomConverterCase1Begin(t *testing.T) {
	params := "test"

	_, err := NewRandomConverter(params)
	expected := "strconv.Atoi: parsing \"test\": invalid syntax"

	if err == nil || err.Error() != expected {
		t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", expected, err.Error())
	}
}

func TestDCrCConvert(t *testing.T) {
	randConv := &RandomConverter{
		begin: 0,
		end:   2,
	}

	received, err := randConv.Convert(randConv.begin)
	if err != nil {
		t.Error(err)
	}
	receivedAsInt, err := IfaceAsInt64(received)
	if err != nil {
		t.Error(err)
	}
	if receivedAsInt != 0 && receivedAsInt != 1 {
		t.Errorf("\nExpected 0 or 1, \nReceived: <%+v>", received)
	}
}

func TestLenTimeConverter(t *testing.T) {
	exp := new(LengthConverter)
	cnv, err := NewDataConverter(MetaLen)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(exp, cnv) {
		t.Errorf("Expecting: %+v, received: %+v", exp, cnv)
	}

	expected := 20
	if rcv, err := cnv.Convert("2015-07-07T14:52:08Z"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
}

func TestLenTimeConverter2(t *testing.T) {
	exp := new(LengthConverter)
	cnv, err := NewDataConverter(MetaLen)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(exp, cnv) {
		t.Errorf("Expecting: %+v, received: %+v", exp, cnv)
	}

	expected := 7
	if rcv, err := cnv.Convert("[slice]"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
}

func TestLenTimeConverter3(t *testing.T) {
	exp := new(LengthConverter)
	cnv, err := NewDataConverter(MetaLen)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(exp, cnv) {
		t.Errorf("Expecting: %+v, received: %+v", exp, cnv)
	}

	expected := 2
	if rcv, err := cnv.Convert([]int{0, 0}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert("[}"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	expected = 0
	if rcv, err := cnv.Convert([]string{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]any{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]bool{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]int{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]int8{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]int16{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]int32{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]int64{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]uint{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]uint8{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]uint16{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]uint32{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]uint64{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]uintptr{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]float32{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]float64{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]complex64{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert([]complex128{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}

	if rcv, err := cnv.Convert(map[string]string{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]any{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]bool{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]int{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]int8{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]int16{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]int32{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]int64{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]uint{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]uint8{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]uint16{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]uint32{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]uint64{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]uintptr{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]float32{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]float64{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]complex64{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert(map[string]complex128{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}

	if rcv, err := cnv.Convert(map[string]Account{}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}

	if rcv, err := cnv.Convert("[]"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	if rcv, err := cnv.Convert("{}"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
}

func TestFloat64Converter(t *testing.T) {
	exp := new(Float64Converter)
	cnv, err := NewDataConverter(MetaFloat64)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(exp, cnv) {
		t.Errorf("Expecting: %+v, received: %+v", exp, cnv)
	}

	expected := 21.7
	if rcv, err := cnv.Convert("21.7"); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}

	expected2 := "strconv.ParseFloat: parsing \"invalid_input\": invalid syntax"
	if _, err := cnv.Convert("invalid_input"); err == nil {
		t.Error("Expected error")
	} else if !reflect.DeepEqual(expected2, err.Error()) {
		t.Errorf("Expecting: %+v, received: %+v", expected2, err.Error())
	}
}

func TestSliceConverter(t *testing.T) {
	exp := new(SliceConverter)
	cnv, err := NewDataConverter(MetaSlice)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(exp, cnv) {
		t.Errorf("Expecting: %+v, received: %+v", exp, cnv)
	}
	expected := []string{"A", "B"}
	if rcv, err := cnv.Convert([]string{"A", "B"}); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
	expected2 := []any{"A", "B"}
	if rcv, err := cnv.Convert(`["A","B"]`); err != nil {
		t.Error(err)
	} else if !reflect.DeepEqual(expected2, rcv) {
		t.Errorf("Expecting: %+v, received: %+v", expected, rcv)
	}
}

func TestE164FromNAPTRConverter(t *testing.T) {
	exp := new(e164Converter)
	cnv, err := NewDataConverter(E164Converter)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(exp, cnv) {
		t.Errorf("Expecting: %+v, received: %+v", exp, cnv)
	}
	if e164, err := cnv.Convert("8.7.6.5.4.3.2.1.0.1.6.e164.arpa."); err != nil {
		t.Error(err)
	} else if e164 != "61012345678" {
		t.Errorf("received: <%s>", e164)
	}
}

func TestDomainNameFromNAPTRConverter(t *testing.T) {
	exp := new(e164DomainConverter)
	cnv, err := NewDataConverter(E164DomainConverter)
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(exp, cnv) {
		t.Errorf("Expecting: %+v, received: %+v", exp, cnv)
	}
	if dName, err := cnv.Convert("8.7.6.5.4.3.2.1.0.1.6.e164.arpa."); err != nil {
		t.Fatal(err)
	} else if dName != "e164.arpa" {
		t.Errorf("received: <%s>", dName)
	}
	if dName, err := cnv.Convert("8.7.6.5.4.3.2.1.0.1.6.e164.itsyscom.com."); err != nil {
		t.Fatal(err)
	} else if dName != "e164.itsyscom.com" {
		t.Errorf("received: <%s>", dName)
	}
	if dName, err := cnv.Convert("8.7.6.5.4.3.2.1.0.1.6.itsyscom.com."); err != nil {
		t.Fatal(err)
	} else if dName != "8.7.6.5.4.3.2.1.0.1.6.itsyscom.com" {
		t.Errorf("received: <%s>", dName)
	}
}

func TestDataConverterLengthConvert(t *testing.T) {
	var lC LengthConverter
	input := NewDecimal(2, 0)
	rcv, _ := lC.Convert(input)
	if rcv != 1 {
		t.Error("Expected 1")
	}
}

func TestDataConverterSliceConvert(t *testing.T) {
	var lC SliceConverter
	input := NewDecimal(2, 0)
	rcv, _ := lC.Convert(input)
	if rcv != "2" {
		t.Error("Expected 2")
	}
}

func TestDataConverterE164Convert(t *testing.T) {
	var lC e164Converter
	input := NewDecimal(2, 0)
	_, err := lC.Convert(input)
	if err == nil || err.Error() != "unknown format" {
		t.Errorf("Expected 'unknown format' error")
	}
}

func TestJoinConverter(t *testing.T) {
	d, err := NewDataConverter(MetaJoin)
	if err != nil {
		t.Fatal(err)
	}
	expVal := "1;2;3;5"
	if i, err := d.Convert("1;2;3;5"); err != nil {
		t.Error(err.Error())
	} else if expVal != i {
		t.Errorf("expecting: %q, received: %q", expVal, i)
	}

	d, err = NewDataConverter(MetaJoin + ":|")
	if err != nil {
		t.Fatal(err)
	}
	expVal = "1|2|3|5"
	if i, err := d.Convert("1;2;3;5"); err != nil {
		t.Error(err.Error())
	} else if expVal != i {
		t.Errorf("expecting: %q, received: %q", expVal, i)
	}
	expErr := `cannot convert field: 5 to []string`
	if _, err := d.Convert(5); err == nil || err.Error() != expErr {
		t.Error(err)
	}
}

func TestSplitConverter(t *testing.T) {
	d, err := NewDataConverter(MetaSplit)
	if err != nil {
		t.Fatal(err)
	}
	expVal := []string{"1", "2", "3", "5"}
	if i, err := d.Convert("1;2;3;5"); err != nil {
		t.Error(err.Error())
	} else if !reflect.DeepEqual(expVal, i) {
		t.Errorf("expecting: %q, received: %q", expVal, i)
	}

	d, err = NewDataConverter(MetaSplit + ":|")
	if err != nil {
		t.Fatal(err)
	}
	if i, err := d.Convert("1|2|3|5"); err != nil {
		t.Error(err.Error())
	} else if !reflect.DeepEqual(expVal, i) {
		t.Errorf("expecting: %q, received: %q", expVal, i)
	}
}

func TestDataConvertersConvertInterface(t *testing.T) {
	dcs := &DataConverters{}
	if rcv, err := dcs.ConvertInterface(EmptyString); err != nil {
		t.Error(err)
	} else if rcv != EmptyString {
		t.Errorf("Expecting: <%+q>, received: <%+q>", EmptyString, rcv)
	}
	if rcv, err := dcs.ConvertInterface("test"); err != nil {
		t.Error(err)
	} else if rcv != "test" {
		t.Errorf("Expecting: <test>, received: <%+q>", rcv)
	}
	dcs = &DataConverters{joinConverter(";")}
	expErrMsg := `cannot convert field: {} to []string`
	if _, err := dcs.ConvertInterface(struct{}{}); err == nil || err.Error() != expErrMsg {
		t.Errorf("Expeceted: %v, received: %v", expErrMsg, err)
	}
}

type structWithFuncField struct {
	ID       string
	Function func(int) bool
}

func TestDataConverterConvertJSONErrUnsupportedType(t *testing.T) {
	dc, err := NewDataConverter(MetaJSON)
	if err != nil {
		t.Error(err)
	}

	obj := structWithFuncField{
		ID: "testStruct",
		Function: func(i int) bool {
			return i != 0
		},
	}

	experr := `json: unsupported type: func(int) bool`
	if rcv, err := dc.Convert(obj); err == nil || err.Error() != experr {
		t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
	} else if rcv != EmptyString {
		t.Errorf("expected: <%+v>, \nreceived: <%+v>", EmptyString, rcv)
	}
}

func TestDataConverterConvertJSONOK(t *testing.T) {
	dc, err := NewDataConverter(MetaJSON)
	if err != nil {
		t.Error(err)
	}

	obj := &CGREvent{
		Tenant: "cgrates.org",
		ID:     "TestCGREv",
		Event: map[string]any{
			AccountField: "1001",
		},
		APIOpts: map[string]any{
			"opt": "value",
		},
	}

	exp := ToJSON(obj)
	if rcv, err := dc.Convert(obj); err != nil {
		t.Error(err)
	} else if rcv.(string) != exp {
		t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rcv)
	}
}

func TestStripConverter(t *testing.T) {
	tests := []struct {
		name           string
		params         string
		input          string
		expected       string
		constructorErr bool
		convertErr     bool
	}{

		{
			name:           "Strip 5 leading characters",
			params:         "*strip:*prefix:5",
			input:          "12345TEST12345",
			expected:       "TEST12345",
			constructorErr: false,
			convertErr:     false,
		},
		{
			name:           "Strip 5 trailing characters",
			params:         "*strip:*suffix:5",
			input:          "12345TEST12345",
			expected:       "12345TEST",
			constructorErr: false,
			convertErr:     false,
		},
		{
			name:           "Strip 5 characters from both sides",
			params:         "*strip:*both:5",
			input:          "12345TEST12345",
			expected:       "TEST",
			constructorErr: false,
			convertErr:     false,
		},
		{
			name:           "Strip all trailing nils",
			params:         "*strip:*suffix:*nil",
			input:          "TEST\u0000\u0000\u0000\u0000",
			expected:       "TEST",
			constructorErr: false,
			convertErr:     false,
		},
		{
			name:           "Strip all leading nils",
			params:         "*strip:*prefix:*nil",
			input:          "\u0000\u0000\u0000\u0000TEST",
			expected:       "TEST",
			constructorErr: false,
			convertErr:     false,
		},
		{
			name:           "Strip all nils from both sides",
			params:         "*strip:*both:*nil",
			input:          "\u0000\u0000TEST\u0000\u0000",
			expected:       "TEST",
			constructorErr: false,
			convertErr:     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:           "Strip 2 leading nils",
			params:         "*strip:*prefix:*nil:2",
			input:          "\u0000\u0000\u0000\u0000TEST",
			expected:       "\u0000\u0000TEST",
			constructorErr: false,
			convertErr:     false,
		},
		{
			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:           "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:       "strip converter: substr parameter cannot be empty",
			constructorErr: true,
			convertErr:     false,
		},
		{
			name:           "Invalid side parameter",
			params:         "*strip:*invalid:*nil",
			input:          "TEST",
			expected:       "strip converter: invalid side parameter",
			constructorErr: false,
			convertErr:     true,
		},
		{
			name:           "Invalid nr. of params *char",
			params:         "*strip:*prefix:*char:*nil:abc:3",
			input:          "TEST",
			expected:       "strip converter: invalid number of parameters (should have 3, 4 or 5)",
			constructorErr: true,
			convertErr:     false,
		},
		{
			name:           "Invalid amount parameter",
			params:         "*strip:*prefix:*char:0:three",
			input:          "000TEST",
			expected:       "strip converter: invalid amount parameter (strconv.Atoi: parsing \"three\": invalid syntax)",
			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,
		},
		{
			name:           "*char missing substring case 1",
			params:         "*strip:*prefix:*char",
			input:          "12345TEST",
			expected:       "strip converter: usage of *char implies the need of 4 or 5 non-empty params",
			constructorErr: true,
			convertErr:     false,
		},
		{
			name:           "*char missing substring case 2",
			params:         "*strip:*prefix:*char::2",
			input:          "12345TEST",
			expected:       "strip converter: usage of *char implies the need of 4 or 5 non-empty params",
			constructorErr: true,
			convertErr:     false,
		},
		{
			name:           "*char missing substring case 3",
			params:         "*strip:*prefix:*char:",
			input:          "12345TEST",
			expected:       "strip converter: usage of *char implies the need of 4 or 5 non-empty params",
			constructorErr: true,
			convertErr:     false,
		},
		{
			name:           "*nil/*space too many parameters",
			params:         "*strip:*prefix:*nil:5:12345",
			input:          "12345TEST",
			expected:       "strip converter: cannot have 5 params in *nil/*space case",
			constructorErr: true,
			convertErr:     false,
		},
		{
			name:           "third param numeric with too many params case 1",
			params:         "*strip:*prefix:1:1",
			input:          "12345TEST",
			expected:       "strip converter: just the amount specified, cannot have more than 3 params",
			constructorErr: true,
			convertErr:     false,
		},
		{
			name:           "third param numeric with too many params case 2",
			params:         "*strip:*prefix:1:12345:1",
			input:          "12345TEST",
			expected:       "strip converter: just the amount specified, cannot have more than 3 params",
			constructorErr: true,
			convertErr:     false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			sc, err := NewDataConverter(tt.params)
			if err != nil != tt.constructorErr {
				t.Errorf("NewStripConverter() error = %v, constructorErr %v", err, tt.constructorErr)
				return
			}
			if tt.constructorErr {
				if err.Error() != tt.expected {
					t.Errorf("expected error message: %v, received: %v", tt.expected, err.Error())
				}
				return
			}
			rcv, err := sc.Convert(tt.input)
			if err != nil != tt.convertErr {
				t.Errorf("Convert() error = %v, convertErr %v", err, tt.convertErr)
				return
			}
			if tt.convertErr {
				if err.Error() != tt.expected {
					t.Errorf("expected error message: %s, received: %s", tt.expected, err.Error())
				}
				return
			}
			if rcv != tt.expected {
				t.Errorf("expected: %q, received: %q", tt.expected, rcv)
			}
		})
	}
}

func TestGigaWordsConverter(t *testing.T) {
	converter := GigawordsConverter{}
	multiplier := int64(4294967296)
	testCases := []struct {
		name          string
		input         any
		expectedValue int64
		expectError   bool
		errorContains string
	}{
		{
			name:          "Input Zero (int)",
			input:         int(0),
			expectedValue: 0,
			expectError:   false,
		},
		{
			name:          "Input Zero (int32)",
			input:         int32(0),
			expectedValue: 0,
			expectError:   false,
		},
		{
			name:          "Input One (int)",
			input:         int(1),
			expectedValue: multiplier,
			expectError:   false,
		},
		{
			name:          "Input Two (int64)",
			input:         int64(2),
			expectedValue: 2 * multiplier,
			expectError:   false,
		},
		{
			name:          "Input Three (string)",
			input:         "3",
			expectedValue: 3 * multiplier,
			expectError:   false,
		},
		{
			name:          "Input Nil",
			input:         nil,
			expectedValue: 0,
			expectError:   true,
			errorContains: "cannot convert",
		},
		{
			name:          "Input Invalid String",
			input:         "abc",
			expectedValue: 0,
			expectError:   true,
			errorContains: "strconv.ParseInt: parsing \"abc\": invalid syntax",
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			output, err := converter.Convert(tc.input)
			if tc.expectError {
				if err == nil || !strings.Contains(err.Error(), tc.errorContains) {
					t.Errorf("Expected error '%s', but got '%v'", tc.errorContains, err)
				}
				return
			}
			if err != nil {
				t.Fatalf("Expected no error, but got: %v", err)
			}

			outputInt64, ok := output.(int64)
			if !ok {
				t.Fatalf("Expected output type int64, but got %T (%v)", output, output)
			}
			if outputInt64 != tc.expectedValue {
				t.Errorf("Expected output %d, but got %d", tc.expectedValue, outputInt64)
			}
		})
	}
}
