Merge lp:~prudhvikrishna/goamz/sqs into lp:~gophers/goamz/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
Reviewer Review Type Date Requested Status
The Go Language Gophers Pending
Review via email: mp+107309@code.launchpad.net
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+}

Subscribers

People subscribed via source and target branches