Merge lp:~jtv/gwacl/require-storage-location into lp:gwacl
- require-storage-location
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Jeroen T. Vermeulen |
Approved revision: | 218 |
Merged at revision: | 215 |
Proposed branch: | lp:~jtv/gwacl/require-storage-location |
Merge into: | lp:gwacl |
Diff against target: |
334 lines (+73/-48) 5 files modified
helpers_http_test.go (+3/-2) storage_base.go (+5/-14) storage_base_test.go (+44/-16) storage_test.go (+20/-16) testing_test.go (+1/-0) |
To merge this branch: | bzr merge lp:~jtv/gwacl/require-storage-location |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Julian Edwards (community) | Approve | ||
Review via email: mp+178721@code.launchpad.net |
Commit message
Make StorageContext.
Description of the change
Unfortunately, making this required is a runtime-
There was a lot of collateral damage, as expected. In particular, two storage tests relied on some arbitrary hard-coded names (not even mentioned in the tests themselves!) being identical between various helper functions. Luckily it wasn't hard to clean this up a bit. The tests themselves are now the only source of those arbitrary strings.
The test-helper factory for storage contexts sets an "unguessable" AzureEndpoint by default, so that we don't accidentally rely on such implicit connections here. Tests that need a known string, have to set one. As per the normal policy I used example.com, except of course in the tests for the functions that actually generate those strings. Those are already acceptance-tested against the real-world URLs, although it probably won't show up in the diff here.
Jeroen
- 218. By Jeroen T. Vermeulen
-
Name AzureEndpoint in panic text.
Jeroen T. Vermeulen (jtv) wrote : | # |
Collateral damage is a recurring problem in Go.
Preview Diff
1 | === modified file 'helpers_http_test.go' | |||
2 | --- helpers_http_test.go 2013-07-08 10:03:48 +0000 | |||
3 | +++ helpers_http_test.go 2013-08-07 02:15:36 +0000 | |||
4 | @@ -50,8 +50,9 @@ | |||
5 | 50 | // random base64-encoded key. | 50 | // random base64-encoded key. |
6 | 51 | func makeStorageContext(transport http.RoundTripper) *StorageContext { | 51 | func makeStorageContext(transport http.RoundTripper) *StorageContext { |
7 | 52 | context := &StorageContext{ | 52 | context := &StorageContext{ |
10 | 53 | Account: MakeRandomString(10), | 53 | Account: MakeRandomString(10), |
11 | 54 | Key: base64.StdEncoding.EncodeToString(MakeRandomByteSlice(10)), | 54 | Key: base64.StdEncoding.EncodeToString(MakeRandomByteSlice(10)), |
12 | 55 | AzureEndpoint: APIEndpoint("http://" + MakeRandomString(5) + ".example.com/"), | ||
13 | 55 | } | 56 | } |
14 | 56 | context.client = &http.Client{Transport: transport} | 57 | context.client = &http.Client{Transport: transport} |
15 | 57 | return context | 58 | return context |
16 | 58 | 59 | ||
17 | === modified file 'storage_base.go' | |||
18 | --- storage_base.go 2013-08-06 10:15:28 +0000 | |||
19 | +++ storage_base.go 2013-08-07 02:15:36 +0000 | |||
20 | @@ -210,12 +210,7 @@ | |||
21 | 210 | Key string | 210 | Key string |
22 | 211 | 211 | ||
23 | 212 | // AzureEndpoint specifies a base service endpoint URL for the Azure APIs. | 212 | // AzureEndpoint specifies a base service endpoint URL for the Azure APIs. |
30 | 213 | // If this is not set, it will default to the international endpoint which | 213 | // This field is required. |
25 | 214 | // will not work in mainland China. | ||
26 | 215 | // | ||
27 | 216 | // Try to set this if at all possible. Use GetEndpoint() to obtain the | ||
28 | 217 | // endpoint associated with a given service location, e.g. "West US" or | ||
29 | 218 | // "North Europe" or "East China". | ||
31 | 219 | AzureEndpoint APIEndpoint | 214 | AzureEndpoint APIEndpoint |
32 | 220 | 215 | ||
33 | 221 | client *http.Client | 216 | client *http.Client |
34 | @@ -334,20 +329,16 @@ | |||
35 | 334 | // getAccountURL returns the base URL for the context's storage account. | 329 | // getAccountURL returns the base URL for the context's storage account. |
36 | 335 | // (The result ends in a slash.) | 330 | // (The result ends in a slash.) |
37 | 336 | func (context *StorageContext) getAccountURL() string { | 331 | func (context *StorageContext) getAccountURL() string { |
44 | 337 | endpoint := context.AzureEndpoint | 332 | if context.AzureEndpoint == APIEndpoint("") { |
45 | 338 | if endpoint == "" { | 333 | panic(errors.New("no AzureEndpoint specified in gwacl.StorageContext")) |
40 | 339 | // No API endpoint specified. Default to the international one. | ||
41 | 340 | // This will not work for mainland China. | ||
42 | 341 | // TODO: Make this required, and panic() instead. | ||
43 | 342 | endpoint = GetEndpoint("West US") | ||
46 | 343 | } | 334 | } |
48 | 344 | return endpoint.BlobStorageAPI(context.Account) | 335 | return context.AzureEndpoint.BlobStorageAPI(context.Account) |
49 | 345 | } | 336 | } |
50 | 346 | 337 | ||
51 | 347 | // getContainerURL returns the URL for a given storage container. | 338 | // getContainerURL returns the URL for a given storage container. |
52 | 348 | // (The result does not end in a slash.) | 339 | // (The result does not end in a slash.) |
53 | 349 | func (context *StorageContext) getContainerURL(container string) string { | 340 | func (context *StorageContext) getContainerURL(container string) string { |
55 | 350 | return context.getAccountURL() + url.QueryEscape(container) | 341 | return strings.TrimRight(context.getAccountURL(), "/") + "/" + url.QueryEscape(container) |
56 | 351 | } | 342 | } |
57 | 352 | 343 | ||
58 | 353 | // GetFileURL returns the URL for a given file in the given container. | 344 | // GetFileURL returns the URL for a given file in the given container. |
59 | 354 | 345 | ||
60 | === modified file 'storage_base_test.go' | |||
61 | --- storage_base_test.go 2013-08-06 04:53:38 +0000 | |||
62 | +++ storage_base_test.go 2013-08-07 02:15:36 +0000 | |||
63 | @@ -6,6 +6,7 @@ | |||
64 | 6 | import ( | 6 | import ( |
65 | 7 | "bytes" | 7 | "bytes" |
66 | 8 | "encoding/base64" | 8 | "encoding/base64" |
67 | 9 | "errors" | ||
68 | 9 | "fmt" | 10 | "fmt" |
69 | 10 | "io/ioutil" | 11 | "io/ioutil" |
70 | 11 | . "launchpad.net/gocheck" | 12 | . "launchpad.net/gocheck" |
71 | @@ -309,33 +310,50 @@ | |||
72 | 309 | "http://"+url.QueryEscape(account)+".blob.example.com") | 310 | "http://"+url.QueryEscape(account)+".blob.example.com") |
73 | 310 | } | 311 | } |
74 | 311 | 312 | ||
76 | 312 | func (*TestStorageContext) TestGetAccountURLDefaultsToInternationalEndpoint(c *C) { | 313 | func (*TestStorageContext) TestGetAccountURLRequiresEndpoint(c *C) { |
77 | 313 | context := StorageContext{Account: "myaccount"} | 314 | context := StorageContext{Account: "myaccount"} |
78 | 314 | c.Check( | 315 | c.Check( |
82 | 315 | context.getAccountURL(), | 316 | context.getAccountURL, |
83 | 316 | Equals, | 317 | Panics, |
84 | 317 | "https://myaccount.blob.core.windows.net/") | 318 | errors.New("no AzureEndpoint specified in gwacl.StorageContext")) |
85 | 318 | } | 319 | } |
86 | 319 | 320 | ||
88 | 320 | func (suite *TestStorageContext) TestGetContainerURL(c *C) { | 321 | func (suite *TestStorageContext) TestGetContainerURLAddsContainer(c *C) { |
89 | 321 | account := makeNastyURLUnfriendlyString() | 322 | account := makeNastyURLUnfriendlyString() |
90 | 322 | container := makeNastyURLUnfriendlyString() | 323 | container := makeNastyURLUnfriendlyString() |
92 | 323 | context := StorageContext{Account: account} | 324 | context := StorageContext{ |
93 | 325 | Account: account, | ||
94 | 326 | AzureEndpoint: "http://example.com/", | ||
95 | 327 | } | ||
96 | 324 | c.Check( | 328 | c.Check( |
97 | 325 | context.getContainerURL(container), | 329 | context.getContainerURL(container), |
98 | 326 | Equals, | 330 | Equals, |
100 | 327 | "https://"+url.QueryEscape(account)+".blob.core.windows.net/"+url.QueryEscape(container)) | 331 | "http://"+url.QueryEscape(account)+".blob.example.com/"+url.QueryEscape(container)) |
101 | 332 | } | ||
102 | 333 | |||
103 | 334 | func (suite *TestStorageContext) TestGetContainerURLAddsSlashIfNeeded(c *C) { | ||
104 | 335 | context := StorageContext{ | ||
105 | 336 | Account: "account", | ||
106 | 337 | AzureEndpoint: "http://example.com", | ||
107 | 338 | } | ||
108 | 339 | c.Check( | ||
109 | 340 | context.getContainerURL("container"), | ||
110 | 341 | Equals, | ||
111 | 342 | "http://account.blob.example.com/container") | ||
112 | 328 | } | 343 | } |
113 | 329 | 344 | ||
114 | 330 | func (suite *TestStorageContext) TestGetFileURL(c *C) { | 345 | func (suite *TestStorageContext) TestGetFileURL(c *C) { |
115 | 331 | account := makeNastyURLUnfriendlyString() | 346 | account := makeNastyURLUnfriendlyString() |
116 | 332 | container := makeNastyURLUnfriendlyString() | 347 | container := makeNastyURLUnfriendlyString() |
117 | 333 | file := makeNastyURLUnfriendlyString() | 348 | file := makeNastyURLUnfriendlyString() |
119 | 334 | context := StorageContext{Account: account} | 349 | context := StorageContext{ |
120 | 350 | Account: account, | ||
121 | 351 | AzureEndpoint: "http://example.com/", | ||
122 | 352 | } | ||
123 | 335 | c.Check( | 353 | c.Check( |
124 | 336 | context.GetFileURL(container, file), | 354 | context.GetFileURL(container, file), |
125 | 337 | Equals, | 355 | Equals, |
127 | 338 | "https://"+url.QueryEscape(account)+".blob.core.windows.net/"+url.QueryEscape(container)+"/"+url.QueryEscape(file)) | 356 | "http://"+url.QueryEscape(account)+".blob.example.com/"+url.QueryEscape(container)+"/"+url.QueryEscape(file)) |
128 | 339 | } | 357 | } |
129 | 340 | 358 | ||
130 | 341 | func (suite *TestStorageContext) TestGetSignedFileURL(c *C) { | 359 | func (suite *TestStorageContext) TestGetSignedFileURL(c *C) { |
131 | @@ -343,7 +361,11 @@ | |||
132 | 343 | container := "container" | 361 | container := "container" |
133 | 344 | file := "/a/file" | 362 | file := "/a/file" |
134 | 345 | key := base64.StdEncoding.EncodeToString([]byte("dummykey")) | 363 | key := base64.StdEncoding.EncodeToString([]byte("dummykey")) |
136 | 346 | context := StorageContext{Account: account, Key: key} | 364 | context := StorageContext{ |
137 | 365 | Account: account, | ||
138 | 366 | Key: key, | ||
139 | 367 | AzureEndpoint: "http://example.com/", | ||
140 | 368 | } | ||
141 | 347 | expires := time.Now() | 369 | expires := time.Now() |
142 | 348 | 370 | ||
143 | 349 | signedURL := context.GetAnonymousFileURL(container, file, expires) | 371 | signedURL := context.GetAnonymousFileURL(container, file, expires) |
144 | @@ -408,11 +430,12 @@ | |||
145 | 408 | response := makeHttpResponse(http.StatusOK, responseBody) | 430 | response := makeHttpResponse(http.StatusOK, responseBody) |
146 | 409 | transport := &TestTransport{Response: response} | 431 | transport := &TestTransport{Response: response} |
147 | 410 | context := makeStorageContext(transport) | 432 | context := makeStorageContext(transport) |
148 | 433 | context.AzureEndpoint = "http://example.com/" | ||
149 | 411 | request := &ListContainersRequest{Marker: ""} | 434 | request := &ListContainersRequest{Marker: ""} |
150 | 412 | results, err := context.ListContainers(request) | 435 | results, err := context.ListContainers(request) |
151 | 413 | c.Assert(err, IsNil) | 436 | c.Assert(err, IsNil) |
152 | 414 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( | 437 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( |
154 | 415 | "https://%s.blob.core.windows.net/?comp=list", context.Account)) | 438 | "http://%s.blob.example.com/?comp=list", context.Account)) |
155 | 416 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") | 439 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") |
156 | 417 | c.Assert(results, NotNil) | 440 | c.Assert(results, NotNil) |
157 | 418 | c.Assert(results.Containers[0].Name, Equals, "name-value") | 441 | c.Assert(results.Containers[0].Name, Equals, "name-value") |
158 | @@ -666,11 +689,12 @@ | |||
159 | 666 | response := makeHttpResponse(http.StatusCreated, "") | 689 | response := makeHttpResponse(http.StatusCreated, "") |
160 | 667 | transport := &TestTransport{Response: response} | 690 | transport := &TestTransport{Response: response} |
161 | 668 | context := makeStorageContext(transport) | 691 | context := makeStorageContext(transport) |
162 | 692 | context.AzureEndpoint = "http://example.com/" | ||
163 | 669 | containerName := MakeRandomString(10) | 693 | containerName := MakeRandomString(10) |
164 | 670 | err := context.CreateContainer(containerName) | 694 | err := context.CreateContainer(containerName) |
165 | 671 | c.Assert(err, IsNil) | 695 | c.Assert(err, IsNil) |
166 | 672 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( | 696 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( |
168 | 673 | "https://%s.blob.core.windows.net/%s?restype=container", | 697 | "http://%s.blob.example.com/%s?restype=container", |
169 | 674 | context.Account, containerName)) | 698 | context.Account, containerName)) |
170 | 675 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") | 699 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") |
171 | 676 | } | 700 | } |
172 | @@ -720,11 +744,12 @@ | |||
173 | 720 | response := makeHttpResponse(http.StatusAccepted, "") | 744 | response := makeHttpResponse(http.StatusAccepted, "") |
174 | 721 | transport := &TestTransport{Response: response} | 745 | transport := &TestTransport{Response: response} |
175 | 722 | context := makeStorageContext(transport) | 746 | context := makeStorageContext(transport) |
176 | 747 | context.AzureEndpoint = "http://example.com/" | ||
177 | 723 | containerName := MakeRandomString(10) | 748 | containerName := MakeRandomString(10) |
178 | 724 | err := context.DeleteContainer(containerName) | 749 | err := context.DeleteContainer(containerName) |
179 | 725 | c.Assert(err, IsNil) | 750 | c.Assert(err, IsNil) |
180 | 726 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( | 751 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( |
182 | 727 | "https://%s.blob.core.windows.net/%s?restype=container", | 752 | "http://%s.blob.example.com/%s?restype=container", |
183 | 728 | context.Account, containerName)) | 753 | context.Account, containerName)) |
184 | 729 | c.Check(transport.Request.Method, Equals, "DELETE") | 754 | c.Check(transport.Request.Method, Equals, "DELETE") |
185 | 730 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") | 755 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") |
186 | @@ -786,11 +811,12 @@ | |||
187 | 786 | 811 | ||
188 | 787 | transport := &TestTransport{Response: response} | 812 | transport := &TestTransport{Response: response} |
189 | 788 | context := makeStorageContext(transport) | 813 | context := makeStorageContext(transport) |
190 | 814 | context.AzureEndpoint = "http://example.com/" | ||
191 | 789 | containerName := MakeRandomString(10) | 815 | containerName := MakeRandomString(10) |
192 | 790 | props, err := context.GetContainerProperties(containerName) | 816 | props, err := context.GetContainerProperties(containerName) |
193 | 791 | c.Assert(err, IsNil) | 817 | c.Assert(err, IsNil) |
194 | 792 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( | 818 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( |
196 | 793 | "https://%s.blob.core.windows.net/%s?restype=container", | 819 | "http://%s.blob.example.com/%s?restype=container", |
197 | 794 | context.Account, containerName)) | 820 | context.Account, containerName)) |
198 | 795 | c.Check(transport.Request.Method, Equals, "GET") | 821 | c.Check(transport.Request.Method, Equals, "GET") |
199 | 796 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") | 822 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") |
200 | @@ -1099,6 +1125,7 @@ | |||
201 | 1099 | response := makeHttpResponse(http.StatusCreated, "") | 1125 | response := makeHttpResponse(http.StatusCreated, "") |
202 | 1100 | transport := &TestTransport{Response: response} | 1126 | transport := &TestTransport{Response: response} |
203 | 1101 | context := makeStorageContext(transport) | 1127 | context := makeStorageContext(transport) |
204 | 1128 | context.AzureEndpoint = "http://example.com/" | ||
205 | 1102 | blocklist := &BlockList{} | 1129 | blocklist := &BlockList{} |
206 | 1103 | blocklist.Add(BlockListLatest, "b1") | 1130 | blocklist.Add(BlockListLatest, "b1") |
207 | 1104 | blocklist.Add(BlockListLatest, "b2") | 1131 | blocklist.Add(BlockListLatest, "b2") |
208 | @@ -1107,7 +1134,7 @@ | |||
209 | 1107 | 1134 | ||
210 | 1108 | c.Check(transport.Request.Method, Equals, "PUT") | 1135 | c.Check(transport.Request.Method, Equals, "PUT") |
211 | 1109 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( | 1136 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( |
213 | 1110 | "https://%s.blob.core.windows.net/container/blobname?comp=blocklist", | 1137 | "http://%s.blob.example.com/container/blobname?comp=blocklist", |
214 | 1111 | context.Account)) | 1138 | context.Account)) |
215 | 1112 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") | 1139 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") |
216 | 1113 | 1140 | ||
217 | @@ -1340,6 +1367,7 @@ | |||
218 | 1340 | response := makeHttpResponse(http.StatusOK, "") | 1367 | response := makeHttpResponse(http.StatusOK, "") |
219 | 1341 | transport := &TestTransport{Response: response} | 1368 | transport := &TestTransport{Response: response} |
220 | 1342 | context := makeStorageContext(transport) | 1369 | context := makeStorageContext(transport) |
221 | 1370 | context.AzureEndpoint = "http://example.com/" | ||
222 | 1343 | err := context.SetContainerACL(&SetContainerACLRequest{ | 1371 | err := context.SetContainerACL(&SetContainerACLRequest{ |
223 | 1344 | Container: "mycontainer", Access: "container"}) | 1372 | Container: "mycontainer", Access: "container"}) |
224 | 1345 | 1373 | ||
225 | @@ -1347,7 +1375,7 @@ | |||
226 | 1347 | c.Check(transport.Request.Method, Equals, "PUT") | 1375 | c.Check(transport.Request.Method, Equals, "PUT") |
227 | 1348 | c.Check(transport.Request.URL.String(), Matches, | 1376 | c.Check(transport.Request.URL.String(), Matches, |
228 | 1349 | fmt.Sprintf( | 1377 | fmt.Sprintf( |
230 | 1350 | "https://%s.blob.core.windows.net/mycontainer?.*", context.Account)) | 1378 | "http://%s.blob.example.com/mycontainer?.*", context.Account)) |
231 | 1351 | c.Check(transport.Request.URL.Query(), DeepEquals, url.Values{ | 1379 | c.Check(transport.Request.URL.Query(), DeepEquals, url.Values{ |
232 | 1352 | "comp": {"acl"}, | 1380 | "comp": {"acl"}, |
233 | 1353 | "restype": {"container"}, | 1381 | "restype": {"container"}, |
234 | 1354 | 1382 | ||
235 | === modified file 'storage_test.go' | |||
236 | --- storage_test.go 2013-08-05 12:01:32 +0000 | |||
237 | +++ storage_test.go 2013-08-07 02:15:36 +0000 | |||
238 | @@ -26,13 +26,14 @@ | |||
239 | 26 | // UploadBlockBlob then sends the list of blocks with PutBlockList. | 26 | // UploadBlockBlob then sends the list of blocks with PutBlockList. |
240 | 27 | transport.AddExchange(makeFakeCreatedResponse(), nil) | 27 | transport.AddExchange(makeFakeCreatedResponse(), nil) |
241 | 28 | // Upload a random blob of data. | 28 | // Upload a random blob of data. |
243 | 29 | data := uploadRandomBlob(c, context, 10) | 29 | data := uploadRandomBlob(c, context, 10, "MyContainer", "MyFile") |
244 | 30 | // There were two exchanges. | 30 | // There were two exchanges. |
245 | 31 | c.Assert(transport.ExchangeCount, Equals, 2) | 31 | c.Assert(transport.ExchangeCount, Equals, 2) |
246 | 32 | // The first request is a Put Block with the block data. | 32 | // The first request is a Put Block with the block data. |
248 | 33 | assertBlockSent(c, context, data, b64("000000000000000000000000000000"), transport.Exchanges[0]) | 33 | fileURL := context.GetFileURL("MyContainer", "MyFile") |
249 | 34 | assertBlockSent(c, context, data, b64("000000000000000000000000000000"), transport.Exchanges[0], fileURL) | ||
250 | 34 | // The second request is Put Block List to commit the block above. | 35 | // The second request is Put Block List to commit the block above. |
252 | 35 | assertBlockListSent(c, context, []string{b64("000000000000000000000000000000")}, transport.Exchanges[1]) | 36 | assertBlockListSent(c, context, []string{b64("000000000000000000000000000000")}, transport.Exchanges[1], fileURL) |
253 | 36 | } | 37 | } |
254 | 37 | 38 | ||
255 | 38 | func (suite *testUploadBlockBlob) TestLargeFile(c *C) { | 39 | func (suite *testUploadBlockBlob) TestLargeFile(c *C) { |
256 | @@ -44,28 +45,29 @@ | |||
257 | 44 | // UploadBlockBlob then sends the list of blocks with PutBlockList. | 45 | // UploadBlockBlob then sends the list of blocks with PutBlockList. |
258 | 45 | transport.AddExchange(makeFakeCreatedResponse(), nil) | 46 | transport.AddExchange(makeFakeCreatedResponse(), nil) |
259 | 46 | // Upload a large random blob of data. | 47 | // Upload a large random blob of data. |
261 | 47 | data := uploadRandomBlob(c, context, 1348*1024) | 48 | data := uploadRandomBlob(c, context, 1348*1024, "MyContainer", "MyFile") |
262 | 48 | // There were three exchanges. | 49 | // There were three exchanges. |
263 | 49 | c.Assert(transport.ExchangeCount, Equals, 3) | 50 | c.Assert(transport.ExchangeCount, Equals, 3) |
264 | 50 | // The first two requests are Put Block with chunks of the block data. The | 51 | // The first two requests are Put Block with chunks of the block data. The |
265 | 51 | // weird looking block IDs are base64 encodings of the strings "0" and "1". | 52 | // weird looking block IDs are base64 encodings of the strings "0" and "1". |
268 | 52 | assertBlockSent(c, context, data[:1024*1024], b64("000000000000000000000000000000"), transport.Exchanges[0]) | 53 | fileURL := context.GetFileURL("MyContainer", "MyFile") |
269 | 53 | assertBlockSent(c, context, data[1024*1024:], b64("000000000000000000000000000001"), transport.Exchanges[1]) | 54 | assertBlockSent(c, context, data[:1024*1024], b64("000000000000000000000000000000"), transport.Exchanges[0], fileURL) |
270 | 55 | assertBlockSent(c, context, data[1024*1024:], b64("000000000000000000000000000001"), transport.Exchanges[1], fileURL) | ||
271 | 54 | // The second request is Put Block List to commit the block above. | 56 | // The second request is Put Block List to commit the block above. |
273 | 55 | assertBlockListSent(c, context, []string{b64("000000000000000000000000000000"), b64("000000000000000000000000000001")}, transport.Exchanges[2]) | 57 | assertBlockListSent(c, context, []string{b64("000000000000000000000000000000"), b64("000000000000000000000000000001")}, transport.Exchanges[2], fileURL) |
274 | 56 | } | 58 | } |
275 | 57 | 59 | ||
277 | 58 | func uploadRandomBlob(c *C, context *StorageContext, size int) []byte { | 60 | func uploadRandomBlob(c *C, context *StorageContext, size int, container, filename string) []byte { |
278 | 59 | data := MakeRandomByteSlice(size) | 61 | data := MakeRandomByteSlice(size) |
279 | 60 | err := context.UploadBlockBlob( | 62 | err := context.UploadBlockBlob( |
281 | 61 | "MyContainer", "MyFile", bytes.NewReader(data)) | 63 | container, filename, bytes.NewReader(data)) |
282 | 62 | c.Assert(err, IsNil) | 64 | c.Assert(err, IsNil) |
283 | 63 | return data | 65 | return data |
284 | 64 | } | 66 | } |
285 | 65 | 67 | ||
286 | 66 | func assertBlockSent( | 68 | func assertBlockSent( |
289 | 67 | c *C, context *StorageContext, data []byte, blockID string, exchange *MockingTransportExchange) { | 69 | c *C, context *StorageContext, data []byte, blockID string, exchange *MockingTransportExchange, fileURL string) { |
290 | 68 | c.Check(exchange.Request.URL.String(), Matches, context.GetFileURL("MyContainer", "MyFile")+"?.*") | 70 | c.Check(exchange.Request.URL.String(), Matches, fileURL+"?.*") |
291 | 69 | c.Check(exchange.Request.URL.Query(), DeepEquals, url.Values{ | 71 | c.Check(exchange.Request.URL.Query(), DeepEquals, url.Values{ |
292 | 70 | "comp": {"block"}, | 72 | "comp": {"block"}, |
293 | 71 | "blockid": {blockID}, | 73 | "blockid": {blockID}, |
294 | @@ -85,10 +87,11 @@ | |||
295 | 85 | } | 87 | } |
296 | 86 | 88 | ||
297 | 87 | func assertBlockListSent( | 89 | func assertBlockListSent( |
302 | 88 | c *C, context *StorageContext, blockIDs []string, exchange *MockingTransportExchange) { | 90 | c *C, context *StorageContext, blockIDs []string, exchange *MockingTransportExchange, fileURL string) { |
303 | 89 | c.Check(exchange.Request.URL.String(), Equals, fmt.Sprintf( | 91 | c.Check(exchange.Request.URL.String(), Matches, fileURL+"?.*") |
304 | 90 | "https://%s.blob.core.windows.net/MyContainer/MyFile"+ | 92 | c.Check(exchange.Request.URL.Query(), DeepEquals, url.Values{ |
305 | 91 | "?comp=blocklist", context.Account)) | 93 | "comp": {"blocklist"}, |
306 | 94 | }) | ||
307 | 92 | body, err := ioutil.ReadAll(exchange.Request.Body) | 95 | body, err := ioutil.ReadAll(exchange.Request.Body) |
308 | 93 | c.Check(err, IsNil) | 96 | c.Check(err, IsNil) |
309 | 94 | expected := "<BlockList>\n" | 97 | expected := "<BlockList>\n" |
310 | @@ -272,10 +275,11 @@ | |||
311 | 272 | } | 275 | } |
312 | 273 | transport := &TestTransport{Response: response} | 276 | transport := &TestTransport{Response: response} |
313 | 274 | context := makeStorageContext(transport) | 277 | context := makeStorageContext(transport) |
314 | 278 | context.AzureEndpoint = "http://example.com/" | ||
315 | 275 | results, err := context.ListAllContainers() | 279 | results, err := context.ListAllContainers() |
316 | 276 | c.Assert(err, IsNil) | 280 | c.Assert(err, IsNil) |
317 | 277 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( | 281 | c.Check(transport.Request.URL.String(), Equals, fmt.Sprintf( |
319 | 278 | "https://%s.blob.core.windows.net/?comp=list", context.Account)) | 282 | "http://%s.blob.example.com/?comp=list", context.Account)) |
320 | 279 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") | 283 | c.Check(transport.Request.Header.Get("Authorization"), Not(Equals), "") |
321 | 280 | c.Assert(results, NotNil) | 284 | c.Assert(results, NotNil) |
322 | 281 | c.Assert(results.Containers[0].Name, Equals, "name-value") | 285 | c.Assert(results.Containers[0].Name, Equals, "name-value") |
323 | 282 | 286 | ||
324 | === modified file 'testing_test.go' | |||
325 | --- testing_test.go 2013-06-27 13:58:43 +0000 | |||
326 | +++ testing_test.go 2013-08-07 02:15:36 +0000 | |||
327 | @@ -19,6 +19,7 @@ | |||
328 | 19 | transport := &TestTransport{Error: error} | 19 | transport := &TestTransport{Error: error} |
329 | 20 | client := &http.Client{Transport: transport} | 20 | client := &http.Client{Transport: transport} |
330 | 21 | context := NewTestStorageContext(client) | 21 | context := NewTestStorageContext(client) |
331 | 22 | context.AzureEndpoint = "http://example.com/" | ||
332 | 22 | request := &ListContainersRequest{Marker: ""} | 23 | request := &ListContainersRequest{Marker: ""} |
333 | 23 | _, err := context.ListContainers(request) | 24 | _, err := context.ListContainers(request) |
334 | 24 | c.Check(err, ErrorMatches, ".*"+errorMessage+".*") | 25 | c.Check(err, ErrorMatches, ".*"+errorMessage+".*") |
Looks great! Good testing as always from you.
8 - Account: MakeRandomStrin g(10), StdEncoding. EncodeToString( MakeRandomByteS lice(10) ), g(10), StdEncoding. EncodeToString( MakeRandomByteS lice(10) ),
9 - Key: base64.
10 + Account: MakeRandomStrin
11 + Key: base64.
12 + AzureEndpoint: APIEndpoint("http://" + MakeRandomString(5) + ".example.com/"),
I'd like to just take a moment to bitch at gofmt for changing lines completely unrelated to the diff at hand. >:(
44 + if context. AzureEndpoint == APIEndpoint("") { New("no Azure blob storage endpoint specified"))
45 + panic(errors.
Can you mention the parameter by name please, it will save a confused developer from hunting down this line of source.