1package azblob_test
2
3import (
4	"crypto/md5"
5	"crypto/rand"
6	"fmt"
7	"io/ioutil"
8
9	"github.com/Azure/azure-storage-blob-go/azblob"
10
11	"bytes"
12
13	"errors"
14	"os"
15	"strings"
16	"time"
17
18	chk "gopkg.in/check.v1" // go get gopkg.in/check.v1
19)
20
21// Copied from policy_unique_request_id.go
22type uuid [16]byte
23
24// The UUID reserved variants.
25const (
26	reservedNCS       byte = 0x80
27	reservedRFC4122   byte = 0x40
28	reservedMicrosoft byte = 0x20
29	reservedFuture    byte = 0x00
30)
31
32func newUUID() (u uuid) {
33	u = uuid{}
34	// Set all bits to randomly (or pseudo-randomly) chosen values.
35	rand.Read(u[:])
36	u[8] = (u[8] | reservedRFC4122) & 0x7F // u.setVariant(ReservedRFC4122)
37
38	var version byte = 4
39	u[6] = (u[6] & 0xF) | (version << 4) // u.setVersion(4)
40	return
41}
42
43func (u uuid) String() string {
44	return fmt.Sprintf("%x-%x-%x-%x-%x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:])
45}
46
47func (s *aztestsSuite) TestCreateBlobURL(c *chk.C) {
48	bsu := getBSU()
49	containerURL, containerName := getContainerURL(c, bsu)
50	testURL, testName := getBlockBlobURL(c, containerURL)
51
52	parts := azblob.NewBlobURLParts(testURL.URL())
53	c.Assert(parts.BlobName, chk.Equals, testName)
54	c.Assert(parts.ContainerName, chk.Equals, containerName)
55
56	correctURL := "https://" + os.Getenv("ACCOUNT_NAME") + ".blob.core.windows.net/" + containerName + "/" + testName
57	temp := testURL.URL()
58	c.Assert(temp.String(), chk.Equals, correctURL)
59}
60
61func (s *aztestsSuite) TestCreateBlobURLWithSnapshotAndSAS(c *chk.C) {
62	bsu := getBSU()
63	containerURL, containerName := getContainerURL(c, bsu)
64	blobURL, blobName := getBlockBlobURL(c, containerURL)
65
66	currentTime := time.Now().UTC()
67	credential, err := getGenericCredential("")
68	if err != nil {
69		c.Fatal("Invalid credential")
70	}
71	sasQueryParams, err := azblob.AccountSASSignatureValues{
72		Protocol:      azblob.SASProtocolHTTPS,
73		ExpiryTime:    currentTime.Add(48 * time.Hour),
74		Permissions:   azblob.AccountSASPermissions{Read: true, List: true}.String(),
75		Services:      azblob.AccountSASServices{Blob: true}.String(),
76		ResourceTypes: azblob.AccountSASResourceTypes{Container: true, Object: true}.String(),
77	}.NewSASQueryParameters(credential)
78	if err != nil {
79		c.Fatal(err)
80	}
81
82	parts := azblob.NewBlobURLParts(blobURL.URL())
83	parts.SAS = sasQueryParams
84	parts.Snapshot = currentTime.Format(azblob.SnapshotTimeFormat)
85	testURL := parts.URL()
86
87	// The snapshot format string is taken from the snapshotTimeFormat value in parsing_urls.go. The field is not public, so
88	// it is copied here
89	correctURL := "https://" + os.Getenv("ACCOUNT_NAME") + ".blob.core.windows.net/" + containerName + "/" + blobName +
90		"?" + "snapshot=" + currentTime.Format("2006-01-02T15:04:05.0000000Z07:00") + "&" + sasQueryParams.Encode()
91	c.Assert(testURL.String(), chk.Equals, correctURL)
92}
93
94func (s *aztestsSuite) TestBlobWithNewPipeline(c *chk.C) {
95	bsu := getBSU()
96	containerURL, _ := getContainerURL(c, bsu)
97	blobURL := containerURL.NewBlockBlobURL(blobPrefix)
98
99	newBlobURL := blobURL.WithPipeline(testPipeline{})
100	_, err := newBlobURL.GetBlockList(ctx, azblob.BlockListAll, azblob.LeaseAccessConditions{})
101	c.Assert(err, chk.NotNil)
102	c.Assert(err.Error(), chk.Equals, testPipelineMessage)
103}
104
105func waitForCopy(c *chk.C, copyBlobURL azblob.BlockBlobURL, blobCopyResponse *azblob.BlobStartCopyFromURLResponse) {
106	status := blobCopyResponse.CopyStatus()
107	// Wait for the copy to finish. If the copy takes longer than a minute, we will fail
108	start := time.Now()
109	for status != azblob.CopyStatusSuccess {
110		props, _ := copyBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
111		status = props.CopyStatus()
112		currentTime := time.Now()
113		if currentTime.Sub(start) >= time.Minute {
114			c.Fail()
115		}
116	}
117}
118
119func (s *aztestsSuite) TestBlobStartCopyDestEmpty(c *chk.C) {
120	bsu := getBSU()
121	containerURL, _ := createNewContainer(c, bsu)
122	defer deleteContainer(c, containerURL)
123	blobURL, _ := createNewBlockBlob(c, containerURL)
124	copyBlobURL, _ := getBlockBlobURL(c, containerURL)
125
126	blobCopyResponse, err := copyBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
127	c.Assert(err, chk.IsNil)
128	waitForCopy(c, copyBlobURL, blobCopyResponse)
129
130	resp, err := copyBlobURL.Download(ctx, 0, 20, azblob.BlobAccessConditions{}, false)
131	c.Assert(err, chk.IsNil)
132
133	// Read the blob data to verify the copy
134	data, err := ioutil.ReadAll(resp.Response().Body)
135	c.Assert(resp.ContentLength(), chk.Equals, int64(len(blockBlobDefaultData)))
136	c.Assert(string(data), chk.Equals, blockBlobDefaultData)
137	resp.Body(azblob.RetryReaderOptions{}).Close()
138}
139
140func (s *aztestsSuite) TestBlobStartCopyMetadata(c *chk.C) {
141	bsu := getBSU()
142	containerURL, _ := createNewContainer(c, bsu)
143	defer deleteContainer(c, containerURL)
144	blobURL, _ := createNewBlockBlob(c, containerURL)
145	copyBlobURL, _ := getBlockBlobURL(c, containerURL)
146
147	resp, err := copyBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
148	c.Assert(err, chk.IsNil)
149	waitForCopy(c, copyBlobURL, resp)
150
151	resp2, err := copyBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
152	c.Assert(err, chk.IsNil)
153	c.Assert(resp2.NewMetadata(), chk.DeepEquals, basicMetadata)
154}
155
156func (s *aztestsSuite) TestBlobStartCopyMetadataNil(c *chk.C) {
157	bsu := getBSU()
158	containerURL, _ := createNewContainer(c, bsu)
159	defer deleteContainer(c, containerURL)
160	blobURL, _ := createNewBlockBlob(c, containerURL)
161	copyBlobURL, _ := getBlockBlobURL(c, containerURL)
162
163	// Have the destination start with metadata so we ensure the nil metadata passed later takes effect
164	_, err := copyBlobURL.Upload(ctx, bytes.NewReader([]byte("data")), azblob.BlobHTTPHeaders{},
165		basicMetadata, azblob.BlobAccessConditions{})
166	c.Assert(err, chk.IsNil)
167
168	resp, err := copyBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
169	c.Assert(err, chk.IsNil)
170
171	waitForCopy(c, copyBlobURL, resp)
172
173	resp2, err := copyBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
174	c.Assert(err, chk.IsNil)
175	c.Assert(resp2.NewMetadata(), chk.HasLen, 0)
176}
177
178func (s *aztestsSuite) TestBlobStartCopyMetadataEmpty(c *chk.C) {
179	bsu := getBSU()
180	containerURL, _ := createNewContainer(c, bsu)
181	defer deleteContainer(c, containerURL)
182	blobURL, _ := createNewBlockBlob(c, containerURL)
183	copyBlobURL, _ := getBlockBlobURL(c, containerURL)
184
185	// Have the destination start with metadata so we ensure the empty metadata passed later takes effect
186	_, err := copyBlobURL.Upload(ctx, bytes.NewReader([]byte("data")), azblob.BlobHTTPHeaders{},
187		basicMetadata, azblob.BlobAccessConditions{})
188	c.Assert(err, chk.IsNil)
189
190	resp, err := copyBlobURL.StartCopyFromURL(ctx, blobURL.URL(), azblob.Metadata{}, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
191	c.Assert(err, chk.IsNil)
192
193	waitForCopy(c, copyBlobURL, resp)
194
195	resp2, err := copyBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
196	c.Assert(err, chk.IsNil)
197	c.Assert(resp2.NewMetadata(), chk.HasLen, 0)
198}
199
200func (s *aztestsSuite) TestBlobStartCopyMetadataInvalidField(c *chk.C) {
201	bsu := getBSU()
202	containerURL, _ := createNewContainer(c, bsu)
203	defer deleteContainer(c, containerURL)
204	blobURL, _ := createNewBlockBlob(c, containerURL)
205	copyBlobURL, _ := getBlockBlobURL(c, containerURL)
206
207	_, err := copyBlobURL.StartCopyFromURL(ctx, blobURL.URL(), azblob.Metadata{"I nvalid.": "bar"}, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
208	c.Assert(err, chk.NotNil)
209	c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true)
210}
211
212func (s *aztestsSuite) TestBlobStartCopySourceNonExistant(c *chk.C) {
213	bsu := getBSU()
214	containerURL, _ := createNewContainer(c, bsu)
215	defer deleteContainer(c, containerURL)
216	blobURL, _ := getBlockBlobURL(c, containerURL)
217	copyBlobURL, _ := getBlockBlobURL(c, containerURL)
218
219	_, err := copyBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
220	validateStorageError(c, err, azblob.ServiceCodeBlobNotFound)
221}
222
223func (s *aztestsSuite) TestBlobStartCopySourcePrivate(c *chk.C) {
224	bsu := getBSU()
225	containerURL, _ := createNewContainer(c, bsu)
226	defer deleteContainer(c, containerURL)
227	_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessNone, nil, azblob.ContainerAccessConditions{})
228	c.Assert(err, chk.IsNil)
229	blobURL, _ := createNewBlockBlob(c, containerURL)
230
231	bsu2, err := getAlternateBSU()
232	if err != nil {
233		c.Skip(err.Error())
234		return
235	}
236	copyContainerURL, _ := createNewContainer(c, bsu2)
237	defer deleteContainer(c, copyContainerURL)
238	copyBlobURL, _ := getBlockBlobURL(c, copyContainerURL)
239
240	if bsu.String() == bsu2.String() {
241		c.Skip("Test not valid because primary and secondary accounts are the same")
242	}
243	_, err = copyBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
244	validateStorageError(c, err, azblob.ServiceCodeCannotVerifyCopySource)
245}
246
247func (s *aztestsSuite) TestBlobStartCopyUsingSASSrc(c *chk.C) {
248	bsu := getBSU()
249	containerURL, containerName := createNewContainer(c, bsu)
250	defer deleteContainer(c, containerURL)
251	_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessNone, nil, azblob.ContainerAccessConditions{})
252	c.Assert(err, chk.IsNil)
253	blobURL, blobName := createNewBlockBlob(c, containerURL)
254
255	// Create sas values for the source blob
256	credential, err := getGenericCredential("")
257	if err != nil {
258		c.Fatal("Invalid credential")
259	}
260	serviceSASValues := azblob.BlobSASSignatureValues{StartTime: time.Now().Add(-1 * time.Hour).UTC(),
261		ExpiryTime: time.Now().Add(time.Hour).UTC(), Permissions: azblob.BlobSASPermissions{Read: true, Write: true}.String(),
262		ContainerName: containerName, BlobName: blobName}
263	queryParams, err := serviceSASValues.NewSASQueryParameters(credential)
264	if err != nil {
265		c.Fatal(err)
266	}
267
268	// Create URLs to the destination blob with sas parameters
269	sasURL := blobURL.URL()
270	sasURL.RawQuery = queryParams.Encode()
271
272	// Create a new container for the destination
273	bsu2, err := getAlternateBSU()
274	if err != nil {
275		c.Skip(err.Error())
276		return
277	}
278	copyContainerURL, _ := createNewContainer(c, bsu2)
279	defer deleteContainer(c, copyContainerURL)
280	copyBlobURL, _ := getBlockBlobURL(c, copyContainerURL)
281
282	resp, err := copyBlobURL.StartCopyFromURL(ctx, sasURL, nil, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
283	c.Assert(err, chk.IsNil)
284
285	waitForCopy(c, copyBlobURL, resp)
286
287	resp2, err := copyBlobURL.Download(ctx, 0, int64(len(blockBlobDefaultData)), azblob.BlobAccessConditions{}, false)
288	c.Assert(err, chk.IsNil)
289
290	data, err := ioutil.ReadAll(resp2.Response().Body)
291	c.Assert(resp2.ContentLength(), chk.Equals, int64(len(blockBlobDefaultData)))
292	c.Assert(string(data), chk.Equals, blockBlobDefaultData)
293	resp2.Body(azblob.RetryReaderOptions{}).Close()
294}
295
296func (s *aztestsSuite) TestBlobStartCopyUsingSASDest(c *chk.C) {
297	bsu := getBSU()
298	containerURL, containerName := createNewContainer(c, bsu)
299	defer deleteContainer(c, containerURL)
300	_, err := containerURL.SetAccessPolicy(ctx, azblob.PublicAccessNone, nil, azblob.ContainerAccessConditions{})
301	c.Assert(err, chk.IsNil)
302	blobURL, blobName := createNewBlockBlob(c, containerURL)
303	_ = blobURL
304
305	// Generate SAS on the source
306	serviceSASValues := azblob.BlobSASSignatureValues{ExpiryTime: time.Now().Add(time.Hour).UTC(),
307		Permissions: azblob.BlobSASPermissions{Read: true, Write: true, Create: true}.String(), ContainerName: containerName, BlobName: blobName}
308	credential, err := getGenericCredential("")
309	if err != nil {
310		c.Fatal("Invalid credential")
311	}
312	queryParams, err := serviceSASValues.NewSASQueryParameters(credential)
313	if err != nil {
314		c.Fatal(err)
315	}
316
317	// Create destination container
318	bsu2, err := getAlternateBSU()
319	if err != nil {
320		c.Skip(err.Error())
321		return
322	}
323
324	copyContainerURL, copyContainerName := createNewContainer(c, bsu2)
325	defer deleteContainer(c, copyContainerURL)
326	copyBlobURL, copyBlobName := getBlockBlobURL(c, copyContainerURL)
327
328	// Generate Sas for the destination
329	credential, err = getGenericCredential("SECONDARY_")
330	if err != nil {
331		c.Fatal("Invalid secondary credential")
332	}
333	copyServiceSASvalues := azblob.BlobSASSignatureValues{StartTime: time.Now().Add(-1 * time.Hour).UTC(),
334		ExpiryTime: time.Now().Add(time.Hour).UTC(), Permissions: azblob.BlobSASPermissions{Read: true, Write: true}.String(),
335		ContainerName: copyContainerName, BlobName: copyBlobName}
336	copyQueryParams, err := copyServiceSASvalues.NewSASQueryParameters(credential)
337	if err != nil {
338		c.Fatal(err)
339	}
340
341	// Generate anonymous URL to destination with SAS
342	anonURL := bsu2.URL()
343	anonURL.RawQuery = copyQueryParams.Encode()
344	anonPipeline := azblob.NewPipeline(azblob.NewAnonymousCredential(), azblob.PipelineOptions{})
345	anonBSU := azblob.NewServiceURL(anonURL, anonPipeline)
346	anonContainerURL := anonBSU.NewContainerURL(copyContainerName)
347	anonBlobURL := anonContainerURL.NewBlockBlobURL(copyBlobName)
348
349	// Apply sas to source
350	srcBlobWithSasURL := blobURL.URL()
351	srcBlobWithSasURL.RawQuery = queryParams.Encode()
352
353	resp, err := anonBlobURL.StartCopyFromURL(ctx, srcBlobWithSasURL, nil, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
354	c.Assert(err, chk.IsNil)
355
356	// Allow copy to happen
357	waitForCopy(c, anonBlobURL, resp)
358
359	resp2, err := copyBlobURL.Download(ctx, 0, int64(len(blockBlobDefaultData)), azblob.BlobAccessConditions{}, false)
360	c.Assert(err, chk.IsNil)
361
362	data, err := ioutil.ReadAll(resp2.Response().Body)
363	_, err = resp2.Body(azblob.RetryReaderOptions{}).Read(data)
364	c.Assert(resp2.ContentLength(), chk.Equals, int64(len(blockBlobDefaultData)))
365	c.Assert(string(data), chk.Equals, blockBlobDefaultData)
366	resp2.Body(azblob.RetryReaderOptions{}).Close()
367}
368
369func (s *aztestsSuite) TestBlobStartCopySourceIfModifiedSinceTrue(c *chk.C) {
370	currentTime := getRelativeTimeGMT(-10)
371
372	bsu := getBSU()
373	containerURL, _ := createNewContainer(c, bsu)
374	defer deleteContainer(c, containerURL)
375	blobURL, _ := createNewBlockBlob(c, containerURL)
376
377	destBlobURL, _ := getBlockBlobURL(c, containerURL)
378	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata,
379		azblob.ModifiedAccessConditions{IfModifiedSince: currentTime},
380		azblob.BlobAccessConditions{})
381	c.Assert(err, chk.IsNil)
382
383	resp, err := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
384	c.Assert(err, chk.IsNil)
385	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
386}
387
388func (s *aztestsSuite) TestBlobStartCopySourceIfModifiedSinceFalse(c *chk.C) {
389	bsu := getBSU()
390	containerURL, _ := createNewContainer(c, bsu)
391	defer deleteContainer(c, containerURL)
392	blobURL, _ := createNewBlockBlob(c, containerURL)
393
394	currentTime := getRelativeTimeGMT(10)
395
396	destBlobURL, _ := getBlockBlobURL(c, containerURL)
397	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil,
398		azblob.ModifiedAccessConditions{IfModifiedSince: currentTime},
399		azblob.BlobAccessConditions{})
400	validateStorageError(c, err, azblob.ServiceCodeSourceConditionNotMet)
401}
402
403func (s *aztestsSuite) TestBlobStartCopySourceIfUnmodifiedSinceTrue(c *chk.C) {
404	bsu := getBSU()
405	containerURL, _ := createNewContainer(c, bsu)
406	defer deleteContainer(c, containerURL)
407	blobURL, _ := createNewBlockBlob(c, containerURL)
408
409	currentTime := getRelativeTimeGMT(10)
410
411	destBlobURL, _ := getBlockBlobURL(c, containerURL)
412	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata,
413		azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime},
414		azblob.BlobAccessConditions{})
415	c.Assert(err, chk.IsNil)
416
417	resp, err := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
418	c.Assert(err, chk.IsNil)
419	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
420}
421
422func (s *aztestsSuite) TestBlobStartCopySourceIfUnmodifiedSinceFalse(c *chk.C) {
423	bsu := getBSU()
424	containerURL, _ := createNewContainer(c, bsu)
425	defer deleteContainer(c, containerURL)
426	blobURL, _ := createNewBlockBlob(c, containerURL)
427
428	currentTime := getRelativeTimeGMT(-10)
429
430	destBlobURL, _ := getBlockBlobURL(c, containerURL)
431	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil,
432		azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime},
433		azblob.BlobAccessConditions{})
434	validateStorageError(c, err, azblob.ServiceCodeSourceConditionNotMet)
435}
436
437func (s *aztestsSuite) TestBlobStartCopySourceIfMatchTrue(c *chk.C) {
438	bsu := getBSU()
439	containerURL, _ := createNewContainer(c, bsu)
440	defer deleteContainer(c, containerURL)
441	blobURL, _ := createNewBlockBlob(c, containerURL)
442
443	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
444	c.Assert(err, chk.IsNil)
445	etag := resp.ETag()
446
447	destBlobURL, _ := getBlockBlobURL(c, containerURL)
448	_, err = destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata,
449		azblob.ModifiedAccessConditions{IfMatch: etag},
450		azblob.BlobAccessConditions{})
451	c.Assert(err, chk.IsNil)
452
453	resp2, err := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
454	c.Assert(err, chk.IsNil)
455	c.Assert(resp2.NewMetadata(), chk.DeepEquals, basicMetadata)
456}
457
458func (s *aztestsSuite) TestBlobStartCopySourceIfMatchFalse(c *chk.C) {
459	bsu := getBSU()
460	containerURL, _ := createNewContainer(c, bsu)
461	defer deleteContainer(c, containerURL)
462	blobURL, _ := createNewBlockBlob(c, containerURL)
463
464	destBlobURL, _ := getBlockBlobURL(c, containerURL)
465	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata,
466		azblob.ModifiedAccessConditions{IfMatch: "a"},
467		azblob.BlobAccessConditions{})
468	validateStorageError(c, err, azblob.ServiceCodeSourceConditionNotMet)
469}
470
471func (s *aztestsSuite) TestBlobStartCopySourceIfNoneMatchTrue(c *chk.C) {
472	bsu := getBSU()
473	containerURL, _ := createNewContainer(c, bsu)
474	defer deleteContainer(c, containerURL)
475	blobURL, _ := createNewBlockBlob(c, containerURL)
476
477	destBlobURL, _ := getBlockBlobURL(c, containerURL)
478	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata,
479		azblob.ModifiedAccessConditions{IfNoneMatch: "a"},
480		azblob.BlobAccessConditions{})
481	c.Assert(err, chk.IsNil)
482
483	resp2, err := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
484	c.Assert(err, chk.IsNil)
485	c.Assert(resp2.NewMetadata(), chk.DeepEquals, basicMetadata)
486}
487
488func (s *aztestsSuite) TestBlobStartCopySourceIfNoneMatchFalse(c *chk.C) {
489	bsu := getBSU()
490	containerURL, _ := createNewContainer(c, bsu)
491	defer deleteContainer(c, containerURL)
492	blobURL, _ := createNewBlockBlob(c, containerURL)
493
494	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
495	c.Assert(err, chk.IsNil)
496	etag := resp.ETag()
497
498	destBlobURL, _ := getBlockBlobURL(c, containerURL)
499	_, err = destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil,
500		azblob.ModifiedAccessConditions{IfNoneMatch: etag},
501		azblob.BlobAccessConditions{})
502	validateStorageError(c, err, azblob.ServiceCodeSourceConditionNotMet)
503}
504
505func (s *aztestsSuite) TestBlobStartCopyDestIfModifiedSinceTrue(c *chk.C) {
506	currentTime := getRelativeTimeGMT(-10)
507	bsu := getBSU()
508	containerURL, _ := createNewContainer(c, bsu)
509	defer deleteContainer(c, containerURL)
510	blobURL, _ := createNewBlockBlob(c, containerURL)
511
512	destBlobURL, _ := createNewBlockBlob(c, containerURL) // The blob must exist to have a last-modified time
513	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata,
514		azblob.ModifiedAccessConditions{},
515		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
516	c.Assert(err, chk.IsNil)
517
518	resp, err := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
519	c.Assert(err, chk.IsNil)
520	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
521}
522
523func (s *aztestsSuite) TestBlobStartCopyDestIfModifiedSinceFalse(c *chk.C) {
524	bsu := getBSU()
525	containerURL, _ := createNewContainer(c, bsu)
526	defer deleteContainer(c, containerURL)
527	blobURL, _ := createNewBlockBlob(c, containerURL)
528
529	destBlobURL, _ := createNewBlockBlob(c, containerURL)
530	currentTime := getRelativeTimeGMT(10)
531
532	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil,
533		azblob.ModifiedAccessConditions{},
534		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
535	validateStorageError(c, err, azblob.ServiceCodeTargetConditionNotMet)
536}
537
538func (s *aztestsSuite) TestBlobStartCopyDestIfUnmodifiedSinceTrue(c *chk.C) {
539	bsu := getBSU()
540	containerURL, _ := createNewContainer(c, bsu)
541	defer deleteContainer(c, containerURL)
542	blobURL, _ := createNewBlockBlob(c, containerURL)
543
544	destBlobURL, _ := createNewBlockBlob(c, containerURL)
545	currentTime := getRelativeTimeGMT(10)
546
547	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata,
548		azblob.ModifiedAccessConditions{},
549		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
550	c.Assert(err, chk.IsNil)
551
552	resp, err := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
553	c.Assert(err, chk.IsNil)
554	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
555}
556
557func (s *aztestsSuite) TestBlobStartCopyDestIfUnmodifiedSinceFalse(c *chk.C) {
558	bsu := getBSU()
559	containerURL, _ := createNewContainer(c, bsu)
560	defer deleteContainer(c, containerURL)
561	blobURL, _ := createNewBlockBlob(c, containerURL)
562
563	currentTime := getRelativeTimeGMT(-10)
564	destBlobURL, _ := createNewBlockBlob(c, containerURL)
565
566	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil,
567		azblob.ModifiedAccessConditions{},
568		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
569	validateStorageError(c, err, azblob.ServiceCodeTargetConditionNotMet)
570}
571
572func (s *aztestsSuite) TestBlobStartCopyDestIfMatchTrue(c *chk.C) {
573	bsu := getBSU()
574	containerURL, _ := createNewContainer(c, bsu)
575	defer deleteContainer(c, containerURL)
576	blobURL, _ := createNewBlockBlob(c, containerURL)
577
578	destBlobURL, _ := createNewBlockBlob(c, containerURL)
579	resp, _ := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
580	etag := resp.ETag()
581
582	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata,
583		azblob.ModifiedAccessConditions{},
584		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: etag}})
585	c.Assert(err, chk.IsNil)
586
587	resp, err = destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
588	c.Assert(err, chk.IsNil)
589	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
590}
591
592func (s *aztestsSuite) TestBlobStartCopyDestIfMatchFalse(c *chk.C) {
593	bsu := getBSU()
594	containerURL, _ := createNewContainer(c, bsu)
595	defer deleteContainer(c, containerURL)
596	blobURL, _ := createNewBlockBlob(c, containerURL)
597
598	destBlobURL, _ := createNewBlockBlob(c, containerURL)
599	resp, _ := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
600	etag := resp.ETag()
601
602	destBlobURL.SetMetadata(ctx, nil, azblob.BlobAccessConditions{}) // SetMetadata chances the blob's etag
603
604	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil, azblob.ModifiedAccessConditions{},
605		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: etag}})
606	validateStorageError(c, err, azblob.ServiceCodeTargetConditionNotMet)
607}
608
609func (s *aztestsSuite) TestBlobStartCopyDestIfNoneMatchTrue(c *chk.C) {
610	bsu := getBSU()
611	containerURL, _ := createNewContainer(c, bsu)
612	defer deleteContainer(c, containerURL)
613	blobURL, _ := createNewBlockBlob(c, containerURL)
614
615	destBlobURL, _ := createNewBlockBlob(c, containerURL)
616	resp, _ := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
617	etag := resp.ETag()
618
619	destBlobURL.SetMetadata(ctx, nil, azblob.BlobAccessConditions{}) // SetMetadata chances the blob's etag
620
621	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), basicMetadata, azblob.ModifiedAccessConditions{},
622		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: etag}})
623	c.Assert(err, chk.IsNil)
624
625	resp, err = destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
626	c.Assert(err, chk.IsNil)
627	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
628}
629
630func (s *aztestsSuite) TestBlobStartCopyDestIfNoneMatchFalse(c *chk.C) {
631	bsu := getBSU()
632	containerURL, _ := createNewContainer(c, bsu)
633	defer deleteContainer(c, containerURL)
634	blobURL, _ := createNewBlockBlob(c, containerURL)
635
636	destBlobURL, _ := createNewBlockBlob(c, containerURL)
637	resp, _ := destBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
638	etag := resp.ETag()
639
640	_, err := destBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil, azblob.ModifiedAccessConditions{},
641		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: etag}})
642	validateStorageError(c, err, azblob.ServiceCodeTargetConditionNotMet)
643}
644
645func (s *aztestsSuite) TestBlobAbortCopyInProgress(c *chk.C) {
646	bsu := getBSU()
647	containerURL, _ := createNewContainer(c, bsu)
648	defer deleteContainer(c, containerURL)
649	blobURL, _ := getBlockBlobURL(c, containerURL)
650
651	// Create a large blob that takes time to copy
652	blobSize := 8 * 1024 * 1024
653	blobData := make([]byte, blobSize, blobSize)
654	for i := range blobData {
655		blobData[i] = byte('a' + i%26)
656	}
657	_, err := blobURL.Upload(ctx, bytes.NewReader(blobData), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
658	c.Assert(err, chk.IsNil)
659	containerURL.SetAccessPolicy(ctx, azblob.PublicAccessBlob, nil, azblob.ContainerAccessConditions{}) // So that we don't have to create a SAS
660
661	// Must copy across accounts so it takes time to copy
662	bsu2, err := getAlternateBSU()
663	if err != nil {
664		c.Skip(err.Error())
665		return
666	}
667
668	copyContainerURL, _ := createNewContainer(c, bsu2)
669	copyBlobURL, _ := getBlockBlobURL(c, copyContainerURL)
670
671	defer deleteContainer(c, copyContainerURL)
672
673	resp, err := copyBlobURL.StartCopyFromURL(ctx, blobURL.URL(), nil, azblob.ModifiedAccessConditions{}, azblob.BlobAccessConditions{})
674	c.Assert(err, chk.IsNil)
675	c.Assert(resp.CopyStatus(), chk.Equals, azblob.CopyStatusPending)
676
677	_, err = copyBlobURL.AbortCopyFromURL(ctx, resp.CopyID(), azblob.LeaseAccessConditions{})
678	if err != nil {
679		// If the error is nil, the test continues as normal.
680		// If the error is not nil, we want to check if it's because the copy is finished and send a message indicating this.
681		validateStorageError(c, err, azblob.ServiceCodeNoPendingCopyOperation)
682		c.Error("The test failed because the copy completed because it was aborted")
683	}
684
685	resp2, _ := copyBlobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
686	c.Assert(resp2.CopyStatus(), chk.Equals, azblob.CopyStatusAborted)
687}
688
689func (s *aztestsSuite) TestBlobAbortCopyNoCopyStarted(c *chk.C) {
690	bsu := getBSU()
691	containerURL, _ := createNewContainer(c, bsu)
692
693	defer deleteContainer(c, containerURL)
694
695	copyBlobURL, _ := getBlockBlobURL(c, containerURL)
696	_, err := copyBlobURL.AbortCopyFromURL(ctx, "copynotstarted", azblob.LeaseAccessConditions{})
697	validateStorageError(c, err, azblob.ServiceCodeInvalidQueryParameterValue)
698}
699
700func (s *aztestsSuite) TestBlobSnapshotMetadata(c *chk.C) {
701	bsu := getBSU()
702	containerURL, _ := createNewContainer(c, bsu)
703	defer deleteContainer(c, containerURL)
704	blobURL, _ := createNewBlockBlob(c, containerURL)
705
706	resp, err := blobURL.CreateSnapshot(ctx, basicMetadata, azblob.BlobAccessConditions{})
707	c.Assert(err, chk.IsNil)
708
709	// Since metadata is specified on the snapshot, the snapshot should have its own metadata different from the (empty) metadata on the source
710	snapshotURL := blobURL.WithSnapshot(resp.Snapshot())
711	resp2, err := snapshotURL.GetProperties(ctx, azblob.BlobAccessConditions{})
712	c.Assert(err, chk.IsNil)
713	c.Assert(resp2.NewMetadata(), chk.DeepEquals, basicMetadata)
714}
715
716func (s *aztestsSuite) TestBlobSnapshotMetadataEmpty(c *chk.C) {
717	bsu := getBSU()
718	containerURL, _ := createNewContainer(c, bsu)
719	defer deleteContainer(c, containerURL)
720	blobURL, _ := createNewBlockBlob(c, containerURL)
721
722	_, err := blobURL.SetMetadata(ctx, basicMetadata, azblob.BlobAccessConditions{})
723	c.Assert(err, chk.IsNil)
724
725	resp, err := blobURL.CreateSnapshot(ctx, azblob.Metadata{}, azblob.BlobAccessConditions{})
726	c.Assert(err, chk.IsNil)
727
728	// In this case, because no metadata was specified, it should copy the basicMetadata from the source
729	snapshotURL := blobURL.WithSnapshot(resp.Snapshot())
730	resp2, err := snapshotURL.GetProperties(ctx, azblob.BlobAccessConditions{})
731	c.Assert(err, chk.IsNil)
732	c.Assert(resp2.NewMetadata(), chk.DeepEquals, basicMetadata)
733}
734
735func (s *aztestsSuite) TestBlobSnapshotMetadataNil(c *chk.C) {
736	bsu := getBSU()
737	containerURL, _ := createNewContainer(c, bsu)
738	defer deleteContainer(c, containerURL)
739	blobURL, _ := createNewBlockBlob(c, containerURL)
740
741	_, err := blobURL.SetMetadata(ctx, basicMetadata, azblob.BlobAccessConditions{})
742	c.Assert(err, chk.IsNil)
743
744	resp, err := blobURL.CreateSnapshot(ctx, nil, azblob.BlobAccessConditions{})
745	c.Assert(err, chk.IsNil)
746
747	snapshotURL := blobURL.WithSnapshot(resp.Snapshot())
748	resp2, err := snapshotURL.GetProperties(ctx, azblob.BlobAccessConditions{})
749	c.Assert(err, chk.IsNil)
750	c.Assert(resp2.NewMetadata(), chk.DeepEquals, basicMetadata)
751}
752
753func (s *aztestsSuite) TestBlobSnapshotMetadataInvalid(c *chk.C) {
754	bsu := getBSU()
755	containerURL, _ := createNewContainer(c, bsu)
756	defer deleteContainer(c, containerURL)
757	blobURL, _ := createNewBlockBlob(c, containerURL)
758
759	_, err := blobURL.CreateSnapshot(ctx, azblob.Metadata{"Invalid Field!": "value"}, azblob.BlobAccessConditions{})
760	c.Assert(err, chk.NotNil)
761	c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true)
762}
763
764func (s *aztestsSuite) TestBlobSnapshotBlobNotExist(c *chk.C) {
765	bsu := getBSU()
766	containerURL, _ := createNewContainer(c, bsu)
767	defer deleteContainer(c, containerURL)
768	blobURL, _ := getBlockBlobURL(c, containerURL)
769
770	_, err := blobURL.CreateSnapshot(ctx, nil, azblob.BlobAccessConditions{})
771	validateStorageError(c, err, azblob.ServiceCodeBlobNotFound)
772}
773
774func (s *aztestsSuite) TestBlobSnapshotOfSnapshot(c *chk.C) {
775	bsu := getBSU()
776	containerURL, _ := createNewContainer(c, bsu)
777	defer deleteContainer(c, containerURL)
778	blobURL, _ := createNewBlockBlob(c, containerURL)
779
780	snapshotURL := blobURL.WithSnapshot(time.Now().UTC().Format(azblob.SnapshotTimeFormat))
781	// The library allows the server to handle the snapshot of snapshot error
782	_, err := snapshotURL.CreateSnapshot(ctx, nil, azblob.BlobAccessConditions{})
783	validateStorageError(c, err, azblob.ServiceCodeInvalidQueryParameterValue)
784}
785
786func (s *aztestsSuite) TestBlobSnapshotIfModifiedSinceTrue(c *chk.C) {
787	currentTime := getRelativeTimeGMT(-10)
788
789	bsu := getBSU()
790	containerURL, _ := createNewContainer(c, bsu)
791	defer deleteContainer(c, containerURL)
792	blobURL, _ := createNewBlockBlob(c, containerURL)
793
794	resp, err := blobURL.CreateSnapshot(ctx, nil,
795		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
796	c.Assert(err, chk.IsNil)
797	c.Assert(resp.Snapshot() != "", chk.Equals, true) // i.e. The snapshot time is not zero. If the service gives us back a snapshot time, it successfully created a snapshot
798}
799
800func (s *aztestsSuite) TestBlobSnapshotIfModifiedSinceFalse(c *chk.C) {
801	bsu := getBSU()
802	containerURL, _ := createNewContainer(c, bsu)
803	defer deleteContainer(c, containerURL)
804	blobURL, _ := createNewBlockBlob(c, containerURL)
805
806	currentTime := getRelativeTimeGMT(10)
807
808	_, err := blobURL.CreateSnapshot(ctx, nil,
809		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
810	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
811}
812
813func (s *aztestsSuite) TestBlobSnapshotIfUnmodifiedSinceTrue(c *chk.C) {
814	bsu := getBSU()
815	containerURL, _ := createNewContainer(c, bsu)
816	defer deleteContainer(c, containerURL)
817	blobURL, _ := createNewBlockBlob(c, containerURL)
818
819	currentTime := getRelativeTimeGMT(10)
820
821	resp, err := blobURL.CreateSnapshot(ctx, nil,
822		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
823	c.Assert(err, chk.IsNil)
824	c.Assert(resp.Snapshot() == "", chk.Equals, false)
825}
826
827func (s *aztestsSuite) TestBlobSnapshotIfUnmodifiedSinceFalse(c *chk.C) {
828	currentTime := getRelativeTimeGMT(-10)
829
830	bsu := getBSU()
831	containerURL, _ := createNewContainer(c, bsu)
832	defer deleteContainer(c, containerURL)
833	blobURL, _ := createNewBlockBlob(c, containerURL)
834
835	_, err := blobURL.CreateSnapshot(ctx, nil,
836		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
837	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
838}
839
840func (s *aztestsSuite) TestBlobSnapshotIfMatchTrue(c *chk.C) {
841	bsu := getBSU()
842	containerURL, _ := createNewContainer(c, bsu)
843	defer deleteContainer(c, containerURL)
844	blobURL, _ := createNewBlockBlob(c, containerURL)
845
846	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
847
848	resp2, err := blobURL.CreateSnapshot(ctx, nil,
849		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}})
850	c.Assert(err, chk.IsNil)
851	c.Assert(resp2.Snapshot() == "", chk.Equals, false)
852}
853
854func (s *aztestsSuite) TestBlobSnapshotIfMatchFalse(c *chk.C) {
855	bsu := getBSU()
856	containerURL, _ := createNewContainer(c, bsu)
857	defer deleteContainer(c, containerURL)
858	blobURL, _ := createNewBlockBlob(c, containerURL)
859
860	_, err := blobURL.CreateSnapshot(ctx, nil,
861		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: "garbage"}})
862	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
863}
864
865func (s *aztestsSuite) TestBlobSnapshotIfNoneMatchTrue(c *chk.C) {
866	bsu := getBSU()
867	containerURL, _ := createNewContainer(c, bsu)
868	defer deleteContainer(c, containerURL)
869	blobURL, _ := createNewBlockBlob(c, containerURL)
870
871	resp, err := blobURL.CreateSnapshot(ctx, nil,
872		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: "garbage"}})
873	c.Assert(err, chk.IsNil)
874	c.Assert(resp.Snapshot() == "", chk.Equals, false)
875}
876
877func (s *aztestsSuite) TestBlobSnapshotIfNoneMatchFalse(c *chk.C) {
878	bsu := getBSU()
879	containerURL, _ := createNewContainer(c, bsu)
880	defer deleteContainer(c, containerURL)
881	blobURL, _ := createNewBlockBlob(c, containerURL)
882
883	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
884
885	_, err = blobURL.CreateSnapshot(ctx, nil,
886		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
887	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
888}
889
890func (s *aztestsSuite) TestBlobDownloadDataNonExistantBlob(c *chk.C) {
891	bsu := getBSU()
892	containerURL, _ := createNewContainer(c, bsu)
893	defer deleteContainer(c, containerURL)
894	blobURL, _ := getBlockBlobURL(c, containerURL)
895
896	_, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
897	validateStorageError(c, err, azblob.ServiceCodeBlobNotFound)
898}
899
900func (s *aztestsSuite) TestBlobDownloadDataNegativeOffset(c *chk.C) {
901	bsu := getBSU()
902	containerURL, _ := createNewContainer(c, bsu)
903	defer deleteContainer(c, containerURL)
904	blobURL, _ := createNewBlockBlob(c, containerURL)
905
906	_, err := blobURL.Download(ctx, -1, 0, azblob.BlobAccessConditions{}, false)
907	c.Assert(err, chk.IsNil)
908}
909
910func (s *aztestsSuite) TestBlobDownloadDataOffsetOutOfRange(c *chk.C) {
911	bsu := getBSU()
912	containerURL, _ := createNewContainer(c, bsu)
913	defer deleteContainer(c, containerURL)
914	blobURL, _ := createNewBlockBlob(c, containerURL)
915
916	_, err := blobURL.Download(ctx, int64(len(blockBlobDefaultData)), azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
917	validateStorageError(c, err, azblob.ServiceCodeInvalidRange)
918}
919
920func (s *aztestsSuite) TestBlobDownloadDataCountNegative(c *chk.C) {
921	bsu := getBSU()
922	containerURL, _ := createNewContainer(c, bsu)
923	defer deleteContainer(c, containerURL)
924	blobURL, _ := createNewBlockBlob(c, containerURL)
925
926	_, err := blobURL.Download(ctx, 0, -2, azblob.BlobAccessConditions{}, false)
927	c.Assert(err, chk.IsNil)
928}
929
930func (s *aztestsSuite) TestBlobDownloadDataCountZero(c *chk.C) {
931	bsu := getBSU()
932	containerURL, _ := createNewContainer(c, bsu)
933	defer deleteContainer(c, containerURL)
934	blobURL, _ := createNewBlockBlob(c, containerURL)
935
936	resp, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
937	c.Assert(err, chk.IsNil)
938
939	// Specifying a count of 0 results in the value being ignored
940	data, err := ioutil.ReadAll(resp.Response().Body)
941	c.Assert(err, chk.IsNil)
942	c.Assert(string(data), chk.Equals, blockBlobDefaultData)
943}
944
945func (s *aztestsSuite) TestBlobDownloadDataCountExact(c *chk.C) {
946	bsu := getBSU()
947	containerURL, _ := createNewContainer(c, bsu)
948	defer deleteContainer(c, containerURL)
949	blobURL, _ := createNewBlockBlob(c, containerURL)
950
951	resp, err := blobURL.Download(ctx, 0, int64(len(blockBlobDefaultData)), azblob.BlobAccessConditions{}, false)
952	c.Assert(err, chk.IsNil)
953
954	data, err := ioutil.ReadAll(resp.Response().Body)
955	c.Assert(err, chk.IsNil)
956	c.Assert(string(data), chk.Equals, blockBlobDefaultData)
957}
958
959func (s *aztestsSuite) TestBlobDownloadDataCountOutOfRange(c *chk.C) {
960	bsu := getBSU()
961	containerURL, _ := createNewContainer(c, bsu)
962	defer deleteContainer(c, containerURL)
963	blobURL, _ := createNewBlockBlob(c, containerURL)
964
965	resp, err := blobURL.Download(ctx, 0, int64(len(blockBlobDefaultData))*2, azblob.BlobAccessConditions{}, false)
966	c.Assert(err, chk.IsNil)
967
968	data, err := ioutil.ReadAll(resp.Response().Body)
969	c.Assert(err, chk.IsNil)
970	c.Assert(string(data), chk.Equals, blockBlobDefaultData)
971}
972
973func (s *aztestsSuite) TestBlobDownloadDataEmptyRangeStruct(c *chk.C) {
974	bsu := getBSU()
975	containerURL, _ := createNewContainer(c, bsu)
976	defer deleteContainer(c, containerURL)
977	blobURL, _ := createNewBlockBlob(c, containerURL)
978
979	resp, err := blobURL.Download(ctx, 0, 0, azblob.BlobAccessConditions{}, false)
980	c.Assert(err, chk.IsNil)
981
982	data, err := ioutil.ReadAll(resp.Response().Body)
983	c.Assert(err, chk.IsNil)
984	c.Assert(string(data), chk.Equals, blockBlobDefaultData)
985}
986
987func (s *aztestsSuite) TestBlobDownloadDataContentMD5(c *chk.C) {
988	bsu := getBSU()
989	containerURL, _ := createNewContainer(c, bsu)
990	defer deleteContainer(c, containerURL)
991	blobURL, _ := createNewBlockBlob(c, containerURL)
992
993	resp, err := blobURL.Download(ctx, 10, 3, azblob.BlobAccessConditions{}, true)
994	c.Assert(err, chk.IsNil)
995	mdf := md5.Sum([]byte(blockBlobDefaultData)[10:13])
996	c.Assert(resp.ContentMD5(), chk.DeepEquals, mdf[:])
997}
998
999func (s *aztestsSuite) TestBlobDownloadDataIfModifiedSinceTrue(c *chk.C) {
1000	currentTime := getRelativeTimeGMT(-10)
1001
1002	bsu := getBSU()
1003	containerURL, _ := createNewContainer(c, bsu)
1004	defer deleteContainer(c, containerURL)
1005	blobURL, _ := createNewBlockBlob(c, containerURL)
1006
1007	resp, err := blobURL.Download(ctx, 0, 0,
1008		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}, false)
1009	c.Assert(err, chk.IsNil)
1010	c.Assert(resp.ContentLength(), chk.Equals, int64(len(blockBlobDefaultData)))
1011}
1012
1013func (s *aztestsSuite) TestBlobDownloadDataIfModifiedSinceFalse(c *chk.C) {
1014	bsu := getBSU()
1015	containerURL, _ := createNewContainer(c, bsu)
1016	defer deleteContainer(c, containerURL)
1017	blobURL, _ := createNewBlockBlob(c, containerURL)
1018
1019	currentTime := getRelativeTimeGMT(10)
1020
1021	_, err := blobURL.Download(ctx, 0, 0,
1022		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}, false)
1023	serr := err.(azblob.StorageError)
1024	c.Assert(serr.Response().StatusCode, chk.Equals, 304) // The server does not return the error in the body even though it is a GET
1025}
1026
1027func (s *aztestsSuite) TestBlobDownloadDataIfUnmodifiedSinceTrue(c *chk.C) {
1028	bsu := getBSU()
1029	containerURL, _ := createNewContainer(c, bsu)
1030	defer deleteContainer(c, containerURL)
1031	blobURL, _ := createNewBlockBlob(c, containerURL)
1032
1033	currentTime := getRelativeTimeGMT(10)
1034
1035	resp, err := blobURL.Download(ctx, 0, 0,
1036		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, false)
1037	c.Assert(err, chk.IsNil)
1038	c.Assert(resp.ContentLength(), chk.Equals, int64(len(blockBlobDefaultData)))
1039}
1040
1041func (s *aztestsSuite) TestBlobDownloadDataIfUnmodifiedSinceFalse(c *chk.C) {
1042	currentTime := getRelativeTimeGMT(-10)
1043
1044	bsu := getBSU()
1045	containerURL, _ := createNewContainer(c, bsu)
1046	defer deleteContainer(c, containerURL)
1047	blobURL, _ := createNewBlockBlob(c, containerURL)
1048
1049	_, err := blobURL.Download(ctx, 0, 0,
1050		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, false)
1051	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1052}
1053
1054func (s *aztestsSuite) TestBlobDownloadDataIfMatchTrue(c *chk.C) {
1055	bsu := getBSU()
1056	containerURL, _ := createNewContainer(c, bsu)
1057	defer deleteContainer(c, containerURL)
1058	blobURL, _ := createNewBlockBlob(c, containerURL)
1059
1060	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1061	c.Assert(err, chk.IsNil)
1062	etag := resp.ETag()
1063
1064	resp2, err := blobURL.Download(ctx, 0, 0,
1065		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: etag}}, false)
1066	c.Assert(err, chk.IsNil)
1067	c.Assert(resp2.ContentLength(), chk.Equals, int64(len(blockBlobDefaultData)))
1068}
1069
1070func (s *aztestsSuite) TestBlobDownloadDataIfMatchFalse(c *chk.C) {
1071	bsu := getBSU()
1072	containerURL, _ := createNewContainer(c, bsu)
1073	defer deleteContainer(c, containerURL)
1074	blobURL, _ := createNewBlockBlob(c, containerURL)
1075
1076	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1077	c.Assert(err, chk.IsNil)
1078	etag := resp.ETag()
1079
1080	blobURL.SetMetadata(ctx, nil, azblob.BlobAccessConditions{})
1081
1082	_, err = blobURL.Download(ctx, 0, 0,
1083		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: etag}}, false)
1084	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1085}
1086
1087func (s *aztestsSuite) TestBlobDownloadDataIfNoneMatchTrue(c *chk.C) {
1088	bsu := getBSU()
1089	containerURL, _ := createNewContainer(c, bsu)
1090	defer deleteContainer(c, containerURL)
1091	blobURL, _ := createNewBlockBlob(c, containerURL)
1092
1093	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1094	c.Assert(err, chk.IsNil)
1095	etag := resp.ETag()
1096
1097	blobURL.SetMetadata(ctx, nil, azblob.BlobAccessConditions{})
1098
1099	resp2, err := blobURL.Download(ctx, 0, 0,
1100		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: etag}}, false)
1101	c.Assert(err, chk.IsNil)
1102	c.Assert(resp2.ContentLength(), chk.Equals, int64(len(blockBlobDefaultData)))
1103}
1104
1105func (s *aztestsSuite) TestBlobDownloadDataIfNoneMatchFalse(c *chk.C) {
1106	bsu := getBSU()
1107	containerURL, _ := createNewContainer(c, bsu)
1108	defer deleteContainer(c, containerURL)
1109	blobURL, _ := createNewBlockBlob(c, containerURL)
1110
1111	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1112	c.Assert(err, chk.IsNil)
1113	etag := resp.ETag()
1114
1115	_, err = blobURL.Download(ctx, 0, 0,
1116		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: etag}}, false)
1117	serr := err.(azblob.StorageError)
1118	c.Assert(serr.Response().StatusCode, chk.Equals, 304) // The server does not return the error in the body even though it is a GET
1119}
1120
1121func (s *aztestsSuite) TestBlobDeleteNonExistant(c *chk.C) {
1122	bsu := getBSU()
1123	containerURL, _ := createNewContainer(c, bsu)
1124	defer deleteContainer(c, containerURL)
1125	blobURL, _ := getBlockBlobURL(c, containerURL)
1126
1127	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionInclude, azblob.BlobAccessConditions{})
1128	validateStorageError(c, err, azblob.ServiceCodeBlobNotFound)
1129}
1130
1131func (s *aztestsSuite) TestBlobDeleteSnapshot(c *chk.C) {
1132	bsu := getBSU()
1133	containerURL, _ := createNewContainer(c, bsu)
1134	defer deleteContainer(c, containerURL)
1135	blobURL, _ := createNewBlockBlob(c, containerURL)
1136
1137	resp, err := blobURL.CreateSnapshot(ctx, nil, azblob.BlobAccessConditions{})
1138	c.Assert(err, chk.IsNil)
1139	snapshotURL := blobURL.WithSnapshot(resp.Snapshot())
1140
1141	_, err = snapshotURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
1142	c.Assert(err, chk.IsNil)
1143
1144	validateBlobDeleted(c, snapshotURL)
1145}
1146
1147func (s *aztestsSuite) TestBlobDeleteSnapshotsInclude(c *chk.C) {
1148	bsu := getBSU()
1149	containerURL, _ := createNewContainer(c, bsu)
1150	defer deleteContainer(c, containerURL)
1151	blobURL, _ := createNewBlockBlob(c, containerURL)
1152
1153	_, err := blobURL.CreateSnapshot(ctx, nil, azblob.BlobAccessConditions{})
1154	c.Assert(err, chk.IsNil)
1155	_, err = blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionInclude, azblob.BlobAccessConditions{})
1156	c.Assert(err, chk.IsNil)
1157
1158	resp, _ := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{},
1159		azblob.ListBlobsSegmentOptions{Details: azblob.BlobListingDetails{Snapshots: true}})
1160	c.Assert(resp.Segment.BlobItems, chk.HasLen, 0)
1161}
1162
1163func (s *aztestsSuite) TestBlobDeleteSnapshotsOnly(c *chk.C) {
1164	bsu := getBSU()
1165	containerURL, _ := createNewContainer(c, bsu)
1166	defer deleteContainer(c, containerURL)
1167	blobURL, _ := createNewBlockBlob(c, containerURL)
1168
1169	_, err := blobURL.CreateSnapshot(ctx, nil, azblob.BlobAccessConditions{})
1170	c.Assert(err, chk.IsNil)
1171	_, err = blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionOnly, azblob.BlobAccessConditions{})
1172	c.Assert(err, chk.IsNil)
1173
1174	resp, _ := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{},
1175		azblob.ListBlobsSegmentOptions{Details: azblob.BlobListingDetails{Snapshots: true}})
1176	c.Assert(resp.Segment.BlobItems, chk.HasLen, 1)
1177	c.Assert(resp.Segment.BlobItems[0].Snapshot == "", chk.Equals, true)
1178}
1179
1180func (s *aztestsSuite) TestBlobDeleteSnapshotsNoneWithSnapshots(c *chk.C) {
1181	bsu := getBSU()
1182	containerURL, _ := createNewContainer(c, bsu)
1183	defer deleteContainer(c, containerURL)
1184	blobURL, _ := createNewBlockBlob(c, containerURL)
1185
1186	_, err := blobURL.CreateSnapshot(ctx, nil, azblob.BlobAccessConditions{})
1187	c.Assert(err, chk.IsNil)
1188	_, err = blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
1189	validateStorageError(c, err, azblob.ServiceCodeSnapshotsPresent)
1190}
1191
1192func validateBlobDeleted(c *chk.C, blobURL azblob.BlockBlobURL) {
1193	_, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1194	c.Assert(err, chk.NotNil)
1195	serr := err.(azblob.StorageError) // Delete blob is a HEAD request and does not return a ServiceCode in the body
1196	c.Assert(serr.Response().StatusCode, chk.Equals, 404)
1197}
1198
1199func (s *aztestsSuite) TestBlobDeleteIfModifiedSinceTrue(c *chk.C) {
1200	currentTime := getRelativeTimeGMT(-10)
1201
1202	bsu := getBSU()
1203	containerURL, _ := createNewContainer(c, bsu)
1204	defer deleteContainer(c, containerURL)
1205	blobURL, _ := createNewBlockBlob(c, containerURL)
1206
1207	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone,
1208		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
1209	c.Assert(err, chk.IsNil)
1210
1211	validateBlobDeleted(c, blobURL)
1212}
1213
1214func (s *aztestsSuite) TestBlobDeleteIfModifiedSinceFalse(c *chk.C) {
1215	bsu := getBSU()
1216	containerURL, _ := createNewContainer(c, bsu)
1217	defer deleteContainer(c, containerURL)
1218	blobURL, _ := createNewBlockBlob(c, containerURL)
1219
1220	currentTime := getRelativeTimeGMT(10)
1221
1222	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone,
1223		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
1224	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1225}
1226
1227func (s *aztestsSuite) TestBlobDeleteIfUnmodifiedSinceTrue(c *chk.C) {
1228	bsu := getBSU()
1229	containerURL, _ := createNewContainer(c, bsu)
1230	defer deleteContainer(c, containerURL)
1231	blobURL, _ := createNewBlockBlob(c, containerURL)
1232
1233	currentTime := getRelativeTimeGMT(10)
1234
1235	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone,
1236		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1237	c.Assert(err, chk.IsNil)
1238
1239	validateBlobDeleted(c, blobURL)
1240}
1241
1242func (s *aztestsSuite) TestBlobDeleteIfUnmodifiedSinceFalse(c *chk.C) {
1243	currentTime := getRelativeTimeGMT(-10)
1244
1245	bsu := getBSU()
1246	containerURL, _ := createNewContainer(c, bsu)
1247	defer deleteContainer(c, containerURL)
1248	blobURL, _ := createNewBlockBlob(c, containerURL)
1249
1250	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone,
1251		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1252	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1253}
1254
1255func (s *aztestsSuite) TestBlobDeleteIfMatchTrue(c *chk.C) {
1256	bsu := getBSU()
1257	containerURL, _ := createNewContainer(c, bsu)
1258	defer deleteContainer(c, containerURL)
1259	blobURL, _ := createNewBlockBlob(c, containerURL)
1260
1261	resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1262	etag := resp.ETag()
1263
1264	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone,
1265		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: etag}})
1266	c.Assert(err, chk.IsNil)
1267
1268	validateBlobDeleted(c, blobURL)
1269}
1270
1271func (s *aztestsSuite) TestBlobDeleteIfMatchFalse(c *chk.C) {
1272	bsu := getBSU()
1273	containerURL, _ := createNewContainer(c, bsu)
1274	defer deleteContainer(c, containerURL)
1275	blobURL, _ := createNewBlockBlob(c, containerURL)
1276
1277	resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1278	etag := resp.ETag()
1279	blobURL.SetMetadata(ctx, nil, azblob.BlobAccessConditions{})
1280
1281	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone,
1282		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: etag}})
1283
1284	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1285}
1286
1287func (s *aztestsSuite) TestBlobDeleteIfNoneMatchTrue(c *chk.C) {
1288	bsu := getBSU()
1289	containerURL, _ := createNewContainer(c, bsu)
1290	defer deleteContainer(c, containerURL)
1291	blobURL, _ := createNewBlockBlob(c, containerURL)
1292
1293	resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1294	etag := resp.ETag()
1295	blobURL.SetMetadata(ctx, nil, azblob.BlobAccessConditions{})
1296
1297	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone,
1298		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: etag}})
1299	c.Assert(err, chk.IsNil)
1300
1301	validateBlobDeleted(c, blobURL)
1302}
1303
1304func (s *aztestsSuite) TestBlobDeleteIfNoneMatchFalse(c *chk.C) {
1305	bsu := getBSU()
1306	containerURL, _ := createNewContainer(c, bsu)
1307	defer deleteContainer(c, containerURL)
1308	blobURL, _ := createNewBlockBlob(c, containerURL)
1309
1310	resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1311	etag := resp.ETag()
1312
1313	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone,
1314		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: etag}})
1315	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1316}
1317
1318func (s *aztestsSuite) TestBlobGetPropsAndMetadataIfModifiedSinceTrue(c *chk.C) {
1319	currentTime := getRelativeTimeGMT(-10)
1320
1321	bsu := getBSU()
1322	containerURL, _ := createNewContainer(c, bsu)
1323	defer deleteContainer(c, containerURL)
1324	blobURL, _ := createNewBlockBlob(c, containerURL)
1325
1326	_, err := blobURL.SetMetadata(ctx, basicMetadata, azblob.BlobAccessConditions{})
1327	c.Assert(err, chk.IsNil)
1328
1329	resp, err := blobURL.GetProperties(ctx,
1330		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
1331	c.Assert(err, chk.IsNil)
1332	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
1333}
1334
1335func (s *aztestsSuite) TestBlobGetPropsAndMetadataIfModifiedSinceFalse(c *chk.C) {
1336	bsu := getBSU()
1337	containerURL, _ := createNewContainer(c, bsu)
1338	defer deleteContainer(c, containerURL)
1339	blobURL, _ := createNewBlockBlob(c, containerURL)
1340
1341	_, err := blobURL.SetMetadata(ctx, basicMetadata, azblob.BlobAccessConditions{})
1342	c.Assert(err, chk.IsNil)
1343
1344	currentTime := getRelativeTimeGMT(10)
1345
1346	_, err = blobURL.GetProperties(ctx,
1347		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
1348	c.Assert(err, chk.NotNil)
1349	serr := err.(azblob.StorageError)
1350	c.Assert(serr.Response().StatusCode, chk.Equals, 304) // No service code returned for a HEAD
1351}
1352
1353func (s *aztestsSuite) TestBlobGetPropsAndMetadataIfUnmodifiedSinceTrue(c *chk.C) {
1354	bsu := getBSU()
1355	containerURL, _ := createNewContainer(c, bsu)
1356	defer deleteContainer(c, containerURL)
1357	blobURL, _ := createNewBlockBlob(c, containerURL)
1358
1359	_, err := blobURL.SetMetadata(ctx, basicMetadata, azblob.BlobAccessConditions{})
1360	c.Assert(err, chk.IsNil)
1361
1362	currentTime := getRelativeTimeGMT(10)
1363
1364	resp, err := blobURL.GetProperties(ctx,
1365		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1366	c.Assert(err, chk.IsNil)
1367	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
1368}
1369
1370func (s *aztestsSuite) TestBlobGetPropsAndMetadataIfUnmodifiedSinceFalse(c *chk.C) {
1371	bsu := getBSU()
1372	containerURL, _ := createNewContainer(c, bsu)
1373	defer deleteContainer(c, containerURL)
1374	blobURL, _ := createNewBlockBlob(c, containerURL)
1375
1376	currentTime := getRelativeTimeGMT(-10)
1377
1378	_, err := blobURL.SetMetadata(ctx, basicMetadata, azblob.BlobAccessConditions{})
1379	c.Assert(err, chk.IsNil)
1380
1381	_, err = blobURL.GetProperties(ctx,
1382		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1383	c.Assert(err, chk.NotNil)
1384	serr := err.(azblob.StorageError)
1385	c.Assert(serr.Response().StatusCode, chk.Equals, 412)
1386}
1387
1388func (s *aztestsSuite) TestBlobGetPropsAndMetadataIfMatchTrue(c *chk.C) {
1389	bsu := getBSU()
1390	containerURL, _ := createNewContainer(c, bsu)
1391	defer deleteContainer(c, containerURL)
1392	blobURL, _ := createNewBlockBlob(c, containerURL)
1393
1394	resp, err := blobURL.SetMetadata(ctx, basicMetadata, azblob.BlobAccessConditions{})
1395	c.Assert(err, chk.IsNil)
1396
1397	resp2, err := blobURL.GetProperties(ctx,
1398		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}})
1399	c.Assert(err, chk.IsNil)
1400	c.Assert(resp2.NewMetadata(), chk.DeepEquals, basicMetadata)
1401}
1402
1403func (s *aztestsSuite) TestBlobGetPropsOnMissingBlob(c *chk.C) {
1404	bsu := getBSU()
1405	containerURL, _ := createNewContainer(c, bsu)
1406	defer deleteContainer(c, containerURL)
1407	blobURL := containerURL.NewBlobURL("MISSING")
1408
1409	_, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1410	c.Assert(err, chk.NotNil)
1411	serr := err.(azblob.StorageError)
1412	c.Assert(serr.Response().StatusCode, chk.Equals, 404)
1413	c.Assert(serr.ServiceCode(), chk.Equals, azblob.ServiceCodeBlobNotFound)
1414}
1415
1416func (s *aztestsSuite) TestBlobGetPropsAndMetadataIfMatchFalse(c *chk.C) {
1417	bsu := getBSU()
1418	containerURL, _ := createNewContainer(c, bsu)
1419	defer deleteContainer(c, containerURL)
1420	blobURL, _ := createNewBlockBlob(c, containerURL)
1421
1422	_, err := blobURL.GetProperties(ctx,
1423		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}})
1424	c.Assert(err, chk.NotNil)
1425	serr := err.(azblob.StorageError)
1426	c.Assert(serr.Response().StatusCode, chk.Equals, 412)
1427}
1428
1429func (s *aztestsSuite) TestBlobGetPropsAndMetadataIfNoneMatchTrue(c *chk.C) {
1430	bsu := getBSU()
1431	containerURL, _ := createNewContainer(c, bsu)
1432	defer deleteContainer(c, containerURL)
1433	blobURL, _ := createNewBlockBlob(c, containerURL)
1434
1435	_, err := blobURL.SetMetadata(ctx, basicMetadata, azblob.BlobAccessConditions{})
1436	c.Assert(err, chk.IsNil)
1437
1438	resp, err := blobURL.GetProperties(ctx,
1439		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}})
1440	c.Assert(err, chk.IsNil)
1441	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
1442}
1443
1444func (s *aztestsSuite) TestBlobGetPropsAndMetadataIfNoneMatchFalse(c *chk.C) {
1445	bsu := getBSU()
1446	containerURL, _ := createNewContainer(c, bsu)
1447	defer deleteContainer(c, containerURL)
1448	blobURL, _ := createNewBlockBlob(c, containerURL)
1449
1450	resp, err := blobURL.SetMetadata(ctx, nil, azblob.BlobAccessConditions{})
1451	c.Assert(err, chk.IsNil)
1452
1453	_, err = blobURL.GetProperties(ctx,
1454		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
1455	c.Assert(err, chk.NotNil)
1456	serr := err.(azblob.StorageError)
1457	c.Assert(serr.Response().StatusCode, chk.Equals, 304)
1458}
1459
1460func (s *aztestsSuite) TestBlobSetPropertiesBasic(c *chk.C) {
1461	bsu := getBSU()
1462	containerURL, _ := createNewContainer(c, bsu)
1463	defer deleteContainer(c, containerURL)
1464	blobURL, _ := createNewBlockBlob(c, containerURL)
1465
1466	_, err := blobURL.SetHTTPHeaders(ctx, basicHeaders, azblob.BlobAccessConditions{})
1467	c.Assert(err, chk.IsNil)
1468
1469	resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1470	h := resp.NewHTTPHeaders()
1471	c.Assert(h, chk.DeepEquals, basicHeaders)
1472}
1473
1474func (s *aztestsSuite) TestBlobSetPropertiesEmptyValue(c *chk.C) {
1475	bsu := getBSU()
1476	containerURL, _ := createNewContainer(c, bsu)
1477	defer deleteContainer(c, containerURL)
1478	blobURL, _ := createNewBlockBlob(c, containerURL)
1479
1480	_, err := blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{ContentType: "my_type"}, azblob.BlobAccessConditions{})
1481	c.Assert(err, chk.IsNil)
1482
1483	_, err = blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{}, azblob.BlobAccessConditions{})
1484	c.Assert(err, chk.IsNil)
1485
1486	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1487	c.Assert(err, chk.IsNil)
1488	c.Assert(resp.ContentType(), chk.Equals, "")
1489}
1490
1491func validatePropertiesSet(c *chk.C, blobURL azblob.BlockBlobURL, disposition string) {
1492	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1493	c.Assert(err, chk.IsNil)
1494	c.Assert(resp.ContentDisposition(), chk.Equals, disposition)
1495}
1496
1497func (s *aztestsSuite) TestBlobSetPropertiesIfModifiedSinceTrue(c *chk.C) {
1498	currentTime := getRelativeTimeGMT(-10)
1499
1500	bsu := getBSU()
1501	containerURL, _ := createNewContainer(c, bsu)
1502	defer deleteContainer(c, containerURL)
1503	blobURL, _ := createNewBlockBlob(c, containerURL)
1504
1505	_, err := blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"},
1506		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
1507	c.Assert(err, chk.IsNil)
1508
1509	validatePropertiesSet(c, blobURL, "my_disposition")
1510}
1511
1512func (s *aztestsSuite) TestBlobSetPropertiesIfModifiedSinceFalse(c *chk.C) {
1513	bsu := getBSU()
1514	containerURL, _ := createNewContainer(c, bsu)
1515	defer deleteContainer(c, containerURL)
1516	blobURL, _ := createNewBlockBlob(c, containerURL)
1517
1518	currentTime := getRelativeTimeGMT(10)
1519
1520	_, err := blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"},
1521		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
1522	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1523}
1524
1525func (s *aztestsSuite) TestBlobSetPropertiesIfUnmodifiedSinceTrue(c *chk.C) {
1526	bsu := getBSU()
1527	containerURL, _ := createNewContainer(c, bsu)
1528	defer deleteContainer(c, containerURL)
1529	blobURL, _ := createNewBlockBlob(c, containerURL)
1530
1531	currentTime := getRelativeTimeGMT(10)
1532
1533	_, err := blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"},
1534		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1535	c.Assert(err, chk.IsNil)
1536
1537	validatePropertiesSet(c, blobURL, "my_disposition")
1538}
1539
1540func (s *aztestsSuite) TestBlobSetPropertiesIfUnmodifiedSinceFalse(c *chk.C) {
1541	currentTime := getRelativeTimeGMT(-10)
1542
1543	bsu := getBSU()
1544	containerURL, _ := createNewContainer(c, bsu)
1545	defer deleteContainer(c, containerURL)
1546	blobURL, _ := createNewBlockBlob(c, containerURL)
1547
1548	_, err := blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"},
1549		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1550	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1551}
1552
1553func (s *aztestsSuite) TestBlobSetPropertiesIfMatchTrue(c *chk.C) {
1554	bsu := getBSU()
1555	containerURL, _ := createNewContainer(c, bsu)
1556	defer deleteContainer(c, containerURL)
1557	blobURL, _ := createNewBlockBlob(c, containerURL)
1558
1559	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1560	c.Assert(err, chk.IsNil)
1561
1562	_, err = blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"},
1563		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}})
1564	c.Assert(err, chk.IsNil)
1565
1566	validatePropertiesSet(c, blobURL, "my_disposition")
1567}
1568
1569func (s *aztestsSuite) TestBlobSetPropertiesIfMatchFalse(c *chk.C) {
1570	bsu := getBSU()
1571	containerURL, _ := createNewContainer(c, bsu)
1572	defer deleteContainer(c, containerURL)
1573	blobURL, _ := createNewBlockBlob(c, containerURL)
1574
1575	_, err := blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"},
1576		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}})
1577	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1578}
1579
1580func (s *aztestsSuite) TestBlobSetPropertiesIfNoneMatchTrue(c *chk.C) {
1581	bsu := getBSU()
1582	containerURL, _ := createNewContainer(c, bsu)
1583	defer deleteContainer(c, containerURL)
1584	blobURL, _ := createNewBlockBlob(c, containerURL)
1585
1586	_, err := blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"},
1587		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}})
1588	c.Assert(err, chk.IsNil)
1589
1590	validatePropertiesSet(c, blobURL, "my_disposition")
1591}
1592
1593func (s *aztestsSuite) TestBlobSetPropertiesIfNoneMatchFalse(c *chk.C) {
1594	bsu := getBSU()
1595	containerURL, _ := createNewContainer(c, bsu)
1596	defer deleteContainer(c, containerURL)
1597	blobURL, _ := createNewBlockBlob(c, containerURL)
1598
1599	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1600	c.Assert(err, chk.IsNil)
1601
1602	_, err = blobURL.SetHTTPHeaders(ctx, azblob.BlobHTTPHeaders{ContentDisposition: "my_disposition"},
1603		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
1604	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1605}
1606
1607func (s *aztestsSuite) TestBlobSetMetadataNil(c *chk.C) {
1608	bsu := getBSU()
1609	containerURL, _ := createNewContainer(c, bsu)
1610	defer deleteContainer(c, containerURL)
1611	blobURL, _ := createNewBlockBlob(c, containerURL)
1612
1613	_, err := blobURL.SetMetadata(ctx, azblob.Metadata{"not": "nil"}, azblob.BlobAccessConditions{})
1614	c.Assert(err, chk.IsNil)
1615
1616	_, err = blobURL.SetMetadata(ctx, nil, azblob.BlobAccessConditions{})
1617	c.Assert(err, chk.IsNil)
1618
1619	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1620	c.Assert(err, chk.IsNil)
1621	c.Assert(resp.NewMetadata(), chk.HasLen, 0)
1622}
1623
1624func (s *aztestsSuite) TestBlobSetMetadataEmpty(c *chk.C) {
1625	bsu := getBSU()
1626	containerURL, _ := createNewContainer(c, bsu)
1627	defer deleteContainer(c, containerURL)
1628	blobURL, _ := createNewBlockBlob(c, containerURL)
1629
1630	_, err := blobURL.SetMetadata(ctx, azblob.Metadata{"not": "nil"}, azblob.BlobAccessConditions{})
1631	c.Assert(err, chk.IsNil)
1632
1633	_, err = blobURL.SetMetadata(ctx, azblob.Metadata{}, azblob.BlobAccessConditions{})
1634	c.Assert(err, chk.IsNil)
1635
1636	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1637	c.Assert(err, chk.IsNil)
1638	c.Assert(resp.NewMetadata(), chk.HasLen, 0)
1639}
1640
1641func (s *aztestsSuite) TestBlobSetMetadataInvalidField(c *chk.C) {
1642	bsu := getBSU()
1643	containerURL, _ := createNewContainer(c, bsu)
1644	defer deleteContainer(c, containerURL)
1645	blobURL, _ := createNewBlockBlob(c, containerURL)
1646
1647	_, err := blobURL.SetMetadata(ctx, azblob.Metadata{"Invalid field!": "value"}, azblob.BlobAccessConditions{})
1648	c.Assert(err, chk.NotNil)
1649	c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true)
1650}
1651
1652func validateMetadataSet(c *chk.C, blobURL azblob.BlockBlobURL) {
1653	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1654	c.Assert(err, chk.IsNil)
1655	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
1656}
1657
1658func (s *aztestsSuite) TestBlobSetMetadataIfModifiedSinceTrue(c *chk.C) {
1659	currentTime := getRelativeTimeGMT(-10)
1660
1661	bsu := getBSU()
1662	containerURL, _ := createNewContainer(c, bsu)
1663	defer deleteContainer(c, containerURL)
1664	blobURL, _ := createNewBlockBlob(c, containerURL)
1665
1666	_, err := blobURL.SetMetadata(ctx, basicMetadata,
1667		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
1668	c.Assert(err, chk.IsNil)
1669
1670	validateMetadataSet(c, blobURL)
1671}
1672
1673func (s *aztestsSuite) TestBlobSetMetadataIfModifiedSinceFalse(c *chk.C) {
1674	bsu := getBSU()
1675	containerURL, _ := createNewContainer(c, bsu)
1676	defer deleteContainer(c, containerURL)
1677	blobURL, _ := createNewBlockBlob(c, containerURL)
1678
1679	currentTime := getRelativeTimeGMT(10)
1680
1681	_, err := blobURL.SetMetadata(ctx, basicMetadata,
1682		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
1683	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1684}
1685
1686func (s *aztestsSuite) TestBlobSetMetadataIfUnmodifiedSinceTrue(c *chk.C) {
1687	bsu := getBSU()
1688	containerURL, _ := createNewContainer(c, bsu)
1689	defer deleteContainer(c, containerURL)
1690	blobURL, _ := createNewBlockBlob(c, containerURL)
1691
1692	currentTime := getRelativeTimeGMT(10)
1693
1694	_, err := blobURL.SetMetadata(ctx, basicMetadata,
1695		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1696	c.Assert(err, chk.IsNil)
1697
1698	validateMetadataSet(c, blobURL)
1699}
1700
1701func (s *aztestsSuite) TestBlobSetMetadataIfUnmodifiedSinceFalse(c *chk.C) {
1702	currentTime := getRelativeTimeGMT(-10)
1703
1704	bsu := getBSU()
1705	containerURL, _ := createNewContainer(c, bsu)
1706	defer deleteContainer(c, containerURL)
1707	blobURL, _ := createNewBlockBlob(c, containerURL)
1708
1709	_, err := blobURL.SetMetadata(ctx, basicMetadata,
1710		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1711	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1712}
1713
1714func (s *aztestsSuite) TestBlobSetMetadataIfMatchTrue(c *chk.C) {
1715	bsu := getBSU()
1716	containerURL, _ := createNewContainer(c, bsu)
1717	defer deleteContainer(c, containerURL)
1718	blobURL, _ := createNewBlockBlob(c, containerURL)
1719
1720	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1721	c.Assert(err, chk.IsNil)
1722
1723	_, err = blobURL.SetMetadata(ctx, basicMetadata,
1724		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}})
1725	c.Assert(err, chk.IsNil)
1726
1727	validateMetadataSet(c, blobURL)
1728}
1729
1730func (s *aztestsSuite) TestBlobSetMetadataIfMatchFalse(c *chk.C) {
1731	bsu := getBSU()
1732	containerURL, _ := createNewContainer(c, bsu)
1733	defer deleteContainer(c, containerURL)
1734	blobURL, _ := createNewBlockBlob(c, containerURL)
1735
1736	_, err := blobURL.SetMetadata(ctx, basicMetadata,
1737		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}})
1738	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1739}
1740
1741func (s *aztestsSuite) TestBlobSetMetadataIfNoneMatchTrue(c *chk.C) {
1742	bsu := getBSU()
1743	containerURL, _ := createNewContainer(c, bsu)
1744	defer deleteContainer(c, containerURL)
1745	blobURL, _ := createNewBlockBlob(c, containerURL)
1746
1747	_, err := blobURL.SetMetadata(ctx, basicMetadata,
1748		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}})
1749	c.Assert(err, chk.IsNil)
1750
1751	validateMetadataSet(c, blobURL)
1752}
1753
1754func (s *aztestsSuite) TestBlobSetMetadataIfNoneMatchFalse(c *chk.C) {
1755	bsu := getBSU()
1756	containerURL, _ := createNewContainer(c, bsu)
1757	defer deleteContainer(c, containerURL)
1758	blobURL, _ := createNewBlockBlob(c, containerURL)
1759
1760	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1761	c.Assert(err, chk.IsNil)
1762
1763	_, err = blobURL.SetMetadata(ctx, basicMetadata,
1764		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
1765	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
1766}
1767
1768func testBlobsUndeleteImpl(c *chk.C, bsu azblob.ServiceURL) error {
1769	containerURL, _ := createNewContainer(c, bsu)
1770	defer deleteContainer(c, containerURL)
1771	blobURL, _ := createNewBlockBlob(c, containerURL)
1772
1773	_, err := blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
1774	c.Assert(err, chk.IsNil) // This call will not have errors related to slow update of service properties, so we assert.
1775
1776	_, err = blobURL.Undelete(ctx)
1777	if err != nil { // We want to give the wrapper method a chance to check if it was an error related to the service properties update.
1778		return err
1779	}
1780
1781	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1782	if err != nil {
1783		return errors.New(string(err.(azblob.StorageError).ServiceCode()))
1784	}
1785	c.Assert(resp.BlobType(), chk.Equals, azblob.BlobBlockBlob) // We could check any property. This is just to double check it was undeleted.
1786	return nil
1787}
1788
1789func (s *aztestsSuite) TestBlobsUndelete(c *chk.C) {
1790	bsu := getBSU()
1791
1792	runTestRequiringServiceProperties(c, bsu, string(azblob.ServiceCodeBlobNotFound), enableSoftDelete, testBlobsUndeleteImpl, disableSoftDelete)
1793}
1794
1795func setAndCheckBlobTier(c *chk.C, containerURL azblob.ContainerURL, blobURL azblob.BlobURL, tier azblob.AccessTierType) {
1796	_, err := blobURL.SetTier(ctx, tier, azblob.LeaseAccessConditions{})
1797	c.Assert(err, chk.IsNil)
1798
1799	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1800	c.Assert(err, chk.IsNil)
1801	c.Assert(resp.AccessTier(), chk.Equals, string(tier))
1802
1803	resp2, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
1804	c.Assert(err, chk.IsNil)
1805	c.Assert(resp2.Segment.BlobItems[0].Properties.AccessTier, chk.Equals, tier)
1806}
1807
1808func (s *aztestsSuite) TestBlobSetTierAllTiers(c *chk.C) {
1809	bsu, err := getBlobStorageBSU()
1810	if err != nil {
1811		c.Skip(err.Error())
1812	}
1813	containerURL, _ := createNewContainer(c, bsu)
1814	defer deleteContainer(c, containerURL)
1815	blobURL, _ := createNewBlockBlob(c, containerURL)
1816
1817	setAndCheckBlobTier(c, containerURL, blobURL.BlobURL, azblob.AccessTierHot)
1818	setAndCheckBlobTier(c, containerURL, blobURL.BlobURL, azblob.AccessTierCool)
1819	setAndCheckBlobTier(c, containerURL, blobURL.BlobURL, azblob.AccessTierArchive)
1820
1821	bsu, err = getPremiumBSU()
1822	if err != nil {
1823		c.Skip(err.Error())
1824	}
1825
1826	containerURL, _ = createNewContainer(c, bsu)
1827	defer deleteContainer(c, containerURL)
1828	pageBlobURL, _ := createNewPageBlob(c, containerURL)
1829
1830	setAndCheckBlobTier(c, containerURL, pageBlobURL.BlobURL, azblob.AccessTierP4)
1831	setAndCheckBlobTier(c, containerURL, pageBlobURL.BlobURL, azblob.AccessTierP6)
1832	setAndCheckBlobTier(c, containerURL, pageBlobURL.BlobURL, azblob.AccessTierP10)
1833	setAndCheckBlobTier(c, containerURL, pageBlobURL.BlobURL, azblob.AccessTierP20)
1834	setAndCheckBlobTier(c, containerURL, pageBlobURL.BlobURL, azblob.AccessTierP30)
1835	setAndCheckBlobTier(c, containerURL, pageBlobURL.BlobURL, azblob.AccessTierP40)
1836	setAndCheckBlobTier(c, containerURL, pageBlobURL.BlobURL, azblob.AccessTierP50)
1837}
1838
1839func (s *aztestsSuite) TestBlobTierInferred(c *chk.C) {
1840	bsu, err := getPremiumBSU()
1841	if err != nil {
1842		c.Skip(err.Error())
1843	}
1844
1845	containerURL, _ := createNewContainer(c, bsu)
1846	defer deleteContainer(c, containerURL)
1847	blobURL, _ := createNewPageBlob(c, containerURL)
1848
1849	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1850	c.Assert(err, chk.IsNil)
1851	c.Assert(resp.AccessTierInferred(), chk.Equals, "true")
1852
1853	resp2, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
1854	c.Assert(err, chk.IsNil)
1855	c.Assert(resp2.Segment.BlobItems[0].Properties.AccessTierInferred, chk.NotNil)
1856	c.Assert(resp2.Segment.BlobItems[0].Properties.AccessTier, chk.Not(chk.Equals), "")
1857
1858	_, err = blobURL.SetTier(ctx, azblob.AccessTierP4, azblob.LeaseAccessConditions{})
1859	c.Assert(err, chk.IsNil)
1860
1861	resp, err = blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1862	c.Assert(err, chk.IsNil)
1863	c.Assert(resp.AccessTierInferred(), chk.Equals, "")
1864
1865	resp2, err = containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
1866	c.Assert(err, chk.IsNil)
1867	c.Assert(resp2.Segment.BlobItems[0].Properties.AccessTierInferred, chk.IsNil) // AccessTierInferred never returned if false
1868}
1869
1870func (s *aztestsSuite) TestBlobArchiveStatus(c *chk.C) {
1871	bsu, err := getBlobStorageBSU()
1872	if err != nil {
1873		c.Skip(err.Error())
1874	}
1875
1876	containerURL, _ := createNewContainer(c, bsu)
1877	defer deleteContainer(c, containerURL)
1878	blobURL, _ := createNewBlockBlob(c, containerURL)
1879
1880	_, err = blobURL.SetTier(ctx, azblob.AccessTierArchive, azblob.LeaseAccessConditions{})
1881	c.Assert(err, chk.IsNil)
1882	_, err = blobURL.SetTier(ctx, azblob.AccessTierCool, azblob.LeaseAccessConditions{})
1883	c.Assert(err, chk.IsNil)
1884
1885	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1886	c.Assert(err, chk.IsNil)
1887	c.Assert(resp.ArchiveStatus(), chk.Equals, string(azblob.ArchiveStatusRehydratePendingToCool))
1888
1889	resp2, err := containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
1890	c.Assert(err, chk.IsNil)
1891	c.Assert(resp2.Segment.BlobItems[0].Properties.ArchiveStatus, chk.Equals, azblob.ArchiveStatusRehydratePendingToCool)
1892
1893	// delete first blob
1894	_, err = blobURL.Delete(ctx, azblob.DeleteSnapshotsOptionNone, azblob.BlobAccessConditions{})
1895	c.Assert(err, chk.IsNil)
1896
1897	blobURL, _ = createNewBlockBlob(c, containerURL)
1898
1899	_, err = blobURL.SetTier(ctx, azblob.AccessTierArchive, azblob.LeaseAccessConditions{})
1900	c.Assert(err, chk.IsNil)
1901	_, err = blobURL.SetTier(ctx, azblob.AccessTierHot, azblob.LeaseAccessConditions{})
1902	c.Assert(err, chk.IsNil)
1903
1904	resp, err = blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
1905	c.Assert(err, chk.IsNil)
1906	c.Assert(resp.ArchiveStatus(), chk.Equals, string(azblob.ArchiveStatusRehydratePendingToHot))
1907
1908	resp2, err = containerURL.ListBlobsFlatSegment(ctx, azblob.Marker{}, azblob.ListBlobsSegmentOptions{})
1909	c.Assert(err, chk.IsNil)
1910	c.Assert(resp2.Segment.BlobItems[0].Properties.ArchiveStatus, chk.Equals, azblob.ArchiveStatusRehydratePendingToHot)
1911}
1912
1913func (s *aztestsSuite) TestBlobTierInvalidValue(c *chk.C) {
1914	bsu, err := getBlobStorageBSU()
1915	if err != nil {
1916		c.Skip(err.Error())
1917	}
1918
1919	containerURL, _ := createNewContainer(c, bsu)
1920	defer deleteContainer(c, containerURL)
1921	blobURL, _ := createNewBlockBlob(c, containerURL)
1922
1923	_, err = blobURL.SetTier(ctx, azblob.AccessTierType("garbage"), azblob.LeaseAccessConditions{})
1924	validateStorageError(c, err, azblob.ServiceCodeInvalidHeaderValue)
1925}
1926