Merge lp:~niemeyer/goamz/testing-cleanup into lp:~gophers/goamz/trunk
- testing-cleanup
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 27 |
Proposed branch: | lp:~niemeyer/goamz/testing-cleanup |
Merge into: | lp:~gophers/goamz/trunk |
Diff against target: |
2514 lines (+427/-1143) 27 files modified
aws/aws_test.go (+5/-0) aws/suite_test.go (+0/-139) ec2/ec2.go (+17/-17) ec2/ec2_test.go (+38/-27) ec2/ec2i_test.go (+2/-4) ec2/ec2t_test.go (+5/-8) ec2/ec2test/filter.go (+2/-2) ec2/ec2test/server.go (+12/-12) ec2/sign.go (+4/-4) ec2/suite_test.go (+0/-118) exp/mturk/mturk.go (+5/-5) exp/mturk/mturk_test.go (+15/-4) exp/mturk/suite_test.go (+0/-120) exp/sdb/sdb.go (+3/-3) exp/sdb/sdb_test.go (+21/-10) exp/sdb/suite_test.go (+0/-139) exp/sns/sns_test.go (+13/-2) exp/sns/suite_test.go (+0/-200) iam/iam_test.go (+18/-7) iam/iami_test.go (+2/-4) iam/suite_test.go (+0/-128) s3/s3.go (+18/-13) s3/s3_test.go (+25/-14) s3/s3i_test.go (+18/-24) s3/suite_test.go (+0/-139) testutil/http.go (+174/-0) testutil/suite.go (+30/-0) |
To merge this branch: | bzr merge lp:~niemeyer/goamz/testing-cleanup |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
The Go Language Gophers | Pending | ||
Review via email: mp+145878@code.launchpad.net |
Commit message
Description of the change
testutil: new package for test clean up
Killed all the repetition in suite_test files, and improved the
implementation of the test HTTP server.
A few test bugs were also fixed on the way.
Gustavo Niemeyer (niemeyer) wrote : | # |
Roger Peppe (rogpeppe) wrote : | # |
LGTM except for the query about the default security group test.
nice to see all that code factored out.
https:/
File ec2/ec2_test.go (right):
https:/
ec2/ec2_test.go:24: testServer.Start()
that makes much more sense, given we're using the global below.
https:/
File ec2/ec2t_test.go (right):
https:/
ec2/ec2t_
s.ec2.SecurityG
why commented out? this was testing specific ec2test functionality.
have you tried these tests live? i seem to remember that
i needed to add the "default" group because it was
being returned for some of the filtering requests.
https:/
File ec2/ec2test/
https:/
ec2/ec2test/
later
align?
(and below)
https:/
File ec2/sign.go (right):
https:/
ec2/sign.go:23: // be in natural order of the keys. This is distinct
from the
s/in natural/in the natural/
?
https:/
File exp/mturk/
https:/
exp/mturk/
great to see all this duplication go away.
https:/
File s3/s3.go (right):
https:/
s3/s3.go:231: // into different groupings of keys, similar to how
folders would work.
s/would// ?
Gustavo Niemeyer (niemeyer) wrote : | # |
https:/
File ec2/ec2t_test.go (right):
https:/
ec2/ec2t_
s.ec2.SecurityG
On 2013/01/31 15:42:43, rog wrote:
> why commented out? this was testing specific ec2test functionality.
Sorry, it shouldn't be commented out. It should be removed. There's
nothing special about the default group, and the test is broken because
it trusts the system to only have a single group named default, which is
not a given.
> have you tried these tests live? i seem to remember that
> i needed to add the "default" group because it was
> being returned for some of the filtering requests.
Yeah, it was testing it live that forced me to fix it.
Roger Peppe (rogpeppe) wrote : | # |
On 31 January 2013 15:58, <email address hidden> wrote:
>
> https:/
> File ec2/ec2t_test.go (right):
>
> https:/
> ec2/ec2t_
> s.ec2.SecurityG
> On 2013/01/31 15:42:43, rog wrote:
>>
>> why commented out? this was testing specific ec2test functionality.
>
>
> Sorry, it shouldn't be commented out. It should be removed. There's
> nothing special about the default group, and the test is broken because
> it trusts the system to only have a single group named default, which is
> not a given.
The default is created by automatically, can't be removed, and has
default permissions
set up for tcp and udp (which means that it gets selected by some of
the filters)
if you try to create another group called "default", you get a
"The security group 'default' is reserved" error.
That seems fairly special to me - I *think* we're always guaranteed
a single group named default... but maybe that's only true of us-east.
How did the test fail for you? I'd definitely like to understand more about
the problem before changing those tests.
Gustavo Niemeyer (niemeyer) wrote : | # |
On 2013/01/31 17:01:29, rog wrote:
> The default is created by automatically, can't be removed, and has
> default permissions set up for tcp and udp (which means that it
> gets selected by some of the filters)
None of that seems relevant for filtering.
> if you try to create another group called "default", you get a
> "The security group 'default' is reserved" error.
I have two groups named "default" in my account, and that's breaking the
test case. One of them comes from VPC. Amazon created it.
> That seems fairly special to me - I *think* we're always guaranteed
> a single group named default... but maybe that's only true of us-east.
I'm not lying, promise.
- 28. By Gustavo Niemeyer
-
Review by Roger.
Gustavo Niemeyer (niemeyer) wrote : | # |
Please take a look.
https:/
File ec2/ec2test/
https:/
ec2/ec2test/
later
On 2013/01/31 15:42:43, rog wrote:
> align?
> (and below)
Done.
https:/
File ec2/sign.go (right):
https:/
ec2/sign.go:23: // be in natural order of the keys. This is distinct
from the
On 2013/01/31 15:42:43, rog wrote:
> s/in natural/in the natural/
> ?
Done.
https:/
File s3/s3.go (right):
https:/
s3/s3.go:231: // into different groupings of keys, similar to how
folders would work.
On 2013/01/31 15:42:43, rog wrote:
> s/would// ?
That's how they would work if S3 used the concept of folders. It
doesn't, so it doesn't work quite that way.
Gustavo Niemeyer (niemeyer) wrote : | # |
*** Submitted:
testutil: new package for test clean up
Killed all the repetition in suite_test files, and improved the
implementation of the test HTTP server.
A few test bugs were also fixed on the way.
R=rog
CC=
https:/
Preview Diff
1 | === modified file 'aws/aws_test.go' | |||
2 | --- aws/aws_test.go 2012-07-02 23:36:49 +0000 | |||
3 | +++ aws/aws_test.go 2013-01-31 17:09:20 +0000 | |||
4 | @@ -5,8 +5,13 @@ | |||
5 | 5 | . "launchpad.net/gocheck" | 5 | . "launchpad.net/gocheck" |
6 | 6 | "os" | 6 | "os" |
7 | 7 | "strings" | 7 | "strings" |
8 | 8 | "testing" | ||
9 | 8 | ) | 9 | ) |
10 | 9 | 10 | ||
11 | 11 | func Test(t *testing.T) { | ||
12 | 12 | TestingT(t) | ||
13 | 13 | } | ||
14 | 14 | |||
15 | 10 | var _ = Suite(&S{}) | 15 | var _ = Suite(&S{}) |
16 | 11 | 16 | ||
17 | 12 | type S struct { | 17 | type S struct { |
18 | 13 | 18 | ||
19 | === removed file 'aws/suite_test.go' | |||
20 | --- aws/suite_test.go 2012-05-03 17:12:28 +0000 | |||
21 | +++ aws/suite_test.go 1970-01-01 00:00:00 +0000 | |||
22 | @@ -1,139 +0,0 @@ | |||
23 | 1 | package aws_test | ||
24 | 2 | |||
25 | 3 | import ( | ||
26 | 4 | "flag" | ||
27 | 5 | "fmt" | ||
28 | 6 | "launchpad.net/goamz/aws" | ||
29 | 7 | . "launchpad.net/gocheck" | ||
30 | 8 | "net/http" | ||
31 | 9 | "net/url" | ||
32 | 10 | "os" | ||
33 | 11 | "testing" | ||
34 | 12 | "time" | ||
35 | 13 | ) | ||
36 | 14 | |||
37 | 15 | func Test(t *testing.T) { | ||
38 | 16 | TestingT(t) | ||
39 | 17 | } | ||
40 | 18 | |||
41 | 19 | var integration = flag.Bool("i", false, "Enable integration tests") | ||
42 | 20 | |||
43 | 21 | type SuiteI struct { | ||
44 | 22 | auth aws.Auth | ||
45 | 23 | } | ||
46 | 24 | |||
47 | 25 | func (s *SuiteI) SetUpSuite(c *C) { | ||
48 | 26 | if !*integration { | ||
49 | 27 | c.Skip("Integration tests not enabled (-int flag)") | ||
50 | 28 | } | ||
51 | 29 | auth, err := aws.EnvAuth() | ||
52 | 30 | if err != nil { | ||
53 | 31 | c.Fatal(err) | ||
54 | 32 | } | ||
55 | 33 | s.auth = auth | ||
56 | 34 | } | ||
57 | 35 | |||
58 | 36 | type HTTPSuite struct{} | ||
59 | 37 | |||
60 | 38 | var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second) | ||
61 | 39 | |||
62 | 40 | func (s *HTTPSuite) SetUpSuite(c *C) { | ||
63 | 41 | testServer.Start() | ||
64 | 42 | } | ||
65 | 43 | |||
66 | 44 | func (s *HTTPSuite) TearDownTest(c *C) { | ||
67 | 45 | testServer.FlushRequests() | ||
68 | 46 | } | ||
69 | 47 | |||
70 | 48 | type TestHTTPServer struct { | ||
71 | 49 | URL string | ||
72 | 50 | Timeout time.Duration | ||
73 | 51 | started bool | ||
74 | 52 | request chan *http.Request | ||
75 | 53 | response chan *testResponse | ||
76 | 54 | pending chan bool | ||
77 | 55 | } | ||
78 | 56 | |||
79 | 57 | type testResponse struct { | ||
80 | 58 | Status int | ||
81 | 59 | Headers map[string]string | ||
82 | 60 | Body string | ||
83 | 61 | } | ||
84 | 62 | |||
85 | 63 | func NewTestHTTPServer(url_ string, timeout time.Duration) *TestHTTPServer { | ||
86 | 64 | return &TestHTTPServer{URL: url_, Timeout: timeout} | ||
87 | 65 | } | ||
88 | 66 | |||
89 | 67 | func (s *TestHTTPServer) Start() { | ||
90 | 68 | if s.started { | ||
91 | 69 | return | ||
92 | 70 | } | ||
93 | 71 | s.started = true | ||
94 | 72 | |||
95 | 73 | s.request = make(chan *http.Request, 64) | ||
96 | 74 | s.response = make(chan *testResponse, 64) | ||
97 | 75 | s.pending = make(chan bool, 64) | ||
98 | 76 | |||
99 | 77 | url, _ := url.Parse(s.URL) | ||
100 | 78 | go http.ListenAndServe(url.Host, s) | ||
101 | 79 | |||
102 | 80 | s.PrepareResponse(123, nil, "") | ||
103 | 81 | for { | ||
104 | 82 | // Wait for it to be up. | ||
105 | 83 | resp, err := http.Get(s.URL) | ||
106 | 84 | if err == nil && resp.StatusCode == 123 { | ||
107 | 85 | break | ||
108 | 86 | } | ||
109 | 87 | fmt.Fprintf(os.Stderr, "\nWaiting for fake server to be up... ") | ||
110 | 88 | time.Sleep(1e8) | ||
111 | 89 | } | ||
112 | 90 | fmt.Fprintf(os.Stderr, "done\n\n") | ||
113 | 91 | s.WaitRequest() // Consume dummy request. | ||
114 | 92 | } | ||
115 | 93 | |||
116 | 94 | // FlushRequests discards requests which were not yet consumed by WaitRequest. | ||
117 | 95 | func (s *TestHTTPServer) FlushRequests() { | ||
118 | 96 | for { | ||
119 | 97 | select { | ||
120 | 98 | case <-s.request: | ||
121 | 99 | default: | ||
122 | 100 | return | ||
123 | 101 | } | ||
124 | 102 | } | ||
125 | 103 | } | ||
126 | 104 | |||
127 | 105 | func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
128 | 106 | s.request <- req | ||
129 | 107 | var resp *testResponse | ||
130 | 108 | select { | ||
131 | 109 | case resp = <-s.response: | ||
132 | 110 | case <-time.After(s.Timeout): | ||
133 | 111 | fmt.Fprintf(os.Stderr, "ERROR: Timeout waiting for test to provide response\n") | ||
134 | 112 | resp = &testResponse{500, nil, ""} | ||
135 | 113 | } | ||
136 | 114 | h := w.Header() | ||
137 | 115 | if resp.Headers != nil { | ||
138 | 116 | for k, v := range resp.Headers { | ||
139 | 117 | h.Set(k, v) | ||
140 | 118 | } | ||
141 | 119 | } | ||
142 | 120 | if resp.Status != 0 { | ||
143 | 121 | w.WriteHeader(resp.Status) | ||
144 | 122 | } | ||
145 | 123 | w.Write([]byte(resp.Body)) | ||
146 | 124 | } | ||
147 | 125 | |||
148 | 126 | func (s *TestHTTPServer) WaitRequest() *http.Request { | ||
149 | 127 | select { | ||
150 | 128 | case req := <-s.request: | ||
151 | 129 | req.ParseForm() | ||
152 | 130 | return req | ||
153 | 131 | case <-time.After(s.Timeout): | ||
154 | 132 | panic("Timeout waiting for goamz request") | ||
155 | 133 | } | ||
156 | 134 | panic("unreached") | ||
157 | 135 | } | ||
158 | 136 | |||
159 | 137 | func (s *TestHTTPServer) PrepareResponse(status int, headers map[string]string, body string) { | ||
160 | 138 | s.response <- &testResponse{status, headers, body} | ||
161 | 139 | } | ||
162 | 140 | 0 | ||
163 | === modified file 'ec2/ec2.go' | |||
164 | --- ec2/ec2.go 2012-10-28 16:05:46 +0000 | |||
165 | +++ ec2/ec2.go 2013-01-31 17:09:20 +0000 | |||
166 | @@ -86,7 +86,7 @@ | |||
167 | 86 | // ---------------------------------------------------------------------------- | 86 | // ---------------------------------------------------------------------------- |
168 | 87 | // Request dispatching logic. | 87 | // Request dispatching logic. |
169 | 88 | 88 | ||
171 | 89 | // Error encapsulates an error returned by EC2. | 89 | // Error encapsulates an error returned by EC2. |
172 | 90 | // | 90 | // |
173 | 91 | // See http://goo.gl/VZGuC for more details. | 91 | // See http://goo.gl/VZGuC for more details. |
174 | 92 | type Error struct { | 92 | type Error struct { |
175 | @@ -425,15 +425,15 @@ | |||
176 | 425 | // | 425 | // |
177 | 426 | // See http://goo.gl/wnDBf for more details. | 426 | // See http://goo.gl/wnDBf for more details. |
178 | 427 | type BlockDeviceMapping struct { | 427 | type BlockDeviceMapping struct { |
185 | 428 | DeviceName string `xml:"deviceName"` | 428 | DeviceName string `xml:"deviceName"` |
186 | 429 | VirtualName string `xml:"virtualName"` | 429 | VirtualName string `xml:"virtualName"` |
187 | 430 | SnapshotId string `xml:"ebs>snapshotId"` | 430 | SnapshotId string `xml:"ebs>snapshotId"` |
188 | 431 | VolumeType string `xml:"ebs>volumeType"` | 431 | VolumeType string `xml:"ebs>volumeType"` |
189 | 432 | VolumeSize int64 `xml:"ebs>volumeSize"` | 432 | VolumeSize int64 `xml:"ebs>volumeSize"` |
190 | 433 | DeleteOnTermination bool `xml:"ebs>deleteOnTermination"` | 433 | DeleteOnTermination bool `xml:"ebs>deleteOnTermination"` |
191 | 434 | 434 | ||
192 | 435 | // The number of I/O operations per second (IOPS) that the volume supports. | 435 | // The number of I/O operations per second (IOPS) that the volume supports. |
194 | 436 | IOPS int64 `xml:"ebs>iops"` | 436 | IOPS int64 `xml:"ebs>iops"` |
195 | 437 | } | 437 | } |
196 | 438 | 438 | ||
197 | 439 | // Image represents details about an image. | 439 | // Image represents details about an image. |
198 | @@ -467,7 +467,7 @@ | |||
199 | 467 | // For example, to get all the private images associated with this account set | 467 | // For example, to get all the private images associated with this account set |
200 | 468 | // the boolean filter "is-private" to true. | 468 | // the boolean filter "is-private" to true. |
201 | 469 | // | 469 | // |
203 | 470 | // Note: calling this function with nil ids and filter parameters will result in | 470 | // Note: calling this function with nil ids and filter parameters will result in |
204 | 471 | // a very large number of images being returned. | 471 | // a very large number of images being returned. |
205 | 472 | // | 472 | // |
206 | 473 | // See http://goo.gl/SRBhW for more details. | 473 | // See http://goo.gl/SRBhW for more details. |
207 | @@ -512,11 +512,11 @@ | |||
208 | 512 | 512 | ||
209 | 513 | // DeleteSnapshots deletes the volume snapshots with the given ids. | 513 | // DeleteSnapshots deletes the volume snapshots with the given ids. |
210 | 514 | // | 514 | // |
216 | 515 | // Note: If you make periodic snapshots of a volume, the snapshots are | 515 | // Note: If you make periodic snapshots of a volume, the snapshots are |
217 | 516 | // incremental so that only the blocks on the device that have changed | 516 | // incremental so that only the blocks on the device that have changed |
218 | 517 | // since your last snapshot are incrementally saved in the new snapshot. | 517 | // since your last snapshot are incrementally saved in the new snapshot. |
219 | 518 | // Even though snapshots are saved incrementally, the snapshot deletion | 518 | // Even though snapshots are saved incrementally, the snapshot deletion |
220 | 519 | // process is designed so that you need to retain only the most recent | 519 | // process is designed so that you need to retain only the most recent |
221 | 520 | // snapshot in order to restore the volume. | 520 | // snapshot in order to restore the volume. |
222 | 521 | // | 521 | // |
223 | 522 | // See http://goo.gl/vwU1y for more details. | 522 | // See http://goo.gl/vwU1y for more details. |
224 | @@ -558,7 +558,7 @@ | |||
225 | 558 | Tags []Tag `xml:"tagSet>item"` | 558 | Tags []Tag `xml:"tagSet>item"` |
226 | 559 | } | 559 | } |
227 | 560 | 560 | ||
229 | 561 | // Snapshots returns details about volume snapshots available to the user. | 561 | // Snapshots returns details about volume snapshots available to the user. |
230 | 562 | // The ids and filter parameters, if provided, limit the snapshots returned. | 562 | // The ids and filter parameters, if provided, limit the snapshots returned. |
231 | 563 | // | 563 | // |
232 | 564 | // See http://goo.gl/ogJL4 for more details. | 564 | // See http://goo.gl/ogJL4 for more details. |
233 | @@ -620,7 +620,7 @@ | |||
234 | 620 | Groups []SecurityGroupInfo `xml:"securityGroupInfo>item"` | 620 | Groups []SecurityGroupInfo `xml:"securityGroupInfo>item"` |
235 | 621 | } | 621 | } |
236 | 622 | 622 | ||
238 | 623 | // SecurityGroup encapsulates details for a security group in EC2. | 623 | // SecurityGroup encapsulates details for a security group in EC2. |
239 | 624 | // | 624 | // |
240 | 625 | // See http://goo.gl/CIdyP for more details. | 625 | // See http://goo.gl/CIdyP for more details. |
241 | 626 | type SecurityGroupInfo struct { | 626 | type SecurityGroupInfo struct { |
242 | @@ -785,7 +785,7 @@ | |||
243 | 785 | } | 785 | } |
244 | 786 | 786 | ||
245 | 787 | // CreateTags adds or overwrites one or more tags for the specified instance ids. | 787 | // CreateTags adds or overwrites one or more tags for the specified instance ids. |
247 | 788 | // | 788 | // |
248 | 789 | // See http://goo.gl/Vmkqc for more details | 789 | // See http://goo.gl/Vmkqc for more details |
249 | 790 | func (ec2 *EC2) CreateTags(instIds []string, tags []Tag) (resp *SimpleResp, err error) { | 790 | func (ec2 *EC2) CreateTags(instIds []string, tags []Tag) (resp *SimpleResp, err error) { |
250 | 791 | params := makeParams("CreateTags") | 791 | params := makeParams("CreateTags") |
251 | 792 | 792 | ||
252 | === modified file 'ec2/ec2_test.go' | |||
253 | --- ec2/ec2_test.go 2012-10-18 18:56:09 +0000 | |||
254 | +++ ec2/ec2_test.go 2013-01-31 17:09:20 +0000 | |||
255 | @@ -3,24 +3,35 @@ | |||
256 | 3 | import ( | 3 | import ( |
257 | 4 | "launchpad.net/goamz/aws" | 4 | "launchpad.net/goamz/aws" |
258 | 5 | "launchpad.net/goamz/ec2" | 5 | "launchpad.net/goamz/ec2" |
259 | 6 | "launchpad.net/goamz/testutil" | ||
260 | 6 | . "launchpad.net/gocheck" | 7 | . "launchpad.net/gocheck" |
261 | 8 | "testing" | ||
262 | 7 | ) | 9 | ) |
263 | 8 | 10 | ||
264 | 11 | func Test(t *testing.T) { | ||
265 | 12 | TestingT(t) | ||
266 | 13 | } | ||
267 | 14 | |||
268 | 9 | var _ = Suite(&S{}) | 15 | var _ = Suite(&S{}) |
269 | 10 | 16 | ||
270 | 11 | type S struct { | 17 | type S struct { |
271 | 12 | HTTPSuite | ||
272 | 13 | ec2 *ec2.EC2 | 18 | ec2 *ec2.EC2 |
273 | 14 | } | 19 | } |
274 | 15 | 20 | ||
275 | 21 | var testServer = testutil.NewHTTPServer() | ||
276 | 22 | |||
277 | 16 | func (s *S) SetUpSuite(c *C) { | 23 | func (s *S) SetUpSuite(c *C) { |
279 | 17 | s.HTTPSuite.SetUpSuite(c) | 24 | testServer.Start() |
280 | 18 | auth := aws.Auth{"abc", "123"} | 25 | auth := aws.Auth{"abc", "123"} |
281 | 19 | s.ec2 = ec2.New(auth, aws.Region{EC2Endpoint: testServer.URL}) | 26 | s.ec2 = ec2.New(auth, aws.Region{EC2Endpoint: testServer.URL}) |
282 | 20 | } | 27 | } |
283 | 21 | 28 | ||
284 | 29 | func (s *S) TearDownTest(c *C) { | ||
285 | 30 | testServer.Flush() | ||
286 | 31 | } | ||
287 | 32 | |||
288 | 22 | func (s *S) TestRunInstancesErrorDump(c *C) { | 33 | func (s *S) TestRunInstancesErrorDump(c *C) { |
290 | 23 | testServer.PrepareResponse(400, nil, ErrorDump) | 34 | testServer.Response(400, nil, ErrorDump) |
291 | 24 | 35 | ||
292 | 25 | options := ec2.RunInstances{ | 36 | options := ec2.RunInstances{ |
293 | 26 | ImageId: "ami-a6f504cf", // Ubuntu Maverick, i386, instance store | 37 | ImageId: "ami-a6f504cf", // Ubuntu Maverick, i386, instance store |
294 | @@ -45,7 +56,7 @@ | |||
295 | 45 | } | 56 | } |
296 | 46 | 57 | ||
297 | 47 | func (s *S) TestRunInstancesErrorWithoutXML(c *C) { | 58 | func (s *S) TestRunInstancesErrorWithoutXML(c *C) { |
299 | 48 | testServer.PrepareResponse(500, nil, "") | 59 | testServer.Response(500, nil, "") |
300 | 49 | options := ec2.RunInstances{ImageId: "image-id"} | 60 | options := ec2.RunInstances{ImageId: "image-id"} |
301 | 50 | 61 | ||
302 | 51 | resp, err := s.ec2.RunInstances(&options) | 62 | resp, err := s.ec2.RunInstances(&options) |
303 | @@ -64,7 +75,7 @@ | |||
304 | 64 | } | 75 | } |
305 | 65 | 76 | ||
306 | 66 | func (s *S) TestRunInstancesExample(c *C) { | 77 | func (s *S) TestRunInstancesExample(c *C) { |
308 | 67 | testServer.PrepareResponse(200, nil, RunInstancesExample) | 78 | testServer.Response(200, nil, RunInstancesExample) |
309 | 68 | 79 | ||
310 | 69 | options := ec2.RunInstances{ | 80 | options := ec2.RunInstances{ |
311 | 70 | KeyName: "my-keys", | 81 | KeyName: "my-keys", |
312 | @@ -145,7 +156,7 @@ | |||
313 | 145 | } | 156 | } |
314 | 146 | 157 | ||
315 | 147 | func (s *S) TestTerminateInstancesExample(c *C) { | 158 | func (s *S) TestTerminateInstancesExample(c *C) { |
317 | 148 | testServer.PrepareResponse(200, nil, TerminateInstancesExample) | 159 | testServer.Response(200, nil, TerminateInstancesExample) |
318 | 149 | 160 | ||
319 | 150 | resp, err := s.ec2.TerminateInstances([]string{"i-1", "i-2"}) | 161 | resp, err := s.ec2.TerminateInstances([]string{"i-1", "i-2"}) |
320 | 151 | 162 | ||
321 | @@ -175,7 +186,7 @@ | |||
322 | 175 | } | 186 | } |
323 | 176 | 187 | ||
324 | 177 | func (s *S) TestDescribeInstancesExample1(c *C) { | 188 | func (s *S) TestDescribeInstancesExample1(c *C) { |
326 | 178 | testServer.PrepareResponse(200, nil, DescribeInstancesExample1) | 189 | testServer.Response(200, nil, DescribeInstancesExample1) |
327 | 179 | 190 | ||
328 | 180 | filter := ec2.NewFilter() | 191 | filter := ec2.NewFilter() |
329 | 181 | filter.Add("key1", "value1") | 192 | filter.Add("key1", "value1") |
330 | @@ -207,7 +218,7 @@ | |||
331 | 207 | } | 218 | } |
332 | 208 | 219 | ||
333 | 209 | func (s *S) TestDescribeInstancesExample2(c *C) { | 220 | func (s *S) TestDescribeInstancesExample2(c *C) { |
335 | 210 | testServer.PrepareResponse(200, nil, DescribeInstancesExample2) | 221 | testServer.Response(200, nil, DescribeInstancesExample2) |
336 | 211 | 222 | ||
337 | 212 | filter := ec2.NewFilter() | 223 | filter := ec2.NewFilter() |
338 | 213 | filter.Add("key1", "value1") | 224 | filter.Add("key1", "value1") |
339 | @@ -244,7 +255,7 @@ | |||
340 | 244 | } | 255 | } |
341 | 245 | 256 | ||
342 | 246 | func (s *S) TestDescribeImagesExample(c *C) { | 257 | func (s *S) TestDescribeImagesExample(c *C) { |
344 | 247 | testServer.PrepareResponse(200, nil, DescribeImagesExample) | 258 | testServer.Response(200, nil, DescribeImagesExample) |
345 | 248 | 259 | ||
346 | 249 | filter := ec2.NewFilter() | 260 | filter := ec2.NewFilter() |
347 | 250 | filter.Add("key1", "value1") | 261 | filter.Add("key1", "value1") |
348 | @@ -292,7 +303,7 @@ | |||
349 | 292 | } | 303 | } |
350 | 293 | 304 | ||
351 | 294 | func (s *S) TestCreateSnapshotExample(c *C) { | 305 | func (s *S) TestCreateSnapshotExample(c *C) { |
353 | 295 | testServer.PrepareResponse(200, nil, CreateSnapshotExample) | 306 | testServer.Response(200, nil, CreateSnapshotExample) |
354 | 296 | 307 | ||
355 | 297 | resp, err := s.ec2.CreateSnapshot("vol-4d826724", "Daily Backup") | 308 | resp, err := s.ec2.CreateSnapshot("vol-4d826724", "Daily Backup") |
356 | 298 | 309 | ||
357 | @@ -314,7 +325,7 @@ | |||
358 | 314 | } | 325 | } |
359 | 315 | 326 | ||
360 | 316 | func (s *S) TestDeleteSnapshotsExample(c *C) { | 327 | func (s *S) TestDeleteSnapshotsExample(c *C) { |
362 | 317 | testServer.PrepareResponse(200, nil, DeleteSnapshotExample) | 328 | testServer.Response(200, nil, DeleteSnapshotExample) |
363 | 318 | 329 | ||
364 | 319 | resp, err := s.ec2.DeleteSnapshots([]string{"snap-78a54011"}) | 330 | resp, err := s.ec2.DeleteSnapshots([]string{"snap-78a54011"}) |
365 | 320 | 331 | ||
366 | @@ -327,7 +338,7 @@ | |||
367 | 327 | } | 338 | } |
368 | 328 | 339 | ||
369 | 329 | func (s *S) TestDescribeSnapshotsExample(c *C) { | 340 | func (s *S) TestDescribeSnapshotsExample(c *C) { |
371 | 330 | testServer.PrepareResponse(200, nil, DescribeSnapshotsExample) | 341 | testServer.Response(200, nil, DescribeSnapshotsExample) |
372 | 331 | 342 | ||
373 | 332 | filter := ec2.NewFilter() | 343 | filter := ec2.NewFilter() |
374 | 333 | filter.Add("key1", "value1") | 344 | filter.Add("key1", "value1") |
375 | @@ -366,7 +377,7 @@ | |||
376 | 366 | } | 377 | } |
377 | 367 | 378 | ||
378 | 368 | func (s *S) TestCreateSecurityGroupExample(c *C) { | 379 | func (s *S) TestCreateSecurityGroupExample(c *C) { |
380 | 369 | testServer.PrepareResponse(200, nil, CreateSecurityGroupExample) | 380 | testServer.Response(200, nil, CreateSecurityGroupExample) |
381 | 370 | 381 | ||
382 | 371 | resp, err := s.ec2.CreateSecurityGroup("websrv", "Web Servers") | 382 | resp, err := s.ec2.CreateSecurityGroup("websrv", "Web Servers") |
383 | 372 | 383 | ||
384 | @@ -382,7 +393,7 @@ | |||
385 | 382 | } | 393 | } |
386 | 383 | 394 | ||
387 | 384 | func (s *S) TestDescribeSecurityGroupsExample(c *C) { | 395 | func (s *S) TestDescribeSecurityGroupsExample(c *C) { |
389 | 385 | testServer.PrepareResponse(200, nil, DescribeSecurityGroupsExample) | 396 | testServer.Response(200, nil, DescribeSecurityGroupsExample) |
390 | 386 | 397 | ||
391 | 387 | resp, err := s.ec2.SecurityGroups([]ec2.SecurityGroup{{Name: "WebServers"}, {Name: "RangedPortsBySource"}}, nil) | 398 | resp, err := s.ec2.SecurityGroups([]ec2.SecurityGroup{{Name: "WebServers"}, {Name: "RangedPortsBySource"}}, nil) |
392 | 388 | 399 | ||
393 | @@ -423,7 +434,7 @@ | |||
394 | 423 | } | 434 | } |
395 | 424 | 435 | ||
396 | 425 | func (s *S) TestDescribeSecurityGroupsExampleWithFilter(c *C) { | 436 | func (s *S) TestDescribeSecurityGroupsExampleWithFilter(c *C) { |
398 | 426 | testServer.PrepareResponse(200, nil, DescribeSecurityGroupsExample) | 437 | testServer.Response(200, nil, DescribeSecurityGroupsExample) |
399 | 427 | 438 | ||
400 | 428 | filter := ec2.NewFilter() | 439 | filter := ec2.NewFilter() |
401 | 429 | filter.Add("ip-permission.protocol", "tcp") | 440 | filter.Add("ip-permission.protocol", "tcp") |
402 | @@ -449,7 +460,7 @@ | |||
403 | 449 | } | 460 | } |
404 | 450 | 461 | ||
405 | 451 | func (s *S) TestDescribeSecurityGroupsDumpWithGroup(c *C) { | 462 | func (s *S) TestDescribeSecurityGroupsDumpWithGroup(c *C) { |
407 | 452 | testServer.PrepareResponse(200, nil, DescribeSecurityGroupsDump) | 463 | testServer.Response(200, nil, DescribeSecurityGroupsDump) |
408 | 453 | 464 | ||
409 | 454 | resp, err := s.ec2.SecurityGroups(nil, nil) | 465 | resp, err := s.ec2.SecurityGroups(nil, nil) |
410 | 455 | 466 | ||
411 | @@ -477,7 +488,7 @@ | |||
412 | 477 | } | 488 | } |
413 | 478 | 489 | ||
414 | 479 | func (s *S) TestDeleteSecurityGroupExample(c *C) { | 490 | func (s *S) TestDeleteSecurityGroupExample(c *C) { |
416 | 480 | testServer.PrepareResponse(200, nil, DeleteSecurityGroupExample) | 491 | testServer.Response(200, nil, DeleteSecurityGroupExample) |
417 | 481 | 492 | ||
418 | 482 | resp, err := s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: "websrv"}) | 493 | resp, err := s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Name: "websrv"}) |
419 | 483 | req := testServer.WaitRequest() | 494 | req := testServer.WaitRequest() |
420 | @@ -490,7 +501,7 @@ | |||
421 | 490 | } | 501 | } |
422 | 491 | 502 | ||
423 | 492 | func (s *S) TestDeleteSecurityGroupExampleWithId(c *C) { | 503 | func (s *S) TestDeleteSecurityGroupExampleWithId(c *C) { |
425 | 493 | testServer.PrepareResponse(200, nil, DeleteSecurityGroupExample) | 504 | testServer.Response(200, nil, DeleteSecurityGroupExample) |
426 | 494 | 505 | ||
427 | 495 | // ignore return and error - we're only want to check the parameter handling. | 506 | // ignore return and error - we're only want to check the parameter handling. |
428 | 496 | s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Id: "sg-67ad940e", Name: "ignored"}) | 507 | s.ec2.DeleteSecurityGroup(ec2.SecurityGroup{Id: "sg-67ad940e", Name: "ignored"}) |
429 | @@ -501,7 +512,7 @@ | |||
430 | 501 | } | 512 | } |
431 | 502 | 513 | ||
432 | 503 | func (s *S) TestAuthorizeSecurityGroupExample1(c *C) { | 514 | func (s *S) TestAuthorizeSecurityGroupExample1(c *C) { |
434 | 504 | testServer.PrepareResponse(200, nil, AuthorizeSecurityGroupIngressExample) | 515 | testServer.Response(200, nil, AuthorizeSecurityGroupIngressExample) |
435 | 505 | 516 | ||
436 | 506 | perms := []ec2.IPPerm{{ | 517 | perms := []ec2.IPPerm{{ |
437 | 507 | Protocol: "tcp", | 518 | Protocol: "tcp", |
438 | @@ -526,7 +537,7 @@ | |||
439 | 526 | } | 537 | } |
440 | 527 | 538 | ||
441 | 528 | func (s *S) TestAuthorizeSecurityGroupExample1WithId(c *C) { | 539 | func (s *S) TestAuthorizeSecurityGroupExample1WithId(c *C) { |
443 | 529 | testServer.PrepareResponse(200, nil, AuthorizeSecurityGroupIngressExample) | 540 | testServer.Response(200, nil, AuthorizeSecurityGroupIngressExample) |
444 | 530 | 541 | ||
445 | 531 | perms := []ec2.IPPerm{{ | 542 | perms := []ec2.IPPerm{{ |
446 | 532 | Protocol: "tcp", | 543 | Protocol: "tcp", |
447 | @@ -544,7 +555,7 @@ | |||
448 | 544 | } | 555 | } |
449 | 545 | 556 | ||
450 | 546 | func (s *S) TestAuthorizeSecurityGroupExample2(c *C) { | 557 | func (s *S) TestAuthorizeSecurityGroupExample2(c *C) { |
452 | 547 | testServer.PrepareResponse(200, nil, AuthorizeSecurityGroupIngressExample) | 558 | testServer.Response(200, nil, AuthorizeSecurityGroupIngressExample) |
453 | 548 | 559 | ||
454 | 549 | perms := []ec2.IPPerm{{ | 560 | perms := []ec2.IPPerm{{ |
455 | 550 | Protocol: "tcp", | 561 | Protocol: "tcp", |
456 | @@ -577,7 +588,7 @@ | |||
457 | 577 | func (s *S) TestRevokeSecurityGroupExample(c *C) { | 588 | func (s *S) TestRevokeSecurityGroupExample(c *C) { |
458 | 578 | // RevokeSecurityGroup is implemented by the same code as AuthorizeSecurityGroup | 589 | // RevokeSecurityGroup is implemented by the same code as AuthorizeSecurityGroup |
459 | 579 | // so there's no need to duplicate all the tests. | 590 | // so there's no need to duplicate all the tests. |
461 | 580 | testServer.PrepareResponse(200, nil, RevokeSecurityGroupIngressExample) | 591 | testServer.Response(200, nil, RevokeSecurityGroupIngressExample) |
462 | 581 | 592 | ||
463 | 582 | resp, err := s.ec2.RevokeSecurityGroup(ec2.SecurityGroup{Name: "websrv"}, nil) | 593 | resp, err := s.ec2.RevokeSecurityGroup(ec2.SecurityGroup{Name: "websrv"}, nil) |
464 | 583 | 594 | ||
465 | @@ -590,7 +601,7 @@ | |||
466 | 590 | } | 601 | } |
467 | 591 | 602 | ||
468 | 592 | func (s *S) TestCreateTags(c *C) { | 603 | func (s *S) TestCreateTags(c *C) { |
470 | 593 | testServer.PrepareResponse(200, nil, CreateTagsExample) | 604 | testServer.Response(200, nil, CreateTagsExample) |
471 | 594 | 605 | ||
472 | 595 | resp, err := s.ec2.CreateTags([]string{"ami-1a2b3c4d", "i-7f4d3a2b"}, []ec2.Tag{{"webserver", ""}, {"stack", "Production"}}) | 606 | resp, err := s.ec2.CreateTags([]string{"ami-1a2b3c4d", "i-7f4d3a2b"}, []ec2.Tag{{"webserver", ""}, {"stack", "Production"}}) |
473 | 596 | 607 | ||
474 | @@ -607,7 +618,7 @@ | |||
475 | 607 | } | 618 | } |
476 | 608 | 619 | ||
477 | 609 | func (s *S) TestStartInstances(c *C) { | 620 | func (s *S) TestStartInstances(c *C) { |
479 | 610 | testServer.PrepareResponse(200, nil, StartInstancesExample) | 621 | testServer.Response(200, nil, StartInstancesExample) |
480 | 611 | 622 | ||
481 | 612 | resp, err := s.ec2.StartInstances("i-10a64379") | 623 | resp, err := s.ec2.StartInstances("i-10a64379") |
482 | 613 | req := testServer.WaitRequest() | 624 | req := testServer.WaitRequest() |
483 | @@ -627,7 +638,7 @@ | |||
484 | 627 | } | 638 | } |
485 | 628 | 639 | ||
486 | 629 | func (s *S) TestStopInstances(c *C) { | 640 | func (s *S) TestStopInstances(c *C) { |
488 | 630 | testServer.PrepareResponse(200, nil, StopInstancesExample) | 641 | testServer.Response(200, nil, StopInstancesExample) |
489 | 631 | 642 | ||
490 | 632 | resp, err := s.ec2.StopInstances("i-10a64379") | 643 | resp, err := s.ec2.StopInstances("i-10a64379") |
491 | 633 | req := testServer.WaitRequest() | 644 | req := testServer.WaitRequest() |
492 | @@ -647,7 +658,7 @@ | |||
493 | 647 | } | 658 | } |
494 | 648 | 659 | ||
495 | 649 | func (s *S) TestRebootInstances(c *C) { | 660 | func (s *S) TestRebootInstances(c *C) { |
497 | 650 | testServer.PrepareResponse(200, nil, RebootInstancesExample) | 661 | testServer.Response(200, nil, RebootInstancesExample) |
498 | 651 | 662 | ||
499 | 652 | resp, err := s.ec2.RebootInstances("i-10a64379") | 663 | resp, err := s.ec2.RebootInstances("i-10a64379") |
500 | 653 | req := testServer.WaitRequest() | 664 | req := testServer.WaitRequest() |
501 | @@ -663,7 +674,7 @@ | |||
502 | 663 | ec2.FakeTime(true) | 674 | ec2.FakeTime(true) |
503 | 664 | defer ec2.FakeTime(false) | 675 | defer ec2.FakeTime(false) |
504 | 665 | 676 | ||
506 | 666 | testServer.PrepareResponse(200, nil, RebootInstancesExample) | 677 | testServer.Response(200, nil, RebootInstancesExample) |
507 | 667 | 678 | ||
508 | 668 | // https://bugs.launchpad.net/goamz/+bug/1022749 | 679 | // https://bugs.launchpad.net/goamz/+bug/1022749 |
509 | 669 | ec2 := ec2.New(s.ec2.Auth, aws.Region{EC2Endpoint: testServer.URL + "/services/Cloud"}) | 680 | ec2 := ec2.New(s.ec2.Auth, aws.Region{EC2Endpoint: testServer.URL + "/services/Cloud"}) |
510 | 670 | 681 | ||
511 | === modified file 'ec2/ec2i_test.go' | |||
512 | --- ec2/ec2i_test.go 2012-10-28 16:05:46 +0000 | |||
513 | +++ ec2/ec2i_test.go 2013-01-31 17:09:20 +0000 | |||
514 | @@ -2,15 +2,13 @@ | |||
515 | 2 | 2 | ||
516 | 3 | import ( | 3 | import ( |
517 | 4 | "crypto/rand" | 4 | "crypto/rand" |
518 | 5 | "flag" | ||
519 | 6 | "fmt" | 5 | "fmt" |
520 | 7 | "launchpad.net/goamz/aws" | 6 | "launchpad.net/goamz/aws" |
521 | 8 | "launchpad.net/goamz/ec2" | 7 | "launchpad.net/goamz/ec2" |
522 | 8 | "launchpad.net/goamz/testutil" | ||
523 | 9 | . "launchpad.net/gocheck" | 9 | . "launchpad.net/gocheck" |
524 | 10 | ) | 10 | ) |
525 | 11 | 11 | ||
526 | 12 | var amazon = flag.Bool("amazon", false, "Enable tests against amazon server") | ||
527 | 13 | |||
528 | 14 | // AmazonServer represents an Amazon EC2 server. | 12 | // AmazonServer represents an Amazon EC2 server. |
529 | 15 | type AmazonServer struct { | 13 | type AmazonServer struct { |
530 | 16 | auth aws.Auth | 14 | auth aws.Auth |
531 | @@ -34,7 +32,7 @@ | |||
532 | 34 | } | 32 | } |
533 | 35 | 33 | ||
534 | 36 | func (s *AmazonClientSuite) SetUpSuite(c *C) { | 34 | func (s *AmazonClientSuite) SetUpSuite(c *C) { |
536 | 37 | if !*amazon { | 35 | if !testutil.Amazon { |
537 | 38 | c.Skip("AmazonClientSuite tests not enabled") | 36 | c.Skip("AmazonClientSuite tests not enabled") |
538 | 39 | } | 37 | } |
539 | 40 | s.srv.SetUp(c) | 38 | s.srv.SetUp(c) |
540 | 41 | 39 | ||
541 | === modified file 'ec2/ec2t_test.go' | |||
542 | --- ec2/ec2t_test.go 2012-10-28 16:05:46 +0000 | |||
543 | +++ ec2/ec2t_test.go 2013-01-31 17:09:20 +0000 | |||
544 | @@ -5,6 +5,7 @@ | |||
545 | 5 | "launchpad.net/goamz/aws" | 5 | "launchpad.net/goamz/aws" |
546 | 6 | "launchpad.net/goamz/ec2" | 6 | "launchpad.net/goamz/ec2" |
547 | 7 | "launchpad.net/goamz/ec2/ec2test" | 7 | "launchpad.net/goamz/ec2/ec2test" |
548 | 8 | "launchpad.net/goamz/testutil" | ||
549 | 8 | . "launchpad.net/gocheck" | 9 | . "launchpad.net/gocheck" |
550 | 9 | "regexp" | 10 | "regexp" |
551 | 10 | "sort" | 11 | "sort" |
552 | @@ -88,7 +89,7 @@ | |||
553 | 88 | var _ = Suite(&AmazonServerSuite{}) | 89 | var _ = Suite(&AmazonServerSuite{}) |
554 | 89 | 90 | ||
555 | 90 | func (s *AmazonServerSuite) SetUpSuite(c *C) { | 91 | func (s *AmazonServerSuite) SetUpSuite(c *C) { |
557 | 91 | if !*amazon { | 92 | if !testutil.Amazon { |
558 | 92 | c.Skip("AmazonServerSuite tests not enabled") | 93 | c.Skip("AmazonServerSuite tests not enabled") |
559 | 93 | } | 94 | } |
560 | 94 | s.srv.SetUp(c) | 95 | s.srv.SetUp(c) |
561 | @@ -435,17 +436,13 @@ | |||
562 | 435 | 436 | ||
563 | 436 | func (s *ServerTests) TestGroupFiltering(c *C) { | 437 | func (s *ServerTests) TestGroupFiltering(c *C) { |
564 | 437 | g := make([]ec2.SecurityGroup, 4) | 438 | g := make([]ec2.SecurityGroup, 4) |
566 | 438 | for i := range g[0:3] { | 439 | for i := range g { |
567 | 439 | resp, err := s.ec2.CreateSecurityGroup(sessionName(fmt.Sprintf("testgroup%d", i)), fmt.Sprintf("testdescription%d", i)) | 440 | resp, err := s.ec2.CreateSecurityGroup(sessionName(fmt.Sprintf("testgroup%d", i)), fmt.Sprintf("testdescription%d", i)) |
568 | 440 | c.Assert(err, IsNil) | 441 | c.Assert(err, IsNil) |
569 | 441 | g[i] = resp.SecurityGroup | 442 | g[i] = resp.SecurityGroup |
570 | 442 | c.Logf("group %d: %v", i, g[i]) | 443 | c.Logf("group %d: %v", i, g[i]) |
571 | 443 | defer s.ec2.DeleteSecurityGroup(g[i]) | 444 | defer s.ec2.DeleteSecurityGroup(g[i]) |
572 | 444 | } | 445 | } |
573 | 445 | // Get the default group. | ||
574 | 446 | resp, err := s.ec2.SecurityGroups([]ec2.SecurityGroup{{Name: "default"}}, nil) | ||
575 | 447 | c.Assert(err, IsNil) | ||
576 | 448 | g[3] = resp.Groups[0].SecurityGroup | ||
577 | 449 | 446 | ||
578 | 450 | perms := [][]ec2.IPPerm{ | 447 | perms := [][]ec2.IPPerm{ |
579 | 451 | {{ | 448 | {{ |
580 | @@ -536,7 +533,7 @@ | |||
581 | 536 | filterCheck("group-name", g[2].Name, groups(2)), | 533 | filterCheck("group-name", g[2].Name, groups(2)), |
582 | 537 | filterCheck("ip-permission.cidr", "1.2.3.4/32", groups(0)), | 534 | filterCheck("ip-permission.cidr", "1.2.3.4/32", groups(0)), |
583 | 538 | filterCheck("ip-permission.group-name", g[1].Name, groups(1, 2)), | 535 | filterCheck("ip-permission.group-name", g[1].Name, groups(1, 2)), |
585 | 539 | filterCheck("ip-permission.protocol", "udp", groups(2, 3)), | 536 | filterCheck("ip-permission.protocol", "udp", groups(2)), |
586 | 540 | filterCheck("ip-permission.from-port", "200", groups(1, 2)), | 537 | filterCheck("ip-permission.from-port", "200", groups(1, 2)), |
587 | 541 | filterCheck("ip-permission.to-port", "200", groups(0)), | 538 | filterCheck("ip-permission.to-port", "200", groups(0)), |
588 | 542 | // TODO owner-id | 539 | // TODO owner-id |
589 | @@ -568,7 +565,7 @@ | |||
590 | 568 | if t.allowExtra { | 565 | if t.allowExtra { |
591 | 569 | namePat := regexp.MustCompile(sessionName("testgroup[0-9]")) | 566 | namePat := regexp.MustCompile(sessionName("testgroup[0-9]")) |
592 | 570 | for id, g := range groups { | 567 | for id, g := range groups { |
594 | 571 | if g.Name != "default" && !namePat.MatchString(g.Name) { | 568 | if !namePat.MatchString(g.Name) { |
595 | 572 | delete(groups, id) | 569 | delete(groups, id) |
596 | 573 | } | 570 | } |
597 | 574 | } | 571 | } |
598 | 575 | 572 | ||
599 | === modified file 'ec2/ec2test/filter.go' | |||
600 | --- ec2/ec2test/filter.go 2012-03-09 14:02:34 +0000 | |||
601 | +++ ec2/ec2test/filter.go 2013-01-31 17:09:20 +0000 | |||
602 | @@ -13,13 +13,13 @@ | |||
603 | 13 | type filter map[string][]string | 13 | type filter map[string][]string |
604 | 14 | 14 | ||
605 | 15 | // newFilter creates a new filter from the Filter fields in the url form. | 15 | // newFilter creates a new filter from the Filter fields in the url form. |
607 | 16 | // | 16 | // |
608 | 17 | // The filtering is specified through a map of name=>values, where the | 17 | // The filtering is specified through a map of name=>values, where the |
609 | 18 | // name is a well-defined key identifying the data to be matched, | 18 | // name is a well-defined key identifying the data to be matched, |
610 | 19 | // and the list of values holds the possible values the filtered | 19 | // and the list of values holds the possible values the filtered |
611 | 20 | // item can take for the key to be included in the | 20 | // item can take for the key to be included in the |
612 | 21 | // result set. For example: | 21 | // result set. For example: |
614 | 22 | // | 22 | // |
615 | 23 | // Filter.1.Name=instance-type | 23 | // Filter.1.Name=instance-type |
616 | 24 | // Filter.1.Value.1=m1.small | 24 | // Filter.1.Value.1=m1.small |
617 | 25 | // Filter.1.Value.2=m1.large | 25 | // Filter.1.Value.2=m1.large |
618 | 26 | 26 | ||
619 | === modified file 'ec2/ec2test/server.go' | |||
620 | --- ec2/ec2test/server.go 2012-09-11 14:10:43 +0000 | |||
621 | +++ ec2/ec2test/server.go 2013-01-31 17:09:20 +0000 | |||
622 | @@ -417,18 +417,18 @@ | |||
623 | 417 | } | 417 | } |
624 | 418 | 418 | ||
625 | 419 | // TODO attributes still to consider: | 419 | // TODO attributes still to consider: |
638 | 420 | // ImageId: accept anything, we can verify later | 420 | // ImageId: accept anything, we can verify later |
639 | 421 | // KeyName ? | 421 | // KeyName ? |
640 | 422 | // InstanceType ? | 422 | // InstanceType ? |
641 | 423 | // KernelId ? | 423 | // KernelId ? |
642 | 424 | // RamdiskId ? | 424 | // RamdiskId ? |
643 | 425 | // AvailZone ? | 425 | // AvailZone ? |
644 | 426 | // GroupName tag | 426 | // GroupName tag |
645 | 427 | // Monitoring ignore? | 427 | // Monitoring ignore? |
646 | 428 | // SubnetId ? | 428 | // SubnetId ? |
647 | 429 | // DisableAPITermination bool | 429 | // DisableAPITermination bool |
648 | 430 | // ShutdownBehavior string | 430 | // ShutdownBehavior string |
649 | 431 | // PrivateIPAddress string | 431 | // PrivateIPAddress string |
650 | 432 | 432 | ||
651 | 433 | srv.mu.Lock() | 433 | srv.mu.Lock() |
652 | 434 | defer srv.mu.Unlock() | 434 | defer srv.mu.Unlock() |
653 | 435 | 435 | ||
654 | === modified file 'ec2/sign.go' | |||
655 | --- ec2/sign.go 2012-10-28 16:04:45 +0000 | |||
656 | +++ ec2/sign.go 2013-01-31 17:09:20 +0000 | |||
657 | @@ -19,10 +19,10 @@ | |||
658 | 19 | params["SignatureVersion"] = "2" | 19 | params["SignatureVersion"] = "2" |
659 | 20 | params["SignatureMethod"] = "HmacSHA256" | 20 | params["SignatureMethod"] = "HmacSHA256" |
660 | 21 | 21 | ||
665 | 22 | // AWS specifies that the parameters in a signed request must | 22 | // AWS specifies that the parameters in a signed request must |
666 | 23 | // be in natural order of the keys. This is distinct from the | 23 | // be provided in the natural order of the keys. This is distinct |
667 | 24 | // natural order of the encoded value of key=value. Basically | 24 | // from the natural order of the encoded value of key=value. |
668 | 25 | // percent and equals affect the sorting order. | 25 | // Percent and equals affect the sorting order. |
669 | 26 | var keys, sarray []string | 26 | var keys, sarray []string |
670 | 27 | for k, _ := range params { | 27 | for k, _ := range params { |
671 | 28 | keys = append(keys, k) | 28 | keys = append(keys, k) |
672 | 29 | 29 | ||
673 | === removed file 'ec2/suite_test.go' | |||
674 | --- ec2/suite_test.go 2012-08-31 08:11:21 +0000 | |||
675 | +++ ec2/suite_test.go 1970-01-01 00:00:00 +0000 | |||
676 | @@ -1,118 +0,0 @@ | |||
677 | 1 | package ec2_test | ||
678 | 2 | |||
679 | 3 | import ( | ||
680 | 4 | "fmt" | ||
681 | 5 | . "launchpad.net/gocheck" | ||
682 | 6 | "net/http" | ||
683 | 7 | "net/url" | ||
684 | 8 | "os" | ||
685 | 9 | "testing" | ||
686 | 10 | "time" | ||
687 | 11 | ) | ||
688 | 12 | |||
689 | 13 | func Test(t *testing.T) { | ||
690 | 14 | TestingT(t) | ||
691 | 15 | } | ||
692 | 16 | |||
693 | 17 | type HTTPSuite struct{} | ||
694 | 18 | |||
695 | 19 | var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second) | ||
696 | 20 | |||
697 | 21 | func (s *HTTPSuite) SetUpSuite(c *C) { | ||
698 | 22 | testServer.Start() | ||
699 | 23 | } | ||
700 | 24 | |||
701 | 25 | func (s *HTTPSuite) TearDownTest(c *C) { | ||
702 | 26 | testServer.FlushRequests() | ||
703 | 27 | } | ||
704 | 28 | |||
705 | 29 | type TestHTTPServer struct { | ||
706 | 30 | URL string | ||
707 | 31 | Timeout time.Duration | ||
708 | 32 | started bool | ||
709 | 33 | request chan *http.Request | ||
710 | 34 | response chan *testResponse | ||
711 | 35 | pending chan bool | ||
712 | 36 | } | ||
713 | 37 | |||
714 | 38 | type testResponse struct { | ||
715 | 39 | Status int | ||
716 | 40 | Headers map[string]string | ||
717 | 41 | Body string | ||
718 | 42 | } | ||
719 | 43 | |||
720 | 44 | func NewTestHTTPServer(url string, timeout time.Duration) *TestHTTPServer { | ||
721 | 45 | return &TestHTTPServer{URL: url, Timeout: timeout} | ||
722 | 46 | } | ||
723 | 47 | |||
724 | 48 | func (s *TestHTTPServer) Start() { | ||
725 | 49 | if s.started { | ||
726 | 50 | return | ||
727 | 51 | } | ||
728 | 52 | s.started = true | ||
729 | 53 | |||
730 | 54 | s.request = make(chan *http.Request, 64) | ||
731 | 55 | s.response = make(chan *testResponse, 64) | ||
732 | 56 | s.pending = make(chan bool, 64) | ||
733 | 57 | |||
734 | 58 | url, _ := url.Parse(s.URL) | ||
735 | 59 | go http.ListenAndServe(url.Host, s) | ||
736 | 60 | |||
737 | 61 | s.PrepareResponse(202, nil, "Nothing.") | ||
738 | 62 | for { | ||
739 | 63 | // Wait for it to be up. | ||
740 | 64 | resp, err := http.Get(s.URL) | ||
741 | 65 | if err == nil && resp.StatusCode == 202 { | ||
742 | 66 | break | ||
743 | 67 | } | ||
744 | 68 | time.Sleep(1e8) | ||
745 | 69 | } | ||
746 | 70 | s.WaitRequest() // Consume dummy request. | ||
747 | 71 | } | ||
748 | 72 | |||
749 | 73 | // FlushRequests discards requests which were not yet consumed by WaitRequest. | ||
750 | 74 | func (s *TestHTTPServer) FlushRequests() { | ||
751 | 75 | for { | ||
752 | 76 | select { | ||
753 | 77 | case <-s.request: | ||
754 | 78 | default: | ||
755 | 79 | return | ||
756 | 80 | } | ||
757 | 81 | } | ||
758 | 82 | } | ||
759 | 83 | |||
760 | 84 | func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
761 | 85 | s.request <- req | ||
762 | 86 | var resp *testResponse | ||
763 | 87 | select { | ||
764 | 88 | case resp = <-s.response: | ||
765 | 89 | case <-time.After(s.Timeout): | ||
766 | 90 | fmt.Fprintf(os.Stderr, "ERROR: Timeout waiting for test to provide response\n") | ||
767 | 91 | resp = &testResponse{500, nil, ""} | ||
768 | 92 | } | ||
769 | 93 | if resp.Headers != nil { | ||
770 | 94 | h := w.Header() | ||
771 | 95 | for k, v := range resp.Headers { | ||
772 | 96 | h.Set(k, v) | ||
773 | 97 | } | ||
774 | 98 | } | ||
775 | 99 | if resp.Status != 0 { | ||
776 | 100 | w.WriteHeader(resp.Status) | ||
777 | 101 | } | ||
778 | 102 | w.Write([]byte(resp.Body)) | ||
779 | 103 | } | ||
780 | 104 | |||
781 | 105 | func (s *TestHTTPServer) WaitRequest() *http.Request { | ||
782 | 106 | select { | ||
783 | 107 | case req := <-s.request: | ||
784 | 108 | req.ParseForm() | ||
785 | 109 | return req | ||
786 | 110 | case <-time.After(s.Timeout): | ||
787 | 111 | panic("Timeout waiting for goamz request") | ||
788 | 112 | } | ||
789 | 113 | panic("unreached") | ||
790 | 114 | } | ||
791 | 115 | |||
792 | 116 | func (s *TestHTTPServer) PrepareResponse(status int, headers map[string]string, body string) { | ||
793 | 117 | s.response <- &testResponse{status, headers, body} | ||
794 | 118 | } | ||
795 | 119 | 0 | ||
796 | === modified file 'exp/mturk/mturk.go' | |||
797 | --- exp/mturk/mturk.go 2012-05-03 17:12:28 +0000 | |||
798 | +++ exp/mturk/mturk.go 2013-01-31 17:09:20 +0000 | |||
799 | @@ -43,7 +43,7 @@ | |||
800 | 43 | // ---------------------------------------------------------------------------- | 43 | // ---------------------------------------------------------------------------- |
801 | 44 | // Request dispatching logic. | 44 | // Request dispatching logic. |
802 | 45 | 45 | ||
804 | 46 | // Error encapsulates an error returned by MTurk. | 46 | // Error encapsulates an error returned by MTurk. |
805 | 47 | type Error struct { | 47 | type Error struct { |
806 | 48 | StatusCode int // HTTP status code (200, 403, ...) | 48 | StatusCode int // HTTP status code (200, 403, ...) |
807 | 49 | Code string // EC2 error code ("UnsupportedOperation", ...) | 49 | Code string // EC2 error code ("UnsupportedOperation", ...) |
808 | @@ -150,7 +150,7 @@ | |||
809 | 150 | // Corresponds to the "CreateHIT" operation of the Mechanical Turk | 150 | // Corresponds to the "CreateHIT" operation of the Mechanical Turk |
810 | 151 | // API. http://goo.gl/cDBRc Currently only supports "external" | 151 | // API. http://goo.gl/cDBRc Currently only supports "external" |
811 | 152 | // questions (see "HIT" struct above). If "keywords", "maxAssignments", | 152 | // questions (see "HIT" struct above). If "keywords", "maxAssignments", |
813 | 153 | // "qualificationRequirement" or "requesterAnnotation" are the zero | 153 | // "qualificationRequirement" or "requesterAnnotation" are the zero |
814 | 154 | // value for their types, they will not be included in the request. | 154 | // value for their types, they will not be included in the request. |
815 | 155 | func (mt *MTurk) CreateHIT(title, description string, question ExternalQuestion, reward Price, assignmentDurationInSeconds, lifetimeInSeconds uint, keywords string, maxAssignments uint, qualificationRequirement *QualificationRequirement, requesterAnnotation string) (h *HIT, err error) { | 155 | func (mt *MTurk) CreateHIT(title, description string, question ExternalQuestion, reward Price, assignmentDurationInSeconds, lifetimeInSeconds uint, keywords string, maxAssignments uint, qualificationRequirement *QualificationRequirement, requesterAnnotation string) (h *HIT, err error) { |
816 | 156 | params := make(map[string]string) | 156 | params := make(map[string]string) |
817 | @@ -191,8 +191,8 @@ | |||
818 | 191 | 191 | ||
819 | 192 | // Corresponds to the "CreateHIT" operation of the Mechanical Turk | 192 | // Corresponds to the "CreateHIT" operation of the Mechanical Turk |
820 | 193 | // API, using an existing "hit type". http://goo.gl/cDBRc Currently only | 193 | // API, using an existing "hit type". http://goo.gl/cDBRc Currently only |
823 | 194 | // supports "external" questions (see "HIT" struct above). If | 194 | // supports "external" questions (see "HIT" struct above). If |
824 | 195 | // "maxAssignments" or "requesterAnnotation" are the zero value for | 195 | // "maxAssignments" or "requesterAnnotation" are the zero value for |
825 | 196 | // their types, they will not be included in the request. | 196 | // their types, they will not be included in the request. |
826 | 197 | func (mt *MTurk) CreateHITOfType(hitTypeId string, q ExternalQuestion, lifetimeInSeconds uint, maxAssignments uint, requesterAnnotation string) (h *HIT, err error) { | 197 | func (mt *MTurk) CreateHITOfType(hitTypeId string, q ExternalQuestion, lifetimeInSeconds uint, maxAssignments uint, requesterAnnotation string) (h *HIT, err error) { |
827 | 198 | params := make(map[string]string) | 198 | params := make(map[string]string) |
828 | @@ -217,7 +217,7 @@ | |||
829 | 217 | return | 217 | return |
830 | 218 | } | 218 | } |
831 | 219 | 219 | ||
833 | 220 | // Corresponds to "SearchHITs" operation of Mechanical Turk. http://goo.gl/PskcX | 220 | // Corresponds to "SearchHITs" operation of Mechanical Turk. http://goo.gl/PskcX |
834 | 221 | // Currenlty supports none of the optional parameters. | 221 | // Currenlty supports none of the optional parameters. |
835 | 222 | func (mt *MTurk) SearchHITs() (s *SearchHITsResult, err error) { | 222 | func (mt *MTurk) SearchHITs() (s *SearchHITsResult, err error) { |
836 | 223 | params := make(map[string]string) | 223 | params := make(map[string]string) |
837 | 224 | 224 | ||
838 | === modified file 'exp/mturk/mturk_test.go' | |||
839 | --- exp/mturk/mturk_test.go 2012-05-03 17:12:28 +0000 | |||
840 | +++ exp/mturk/mturk_test.go 2013-01-31 17:09:20 +0000 | |||
841 | @@ -3,19 +3,26 @@ | |||
842 | 3 | import ( | 3 | import ( |
843 | 4 | "launchpad.net/goamz/aws" | 4 | "launchpad.net/goamz/aws" |
844 | 5 | "launchpad.net/goamz/exp/mturk" | 5 | "launchpad.net/goamz/exp/mturk" |
845 | 6 | "launchpad.net/goamz/testutil" | ||
846 | 6 | . "launchpad.net/gocheck" | 7 | . "launchpad.net/gocheck" |
847 | 7 | "net/url" | 8 | "net/url" |
848 | 9 | "testing" | ||
849 | 8 | ) | 10 | ) |
850 | 9 | 11 | ||
851 | 12 | func Test(t *testing.T) { | ||
852 | 13 | TestingT(t) | ||
853 | 14 | } | ||
854 | 15 | |||
855 | 10 | var _ = Suite(&S{}) | 16 | var _ = Suite(&S{}) |
856 | 11 | 17 | ||
857 | 12 | type S struct { | 18 | type S struct { |
858 | 13 | HTTPSuite | ||
859 | 14 | mturk *mturk.MTurk | 19 | mturk *mturk.MTurk |
860 | 15 | } | 20 | } |
861 | 16 | 21 | ||
862 | 22 | var testServer = testutil.NewHTTPServer() | ||
863 | 23 | |||
864 | 17 | func (s *S) SetUpSuite(c *C) { | 24 | func (s *S) SetUpSuite(c *C) { |
866 | 18 | s.HTTPSuite.SetUpSuite(c) | 25 | testServer.Start() |
867 | 19 | auth := aws.Auth{"abc", "123"} | 26 | auth := aws.Auth{"abc", "123"} |
868 | 20 | u, err := url.Parse(testServer.URL) | 27 | u, err := url.Parse(testServer.URL) |
869 | 21 | if err != nil { | 28 | if err != nil { |
870 | @@ -28,8 +35,12 @@ | |||
871 | 28 | } | 35 | } |
872 | 29 | } | 36 | } |
873 | 30 | 37 | ||
874 | 38 | func (s *S) TearDownTest(c *C) { | ||
875 | 39 | testServer.Flush() | ||
876 | 40 | } | ||
877 | 41 | |||
878 | 31 | func (s *S) TestCreateHIT(c *C) { | 42 | func (s *S) TestCreateHIT(c *C) { |
880 | 32 | testServer.PrepareResponse(200, nil, BasicHitResponse) | 43 | testServer.Response(200, nil, BasicHitResponse) |
881 | 33 | 44 | ||
882 | 34 | question := mturk.ExternalQuestion{ | 45 | question := mturk.ExternalQuestion{ |
883 | 35 | ExternalURL: "http://www.amazon.com", | 46 | ExternalURL: "http://www.amazon.com", |
884 | @@ -51,7 +62,7 @@ | |||
885 | 51 | } | 62 | } |
886 | 52 | 63 | ||
887 | 53 | func (s *S) TestSearchHITs(c *C) { | 64 | func (s *S) TestSearchHITs(c *C) { |
889 | 54 | testServer.PrepareResponse(200, nil, SearchHITResponse) | 65 | testServer.Response(200, nil, SearchHITResponse) |
890 | 55 | 66 | ||
891 | 56 | hitResult, err := s.mturk.SearchHITs() | 67 | hitResult, err := s.mturk.SearchHITs() |
892 | 57 | 68 | ||
893 | 58 | 69 | ||
894 | === removed file 'exp/mturk/suite_test.go' | |||
895 | --- exp/mturk/suite_test.go 2012-03-09 15:34:56 +0000 | |||
896 | +++ exp/mturk/suite_test.go 1970-01-01 00:00:00 +0000 | |||
897 | @@ -1,120 +0,0 @@ | |||
898 | 1 | package mturk_test | ||
899 | 2 | |||
900 | 3 | import ( | ||
901 | 4 | "fmt" | ||
902 | 5 | . "launchpad.net/gocheck" | ||
903 | 6 | "net/http" | ||
904 | 7 | "net/url" | ||
905 | 8 | "os" | ||
906 | 9 | "testing" | ||
907 | 10 | "time" | ||
908 | 11 | ) | ||
909 | 12 | |||
910 | 13 | func Test(t *testing.T) { | ||
911 | 14 | TestingT(t) | ||
912 | 15 | } | ||
913 | 16 | |||
914 | 17 | type HTTPSuite struct{} | ||
915 | 18 | |||
916 | 19 | var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second) | ||
917 | 20 | |||
918 | 21 | func (s *HTTPSuite) SetUpSuite(c *C) { | ||
919 | 22 | testServer.Start() | ||
920 | 23 | } | ||
921 | 24 | |||
922 | 25 | func (s *HTTPSuite) TearDownTest(c *C) { | ||
923 | 26 | testServer.FlushRequests() | ||
924 | 27 | } | ||
925 | 28 | |||
926 | 29 | type TestHTTPServer struct { | ||
927 | 30 | URL string | ||
928 | 31 | Timeout time.Duration | ||
929 | 32 | started bool | ||
930 | 33 | request chan *http.Request | ||
931 | 34 | response chan *testResponse | ||
932 | 35 | pending chan bool | ||
933 | 36 | } | ||
934 | 37 | |||
935 | 38 | type testResponse struct { | ||
936 | 39 | Status int | ||
937 | 40 | Headers map[string]string | ||
938 | 41 | Body string | ||
939 | 42 | } | ||
940 | 43 | |||
941 | 44 | func NewTestHTTPServer(url string, timeout time.Duration) *TestHTTPServer { | ||
942 | 45 | return &TestHTTPServer{URL: url, Timeout: timeout} | ||
943 | 46 | } | ||
944 | 47 | |||
945 | 48 | func (s *TestHTTPServer) Start() { | ||
946 | 49 | if s.started { | ||
947 | 50 | return | ||
948 | 51 | } | ||
949 | 52 | s.started = true | ||
950 | 53 | |||
951 | 54 | s.request = make(chan *http.Request, 64) | ||
952 | 55 | s.response = make(chan *testResponse, 64) | ||
953 | 56 | s.pending = make(chan bool, 64) | ||
954 | 57 | |||
955 | 58 | url, _ := url.Parse(s.URL) | ||
956 | 59 | go http.ListenAndServe(url.Host, s) | ||
957 | 60 | |||
958 | 61 | s.PrepareResponse(202, nil, "Nothing.") | ||
959 | 62 | for { | ||
960 | 63 | // Wait for it to be up. | ||
961 | 64 | resp, err := http.Get(s.URL) | ||
962 | 65 | if err == nil && resp.StatusCode == 202 { | ||
963 | 66 | break | ||
964 | 67 | } | ||
965 | 68 | fmt.Fprintf(os.Stderr, "\nWaiting for fake server to be up... ") | ||
966 | 69 | time.Sleep(1e8) | ||
967 | 70 | } | ||
968 | 71 | fmt.Fprintf(os.Stderr, "done\n\n") | ||
969 | 72 | s.WaitRequest() // Consume dummy request. | ||
970 | 73 | } | ||
971 | 74 | |||
972 | 75 | // FlushRequests discards requests which were not yet consumed by WaitRequest. | ||
973 | 76 | func (s *TestHTTPServer) FlushRequests() { | ||
974 | 77 | for { | ||
975 | 78 | select { | ||
976 | 79 | case <-s.request: | ||
977 | 80 | default: | ||
978 | 81 | return | ||
979 | 82 | } | ||
980 | 83 | } | ||
981 | 84 | } | ||
982 | 85 | |||
983 | 86 | func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
984 | 87 | s.request <- req | ||
985 | 88 | var resp *testResponse | ||
986 | 89 | select { | ||
987 | 90 | case resp = <-s.response: | ||
988 | 91 | case <-time.After(s.Timeout): | ||
989 | 92 | fmt.Fprintf(os.Stderr, "ERROR: Timeout waiting for test to provide response\n") | ||
990 | 93 | resp = &testResponse{500, nil, ""} | ||
991 | 94 | } | ||
992 | 95 | if resp.Headers != nil { | ||
993 | 96 | h := w.Header() | ||
994 | 97 | for k, v := range resp.Headers { | ||
995 | 98 | h.Set(k, v) | ||
996 | 99 | } | ||
997 | 100 | } | ||
998 | 101 | if resp.Status != 0 { | ||
999 | 102 | w.WriteHeader(resp.Status) | ||
1000 | 103 | } | ||
1001 | 104 | w.Write([]byte(resp.Body)) | ||
1002 | 105 | } | ||
1003 | 106 | |||
1004 | 107 | func (s *TestHTTPServer) WaitRequest() *http.Request { | ||
1005 | 108 | select { | ||
1006 | 109 | case req := <-s.request: | ||
1007 | 110 | req.ParseForm() | ||
1008 | 111 | return req | ||
1009 | 112 | case <-time.After(s.Timeout): | ||
1010 | 113 | panic("Timeout waiting for goamz request") | ||
1011 | 114 | } | ||
1012 | 115 | panic("unreached") | ||
1013 | 116 | } | ||
1014 | 117 | |||
1015 | 118 | func (s *TestHTTPServer) PrepareResponse(status int, headers map[string]string, body string) { | ||
1016 | 119 | s.response <- &testResponse{status, headers, body} | ||
1017 | 120 | } | ||
1018 | 121 | 0 | ||
1019 | === modified file 'exp/sdb/sdb.go' | |||
1020 | --- exp/sdb/sdb.go 2012-03-09 15:34:56 +0000 | |||
1021 | +++ exp/sdb/sdb.go 2013-01-31 17:09:20 +0000 | |||
1022 | @@ -18,7 +18,7 @@ | |||
1023 | 18 | 18 | ||
1024 | 19 | // BUG: SelectResp isn't properly organized. It must change. | 19 | // BUG: SelectResp isn't properly organized. It must change. |
1025 | 20 | 20 | ||
1027 | 21 | // | 21 | // |
1028 | 22 | 22 | ||
1029 | 23 | import ( | 23 | import ( |
1030 | 24 | "encoding/xml" | 24 | "encoding/xml" |
1031 | @@ -129,7 +129,7 @@ | |||
1032 | 129 | 129 | ||
1033 | 130 | // Select returns a set of items and attributes that match expr. | 130 | // Select returns a set of items and attributes that match expr. |
1034 | 131 | // Select is similar to the standard SQL SELECT statement. | 131 | // Select is similar to the standard SQL SELECT statement. |
1036 | 132 | // | 132 | // |
1037 | 133 | // See http://goo.gl/GTsSZ for more details. | 133 | // See http://goo.gl/GTsSZ for more details. |
1038 | 134 | func (sdb *SDB) Select(expr string, consistent bool) (resp *SelectResp, err error) { | 134 | func (sdb *SDB) Select(expr string, consistent bool) (resp *SelectResp, err error) { |
1039 | 135 | resp = &SelectResp{} | 135 | resp = &SelectResp{} |
1040 | @@ -206,7 +206,7 @@ | |||
1041 | 206 | pa.missing[name] = true | 206 | pa.missing[name] = true |
1042 | 207 | } | 207 | } |
1043 | 208 | 208 | ||
1045 | 209 | // PutAttrs adds attrs to item. | 209 | // PutAttrs adds attrs to item. |
1046 | 210 | // | 210 | // |
1047 | 211 | // See http://goo.gl/yTAV4 for more details. | 211 | // See http://goo.gl/yTAV4 for more details. |
1048 | 212 | func (item *Item) PutAttrs(attrs *PutAttrs) (resp *SimpleResp, err error) { | 212 | func (item *Item) PutAttrs(attrs *PutAttrs) (resp *SimpleResp, err error) { |
1049 | 213 | 213 | ||
1050 | === modified file 'exp/sdb/sdb_test.go' | |||
1051 | --- exp/sdb/sdb_test.go 2012-03-09 15:34:56 +0000 | |||
1052 | +++ exp/sdb/sdb_test.go 2013-01-31 17:09:20 +0000 | |||
1053 | @@ -3,24 +3,35 @@ | |||
1054 | 3 | import ( | 3 | import ( |
1055 | 4 | "launchpad.net/goamz/aws" | 4 | "launchpad.net/goamz/aws" |
1056 | 5 | "launchpad.net/goamz/exp/sdb" | 5 | "launchpad.net/goamz/exp/sdb" |
1057 | 6 | "launchpad.net/goamz/testutil" | ||
1058 | 6 | . "launchpad.net/gocheck" | 7 | . "launchpad.net/gocheck" |
1059 | 8 | "testing" | ||
1060 | 7 | ) | 9 | ) |
1061 | 8 | 10 | ||
1062 | 11 | func Test(t *testing.T) { | ||
1063 | 12 | TestingT(t) | ||
1064 | 13 | } | ||
1065 | 14 | |||
1066 | 9 | var _ = Suite(&S{}) | 15 | var _ = Suite(&S{}) |
1067 | 10 | 16 | ||
1068 | 11 | type S struct { | 17 | type S struct { |
1069 | 12 | HTTPSuite | ||
1070 | 13 | sdb *sdb.SDB | 18 | sdb *sdb.SDB |
1071 | 14 | } | 19 | } |
1072 | 15 | 20 | ||
1073 | 21 | var testServer = testutil.NewHTTPServer() | ||
1074 | 22 | |||
1075 | 16 | func (s *S) SetUpSuite(c *C) { | 23 | func (s *S) SetUpSuite(c *C) { |
1077 | 17 | s.HTTPSuite.SetUpSuite(c) | 24 | testServer.Start() |
1078 | 18 | auth := aws.Auth{"abc", "123"} | 25 | auth := aws.Auth{"abc", "123"} |
1079 | 19 | s.sdb = sdb.New(auth, aws.Region{SDBEndpoint: testServer.URL}) | 26 | s.sdb = sdb.New(auth, aws.Region{SDBEndpoint: testServer.URL}) |
1080 | 20 | } | 27 | } |
1081 | 21 | 28 | ||
1082 | 29 | func (s *S) TearDownTest(c *C) { | ||
1083 | 30 | testServer.Flush() | ||
1084 | 31 | } | ||
1085 | 32 | |||
1086 | 22 | func (s *S) TestCreateDomainOK(c *C) { | 33 | func (s *S) TestCreateDomainOK(c *C) { |
1088 | 23 | testServer.PrepareResponse(200, nil, TestCreateDomainXmlOK) | 34 | testServer.Response(200, nil, TestCreateDomainXmlOK) |
1089 | 24 | 35 | ||
1090 | 25 | domain := s.sdb.Domain("domain") | 36 | domain := s.sdb.Domain("domain") |
1091 | 26 | resp, err := domain.CreateDomain() | 37 | resp, err := domain.CreateDomain() |
1092 | @@ -37,7 +48,7 @@ | |||
1093 | 37 | } | 48 | } |
1094 | 38 | 49 | ||
1095 | 39 | func (s *S) TestListDomainsOK(c *C) { | 50 | func (s *S) TestListDomainsOK(c *C) { |
1097 | 40 | testServer.PrepareResponse(200, nil, TestListDomainsXmlOK) | 51 | testServer.Response(200, nil, TestListDomainsXmlOK) |
1098 | 41 | 52 | ||
1099 | 42 | resp, err := s.sdb.ListDomains() | 53 | resp, err := s.sdb.ListDomains() |
1100 | 43 | req := testServer.WaitRequest() | 54 | req := testServer.WaitRequest() |
1101 | @@ -54,7 +65,7 @@ | |||
1102 | 54 | } | 65 | } |
1103 | 55 | 66 | ||
1104 | 56 | func (s *S) TestListDomainsWithNextTokenXmlOK(c *C) { | 67 | func (s *S) TestListDomainsWithNextTokenXmlOK(c *C) { |
1106 | 57 | testServer.PrepareResponse(200, nil, TestListDomainsWithNextTokenXmlOK) | 68 | testServer.Response(200, nil, TestListDomainsWithNextTokenXmlOK) |
1107 | 58 | 69 | ||
1108 | 59 | resp, err := s.sdb.ListDomains() | 70 | resp, err := s.sdb.ListDomains() |
1109 | 60 | req := testServer.WaitRequest() | 71 | req := testServer.WaitRequest() |
1110 | @@ -72,7 +83,7 @@ | |||
1111 | 72 | } | 83 | } |
1112 | 73 | 84 | ||
1113 | 74 | func (s *S) TestDeleteDomainOK(c *C) { | 85 | func (s *S) TestDeleteDomainOK(c *C) { |
1115 | 75 | testServer.PrepareResponse(200, nil, TestDeleteDomainXmlOK) | 86 | testServer.Response(200, nil, TestDeleteDomainXmlOK) |
1116 | 76 | 87 | ||
1117 | 77 | domain := s.sdb.Domain("domain") | 88 | domain := s.sdb.Domain("domain") |
1118 | 78 | resp, err := domain.DeleteDomain() | 89 | resp, err := domain.DeleteDomain() |
1119 | @@ -89,7 +100,7 @@ | |||
1120 | 89 | } | 100 | } |
1121 | 90 | 101 | ||
1122 | 91 | func (s *S) TestPutAttrsOK(c *C) { | 102 | func (s *S) TestPutAttrsOK(c *C) { |
1124 | 92 | testServer.PrepareResponse(200, nil, TestPutAttrsXmlOK) | 103 | testServer.Response(200, nil, TestPutAttrsXmlOK) |
1125 | 93 | 104 | ||
1126 | 94 | domain := s.sdb.Domain("MyDomain") | 105 | domain := s.sdb.Domain("MyDomain") |
1127 | 95 | item := domain.Item("Item123") | 106 | item := domain.Item("Item123") |
1128 | @@ -128,7 +139,7 @@ | |||
1129 | 128 | } | 139 | } |
1130 | 129 | 140 | ||
1131 | 130 | func (s *S) TestAttrsOK(c *C) { | 141 | func (s *S) TestAttrsOK(c *C) { |
1133 | 131 | testServer.PrepareResponse(200, nil, TestAttrsXmlOK) | 142 | testServer.Response(200, nil, TestAttrsXmlOK) |
1134 | 132 | 143 | ||
1135 | 133 | domain := s.sdb.Domain("MyDomain") | 144 | domain := s.sdb.Domain("MyDomain") |
1136 | 134 | item := domain.Item("Item123") | 145 | item := domain.Item("Item123") |
1137 | @@ -155,7 +166,7 @@ | |||
1138 | 155 | } | 166 | } |
1139 | 156 | 167 | ||
1140 | 157 | func (s *S) TestAttrsSelectOK(c *C) { | 168 | func (s *S) TestAttrsSelectOK(c *C) { |
1142 | 158 | testServer.PrepareResponse(200, nil, TestAttrsXmlOK) | 169 | testServer.Response(200, nil, TestAttrsXmlOK) |
1143 | 159 | 170 | ||
1144 | 160 | domain := s.sdb.Domain("MyDomain") | 171 | domain := s.sdb.Domain("MyDomain") |
1145 | 161 | item := domain.Item("Item123") | 172 | item := domain.Item("Item123") |
1146 | @@ -184,7 +195,7 @@ | |||
1147 | 184 | } | 195 | } |
1148 | 185 | 196 | ||
1149 | 186 | func (s *S) TestSelectOK(c *C) { | 197 | func (s *S) TestSelectOK(c *C) { |
1151 | 187 | testServer.PrepareResponse(200, nil, TestSelectXmlOK) | 198 | testServer.Response(200, nil, TestSelectXmlOK) |
1152 | 188 | 199 | ||
1153 | 189 | resp, err := s.sdb.Select("select Color from MyDomain where Color like 'Blue%'", true) | 200 | resp, err := s.sdb.Select("select Color from MyDomain where Color like 'Blue%'", true) |
1154 | 190 | req := testServer.WaitRequest() | 201 | req := testServer.WaitRequest() |
1155 | 191 | 202 | ||
1156 | === removed file 'exp/sdb/suite_test.go' | |||
1157 | --- exp/sdb/suite_test.go 2012-03-09 15:34:56 +0000 | |||
1158 | +++ exp/sdb/suite_test.go 1970-01-01 00:00:00 +0000 | |||
1159 | @@ -1,139 +0,0 @@ | |||
1160 | 1 | package sdb_test | ||
1161 | 2 | |||
1162 | 3 | import ( | ||
1163 | 4 | "flag" | ||
1164 | 5 | "fmt" | ||
1165 | 6 | "launchpad.net/goamz/aws" | ||
1166 | 7 | "launchpad.net/gocheck" | ||
1167 | 8 | "net/http" | ||
1168 | 9 | "net/url" | ||
1169 | 10 | "os" | ||
1170 | 11 | "testing" | ||
1171 | 12 | "time" | ||
1172 | 13 | ) | ||
1173 | 14 | |||
1174 | 15 | func Test(t *testing.T) { | ||
1175 | 16 | gocheck.TestingT(t) | ||
1176 | 17 | } | ||
1177 | 18 | |||
1178 | 19 | var integration = flag.Bool("i", false, "Enable integration tests") | ||
1179 | 20 | |||
1180 | 21 | type SuiteI struct { | ||
1181 | 22 | auth aws.Auth | ||
1182 | 23 | } | ||
1183 | 24 | |||
1184 | 25 | func (s *SuiteI) SetUpSuite(c *gocheck.C) { | ||
1185 | 26 | if !*integration { | ||
1186 | 27 | c.Skip("Integration tests not enabled (-int flag)") | ||
1187 | 28 | } | ||
1188 | 29 | auth, err := aws.EnvAuth() | ||
1189 | 30 | if err != nil { | ||
1190 | 31 | c.Fatal(err) | ||
1191 | 32 | } | ||
1192 | 33 | s.auth = auth | ||
1193 | 34 | } | ||
1194 | 35 | |||
1195 | 36 | type HTTPSuite struct{} | ||
1196 | 37 | |||
1197 | 38 | var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second) | ||
1198 | 39 | |||
1199 | 40 | func (s *HTTPSuite) SetUpSuite(c *gocheck.C) { | ||
1200 | 41 | testServer.Start() | ||
1201 | 42 | } | ||
1202 | 43 | |||
1203 | 44 | func (s *HTTPSuite) TearDownTest(c *gocheck.C) { | ||
1204 | 45 | testServer.FlushRequests() | ||
1205 | 46 | } | ||
1206 | 47 | |||
1207 | 48 | type TestHTTPServer struct { | ||
1208 | 49 | URL string | ||
1209 | 50 | Timeout time.Duration | ||
1210 | 51 | started bool | ||
1211 | 52 | request chan *http.Request | ||
1212 | 53 | response chan *testResponse | ||
1213 | 54 | pending chan bool | ||
1214 | 55 | } | ||
1215 | 56 | |||
1216 | 57 | type testResponse struct { | ||
1217 | 58 | Status int | ||
1218 | 59 | Headers map[string]string | ||
1219 | 60 | Body string | ||
1220 | 61 | } | ||
1221 | 62 | |||
1222 | 63 | func NewTestHTTPServer(url_ string, timeout time.Duration) *TestHTTPServer { | ||
1223 | 64 | return &TestHTTPServer{URL: url_, Timeout: timeout} | ||
1224 | 65 | } | ||
1225 | 66 | |||
1226 | 67 | func (s *TestHTTPServer) Start() { | ||
1227 | 68 | if s.started { | ||
1228 | 69 | return | ||
1229 | 70 | } | ||
1230 | 71 | s.started = true | ||
1231 | 72 | |||
1232 | 73 | s.request = make(chan *http.Request, 64) | ||
1233 | 74 | s.response = make(chan *testResponse, 64) | ||
1234 | 75 | s.pending = make(chan bool, 64) | ||
1235 | 76 | |||
1236 | 77 | url_, _ := url.Parse(s.URL) | ||
1237 | 78 | go http.ListenAndServe(url_.Host, s) | ||
1238 | 79 | |||
1239 | 80 | s.PrepareResponse(202, nil, "Nothing.") | ||
1240 | 81 | for { | ||
1241 | 82 | // Wait for it to be up. | ||
1242 | 83 | resp, err := http.Get(s.URL) | ||
1243 | 84 | if err == nil && resp.StatusCode == 202 { | ||
1244 | 85 | break | ||
1245 | 86 | } | ||
1246 | 87 | fmt.Fprintf(os.Stderr, "\nWaiting for fake server to be up... ") | ||
1247 | 88 | time.Sleep(1e8) | ||
1248 | 89 | } | ||
1249 | 90 | fmt.Fprintf(os.Stderr, "done\n\n") | ||
1250 | 91 | s.WaitRequest() // Consume dummy request. | ||
1251 | 92 | } | ||
1252 | 93 | |||
1253 | 94 | // FlushRequests discards requests which were not yet consumed by WaitRequest. | ||
1254 | 95 | func (s *TestHTTPServer) FlushRequests() { | ||
1255 | 96 | for { | ||
1256 | 97 | select { | ||
1257 | 98 | case <-s.request: | ||
1258 | 99 | default: | ||
1259 | 100 | return | ||
1260 | 101 | } | ||
1261 | 102 | } | ||
1262 | 103 | } | ||
1263 | 104 | |||
1264 | 105 | func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
1265 | 106 | s.request <- req | ||
1266 | 107 | var resp *testResponse | ||
1267 | 108 | select { | ||
1268 | 109 | case resp = <-s.response: | ||
1269 | 110 | case <-time.After(s.Timeout): | ||
1270 | 111 | fmt.Fprintf(os.Stderr, "ERROR: Timeout waiting for test to provide response\n") | ||
1271 | 112 | resp = &testResponse{500, nil, ""} | ||
1272 | 113 | } | ||
1273 | 114 | if resp.Headers != nil { | ||
1274 | 115 | h := w.Header() | ||
1275 | 116 | for k, v := range resp.Headers { | ||
1276 | 117 | h.Set(k, v) | ||
1277 | 118 | } | ||
1278 | 119 | } | ||
1279 | 120 | if resp.Status != 0 { | ||
1280 | 121 | w.WriteHeader(resp.Status) | ||
1281 | 122 | } | ||
1282 | 123 | w.Write([]byte(resp.Body)) | ||
1283 | 124 | } | ||
1284 | 125 | |||
1285 | 126 | func (s *TestHTTPServer) WaitRequest() *http.Request { | ||
1286 | 127 | select { | ||
1287 | 128 | case req := <-s.request: | ||
1288 | 129 | req.ParseForm() | ||
1289 | 130 | return req | ||
1290 | 131 | case <-time.After(s.Timeout): | ||
1291 | 132 | panic("Timeout waiting for goamz request") | ||
1292 | 133 | } | ||
1293 | 134 | panic("unreached") | ||
1294 | 135 | } | ||
1295 | 136 | |||
1296 | 137 | func (s *TestHTTPServer) PrepareResponse(status int, headers map[string]string, body string) { | ||
1297 | 138 | s.response <- &testResponse{status, headers, body} | ||
1298 | 139 | } | ||
1299 | 140 | 0 | ||
1300 | === modified file 'exp/sns/sns_test.go' | |||
1301 | --- exp/sns/sns_test.go 2012-05-03 17:12:28 +0000 | |||
1302 | +++ exp/sns/sns_test.go 2013-01-31 17:09:20 +0000 | |||
1303 | @@ -3,22 +3,33 @@ | |||
1304 | 3 | import ( | 3 | import ( |
1305 | 4 | "launchpad.net/goamz/aws" | 4 | "launchpad.net/goamz/aws" |
1306 | 5 | "launchpad.net/goamz/exp/sns" | 5 | "launchpad.net/goamz/exp/sns" |
1307 | 6 | "launchpad.net/goamz/testutil" | ||
1308 | 6 | . "launchpad.net/gocheck" | 7 | . "launchpad.net/gocheck" |
1309 | 8 | "testing" | ||
1310 | 7 | ) | 9 | ) |
1311 | 8 | 10 | ||
1312 | 11 | func Test(t *testing.T) { | ||
1313 | 12 | TestingT(t) | ||
1314 | 13 | } | ||
1315 | 14 | |||
1316 | 9 | var _ = Suite(&S{}) | 15 | var _ = Suite(&S{}) |
1317 | 10 | 16 | ||
1318 | 11 | type S struct { | 17 | type S struct { |
1319 | 12 | HTTPSuite | ||
1320 | 13 | sns *sns.SNS | 18 | sns *sns.SNS |
1321 | 14 | } | 19 | } |
1322 | 15 | 20 | ||
1323 | 21 | var testServer = testutil.NewHTTPServer() | ||
1324 | 22 | |||
1325 | 16 | func (s *S) SetUpSuite(c *C) { | 23 | func (s *S) SetUpSuite(c *C) { |
1327 | 17 | s.HTTPSuite.SetUpSuite(c) | 24 | testServer.Start() |
1328 | 18 | auth := aws.Auth{"abc", "123"} | 25 | auth := aws.Auth{"abc", "123"} |
1329 | 19 | s.sns = sns.New(auth, aws.Region{SNSEndpoint: testServer.URL}) | 26 | s.sns = sns.New(auth, aws.Region{SNSEndpoint: testServer.URL}) |
1330 | 20 | } | 27 | } |
1331 | 21 | 28 | ||
1332 | 29 | func (s *S) TearDownTest(c *C) { | ||
1333 | 30 | testServer.Flush() | ||
1334 | 31 | } | ||
1335 | 32 | |||
1336 | 22 | func (s *S) TestListTopicsOK(c *C) { | 33 | func (s *S) TestListTopicsOK(c *C) { |
1337 | 23 | testServer.Response(200, nil, TestListTopicsXmlOK) | 34 | testServer.Response(200, nil, TestListTopicsXmlOK) |
1338 | 24 | 35 | ||
1339 | 25 | 36 | ||
1340 | === removed file 'exp/sns/suite_test.go' | |||
1341 | --- exp/sns/suite_test.go 2012-03-09 15:34:56 +0000 | |||
1342 | +++ exp/sns/suite_test.go 1970-01-01 00:00:00 +0000 | |||
1343 | @@ -1,200 +0,0 @@ | |||
1344 | 1 | package sns_test | ||
1345 | 2 | |||
1346 | 3 | import ( | ||
1347 | 4 | "bytes" | ||
1348 | 5 | "flag" | ||
1349 | 6 | "fmt" | ||
1350 | 7 | "io/ioutil" | ||
1351 | 8 | . "launchpad.net/gocheck" | ||
1352 | 9 | "net/http" | ||
1353 | 10 | "net/url" | ||
1354 | 11 | "os" | ||
1355 | 12 | "testing" | ||
1356 | 13 | "time" | ||
1357 | 14 | ) | ||
1358 | 15 | |||
1359 | 16 | func Test(t *testing.T) { | ||
1360 | 17 | TestingT(t) | ||
1361 | 18 | } | ||
1362 | 19 | |||
1363 | 20 | var integration = flag.Bool("i", false, "Enable integration tests") | ||
1364 | 21 | |||
1365 | 22 | type SuiteI struct{} | ||
1366 | 23 | |||
1367 | 24 | func (s *SuiteI) SetUpSuite(c *C) { | ||
1368 | 25 | if !*integration { | ||
1369 | 26 | c.Skip("Integration tests not enabled (-i flag)") | ||
1370 | 27 | } | ||
1371 | 28 | } | ||
1372 | 29 | |||
1373 | 30 | type HTTPSuite struct{} | ||
1374 | 31 | |||
1375 | 32 | var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second) | ||
1376 | 33 | |||
1377 | 34 | func (s *HTTPSuite) SetUpSuite(c *C) { | ||
1378 | 35 | testServer.Start() | ||
1379 | 36 | } | ||
1380 | 37 | |||
1381 | 38 | func (s *HTTPSuite) TearDownTest(c *C) { | ||
1382 | 39 | testServer.Flush() | ||
1383 | 40 | } | ||
1384 | 41 | |||
1385 | 42 | type TestHTTPServer struct { | ||
1386 | 43 | URL string | ||
1387 | 44 | Timeout time.Duration | ||
1388 | 45 | started bool | ||
1389 | 46 | request chan *http.Request | ||
1390 | 47 | response chan ResponseFunc | ||
1391 | 48 | pending chan bool | ||
1392 | 49 | } | ||
1393 | 50 | |||
1394 | 51 | func NewTestHTTPServer(url_ string, timeout time.Duration) *TestHTTPServer { | ||
1395 | 52 | return &TestHTTPServer{URL: url_, Timeout: timeout} | ||
1396 | 53 | } | ||
1397 | 54 | |||
1398 | 55 | type Response struct { | ||
1399 | 56 | Status int | ||
1400 | 57 | Headers map[string]string | ||
1401 | 58 | Body string | ||
1402 | 59 | } | ||
1403 | 60 | |||
1404 | 61 | type ResponseFunc func(path string) Response | ||
1405 | 62 | |||
1406 | 63 | func (s *TestHTTPServer) Start() { | ||
1407 | 64 | if s.started { | ||
1408 | 65 | return | ||
1409 | 66 | } | ||
1410 | 67 | s.started = true | ||
1411 | 68 | |||
1412 | 69 | s.request = make(chan *http.Request, 64) | ||
1413 | 70 | s.response = make(chan ResponseFunc, 64) | ||
1414 | 71 | s.pending = make(chan bool, 64) | ||
1415 | 72 | |||
1416 | 73 | url_, _ := url.Parse(s.URL) | ||
1417 | 74 | go http.ListenAndServe(url_.Host, s) | ||
1418 | 75 | |||
1419 | 76 | s.Response(203, nil, "") | ||
1420 | 77 | for { | ||
1421 | 78 | // Wait for it to be up. | ||
1422 | 79 | resp, err := http.Get(s.URL) | ||
1423 | 80 | if err == nil && resp.StatusCode == 203 { | ||
1424 | 81 | break | ||
1425 | 82 | } | ||
1426 | 83 | fmt.Fprintf(os.Stderr, "\nWaiting for fake server to be up... ") | ||
1427 | 84 | time.Sleep(1e8) | ||
1428 | 85 | } | ||
1429 | 86 | fmt.Fprintf(os.Stderr, "done\n\n") | ||
1430 | 87 | s.WaitRequest() // Consume dummy request. | ||
1431 | 88 | } | ||
1432 | 89 | |||
1433 | 90 | // FlushRequests discards requests which were not yet consumed by WaitRequest. | ||
1434 | 91 | func (s *TestHTTPServer) Flush() { | ||
1435 | 92 | for { | ||
1436 | 93 | select { | ||
1437 | 94 | case <-s.request: | ||
1438 | 95 | case <-s.response: | ||
1439 | 96 | default: | ||
1440 | 97 | return | ||
1441 | 98 | } | ||
1442 | 99 | } | ||
1443 | 100 | } | ||
1444 | 101 | |||
1445 | 102 | func body(req *http.Request) string { | ||
1446 | 103 | data, err := ioutil.ReadAll(req.Body) | ||
1447 | 104 | if err != nil { | ||
1448 | 105 | panic(err) | ||
1449 | 106 | } | ||
1450 | 107 | return string(data) | ||
1451 | 108 | } | ||
1452 | 109 | |||
1453 | 110 | func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
1454 | 111 | req.ParseMultipartForm(1e6) | ||
1455 | 112 | data, err := ioutil.ReadAll(req.Body) | ||
1456 | 113 | if err != nil { | ||
1457 | 114 | panic(err) | ||
1458 | 115 | } | ||
1459 | 116 | req.Body = ioutil.NopCloser(bytes.NewBuffer(data)) | ||
1460 | 117 | s.request <- req | ||
1461 | 118 | var resp Response | ||
1462 | 119 | select { | ||
1463 | 120 | case respFunc := <-s.response: | ||
1464 | 121 | resp = respFunc(req.URL.Path) | ||
1465 | 122 | case <-time.After(s.Timeout): | ||
1466 | 123 | const msg = "ERROR: Timeout waiting for test to prepare a response\n" | ||
1467 | 124 | fmt.Fprintf(os.Stderr, msg) | ||
1468 | 125 | resp = Response{500, nil, msg} | ||
1469 | 126 | } | ||
1470 | 127 | if resp.Headers != nil { | ||
1471 | 128 | h := w.Header() | ||
1472 | 129 | for k, v := range resp.Headers { | ||
1473 | 130 | h.Set(k, v) | ||
1474 | 131 | } | ||
1475 | 132 | } | ||
1476 | 133 | if resp.Status != 0 { | ||
1477 | 134 | w.WriteHeader(resp.Status) | ||
1478 | 135 | } | ||
1479 | 136 | w.Write([]byte(resp.Body)) | ||
1480 | 137 | } | ||
1481 | 138 | |||
1482 | 139 | // WaitRequests returns the next n requests made to the http server from | ||
1483 | 140 | // the queue. If not enough requests were previously made, it waits until | ||
1484 | 141 | // the timeout value for them to be made. | ||
1485 | 142 | func (s *TestHTTPServer) WaitRequests(n int) []*http.Request { | ||
1486 | 143 | reqs := make([]*http.Request, 0, n) | ||
1487 | 144 | for i := 0; i < n; i++ { | ||
1488 | 145 | select { | ||
1489 | 146 | case req := <-s.request: | ||
1490 | 147 | reqs = append(reqs, req) | ||
1491 | 148 | case <-time.After(s.Timeout): | ||
1492 | 149 | panic("Timeout waiting for request") | ||
1493 | 150 | } | ||
1494 | 151 | } | ||
1495 | 152 | return reqs | ||
1496 | 153 | } | ||
1497 | 154 | |||
1498 | 155 | // WaitRequest returns the next request made to the http server from | ||
1499 | 156 | // the queue. If no requests were previously made, it waits until the | ||
1500 | 157 | // timeout value for one to be made. | ||
1501 | 158 | func (s *TestHTTPServer) WaitRequest() *http.Request { | ||
1502 | 159 | return s.WaitRequests(1)[0] | ||
1503 | 160 | } | ||
1504 | 161 | |||
1505 | 162 | // ResponseFunc prepares the test server to respond the following n | ||
1506 | 163 | // requests using f to build each response. | ||
1507 | 164 | func (s *TestHTTPServer) ResponseFunc(n int, f ResponseFunc) { | ||
1508 | 165 | for i := 0; i < n; i++ { | ||
1509 | 166 | s.response <- f | ||
1510 | 167 | } | ||
1511 | 168 | } | ||
1512 | 169 | |||
1513 | 170 | // ResponseMap maps request paths to responses. | ||
1514 | 171 | type ResponseMap map[string]Response | ||
1515 | 172 | |||
1516 | 173 | // ResponseMap prepares the test server to respond the following n | ||
1517 | 174 | // requests using the m to obtain the responses. | ||
1518 | 175 | func (s *TestHTTPServer) ResponseMap(n int, m ResponseMap) { | ||
1519 | 176 | f := func(path string) Response { | ||
1520 | 177 | for rpath, resp := range m { | ||
1521 | 178 | if rpath == path { | ||
1522 | 179 | return resp | ||
1523 | 180 | } | ||
1524 | 181 | } | ||
1525 | 182 | return Response{Status: 500, Body: "Path not found in response map: " + path} | ||
1526 | 183 | } | ||
1527 | 184 | s.ResponseFunc(n, f) | ||
1528 | 185 | } | ||
1529 | 186 | |||
1530 | 187 | // Responses prepares the test server to respond the following n requests | ||
1531 | 188 | // using the provided response parameters. | ||
1532 | 189 | func (s *TestHTTPServer) Responses(n int, status int, headers map[string]string, body string) { | ||
1533 | 190 | f := func(path string) Response { | ||
1534 | 191 | return Response{status, headers, body} | ||
1535 | 192 | } | ||
1536 | 193 | s.ResponseFunc(n, f) | ||
1537 | 194 | } | ||
1538 | 195 | |||
1539 | 196 | // Response prepares the test server to respond the following request | ||
1540 | 197 | // using the provided response parameters. | ||
1541 | 198 | func (s *TestHTTPServer) Response(status int, headers map[string]string, body string) { | ||
1542 | 199 | s.Responses(1, status, headers, body) | ||
1543 | 200 | } | ||
1544 | 201 | 0 | ||
1545 | === modified file 'iam/iam_test.go' | |||
1546 | --- iam/iam_test.go 2012-10-10 20:16:54 +0000 | |||
1547 | +++ iam/iam_test.go 2013-01-31 17:09:20 +0000 | |||
1548 | @@ -3,24 +3,35 @@ | |||
1549 | 3 | import ( | 3 | import ( |
1550 | 4 | "launchpad.net/goamz/aws" | 4 | "launchpad.net/goamz/aws" |
1551 | 5 | "launchpad.net/goamz/iam" | 5 | "launchpad.net/goamz/iam" |
1552 | 6 | "launchpad.net/goamz/testutil" | ||
1553 | 6 | . "launchpad.net/gocheck" | 7 | . "launchpad.net/gocheck" |
1554 | 8 | "testing" | ||
1555 | 7 | ) | 9 | ) |
1556 | 8 | 10 | ||
1557 | 11 | func Test(t *testing.T) { | ||
1558 | 12 | TestingT(t) | ||
1559 | 13 | } | ||
1560 | 14 | |||
1561 | 9 | type S struct { | 15 | type S struct { |
1562 | 10 | HTTPSuite | ||
1563 | 11 | iam *iam.IAM | 16 | iam *iam.IAM |
1564 | 12 | } | 17 | } |
1565 | 13 | 18 | ||
1566 | 14 | var _ = Suite(&S{}) | 19 | var _ = Suite(&S{}) |
1567 | 15 | 20 | ||
1568 | 21 | var testServer = testutil.NewHTTPServer() | ||
1569 | 22 | |||
1570 | 16 | func (s *S) SetUpSuite(c *C) { | 23 | func (s *S) SetUpSuite(c *C) { |
1572 | 17 | s.HTTPSuite.SetUpSuite(c) | 24 | testServer.Start() |
1573 | 18 | auth := aws.Auth{"abc", "123"} | 25 | auth := aws.Auth{"abc", "123"} |
1574 | 19 | s.iam = iam.New(auth, aws.Region{IAMEndpoint: testServer.URL}) | 26 | s.iam = iam.New(auth, aws.Region{IAMEndpoint: testServer.URL}) |
1575 | 20 | } | 27 | } |
1576 | 21 | 28 | ||
1577 | 29 | func (s *S) TearDownTest(c *C) { | ||
1578 | 30 | testServer.Flush() | ||
1579 | 31 | } | ||
1580 | 32 | |||
1581 | 22 | func (s *S) TestCreateUser(c *C) { | 33 | func (s *S) TestCreateUser(c *C) { |
1583 | 23 | testServer.PrepareResponse(200, nil, CreateUserExample) | 34 | testServer.Response(200, nil, CreateUserExample) |
1584 | 24 | resp, err := s.iam.CreateUser("Bob", "/division_abc/subdivision_xyz/") | 35 | resp, err := s.iam.CreateUser("Bob", "/division_abc/subdivision_xyz/") |
1585 | 25 | values := testServer.WaitRequest().URL.Query() | 36 | values := testServer.WaitRequest().URL.Query() |
1586 | 26 | c.Assert(values.Get("Action"), Equals, "CreateUser") | 37 | c.Assert(values.Get("Action"), Equals, "CreateUser") |
1587 | @@ -38,7 +49,7 @@ | |||
1588 | 38 | } | 49 | } |
1589 | 39 | 50 | ||
1590 | 40 | func (s *S) TestCreateUserConflict(c *C) { | 51 | func (s *S) TestCreateUserConflict(c *C) { |
1592 | 41 | testServer.PrepareResponse(409, nil, DuplicateUserExample) | 52 | testServer.Response(409, nil, DuplicateUserExample) |
1593 | 42 | resp, err := s.iam.CreateUser("Bob", "/division_abc/subdivision_xyz/") | 53 | resp, err := s.iam.CreateUser("Bob", "/division_abc/subdivision_xyz/") |
1594 | 43 | testServer.WaitRequest() | 54 | testServer.WaitRequest() |
1595 | 44 | c.Assert(resp, IsNil) | 55 | c.Assert(resp, IsNil) |
1596 | @@ -50,7 +61,7 @@ | |||
1597 | 50 | } | 61 | } |
1598 | 51 | 62 | ||
1599 | 52 | func (s *S) TestGetUser(c *C) { | 63 | func (s *S) TestGetUser(c *C) { |
1601 | 53 | testServer.PrepareResponse(200, nil, GetUserExample) | 64 | testServer.Response(200, nil, GetUserExample) |
1602 | 54 | resp, err := s.iam.GetUser("Bob") | 65 | resp, err := s.iam.GetUser("Bob") |
1603 | 55 | values := testServer.WaitRequest().URL.Query() | 66 | values := testServer.WaitRequest().URL.Query() |
1604 | 56 | c.Assert(values.Get("Action"), Equals, "GetUser") | 67 | c.Assert(values.Get("Action"), Equals, "GetUser") |
1605 | @@ -67,7 +78,7 @@ | |||
1606 | 67 | } | 78 | } |
1607 | 68 | 79 | ||
1608 | 69 | func (s *S) TestDeleteUser(c *C) { | 80 | func (s *S) TestDeleteUser(c *C) { |
1610 | 70 | testServer.PrepareResponse(200, nil, RequestIdExample) | 81 | testServer.Response(200, nil, RequestIdExample) |
1611 | 71 | resp, err := s.iam.DeleteUser("Bob") | 82 | resp, err := s.iam.DeleteUser("Bob") |
1612 | 72 | values := testServer.WaitRequest().URL.Query() | 83 | values := testServer.WaitRequest().URL.Query() |
1613 | 73 | c.Assert(values.Get("Action"), Equals, "DeleteUser") | 84 | c.Assert(values.Get("Action"), Equals, "DeleteUser") |
1614 | @@ -77,7 +88,7 @@ | |||
1615 | 77 | } | 88 | } |
1616 | 78 | 89 | ||
1617 | 79 | func (s *S) TestCreateAccessKey(c *C) { | 90 | func (s *S) TestCreateAccessKey(c *C) { |
1619 | 80 | testServer.PrepareResponse(200, nil, CreateAccessKeyExample) | 91 | testServer.Response(200, nil, CreateAccessKeyExample) |
1620 | 81 | resp, err := s.iam.CreateAccessKey("Bob") | 92 | resp, err := s.iam.CreateAccessKey("Bob") |
1621 | 82 | values := testServer.WaitRequest().URL.Query() | 93 | values := testServer.WaitRequest().URL.Query() |
1622 | 83 | c.Assert(values.Get("Action"), Equals, "CreateAccessKey") | 94 | c.Assert(values.Get("Action"), Equals, "CreateAccessKey") |
1623 | 84 | 95 | ||
1624 | === modified file 'iam/iami_test.go' | |||
1625 | --- iam/iami_test.go 2012-10-10 20:21:55 +0000 | |||
1626 | +++ iam/iami_test.go 2013-01-31 17:09:20 +0000 | |||
1627 | @@ -1,14 +1,12 @@ | |||
1628 | 1 | package iam_test | 1 | package iam_test |
1629 | 2 | 2 | ||
1630 | 3 | import ( | 3 | import ( |
1631 | 4 | "flag" | ||
1632 | 5 | "launchpad.net/goamz/aws" | 4 | "launchpad.net/goamz/aws" |
1633 | 6 | "launchpad.net/goamz/iam" | 5 | "launchpad.net/goamz/iam" |
1634 | 6 | "launchpad.net/goamz/testutil" | ||
1635 | 7 | . "launchpad.net/gocheck" | 7 | . "launchpad.net/gocheck" |
1636 | 8 | ) | 8 | ) |
1637 | 9 | 9 | ||
1638 | 10 | var amazon = flag.Bool("amazon", false, "Enable tests against amazon server") | ||
1639 | 11 | |||
1640 | 12 | // AmazonServer represents an Amazon AWS server. | 10 | // AmazonServer represents an Amazon AWS server. |
1641 | 13 | type AmazonServer struct { | 11 | type AmazonServer struct { |
1642 | 14 | auth aws.Auth | 12 | auth aws.Auth |
1643 | @@ -31,7 +29,7 @@ | |||
1644 | 31 | } | 29 | } |
1645 | 32 | 30 | ||
1646 | 33 | func (s *AmazonClientSuite) SetUpSuite(c *C) { | 31 | func (s *AmazonClientSuite) SetUpSuite(c *C) { |
1648 | 34 | if !*amazon { | 32 | if !testutil.Amazon { |
1649 | 35 | c.Skip("AmazonClientSuite tests not enabled") | 33 | c.Skip("AmazonClientSuite tests not enabled") |
1650 | 36 | } | 34 | } |
1651 | 37 | s.srv.SetUp(c) | 35 | s.srv.SetUp(c) |
1652 | 38 | 36 | ||
1653 | === removed file 'iam/suite_test.go' | |||
1654 | --- iam/suite_test.go 2012-10-05 22:45:47 +0000 | |||
1655 | +++ iam/suite_test.go 1970-01-01 00:00:00 +0000 | |||
1656 | @@ -1,128 +0,0 @@ | |||
1657 | 1 | package iam_test | ||
1658 | 2 | |||
1659 | 3 | import ( | ||
1660 | 4 | "bytes" | ||
1661 | 5 | "fmt" | ||
1662 | 6 | "io/ioutil" | ||
1663 | 7 | . "launchpad.net/gocheck" | ||
1664 | 8 | "net/http" | ||
1665 | 9 | "net/url" | ||
1666 | 10 | "os" | ||
1667 | 11 | "testing" | ||
1668 | 12 | "time" | ||
1669 | 13 | ) | ||
1670 | 14 | |||
1671 | 15 | func Test(t *testing.T) { | ||
1672 | 16 | TestingT(t) | ||
1673 | 17 | } | ||
1674 | 18 | |||
1675 | 19 | type HTTPSuite struct{} | ||
1676 | 20 | |||
1677 | 21 | var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second) | ||
1678 | 22 | |||
1679 | 23 | func (s *HTTPSuite) SetUpSuite(c *C) { | ||
1680 | 24 | testServer.Start() | ||
1681 | 25 | } | ||
1682 | 26 | |||
1683 | 27 | func (s *HTTPSuite) TearDownTest(c *C) { | ||
1684 | 28 | testServer.FlushRequests() | ||
1685 | 29 | } | ||
1686 | 30 | |||
1687 | 31 | type TestHTTPServer struct { | ||
1688 | 32 | URL string | ||
1689 | 33 | Timeout time.Duration | ||
1690 | 34 | started bool | ||
1691 | 35 | body chan []byte | ||
1692 | 36 | request chan *http.Request | ||
1693 | 37 | response chan *testResponse | ||
1694 | 38 | pending chan bool | ||
1695 | 39 | } | ||
1696 | 40 | |||
1697 | 41 | type testResponse struct { | ||
1698 | 42 | Status int | ||
1699 | 43 | Headers map[string]string | ||
1700 | 44 | Body string | ||
1701 | 45 | } | ||
1702 | 46 | |||
1703 | 47 | func NewTestHTTPServer(url string, timeout time.Duration) *TestHTTPServer { | ||
1704 | 48 | return &TestHTTPServer{URL: url, Timeout: timeout} | ||
1705 | 49 | } | ||
1706 | 50 | |||
1707 | 51 | func (s *TestHTTPServer) Start() { | ||
1708 | 52 | if s.started { | ||
1709 | 53 | return | ||
1710 | 54 | } | ||
1711 | 55 | s.started = true | ||
1712 | 56 | |||
1713 | 57 | s.body = make(chan []byte, 64) | ||
1714 | 58 | s.request = make(chan *http.Request, 64) | ||
1715 | 59 | s.response = make(chan *testResponse, 64) | ||
1716 | 60 | s.pending = make(chan bool, 64) | ||
1717 | 61 | |||
1718 | 62 | url, _ := url.Parse(s.URL) | ||
1719 | 63 | go http.ListenAndServe(url.Host, s) | ||
1720 | 64 | |||
1721 | 65 | s.PrepareResponse(202, nil, "Nothing.") | ||
1722 | 66 | for { | ||
1723 | 67 | // Wait for it to be up. | ||
1724 | 68 | resp, err := http.Get(s.URL) | ||
1725 | 69 | if err == nil && resp.StatusCode == 202 { | ||
1726 | 70 | break | ||
1727 | 71 | } | ||
1728 | 72 | fmt.Fprintf(os.Stderr, "\nWaiting for fake server to be up... ") | ||
1729 | 73 | time.Sleep(1e8) | ||
1730 | 74 | } | ||
1731 | 75 | fmt.Fprintf(os.Stderr, "done\n\n") | ||
1732 | 76 | s.WaitRequest() // Consume dummy request. | ||
1733 | 77 | } | ||
1734 | 78 | |||
1735 | 79 | // FlushRequests discards requests which were not yet consumed by WaitRequest. | ||
1736 | 80 | func (s *TestHTTPServer) FlushRequests() { | ||
1737 | 81 | for { | ||
1738 | 82 | select { | ||
1739 | 83 | case <-s.request: | ||
1740 | 84 | default: | ||
1741 | 85 | return | ||
1742 | 86 | } | ||
1743 | 87 | } | ||
1744 | 88 | } | ||
1745 | 89 | |||
1746 | 90 | func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
1747 | 91 | b, _ := ioutil.ReadAll(req.Body) | ||
1748 | 92 | s.body <- b | ||
1749 | 93 | s.request <- req | ||
1750 | 94 | var resp *testResponse | ||
1751 | 95 | select { | ||
1752 | 96 | case resp = <-s.response: | ||
1753 | 97 | case <-time.After(s.Timeout): | ||
1754 | 98 | fmt.Fprintf(os.Stderr, "ERROR: Timeout waiting for test to provide response\n") | ||
1755 | 99 | resp = &testResponse{500, nil, ""} | ||
1756 | 100 | } | ||
1757 | 101 | if resp.Headers != nil { | ||
1758 | 102 | h := w.Header() | ||
1759 | 103 | for k, v := range resp.Headers { | ||
1760 | 104 | h.Set(k, v) | ||
1761 | 105 | } | ||
1762 | 106 | } | ||
1763 | 107 | if resp.Status != 0 { | ||
1764 | 108 | w.WriteHeader(resp.Status) | ||
1765 | 109 | } | ||
1766 | 110 | w.Write([]byte(resp.Body)) | ||
1767 | 111 | } | ||
1768 | 112 | |||
1769 | 113 | func (s *TestHTTPServer) WaitRequest() *http.Request { | ||
1770 | 114 | select { | ||
1771 | 115 | case req := <-s.request: | ||
1772 | 116 | body := <-s.body | ||
1773 | 117 | req.Body = ioutil.NopCloser(bytes.NewReader(body)) | ||
1774 | 118 | req.ParseForm() | ||
1775 | 119 | return req | ||
1776 | 120 | case <-time.After(s.Timeout): | ||
1777 | 121 | panic("Timeout waiting for goamz request") | ||
1778 | 122 | } | ||
1779 | 123 | panic("unreached") | ||
1780 | 124 | } | ||
1781 | 125 | |||
1782 | 126 | func (s *TestHTTPServer) PrepareResponse(status int, headers map[string]string, body string) { | ||
1783 | 127 | s.response <- &testResponse{status, headers, body} | ||
1784 | 128 | } | ||
1785 | 129 | 0 | ||
1786 | === modified file 's3/s3.go' | |||
1787 | --- s3/s3.go 2012-12-10 05:30:05 +0000 | |||
1788 | +++ s3/s3.go 2013-01-31 17:09:20 +0000 | |||
1789 | @@ -67,7 +67,7 @@ | |||
1790 | 67 | // locationConstraint returns an io.Reader specifying a LocationConstraint if | 67 | // locationConstraint returns an io.Reader specifying a LocationConstraint if |
1791 | 68 | // required for the region. | 68 | // required for the region. |
1792 | 69 | // | 69 | // |
1794 | 70 | // See http://goo.gl/bh9Kq for more details. | 70 | // See http://goo.gl/bh9Kq for details. |
1795 | 71 | func (s3 *S3) locationConstraint() io.Reader { | 71 | func (s3 *S3) locationConstraint() io.Reader { |
1796 | 72 | constraint := "" | 72 | constraint := "" |
1797 | 73 | if s3.Region.S3LocationConstraint { | 73 | if s3.Region.S3LocationConstraint { |
1798 | @@ -89,7 +89,7 @@ | |||
1799 | 89 | 89 | ||
1800 | 90 | // PutBucket creates a new bucket. | 90 | // PutBucket creates a new bucket. |
1801 | 91 | // | 91 | // |
1803 | 92 | // See http://goo.gl/ndjnR for more details. | 92 | // See http://goo.gl/ndjnR for details. |
1804 | 93 | func (b *Bucket) PutBucket(perm ACL) error { | 93 | func (b *Bucket) PutBucket(perm ACL) error { |
1805 | 94 | headers := map[string][]string{ | 94 | headers := map[string][]string{ |
1806 | 95 | "x-amz-acl": {string(perm)}, | 95 | "x-amz-acl": {string(perm)}, |
1807 | @@ -107,7 +107,7 @@ | |||
1808 | 107 | // DelBucket removes an existing S3 bucket. All objects in the bucket must | 107 | // DelBucket removes an existing S3 bucket. All objects in the bucket must |
1809 | 108 | // be removed before the bucket itself can be removed. | 108 | // be removed before the bucket itself can be removed. |
1810 | 109 | // | 109 | // |
1812 | 110 | // See http://goo.gl/GoBrY for more details. | 110 | // See http://goo.gl/GoBrY for details. |
1813 | 111 | func (b *Bucket) DelBucket() error { | 111 | func (b *Bucket) DelBucket() error { |
1814 | 112 | req := &request{ | 112 | req := &request{ |
1815 | 113 | method: "DELETE", | 113 | method: "DELETE", |
1816 | @@ -117,9 +117,14 @@ | |||
1817 | 117 | return b.S3.query(req, nil) | 117 | return b.S3.query(req, nil) |
1818 | 118 | } | 118 | } |
1819 | 119 | 119 | ||
1820 | 120 | func hasCode(err error, code string) bool { | ||
1821 | 121 | s3err, ok := err.(*Error) | ||
1822 | 122 | return ok && s3err.Code == code | ||
1823 | 123 | } | ||
1824 | 124 | |||
1825 | 120 | // Get retrieves an object from an S3 bucket. | 125 | // Get retrieves an object from an S3 bucket. |
1826 | 121 | // | 126 | // |
1828 | 122 | // See http://goo.gl/isCO7 for more details. | 127 | // See http://goo.gl/isCO7 for details. |
1829 | 123 | func (b *Bucket) Get(path string) (data []byte, err error) { | 128 | func (b *Bucket) Get(path string) (data []byte, err error) { |
1830 | 124 | body, err := b.GetReader(path) | 129 | body, err := b.GetReader(path) |
1831 | 125 | if err != nil { | 130 | if err != nil { |
1832 | @@ -151,7 +156,7 @@ | |||
1833 | 151 | 156 | ||
1834 | 152 | // Put inserts an object into the S3 bucket. | 157 | // Put inserts an object into the S3 bucket. |
1835 | 153 | // | 158 | // |
1837 | 154 | // See http://goo.gl/FEBPD for more details. | 159 | // See http://goo.gl/FEBPD for details. |
1838 | 155 | func (b *Bucket) Put(path string, data []byte, contType string, perm ACL) error { | 160 | func (b *Bucket) Put(path string, data []byte, contType string, perm ACL) error { |
1839 | 156 | body := bytes.NewBuffer(data) | 161 | body := bytes.NewBuffer(data) |
1840 | 157 | return b.PutReader(path, body, int64(len(data)), contType, perm) | 162 | return b.PutReader(path, body, int64(len(data)), contType, perm) |
1841 | @@ -177,7 +182,7 @@ | |||
1842 | 177 | 182 | ||
1843 | 178 | // Del removes an object from the S3 bucket. | 183 | // Del removes an object from the S3 bucket. |
1844 | 179 | // | 184 | // |
1846 | 180 | // See http://goo.gl/APeTt for more details. | 185 | // See http://goo.gl/APeTt for details. |
1847 | 181 | func (b *Bucket) Del(path string) error { | 186 | func (b *Bucket) Del(path string) error { |
1848 | 182 | req := &request{ | 187 | req := &request{ |
1849 | 183 | method: "DELETE", | 188 | method: "DELETE", |
1850 | @@ -215,15 +220,15 @@ | |||
1851 | 215 | Owner Owner | 220 | Owner Owner |
1852 | 216 | } | 221 | } |
1853 | 217 | 222 | ||
1855 | 218 | // List returns a information about objects in an S3 bucket. | 223 | // List returns information about objects in an S3 bucket. |
1856 | 219 | // | 224 | // |
1857 | 220 | // The prefix parameter limits the response to keys that begin with the | 225 | // The prefix parameter limits the response to keys that begin with the |
1860 | 221 | // specified prefix. You can use prefixes to separate a bucket into different | 226 | // specified prefix. |
1859 | 222 | // groupings of keys (e.g. to get a feeling of folders). | ||
1861 | 223 | // | 227 | // |
1865 | 224 | // The delimited parameter causes the response to group all of the keys that | 228 | // The delim parameter causes the response to group all of the keys that |
1866 | 225 | // share a common prefix up to the next delimiter to be grouped in a single | 229 | // share a common prefix up to the next delimiter in a single entry within |
1867 | 226 | // entry within the CommonPrefixes field. | 230 | // the CommonPrefixes field. You can use delimiters to separate a bucket |
1868 | 231 | // into different groupings of keys, similar to how folders would work. | ||
1869 | 227 | // | 232 | // |
1870 | 228 | // The marker parameter specifies the key to start with when listing objects | 233 | // The marker parameter specifies the key to start with when listing objects |
1871 | 229 | // in a bucket. Amazon S3 lists objects in alphabetical order and | 234 | // in a bucket. Amazon S3 lists objects in alphabetical order and |
1872 | @@ -270,7 +275,7 @@ | |||
1873 | 270 | // }, | 275 | // }, |
1874 | 271 | // } | 276 | // } |
1875 | 272 | // | 277 | // |
1877 | 273 | // See http://goo.gl/YjQTc for more details. | 278 | // See http://goo.gl/YjQTc for details. |
1878 | 274 | func (b *Bucket) List(prefix, delim, marker string, max int) (result *ListResp, err error) { | 279 | func (b *Bucket) List(prefix, delim, marker string, max int) (result *ListResp, err error) { |
1879 | 275 | params := map[string][]string{ | 280 | params := map[string][]string{ |
1880 | 276 | "prefix": {prefix}, | 281 | "prefix": {prefix}, |
1881 | 277 | 282 | ||
1882 | === modified file 's3/s3_test.go' | |||
1883 | --- s3/s3_test.go 2012-07-05 05:47:52 +0000 | |||
1884 | +++ s3/s3_test.go 2013-01-31 17:09:20 +0000 | |||
1885 | @@ -4,29 +4,40 @@ | |||
1886 | 4 | "bytes" | 4 | "bytes" |
1887 | 5 | "io/ioutil" | 5 | "io/ioutil" |
1888 | 6 | "net/http" | 6 | "net/http" |
1889 | 7 | "testing" | ||
1890 | 7 | 8 | ||
1891 | 8 | "launchpad.net/goamz/aws" | 9 | "launchpad.net/goamz/aws" |
1892 | 9 | "launchpad.net/goamz/s3" | 10 | "launchpad.net/goamz/s3" |
1893 | 11 | "launchpad.net/goamz/testutil" | ||
1894 | 10 | . "launchpad.net/gocheck" | 12 | . "launchpad.net/gocheck" |
1895 | 11 | ) | 13 | ) |
1896 | 12 | 14 | ||
1898 | 13 | var _ = Suite(&S{}) | 15 | func Test(t *testing.T) { |
1899 | 16 | TestingT(t) | ||
1900 | 17 | } | ||
1901 | 14 | 18 | ||
1902 | 15 | type S struct { | 19 | type S struct { |
1903 | 16 | HTTPSuite | ||
1904 | 17 | s3 *s3.S3 | 20 | s3 *s3.S3 |
1905 | 18 | } | 21 | } |
1906 | 19 | 22 | ||
1907 | 23 | var _ = Suite(&S{}) | ||
1908 | 24 | |||
1909 | 25 | var testServer = testutil.NewHTTPServer() | ||
1910 | 26 | |||
1911 | 20 | func (s *S) SetUpSuite(c *C) { | 27 | func (s *S) SetUpSuite(c *C) { |
1913 | 21 | s.HTTPSuite.SetUpSuite(c) | 28 | testServer.Start() |
1914 | 22 | auth := aws.Auth{"abc", "123"} | 29 | auth := aws.Auth{"abc", "123"} |
1915 | 23 | s.s3 = s3.New(auth, aws.Region{Name: "faux-region-1", S3Endpoint: testServer.URL}) | 30 | s.s3 = s3.New(auth, aws.Region{Name: "faux-region-1", S3Endpoint: testServer.URL}) |
1916 | 24 | } | 31 | } |
1917 | 25 | 32 | ||
1918 | 33 | func (s *S) TearDownTest(c *C) { | ||
1919 | 34 | testServer.Flush() | ||
1920 | 35 | } | ||
1921 | 36 | |||
1922 | 26 | // PutBucket docs: http://goo.gl/kBTCu | 37 | // PutBucket docs: http://goo.gl/kBTCu |
1923 | 27 | 38 | ||
1924 | 28 | func (s *S) TestPutBucket(c *C) { | 39 | func (s *S) TestPutBucket(c *C) { |
1926 | 29 | testServer.PrepareResponse(200, nil, "") | 40 | testServer.Response(200, nil, "") |
1927 | 30 | 41 | ||
1928 | 31 | b := s.s3.Bucket("bucket") | 42 | b := s.s3.Bucket("bucket") |
1929 | 32 | err := b.PutBucket(s3.Private) | 43 | err := b.PutBucket(s3.Private) |
1930 | @@ -41,7 +52,7 @@ | |||
1931 | 41 | // DeleteBucket docs: http://goo.gl/GoBrY | 52 | // DeleteBucket docs: http://goo.gl/GoBrY |
1932 | 42 | 53 | ||
1933 | 43 | func (s *S) TestDelBucket(c *C) { | 54 | func (s *S) TestDelBucket(c *C) { |
1935 | 44 | testServer.PrepareResponse(204, nil, "") | 55 | testServer.Response(204, nil, "") |
1936 | 45 | 56 | ||
1937 | 46 | b := s.s3.Bucket("bucket") | 57 | b := s.s3.Bucket("bucket") |
1938 | 47 | err := b.DelBucket() | 58 | err := b.DelBucket() |
1939 | @@ -56,7 +67,7 @@ | |||
1940 | 56 | // GetObject docs: http://goo.gl/isCO7 | 67 | // GetObject docs: http://goo.gl/isCO7 |
1941 | 57 | 68 | ||
1942 | 58 | func (s *S) TestGet(c *C) { | 69 | func (s *S) TestGet(c *C) { |
1944 | 59 | testServer.PrepareResponse(200, nil, "content") | 70 | testServer.Response(200, nil, "content") |
1945 | 60 | 71 | ||
1946 | 61 | b := s.s3.Bucket("bucket") | 72 | b := s.s3.Bucket("bucket") |
1947 | 62 | data, err := b.Get("name") | 73 | data, err := b.Get("name") |
1948 | @@ -71,7 +82,7 @@ | |||
1949 | 71 | } | 82 | } |
1950 | 72 | 83 | ||
1951 | 73 | func (s *S) TestURL(c *C) { | 84 | func (s *S) TestURL(c *C) { |
1953 | 74 | testServer.PrepareResponse(200, nil, "content") | 85 | testServer.Response(200, nil, "content") |
1954 | 75 | 86 | ||
1955 | 76 | b := s.s3.Bucket("bucket") | 87 | b := s.s3.Bucket("bucket") |
1956 | 77 | url := b.URL("name") | 88 | url := b.URL("name") |
1957 | @@ -88,7 +99,7 @@ | |||
1958 | 88 | } | 99 | } |
1959 | 89 | 100 | ||
1960 | 90 | func (s *S) TestGetReader(c *C) { | 101 | func (s *S) TestGetReader(c *C) { |
1962 | 91 | testServer.PrepareResponse(200, nil, "content") | 102 | testServer.Response(200, nil, "content") |
1963 | 92 | 103 | ||
1964 | 93 | b := s.s3.Bucket("bucket") | 104 | b := s.s3.Bucket("bucket") |
1965 | 94 | rc, err := b.GetReader("name") | 105 | rc, err := b.GetReader("name") |
1966 | @@ -105,7 +116,7 @@ | |||
1967 | 105 | } | 116 | } |
1968 | 106 | 117 | ||
1969 | 107 | func (s *S) TestGetNotFound(c *C) { | 118 | func (s *S) TestGetNotFound(c *C) { |
1971 | 108 | testServer.PrepareResponse(404, nil, GetObjectErrorDump) | 119 | testServer.Response(404, nil, GetObjectErrorDump) |
1972 | 109 | 120 | ||
1973 | 110 | b := s.s3.Bucket("non-existent-bucket") | 121 | b := s.s3.Bucket("non-existent-bucket") |
1974 | 111 | data, err := b.Get("non-existent") | 122 | data, err := b.Get("non-existent") |
1975 | @@ -130,7 +141,7 @@ | |||
1976 | 130 | // PutObject docs: http://goo.gl/FEBPD | 141 | // PutObject docs: http://goo.gl/FEBPD |
1977 | 131 | 142 | ||
1978 | 132 | func (s *S) TestPutObject(c *C) { | 143 | func (s *S) TestPutObject(c *C) { |
1980 | 133 | testServer.PrepareResponse(200, nil, "") | 144 | testServer.Response(200, nil, "") |
1981 | 134 | 145 | ||
1982 | 135 | b := s.s3.Bucket("bucket") | 146 | b := s.s3.Bucket("bucket") |
1983 | 136 | err := b.Put("name", []byte("content"), "content-type", s3.Private) | 147 | err := b.Put("name", []byte("content"), "content-type", s3.Private) |
1984 | @@ -147,7 +158,7 @@ | |||
1985 | 147 | } | 158 | } |
1986 | 148 | 159 | ||
1987 | 149 | func (s *S) TestPutReader(c *C) { | 160 | func (s *S) TestPutReader(c *C) { |
1989 | 150 | testServer.PrepareResponse(200, nil, "") | 161 | testServer.Response(200, nil, "") |
1990 | 151 | 162 | ||
1991 | 152 | b := s.s3.Bucket("bucket") | 163 | b := s.s3.Bucket("bucket") |
1992 | 153 | buf := bytes.NewBufferString("content") | 164 | buf := bytes.NewBufferString("content") |
1993 | @@ -167,7 +178,7 @@ | |||
1994 | 167 | // DelObject docs: http://goo.gl/APeTt | 178 | // DelObject docs: http://goo.gl/APeTt |
1995 | 168 | 179 | ||
1996 | 169 | func (s *S) TestDelObject(c *C) { | 180 | func (s *S) TestDelObject(c *C) { |
1998 | 170 | testServer.PrepareResponse(200, nil, "") | 181 | testServer.Response(200, nil, "") |
1999 | 171 | 182 | ||
2000 | 172 | b := s.s3.Bucket("bucket") | 183 | b := s.s3.Bucket("bucket") |
2001 | 173 | err := b.Del("name") | 184 | err := b.Del("name") |
2002 | @@ -182,7 +193,7 @@ | |||
2003 | 182 | // Bucket List Objects docs: http://goo.gl/YjQTc | 193 | // Bucket List Objects docs: http://goo.gl/YjQTc |
2004 | 183 | 194 | ||
2005 | 184 | func (s *S) TestList(c *C) { | 195 | func (s *S) TestList(c *C) { |
2007 | 185 | testServer.PrepareResponse(200, nil, GetListResultDump1) | 196 | testServer.Response(200, nil, GetListResultDump1) |
2008 | 186 | 197 | ||
2009 | 187 | b := s.s3.Bucket("quotes") | 198 | b := s.s3.Bucket("quotes") |
2010 | 188 | 199 | ||
2011 | @@ -221,7 +232,7 @@ | |||
2012 | 221 | } | 232 | } |
2013 | 222 | 233 | ||
2014 | 223 | func (s *S) TestListWithDelimiter(c *C) { | 234 | func (s *S) TestListWithDelimiter(c *C) { |
2016 | 224 | testServer.PrepareResponse(200, nil, GetListResultDump2) | 235 | testServer.Response(200, nil, GetListResultDump2) |
2017 | 225 | 236 | ||
2018 | 226 | b := s.s3.Bucket("quotes") | 237 | b := s.s3.Bucket("quotes") |
2019 | 227 | 238 | ||
2020 | 228 | 239 | ||
2021 | === modified file 's3/s3i_test.go' | |||
2022 | --- s3/s3i_test.go 2013-01-28 13:30:10 +0000 | |||
2023 | +++ s3/s3i_test.go 2013-01-31 17:09:20 +0000 | |||
2024 | @@ -10,6 +10,7 @@ | |||
2025 | 10 | 10 | ||
2026 | 11 | "launchpad.net/goamz/aws" | 11 | "launchpad.net/goamz/aws" |
2027 | 12 | "launchpad.net/goamz/s3" | 12 | "launchpad.net/goamz/s3" |
2028 | 13 | "launchpad.net/goamz/testutil" | ||
2029 | 13 | . "launchpad.net/gocheck" | 14 | . "launchpad.net/gocheck" |
2030 | 14 | "time" | 15 | "time" |
2031 | 15 | ) | 16 | ) |
2032 | @@ -45,7 +46,7 @@ | |||
2033 | 45 | } | 46 | } |
2034 | 46 | 47 | ||
2035 | 47 | func (s *AmazonClientSuite) SetUpSuite(c *C) { | 48 | func (s *AmazonClientSuite) SetUpSuite(c *C) { |
2037 | 48 | if !*amazon { | 49 | if !testutil.Amazon { |
2038 | 49 | c.Skip("live tests against AWS disabled (no -amazon)") | 50 | c.Skip("live tests against AWS disabled (no -amazon)") |
2039 | 50 | } | 51 | } |
2040 | 51 | s.srv.SetUp(c) | 52 | s.srv.SetUp(c) |
2041 | @@ -62,7 +63,7 @@ | |||
2042 | 62 | } | 63 | } |
2043 | 63 | 64 | ||
2044 | 64 | func (s *AmazonDomainClientSuite) SetUpSuite(c *C) { | 65 | func (s *AmazonDomainClientSuite) SetUpSuite(c *C) { |
2046 | 65 | if !*amazon { | 66 | if !testutil.Amazon { |
2047 | 66 | c.Skip("live tests against AWS disabled (no -amazon)") | 67 | c.Skip("live tests against AWS disabled (no -amazon)") |
2048 | 67 | } | 68 | } |
2049 | 68 | s.srv.SetUp(c) | 69 | s.srv.SetUp(c) |
2050 | @@ -102,12 +103,15 @@ | |||
2051 | 102 | 103 | ||
2052 | 103 | func (s *ClientTests) TestBasicFunctionality(c *C) { | 104 | func (s *ClientTests) TestBasicFunctionality(c *C) { |
2053 | 104 | b := s.Bucket(testBucket) | 105 | b := s.Bucket(testBucket) |
2054 | 106 | b.DelBucket() | ||
2055 | 107 | |||
2056 | 105 | err := b.PutBucket(s3.PublicRead) | 108 | err := b.PutBucket(s3.PublicRead) |
2057 | 106 | c.Assert(err, IsNil) | 109 | c.Assert(err, IsNil) |
2058 | 107 | defer b.DelBucket() | 110 | defer b.DelBucket() |
2059 | 108 | 111 | ||
2060 | 109 | err = b.Put("name", []byte("yo!"), "text/plain", s3.PublicRead) | 112 | err = b.Put("name", []byte("yo!"), "text/plain", s3.PublicRead) |
2061 | 110 | c.Assert(err, IsNil) | 113 | c.Assert(err, IsNil) |
2062 | 114 | defer b.Del("name") | ||
2063 | 111 | 115 | ||
2064 | 112 | data, err := b.Get("name") | 116 | data, err := b.Get("name") |
2065 | 113 | c.Assert(err, IsNil) | 117 | c.Assert(err, IsNil) |
2066 | @@ -120,6 +124,7 @@ | |||
2067 | 120 | buf := bytes.NewBufferString("hey!") | 124 | buf := bytes.NewBufferString("hey!") |
2068 | 121 | err = b.PutReader("name2", buf, int64(buf.Len()), "text/plain", s3.Private) | 125 | err = b.PutReader("name2", buf, int64(buf.Len()), "text/plain", s3.Private) |
2069 | 122 | c.Assert(err, IsNil) | 126 | c.Assert(err, IsNil) |
2070 | 127 | defer b.Del("name2") | ||
2071 | 123 | 128 | ||
2072 | 124 | rc, err := b.GetReader("name2") | 129 | rc, err := b.GetReader("name2") |
2073 | 125 | c.Assert(err, IsNil) | 130 | c.Assert(err, IsNil) |
2074 | @@ -225,16 +230,13 @@ | |||
2075 | 225 | // normal list. | 230 | // normal list. |
2076 | 226 | { | 231 | { |
2077 | 227 | Contents: keys(objectNames...), | 232 | Contents: keys(objectNames...), |
2080 | 228 | }, | 233 | }, { |
2079 | 229 | { | ||
2081 | 230 | Marker: objectNames[0], | 234 | Marker: objectNames[0], |
2082 | 231 | Contents: keys(objectNames[1:]...), | 235 | Contents: keys(objectNames[1:]...), |
2085 | 232 | }, | 236 | }, { |
2084 | 233 | { | ||
2086 | 234 | Marker: objectNames[0] + "a", | 237 | Marker: objectNames[0] + "a", |
2087 | 235 | Contents: keys(objectNames[1:]...), | 238 | Contents: keys(objectNames[1:]...), |
2090 | 236 | }, | 239 | }, { |
2089 | 237 | { | ||
2091 | 238 | Marker: "z", | 240 | Marker: "z", |
2092 | 239 | }, | 241 | }, |
2093 | 240 | 242 | ||
2094 | @@ -243,14 +245,12 @@ | |||
2095 | 243 | MaxKeys: 2, | 245 | MaxKeys: 2, |
2096 | 244 | Contents: keys(objectNames[0:2]...), | 246 | Contents: keys(objectNames[0:2]...), |
2097 | 245 | IsTruncated: true, | 247 | IsTruncated: true, |
2100 | 246 | }, | 248 | }, { |
2099 | 247 | { | ||
2101 | 248 | MaxKeys: 2, | 249 | MaxKeys: 2, |
2102 | 249 | Marker: objectNames[0], | 250 | Marker: objectNames[0], |
2103 | 250 | Contents: keys(objectNames[1:3]...), | 251 | Contents: keys(objectNames[1:3]...), |
2104 | 251 | IsTruncated: true, | 252 | IsTruncated: true, |
2107 | 252 | }, | 253 | }, { |
2106 | 253 | { | ||
2108 | 254 | MaxKeys: 2, | 254 | MaxKeys: 2, |
2109 | 255 | Marker: objectNames[len(objectNames)-2], | 255 | Marker: objectNames[len(objectNames)-2], |
2110 | 256 | Contents: keys(objectNames[len(objectNames)-1:]...), | 256 | Contents: keys(objectNames[len(objectNames)-1:]...), |
2111 | @@ -261,38 +261,32 @@ | |||
2112 | 261 | Delimiter: "/", | 261 | Delimiter: "/", |
2113 | 262 | CommonPrefixes: []string{"photos/", "test/"}, | 262 | CommonPrefixes: []string{"photos/", "test/"}, |
2114 | 263 | Contents: keys("index.html", "index2.html"), | 263 | Contents: keys("index.html", "index2.html"), |
2117 | 264 | }, | 264 | }, { |
2116 | 265 | { | ||
2118 | 266 | Delimiter: "/", | 265 | Delimiter: "/", |
2119 | 267 | Prefix: "photos/2006/", | 266 | Prefix: "photos/2006/", |
2120 | 268 | CommonPrefixes: []string{"photos/2006/February/", "photos/2006/January/"}, | 267 | CommonPrefixes: []string{"photos/2006/February/", "photos/2006/January/"}, |
2123 | 269 | }, | 268 | }, { |
2122 | 270 | { | ||
2124 | 271 | Delimiter: "/", | 269 | Delimiter: "/", |
2125 | 272 | Prefix: "t", | 270 | Prefix: "t", |
2126 | 273 | CommonPrefixes: []string{"test/"}, | 271 | CommonPrefixes: []string{"test/"}, |
2129 | 274 | }, | 272 | }, { |
2128 | 275 | { | ||
2130 | 276 | Delimiter: "/", | 273 | Delimiter: "/", |
2131 | 277 | MaxKeys: 1, | 274 | MaxKeys: 1, |
2132 | 278 | Contents: keys("index.html"), | 275 | Contents: keys("index.html"), |
2133 | 279 | IsTruncated: true, | 276 | IsTruncated: true, |
2136 | 280 | }, | 277 | }, { |
2135 | 281 | { | ||
2137 | 282 | Delimiter: "/", | 278 | Delimiter: "/", |
2138 | 283 | MaxKeys: 1, | 279 | MaxKeys: 1, |
2139 | 284 | Marker: "index2.html", | 280 | Marker: "index2.html", |
2140 | 285 | CommonPrefixes: []string{"photos/"}, | 281 | CommonPrefixes: []string{"photos/"}, |
2141 | 286 | IsTruncated: true, | 282 | IsTruncated: true, |
2144 | 287 | }, | 283 | }, { |
2143 | 288 | { | ||
2145 | 289 | Delimiter: "/", | 284 | Delimiter: "/", |
2146 | 290 | MaxKeys: 1, | 285 | MaxKeys: 1, |
2147 | 291 | Marker: "photos/", | 286 | Marker: "photos/", |
2148 | 292 | CommonPrefixes: []string{"test/"}, | 287 | CommonPrefixes: []string{"test/"}, |
2149 | 293 | IsTruncated: false, | 288 | IsTruncated: false, |
2152 | 294 | }, | 289 | }, { |
2151 | 295 | { | ||
2153 | 296 | Delimiter: "Feb", | 290 | Delimiter: "Feb", |
2154 | 297 | CommonPrefixes: []string{"photos/2006/Feb"}, | 291 | CommonPrefixes: []string{"photos/2006/Feb"}, |
2155 | 298 | Contents: keys("index.html", "index2.html", "photos/2006/January/sample.jpg", "test/bar", "test/foo"), | 292 | Contents: keys("index.html", "index2.html", "photos/2006/January/sample.jpg", "test/bar", "test/foo"), |
2156 | 299 | 293 | ||
2157 | === removed file 's3/suite_test.go' | |||
2158 | --- s3/suite_test.go 2012-05-02 15:22:53 +0000 | |||
2159 | +++ s3/suite_test.go 1970-01-01 00:00:00 +0000 | |||
2160 | @@ -1,139 +0,0 @@ | |||
2161 | 1 | package s3_test | ||
2162 | 2 | |||
2163 | 3 | import ( | ||
2164 | 4 | "flag" | ||
2165 | 5 | "fmt" | ||
2166 | 6 | "launchpad.net/goamz/aws" | ||
2167 | 7 | . "launchpad.net/gocheck" | ||
2168 | 8 | "net/http" | ||
2169 | 9 | "net/url" | ||
2170 | 10 | "os" | ||
2171 | 11 | "testing" | ||
2172 | 12 | "time" | ||
2173 | 13 | ) | ||
2174 | 14 | |||
2175 | 15 | func Test(t *testing.T) { | ||
2176 | 16 | TestingT(t) | ||
2177 | 17 | } | ||
2178 | 18 | |||
2179 | 19 | var amazon = flag.Bool("amazon", false, "Enable tests against amazon server") | ||
2180 | 20 | |||
2181 | 21 | type SuiteI struct { | ||
2182 | 22 | auth aws.Auth | ||
2183 | 23 | } | ||
2184 | 24 | |||
2185 | 25 | func (s *SuiteI) SetUpSuite(c *C) { | ||
2186 | 26 | if !*amazon { | ||
2187 | 27 | c.Skip("amazon tests not enabled (-amazon flag)") | ||
2188 | 28 | } | ||
2189 | 29 | auth, err := aws.EnvAuth() | ||
2190 | 30 | if err != nil { | ||
2191 | 31 | c.Fatal(err.Error()) | ||
2192 | 32 | } | ||
2193 | 33 | s.auth = auth | ||
2194 | 34 | } | ||
2195 | 35 | |||
2196 | 36 | type HTTPSuite struct{} | ||
2197 | 37 | |||
2198 | 38 | var testServer = NewTestHTTPServer("http://localhost:4444", 5*time.Second) | ||
2199 | 39 | |||
2200 | 40 | func (s *HTTPSuite) SetUpSuite(c *C) { | ||
2201 | 41 | testServer.Start() | ||
2202 | 42 | } | ||
2203 | 43 | |||
2204 | 44 | func (s *HTTPSuite) TearDownTest(c *C) { | ||
2205 | 45 | testServer.FlushRequests() | ||
2206 | 46 | } | ||
2207 | 47 | |||
2208 | 48 | type TestHTTPServer struct { | ||
2209 | 49 | URL string | ||
2210 | 50 | Timeout time.Duration | ||
2211 | 51 | started bool | ||
2212 | 52 | request chan *http.Request | ||
2213 | 53 | response chan *testResponse | ||
2214 | 54 | pending chan bool | ||
2215 | 55 | } | ||
2216 | 56 | |||
2217 | 57 | type testResponse struct { | ||
2218 | 58 | Status int | ||
2219 | 59 | Headers map[string]string | ||
2220 | 60 | Body string | ||
2221 | 61 | } | ||
2222 | 62 | |||
2223 | 63 | func NewTestHTTPServer(url string, timeout time.Duration) *TestHTTPServer { | ||
2224 | 64 | return &TestHTTPServer{URL: url, Timeout: timeout} | ||
2225 | 65 | } | ||
2226 | 66 | |||
2227 | 67 | func (s *TestHTTPServer) Start() { | ||
2228 | 68 | if s.started { | ||
2229 | 69 | return | ||
2230 | 70 | } | ||
2231 | 71 | s.started = true | ||
2232 | 72 | |||
2233 | 73 | s.request = make(chan *http.Request, 64) | ||
2234 | 74 | s.response = make(chan *testResponse, 64) | ||
2235 | 75 | s.pending = make(chan bool, 64) | ||
2236 | 76 | |||
2237 | 77 | url, _ := url.Parse(s.URL) | ||
2238 | 78 | go http.ListenAndServe(url.Host, s) | ||
2239 | 79 | |||
2240 | 80 | s.PrepareResponse(202, nil, "Nothing.") | ||
2241 | 81 | for { | ||
2242 | 82 | // Wait for it to be up. | ||
2243 | 83 | resp, err := http.Get(s.URL) | ||
2244 | 84 | if err == nil && resp.StatusCode == 202 { | ||
2245 | 85 | break | ||
2246 | 86 | } | ||
2247 | 87 | fmt.Fprintf(os.Stderr, "\nWaiting for fake server to be up... ") | ||
2248 | 88 | time.Sleep(1e8) | ||
2249 | 89 | } | ||
2250 | 90 | fmt.Fprintf(os.Stderr, "done\n\n") | ||
2251 | 91 | s.WaitRequest() // Consume dummy request. | ||
2252 | 92 | } | ||
2253 | 93 | |||
2254 | 94 | // FlushRequests discards requests which were not yet consumed by WaitRequest. | ||
2255 | 95 | func (s *TestHTTPServer) FlushRequests() { | ||
2256 | 96 | for { | ||
2257 | 97 | select { | ||
2258 | 98 | case <-s.request: | ||
2259 | 99 | default: | ||
2260 | 100 | return | ||
2261 | 101 | } | ||
2262 | 102 | } | ||
2263 | 103 | } | ||
2264 | 104 | |||
2265 | 105 | func (s *TestHTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
2266 | 106 | s.request <- req | ||
2267 | 107 | var resp *testResponse | ||
2268 | 108 | select { | ||
2269 | 109 | case resp = <-s.response: | ||
2270 | 110 | case <-time.After(s.Timeout): | ||
2271 | 111 | fmt.Fprintf(os.Stderr, "ERROR: Timeout waiting for test to provide response\n") | ||
2272 | 112 | resp = &testResponse{500, nil, ""} | ||
2273 | 113 | } | ||
2274 | 114 | if resp.Headers != nil { | ||
2275 | 115 | h := w.Header() | ||
2276 | 116 | for k, v := range resp.Headers { | ||
2277 | 117 | h.Set(k, v) | ||
2278 | 118 | } | ||
2279 | 119 | } | ||
2280 | 120 | if resp.Status != 0 { | ||
2281 | 121 | w.WriteHeader(resp.Status) | ||
2282 | 122 | } | ||
2283 | 123 | w.Write([]byte(resp.Body)) | ||
2284 | 124 | } | ||
2285 | 125 | |||
2286 | 126 | func (s *TestHTTPServer) WaitRequest() *http.Request { | ||
2287 | 127 | select { | ||
2288 | 128 | case req := <-s.request: | ||
2289 | 129 | req.ParseForm() | ||
2290 | 130 | return req | ||
2291 | 131 | case <-time.After(s.Timeout): | ||
2292 | 132 | panic("Timeout waiting for goamz request") | ||
2293 | 133 | } | ||
2294 | 134 | panic("unreached") | ||
2295 | 135 | } | ||
2296 | 136 | |||
2297 | 137 | func (s *TestHTTPServer) PrepareResponse(status int, headers map[string]string, body string) { | ||
2298 | 138 | s.response <- &testResponse{status, headers, body} | ||
2299 | 139 | } | ||
2300 | 140 | 0 | ||
2301 | === added directory 'testutil' | |||
2302 | === added file 'testutil/http.go' | |||
2303 | --- testutil/http.go 1970-01-01 00:00:00 +0000 | |||
2304 | +++ testutil/http.go 2013-01-31 17:09:20 +0000 | |||
2305 | @@ -0,0 +1,174 @@ | |||
2306 | 1 | package testutil | ||
2307 | 2 | |||
2308 | 3 | import ( | ||
2309 | 4 | "bytes" | ||
2310 | 5 | "fmt" | ||
2311 | 6 | "io/ioutil" | ||
2312 | 7 | "net" | ||
2313 | 8 | "net/http" | ||
2314 | 9 | "net/url" | ||
2315 | 10 | "os" | ||
2316 | 11 | "time" | ||
2317 | 12 | ) | ||
2318 | 13 | |||
2319 | 14 | type HTTPServer struct { | ||
2320 | 15 | URL string | ||
2321 | 16 | Timeout time.Duration | ||
2322 | 17 | started bool | ||
2323 | 18 | request chan *http.Request | ||
2324 | 19 | response chan ResponseFunc | ||
2325 | 20 | } | ||
2326 | 21 | |||
2327 | 22 | type Response struct { | ||
2328 | 23 | Status int | ||
2329 | 24 | Headers map[string]string | ||
2330 | 25 | Body string | ||
2331 | 26 | } | ||
2332 | 27 | |||
2333 | 28 | func NewHTTPServer() *HTTPServer { | ||
2334 | 29 | return &HTTPServer{URL: "http://localhost:4444", Timeout: 5 * time.Second} | ||
2335 | 30 | } | ||
2336 | 31 | |||
2337 | 32 | type ResponseFunc func(path string) Response | ||
2338 | 33 | |||
2339 | 34 | func (s *HTTPServer) Start() { | ||
2340 | 35 | if s.started { | ||
2341 | 36 | return | ||
2342 | 37 | } | ||
2343 | 38 | s.started = true | ||
2344 | 39 | s.request = make(chan *http.Request, 64) | ||
2345 | 40 | s.response = make(chan ResponseFunc, 64) | ||
2346 | 41 | u, err := url.Parse(s.URL) | ||
2347 | 42 | if err != nil { | ||
2348 | 43 | panic(err) | ||
2349 | 44 | } | ||
2350 | 45 | l, err := net.Listen("tcp", u.Host) | ||
2351 | 46 | if err != nil { | ||
2352 | 47 | panic(err) | ||
2353 | 48 | } | ||
2354 | 49 | go http.Serve(l, s) | ||
2355 | 50 | |||
2356 | 51 | s.Response(203, nil, "") | ||
2357 | 52 | for { | ||
2358 | 53 | // Wait for it to be up. | ||
2359 | 54 | resp, err := http.Get(s.URL) | ||
2360 | 55 | if err == nil && resp.StatusCode == 203 { | ||
2361 | 56 | break | ||
2362 | 57 | } | ||
2363 | 58 | time.Sleep(1e8) | ||
2364 | 59 | } | ||
2365 | 60 | s.WaitRequest() // Consume dummy request. | ||
2366 | 61 | } | ||
2367 | 62 | |||
2368 | 63 | // Flush discards all pending requests and responses. | ||
2369 | 64 | func (s *HTTPServer) Flush() { | ||
2370 | 65 | for { | ||
2371 | 66 | select { | ||
2372 | 67 | case <-s.request: | ||
2373 | 68 | case <-s.response: | ||
2374 | 69 | default: | ||
2375 | 70 | return | ||
2376 | 71 | } | ||
2377 | 72 | } | ||
2378 | 73 | } | ||
2379 | 74 | |||
2380 | 75 | func body(req *http.Request) string { | ||
2381 | 76 | data, err := ioutil.ReadAll(req.Body) | ||
2382 | 77 | if err != nil { | ||
2383 | 78 | panic(err) | ||
2384 | 79 | } | ||
2385 | 80 | return string(data) | ||
2386 | 81 | } | ||
2387 | 82 | |||
2388 | 83 | func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { | ||
2389 | 84 | req.ParseMultipartForm(1e6) | ||
2390 | 85 | data, err := ioutil.ReadAll(req.Body) | ||
2391 | 86 | if err != nil { | ||
2392 | 87 | panic(err) | ||
2393 | 88 | } | ||
2394 | 89 | req.Body = ioutil.NopCloser(bytes.NewBuffer(data)) | ||
2395 | 90 | s.request <- req | ||
2396 | 91 | var resp Response | ||
2397 | 92 | select { | ||
2398 | 93 | case respFunc := <-s.response: | ||
2399 | 94 | resp = respFunc(req.URL.Path) | ||
2400 | 95 | case <-time.After(s.Timeout): | ||
2401 | 96 | const msg = "ERROR: Timeout waiting for test to prepare a response\n" | ||
2402 | 97 | fmt.Fprintf(os.Stderr, msg) | ||
2403 | 98 | resp = Response{500, nil, msg} | ||
2404 | 99 | } | ||
2405 | 100 | if resp.Headers != nil { | ||
2406 | 101 | h := w.Header() | ||
2407 | 102 | for k, v := range resp.Headers { | ||
2408 | 103 | h.Set(k, v) | ||
2409 | 104 | } | ||
2410 | 105 | } | ||
2411 | 106 | if resp.Status != 0 { | ||
2412 | 107 | w.WriteHeader(resp.Status) | ||
2413 | 108 | } | ||
2414 | 109 | w.Write([]byte(resp.Body)) | ||
2415 | 110 | } | ||
2416 | 111 | |||
2417 | 112 | // WaitRequests returns the next n requests made to the http server from | ||
2418 | 113 | // the queue. If not enough requests were previously made, it waits until | ||
2419 | 114 | // the timeout value for them to be made. | ||
2420 | 115 | func (s *HTTPServer) WaitRequests(n int) []*http.Request { | ||
2421 | 116 | reqs := make([]*http.Request, 0, n) | ||
2422 | 117 | for i := 0; i < n; i++ { | ||
2423 | 118 | select { | ||
2424 | 119 | case req := <-s.request: | ||
2425 | 120 | reqs = append(reqs, req) | ||
2426 | 121 | case <-time.After(s.Timeout): | ||
2427 | 122 | panic("Timeout waiting for request") | ||
2428 | 123 | } | ||
2429 | 124 | } | ||
2430 | 125 | return reqs | ||
2431 | 126 | } | ||
2432 | 127 | |||
2433 | 128 | // WaitRequest returns the next request made to the http server from | ||
2434 | 129 | // the queue. If no requests were previously made, it waits until the | ||
2435 | 130 | // timeout value for one to be made. | ||
2436 | 131 | func (s *HTTPServer) WaitRequest() *http.Request { | ||
2437 | 132 | return s.WaitRequests(1)[0] | ||
2438 | 133 | } | ||
2439 | 134 | |||
2440 | 135 | // ResponseFunc prepares the test server to respond the following n | ||
2441 | 136 | // requests using f to build each response. | ||
2442 | 137 | func (s *HTTPServer) ResponseFunc(n int, f ResponseFunc) { | ||
2443 | 138 | for i := 0; i < n; i++ { | ||
2444 | 139 | s.response <- f | ||
2445 | 140 | } | ||
2446 | 141 | } | ||
2447 | 142 | |||
2448 | 143 | // ResponseMap maps request paths to responses. | ||
2449 | 144 | type ResponseMap map[string]Response | ||
2450 | 145 | |||
2451 | 146 | // ResponseMap prepares the test server to respond the following n | ||
2452 | 147 | // requests using the m to obtain the responses. | ||
2453 | 148 | func (s *HTTPServer) ResponseMap(n int, m ResponseMap) { | ||
2454 | 149 | f := func(path string) Response { | ||
2455 | 150 | for rpath, resp := range m { | ||
2456 | 151 | if rpath == path { | ||
2457 | 152 | return resp | ||
2458 | 153 | } | ||
2459 | 154 | } | ||
2460 | 155 | body := "Path not found in response map: " + path | ||
2461 | 156 | return Response{Status: 500, Body: body} | ||
2462 | 157 | } | ||
2463 | 158 | s.ResponseFunc(n, f) | ||
2464 | 159 | } | ||
2465 | 160 | |||
2466 | 161 | // Responses prepares the test server to respond the following n requests | ||
2467 | 162 | // using the provided response parameters. | ||
2468 | 163 | func (s *HTTPServer) Responses(n int, status int, headers map[string]string, body string) { | ||
2469 | 164 | f := func(path string) Response { | ||
2470 | 165 | return Response{status, headers, body} | ||
2471 | 166 | } | ||
2472 | 167 | s.ResponseFunc(n, f) | ||
2473 | 168 | } | ||
2474 | 169 | |||
2475 | 170 | // Response prepares the test server to respond the following request | ||
2476 | 171 | // using the provided response parameters. | ||
2477 | 172 | func (s *HTTPServer) Response(status int, headers map[string]string, body string) { | ||
2478 | 173 | s.Responses(1, status, headers, body) | ||
2479 | 174 | } | ||
2480 | 0 | 175 | ||
2481 | === added file 'testutil/suite.go' | |||
2482 | --- testutil/suite.go 1970-01-01 00:00:00 +0000 | |||
2483 | +++ testutil/suite.go 2013-01-31 17:09:20 +0000 | |||
2484 | @@ -0,0 +1,30 @@ | |||
2485 | 1 | package testutil | ||
2486 | 2 | |||
2487 | 3 | import ( | ||
2488 | 4 | "flag" | ||
2489 | 5 | "launchpad.net/goamz/aws" | ||
2490 | 6 | . "launchpad.net/gocheck" | ||
2491 | 7 | ) | ||
2492 | 8 | |||
2493 | 9 | // Amazon must be used by all tested packages to determine whether to | ||
2494 | 10 | // run functional tests against the real AWS servers. | ||
2495 | 11 | var Amazon bool | ||
2496 | 12 | |||
2497 | 13 | func init() { | ||
2498 | 14 | flag.BoolVar(&Amazon, "amazon", false, "Enable tests against amazon server") | ||
2499 | 15 | } | ||
2500 | 16 | |||
2501 | 17 | type LiveSuite struct { | ||
2502 | 18 | auth aws.Auth | ||
2503 | 19 | } | ||
2504 | 20 | |||
2505 | 21 | func (s *LiveSuite) SetUpSuite(c *C) { | ||
2506 | 22 | if !Amazon { | ||
2507 | 23 | c.Skip("amazon tests not enabled (-amazon flag)") | ||
2508 | 24 | } | ||
2509 | 25 | auth, err := aws.EnvAuth() | ||
2510 | 26 | if err != nil { | ||
2511 | 27 | c.Fatal(err.Error()) | ||
2512 | 28 | } | ||
2513 | 29 | s.auth = auth | ||
2514 | 30 | } |
Reviewers: mp+145878_ code.launchpad. net,
Message:
Please take a look.
Description:
testutil: new package for test clean up
Killed all the repetition in suite_test files, and improved the
implementation of the test HTTP server.
A few test bugs were also fixed on the way.
https:/ /code.launchpad .net/~niemeyer/ goamz/testing- cleanup/ +merge/ 145878
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/7232065/
Affected files: filter. go server. go mturk_test. go suite_test. go suite_test. go suite_test. go
A [revision details]
M aws/aws_test.go
D aws/suite_test.go
M ec2/ec2.go
M ec2/ec2_test.go
M ec2/ec2i_test.go
M ec2/ec2t_test.go
M ec2/ec2test/
M ec2/ec2test/
M ec2/sign.go
D ec2/suite_test.go
M exp/mturk/mturk.go
M exp/mturk/
D exp/mturk/
M exp/sdb/sdb.go
M exp/sdb/sdb_test.go
D exp/sdb/
M exp/sns/sns_test.go
D exp/sns/
M iam/iam_test.go
M iam/iami_test.go
D iam/suite_test.go
M s3/s3.go
M s3/s3_test.go
M s3/s3i_test.go
D s3/suite_test.go
A testutil/http.go
A testutil/suite.go