| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- package dynamodbattribute
- import (
- "math"
- "testing"
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/aws/awserr"
- "github.com/aws/aws-sdk-go/service/dynamodb"
- )
- type mySimpleStruct struct {
- String string
- Int int
- Uint uint
- Float32 float32
- Float64 float64
- Bool bool
- Null *interface{}
- }
- type myComplexStruct struct {
- Simple []mySimpleStruct
- }
- type converterTestInput struct {
- input interface{}
- expected interface{}
- err awserr.Error
- inputType string // "enum" of types
- }
- var trueValue = true
- var falseValue = false
- var converterScalarInputs = []converterTestInput{
- {
- input: nil,
- expected: &dynamodb.AttributeValue{NULL: &trueValue},
- },
- {
- input: "some string",
- expected: &dynamodb.AttributeValue{S: aws.String("some string")},
- },
- {
- input: true,
- expected: &dynamodb.AttributeValue{BOOL: &trueValue},
- },
- {
- input: false,
- expected: &dynamodb.AttributeValue{BOOL: &falseValue},
- },
- {
- input: 3.14,
- expected: &dynamodb.AttributeValue{N: aws.String("3.14")},
- },
- {
- input: math.MaxFloat32,
- expected: &dynamodb.AttributeValue{N: aws.String("340282346638528860000000000000000000000")},
- },
- {
- input: math.MaxFloat64,
- expected: &dynamodb.AttributeValue{N: aws.String("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")},
- },
- {
- input: 12,
- expected: &dynamodb.AttributeValue{N: aws.String("12")},
- },
- {
- input: mySimpleStruct{},
- expected: &dynamodb.AttributeValue{
- M: map[string]*dynamodb.AttributeValue{
- "Bool": {BOOL: &falseValue},
- "Float32": {N: aws.String("0")},
- "Float64": {N: aws.String("0")},
- "Int": {N: aws.String("0")},
- "Null": {NULL: &trueValue},
- "String": {S: aws.String("")},
- "Uint": {N: aws.String("0")},
- },
- },
- inputType: "mySimpleStruct",
- },
- }
- var converterMapTestInputs = []converterTestInput{
- // Scalar tests
- {
- input: nil,
- err: awserr.New("SerializationError", "in must be a map[string]interface{} or struct, got <nil>", nil),
- },
- {
- input: map[string]interface{}{"string": "some string"},
- expected: map[string]*dynamodb.AttributeValue{"string": {S: aws.String("some string")}},
- },
- {
- input: map[string]interface{}{"bool": true},
- expected: map[string]*dynamodb.AttributeValue{"bool": {BOOL: &trueValue}},
- },
- {
- input: map[string]interface{}{"bool": false},
- expected: map[string]*dynamodb.AttributeValue{"bool": {BOOL: &falseValue}},
- },
- {
- input: map[string]interface{}{"null": nil},
- expected: map[string]*dynamodb.AttributeValue{"null": {NULL: &trueValue}},
- },
- {
- input: map[string]interface{}{"float": 3.14},
- expected: map[string]*dynamodb.AttributeValue{"float": {N: aws.String("3.14")}},
- },
- {
- input: map[string]interface{}{"float": math.MaxFloat32},
- expected: map[string]*dynamodb.AttributeValue{"float": {N: aws.String("340282346638528860000000000000000000000")}},
- },
- {
- input: map[string]interface{}{"float": math.MaxFloat64},
- expected: map[string]*dynamodb.AttributeValue{"float": {N: aws.String("179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")}},
- },
- {
- input: map[string]interface{}{"int": int(12)},
- expected: map[string]*dynamodb.AttributeValue{"int": {N: aws.String("12")}},
- },
- {
- input: map[string]interface{}{"byte": []byte{48, 49}},
- expected: map[string]*dynamodb.AttributeValue{"byte": {B: []byte{48, 49}}},
- },
- // List
- {
- input: map[string]interface{}{"list": []interface{}{"a string", 12, 3.14, true, nil, false}},
- expected: map[string]*dynamodb.AttributeValue{
- "list": {
- L: []*dynamodb.AttributeValue{
- {S: aws.String("a string")},
- {N: aws.String("12")},
- {N: aws.String("3.14")},
- {BOOL: &trueValue},
- {NULL: &trueValue},
- {BOOL: &falseValue},
- },
- },
- },
- },
- // Map
- {
- input: map[string]interface{}{"map": map[string]interface{}{"nestedint": 12}},
- expected: map[string]*dynamodb.AttributeValue{
- "map": {
- M: map[string]*dynamodb.AttributeValue{
- "nestedint": {
- N: aws.String("12"),
- },
- },
- },
- },
- },
- // Structs
- {
- input: mySimpleStruct{},
- expected: map[string]*dynamodb.AttributeValue{
- "Bool": {BOOL: &falseValue},
- "Float32": {N: aws.String("0")},
- "Float64": {N: aws.String("0")},
- "Int": {N: aws.String("0")},
- "Null": {NULL: &trueValue},
- "String": {S: aws.String("")},
- "Uint": {N: aws.String("0")},
- },
- inputType: "mySimpleStruct",
- },
- {
- input: myComplexStruct{},
- expected: map[string]*dynamodb.AttributeValue{
- "Simple": {NULL: &trueValue},
- },
- inputType: "myComplexStruct",
- },
- {
- input: myComplexStruct{Simple: []mySimpleStruct{{Int: -2}, {Uint: 5}}},
- expected: map[string]*dynamodb.AttributeValue{
- "Simple": {
- L: []*dynamodb.AttributeValue{
- {
- M: map[string]*dynamodb.AttributeValue{
- "Bool": {BOOL: &falseValue},
- "Float32": {N: aws.String("0")},
- "Float64": {N: aws.String("0")},
- "Int": {N: aws.String("-2")},
- "Null": {NULL: &trueValue},
- "String": {S: aws.String("")},
- "Uint": {N: aws.String("0")},
- },
- },
- {
- M: map[string]*dynamodb.AttributeValue{
- "Bool": {BOOL: &falseValue},
- "Float32": {N: aws.String("0")},
- "Float64": {N: aws.String("0")},
- "Int": {N: aws.String("0")},
- "Null": {NULL: &trueValue},
- "String": {S: aws.String("")},
- "Uint": {N: aws.String("5")},
- },
- },
- },
- },
- },
- inputType: "myComplexStruct",
- },
- }
- var converterListTestInputs = []converterTestInput{
- {
- input: nil,
- err: awserr.New("SerializationError", "in must be an array or slice, got <nil>", nil),
- },
- {
- input: []interface{}{},
- expected: []*dynamodb.AttributeValue{},
- },
- {
- input: []interface{}{"a string", 12, 3.14, true, nil, false},
- expected: []*dynamodb.AttributeValue{
- {S: aws.String("a string")},
- {N: aws.String("12")},
- {N: aws.String("3.14")},
- {BOOL: &trueValue},
- {NULL: &trueValue},
- {BOOL: &falseValue},
- },
- },
- {
- input: []mySimpleStruct{{}},
- expected: []*dynamodb.AttributeValue{
- {
- M: map[string]*dynamodb.AttributeValue{
- "Bool": {BOOL: &falseValue},
- "Float32": {N: aws.String("0")},
- "Float64": {N: aws.String("0")},
- "Int": {N: aws.String("0")},
- "Null": {NULL: &trueValue},
- "String": {S: aws.String("")},
- "Uint": {N: aws.String("0")},
- },
- },
- },
- inputType: "mySimpleStruct",
- },
- }
- func TestConvertTo(t *testing.T) {
- for _, test := range converterScalarInputs {
- testConvertTo(t, test)
- }
- }
- func testConvertTo(t *testing.T, test converterTestInput) {
- actual, err := ConvertTo(test.input)
- if test.err != nil {
- if err == nil {
- t.Errorf("ConvertTo with input %#v retured %#v, expected error `%s`", test.input, actual, test.err)
- } else if err.Error() != test.err.Error() {
- t.Errorf("ConvertTo with input %#v retured error `%s`, expected error `%s`", test.input, err, test.err)
- }
- } else {
- if err != nil {
- t.Errorf("ConvertTo with input %#v retured error `%s`", test.input, err)
- }
- compareObjects(t, test.expected, actual)
- }
- }
- func TestConvertFrom(t *testing.T) {
- // Using the same inputs from TestConvertTo, test the reverse mapping.
- for _, test := range converterScalarInputs {
- if test.expected != nil {
- testConvertFrom(t, test)
- }
- }
- }
- func testConvertFrom(t *testing.T, test converterTestInput) {
- switch test.inputType {
- case "mySimpleStruct":
- var actual mySimpleStruct
- if err := ConvertFrom(test.expected.(*dynamodb.AttributeValue), &actual); err != nil {
- t.Errorf("ConvertFrom with input %#v retured error `%s`", test.expected, err)
- }
- compareObjects(t, test.input, actual)
- case "myComplexStruct":
- var actual myComplexStruct
- if err := ConvertFrom(test.expected.(*dynamodb.AttributeValue), &actual); err != nil {
- t.Errorf("ConvertFrom with input %#v retured error `%s`", test.expected, err)
- }
- compareObjects(t, test.input, actual)
- default:
- var actual interface{}
- if err := ConvertFrom(test.expected.(*dynamodb.AttributeValue), &actual); err != nil {
- t.Errorf("ConvertFrom with input %#v retured error `%s`", test.expected, err)
- }
- compareObjects(t, test.input, actual)
- }
- }
- func TestConvertFromError(t *testing.T) {
- // Test that we get an error using ConvertFrom to convert to a map.
- var actual map[string]interface{}
- expected := awserr.New("SerializationError", `v must be a non-nil pointer to an interface{} or struct, got *map[string]interface {}`, nil).Error()
- if err := ConvertFrom(nil, &actual); err == nil {
- t.Errorf("ConvertFrom with input %#v returned no error, expected error `%s`", nil, expected)
- } else if err.Error() != expected {
- t.Errorf("ConvertFrom with input %#v returned error `%s`, expected error `%s`", nil, err, expected)
- }
- // Test that we get an error using ConvertFrom to convert to a list.
- var actual2 []interface{}
- expected = awserr.New("SerializationError", `v must be a non-nil pointer to an interface{} or struct, got *[]interface {}`, nil).Error()
- if err := ConvertFrom(nil, &actual2); err == nil {
- t.Errorf("ConvertFrom with input %#v returned no error, expected error `%s`", nil, expected)
- } else if err.Error() != expected {
- t.Errorf("ConvertFrom with input %#v returned error `%s`, expected error `%s`", nil, err, expected)
- }
- }
- func TestConvertToMap(t *testing.T) {
- for _, test := range converterMapTestInputs {
- testConvertToMap(t, test)
- }
- }
- func testConvertToMap(t *testing.T, test converterTestInput) {
- actual, err := ConvertToMap(test.input)
- if test.err != nil {
- if err == nil {
- t.Errorf("ConvertToMap with input %#v retured %#v, expected error `%s`", test.input, actual, test.err)
- } else if err.Error() != test.err.Error() {
- t.Errorf("ConvertToMap with input %#v retured error `%s`, expected error `%s`", test.input, err, test.err)
- }
- } else {
- if err != nil {
- t.Errorf("ConvertToMap with input %#v retured error `%s`", test.input, err)
- }
- compareObjects(t, test.expected, actual)
- }
- }
- func TestConvertFromMap(t *testing.T) {
- // Using the same inputs from TestConvertToMap, test the reverse mapping.
- for _, test := range converterMapTestInputs {
- if test.expected != nil {
- testConvertFromMap(t, test)
- }
- }
- }
- func testConvertFromMap(t *testing.T, test converterTestInput) {
- switch test.inputType {
- case "mySimpleStruct":
- var actual mySimpleStruct
- if err := ConvertFromMap(test.expected.(map[string]*dynamodb.AttributeValue), &actual); err != nil {
- t.Errorf("ConvertFromMap with input %#v retured error `%s`", test.expected, err)
- }
- compareObjects(t, test.input, actual)
- case "myComplexStruct":
- var actual myComplexStruct
- if err := ConvertFromMap(test.expected.(map[string]*dynamodb.AttributeValue), &actual); err != nil {
- t.Errorf("ConvertFromMap with input %#v retured error `%s`", test.expected, err)
- }
- compareObjects(t, test.input, actual)
- default:
- var actual map[string]interface{}
- if err := ConvertFromMap(test.expected.(map[string]*dynamodb.AttributeValue), &actual); err != nil {
- t.Errorf("ConvertFromMap with input %#v retured error `%s`", test.expected, err)
- }
- compareObjects(t, test.input, actual)
- }
- }
- func TestConvertFromMapError(t *testing.T) {
- // Test that we get an error using ConvertFromMap to convert to an interface{}.
- var actual interface{}
- expected := awserr.New("SerializationError", `v must be a non-nil pointer to a map[string]interface{} or struct, got *interface {}`, nil).Error()
- if err := ConvertFromMap(nil, &actual); err == nil {
- t.Errorf("ConvertFromMap with input %#v returned no error, expected error `%s`", nil, expected)
- } else if err.Error() != expected {
- t.Errorf("ConvertFromMap with input %#v returned error `%s`, expected error `%s`", nil, err, expected)
- }
- // Test that we get an error using ConvertFromMap to convert to a slice.
- var actual2 []interface{}
- expected = awserr.New("SerializationError", `v must be a non-nil pointer to a map[string]interface{} or struct, got *[]interface {}`, nil).Error()
- if err := ConvertFromMap(nil, &actual2); err == nil {
- t.Errorf("ConvertFromMap with input %#v returned no error, expected error `%s`", nil, expected)
- } else if err.Error() != expected {
- t.Errorf("ConvertFromMap with input %#v returned error `%s`, expected error `%s`", nil, err, expected)
- }
- }
- func TestConvertToList(t *testing.T) {
- for _, test := range converterListTestInputs {
- testConvertToList(t, test)
- }
- }
- func testConvertToList(t *testing.T, test converterTestInput) {
- actual, err := ConvertToList(test.input)
- if test.err != nil {
- if err == nil {
- t.Errorf("ConvertToList with input %#v retured %#v, expected error `%s`", test.input, actual, test.err)
- } else if err.Error() != test.err.Error() {
- t.Errorf("ConvertToList with input %#v retured error `%s`, expected error `%s`", test.input, err, test.err)
- }
- } else {
- if err != nil {
- t.Errorf("ConvertToList with input %#v retured error `%s`", test.input, err)
- }
- compareObjects(t, test.expected, actual)
- }
- }
- func TestConvertFromList(t *testing.T) {
- // Using the same inputs from TestConvertToList, test the reverse mapping.
- for _, test := range converterListTestInputs {
- if test.expected != nil {
- testConvertFromList(t, test)
- }
- }
- }
- func testConvertFromList(t *testing.T, test converterTestInput) {
- switch test.inputType {
- case "mySimpleStruct":
- var actual []mySimpleStruct
- if err := ConvertFromList(test.expected.([]*dynamodb.AttributeValue), &actual); err != nil {
- t.Errorf("ConvertFromList with input %#v retured error `%s`", test.expected, err)
- }
- compareObjects(t, test.input, actual)
- case "myComplexStruct":
- var actual []myComplexStruct
- if err := ConvertFromList(test.expected.([]*dynamodb.AttributeValue), &actual); err != nil {
- t.Errorf("ConvertFromList with input %#v retured error `%s`", test.expected, err)
- }
- compareObjects(t, test.input, actual)
- default:
- var actual []interface{}
- if err := ConvertFromList(test.expected.([]*dynamodb.AttributeValue), &actual); err != nil {
- t.Errorf("ConvertFromList with input %#v retured error `%s`", test.expected, err)
- }
- compareObjects(t, test.input, actual)
- }
- }
- func TestConvertFromListError(t *testing.T) {
- // Test that we get an error using ConvertFromList to convert to a map.
- var actual map[string]interface{}
- expected := awserr.New("SerializationError", `v must be a non-nil pointer to an array or slice, got *map[string]interface {}`, nil).Error()
- if err := ConvertFromList(nil, &actual); err == nil {
- t.Errorf("ConvertFromList with input %#v returned no error, expected error `%s`", nil, expected)
- } else if err.Error() != expected {
- t.Errorf("ConvertFromList with input %#v returned error `%s`, expected error `%s`", nil, err, expected)
- }
- // Test that we get an error using ConvertFromList to convert to a struct.
- var actual2 myComplexStruct
- expected = awserr.New("SerializationError", `v must be a non-nil pointer to an array or slice, got *dynamodbattribute.myComplexStruct`, nil).Error()
- if err := ConvertFromList(nil, &actual2); err == nil {
- t.Errorf("ConvertFromList with input %#v returned no error, expected error `%s`", nil, expected)
- } else if err.Error() != expected {
- t.Errorf("ConvertFromList with input %#v returned error `%s`, expected error `%s`", nil, err, expected)
- }
- // Test that we get an error using ConvertFromList to convert to an interface{}.
- var actual3 interface{}
- expected = awserr.New("SerializationError", `v must be a non-nil pointer to an array or slice, got *interface {}`, nil).Error()
- if err := ConvertFromList(nil, &actual3); err == nil {
- t.Errorf("ConvertFromList with input %#v returned no error, expected error `%s`", nil, expected)
- } else if err.Error() != expected {
- t.Errorf("ConvertFromList with input %#v returned error `%s`, expected error `%s`", nil, err, expected)
- }
- }
- func BenchmarkConvertTo(b *testing.B) {
- d := mySimpleStruct{
- String: "abc",
- Int: 123,
- Uint: 123,
- Float32: 123.321,
- Float64: 123.321,
- Bool: true,
- Null: nil,
- }
- for i := 0; i < b.N; i++ {
- _, err := ConvertTo(d)
- if err != nil {
- b.Fatal("unexpected error", err)
- }
- }
- }
|