Skip to content

Commit

Permalink
set String and Numeric field data using struct with basic types
Browse files Browse the repository at this point in the history
  • Loading branch information
alovak committed Sep 8, 2023
1 parent b65ea63 commit b657e60
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 30 deletions.
161 changes: 150 additions & 11 deletions exp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
})
}
})
}
40 changes: 26 additions & 14 deletions field/numeric.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/json"
"errors"
"fmt"
"math"
"strconv"

"github.com/moov-io/iso8583/utils"
Expand Down Expand Up @@ -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
Expand Down
14 changes: 9 additions & 5 deletions field/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit b657e60

Please sign in to comment.