From b657e60fefd51d21adf8dc95898149009798576a Mon Sep 17 00:00:00 2001 From: Pavel Gabriel Date: Fri, 8 Sep 2023 10:56:22 +0200 Subject: [PATCH] set String and Numeric field data using struct with basic types --- exp_test.go | 161 +++++++++++++++++++++++++++++++++++++++++++---- field/numeric.go | 40 +++++++----- field/string.go | 14 +++-- 3 files changed, 185 insertions(+), 30 deletions(-) diff --git a/exp_test.go b/exp_test.go index f6d45b1..0142461 100644 --- a/exp_test.go +++ b/exp_test.go @@ -13,23 +13,162 @@ func TestStructWithTypes(t *testing.T) { MTI string `index:"0"` PrimaryAccountNumber string `index:"2"` ProcessingCode int `index:"3"` - TransactionAmount int `index:"4,keepzero"` // we will set message field value to 0 + TransactionAmount *int `index:"4,keepzero"` // we will set message field value to 0 } t.Run("pack", func(t *testing.T) { - authRequest := &authRequestData{ - MTI: "0110", - PrimaryAccountNumber: "4242424242424242", - ProcessingCode: 200000, + panInt := 4242424242424242 + panStr := "4242424242424242" + + tests := []struct { + name string + input interface{} + expectedPackedString string + }{ + // Tests for string type + { + name: "struct with string type and value set", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber string `index:"2"` + }{ + MTI: "0110", + PrimaryAccountNumber: panStr, + }, + expectedPackedString: "011040000000000000000000000000000000164242424242424242", + }, + { + name: "struct with string type and no value", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber string `index:"2"` + }{ + MTI: "0110", + }, + expectedPackedString: "011000000000000000000000000000000000", + }, + { + name: "struct with string type, no value and keepzero tag - length prefix is set to 0 and no value is following", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber string `index:"2,keepzero"` + }{ + MTI: "0110", + }, + expectedPackedString: "01104000000000000000000000000000000000", + }, + + // Tests for *string type + { + name: "struct with *string type and value set", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber *string `index:"2"` + }{ + MTI: "0110", + PrimaryAccountNumber: &panStr, + }, + expectedPackedString: "011040000000000000000000000000000000164242424242424242", + }, + { + name: "struct with *string type and no value", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber *string `index:"2"` + }{ + MTI: "0110", + }, + expectedPackedString: "011000000000000000000000000000000000", + }, + { + name: "struct with *string type, no value and keepzero tag", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber *string `index:"2,keepzero"` + }{ + MTI: "0110", + }, + expectedPackedString: "011000000000000000000000000000000000", + }, + + // Tests for int type + { + name: "struct with int type and value set", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber int `index:"2"` + }{ + MTI: "0110", + PrimaryAccountNumber: panInt, + }, + expectedPackedString: "011040000000000000000000000000000000164242424242424242", + }, + { + name: "struct with int type and no value", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber int `index:"2"` + }{ + MTI: "0110", + }, + expectedPackedString: "011000000000000000000000000000000000", + }, + { + name: "struct with int type, no value and keepzero tag", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber int `index:"2,keepzero"` + }{ + MTI: "0110", + }, + expectedPackedString: "011040000000000000000000000000000000010", + }, + + // Tests for *int type + { + name: "struct with *int type and value set", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber *int `index:"2"` + }{ + MTI: "0110", + PrimaryAccountNumber: &panInt, + }, + expectedPackedString: "011040000000000000000000000000000000164242424242424242", + }, + { + name: "struct with *int type and no value", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber *int `index:"2"` + }{ + MTI: "0110", + }, + expectedPackedString: "011000000000000000000000000000000000", + }, + { + name: "struct with *int type, no value and keepzero tag", + input: struct { + MTI string `index:"0"` + PrimaryAccountNumber *int `index:"2,keepzero"` + }{ + MTI: "0110", + }, + expectedPackedString: "011000000000000000000000000000000000", + }, } - message := iso8583.NewMessage(specs.Spec87ASCII) - err := message.Marshal(authRequest) - require.NoError(t, err) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + message := iso8583.NewMessage(specs.Spec87ASCII) + err := message.Marshal(tt.input) + require.NoError(t, err) - packed, err := message.Pack() - require.NoError(t, err) + packed, err := message.Pack() + require.NoError(t, err) - require.Equal(t, "011070000000000000000000000000000000164242424242424242200000000000000000", string(packed)) + require.Equal(t, tt.expectedPackedString, string(packed)) + }) + } }) } diff --git a/field/numeric.go b/field/numeric.go index 3cf04d7..4e11992 100644 --- a/field/numeric.go +++ b/field/numeric.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "math" "strconv" "github.com/moov-io/iso8583/utils" @@ -148,22 +147,35 @@ func (f *Numeric) SetData(data interface{}) error { f.value = v.value case int: f.value = v - case int32: - if v >= math.MinInt32 && v <= math.MaxInt32 { - f.value = int(v) - } else { - return fmt.Errorf("int32 value out of range for int") + case *int: + if v == nil { + f.value = 0 + return nil } - case int64: - if v >= math.MinInt64 && v <= math.MaxInt64 { - f.value = int(v) - } else { - return fmt.Errorf("int64 value out of range for int") + f.value = *v + case string: + if v == "" { + f.value = 0 + return nil } - case []byte: - return f.SetBytes(v) + val, err := strconv.Atoi(v) + if err != nil { + return utils.NewSafeError(err, "failed to convert sting value into number") + } + f.value = val + case *string: + if v == nil { + f.value = 0 + return nil + } + + val, err := strconv.Atoi(*v) + if err != nil { + return utils.NewSafeError(err, "failed to convert sting value into number") + } + f.value = val default: - return fmt.Errorf("data does not match require *Numeric or supported numeric types (int, int32, int64)") + return fmt.Errorf("data does not match require *Numeric or supported numeric types (int, *int, string, *string)") } return nil diff --git a/field/string.go b/field/string.go index 29489e0..0640390 100644 --- a/field/string.go +++ b/field/string.go @@ -137,14 +137,18 @@ func (f *String) SetData(data interface{}) error { return nil } f.value = v + case *string: + if v == nil { + f.value = "" + return nil + } + f.value = *v case int: f.value = strconv.FormatInt(int64(v), 10) - case int32: - f.value = strconv.FormatInt(int64(v), 10) - case int64: - f.value = strconv.FormatInt(v, 10) + case *int: + f.value = strconv.FormatInt(int64(*v), 10) default: - return fmt.Errorf("data does not match required *String or string type") + return fmt.Errorf("data does not match required *String or (string, *string, int, *int) type") } return nil