Merge lp:~prudhvikrishna/goamz/sqs into lp:~gophers/goamz/trunk
- sqs
- Merge into trunk
Proposed by
Prudhvi Surapaneni
Status: | Needs review |
---|---|
Proposed branch: | lp:~prudhvikrishna/goamz/sqs |
Merge into: | lp:~gophers/goamz/trunk |
Diff against target: |
1304 lines (+1280/-0) 5 files modified
response_test.go (+238/-0) sign.go (+35/-0) sqs.go (+581/-0) sqs_test.go (+306/-0) suite_test.go (+120/-0) |
To merge this branch: | bzr merge lp:~prudhvikrishna/goamz/sqs |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
The Go Language Gophers | Pending | ||
Review via email: mp+107309@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Unmerged revisions
- 3. By Prudhvi Surapaneni
-
Fix Attribute Names
- 2. By Prudhvi Surapaneni
-
Use different Path's basing on access
- 1. By Prudhvi Surapaneni
-
Import SQS
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'response_test.go' |
2 | --- response_test.go 1970-01-01 00:00:00 +0000 |
3 | +++ response_test.go 2012-05-25 00:21:19 +0000 |
4 | @@ -0,0 +1,238 @@ |
5 | +package sqs_test |
6 | + |
7 | +var TestCreateQueueXmlOK = ` |
8 | +<CreateQueueResponse> |
9 | + <CreateQueueResult> |
10 | + <QueueUrl>http://sqs.us-east-1.amazonaws.com/123456789012/testQueue</QueueUrl> |
11 | + </CreateQueueResult> |
12 | + <ResponseMetadata> |
13 | + <RequestId>7a62c49f-347e-4fc4-9331-6e8e7a96aa73</RequestId> |
14 | + </ResponseMetadata> |
15 | +</CreateQueueResponse> |
16 | +` |
17 | + |
18 | +var TestListQueuesXmlOK = ` |
19 | +<ListQueuesResponse> |
20 | + <ListQueuesResult> |
21 | + <QueueUrl>http://sqs.us-east-1.amazonaws.com/123456789012/testQueue</QueueUrl> |
22 | + </ListQueuesResult> |
23 | + <ResponseMetadata> |
24 | + <RequestId>725275ae-0b9b-4762-b238-436d7c65a1ac</RequestId> |
25 | + </ResponseMetadata> |
26 | +</ListQueuesResponse> |
27 | +` |
28 | + |
29 | +var TestGetQueueUrlXmlOK = ` |
30 | +<GetQueueUrlResponse> |
31 | + <GetQueueUrlResult> |
32 | + <QueueUrl>http://sqs.us-east-1.amazonaws.com/123456789012/testQueue</QueueUrl> |
33 | + </GetQueueUrlResult> |
34 | + <ResponseMetadata> |
35 | + <RequestId>470a6f13-2ed9-4181-ad8a-2fdea142988e</RequestId> |
36 | + </ResponseMetadata> |
37 | +</GetQueueUrlResponse> |
38 | +` |
39 | + |
40 | +var TestChangeMessageVisibilityXmlOK = ` |
41 | +<ChangeMessageVisibilityResponse> |
42 | + <ResponseMetadata> |
43 | + <RequestId>6a7a282a-d013-4a59-aba9-335b0fa48bed</RequestId> |
44 | + </ResponseMetadata> |
45 | +</ChangeMessageVisibilityResponse> |
46 | +` |
47 | + |
48 | +var TestChangeMessaveVisibilityBatchXmlOK = ` |
49 | +<ChangeMessageVisibilityBatchResponse> |
50 | + <ChangeMessageVisibilityBatchResult> |
51 | + <ChangeMessageVisibilityBatchResultEntry> |
52 | + <Id>change_visibility_msg_2</Id> |
53 | + </ChangeMessageVisibilityBatchResultEntry> |
54 | + <ChangeMessageVisibilityBatchResultEntry> |
55 | + <Id>change_visibility_msg_3</Id> |
56 | + </ChangeMessageVisibilityBatchResultEntry> |
57 | + </ChangeMessageVisibilityBatchResult> |
58 | + <ResponseMetadata> |
59 | + <RequestId>ca9668f7-ab1b-4f7a-8859-f15747ab17a7</RequestId> |
60 | + </ResponseMetadata> |
61 | +</ChangeMessageVisibilityBatchResponse> |
62 | +` |
63 | + |
64 | +var TestReceiveMessageXmlOK = ` |
65 | +<ReceiveMessageResponse> |
66 | + <ReceiveMessageResult> |
67 | + <Message> |
68 | + <MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId> |
69 | + <ReceiptHandle>MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+CwLj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QEauMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=</ReceiptHandle> |
70 | + <MD5OfBody>fafb00f5732ab283681e124bf8747ed1</MD5OfBody> |
71 | + <Body>This is a test message</Body> |
72 | + <Attribute> |
73 | + <Name>SenderId</Name> |
74 | + <Value>195004372649</Value> |
75 | + </Attribute> |
76 | + <Attribute> |
77 | + <Name>SentTimestamp</Name> |
78 | + <Value>1238099229000</Value> |
79 | + </Attribute> |
80 | + <Attribute> |
81 | + <Name>ApproximateReceiveCount</Name> |
82 | + <Value>5</Value> |
83 | + </Attribute> |
84 | + <Attribute> |
85 | + <Name>ApproximateFirstReceiveTimestamp</Name> |
86 | + <Value>1250700979248</Value> |
87 | + </Attribute> |
88 | + </Message> |
89 | + </ReceiveMessageResult> |
90 | +<ResponseMetadata> |
91 | + <RequestId>b6633655-283d-45b4-aee4-4e84e0ae6afa</RequestId> |
92 | +</ResponseMetadata> |
93 | +</ReceiveMessageResponse> |
94 | +` |
95 | + |
96 | +var TestDeleteMessageXmlOK = ` |
97 | +<DeleteQueueResponse> |
98 | + <ResponseMetadata> |
99 | + <RequestId>b5293cb5-d306-4a17-9048-b263635abe42</RequestId> |
100 | + </ResponseMetadata> |
101 | +</DeleteQueueResponse> |
102 | +` |
103 | + |
104 | +var TestSendMessageXmlOK = ` |
105 | +<SendMessageResponse> |
106 | + <SendMessageResult> |
107 | + <MD5OfMessageBody>fafb00f5732ab283681e124bf8747ed1</MD5OfMessageBody> |
108 | + <MessageId>5fea7756-0ea4-451a-a703-a558b933e274</MessageId> |
109 | + </SendMessageResult> |
110 | + <ResponseMetadata> |
111 | + <RequestId>27daac76-34dd-47df-bd01-1f6e873584a0</RequestId> |
112 | + </ResponseMetadata> |
113 | +</SendMessageResponse> |
114 | +` |
115 | + |
116 | +var TestSendMessageBatchXmlOK = ` |
117 | +<SendMessageBatchResponse> |
118 | +<SendMessageBatchResult> |
119 | + <SendMessageBatchResultEntry> |
120 | + <Id>test_msg_001</Id> |
121 | + <MessageId>0a5231c7-8bff-4955-be2e-8dc7c50a25fa</MessageId> |
122 | + <MD5OfMessageBody>0e024d309850c78cba5eabbeff7cae71</MD5OfMessageBody> |
123 | + </SendMessageBatchResultEntry> |
124 | + <SendMessageBatchResultEntry> |
125 | + <Id>test_msg_002</Id> |
126 | + <MessageId>15ee1ed3-87e7-40c1-bdaa-2e49968ea7e9</MessageId> |
127 | + <MD5OfMessageBody>7fb8146a82f95e0af155278f406862c2</MD5OfMessageBody> |
128 | + </SendMessageBatchResultEntry> |
129 | +</SendMessageBatchResult> |
130 | +<ResponseMetadata> |
131 | + <RequestId>ca1ad5d0-8271-408b-8d0f-1351bf547e74</RequestId> |
132 | +</ResponseMetadata> |
133 | +</SendMessageBatchResponse> |
134 | +` |
135 | + |
136 | +var TestGetQueueAttributesAllXmlOK = ` |
137 | +<GetQueueAttributesResponse> |
138 | + <GetQueueAttributesResult> |
139 | + <Attribute> |
140 | + <Name>VisibilityTimeout</Name> |
141 | + <Value>30</Value> |
142 | + </Attribute> |
143 | + <Attribute> |
144 | + <Name>ApproximateNumberOfMessages</Name> |
145 | + <Value>0</Value> |
146 | + </Attribute> |
147 | + <Attribute> |
148 | + <Name>ApproximateNumberOfMessagesNotVisible</Name> |
149 | + <Value>0</Value> |
150 | + </Attribute> |
151 | + <Attribute> |
152 | + <Name>CreatedTimestamp</Name> |
153 | + <Value>1286771522</Value> |
154 | + </Attribute> |
155 | + <Attribute> |
156 | + <Name>LastModifiedTimestamp</Name> |
157 | + <Value>1286771522</Value> |
158 | + </Attribute> |
159 | + <Attribute> |
160 | + <Name>QueueArn</Name> |
161 | + <Value>arn:aws:sqs:us-east-1:123456789012:qfoo</Value> |
162 | + </Attribute> |
163 | + <Attribute> |
164 | + <Name>MaximumMessageSize</Name> |
165 | + <Value>8192</Value> |
166 | + </Attribute> |
167 | + <Attribute> |
168 | + <Name>MessageRetentionPeriod</Name> |
169 | + <Value>345600</Value> |
170 | + </Attribute> |
171 | + </GetQueueAttributesResult> |
172 | + <ResponseMetadata> |
173 | + <RequestId>1ea71be5-b5a2-4f9d-b85a-945d8d08cd0b</RequestId> |
174 | + </ResponseMetadata> |
175 | +</GetQueueAttributesResponse> |
176 | +` |
177 | + |
178 | +var TestGetQueueAttributesSelectiveXmlOK = ` |
179 | +<GetQueueAttributesResponse> |
180 | + <GetQueueAttributesResult> |
181 | + <Attribute> |
182 | + <Name>VisibilityTimeout</Name> |
183 | + <Value>30</Value> |
184 | + </Attribute> |
185 | + <Attribute> |
186 | + <Name>DelaySeconds</Name> |
187 | + <Value>0</Value> |
188 | + </Attribute> |
189 | + </GetQueueAttributesResult> |
190 | + <ResponseMetadata> |
191 | + <RequestId>1ea71be5-b5a2-4f9d-b85a-945d8d08cd0b</RequestId> |
192 | + </ResponseMetadata> |
193 | +</GetQueueAttributesResponse> |
194 | +` |
195 | + |
196 | +var TestDeleteMessageBatchXmlOK = ` |
197 | +<DeleteMessageBatchResponse> |
198 | + <DeleteMessageBatchResult> |
199 | + <DeleteMessageBatchResultEntry> |
200 | + <Id>msg1</Id> |
201 | + </DeleteMessageBatchResultEntry> |
202 | + <DeleteMessageBatchResultEntry> |
203 | + <Id>msg2</Id> |
204 | + </DeleteMessageBatchResultEntry> |
205 | + </DeleteMessageBatchResult> |
206 | + <ResponseMetadata> |
207 | + <RequestId>d6f86b7a-74d1-4439-b43f-196a1e29cd85</RequestId> |
208 | + </ResponseMetadata> |
209 | +</DeleteMessageBatchResponse> |
210 | +` |
211 | + |
212 | +var TestAddPermissionXmlOK = ` |
213 | +<AddPermissionResponse> |
214 | + <ResponseMetadata> |
215 | + <RequestId>9a285199-c8d6-47c2-bdb2-314cb47d599d</RequestId> |
216 | + </ResponseMetadata> |
217 | +</AddPermissionResponse> |
218 | +` |
219 | + |
220 | +var TestRemovePermissionXmlOK = ` |
221 | +<RemovePermissionResponse> |
222 | + <ResponseMetadata> |
223 | + <RequestId>f8bdb362-6616-42c0-977a-ce9a8bcce3bb</RequestId> |
224 | + </ResponseMetadata> |
225 | +</RemovePermissionResponse> |
226 | +` |
227 | + |
228 | +var TestDeleteQueueXmlOK = ` |
229 | +<DeleteQueueResponse> |
230 | + <ResponseMetadata> |
231 | + <RequestId>6fde8d1e-52cd-4581-8cd9-c512f4c64223</RequestId> |
232 | + </ResponseMetadata> |
233 | +</DeleteQueueResponse> |
234 | +` |
235 | + |
236 | +var TestSetQueueAttributesXmlOK = ` |
237 | +<SetQueueAttributesResponse> |
238 | + <ResponseMetadata> |
239 | + <RequestId>e5cca473-4fc0-4198-a451-8abb94d02c75</RequestId> |
240 | + </ResponseMetadata> |
241 | +</SetQueueAttributesResponse> |
242 | +` |
243 | |
244 | === added file 'sign.go' |
245 | --- sign.go 1970-01-01 00:00:00 +0000 |
246 | +++ sign.go 2012-05-25 00:21:19 +0000 |
247 | @@ -0,0 +1,35 @@ |
248 | +package sqs |
249 | + |
250 | +import ( |
251 | + "crypto/hmac" |
252 | + "crypto/sha256" |
253 | + "encoding/base64" |
254 | + "launchpad.net/goamz/aws" |
255 | + "sort" |
256 | + "strings" |
257 | +) |
258 | + |
259 | +// ---------------------------------------------------------------------------- |
260 | +// EC2 signing (http://goo.gl/fQmAN) |
261 | + |
262 | +var b64 = base64.StdEncoding |
263 | + |
264 | +func sign(auth aws.Auth, method, path string, params map[string]string, host string) { |
265 | + params["AWSAccessKeyId"] = auth.AccessKey |
266 | + params["SignatureVersion"] = "2" |
267 | + params["SignatureMethod"] = "HmacSHA256" |
268 | + |
269 | + var sarray []string |
270 | + for k, v := range params { |
271 | + sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(v)) |
272 | + } |
273 | + sort.StringSlice(sarray).Sort() |
274 | + joined := strings.Join(sarray, "&") |
275 | + payload := method + "\n" + host + "\n" + path + "\n" + joined |
276 | + hash := hmac.New(sha256.New, []byte(auth.SecretKey)) |
277 | + hash.Write([]byte(payload)) |
278 | + signature := make([]byte, b64.EncodedLen(hash.Size())) |
279 | + b64.Encode(signature, hash.Sum(nil)) |
280 | + |
281 | + params["Signature"] = string(signature) |
282 | +} |
283 | |
284 | === added file 'sqs.go' |
285 | --- sqs.go 1970-01-01 00:00:00 +0000 |
286 | +++ sqs.go 2012-05-25 00:21:19 +0000 |
287 | @@ -0,0 +1,581 @@ |
288 | +// |
289 | +// goamz - Go packages to interact with the Amazon Web Services. |
290 | +// |
291 | +// https://wiki.ubuntu.com/goamz |
292 | +// |
293 | +// Copyright (c) 2012 Memeo Inc. |
294 | +// |
295 | +// Written by Prudhvi Krishna Surapaneni <me@prudhvi.net> |
296 | +// |
297 | +package sqs |
298 | + |
299 | +import ( |
300 | + "encoding/xml" |
301 | + "fmt" |
302 | + "launchpad.net/goamz/aws" |
303 | + "log" |
304 | + "net/http" |
305 | + "net/http/httputil" |
306 | + "net/url" |
307 | + "strconv" |
308 | + "time" |
309 | +) |
310 | + |
311 | +// The SQS type encapsulates operations with specific SQS region |
312 | +type SQS struct { |
313 | + aws.Auth |
314 | + aws.Region |
315 | + private byte // Reserve the right of using private data. |
316 | +} |
317 | + |
318 | +const debug = false |
319 | + |
320 | +// New creates a new SQS handle |
321 | +func New(auth aws.Auth, region aws.Region) *SQS { |
322 | + return &SQS{auth, region, 0} |
323 | +} |
324 | + |
325 | +// Queue type encapsulates operations on a SQS Queue |
326 | +type Queue struct { |
327 | + *SQS |
328 | + Url string |
329 | +} |
330 | + |
331 | +// Response to a CreateQueue request. |
332 | +// |
333 | +// See http://goo.gl/sVUjF for more details |
334 | +type CreateQueueResponse struct { |
335 | + QueueUrl string `xml:"CreateQueueResult>QueueUrl"` |
336 | + ResponseMetadata |
337 | +} |
338 | + |
339 | +// Response to a ListQueues request. |
340 | +// |
341 | +// See http://goo.gl/RPRWr for more details |
342 | +type ListQueuesResponse struct { |
343 | + QueueUrl []string `xml:"ListQueuesResult>QueueUrl"` |
344 | + ResponseMetadata |
345 | +} |
346 | + |
347 | +// Response to a GetQueueUrl request. |
348 | +// |
349 | +// See http://goo.gl/hk7Iu for more details |
350 | +type GetQueueUrlResponse struct { |
351 | + QueueUrl string `xml:"GetQueueUrlResult>QueueUrl"` |
352 | + ResponseMetadata |
353 | +} |
354 | + |
355 | +// Response to a ChangeMessageVisibility request. |
356 | +// |
357 | +// See http://goo.gl/EyJKF for more details |
358 | +type ChangeMessageVisibilityResponse struct { |
359 | + ResponseMetadata |
360 | +} |
361 | + |
362 | +// See http://goo.gl/XTo0s for more details |
363 | +type ResponseMetadata struct { |
364 | + RequestId string `xml:"ResponseMetadata>RequestId"` |
365 | +} |
366 | + |
367 | +// Error represents an error in an operation with SQS |
368 | +type Error struct { |
369 | + StatusCode int // HTTP Status Code (200, 403, ... ) |
370 | + Code string // SQS Error Code |
371 | + Message string // The human-oriented error message |
372 | + RequestId string `xml:"RequestID"` |
373 | +} |
374 | + |
375 | +func (err *Error) Error() string { |
376 | + if err.Code != "" { |
377 | + return err.Message |
378 | + } |
379 | + |
380 | + return fmt.Sprintf("%s (%s)", err.Message, err.Code) |
381 | +} |
382 | + |
383 | +// For now a single error inst is being exposed. In the future it may be useful |
384 | +// to provide access to all of them, but rather than doing it as an array/slice, |
385 | +// use a *next pointer, so that it's backward compatible and it continues to be |
386 | +// easy to handle the first error, which is what most people will want. |
387 | +type xmlErrors struct { |
388 | + RequestId string |
389 | + Errors []Error `xml:"Errors>Error"` |
390 | +} |
391 | + |
392 | +// Attribute represents an instance of a SQS Queue Attribute. |
393 | +type Attribute struct { |
394 | + Name string |
395 | + Value string |
396 | +} |
397 | + |
398 | +// See http://goo.gl/pgffn for more details. |
399 | +type ChangeMessageVisibilityBatchEntry struct { |
400 | + Id string |
401 | + ReceiptHandle string |
402 | + VisibilityTimeout int |
403 | +} |
404 | + |
405 | +// ReceiveMessageResponse holds the results of ReceiveMessage |
406 | +type ReceiveMessageResponse struct { |
407 | + Messages []Message `xml:"ReceiveMessageResult>Message"` |
408 | + ResponseMetadata |
409 | +} |
410 | + |
411 | +type DeleteMessageResponse struct { |
412 | + ResponseMetadata |
413 | +} |
414 | + |
415 | +type SendMessageResponse struct { |
416 | + SendMessageResult |
417 | + ResponseMetadata |
418 | +} |
419 | + |
420 | +type SendMessageBatchResponse struct { |
421 | + SendMessageBatchResult |
422 | + ResponseMetadata |
423 | +} |
424 | + |
425 | +// SendMessageBatchResult holds the results of SendMessageBatch |
426 | +type SendMessageBatchResult struct { |
427 | + Entries []SendMessageBatchResultEntry `xml:"SendMessageBatchResult>SendMessageBatchResultEntry"` |
428 | +} |
429 | + |
430 | +type SendMessageBatchResultEntry struct { |
431 | + MD5OfMessageBody string `xml:"MD5OfMessageBody"` |
432 | + MessageId string `xml:"MessageId"` |
433 | + Id string `xml:"Id"` |
434 | +} |
435 | + |
436 | +type SendMessageBatchRequestEntry struct { |
437 | + Id string |
438 | + MessageBody string |
439 | + DelaySeconds int |
440 | +} |
441 | + |
442 | +type SendMessageResult struct { |
443 | + MD5OfMessageBody string `xml:"SendMessageResult>MD5OfMessageBody"` |
444 | + MessageId string `xml:"SendMessageResult>MessageId"` |
445 | +} |
446 | + |
447 | +// Represents an instance of a SQS Message |
448 | +type Message struct { |
449 | + MessageId string `xml:"MessageId"` |
450 | + Body string `xml:"Body"` |
451 | + MD5OfBody string `xml:"MD5OfBody"` |
452 | + ReceiptHandle string `xml:"ReceiptHandle"` |
453 | + Attribute []Attribute `xml:"Attribute"` |
454 | +} |
455 | + |
456 | +type ChangeMessageVisibilityBatchResponse struct { |
457 | + Id []string `xml:"ChangeMessageVisibilityBatchResult>ChangeMessageVisibilityBatchResultEntry>Id"` |
458 | + ResponseMetadata |
459 | +} |
460 | + |
461 | +type GetQueueAttributesResponse struct { |
462 | + Attributes []Attribute `xml:"GetQueueAttributesResult>Attribute"` |
463 | + ResponseMetadata |
464 | +} |
465 | + |
466 | +type DeleteMessageBatchResult struct { |
467 | + Ids []string `xml:"DeleteMessageBatchResult>DeleteMessageBatchResultEntry>Id"` |
468 | +} |
469 | + |
470 | +type DeleteMessageBatchResponse struct { |
471 | + DeleteMessageBatchResult `xml:"DeleteMessageBatchResponse>DeleteMessageBatchResult"` |
472 | + ResponseMetadata |
473 | +} |
474 | + |
475 | +type DeleteMessageBatch struct { |
476 | + Id string |
477 | + ReceiptHandle string |
478 | +} |
479 | + |
480 | +type AccountPermission struct { |
481 | + AWSAccountId string |
482 | + ActionName string |
483 | +} |
484 | + |
485 | +type AddPermissionResponse struct { |
486 | + ResponseMetadata |
487 | +} |
488 | + |
489 | +type RemovePermissionResponse struct { |
490 | + ResponseMetadata |
491 | +} |
492 | + |
493 | +type SetQueueAttributesResponse struct { |
494 | + ResponseMetadata |
495 | +} |
496 | + |
497 | +type DeleteQueueResponse struct { |
498 | + ResponseMetadata |
499 | +} |
500 | + |
501 | +// CreateQueue action creates a new queue. |
502 | +// |
503 | +// See http://goo.gl/sVUjF for more details |
504 | +func (s *SQS) CreateQueue(name string, attributes []Attribute) (queue *Queue, err error) { |
505 | + resp := &CreateQueueResponse{} |
506 | + params := makeParams("CreateQueue") |
507 | + queue = nil |
508 | + |
509 | + for i, attribute := range attributes { |
510 | + params["AttributeName."+strconv.Itoa(i+1)+".Name"] = attribute.Name |
511 | + params["AttributeName."+strconv.Itoa(i+1)+".Value"] = attribute.Value |
512 | + } |
513 | + |
514 | + params["QueueName"] = name |
515 | + err = s.query("", params, resp) |
516 | + if err != nil { |
517 | + return nil, err |
518 | + } |
519 | + queue = &Queue{s, resp.QueueUrl} |
520 | + return queue, err |
521 | +} |
522 | + |
523 | +// AddPermission action adds a permission to a queue for a specific principal. |
524 | +// |
525 | +// See http://goo.gl/8WBp8 for more details |
526 | +func (q *Queue) AddPermission(label string, accountPermissions []AccountPermission) (resp *AddPermissionResponse, err error) { |
527 | + resp = &AddPermissionResponse{} |
528 | + params := makeParams("AddPermission") |
529 | + |
530 | + params["Label"] = label |
531 | + for i, accountPermission := range accountPermissions { |
532 | + params["AWSAccountId."+strconv.Itoa(i+1)] = accountPermission.AWSAccountId |
533 | + params["ActionName."+strconv.Itoa(i+1)] = accountPermission.ActionName |
534 | + } |
535 | + |
536 | + err = q.SQS.query(q.Url, params, resp) |
537 | + return |
538 | +} |
539 | + |
540 | +// RemovePermission action revokes any permissions in the queue policy that matches the Label parameter. |
541 | +// |
542 | +// See http://goo.gl/YLOe8 for more details |
543 | +func (q *Queue) RemovePermission(label string) (resp *RemovePermissionResponse, err error) { |
544 | + resp = &RemovePermissionResponse{} |
545 | + params := makeParams("RemovePermission") |
546 | + |
547 | + params["Label"] = label |
548 | + err = q.SQS.query(q.Url, params, resp) |
549 | + return |
550 | +} |
551 | + |
552 | +// GetQueueAttributes action returns one or all attributes of a queue. |
553 | +// |
554 | +// See http://goo.gl/WejDu for more details |
555 | +func (q *Queue) GetQueueAttributes(attributes []string) (resp *GetQueueAttributesResponse, err error) { |
556 | + resp = &GetQueueAttributesResponse{} |
557 | + params := makeParams("GetQueueAttributes") |
558 | + |
559 | + for i, attribute := range attributes { |
560 | + params["AttributeName."+strconv.Itoa(i+1)] = attribute |
561 | + } |
562 | + |
563 | + err = q.SQS.query(q.Url, params, resp) |
564 | + return |
565 | +} |
566 | + |
567 | +// ChangeMessageVisibility action changes the visibility timeout of a specified message in a queue to a new value. |
568 | +// |
569 | +// See http://goo.gl/EyJKF for more details |
570 | +func (q *Queue) ChangeMessageVisibility(receiptHandle string, visibilityTimeout int) (resp *ChangeMessageVisibilityResponse, err error) { |
571 | + resp = &ChangeMessageVisibilityResponse{} |
572 | + params := makeParams("ChangeMessageVisibility") |
573 | + |
574 | + params["VisibilityTimeout"] = strconv.Itoa(visibilityTimeout) |
575 | + params["ReceiptHandle"] = receiptHandle |
576 | + |
577 | + err = q.SQS.query(q.Url, params, resp) |
578 | + return |
579 | +} |
580 | + |
581 | +// ChangeMessageVisibilityBatch action is a batch version of the ChangeMessageVisibility action. |
582 | +// |
583 | +// See http://goo.gl/pgffn for more details |
584 | +func (q *Queue) ChangeMessageVisibilityBatch(messageVisibilityBatch []ChangeMessageVisibilityBatchEntry) (resp *ChangeMessageVisibilityBatchResponse, err error) { |
585 | + resp = &ChangeMessageVisibilityBatchResponse{} |
586 | + params := makeParams("ChangeMessageVisibilityBatch") |
587 | + |
588 | + for i, messageVisibility := range messageVisibilityBatch { |
589 | + params["ChangeMessageVisibilityBatchRequestEntry."+strconv.Itoa(i+1)+".Id"] = messageVisibility.Id |
590 | + params["ChangeMessageVisibilityBatchRequestEntry."+strconv.Itoa(i+1)+".ReceiptHandle"] = messageVisibility.ReceiptHandle |
591 | + params["ChangeMessageVisibilityBatchRequestEntry."+strconv.Itoa(i+1)+".VisibilityTimeout"] = strconv.Itoa(messageVisibility.VisibilityTimeout) |
592 | + } |
593 | + |
594 | + err = q.SQS.query(q.Url, params, resp) |
595 | + return |
596 | +} |
597 | + |
598 | +// ReceiveMessage action retrieves one or more messages from the specified queue. |
599 | +// |
600 | +// See http://goo.gl/ThPrF for more details |
601 | +func (q *Queue) ReceiveMessage(attributes []string, maxNumberOfMessages int, visibilityTimeout int) (resp *ReceiveMessageResponse, err error) { |
602 | + resp = &ReceiveMessageResponse{} |
603 | + params := makeParams("ReceiveMessage") |
604 | + |
605 | + for i, attribute := range attributes { |
606 | + params["AttributeName."+strconv.Itoa(i+1)] = attribute |
607 | + } |
608 | + |
609 | + params["MaxNumberOfMessages"] = strconv.Itoa(maxNumberOfMessages) |
610 | + params["VisibilityTimeout"] = strconv.Itoa(visibilityTimeout) |
611 | + |
612 | + err = q.SQS.query(q.Url, params, resp) |
613 | + return |
614 | +} |
615 | + |
616 | +// DeleteMessage action deletes the specified message from the specified queue. |
617 | +// |
618 | +// See http://goo.gl/6XBv7 for more details |
619 | +func (q *Queue) DeleteMessage(receiptHandle string) (resp *DeleteMessageResponse, err error) { |
620 | + resp = &DeleteMessageResponse{} |
621 | + params := makeParams("DeleteMessage") |
622 | + |
623 | + params["ReceiptHandle"] = receiptHandle |
624 | + |
625 | + err = q.SQS.query(q.Url, params, resp) |
626 | + return |
627 | +} |
628 | + |
629 | +// DeleteMessageBatch action is a batch version of the DeleteMessage action. |
630 | +// |
631 | +// See http://goo.gl/y1ehG for more details |
632 | +func (q *Queue) DeleteMessageBatch(deleteMessageBatch []DeleteMessageBatch) (resp *DeleteMessageBatchResponse, err error) { |
633 | + resp = &DeleteMessageBatchResponse{} |
634 | + params := makeParams("DeleteMessageBatch") |
635 | + |
636 | + for i, deleteMessage := range deleteMessageBatch { |
637 | + params["DeleteMessageBatchRequestEntry."+strconv.Itoa(i+1)+".Id"] = deleteMessage.Id |
638 | + params["DeleteMessageBatchRequestEntry."+strconv.Itoa(i+1)+".ReceiptHandle"] = deleteMessage.ReceiptHandle |
639 | + } |
640 | + |
641 | + err = q.SQS.query(q.Url, params, resp) |
642 | + return |
643 | +} |
644 | + |
645 | +// SendMessage action delivers a message to the specified queue. |
646 | +// The maximum allowed size is 64KB |
647 | +// |
648 | +// See http://goo.gl/7OnPb for more details |
649 | +func (q *Queue) SendMessage(messageBody string) (resp *SendMessageResponse, err error) { |
650 | + resp = &SendMessageResponse{} |
651 | + params := makeParams("SendMessage") |
652 | + |
653 | + params["MessageBody"] = messageBody |
654 | + err = q.SQS.query(q.Url, params, resp) |
655 | + return |
656 | +} |
657 | + |
658 | +// SendMessageWithDelay is a helper function for SendMessage action which delivers a message to the specified queue |
659 | +// with a delay. |
660 | +// |
661 | +// See http://goo.gl/7OnPb for more details |
662 | +func (q *Queue) SendMessageWithDelay(messageBody string, delaySeconds int) (resp *SendMessageResponse, err error) { |
663 | + resp = &SendMessageResponse{} |
664 | + params := makeParams("SendMessage") |
665 | + |
666 | + params["MessageBody"] = messageBody |
667 | + params["DelaySeconds"] = strconv.Itoa(delaySeconds) |
668 | + err = q.SQS.query(q.Url, params, resp) |
669 | + return |
670 | +} |
671 | + |
672 | +// SendMessageBatch action delivers up to ten messages to the specified queue. |
673 | +// |
674 | +// See http://goo.gl/mNytv for more details |
675 | +func (q *Queue) SendMessageBatch(sendMessageBatchRequests []SendMessageBatchRequestEntry) (resp *SendMessageBatchResponse, err error) { |
676 | + resp = &SendMessageBatchResponse{} |
677 | + params := makeParams("SendMessageBatch") |
678 | + |
679 | + for i, sendMessageBatchRequest := range sendMessageBatchRequests { |
680 | + params["SendMessageBatchRequestEntry."+strconv.Itoa(i+1)+".Id"] = sendMessageBatchRequest.Id |
681 | + params["SendMessageBatchRequestEntry."+strconv.Itoa(i+1)+".MessageBody"] = sendMessageBatchRequest.MessageBody |
682 | + params["SendMessageBatchRequestEntry."+strconv.Itoa(i+1)+".DelaySeconds"] = strconv.Itoa(sendMessageBatchRequest.DelaySeconds) |
683 | + } |
684 | + |
685 | + err = q.SQS.query(q.Url, params, resp) |
686 | + return |
687 | +} |
688 | + |
689 | +// Delete action deletes the queue specified by the queue URL, regardless of whether the queue is empty. |
690 | +// |
691 | +// See http://goo.gl/c3YCr for more details |
692 | +func (q *Queue) Delete() (resp *DeleteQueueResponse, err error) { |
693 | + resp = &DeleteQueueResponse{} |
694 | + params := makeParams("Delete") |
695 | + |
696 | + err = q.SQS.query(q.Url, params, resp) |
697 | + return |
698 | +} |
699 | + |
700 | +// SetQueueAttributes action sets one attribute of a queue per request. |
701 | +// |
702 | +// See http://goo.gl/LyZnj for more details |
703 | +func (q *Queue) SetQueueAttributes(attribute Attribute) (resp *SetQueueAttributesResponse, err error) { |
704 | + resp = &SetQueueAttributesResponse{} |
705 | + params := makeParams("SetQueueAttributes") |
706 | + |
707 | + params["Attribute.Name"] = attribute.Name |
708 | + params["Attribute.Value"] = attribute.Value |
709 | + |
710 | + err = q.SQS.query(q.Url, params, resp) |
711 | + return |
712 | +} |
713 | + |
714 | +// ListQueues action returns a list of your queues. |
715 | +// |
716 | +// See http://goo.gl/RPRWr for more details |
717 | + |
718 | +func (s *SQS) ListQueues() (resp *ListQueuesResponse, err error) { |
719 | + resp = &ListQueuesResponse{} |
720 | + params := makeParams("ListQueues") |
721 | + |
722 | + err = s.query("", params, resp) |
723 | + return |
724 | +} |
725 | + |
726 | +// ListQueuesWithPrefix action returns only a list of queues with a name beginning with the specified value are returned |
727 | +// |
728 | +// See http://goo.gl/RPRWr for more details |
729 | +func (s *SQS) ListQueuesWithPrefix(queueNamePrefix string) (resp *ListQueuesResponse, err error) { |
730 | + resp = &ListQueuesResponse{} |
731 | + params := makeParams("ListQueues") |
732 | + |
733 | + if queueNamePrefix != "" { |
734 | + params["QueueNamePrefix"] = queueNamePrefix |
735 | + } |
736 | + |
737 | + err = s.query("", params, resp) |
738 | + return |
739 | +} |
740 | + |
741 | +// GetQueue is a helper function for GetQueueUrl action that returns an instance of a queue with specified name. |
742 | +// |
743 | +// See http://goo.gl/hk7Iu for more details |
744 | +func (s *SQS) GetQueue(queueName string) (queue *Queue, err error) { |
745 | + resp, err := s.GetQueueUrl(queueName) |
746 | + if err != nil { |
747 | + return nil, err |
748 | + } |
749 | + |
750 | + queue = &Queue{s, resp.QueueUrl} |
751 | + return |
752 | +} |
753 | + |
754 | +// GetQueueOfOwner is a helper function for GetQueueUrl action that returns an instance of a queue with specified name |
755 | +// and belongs to the specified AWS Account Id. |
756 | +// |
757 | +// See http://goo.gl/hk7Iu for more details |
758 | +func (s *SQS) GetQueueOfOwner(queueName, queueOwnerAWSAccountId string) (queue *Queue, err error) { |
759 | + resp, err := s.GetQueueUrlOfOwner(queueName, queueOwnerAWSAccountId) |
760 | + if err != nil { |
761 | + return nil, err |
762 | + } |
763 | + |
764 | + queue = &Queue{s, resp.QueueUrl} |
765 | + return |
766 | + |
767 | +} |
768 | + |
769 | +// GetQueueUrl action returns the Uniform Resource Locater (URL) of a queue. |
770 | +// |
771 | +// See http://goo.gl/hk7Iu for more details |
772 | +func (s *SQS) GetQueueUrl(queueName string) (resp *GetQueueUrlResponse, err error) { |
773 | + resp = &GetQueueUrlResponse{} |
774 | + params := makeParams("GetQueueUrl") |
775 | + |
776 | + params["QueueName"] = queueName |
777 | + |
778 | + err = s.query("", params, resp) |
779 | + return |
780 | +} |
781 | + |
782 | +// GetQueueUrlOfOwner is a helper function for GetQueueUrl action that returns the URL of a queue with specified name |
783 | +// and belongs to the specified AWS Account Id. |
784 | +// |
785 | +// See http://goo.gl/hk7Iu for more details for more details |
786 | +func (s *SQS) GetQueueUrlOfOwner(queueName, queueOwnerAWSAccountId string) (resp *GetQueueUrlResponse, err error) { |
787 | + resp = &GetQueueUrlResponse{} |
788 | + params := makeParams("GetQueueUrl") |
789 | + |
790 | + params["QueueName"] = queueName |
791 | + |
792 | + if queueOwnerAWSAccountId != "" { |
793 | + params["QueueOwnerAWSAccountId"] = queueOwnerAWSAccountId |
794 | + } |
795 | + |
796 | + err = s.query("", params, resp) |
797 | + return |
798 | +} |
799 | + |
800 | +func (s *SQS) query(queueUrl string, params map[string]string, resp interface{}) error { |
801 | + params["Version"] = "2011-10-01" |
802 | + params["Timestamp"] = time.Now().In(time.UTC).Format(time.RFC3339) |
803 | + var endpoint *url.URL |
804 | + var path string |
805 | + var err error |
806 | + if queueUrl != "" { |
807 | + endpoint, err = url.Parse(queueUrl) |
808 | + path = queueUrl[len(s.Region.SQSEndpoint):] |
809 | + } else { |
810 | + endpoint, err = url.Parse(s.Region.SQSEndpoint) |
811 | + path = "/" |
812 | + } |
813 | + if err != nil { |
814 | + return err |
815 | + } |
816 | + |
817 | + sign(s.Auth, "GET", path, params, endpoint.Host) |
818 | + endpoint.RawQuery = multimap(params).Encode() |
819 | + if debug { |
820 | + log.Printf("get { %v } -> {\n", endpoint.String()) |
821 | + } |
822 | + |
823 | + r, err := http.Get(endpoint.String()) |
824 | + if err != nil { |
825 | + return err |
826 | + } |
827 | + defer r.Body.Close() |
828 | + |
829 | + if debug { |
830 | + dump, _ := httputil.DumpResponse(r, true) |
831 | + log.Printf("response:\n") |
832 | + log.Printf("%v\n}\n", string(dump)) |
833 | + } |
834 | + if r.StatusCode != 200 { |
835 | + return buildError(r) |
836 | + } |
837 | + err = xml.NewDecoder(r.Body).Decode(resp) |
838 | + return err |
839 | +} |
840 | + |
841 | +func multimap(p map[string]string) url.Values { |
842 | + q := make(url.Values, len(p)) |
843 | + for k, v := range p { |
844 | + q[k] = []string{v} |
845 | + } |
846 | + return q |
847 | +} |
848 | + |
849 | +func buildError(r *http.Response) error { |
850 | + errors := xmlErrors{} |
851 | + xml.NewDecoder(r.Body).Decode(&errors) |
852 | + var err Error |
853 | + if len(errors.Errors) > 0 { |
854 | + err = errors.Errors[0] |
855 | + } |
856 | + err.RequestId = errors.RequestId |
857 | + err.StatusCode = r.StatusCode |
858 | + if err.Message == "" { |
859 | + err.Message = r.Status |
860 | + } |
861 | + return &err |
862 | +} |
863 | + |
864 | +func makeParams(action string) map[string]string { |
865 | + params := make(map[string]string) |
866 | + params["Action"] = action |
867 | + return params |
868 | +} |
869 | |
870 | === added file 'sqs_test.go' |
871 | --- sqs_test.go 1970-01-01 00:00:00 +0000 |
872 | +++ sqs_test.go 2012-05-25 00:21:19 +0000 |
873 | @@ -0,0 +1,306 @@ |
874 | +package sqs_test |
875 | + |
876 | +import ( |
877 | + "../sqs" |
878 | + "launchpad.net/goamz/aws" |
879 | + . "launchpad.net/gocheck" |
880 | +) |
881 | + |
882 | +var _ = Suite(&S{}) |
883 | + |
884 | +type S struct { |
885 | + //testServer.PrepareResponse(200, nil, TestChangeMessageVisibilityXmlOK) |
886 | + HTTPSuite |
887 | + sqs *sqs.SQS |
888 | +} |
889 | + |
890 | +func (s *S) SetUpSuite(c *C) { |
891 | + s.HTTPSuite.SetUpSuite(c) |
892 | + auth := aws.Auth{"abc", "123"} |
893 | + s.sqs = sqs.New(auth, aws.Region{SQSEndpoint: testServer.URL}) |
894 | +} |
895 | + |
896 | +func (s *S) TestCreateQueue(c *C) { |
897 | + testServer.PrepareResponse(200, nil, TestCreateQueueXmlOK) |
898 | + |
899 | + timeOutAttribute := sqs.Attribute{"VisibilityTimeout", "60"} |
900 | + maxMessageSizeAttribute := sqs.Attribute{"MaximumMessageSize", "65536"} |
901 | + messageRetentionAttribute := sqs.Attribute{"MessageRetentionPeriod", "345600"} |
902 | + q, err := s.sqs.CreateQueue("testQueue", []sqs.Attribute{timeOutAttribute, maxMessageSizeAttribute, messageRetentionAttribute}) |
903 | + req := testServer.WaitRequest() |
904 | + |
905 | + c.Assert(req.Method, Equals, "GET") |
906 | + c.Assert(req.URL.Path, Equals, "/") |
907 | + c.Assert(req.Header["Date"], Not(Equals), "") |
908 | + c.Assert(q.Url, Equals, "http://sqs.us-east-1.amazonaws.com/123456789012/testQueue") |
909 | + c.Assert(err, IsNil) |
910 | +} |
911 | + |
912 | +func (s *S) TestListQueues(c *C) { |
913 | + testServer.PrepareResponse(200, nil, TestListQueuesXmlOK) |
914 | + |
915 | + resp, err := s.sqs.ListQueues() |
916 | + req := testServer.WaitRequest() |
917 | + |
918 | + c.Assert(req.Method, Equals, "GET") |
919 | + c.Assert(req.URL.Path, Equals, "/") |
920 | + c.Assert(req.Header["Date"], Not(Equals), "") |
921 | + c.Assert(len(resp.QueueUrl), Not(Equals), 0) |
922 | + c.Assert(resp.QueueUrl[0], Equals, "http://sqs.us-east-1.amazonaws.com/123456789012/testQueue") |
923 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "725275ae-0b9b-4762-b238-436d7c65a1ac") |
924 | + c.Assert(err, IsNil) |
925 | +} |
926 | + |
927 | +func (s *S) TestGetQueueUrl(c *C) { |
928 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
929 | + |
930 | + resp, err := s.sqs.GetQueueUrl("testQueue") |
931 | + req := testServer.WaitRequest() |
932 | + |
933 | + c.Assert(req.Method, Equals, "GET") |
934 | + c.Assert(req.URL.Path, Equals, "/") |
935 | + c.Assert(req.Header["Date"], Not(Equals), "") |
936 | + c.Assert(resp.QueueUrl, Equals, "http://sqs.us-east-1.amazonaws.com/123456789012/testQueue") |
937 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "470a6f13-2ed9-4181-ad8a-2fdea142988e") |
938 | + c.Assert(err, IsNil) |
939 | +} |
940 | + |
941 | +func (s *S) TestChangeMessageVisibility(c *C) { |
942 | + //testServer.PrepareResponse(200, nil, TestChangeMessageVisibilityXmlOK) |
943 | + testServer.PrepareResponse(200, nil, TestCreateQueueXmlOK) |
944 | + |
945 | + timeOutAttribute := sqs.Attribute{"VisibilityTimeout", "60"} |
946 | + maxMessageSizeAttribute := sqs.Attribute{"MaximumMessageSize", "65536"} |
947 | + messageRetentionAttribute := sqs.Attribute{"MessageRetentionPeriod", "345600"} |
948 | + q, err := s.sqs.CreateQueue("testQueue", []sqs.Attribute{timeOutAttribute, maxMessageSizeAttribute, messageRetentionAttribute}) |
949 | + req := testServer.WaitRequest() |
950 | + |
951 | + c.Assert(req.Method, Equals, "GET") |
952 | + testServer.PrepareResponse(200, nil, TestChangeMessageVisibilityXmlOK) |
953 | + resp, err := q.ChangeMessageVisibility("MbZj6wDWli%2BJvwwJaBV%2B3dcjk2YW2vA3%2BSTFFljT", 0) |
954 | + testServer.WaitRequest() |
955 | + c.Assert(err, IsNil) |
956 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "6a7a282a-d013-4a59-aba9-335b0fa48bed") |
957 | +} |
958 | + |
959 | +func (s *S) TestChangeMessageVisibilityBatch(c *C) { |
960 | + testServer.PrepareResponse(200, nil, TestCreateQueueXmlOK) |
961 | + |
962 | + timeOutAttribute := sqs.Attribute{"VisibilityTimeout", "60"} |
963 | + maxMessageSizeAttribute := sqs.Attribute{"MaximumMessageSize", "65536"} |
964 | + messageRetentionAttribute := sqs.Attribute{"MessageRetentionPeriod", "345600"} |
965 | + q, err := s.sqs.CreateQueue("testQueue", []sqs.Attribute{timeOutAttribute, maxMessageSizeAttribute, messageRetentionAttribute}) |
966 | + testServer.WaitRequest() |
967 | + |
968 | + testServer.PrepareResponse(200, nil, TestChangeMessaveVisibilityBatchXmlOK) |
969 | + |
970 | + messageVisibilityBatch := []sqs.ChangeMessageVisibilityBatchEntry{sqs.ChangeMessageVisibilityBatchEntry{"change_visibility_msg_2", "gfk0T0R0waama4fVFffkjKzmhMCymjQvfTFk2LxT33G4ms5subrE0deLKWSscPU1oD3J9zgeS4PQQ3U30qOumIE6AdAv3w%2F%2Fa1IXW6AqaWhGsEPaLm3Vf6IiWqdM8u5imB%2BNTwj3tQRzOWdTOePjOjPcTpRxBtXix%2BEvwJOZUma9wabv%2BSw6ZHjwmNcVDx8dZXJhVp16Bksiox%2FGrUvrVTCJRTWTLc59oHLLF8sEkKzRmGNzTDGTiV%2BYjHfQj60FD3rVaXmzTsoNxRhKJ72uIHVMGVQiAGgBX6HGv9LDmYhPXw4hy%2FNgIg%3D%3D", 45}, sqs.ChangeMessageVisibilityBatchEntry{"change_visibility_msg_3", "gfk0T0R0waama4fVFffkjKzmhMCymjQvfTFk2LxT33FUgBz3%2BnougdeLKWSscPU1%2FXgx%2BxcNnjnQQ3U30qOumIE6AdAv3w%2F%2Fa1IXW6AqaWhGsEPaLm3Vf6IiWqdM8u5imB%2BNTwj3tQRzOWdTOePjOsogjZM%2F7kzn4Ew27XLU9I%2FYaWYmKvDbq%2Fk3HKVB9HfB43kE49atP2aWrzNL4yunG41Q4cfRRtfJdcGQGNHQ2%2Byd0Usf5qR1dZr1iDo5xk946eQat83AxTRP%2BY4Qi0V7FAeSLH9su9xpX6HGv9LDmYhPXw4hy%2FNgIg%3D%3D", 45}} |
971 | + resp, err := q.ChangeMessageVisibilityBatch(messageVisibilityBatch) |
972 | + testServer.WaitRequest() |
973 | + c.Assert(err, IsNil) |
974 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "ca9668f7-ab1b-4f7a-8859-f15747ab17a7") |
975 | + c.Assert(resp.Id[0], Equals, "change_visibility_msg_2") |
976 | + c.Assert(resp.Id[1], Equals, "change_visibility_msg_3") |
977 | +} |
978 | + |
979 | +func (s *S) TestReceiveMessage(c *C) { |
980 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
981 | + |
982 | + q, err := s.sqs.GetQueue("testQueue") |
983 | + testServer.WaitRequest() |
984 | + |
985 | + testServer.PrepareResponse(200, nil, TestReceiveMessageXmlOK) |
986 | + |
987 | + resp, err := q.ReceiveMessage([]string{"All"}, 5, 15) |
988 | + testServer.WaitRequest() |
989 | + c.Assert(err, IsNil) |
990 | + c.Assert(len(resp.Messages), Not(Equals), 0) |
991 | +} |
992 | + |
993 | +func (s *S) TestDeleteMessage(c *C) { |
994 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
995 | + |
996 | + q, err := s.sqs.GetQueue("testQueue") |
997 | + testServer.WaitRequest() |
998 | + |
999 | + testServer.PrepareResponse(200, nil, TestDeleteMessageXmlOK) |
1000 | + |
1001 | + resp, err := q.DeleteMessage("MbZj6wDWli%2BJvwwJaBV%2B3dcjk2YW2vA3%2BSTFFljTM8tJJg6HRG6PYSasuWXPJB%2BCwLj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ%2BQEauMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=") |
1002 | + testServer.WaitRequest() |
1003 | + c.Assert(err, IsNil) |
1004 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "b5293cb5-d306-4a17-9048-b263635abe42") |
1005 | +} |
1006 | + |
1007 | +func (s *S) TestDeleteMessageBatch(c *C) { |
1008 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1009 | + |
1010 | + q, err := s.sqs.GetQueue("testQueue") |
1011 | + testServer.WaitRequest() |
1012 | + |
1013 | + testServer.PrepareResponse(200, nil, TestDeleteMessageBatchXmlOK) |
1014 | + |
1015 | + deleteMessageBatch := []sqs.DeleteMessageBatch{sqs.DeleteMessageBatch{Id: "msg1", ReceiptHandle: "gfk0T0R0waama4fVFffkjPQrrvzMrOg0fTFk2LxT33EuB8wR0ZCFgKWyXGWFoqqpCIiprQUEhir%2F5LeGPpYTLzjqLQxyQYaQALeSNHb0us3uE84uujxpBhsDkZUQkjFFkNqBXn48xlMcVhTcI3YLH%2Bd%2BIqetIOHgBCZAPx6r%2B09dWaBXei6nbK5Ygih21DCDdAwFV68Jo8DXhb3ErEfoDqx7vyvC5nCpdwqv%2BJhU%2FTNGjNN8t51v5c%2FAXvQsAzyZVNapxUrHIt4NxRhKJ72uICcxruyE8eRXlxIVNgeNP8ZEDcw7zZU1Zw%3D%3D"}, sqs.DeleteMessageBatch{Id: "msg2", ReceiptHandle: "gfk0T0R0waama4fVFffkjKzmhMCymjQvfTFk2LxT33G4ms5subrE0deLKWSscPU1oD3J9zgeS4PQQ3U30qOumIE6AdAv3w%2F%2Fa1IXW6AqaWhGsEPaLm3Vf6IiWqdM8u5imB%2BNTwj3tQRzOWdTOePjOjPcTpRxBtXix%2BEvwJOZUma9wabv%2BSw6ZHjwmNcVDx8dZXJhVp16Bksiox%2FGrUvrVTCJRTWTLc59oHLLF8sEkKzRmGNzTDGTiV%2BYjHfQj60FD3rVaXmzTsoNxRhKJ72uIHVMGVQiAGgB%2BqAbSqfKHDQtVOmJJgkHug%3D%3D"}} |
1016 | + resp, err := q.DeleteMessageBatch(deleteMessageBatch) |
1017 | + testServer.WaitRequest() |
1018 | + |
1019 | + c.Assert(err, IsNil) |
1020 | + c.Assert(len(resp.DeleteMessageBatchResult.Ids), Equals, 2) |
1021 | + c.Assert(resp.DeleteMessageBatchResult.Ids[0], Equals, "msg1") |
1022 | + c.Assert(resp.DeleteMessageBatchResult.Ids[1], Equals, "msg2") |
1023 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "d6f86b7a-74d1-4439-b43f-196a1e29cd85") |
1024 | +} |
1025 | + |
1026 | +func (s *S) TestAddPermission(c *C) { |
1027 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1028 | + |
1029 | + q, err := s.sqs.GetQueue("testQueue") |
1030 | + testServer.WaitRequest() |
1031 | + |
1032 | + testServer.PrepareResponse(200, nil, TestAddPermissionXmlOK) |
1033 | + resp, err := q.AddPermission("testLabel", []sqs.AccountPermission{sqs.AccountPermission{"125074342641", "SendMessage"}, sqs.AccountPermission{"125074342642", "ReceiveMessage"}}) |
1034 | + testServer.WaitRequest() |
1035 | + |
1036 | + c.Assert(err, IsNil) |
1037 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "9a285199-c8d6-47c2-bdb2-314cb47d599d") |
1038 | +} |
1039 | + |
1040 | +func (s *S) TestRemovePermission(c *C) { |
1041 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1042 | + |
1043 | + q, err := s.sqs.GetQueue("testQueue") |
1044 | + testServer.WaitRequest() |
1045 | + |
1046 | + testServer.PrepareResponse(200, nil, TestRemovePermissionXmlOK) |
1047 | + resp, err := q.RemovePermission("testLabel") |
1048 | + testServer.WaitRequest() |
1049 | + |
1050 | + c.Assert(err, IsNil) |
1051 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "f8bdb362-6616-42c0-977a-ce9a8bcce3bb") |
1052 | +} |
1053 | + |
1054 | +func (s *S) TestSendMessage(c *C) { |
1055 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1056 | + |
1057 | + q, err := s.sqs.GetQueue("testQueue") |
1058 | + testServer.WaitRequest() |
1059 | + |
1060 | + testServer.PrepareResponse(200, nil, TestSendMessageXmlOK) |
1061 | + |
1062 | + resp, err := q.SendMessage("This is a Message") |
1063 | + testServer.WaitRequest() |
1064 | + c.Assert(err, IsNil) |
1065 | + c.Assert(resp.SendMessageResult.MD5OfMessageBody, Equals, "fafb00f5732ab283681e124bf8747ed1") |
1066 | + c.Assert(resp.SendMessageResult.MessageId, Equals, "5fea7756-0ea4-451a-a703-a558b933e274") |
1067 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "27daac76-34dd-47df-bd01-1f6e873584a0") |
1068 | +} |
1069 | + |
1070 | +func (s *S) TestSendMessageWithDelay(c *C) { |
1071 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1072 | + |
1073 | + q, err := s.sqs.GetQueue("testQueue") |
1074 | + testServer.WaitRequest() |
1075 | + |
1076 | + testServer.PrepareResponse(200, nil, TestSendMessageXmlOK) |
1077 | + |
1078 | + resp, err := q.SendMessageWithDelay("This is a Message", 60) |
1079 | + testServer.WaitRequest() |
1080 | + c.Assert(err, IsNil) |
1081 | + c.Assert(resp.SendMessageResult.MD5OfMessageBody, Equals, "fafb00f5732ab283681e124bf8747ed1") |
1082 | + c.Assert(resp.SendMessageResult.MessageId, Equals, "5fea7756-0ea4-451a-a703-a558b933e274") |
1083 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "27daac76-34dd-47df-bd01-1f6e873584a0") |
1084 | +} |
1085 | + |
1086 | +func (s *S) TestSendMessageBatch(c *C) { |
1087 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1088 | + |
1089 | + q, err := s.sqs.GetQueue("testQueue") |
1090 | + testServer.WaitRequest() |
1091 | + |
1092 | + testServer.PrepareResponse(200, nil, TestSendMessageBatchXmlOK) |
1093 | + |
1094 | + sendMessageBatchRequests := []sqs.SendMessageBatchRequestEntry{sqs.SendMessageBatchRequestEntry{Id: "test_msg_001", MessageBody: "test message body 1", DelaySeconds: 30}} |
1095 | + resp, err := q.SendMessageBatch(sendMessageBatchRequests) |
1096 | + testServer.WaitRequest() |
1097 | + c.Assert(err, IsNil) |
1098 | + c.Assert(len(resp.SendMessageBatchResult.Entries), Equals, 2) |
1099 | + c.Assert(resp.SendMessageBatchResult.Entries[0].Id, Equals, "test_msg_001") |
1100 | +} |
1101 | + |
1102 | +func (s *S) TestGetQueueAttributes(c *C) { |
1103 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1104 | + |
1105 | + q, err := s.sqs.GetQueue("testQueue") |
1106 | + testServer.WaitRequest() |
1107 | + |
1108 | + testServer.PrepareResponse(200, nil, TestGetQueueAttributesAllXmlOK) |
1109 | + |
1110 | + resp, err := q.GetQueueAttributes([]string{"ALL"}) |
1111 | + testServer.WaitRequest() |
1112 | + |
1113 | + c.Assert(err, IsNil) |
1114 | + c.Assert(len(resp.Attributes), Equals, 8) |
1115 | + c.Assert(resp.Attributes[0].Name, Equals, "VisibilityTimeout") |
1116 | + c.Assert(resp.Attributes[0].Value, Equals, "30") |
1117 | +} |
1118 | + |
1119 | +func (s *S) TestGetQueueAttributesSelective(c *C) { |
1120 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1121 | + |
1122 | + q, err := s.sqs.GetQueue("testQueue") |
1123 | + testServer.WaitRequest() |
1124 | + |
1125 | + testServer.PrepareResponse(200, nil, TestGetQueueAttributesSelectiveXmlOK) |
1126 | + |
1127 | + resp, err := q.GetQueueAttributes([]string{"VisibilityTimeout", "DelaySeconds"}) |
1128 | + testServer.WaitRequest() |
1129 | + |
1130 | + c.Assert(err, IsNil) |
1131 | + c.Assert(len(resp.Attributes), Equals, 2) |
1132 | + c.Assert(resp.Attributes[0].Name, Equals, "VisibilityTimeout") |
1133 | + c.Assert(resp.Attributes[0].Value, Equals, "30") |
1134 | + c.Assert(resp.Attributes[1].Name, Equals, "DelaySeconds") |
1135 | + c.Assert(resp.Attributes[1].Value, Equals, "0") |
1136 | +} |
1137 | + |
1138 | +func (s *S) TestDeleteQueue(c *C) { |
1139 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1140 | + |
1141 | + q, err := s.sqs.GetQueue("testQueue") |
1142 | + testServer.WaitRequest() |
1143 | + |
1144 | + testServer.PrepareResponse(200, nil, TestDeleteQueueXmlOK) |
1145 | + resp, err := q.Delete() |
1146 | + testServer.WaitRequest() |
1147 | + |
1148 | + c.Assert(err, IsNil) |
1149 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "6fde8d1e-52cd-4581-8cd9-c512f4c64223") |
1150 | +} |
1151 | + |
1152 | +func (s *S) TestSetQueueAttributes(c *C) { |
1153 | + testServer.PrepareResponse(200, nil, TestGetQueueUrlXmlOK) |
1154 | + |
1155 | + q, err := s.sqs.GetQueue("testQueue") |
1156 | + testServer.WaitRequest() |
1157 | + |
1158 | + testServer.PrepareResponse(200, nil, TestSetQueueAttributesXmlOK) |
1159 | + var policyStr = ` |
1160 | + { |
1161 | + "Version":"2008-10-17", |
1162 | + "Id":"/123456789012/testQueue/SQSDefaultPolicy", |
1163 | + "Statement": [ |
1164 | + { |
1165 | + "Sid":"Queue1ReceiveMessage", |
1166 | + "Effect":"Allow", |
1167 | + "Principal":{"AWS":"*"}, |
1168 | + "Action":"SQS:ReceiveMessage", |
1169 | + "Resource":"arn:aws:sqs:us-east-1:123456789012:testQueue" |
1170 | + } |
1171 | + ] |
1172 | + } |
1173 | + ` |
1174 | + resp, err := q.SetQueueAttributes(sqs.Attribute{"Policy", policyStr}) |
1175 | + testServer.WaitRequest() |
1176 | + |
1177 | + c.Assert(err, IsNil) |
1178 | + c.Assert(resp.ResponseMetadata.RequestId, Equals, "e5cca473-4fc0-4198-a451-8abb94d02c75") |
1179 | +} |
1180 | |
1181 | === added file 'suite_test.go' |
1182 | --- suite_test.go 1970-01-01 00:00:00 +0000 |
1183 | +++ suite_test.go 2012-05-25 00:21:19 +0000 |
1184 | @@ -0,0 +1,120 @@ |
1185 | +package sqs_test |
1186 | + |
1187 | +import ( |
1188 | + "fmt" |
1189 | + . "launchpad.net/gocheck" |
1190 | + "net/http" |
1191 | + "net/url" |
1192 | + "os" |
1193 | + "testing" |
1194 | + "time" |
1195 | +) |
1196 | + |
1197 | +func Test(t *testing.T) { |
1198 | + TestingT(t) |
1199 | +} |
1200 | + |
1201 | +type HTTPSuite struct{} |
1202 | + |
1203 | +var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second) |
1204 | + |
1205 | +func (s *HTTPSuite) SetUpSuite(c *C) { |
1206 | + testServer.Start() |
1207 | +} |
1208 | + |
1209 | +func (s *HTTPSuite) TearDownTest(c *C) { |
1210 | + testServer.FlushRequests() |
1211 | +} |
1212 | + |
1213 | +type TestHTTPServer struct { |
1214 | + URL string |
1215 | + Timeout time.Duration |
1216 | + started bool |
1217 | + request chan *http.Request |
1218 | + response chan *testResponse |
1219 | + pending chan bool |
1220 | +} |
1221 | + |
1222 | +type testResponse struct { |
1223 | + Status int |
1224 | + Headers map[string]string |
1225 | + Body string |
1226 | +} |
1227 | + |
1228 | +func NewTestHTTPServer(url string, timeout time.Duration) *TestHTTPServer { |
1229 | + return &TestHTTPServer{URL: url, Timeout: timeout} |
1230 | +} |
1231 | + |
1232 | +func (s *TestHTTPServer) Start() { |
1233 | + if s.started { |
1234 | + return |
1235 | + } |
1236 | + s.started = true |
1237 | + |
1238 | + s.request = make(chan *http.Request, 64) |
1239 | + s.response = make(chan *testResponse, 64) |
1240 | + s.pending = make(chan bool, 64) |
1241 | + |
1242 | + url, _ := url.Parse(s.URL) |
1243 | + go http.ListenAndServe(url.Host, s) |
1244 | + |
1245 | + s.PrepareResponse(202, nil, "Nothing.") |
1246 | + for { |
1247 | + // Wait for it to be up. |
1248 | + resp, err := http.Get(s.URL) |
1249 | + if err == nil && resp.StatusCode == 202 { |
1250 | + break |
1251 | + } |
1252 | + fmt.Fprintf(os.Stderr, "\nWaiting for fake server to be up... ") |
1253 | + time.Sleep(1e8) |
1254 | + } |
1255 | + fmt.Fprintf(os.Stderr, "done\n\n") |
1256 | + s.WaitRequest() // Consume dummy request |
1257 | +} |
1258 | + |
1259 | +// FulshRequests discards requests which were not yet consumed by WaitRequest |
1260 | +func (s *TestHTTPServer) FlushRequests() { |
1261 | + for { |
1262 | + select { |
1263 | + case <-s.request: |
1264 | + default: |
1265 | + return |
1266 | + } |
1267 | + } |
1268 | +} |
1269 | + |
1270 | +func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { |
1271 | + s.request <- req |
1272 | + var resp *testResponse |
1273 | + select { |
1274 | + case resp = <-s.response: |
1275 | + case <-time.After(s.Timeout): |
1276 | + fmt.Fprintf(os.Stderr, "ERROR: Timeout waiting for test to provide response\n") |
1277 | + resp = &testResponse{500, nil, ""} |
1278 | + } |
1279 | + if resp.Headers != nil { |
1280 | + h := w.Header() |
1281 | + for k, v := range resp.Headers { |
1282 | + h.Set(k, v) |
1283 | + } |
1284 | + } |
1285 | + if resp.Status != 0 { |
1286 | + w.WriteHeader(resp.Status) |
1287 | + } |
1288 | + w.Write([]byte(resp.Body)) |
1289 | +} |
1290 | + |
1291 | +func (s *TestHTTPServer) WaitRequest() *http.Request { |
1292 | + select { |
1293 | + case req := <-s.request: |
1294 | + req.ParseForm() |
1295 | + return req |
1296 | + case <-time.After(s.Timeout): |
1297 | + panic("Timeout waiting for goamz request") |
1298 | + } |
1299 | + panic("unreached") |
1300 | +} |
1301 | + |
1302 | +func (s *TestHTTPServer) PrepareResponse(status int, headers map[string]string, body string) { |
1303 | + s.response <- &testResponse{status, headers, body} |
1304 | +} |