Skip to content

Commit 584b9ab

Browse files
authored
Fix XML unmarshaler not correctly unmarshaling list of timestamp values (#166)
Fixes a bug in the XML unmarshaler that would incorrectly try to unmarshal "time.Time" parameters that did not have the struct tag type on them. This would occur for nested lists like CloudWatch's GetMetricDataResponse MetricDataResults timestamp parameters. Adds protocol tests for XML unmarshaling with list of timestamps. Related to aws/aws-sdk-go#1894 Fix #1892
1 parent 996478f commit 584b9ab

File tree

3 files changed

+216
-24
lines changed

3 files changed

+216
-24
lines changed

models/protocol_tests/output/rest-xml.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@
4242
},
4343
"Timestamp": {
4444
"shape": "TimestampType"
45+
},
46+
"Blobs": {
47+
"shape": "Blobs"
48+
},
49+
"Timestamps": {
50+
"shape": "Timestamps"
51+
},
52+
"Float64s": {
53+
"shape": "Float64s"
4554
}
4655
}
4756
},
@@ -76,6 +85,21 @@
7685
},
7786
"TimestampType": {
7887
"type": "timestamp"
88+
},
89+
"BlobType": {
90+
"type": "blob"
91+
},
92+
"Blobs": {
93+
"type":"list",
94+
"member":{"shape":"BlobType"}
95+
},
96+
"Timestamps":{
97+
"type":"list",
98+
"member":{"shape":"TimestampType"}
99+
},
100+
"Float64s": {
101+
"type":"list",
102+
"member":{"shape":"FloatType"}
79103
}
80104
},
81105
"cases": [
@@ -136,6 +160,24 @@
136160
},
137161
"body": "<OperationNameResponse><Str></Str><FooNum>123</FooNum><FalseBool>false</FalseBool><TrueBool>true</TrueBool><Float>1.2</Float><Double>1.3</Double><Long>200</Long><Char>a</Char><Timestamp>2015-01-25T08:00:00Z</Timestamp></OperationNameResponse>"
138162
}
163+
},
164+
{
165+
"given": {
166+
"output": {
167+
"shape": "OutputShape"
168+
},
169+
"name": "OperationName"
170+
},
171+
"result": {
172+
"Float64s": [0.1, 0.2],
173+
"Blobs": ["value", "value2"],
174+
"Timestamps": [1422172800, 1422172801]
175+
},
176+
"response": {
177+
"status_code": 200,
178+
"headers": {},
179+
"body": "<OperationNameResponse><Float64s><member>0.1</member><member>0.2</member></Float64s><Blobs><member>dmFsdWU=</member><member>dmFsdWUy</member></Blobs><Timestamps><member>2015-01-25T08:00:00Z</member><member>2015-01-25T08:00:01Z</member></Timestamps></OperationNameResponse>"
180+
}
139181
}
140182
]
141183
},

private/protocol/restxml/unmarshal_test.go

Lines changed: 148 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ type OutputService1TestCaseOperation1Request struct {
100100
}
101101

