encode_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. package dynamodbattribute
  2. import (
  3. "fmt"
  4. "reflect"
  5. "testing"
  6. "time"
  7. "github.com/aws/aws-sdk-go/aws"
  8. "github.com/aws/aws-sdk-go/aws/awserr"
  9. "github.com/aws/aws-sdk-go/service/dynamodb"
  10. )
  11. func TestMarshalErrorTypes(t *testing.T) {
  12. var _ awserr.Error = (*InvalidMarshalError)(nil)
  13. var _ awserr.Error = (*unsupportedMarshalTypeError)(nil)
  14. }
  15. func TestMarshalShared(t *testing.T) {
  16. for i, c := range sharedTestCases {
  17. av, err := Marshal(c.expected)
  18. assertConvertTest(t, i, av, c.in, err, c.err)
  19. }
  20. }
  21. func TestMarshalListShared(t *testing.T) {
  22. for i, c := range sharedListTestCases {
  23. av, err := MarshalList(c.expected)
  24. assertConvertTest(t, i, av, c.in, err, c.err)
  25. }
  26. }
  27. func TestMarshalMapShared(t *testing.T) {
  28. for i, c := range sharedMapTestCases {
  29. av, err := MarshalMap(c.expected)
  30. assertConvertTest(t, i, av, c.in, err, c.err)
  31. }
  32. }
  33. type marshalMarshaler struct {
  34. Value string
  35. Value2 int
  36. Value3 bool
  37. Value4 time.Time
  38. }
  39. func (m *marshalMarshaler) MarshalDynamoDBAttributeValue(av *dynamodb.AttributeValue) error {
  40. av.M = map[string]*dynamodb.AttributeValue{
  41. "abc": {S: &m.Value},
  42. "def": {N: aws.String(fmt.Sprintf("%d", m.Value2))},
  43. "ghi": {BOOL: &m.Value3},
  44. "jkl": {S: aws.String(m.Value4.Format(time.RFC3339Nano))},
  45. }
  46. return nil
  47. }
  48. func TestMarshalMashaler(t *testing.T) {
  49. m := &marshalMarshaler{
  50. Value: "value",
  51. Value2: 123,
  52. Value3: true,
  53. Value4: testDate,
  54. }
  55. expect := &dynamodb.AttributeValue{
  56. M: map[string]*dynamodb.AttributeValue{
  57. "abc": {S: aws.String("value")},
  58. "def": {N: aws.String("123")},
  59. "ghi": {BOOL: aws.Bool(true)},
  60. "jkl": {S: aws.String("2016-05-03T17:06:26.209072Z")},
  61. },
  62. }
  63. actual, err := Marshal(m)
  64. if err != nil {
  65. t.Errorf("expect nil, got %v", err)
  66. }
  67. if e, a := expect, actual; !reflect.DeepEqual(e, a) {
  68. t.Errorf("expect %v, got %v", e, a)
  69. }
  70. }
  71. type testOmitEmptyElemListStruct struct {
  72. Values []string `dynamodbav:",omitemptyelem"`
  73. }
  74. type testOmitEmptyElemMapStruct struct {
  75. Values map[string]interface{} `dynamodbav:",omitemptyelem"`
  76. }
  77. func TestMarshalListOmitEmptyElem(t *testing.T) {
  78. expect := &dynamodb.AttributeValue{
  79. M: map[string]*dynamodb.AttributeValue{
  80. "Values": {L: []*dynamodb.AttributeValue{
  81. {S: aws.String("abc")},
  82. {S: aws.String("123")},
  83. }},
  84. },
  85. }
  86. m := testOmitEmptyElemListStruct{Values: []string{"abc", "", "123"}}
  87. actual, err := Marshal(m)
  88. if err != nil {
  89. t.Errorf("expect nil, got %v", err)
  90. }
  91. if e, a := expect, actual; !reflect.DeepEqual(e, a) {
  92. t.Errorf("expect %v, got %v", e, a)
  93. }
  94. }
  95. func TestMarshalMapOmitEmptyElem(t *testing.T) {
  96. expect := &dynamodb.AttributeValue{
  97. M: map[string]*dynamodb.AttributeValue{
  98. "Values": {M: map[string]*dynamodb.AttributeValue{
  99. "abc": {N: aws.String("123")},
  100. "klm": {S: aws.String("abc")},
  101. }},
  102. },
  103. }
  104. m := testOmitEmptyElemMapStruct{Values: map[string]interface{}{
  105. "abc": 123.,
  106. "efg": nil,
  107. "hij": "",
  108. "klm": "abc",
  109. }}
  110. actual, err := Marshal(m)
  111. if err != nil {
  112. t.Errorf("expect nil, got %v", err)
  113. }
  114. if e, a := expect, actual; !reflect.DeepEqual(e, a) {
  115. t.Errorf("expect %v, got %v", e, a)
  116. }
  117. }
  118. type testOmitEmptyScalar struct {
  119. IntZero int `dynamodbav:",omitempty"`
  120. IntPtrNil *int `dynamodbav:",omitempty"`
  121. IntPtrSetZero *int `dynamodbav:",omitempty"`
  122. }
  123. func TestMarshalOmitEmpty(t *testing.T) {
  124. expect := &dynamodb.AttributeValue{
  125. M: map[string]*dynamodb.AttributeValue{
  126. "IntPtrSetZero": {N: aws.String("0")},
  127. },
  128. }
  129. m := testOmitEmptyScalar{IntPtrSetZero: aws.Int(0)}
  130. actual, err := Marshal(m)
  131. if err != nil {
  132. t.Errorf("expect nil, got %v", err)
  133. }
  134. if e, a := expect, actual; !reflect.DeepEqual(e, a) {
  135. t.Errorf("expect %v, got %v", e, a)
  136. }
  137. }
  138. func TestEncodeEmbeddedPointerStruct(t *testing.T) {
  139. type B struct {
  140. Bint int
  141. }
  142. type C struct {
  143. Cint int
  144. }
  145. type A struct {
  146. Aint int
  147. *B
  148. *C
  149. }
  150. a := A{Aint: 321, B: &B{123}}
  151. if e, a := 321, a.Aint; e != a {
  152. t.Errorf("expect %v, got %v", e, a)
  153. }
  154. if e, a := 123, a.Bint; e != a {
  155. t.Errorf("expect %v, got %v", e, a)
  156. }
  157. if a.C != nil {
  158. t.Errorf("expect nil, got %v", a.C)
  159. }
  160. actual, err := Marshal(a)
  161. if err != nil {
  162. t.Errorf("expect nil, got %v", err)
  163. }
  164. expect := &dynamodb.AttributeValue{
  165. M: map[string]*dynamodb.AttributeValue{
  166. "Aint": {
  167. N: aws.String("321"),
  168. },
  169. "Bint": {
  170. N: aws.String("123"),
  171. },
  172. },
  173. }
  174. if e, a := expect, actual; !reflect.DeepEqual(e, a) {
  175. t.Errorf("expect %v, got %v", e, a)
  176. }
  177. }
  178. func TestEncodeUnixTime(t *testing.T) {
  179. type A struct {
  180. Normal time.Time
  181. Tagged time.Time `dynamodbav:",unixtime"`
  182. Typed UnixTime
  183. }
  184. a := A{
  185. Normal: time.Unix(123, 0).UTC(),
  186. Tagged: time.Unix(456, 0),
  187. Typed: UnixTime(time.Unix(789, 0)),
  188. }
  189. actual, err := Marshal(a)
  190. if err != nil {
  191. t.Errorf("expect nil, got %v", err)
  192. }
  193. expect := &dynamodb.AttributeValue{
  194. M: map[string]*dynamodb.AttributeValue{
  195. "Normal": {
  196. S: aws.String("1970-01-01T00:02:03Z"),
  197. },
  198. "Tagged": {
  199. N: aws.String("456"),
  200. },
  201. "Typed": {
  202. N: aws.String("789"),
  203. },
  204. },
  205. }
  206. if e, a := expect, actual; !reflect.DeepEqual(e, a) {
  207. t.Errorf("expect %v, got %v", e, a)
  208. }
  209. }
  210. type AliasedTime time.Time
  211. func TestEncodeAliasedUnixTime(t *testing.T) {
  212. type A struct {
  213. Normal AliasedTime
  214. Tagged AliasedTime `dynamodbav:",unixtime"`
  215. }
  216. a := A{
  217. Normal: AliasedTime(time.Unix(123, 0).UTC()),
  218. Tagged: AliasedTime(time.Unix(456, 0)),
  219. }
  220. actual, err := Marshal(a)
  221. if err != nil {
  222. t.Errorf("expect no err, got %v", err)
  223. }
  224. expect := &dynamodb.AttributeValue{
  225. M: map[string]*dynamodb.AttributeValue{
  226. "Normal": {
  227. S: aws.String("1970-01-01T00:02:03Z"),
  228. },
  229. "Tagged": {
  230. N: aws.String("456"),
  231. },
  232. },
  233. }
  234. if e, a := expect, actual; !reflect.DeepEqual(e, a) {
  235. t.Errorf("expect %v, got %v", e, a)
  236. }
  237. }