102102
// Send marshals and sends the OutputService1TestCaseOperation1 API request.
103-
func (r OutputService1TestCaseOperation1Request) Send() (*OutputService1TestShapeOutputService1TestCaseOperation2Output, error) {
103+
func (r OutputService1TestCaseOperation1Request) Send() (*OutputService1TestShapeOutputService1TestCaseOperation3Output, error) {
104104
err := r.Request.Send()
105105
if err != nil {
106106
return nil, err
107107
}
108108

109-
return r.Request.Data.(*OutputService1TestShapeOutputService1TestCaseOperation2Output), nil
109+
return r.Request.Data.(*OutputService1TestShapeOutputService1TestCaseOperation3Output), nil
110110
}
111111

112112
// OutputService1TestCaseOperation1Request returns a request value for making API operation for
@@ -129,7 +129,7 @@ func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation1Request(inp
129129
input = &OutputService1TestShapeOutputService1TestCaseOperation1Input{}
130130
}
131131

132-
output := &OutputService1TestShapeOutputService1TestCaseOperation2Output{}
132+
output := &OutputService1TestShapeOutputService1TestCaseOperation3Output{}
133133
req := c.newRequest(op, input, output)
134134
output.responseMetadata = aws.Response{Request: req}
135135

@@ -146,13 +146,13 @@ type OutputService1TestCaseOperation2Request struct {
146146
}
147147

148148
// Send marshals and sends the OutputService1TestCaseOperation2 API request.
149-
func (r OutputService1TestCaseOperation2Request) Send() (*OutputService1TestShapeOutputService1TestCaseOperation2Output, error) {
149+
func (r OutputService1TestCaseOperation2Request) Send() (*OutputService1TestShapeOutputService1TestCaseOperation3Output, error) {
150150
err := r.Request.Send()
151151
if err != nil {
152152
return nil, err
153153
}
154154

155-
return r.Request.Data.(*OutputService1TestShapeOutputService1TestCaseOperation2Output), nil
155+
return r.Request.Data.(*OutputService1TestShapeOutputService1TestCaseOperation3Output), nil
156156
}
157157

158158
// OutputService1TestCaseOperation2Request returns a request value for making API operation for
@@ -175,13 +175,59 @@ func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation2Request(inp
175175
input = &OutputService1TestShapeOutputService1TestCaseOperation2Input{}
176176
}
177177

178-
output := &OutputService1TestShapeOutputService1TestCaseOperation2Output{}
178+
output := &OutputService1TestShapeOutputService1TestCaseOperation3Output{}
179179
req := c.newRequest(op, input, output)
180180
output.responseMetadata = aws.Response{Request: req}
181181

182182
return OutputService1TestCaseOperation2Request{Request: req, Input: input, Copy: c.OutputService1TestCaseOperation2Request}
183183
}
184184

185+
const opOutputService1TestCaseOperation3 = "OperationName"
186+
187+
// OutputService1TestCaseOperation3Request is a API request type for the OutputService1TestCaseOperation3 API operation.
188+
type OutputService1TestCaseOperation3Request struct {
189+
*aws.Request
190+
Input *OutputService1TestShapeOutputService1TestCaseOperation3Input
191+
Copy func(*OutputService1TestShapeOutputService1TestCaseOperation3Input) OutputService1TestCaseOperation3Request
192+
}
193+
194+
// Send marshals and sends the OutputService1TestCaseOperation3 API request.
195+
func (r OutputService1TestCaseOperation3Request) Send() (*OutputService1TestShapeOutputService1TestCaseOperation3Output, error) {
196+
err := r.Request.Send()
197+
if err != nil {
198+
return nil, err
199+
}
200+
201+
return r.Request.Data.(*OutputService1TestShapeOutputService1TestCaseOperation3Output), nil
202+
}
203+
204+
// OutputService1TestCaseOperation3Request returns a request value for making API operation for
205+
// .
206+
//
207+
// // Example sending a request using the OutputService1TestCaseOperation3Request method.
208+
// req := client.OutputService1TestCaseOperation3Request(params)
209+
// resp, err := req.Send()
210+
// if err == nil {
211+
// fmt.Println(resp)
212+
// }
213+
func (c *OutputService1ProtocolTest) OutputService1TestCaseOperation3Request(input *OutputService1TestShapeOutputService1TestCaseOperation3Input) OutputService1TestCaseOperation3Request {
214+
op := &aws.Operation{
215+
Name: opOutputService1TestCaseOperation3,
216+
217+
HTTPPath: "/",
218+
}
219+
220+
if input == nil {
221+
input = &OutputService1TestShapeOutputService1TestCaseOperation3Input{}
222+
}
223+
224+
output := &OutputService1TestShapeOutputService1TestCaseOperation3Output{}
225+
req := c.newRequest(op, input, output)
226+
output.responseMetadata = aws.Response{Request: req}
227+
228+
return OutputService1TestCaseOperation3Request{Request: req, Input: input, Copy: c.OutputService1TestCaseOperation3Request}
229+
}
230+
185231
type OutputService1TestShapeOutputService1TestCaseOperation1Input struct {
186232
_ struct{} `type:"structure"`
187233
}
@@ -202,11 +248,23 @@ func (s OutputService1TestShapeOutputService1TestCaseOperation2Input) MarshalFie
202248
return nil
203249
}
204250

205-
type OutputService1TestShapeOutputService1TestCaseOperation2Output struct {
251+
type OutputService1TestShapeOutputService1TestCaseOperation3Input struct {
252+
_ struct{} `type:"structure"`
253+
}
254+
255+
// MarshalFields encodes the AWS API shape using the passed in protocol encoder.
256+
func (s OutputService1TestShapeOutputService1TestCaseOperation3Input) MarshalFields(e protocol.FieldEncoder) error {
257+
258+
return nil
259+
}
260+
261+
type OutputService1TestShapeOutputService1TestCaseOperation3Output struct {
206262
_ struct{} `type:"structure"`
207263

208264
responseMetadata aws.Response
209265

266+
Blobs [][]byte `type:"list"`
267+
210268
Char *string `type:"character"`
211269

212270
Double *float64 `type:"double"`
@@ -215,6 +273,8 @@ type OutputService1TestShapeOutputService1TestCaseOperation2Output struct {
215273

216274
Float *float64 `type:"float"`
217275

276+
Float64s []float64 `type:"list"`
277+
218278
ImaHeader *string `location:"header" type:"string"`
219279

220280
ImaHeaderLocation *string `location:"header" locationName:"X-Foo" type:"string"`
@@ -227,16 +287,30 @@ type OutputService1TestShapeOutputService1TestCaseOperation2Output struct {
227287

228288
Timestamp *time.Time `type:"timestamp" timestampFormat:"iso8601"`
229289

290+
Timestamps []time.Time `type:"list"`
291+
230292
TrueBool *bool `type:"boolean"`
231293
}
232294

233295
// SDKResponseMetdata return sthe response metadata for the API.
234-
func (s OutputService1TestShapeOutputService1TestCaseOperation2Output) SDKResponseMetadata() aws.Response {
296+
func (s OutputService1TestShapeOutputService1TestCaseOperation3Output) SDKResponseMetadata() aws.Response {
235297
return s.responseMetadata
236298
}
237299

238300
// MarshalFields encodes the AWS API shape using the passed in protocol encoder.
239-
func (s OutputService1TestShapeOutputService1TestCaseOperation2Output) MarshalFields(e protocol.FieldEncoder) error {
301+
func (s OutputService1TestShapeOutputService1TestCaseOperation3Output) MarshalFields(e protocol.FieldEncoder) error {
302+
if len(s.Blobs) > 0 {
303+
v := s.Blobs
304+
305+
metadata := protocol.Metadata{}
306+
ls0 := e.List(protocol.BodyTarget, "Blobs", metadata)
307+
ls0.Start()
308+
for _, v1 := range v {
309+
ls0.ListAddValue(protocol.BytesValue(v1))
310+
}
311+
ls0.End()
312+
313+
}
240314
if s.Char != nil {
241315
v := *s.Char
242316

@@ -261,6 +335,18 @@ func (s OutputService1TestShapeOutputService1TestCaseOperation2Output) MarshalFi
261335
metadata := protocol.Metadata{}
262336
e.SetValue(protocol.BodyTarget, "Float", protocol.Float64Value(v), metadata)
263337
}
338+
if len(s.Float64s) > 0 {
339+
v := s.Float64s
340+
341+
metadata := protocol.Metadata{}
342+
ls0 := e.List(protocol.BodyTarget, "Float64s", metadata)
343+
ls0.Start()
344+
for _, v1 := range v {
345+
ls0.ListAddValue(protocol.Float64Value(v1))
346+
}
347+
ls0.End()
348+
349+
}
264350
if s.Long != nil {
265351
v := *s.Long
266352

@@ -285,6 +371,18 @@ func (s OutputService1TestShapeOutputService1TestCaseOperation2Output) MarshalFi
285371
metadata := protocol.Metadata{}
286372
e.SetValue(protocol.BodyTarget, "Timestamp", protocol.TimeValue{V: v, Format: protocol.ISO8601TimeFormat}, metadata)
287373
}
374+
if len(s.Timestamps) > 0 {
375+
v := s.Timestamps
376+
377+
metadata := protocol.Metadata{}
378+
ls0 := e.List(protocol.BodyTarget, "Timestamps", metadata)
379+
ls0.Start()
380+
for _, v1 := range v {
381+
ls0.ListAddValue(protocol.TimeValue{V: v1})
382+
}
383+
ls0.End()
384+
385+
}
288386
if s.TrueBool != nil {
289387
v := *s.TrueBool
290388

@@ -2325,7 +2423,7 @@ func TestOutputService1ProtocolTestScalarMembersCase1(t *testing.T) {
23252423
t.Errorf("expect not error, got %v", req.Error)
23262424
}
23272425

2328-
out := req.Data.(*OutputService1TestShapeOutputService1TestCaseOperation2Output)
2426+
out := req.Data.(*OutputService1TestShapeOutputService1TestCaseOperation3Output)
23292427
// assert response
23302428
if out == nil {
23312429
t.Errorf("expect not to be nil")
@@ -2387,7 +2485,7 @@ func TestOutputService1ProtocolTestScalarMembersCase2(t *testing.T) {
23872485
t.Errorf("expect not error, got %v", req.Error)
23882486
}
23892487

2390-
out := req.Data.(*OutputService1TestShapeOutputService1TestCaseOperation2Output)
2488+
out := req.Data.(*OutputService1TestShapeOutputService1TestCaseOperation3Output)
23912489
// assert response
23922490
if out == nil {
23932491
t.Errorf("expect not to be nil")
@@ -2428,6 +2526,45 @@ func TestOutputService1ProtocolTestScalarMembersCase2(t *testing.T) {
24282526

24292527
}
24302528

2529+
func TestOutputService1ProtocolTestScalarMembersCase3(t *testing.T) {
2530+
cfg := unit.Config()
2531+
cfg.EndpointResolver = aws.ResolveWithEndpointURL("https://test")
2532+
2533+
svc := NewOutputService1ProtocolTest(cfg)
2534+
2535+
buf := bytes.NewReader([]byte("<OperationNameResponse><Float64s><member>0.1</member><member>0.2</member></Float64s><Blobs><member>dmFsdWU=</member><member>dmFsdWUy</member></Blobs><Timestamps><member>2015-01-25T08:00:00Z</member><member>2015-01-25T08:00:01Z</member></Timestamps></OperationNameResponse>"))
2536+
req := svc.OutputService1TestCaseOperation3Request(nil)
2537+
req.HTTPResponse = &http.Response{StatusCode: 200, Body: ioutil.NopCloser(buf), Header: http.Header{}}
2538+
2539+
// set headers
2540+
2541+
// unmarshal response
2542+
restxml.UnmarshalMeta(req.Request)
2543+
restxml.Unmarshal(req.Request)
2544+
if req.Error != nil {
2545+
t.Errorf("expect not error, got %v", req.Error)
2546+
}
2547+
2548+
out := req.Data.(*OutputService1TestShapeOutputService1TestCaseOperation3Output)
2549+
// assert response
2550+
if out == nil {
2551+
t.Errorf("expect not to be nil")
2552+
}
2553+
if e, a := "value", string(out.Blobs[0]); e != a {
2554+
t.Errorf("expect %v, got %v", e, a)
2555+
}
2556+
if e, a := "value2", string(out.Blobs[1]); e != a {
2557+
t.Errorf("expect %v, got %v", e, a)
2558+
}
2559+
if e, a := time.Unix(1.4221728e+09, 0).UTC().String(), out.Timestamps[0].String(); e != a {
2560+
t.Errorf("expect %v, got %v", e, a)
2561+
}
2562+
if e, a := time.Unix(1.422172801e+09, 0).UTC().String(), out.Timestamps[1].String(); e != a {
2563+
t.Errorf("expect %v, got %v", e, a)
2564+
}
2565+
2566+
}
2567+
24312568
func TestOutputService2ProtocolTestBlobCase1(t *testing.T) {
24322569
cfg := unit.Config()
24332570
cfg.EndpointResolver = aws.ResolveWithEndpointURL("https://test")

0 commit comments

Comments
 (0)