1package azblob
2
3import (
4	"context"
5	"crypto/md5"
6	"io/ioutil"
7
8	"bytes"
9	"strings"
10	"time"
11
12	chk "gopkg.in/check.v1"
13)
14
15func (s *aztestsSuite) TestPutGetPages(c *chk.C) {
16	bsu := getBSU()
17	container, _ := createNewContainer(c, bsu)
18	defer delContainer(c, container)
19
20	blob, _ := createNewPageBlob(c, container)
21
22	pageRange := PageRange{Start: 0, End: 1023}
23	putResp, err := blob.UploadPages(context.Background(), 0, getReaderToRandomBytes(1024), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
24	c.Assert(err, chk.IsNil)
25	c.Assert(putResp.Response().StatusCode, chk.Equals, 201)
26	c.Assert(putResp.LastModified().IsZero(), chk.Equals, false)
27	c.Assert(putResp.ETag(), chk.Not(chk.Equals), ETagNone)
28	c.Assert(putResp.ContentMD5(), chk.Not(chk.Equals), "")
29	c.Assert(putResp.BlobSequenceNumber(), chk.Equals, int64(0))
30	c.Assert(putResp.RequestID(), chk.Not(chk.Equals), "")
31	c.Assert(putResp.Version(), chk.Not(chk.Equals), "")
32	c.Assert(putResp.Date().IsZero(), chk.Equals, false)
33
34	pageList, err := blob.GetPageRanges(context.Background(), 0, 1023, BlobAccessConditions{})
35	c.Assert(err, chk.IsNil)
36	c.Assert(pageList.Response().StatusCode, chk.Equals, 200)
37	c.Assert(pageList.LastModified().IsZero(), chk.Equals, false)
38	c.Assert(pageList.ETag(), chk.Not(chk.Equals), ETagNone)
39	c.Assert(pageList.BlobContentLength(), chk.Equals, int64(512*10))
40	c.Assert(pageList.RequestID(), chk.Not(chk.Equals), "")
41	c.Assert(pageList.Version(), chk.Not(chk.Equals), "")
42	c.Assert(pageList.Date().IsZero(), chk.Equals, false)
43	c.Assert(pageList.PageRange, chk.HasLen, 1)
44	c.Assert(pageList.PageRange[0], chk.DeepEquals, pageRange)
45}
46
47func (s *aztestsSuite) TestUploadPagesFromURL(c *chk.C) {
48	bsu := getBSU()
49	credential, err := getGenericCredential("")
50	if err != nil {
51		c.Fatal("Invalid credential")
52	}
53	container, _ := createNewContainer(c, bsu)
54	defer delContainer(c, container)
55
56	testSize := 4 * 1024 * 1024 // 4MB
57	r, sourceData := getRandomDataAndReader(testSize)
58	ctx := context.Background() // Use default Background context
59	srcBlob, _ := createNewPageBlobWithSize(c, container, int64(testSize))
60	destBlob, _ := createNewPageBlobWithSize(c, container, int64(testSize))
61
62	// Prepare source blob for copy.
63	uploadSrcResp1, err := srcBlob.UploadPages(ctx, 0, r, PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
64	c.Assert(err, chk.IsNil)
65	c.Assert(uploadSrcResp1.Response().StatusCode, chk.Equals, 201)
66
67	// Get source blob URL with SAS for UploadPagesFromURL.
68	srcBlobParts := NewBlobURLParts(srcBlob.URL())
69
70	srcBlobParts.SAS, err = BlobSASSignatureValues{
71		Protocol:      SASProtocolHTTPS,                     // Users MUST use HTTPS (not HTTP)
72		ExpiryTime:    time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
73		ContainerName: srcBlobParts.ContainerName,
74		BlobName:      srcBlobParts.BlobName,
75		Permissions:   BlobSASPermissions{Read: true}.String(),
76	}.NewSASQueryParameters(credential)
77	if err != nil {
78		c.Fatal(err)
79	}
80
81	srcBlobURLWithSAS := srcBlobParts.URL()
82
83	// Upload page from URL.
84	pResp1, err := destBlob.UploadPagesFromURL(ctx, srcBlobURLWithSAS, 0, 0, int64(testSize), nil, PageBlobAccessConditions{}, ModifiedAccessConditions{}, ClientProvidedKeyOptions{})
85	c.Assert(err, chk.IsNil)
86	c.Assert(pResp1.ETag(), chk.NotNil)
87	c.Assert(pResp1.LastModified(), chk.NotNil)
88	c.Assert(pResp1.Response().StatusCode, chk.Equals, 201)
89	c.Assert(pResp1.ContentMD5(), chk.Not(chk.Equals), "")
90	c.Assert(pResp1.RequestID(), chk.Not(chk.Equals), "")
91	c.Assert(pResp1.Version(), chk.Not(chk.Equals), "")
92	c.Assert(pResp1.Date().IsZero(), chk.Equals, false)
93
94	// Check data integrity through downloading.
95	downloadResp, err := destBlob.BlobURL.Download(ctx, 0, CountToEnd, BlobAccessConditions{}, false, ClientProvidedKeyOptions{})
96	c.Assert(err, chk.IsNil)
97	destData, err := ioutil.ReadAll(downloadResp.Body(RetryReaderOptions{}))
98	c.Assert(err, chk.IsNil)
99	c.Assert(destData, chk.DeepEquals, sourceData)
100}
101
102func (s *aztestsSuite) TestUploadPagesFromURLWithMD5(c *chk.C) {
103	bsu := getBSU()
104	credential, err := getGenericCredential("")
105	if err != nil {
106		c.Fatal("Invalid credential")
107	}
108	container, _ := createNewContainer(c, bsu)
109	defer delContainer(c, container)
110
111	testSize := 4 * 1024 * 1024 // 4MB
112	r, sourceData := getRandomDataAndReader(testSize)
113	md5Value := md5.Sum(sourceData)
114	ctx := context.Background() // Use default Background context
115	srcBlob, _ := createNewPageBlobWithSize(c, container, int64(testSize))
116	destBlob, _ := createNewPageBlobWithSize(c, container, int64(testSize))
117
118	// Prepare source blob for copy.
119	uploadSrcResp1, err := srcBlob.UploadPages(ctx, 0, r, PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
120	c.Assert(err, chk.IsNil)
121	c.Assert(uploadSrcResp1.Response().StatusCode, chk.Equals, 201)
122
123	// Get source blob URL with SAS for UploadPagesFromURL.
124	srcBlobParts := NewBlobURLParts(srcBlob.URL())
125
126	srcBlobParts.SAS, err = BlobSASSignatureValues{
127		Protocol:      SASProtocolHTTPS,                     // Users MUST use HTTPS (not HTTP)
128		ExpiryTime:    time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
129		ContainerName: srcBlobParts.ContainerName,
130		BlobName:      srcBlobParts.BlobName,
131		Permissions:   BlobSASPermissions{Read: true}.String(),
132	}.NewSASQueryParameters(credential)
133	if err != nil {
134		c.Fatal(err)
135	}
136
137	srcBlobURLWithSAS := srcBlobParts.URL()
138
139	// Upload page from URL with MD5.
140	pResp1, err := destBlob.UploadPagesFromURL(ctx, srcBlobURLWithSAS, 0, 0, int64(testSize), md5Value[:], PageBlobAccessConditions{}, ModifiedAccessConditions{}, ClientProvidedKeyOptions{})
141	c.Assert(err, chk.IsNil)
142	c.Assert(pResp1.ETag(), chk.NotNil)
143	c.Assert(pResp1.LastModified(), chk.NotNil)
144	c.Assert(pResp1.Response().StatusCode, chk.Equals, 201)
145	c.Assert(pResp1.RequestID(), chk.Not(chk.Equals), "")
146	c.Assert(pResp1.Version(), chk.Not(chk.Equals), "")
147	c.Assert(pResp1.Date().IsZero(), chk.Equals, false)
148	c.Assert(pResp1.ContentMD5(), chk.DeepEquals, md5Value[:])
149	c.Assert(pResp1.BlobSequenceNumber(), chk.Equals, int64(0))
150
151	// Check data integrity through downloading.
152	downloadResp, err := destBlob.BlobURL.Download(ctx, 0, CountToEnd, BlobAccessConditions{}, false, ClientProvidedKeyOptions{})
153	c.Assert(err, chk.IsNil)
154	destData, err := ioutil.ReadAll(downloadResp.Body(RetryReaderOptions{}))
155	c.Assert(err, chk.IsNil)
156	c.Assert(destData, chk.DeepEquals, sourceData)
157
158	// Upload page from URL with bad MD5
159	_, badMD5 := getRandomDataAndReader(16)
160	_, err = destBlob.UploadPagesFromURL(ctx, srcBlobURLWithSAS, 0, 0, int64(testSize), badMD5[:], PageBlobAccessConditions{}, ModifiedAccessConditions{}, ClientProvidedKeyOptions{})
161	validateStorageError(c, err, ServiceCodeMd5Mismatch)
162}
163
164func (s *aztestsSuite) TestClearDiffPages(c *chk.C) {
165	bsu := getBSU()
166	container, _ := createNewContainer(c, bsu)
167	defer delContainer(c, container)
168
169	blob, _ := createNewPageBlob(c, container)
170	_, err := blob.UploadPages(context.Background(), 0, getReaderToRandomBytes(2048), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
171	c.Assert(err, chk.IsNil)
172
173	snapshotResp, err := blob.CreateSnapshot(context.Background(), nil, BlobAccessConditions{}, ClientProvidedKeyOptions{})
174	c.Assert(err, chk.IsNil)
175
176	_, err = blob.UploadPages(context.Background(), 2048, getReaderToRandomBytes(2048), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
177	c.Assert(err, chk.IsNil)
178
179	pageList, err := blob.GetPageRangesDiff(context.Background(), 0, 4096, snapshotResp.Snapshot(), BlobAccessConditions{})
180	c.Assert(err, chk.IsNil)
181	c.Assert(pageList.PageRange, chk.HasLen, 1)
182	c.Assert(pageList.PageRange[0].Start, chk.Equals, int64(2048))
183	c.Assert(pageList.PageRange[0].End, chk.Equals, int64(4095))
184
185	clearResp, err := blob.ClearPages(context.Background(), 2048, 2048, PageBlobAccessConditions{}, ClientProvidedKeyOptions{})
186	c.Assert(err, chk.IsNil)
187	c.Assert(clearResp.Response().StatusCode, chk.Equals, 201)
188
189	pageList, err = blob.GetPageRangesDiff(context.Background(), 0, 4095, snapshotResp.Snapshot(), BlobAccessConditions{})
190	c.Assert(err, chk.IsNil)
191	c.Assert(pageList.PageRange, chk.HasLen, 0)
192}
193
194func (s *aztestsSuite) TestIncrementalCopy(c *chk.C) {
195	bsu := getBSU()
196	container, _ := createNewContainer(c, bsu)
197	defer delContainer(c, container)
198	_, err := container.SetAccessPolicy(context.Background(), PublicAccessBlob, nil, ContainerAccessConditions{})
199	c.Assert(err, chk.IsNil)
200
201	srcBlob, _ := createNewPageBlob(c, container)
202	_, err = srcBlob.UploadPages(context.Background(), 0, getReaderToRandomBytes(1024), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
203	c.Assert(err, chk.IsNil)
204	snapshotResp, err := srcBlob.CreateSnapshot(context.Background(), nil, BlobAccessConditions{}, ClientProvidedKeyOptions{})
205	c.Assert(err, chk.IsNil)
206
207	dstBlob := container.NewPageBlobURL(generateBlobName())
208
209	resp, err := dstBlob.StartCopyIncremental(context.Background(), srcBlob.URL(), snapshotResp.Snapshot(), BlobAccessConditions{})
210	c.Assert(err, chk.IsNil)
211	c.Assert(resp.Response().StatusCode, chk.Equals, 202)
212	c.Assert(resp.LastModified().IsZero(), chk.Equals, false)
213	c.Assert(resp.ETag(), chk.Not(chk.Equals), ETagNone)
214	c.Assert(resp.RequestID(), chk.Not(chk.Equals), "")
215	c.Assert(resp.Version(), chk.Not(chk.Equals), "")
216	c.Assert(resp.Date().IsZero(), chk.Equals, false)
217	c.Assert(resp.CopyID(), chk.Not(chk.Equals), "")
218	c.Assert(resp.CopyStatus(), chk.Equals, CopyStatusPending)
219
220	waitForIncrementalCopy(c, dstBlob, resp)
221}
222
223func (s *aztestsSuite) TestResizePageBlob(c *chk.C) {
224	bsu := getBSU()
225	container, _ := createNewContainer(c, bsu)
226	defer delContainer(c, container)
227
228	blob, _ := createNewPageBlob(c, container)
229	resp, err := blob.Resize(context.Background(), 2048, BlobAccessConditions{}, ClientProvidedKeyOptions{})
230	c.Assert(err, chk.IsNil)
231	c.Assert(resp.Response().StatusCode, chk.Equals, 200)
232
233	resp, err = blob.Resize(context.Background(), 8192, BlobAccessConditions{}, ClientProvidedKeyOptions{})
234	c.Assert(err, chk.IsNil)
235	c.Assert(resp.Response().StatusCode, chk.Equals, 200)
236
237	resp2, err := blob.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
238	c.Assert(err, chk.IsNil)
239	c.Assert(resp2.ContentLength(), chk.Equals, int64(8192))
240}
241
242func (s *aztestsSuite) TestPageSequenceNumbers(c *chk.C) {
243	bsu := getBSU()
244	container, _ := createNewContainer(c, bsu)
245	blob, _ := createNewPageBlob(c, container)
246
247	defer delContainer(c, container)
248
249	resp, err := blob.UpdateSequenceNumber(context.Background(), SequenceNumberActionIncrement, 0, BlobAccessConditions{})
250	c.Assert(err, chk.IsNil)
251	c.Assert(resp.Response().StatusCode, chk.Equals, 200)
252
253	resp, err = blob.UpdateSequenceNumber(context.Background(), SequenceNumberActionMax, 7, BlobAccessConditions{})
254	c.Assert(err, chk.IsNil)
255	c.Assert(resp.Response().StatusCode, chk.Equals, 200)
256
257	resp, err = blob.UpdateSequenceNumber(context.Background(), SequenceNumberActionUpdate, 11, BlobAccessConditions{})
258	c.Assert(err, chk.IsNil)
259	c.Assert(resp.Response().StatusCode, chk.Equals, 200)
260}
261
262func (s *aztestsSuite) TestPutPagesWithMD5(c *chk.C) {
263	bsu := getBSU()
264	container, _ := createNewContainer(c, bsu)
265	defer delContainer(c, container)
266
267	blob, _ := createNewPageBlob(c, container)
268
269	// put page with valid MD5
270	readerToBody, body := getRandomDataAndReader(1024)
271	md5Value := md5.Sum(body)
272	putResp, err := blob.UploadPages(context.Background(), 0, readerToBody, PageBlobAccessConditions{}, md5Value[:], ClientProvidedKeyOptions{})
273	c.Assert(err, chk.IsNil)
274	c.Assert(putResp.Response().StatusCode, chk.Equals, 201)
275	c.Assert(putResp.LastModified().IsZero(), chk.Equals, false)
276	c.Assert(putResp.ETag(), chk.Not(chk.Equals), ETagNone)
277	c.Assert(putResp.ContentMD5(), chk.DeepEquals, md5Value[:])
278	c.Assert(putResp.BlobSequenceNumber(), chk.Equals, int64(0))
279	c.Assert(putResp.RequestID(), chk.Not(chk.Equals), "")
280	c.Assert(putResp.Version(), chk.Not(chk.Equals), "")
281	c.Assert(putResp.Date().IsZero(), chk.Equals, false)
282
283	// put page with bad MD5
284	readerToBody, body = getRandomDataAndReader(1024)
285	_, badMD5 := getRandomDataAndReader(16)
286	putResp, err = blob.UploadPages(context.Background(), 0, readerToBody, PageBlobAccessConditions{}, badMD5[:], ClientProvidedKeyOptions{})
287	validateStorageError(c, err, ServiceCodeMd5Mismatch)
288}
289
290func (s *aztestsSuite) TestBlobCreatePageSizeInvalid(c *chk.C) {
291	bsu := getBSU()
292	containerURL, _ := createNewContainer(c, bsu)
293	defer deleteContainer(c, containerURL)
294	blobURL, _ := getPageBlobURL(c, containerURL)
295
296	_, err := blobURL.Create(ctx, 1, 0, BlobHTTPHeaders{}, nil, BlobAccessConditions{}, DefaultPremiumBlobAccessTier, nil, ClientProvidedKeyOptions{})
297	validateStorageError(c, err, ServiceCodeInvalidHeaderValue)
298}
299
300func (s *aztestsSuite) TestBlobCreatePageSequenceInvalid(c *chk.C) {
301	bsu := getBSU()
302	containerURL, _ := createNewContainer(c, bsu)
303	defer deleteContainer(c, containerURL)
304	blobURL, _ := getPageBlobURL(c, containerURL)
305
306	_, err := blobURL.Create(ctx, PageBlobPageBytes, -1, BlobHTTPHeaders{}, nil, BlobAccessConditions{}, DefaultPremiumBlobAccessTier, nil, ClientProvidedKeyOptions{})
307	c.Assert(err, chk.Not(chk.IsNil))
308}
309
310func (s *aztestsSuite) TestBlobCreatePageMetadataNonEmpty(c *chk.C) {
311	bsu := getBSU()
312	containerURL, _ := createNewContainer(c, bsu)
313	defer deleteContainer(c, containerURL)
314	blobURL, _ := getPageBlobURL(c, containerURL)
315
316	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{}, DefaultPremiumBlobAccessTier, nil, ClientProvidedKeyOptions{})
317
318	resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
319	c.Assert(err, chk.IsNil)
320	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
321}
322
323func (s *aztestsSuite) TestBlobCreatePageMetadataEmpty(c *chk.C) {
324	bsu := getBSU()
325	containerURL, _ := createNewContainer(c, bsu)
326	defer deleteContainer(c, containerURL)
327	blobURL, _ := getPageBlobURL(c, containerURL)
328
329	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, Metadata{}, BlobAccessConditions{}, DefaultPremiumBlobAccessTier, nil, ClientProvidedKeyOptions{})
330
331	resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
332	c.Assert(err, chk.IsNil)
333	c.Assert(resp.NewMetadata(), chk.HasLen, 0)
334}
335
336func (s *aztestsSuite) TestBlobCreatePageMetadataInvalid(c *chk.C) {
337	bsu := getBSU()
338	containerURL, _ := createNewContainer(c, bsu)
339	defer deleteContainer(c, containerURL)
340	blobURL, _ := getPageBlobURL(c, containerURL)
341
342	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, Metadata{"In valid1": "bar"}, BlobAccessConditions{}, PremiumPageBlobAccessTierNone, nil, ClientProvidedKeyOptions{})
343	c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true)
344
345}
346
347func (s *aztestsSuite) TestBlobCreatePageHTTPHeaders(c *chk.C) {
348	bsu := getBSU()
349	containerURL, _ := createNewContainer(c, bsu)
350	defer deleteContainer(c, containerURL)
351	blobURL, _ := getPageBlobURL(c, containerURL)
352
353	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, basicHeaders, nil, BlobAccessConditions{}, PremiumPageBlobAccessTierNone, nil, ClientProvidedKeyOptions{})
354	c.Assert(err, chk.IsNil)
355
356	resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
357	c.Assert(err, chk.IsNil)
358	h := resp.NewHTTPHeaders()
359	c.Assert(h, chk.DeepEquals, basicHeaders)
360}
361
362func validatePageBlobPut(c *chk.C, blobURL PageBlobURL) {
363	resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
364	c.Assert(err, chk.IsNil)
365	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
366}
367
368func (s *aztestsSuite) TestBlobCreatePageIfModifiedSinceTrue(c *chk.C) {
369	bsu := getBSU()
370	containerURL, _ := createNewContainer(c, bsu)
371	defer deleteContainer(c, containerURL)
372	blobURL, _ := createNewPageBlob(c, containerURL) // Originally created without metadata
373
374	currentTime := getRelativeTimeGMT(-10)
375
376	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, DefaultPremiumBlobAccessTier, nil, ClientProvidedKeyOptions{})
377	c.Assert(err, chk.IsNil)
378
379	validatePageBlobPut(c, blobURL)
380}
381
382func (s *aztestsSuite) TestBlobCreatePageIfModifiedSinceFalse(c *chk.C) {
383	bsu := getBSU()
384	containerURL, _ := createNewContainer(c, bsu)
385	defer deleteContainer(c, containerURL)
386	blobURL, _ := createNewPageBlob(c, containerURL) // Originally created without metadata
387
388	currentTime := getRelativeTimeGMT(10)
389
390	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, DefaultPremiumBlobAccessTier, nil, ClientProvidedKeyOptions{})
391	validateStorageError(c, err, ServiceCodeConditionNotMet)
392}
393
394func (s *aztestsSuite) TestBlobCreatePageIfUnmodifiedSinceTrue(c *chk.C) {
395	bsu := getBSU()
396	containerURL, _ := createNewContainer(c, bsu)
397	defer deleteContainer(c, containerURL)
398	blobURL, _ := createNewPageBlob(c, containerURL) // Originally created without metadata
399
400	currentTime := getRelativeTimeGMT(10)
401
402	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, DefaultPremiumBlobAccessTier, nil, ClientProvidedKeyOptions{})
403	c.Assert(err, chk.IsNil)
404
405	validatePageBlobPut(c, blobURL)
406}
407
408func (s *aztestsSuite) TestBlobCreatePageIfUnmodifiedSinceFalse(c *chk.C) {
409	bsu := getBSU()
410	containerURL, _ := createNewContainer(c, bsu)
411	defer deleteContainer(c, containerURL)
412	blobURL, _ := createNewPageBlob(c, containerURL) // Originally created without metadata
413
414	currentTime := getRelativeTimeGMT(-10)
415
416	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, DefaultPremiumBlobAccessTier, nil, ClientProvidedKeyOptions{})
417	validateStorageError(c, err, ServiceCodeConditionNotMet)
418}
419
420func (s *aztestsSuite) TestBlobCreatePageIfMatchTrue(c *chk.C) {
421	bsu := getBSU()
422	containerURL, _ := createNewContainer(c, bsu)
423	defer deleteContainer(c, containerURL)
424	blobURL, _ := createNewPageBlob(c, containerURL) // Originally created without metadata
425
426	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
427
428	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}}, PremiumPageBlobAccessTierNone, nil, ClientProvidedKeyOptions{})
429	c.Assert(err, chk.IsNil)
430
431	validatePageBlobPut(c, blobURL)
432}
433
434func (s *aztestsSuite) TestBlobCreatePageIfMatchFalse(c *chk.C) {
435	bsu := getBSU()
436	containerURL, _ := createNewContainer(c, bsu)
437	defer deleteContainer(c, containerURL)
438	blobURL, _ := createNewPageBlob(c, containerURL) // Originally created without metadata
439
440	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}}, PremiumPageBlobAccessTierNone, nil, ClientProvidedKeyOptions{})
441	validateStorageError(c, err, ServiceCodeConditionNotMet)
442}
443
444func (s *aztestsSuite) TestBlobCreatePageIfNoneMatchTrue(c *chk.C) {
445	bsu := getBSU()
446	containerURL, _ := createNewContainer(c, bsu)
447	defer deleteContainer(c, containerURL)
448	blobURL, _ := createNewPageBlob(c, containerURL) // Originally created without metadata
449
450	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}}, PremiumPageBlobAccessTierNone, nil, ClientProvidedKeyOptions{})
451	c.Assert(err, chk.IsNil)
452
453	validatePageBlobPut(c, blobURL)
454}
455
456func (s *aztestsSuite) TestBlobCreatePageIfNoneMatchFalse(c *chk.C) {
457	bsu := getBSU()
458	containerURL, _ := createNewContainer(c, bsu)
459	defer deleteContainer(c, containerURL)
460	blobURL, _ := createNewPageBlob(c, containerURL) // Originally created without metadata
461
462	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
463
464	_, err := blobURL.Create(ctx, PageBlobPageBytes, 0, BlobHTTPHeaders{}, basicMetadata, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}}, DefaultPremiumBlobAccessTier, nil, ClientProvidedKeyOptions{})
465
466	validateStorageError(c, err, ServiceCodeConditionNotMet)
467}
468
469func (s *aztestsSuite) TestBlobPutPagesInvalidRange(c *chk.C) {
470	bsu := getBSU()
471	containerURL, _ := createNewContainer(c, bsu)
472	defer deleteContainer(c, containerURL)
473	blobURL, _ := createNewPageBlob(c, containerURL)
474
475	_, err := blobURL.UploadPages(ctx, 0, strings.NewReader(blockBlobDefaultData), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
476	c.Assert(err, chk.Not(chk.IsNil))
477}
478
479func (s *aztestsSuite) TestBlobPutPagesNilBody(c *chk.C) {
480	bsu := getBSU()
481	containerURL, _ := createNewContainer(c, bsu)
482	defer deleteContainer(c, containerURL)
483	blobURL, _ := createNewPageBlob(c, containerURL)
484
485	_, err := blobURL.UploadPages(ctx, 0, nil, PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
486	c.Assert(err, chk.Not(chk.IsNil))
487}
488
489func (s *aztestsSuite) TestBlobPutPagesEmptyBody(c *chk.C) {
490	bsu := getBSU()
491	containerURL, _ := createNewContainer(c, bsu)
492	defer deleteContainer(c, containerURL)
493	blobURL, _ := createNewPageBlob(c, containerURL)
494
495	_, err := blobURL.UploadPages(ctx, 0, bytes.NewReader([]byte{}), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
496	c.Assert(err, chk.Not(chk.IsNil))
497}
498
499func (s *aztestsSuite) TestBlobPutPagesNonExistantBlob(c *chk.C) {
500	bsu := getBSU()
501	containerURL, _ := createNewContainer(c, bsu)
502	defer deleteContainer(c, containerURL)
503	blobURL, _ := getPageBlobURL(c, containerURL)
504
505	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
506	validateStorageError(c, err, ServiceCodeBlobNotFound)
507}
508
509func validateUploadPages(c *chk.C, blobURL PageBlobURL) {
510	// This will only validate a single put page at 0-PageBlobPageBytes-1
511	resp, err := blobURL.GetPageRanges(ctx, 0, 0, BlobAccessConditions{})
512	c.Assert(err, chk.IsNil)
513	c.Assert(resp.PageRange[0], chk.Equals, PageRange{Start: 0, End: PageBlobPageBytes - 1})
514}
515
516func (s *aztestsSuite) TestBlobPutPagesIfModifiedSinceTrue(c *chk.C) {
517	bsu := getBSU()
518	containerURL, _ := createNewContainer(c, bsu)
519	defer deleteContainer(c, containerURL)
520	blobURL, _ := createNewPageBlob(c, containerURL)
521
522	currentTime := getRelativeTimeGMT(-10)
523
524	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, nil, ClientProvidedKeyOptions{})
525	c.Assert(err, chk.IsNil)
526
527	validateUploadPages(c, blobURL)
528}
529
530func (s *aztestsSuite) TestBlobPutPagesIfModifiedSinceFalse(c *chk.C) {
531	bsu := getBSU()
532	containerURL, _ := createNewContainer(c, bsu)
533	defer deleteContainer(c, containerURL)
534	blobURL, _ := createNewPageBlob(c, containerURL)
535
536	currentTime := getRelativeTimeGMT(10)
537
538	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, nil, ClientProvidedKeyOptions{})
539	validateStorageError(c, err, ServiceCodeConditionNotMet)
540}
541
542func (s *aztestsSuite) TestBlobPutPagesIfUnmodifiedSinceTrue(c *chk.C) {
543	bsu := getBSU()
544	containerURL, _ := createNewContainer(c, bsu)
545	defer deleteContainer(c, containerURL)
546	blobURL, _ := createNewPageBlob(c, containerURL)
547
548	currentTime := getRelativeTimeGMT(10)
549
550	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, nil, ClientProvidedKeyOptions{})
551	c.Assert(err, chk.IsNil)
552
553	validateUploadPages(c, blobURL)
554}
555
556func (s *aztestsSuite) TestBlobPutPagesIfUnmodifiedSinceFalse(c *chk.C) {
557	bsu := getBSU()
558	containerURL, _ := createNewContainer(c, bsu)
559	defer deleteContainer(c, containerURL)
560	blobURL, _ := createNewPageBlob(c, containerURL)
561
562	currentTime := getRelativeTimeGMT(-10)
563
564	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, nil, ClientProvidedKeyOptions{})
565	validateStorageError(c, err, ServiceCodeConditionNotMet)
566}
567
568func (s *aztestsSuite) TestBlobPutPagesIfMatchTrue(c *chk.C) {
569	bsu := getBSU()
570	containerURL, _ := createNewContainer(c, bsu)
571	defer deleteContainer(c, containerURL)
572	blobURL, _ := createNewPageBlob(c, containerURL)
573
574	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
575
576	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}}, nil, ClientProvidedKeyOptions{})
577	c.Assert(err, chk.IsNil)
578
579	validateUploadPages(c, blobURL)
580}
581
582func (s *aztestsSuite) TestBlobPutPagesIfMatchFalse(c *chk.C) {
583	bsu := getBSU()
584	containerURL, _ := createNewContainer(c, bsu)
585	defer deleteContainer(c, containerURL)
586	blobURL, _ := createNewPageBlob(c, containerURL)
587
588	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}}, nil, ClientProvidedKeyOptions{})
589	validateStorageError(c, err, ServiceCodeConditionNotMet)
590}
591
592func (s *aztestsSuite) TestBlobPutPagesIfNoneMatchTrue(c *chk.C) {
593	bsu := getBSU()
594	containerURL, _ := createNewContainer(c, bsu)
595	defer deleteContainer(c, containerURL)
596	blobURL, _ := createNewPageBlob(c, containerURL)
597
598	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}}, nil, ClientProvidedKeyOptions{})
599	c.Assert(err, chk.IsNil)
600
601	validateUploadPages(c, blobURL)
602}
603
604func (s *aztestsSuite) TestBlobPutPagesIfNoneMatchFalse(c *chk.C) {
605	bsu := getBSU()
606	containerURL, _ := createNewContainer(c, bsu)
607	defer deleteContainer(c, containerURL)
608	blobURL, _ := createNewPageBlob(c, containerURL)
609
610	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
611
612	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}}, nil, ClientProvidedKeyOptions{})
613	validateStorageError(c, err, ServiceCodeConditionNotMet)
614}
615
616func (s *aztestsSuite) TestBlobPutPagesIfSequenceNumberLessThanTrue(c *chk.C) {
617	bsu := getBSU()
618	containerURL, _ := createNewContainer(c, bsu)
619	defer deleteContainer(c, containerURL)
620	blobURL, _ := createNewPageBlob(c, containerURL)
621
622	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThan: 10}}, nil, ClientProvidedKeyOptions{})
623	c.Assert(err, chk.IsNil)
624
625	validateUploadPages(c, blobURL)
626}
627
628func (s *aztestsSuite) TestBlobPutPagesIfSequenceNumberLessThanFalse(c *chk.C) {
629	bsu := getBSU()
630	containerURL, _ := createNewContainer(c, bsu)
631	defer deleteContainer(c, containerURL)
632	blobURL, _ := createNewPageBlob(c, containerURL)
633
634	blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionUpdate, 10, BlobAccessConditions{})
635	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThan: 1}}, nil, ClientProvidedKeyOptions{})
636	validateStorageError(c, err, ServiceCodeSequenceNumberConditionNotMet)
637}
638
639func (s *aztestsSuite) TestBlobPutPagesIfSequenceNumberLessThanNegOne(c *chk.C) {
640	bsu := getBSU()
641	containerURL, _ := createNewContainer(c, bsu)
642	defer deleteContainer(c, containerURL)
643	blobURL, _ := createNewPageBlob(c, containerURL)
644
645	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThan: -1}}, nil, ClientProvidedKeyOptions{}) // This will cause the library to set the value of the header to 0
646	validateStorageError(c, err, ServiceCodeSequenceNumberConditionNotMet)
647}
648
649func (s *aztestsSuite) TestBlobPutPagesIfSequenceNumberLTETrue(c *chk.C) {
650	bsu := getBSU()
651	containerURL, _ := createNewContainer(c, bsu)
652	defer deleteContainer(c, containerURL)
653	blobURL, _ := createNewPageBlob(c, containerURL)
654
655	blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionUpdate, 1, BlobAccessConditions{})
656	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThanOrEqual: 1}}, nil, ClientProvidedKeyOptions{})
657	c.Assert(err, chk.IsNil)
658
659	validateUploadPages(c, blobURL)
660}
661
662func (s *aztestsSuite) TestBlobPutPagesIfSequenceNumberLTEqualFalse(c *chk.C) {
663	bsu := getBSU()
664	containerURL, _ := createNewContainer(c, bsu)
665	defer deleteContainer(c, containerURL)
666	blobURL, _ := createNewPageBlob(c, containerURL)
667
668	blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionUpdate, 10, BlobAccessConditions{})
669	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThanOrEqual: 1}}, nil, ClientProvidedKeyOptions{})
670	validateStorageError(c, err, ServiceCodeSequenceNumberConditionNotMet)
671}
672
673func (s *aztestsSuite) TestBlobPutPagesIfSequenceNumberLTENegOne(c *chk.C) {
674	bsu := getBSU()
675	containerURL, _ := createNewContainer(c, bsu)
676	defer deleteContainer(c, containerURL)
677	blobURL, _ := createNewPageBlob(c, containerURL)
678
679	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThanOrEqual: -1}}, nil, ClientProvidedKeyOptions{}) // This will cause the library to set the value of the header to 0
680	c.Assert(err, chk.IsNil)
681
682	validateUploadPages(c, blobURL)
683}
684
685func (s *aztestsSuite) TestBlobPutPagesIfSequenceNumberEqualTrue(c *chk.C) {
686	bsu := getBSU()
687	containerURL, _ := createNewContainer(c, bsu)
688	defer deleteContainer(c, containerURL)
689	blobURL, _ := createNewPageBlob(c, containerURL)
690
691	blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionUpdate, 1, BlobAccessConditions{})
692	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberEqual: 1}}, nil, ClientProvidedKeyOptions{})
693	c.Assert(err, chk.IsNil)
694
695	validateUploadPages(c, blobURL)
696}
697
698func (s *aztestsSuite) TestBlobPutPagesIfSequenceNumberEqualFalse(c *chk.C) {
699	bsu := getBSU()
700	containerURL, _ := createNewContainer(c, bsu)
701	defer deleteContainer(c, containerURL)
702	blobURL, _ := createNewPageBlob(c, containerURL)
703
704	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberEqual: 1}}, nil, ClientProvidedKeyOptions{})
705	validateStorageError(c, err, ServiceCodeSequenceNumberConditionNotMet)
706}
707
708func (s *aztestsSuite) TestBlobPutPagesIfSequenceNumberEqualNegOne(c *chk.C) {
709	bsu := getBSU()
710	containerURL, _ := createNewContainer(c, bsu)
711	defer deleteContainer(c, containerURL)
712	blobURL, _ := createNewPageBlob(c, containerURL)
713
714	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberEqual: -1}}, nil, ClientProvidedKeyOptions{}) // This will cause the library to set the value of the header to 0
715	c.Assert(err, chk.IsNil)
716
717	validateUploadPages(c, blobURL)
718}
719
720func setupClearPagesTest(c *chk.C) (ContainerURL, PageBlobURL) {
721	bsu := getBSU()
722	containerURL, _ := createNewContainer(c, bsu)
723	blobURL, _ := createNewPageBlob(c, containerURL)
724
725	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
726	c.Assert(err, chk.IsNil)
727
728	return containerURL, blobURL
729}
730
731func validateClearPagesTest(c *chk.C, blobURL PageBlobURL) {
732	resp, err := blobURL.GetPageRanges(ctx, 0, 0, BlobAccessConditions{})
733	c.Assert(err, chk.IsNil)
734	c.Assert(resp.PageRange, chk.HasLen, 0)
735}
736
737func (s *aztestsSuite) TestBlobClearPagesInvalidRange(c *chk.C) {
738	containerURL, blobURL := setupClearPagesTest(c)
739	defer deleteContainer(c, containerURL)
740
741	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes+1, PageBlobAccessConditions{}, ClientProvidedKeyOptions{})
742	c.Assert(err, chk.Not(chk.IsNil))
743}
744
745func (s *aztestsSuite) TestBlobClearPagesIfModifiedSinceTrue(c *chk.C) {
746	containerURL, blobURL := setupClearPagesTest(c)
747	defer deleteContainer(c, containerURL)
748
749	currentTime := getRelativeTimeGMT(-10)
750
751	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, ClientProvidedKeyOptions{})
752	c.Assert(err, chk.IsNil)
753
754	validateClearPagesTest(c, blobURL)
755}
756
757func (s *aztestsSuite) TestBlobClearPagesIfModifiedSinceFalse(c *chk.C) {
758	containerURL, blobURL := setupClearPagesTest(c)
759	defer deleteContainer(c, containerURL)
760
761	currentTime := getRelativeTimeGMT(10)
762
763	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, ClientProvidedKeyOptions{})
764	validateStorageError(c, err, ServiceCodeConditionNotMet)
765}
766
767func (s *aztestsSuite) TestBlobClearPagesIfUnmodifiedSinceTrue(c *chk.C) {
768	containerURL, blobURL := setupClearPagesTest(c)
769	defer deleteContainer(c, containerURL)
770
771	currentTime := getRelativeTimeGMT(10)
772
773	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, ClientProvidedKeyOptions{})
774	c.Assert(err, chk.IsNil)
775
776	validateClearPagesTest(c, blobURL)
777}
778
779func (s *aztestsSuite) TestBlobClearPagesIfUnmodifiedSinceFalse(c *chk.C) {
780	containerURL, blobURL := setupClearPagesTest(c)
781	defer deleteContainer(c, containerURL)
782
783	currentTime := getRelativeTimeGMT(-10)
784
785	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, ClientProvidedKeyOptions{})
786	validateStorageError(c, err, ServiceCodeConditionNotMet)
787}
788
789func (s *aztestsSuite) TestBlobClearPagesIfMatchTrue(c *chk.C) {
790	containerURL, blobURL := setupClearPagesTest(c)
791	defer deleteContainer(c, containerURL)
792
793	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
794
795	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}}, ClientProvidedKeyOptions{})
796	c.Assert(err, chk.IsNil)
797
798	validateClearPagesTest(c, blobURL)
799}
800
801func (s *aztestsSuite) TestBlobClearPagesIfMatchFalse(c *chk.C) {
802	containerURL, blobURL := setupClearPagesTest(c)
803	defer deleteContainer(c, containerURL)
804
805	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}}, ClientProvidedKeyOptions{})
806	validateStorageError(c, err, ServiceCodeConditionNotMet)
807}
808
809func (s *aztestsSuite) TestBlobClearPagesIfNoneMatchTrue(c *chk.C) {
810	containerURL, blobURL := setupClearPagesTest(c)
811	defer deleteContainer(c, containerURL)
812
813	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}}, ClientProvidedKeyOptions{})
814	c.Assert(err, chk.IsNil)
815
816	validateClearPagesTest(c, blobURL)
817}
818
819func (s *aztestsSuite) TestBlobClearPagesIfNoneMatchFalse(c *chk.C) {
820	containerURL, blobURL := setupClearPagesTest(c)
821	defer deleteContainer(c, containerURL)
822
823	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
824
825	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}}, ClientProvidedKeyOptions{})
826	validateStorageError(c, err, ServiceCodeConditionNotMet)
827}
828
829func (s *aztestsSuite) TestBlobClearPagesIfSequenceNumberLessThanTrue(c *chk.C) {
830	containerURL, blobURL := setupClearPagesTest(c)
831	defer deleteContainer(c, containerURL)
832
833	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThan: 10}}, ClientProvidedKeyOptions{})
834	c.Assert(err, chk.IsNil)
835
836	validateClearPagesTest(c, blobURL)
837}
838
839func (s *aztestsSuite) TestBlobClearPagesIfSequenceNumberLessThanFalse(c *chk.C) {
840	containerURL, blobURL := setupClearPagesTest(c)
841	defer deleteContainer(c, containerURL)
842
843	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionUpdate, 10, BlobAccessConditions{})
844	c.Assert(err, chk.IsNil)
845	_, err = blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThan: 1}}, ClientProvidedKeyOptions{})
846	validateStorageError(c, err, ServiceCodeSequenceNumberConditionNotMet)
847}
848
849func (s *aztestsSuite) TestBlobClearPagesIfSequenceNumberLessThanNegOne(c *chk.C) {
850	containerURL, blobURL := setupClearPagesTest(c)
851	defer deleteContainer(c, containerURL)
852
853	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThan: -1}}, ClientProvidedKeyOptions{}) // This will cause the library to set the value of the header to 0
854	validateStorageError(c, err, ServiceCodeSequenceNumberConditionNotMet)
855}
856
857func (s *aztestsSuite) TestBlobClearPagesIfSequenceNumberLTETrue(c *chk.C) {
858	containerURL, blobURL := setupClearPagesTest(c)
859	defer deleteContainer(c, containerURL)
860
861	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThanOrEqual: 10}}, ClientProvidedKeyOptions{})
862	c.Assert(err, chk.IsNil)
863
864	validateClearPagesTest(c, blobURL)
865}
866
867func (s *aztestsSuite) TestBlobClearPagesIfSequenceNumberLTEFalse(c *chk.C) {
868	containerURL, blobURL := setupClearPagesTest(c)
869	defer deleteContainer(c, containerURL)
870
871	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionUpdate, 10, BlobAccessConditions{})
872	c.Assert(err, chk.IsNil)
873	_, err = blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThanOrEqual: 1}}, ClientProvidedKeyOptions{})
874	validateStorageError(c, err, ServiceCodeSequenceNumberConditionNotMet)
875}
876
877func (s *aztestsSuite) TestBlobClearPagesIfSequenceNumberLTENegOne(c *chk.C) {
878	containerURL, blobURL := setupClearPagesTest(c)
879	defer deleteContainer(c, containerURL)
880
881	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberLessThanOrEqual: -1}}, ClientProvidedKeyOptions{}) // This will cause the library to set the value of the header to 0
882	c.Assert(err, chk.IsNil)
883
884	validateClearPagesTest(c, blobURL)
885}
886
887func (s *aztestsSuite) TestBlobClearPagesIfSequenceNumberEqualTrue(c *chk.C) {
888	containerURL, blobURL := setupClearPagesTest(c)
889	defer deleteContainer(c, containerURL)
890
891	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionUpdate, 10, BlobAccessConditions{})
892	c.Assert(err, chk.IsNil)
893	_, err = blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberEqual: 10}}, ClientProvidedKeyOptions{})
894	c.Assert(err, chk.IsNil)
895
896	validateClearPagesTest(c, blobURL)
897}
898
899func (s *aztestsSuite) TestBlobClearPagesIfSequenceNumberEqualFalse(c *chk.C) {
900	containerURL, blobURL := setupClearPagesTest(c)
901	defer deleteContainer(c, containerURL)
902
903	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionUpdate, 10, BlobAccessConditions{})
904	c.Assert(err, chk.IsNil)
905	_, err = blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberEqual: 1}}, ClientProvidedKeyOptions{})
906	validateStorageError(c, err, ServiceCodeSequenceNumberConditionNotMet)
907}
908
909func (s *aztestsSuite) TestBlobClearPagesIfSequenceNumberEqualNegOne(c *chk.C) {
910	containerURL, blobURL := setupClearPagesTest(c)
911	defer deleteContainer(c, containerURL)
912
913	_, err := blobURL.ClearPages(ctx, 0, PageBlobPageBytes, PageBlobAccessConditions{SequenceNumberAccessConditions: SequenceNumberAccessConditions{IfSequenceNumberEqual: -1}}, ClientProvidedKeyOptions{}) // This will cause the library to set the value of the header to 0
914	c.Assert(err, chk.IsNil)
915
916	validateClearPagesTest(c, blobURL)
917}
918
919func setupGetPageRangesTest(c *chk.C) (containerURL ContainerURL, blobURL PageBlobURL) {
920	bsu := getBSU()
921	containerURL, _ = createNewContainer(c, bsu)
922	blobURL, _ = createNewPageBlob(c, containerURL)
923
924	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
925	c.Assert(err, chk.IsNil)
926
927	return
928}
929
930func validateBasicGetPageRanges(c *chk.C, resp *PageList, err error) {
931	c.Assert(err, chk.IsNil)
932	c.Assert(resp.PageRange, chk.HasLen, 1)
933	c.Assert(resp.PageRange[0], chk.Equals, PageRange{Start: 0, End: PageBlobPageBytes - 1})
934}
935
936func (s *aztestsSuite) TestBlobGetPageRangesEmptyBlob(c *chk.C) {
937	bsu := getBSU()
938	containerURL, _ := createNewContainer(c, bsu)
939	defer deleteContainer(c, containerURL)
940	blobURL, _ := createNewPageBlob(c, containerURL)
941
942	resp, err := blobURL.GetPageRanges(ctx, 0, 0, BlobAccessConditions{})
943	c.Assert(err, chk.IsNil)
944	c.Assert(resp.PageRange, chk.HasLen, 0)
945}
946
947func (s *aztestsSuite) TestBlobGetPageRangesEmptyRange(c *chk.C) {
948	containerURL, blobURL := setupGetPageRangesTest(c)
949	defer deleteContainer(c, containerURL)
950
951	resp, err := blobURL.GetPageRanges(ctx, 0, 0, BlobAccessConditions{})
952	validateBasicGetPageRanges(c, resp, err)
953}
954
955func (s *aztestsSuite) TestBlobGetPageRangesInvalidRange(c *chk.C) {
956	containerURL, blobURL := setupGetPageRangesTest(c)
957	defer deleteContainer(c, containerURL)
958
959	_, err := blobURL.GetPageRanges(ctx, -2, 500, BlobAccessConditions{})
960	c.Assert(err, chk.IsNil)
961}
962
963func (s *aztestsSuite) TestBlobGetPageRangesNonContiguousRanges(c *chk.C) {
964	containerURL, blobURL := setupGetPageRangesTest(c)
965	defer deleteContainer(c, containerURL)
966
967	_, err := blobURL.UploadPages(ctx, PageBlobPageBytes*2, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
968	c.Assert(err, chk.IsNil)
969	resp, err := blobURL.GetPageRanges(ctx, 0, 0, BlobAccessConditions{})
970	c.Assert(err, chk.IsNil)
971	c.Assert(resp.PageRange, chk.HasLen, 2)
972	c.Assert(resp.PageRange[0], chk.Equals, PageRange{Start: 0, End: PageBlobPageBytes - 1})
973	c.Assert(resp.PageRange[1], chk.Equals, PageRange{Start: PageBlobPageBytes * 2, End: (PageBlobPageBytes * 3) - 1})
974}
975func (s *aztestsSuite) TestblobGetPageRangesNotPageAligned(c *chk.C) {
976	containerURL, blobURL := setupGetPageRangesTest(c)
977	defer deleteContainer(c, containerURL)
978
979	resp, err := blobURL.GetPageRanges(ctx, 0, 2000, BlobAccessConditions{})
980	c.Assert(err, chk.IsNil)
981	validateBasicGetPageRanges(c, resp, err)
982}
983
984func (s *aztestsSuite) TestBlobGetPageRangesSnapshot(c *chk.C) {
985	containerURL, blobURL := setupGetPageRangesTest(c)
986	defer deleteContainer(c, containerURL)
987
988	resp, _ := blobURL.CreateSnapshot(ctx, nil, BlobAccessConditions{}, ClientProvidedKeyOptions{})
989	snapshotURL := blobURL.WithSnapshot(resp.Snapshot())
990	resp2, err := snapshotURL.GetPageRanges(ctx, 0, 0, BlobAccessConditions{})
991	c.Assert(err, chk.IsNil)
992	validateBasicGetPageRanges(c, resp2, err)
993}
994
995func (s *aztestsSuite) TestBlobGetPageRangesIfModifiedSinceTrue(c *chk.C) {
996	containerURL, blobURL := setupGetPageRangesTest(c)
997	defer deleteContainer(c, containerURL)
998
999	currentTime := getRelativeTimeGMT(-10)
1000
1001	resp, err := blobURL.GetPageRanges(ctx, 0, 0,
1002		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
1003	validateBasicGetPageRanges(c, resp, err)
1004}
1005
1006func (s *aztestsSuite) TestBlobGetPageRangesIfModifiedSinceFalse(c *chk.C) {
1007	containerURL, blobURL := setupGetPageRangesTest(c)
1008	defer deleteContainer(c, containerURL)
1009
1010	currentTime := getRelativeTimeGMT(10)
1011
1012	_, err := blobURL.GetPageRanges(ctx, 0, 0,
1013		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
1014	serr := err.(StorageError)
1015	c.Assert(serr.Response().StatusCode, chk.Equals, 304) // Service Code not returned in the body for a HEAD
1016}
1017
1018func (s *aztestsSuite) TestBlobGetPageRangesIfUnmodifiedSinceTrue(c *chk.C) {
1019	containerURL, blobURL := setupGetPageRangesTest(c)
1020	defer deleteContainer(c, containerURL)
1021
1022	currentTime := getRelativeTimeGMT(10)
1023
1024	resp, err := blobURL.GetPageRanges(ctx, 0, 0,
1025		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1026	validateBasicGetPageRanges(c, resp, err)
1027}
1028
1029func (s *aztestsSuite) TestBlobGetPageRangesIfUnmodifiedSinceFalse(c *chk.C) {
1030	containerURL, blobURL := setupGetPageRangesTest(c)
1031	defer deleteContainer(c, containerURL)
1032
1033	currentTime := getRelativeTimeGMT(-10)
1034
1035	_, err := blobURL.GetPageRanges(ctx, 0, 0,
1036		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1037	validateStorageError(c, err, ServiceCodeConditionNotMet)
1038}
1039
1040func (s *aztestsSuite) TestBlobGetPageRangesIfMatchTrue(c *chk.C) {
1041	containerURL, blobURL := setupGetPageRangesTest(c)
1042	defer deleteContainer(c, containerURL)
1043
1044	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1045
1046	resp2, err := blobURL.GetPageRanges(ctx, 0, 0,
1047		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}})
1048	validateBasicGetPageRanges(c, resp2, err)
1049}
1050
1051func (s *aztestsSuite) TestBlobGetPageRangesIfMatchFalse(c *chk.C) {
1052	containerURL, blobURL := setupGetPageRangesTest(c)
1053	defer deleteContainer(c, containerURL)
1054
1055	_, err := blobURL.GetPageRanges(ctx, 0, 0,
1056		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}})
1057	validateStorageError(c, err, ServiceCodeConditionNotMet)
1058}
1059
1060func (s *aztestsSuite) TestBlobGetPageRangesIfNoneMatchTrue(c *chk.C) {
1061	containerURL, blobURL := setupGetPageRangesTest(c)
1062	defer deleteContainer(c, containerURL)
1063
1064	resp, err := blobURL.GetPageRanges(ctx, 0, 0,
1065		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}})
1066	validateBasicGetPageRanges(c, resp, err)
1067}
1068
1069func (s *aztestsSuite) TestBlobGetPageRangesIfNoneMatchFalse(c *chk.C) {
1070	containerURL, blobURL := setupGetPageRangesTest(c)
1071	defer deleteContainer(c, containerURL)
1072
1073	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1074
1075	_, err := blobURL.GetPageRanges(ctx, 0, 0,
1076		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
1077	serr := err.(StorageError)
1078	c.Assert(serr.Response().StatusCode, chk.Equals, 304) // Service Code not returned in the body for a HEAD
1079}
1080
1081func setupDiffPageRangesTest(c *chk.C) (containerURL ContainerURL, blobURL PageBlobURL, snapshot string) {
1082	bsu := getBSU()
1083	containerURL, _ = createNewContainer(c, bsu)
1084	blobURL, _ = createNewPageBlob(c, containerURL)
1085
1086	_, err := blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
1087	c.Assert(err, chk.IsNil)
1088
1089	resp, err := blobURL.CreateSnapshot(ctx, nil, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1090	c.Assert(err, chk.IsNil)
1091	snapshot = resp.Snapshot()
1092
1093	_, err = blobURL.UploadPages(ctx, 0, getReaderToRandomBytes(PageBlobPageBytes), PageBlobAccessConditions{}, nil, ClientProvidedKeyOptions{})
1094	c.Assert(err, chk.IsNil) // This ensures there is a diff on the first page
1095	return
1096}
1097
1098func validateDiffPageRanges(c *chk.C, resp *PageList, err error) {
1099	c.Assert(err, chk.IsNil)
1100	c.Assert(resp.PageRange, chk.HasLen, 1)
1101	c.Assert(resp.PageRange[0].Start, chk.Equals, int64(0))
1102	c.Assert(resp.PageRange[0].End, chk.Equals, int64(PageBlobPageBytes-1))
1103}
1104
1105func (s *aztestsSuite) TestBlobDiffPageRangesNonExistantSnapshot(c *chk.C) {
1106	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1107	defer deleteContainer(c, containerURL)
1108
1109	snapshotTime, _ := time.Parse(SnapshotTimeFormat, snapshot)
1110	snapshotTime = snapshotTime.Add(time.Minute)
1111	_, err := blobURL.GetPageRangesDiff(ctx, 0, 0, snapshotTime.Format(SnapshotTimeFormat), BlobAccessConditions{})
1112	validateStorageError(c, err, ServiceCodePreviousSnapshotNotFound)
1113}
1114
1115func (s *aztestsSuite) TestBlobDiffPageRangeInvalidRange(c *chk.C) {
1116	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1117	defer deleteContainer(c, containerURL)
1118	_, err := blobURL.GetPageRangesDiff(ctx, -22, 14, snapshot, BlobAccessConditions{})
1119	c.Assert(err, chk.IsNil)
1120}
1121
1122func (s *aztestsSuite) TestBlobDiffPageRangeIfModifiedSinceTrue(c *chk.C) {
1123	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1124	defer deleteContainer(c, containerURL)
1125
1126	currentTime := getRelativeTimeGMT(-10)
1127
1128	resp, err := blobURL.GetPageRangesDiff(ctx, 0, 0, snapshot,
1129		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
1130	validateDiffPageRanges(c, resp, err)
1131}
1132
1133func (s *aztestsSuite) TestBlobDiffPageRangeIfModifiedSinceFalse(c *chk.C) {
1134	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1135	defer deleteContainer(c, containerURL)
1136
1137	currentTime := getRelativeTimeGMT(10)
1138
1139	_, err := blobURL.GetPageRangesDiff(ctx, 0, 0, snapshot,
1140		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
1141	serr := err.(StorageError)
1142	c.Assert(serr.Response().StatusCode, chk.Equals, 304) // Service Code not returned in the body for a HEAD
1143}
1144
1145func (s *aztestsSuite) TestBlobDiffPageRangeIfUnmodifiedSinceTrue(c *chk.C) {
1146	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1147	defer deleteContainer(c, containerURL)
1148
1149	currentTime := getRelativeTimeGMT(10)
1150
1151	resp, err := blobURL.GetPageRangesDiff(ctx, 0, 0, snapshot,
1152		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1153	validateDiffPageRanges(c, resp, err)
1154}
1155
1156func (s *aztestsSuite) TestBlobDiffPageRangeIfUnmodifiedSinceFalse(c *chk.C) {
1157	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1158	defer deleteContainer(c, containerURL)
1159
1160	currentTime := getRelativeTimeGMT(-10)
1161
1162	_, err := blobURL.GetPageRangesDiff(ctx, 0, 0, snapshot,
1163		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1164	validateStorageError(c, err, ServiceCodeConditionNotMet)
1165}
1166
1167func (s *aztestsSuite) TestBlobDiffPageRangeIfMatchTrue(c *chk.C) {
1168	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1169	defer deleteContainer(c, containerURL)
1170
1171	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1172
1173	resp2, err := blobURL.GetPageRangesDiff(ctx, 0, 0, snapshot,
1174		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}})
1175	validateDiffPageRanges(c, resp2, err)
1176}
1177
1178func (s *aztestsSuite) TestBlobDiffPageRangeIfMatchFalse(c *chk.C) {
1179	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1180	defer deleteContainer(c, containerURL)
1181
1182	_, err := blobURL.GetPageRangesDiff(ctx, 0, 0, snapshot,
1183		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}})
1184	validateStorageError(c, err, ServiceCodeConditionNotMet)
1185}
1186
1187func (s *aztestsSuite) TestBlobDiffPageRangeIfNoneMatchTrue(c *chk.C) {
1188	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1189	defer deleteContainer(c, containerURL)
1190
1191	resp, err := blobURL.GetPageRangesDiff(ctx, 0, 0, snapshot,
1192		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}})
1193	validateDiffPageRanges(c, resp, err)
1194}
1195
1196func (s *aztestsSuite) TestBlobDiffPageRangeIfNoneMatchFalse(c *chk.C) {
1197	containerURL, blobURL, snapshot := setupDiffPageRangesTest(c)
1198	defer deleteContainer(c, containerURL)
1199
1200	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1201
1202	_, err := blobURL.GetPageRangesDiff(ctx, 0, 0, snapshot,
1203		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
1204	serr := err.(StorageError)
1205	c.Assert(serr.Response().StatusCode, chk.Equals, 304) // Service Code not returned in the body for a HEAD
1206}
1207
1208func (s *aztestsSuite) TestBlobResizeZero(c *chk.C) {
1209	bsu := getBSU()
1210	containerURL, _ := createNewContainer(c, bsu)
1211	defer deleteContainer(c, containerURL)
1212	blobURL, _ := createNewPageBlob(c, containerURL)
1213
1214	// The default blob is created with size > 0, so this should actually update
1215	_, err := blobURL.Resize(ctx, 0, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1216	c.Assert(err, chk.IsNil)
1217
1218	resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1219	c.Assert(err, chk.IsNil)
1220	c.Assert(resp.ContentLength(), chk.Equals, int64(0))
1221}
1222
1223func (s *aztestsSuite) TestBlobResizeInvalidSizeNegative(c *chk.C) {
1224	bsu := getBSU()
1225	containerURL, _ := createNewContainer(c, bsu)
1226	defer deleteContainer(c, containerURL)
1227	blobURL, _ := createNewPageBlob(c, containerURL)
1228
1229	_, err := blobURL.Resize(ctx, -4, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1230	c.Assert(err, chk.Not(chk.IsNil))
1231}
1232
1233func (s *aztestsSuite) TestBlobResizeInvalidSizeMisaligned(c *chk.C) {
1234	bsu := getBSU()
1235	containerURL, _ := createNewContainer(c, bsu)
1236	defer deleteContainer(c, containerURL)
1237	blobURL, _ := createNewPageBlob(c, containerURL)
1238
1239	_, err := blobURL.Resize(ctx, 12, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1240	c.Assert(err, chk.Not(chk.IsNil))
1241}
1242
1243func validateResize(c *chk.C, blobURL PageBlobURL) {
1244	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1245	c.Assert(resp.ContentLength(), chk.Equals, int64(PageBlobPageBytes))
1246}
1247
1248func (s *aztestsSuite) TestBlobResizeIfModifiedSinceTrue(c *chk.C) {
1249	bsu := getBSU()
1250	containerURL, _ := createNewContainer(c, bsu)
1251	defer deleteContainer(c, containerURL)
1252	blobURL, _ := createNewPageBlob(c, containerURL)
1253
1254	currentTime := getRelativeTimeGMT(-10)
1255
1256	_, err := blobURL.Resize(ctx, PageBlobPageBytes, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, ClientProvidedKeyOptions{})
1257	c.Assert(err, chk.IsNil)
1258
1259	validateResize(c, blobURL)
1260}
1261
1262func (s *aztestsSuite) TestBlobResizeIfModifiedSinceFalse(c *chk.C) {
1263	bsu := getBSU()
1264	containerURL, _ := createNewContainer(c, bsu)
1265	defer deleteContainer(c, containerURL)
1266	blobURL, _ := createNewPageBlob(c, containerURL)
1267
1268	currentTime := getRelativeTimeGMT(10)
1269
1270	_, err := blobURL.Resize(ctx, PageBlobPageBytes, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}}, ClientProvidedKeyOptions{})
1271	validateStorageError(c, err, ServiceCodeConditionNotMet)
1272}
1273
1274func (s *aztestsSuite) TestBlobResizeIfUnmodifiedSinceTrue(c *chk.C) {
1275	bsu := getBSU()
1276	containerURL, _ := createNewContainer(c, bsu)
1277	defer deleteContainer(c, containerURL)
1278	blobURL, _ := createNewPageBlob(c, containerURL)
1279
1280	currentTime := getRelativeTimeGMT(10)
1281
1282	_, err := blobURL.Resize(ctx, PageBlobPageBytes, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, ClientProvidedKeyOptions{})
1283	c.Assert(err, chk.IsNil)
1284
1285	validateResize(c, blobURL)
1286}
1287
1288func (s *aztestsSuite) TestBlobResizeIfUnmodifiedSinceFalse(c *chk.C) {
1289	bsu := getBSU()
1290	containerURL, _ := createNewContainer(c, bsu)
1291	defer deleteContainer(c, containerURL)
1292	blobURL, _ := createNewPageBlob(c, containerURL)
1293
1294	currentTime := getRelativeTimeGMT(-10)
1295
1296	_, err := blobURL.Resize(ctx, PageBlobPageBytes, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, ClientProvidedKeyOptions{})
1297	validateStorageError(c, err, ServiceCodeConditionNotMet)
1298}
1299
1300func (s *aztestsSuite) TestBlobResizeIfMatchTrue(c *chk.C) {
1301	bsu := getBSU()
1302	containerURL, _ := createNewContainer(c, bsu)
1303	defer deleteContainer(c, containerURL)
1304	blobURL, _ := createNewPageBlob(c, containerURL)
1305
1306	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1307
1308	_, err := blobURL.Resize(ctx, PageBlobPageBytes, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}}, ClientProvidedKeyOptions{})
1309	c.Assert(err, chk.IsNil)
1310
1311	validateResize(c, blobURL)
1312}
1313
1314func (s *aztestsSuite) TestBlobResizeIfMatchFalse(c *chk.C) {
1315	bsu := getBSU()
1316	containerURL, _ := createNewContainer(c, bsu)
1317	defer deleteContainer(c, containerURL)
1318	blobURL, _ := createNewPageBlob(c, containerURL)
1319
1320	_, err := blobURL.Resize(ctx, PageBlobPageBytes, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}}, ClientProvidedKeyOptions{})
1321	validateStorageError(c, err, ServiceCodeConditionNotMet)
1322}
1323
1324func (s *aztestsSuite) TestBlobResizeIfNoneMatchTrue(c *chk.C) {
1325	bsu := getBSU()
1326	containerURL, _ := createNewContainer(c, bsu)
1327	defer deleteContainer(c, containerURL)
1328	blobURL, _ := createNewPageBlob(c, containerURL)
1329
1330	_, err := blobURL.Resize(ctx, PageBlobPageBytes, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}}, ClientProvidedKeyOptions{})
1331	c.Assert(err, chk.IsNil)
1332
1333	validateResize(c, blobURL)
1334}
1335
1336func (s *aztestsSuite) TestBlobResizeIfNoneMatchFalse(c *chk.C) {
1337	bsu := getBSU()
1338	containerURL, _ := createNewContainer(c, bsu)
1339	defer deleteContainer(c, containerURL)
1340	blobURL, _ := createNewPageBlob(c, containerURL)
1341
1342	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1343
1344	_, err := blobURL.Resize(ctx, PageBlobPageBytes, BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}}, ClientProvidedKeyOptions{})
1345	validateStorageError(c, err, ServiceCodeConditionNotMet)
1346}
1347
1348func (s *aztestsSuite) TestBlobSetSequenceNumberActionTypeInvalid(c *chk.C) {
1349	bsu := getBSU()
1350	containerURL, _ := createNewContainer(c, bsu)
1351	defer deleteContainer(c, containerURL)
1352	blobURL, _ := createNewPageBlob(c, containerURL)
1353
1354	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionType("garbage"), 1, BlobAccessConditions{})
1355	validateStorageError(c, err, ServiceCodeInvalidHeaderValue)
1356}
1357
1358func (s *aztestsSuite) TestBlobSetSequenceNumberSequenceNumberInvalid(c *chk.C) {
1359	bsu := getBSU()
1360	containerURL, _ := createNewContainer(c, bsu)
1361	defer deleteContainer(c, containerURL)
1362	blobURL, _ := createNewPageBlob(c, containerURL)
1363
1364	defer func() { // Invalid sequence number should panic
1365		recover()
1366	}()
1367
1368	blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionUpdate, -1, BlobAccessConditions{})
1369}
1370
1371func validateSequenceNumberSet(c *chk.C, blobURL PageBlobURL) {
1372	resp, err := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1373	c.Assert(err, chk.IsNil)
1374	c.Assert(resp.BlobSequenceNumber(), chk.Equals, int64(1))
1375}
1376
1377func (s *aztestsSuite) TestBlobSetSequenceNumberIfModifiedSinceTrue(c *chk.C) {
1378	bsu := getBSU()
1379	containerURL, _ := createNewContainer(c, bsu)
1380	defer deleteContainer(c, containerURL)
1381	blobURL, _ := createNewPageBlob(c, containerURL)
1382
1383	currentTime := getRelativeTimeGMT(-10)
1384
1385	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionIncrement, 0,
1386		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
1387	c.Assert(err, chk.IsNil)
1388
1389	validateSequenceNumberSet(c, blobURL)
1390}
1391
1392func (s *aztestsSuite) TestBlobSetSequenceNumberIfModifiedSinceFalse(c *chk.C) {
1393	bsu := getBSU()
1394	containerURL, _ := createNewContainer(c, bsu)
1395	defer deleteContainer(c, containerURL)
1396	blobURL, _ := createNewPageBlob(c, containerURL)
1397
1398	currentTime := getRelativeTimeGMT(10)
1399
1400	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionIncrement, 0,
1401		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
1402	validateStorageError(c, err, ServiceCodeConditionNotMet)
1403}
1404
1405func (s *aztestsSuite) TestBlobSetSequenceNumberIfUnmodifiedSinceTrue(c *chk.C) {
1406	bsu := getBSU()
1407	containerURL, _ := createNewContainer(c, bsu)
1408	defer deleteContainer(c, containerURL)
1409	blobURL, _ := createNewPageBlob(c, containerURL)
1410
1411	currentTime := getRelativeTimeGMT(10)
1412
1413	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionIncrement, 0,
1414		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1415	c.Assert(err, chk.IsNil)
1416
1417	validateSequenceNumberSet(c, blobURL)
1418}
1419
1420func (s *aztestsSuite) TestBlobSetSequenceNumberIfUnmodifiedSinceFalse(c *chk.C) {
1421	bsu := getBSU()
1422	containerURL, _ := createNewContainer(c, bsu)
1423	defer deleteContainer(c, containerURL)
1424	blobURL, _ := createNewPageBlob(c, containerURL)
1425
1426	currentTime := getRelativeTimeGMT(-10)
1427
1428	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionIncrement, 0,
1429		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1430	validateStorageError(c, err, ServiceCodeConditionNotMet)
1431}
1432
1433func (s *aztestsSuite) TestBlobSetSequenceNumberIfMatchTrue(c *chk.C) {
1434	bsu := getBSU()
1435	containerURL, _ := createNewContainer(c, bsu)
1436	defer deleteContainer(c, containerURL)
1437	blobURL, _ := createNewPageBlob(c, containerURL)
1438
1439	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1440
1441	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionIncrement, 0,
1442		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}})
1443	c.Assert(err, chk.IsNil)
1444
1445	validateSequenceNumberSet(c, blobURL)
1446}
1447
1448func (s *aztestsSuite) TestBlobSetSequenceNumberIfMatchFalse(c *chk.C) {
1449	bsu := getBSU()
1450	containerURL, _ := createNewContainer(c, bsu)
1451	defer deleteContainer(c, containerURL)
1452	blobURL, _ := createNewPageBlob(c, containerURL)
1453
1454	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionIncrement, 0,
1455		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}})
1456	validateStorageError(c, err, ServiceCodeConditionNotMet)
1457}
1458
1459func (s *aztestsSuite) TestBlobSetSequenceNumberIfNoneMatchTrue(c *chk.C) {
1460	bsu := getBSU()
1461	containerURL, _ := createNewContainer(c, bsu)
1462	defer deleteContainer(c, containerURL)
1463	blobURL, _ := createNewPageBlob(c, containerURL)
1464
1465	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionIncrement, 0,
1466		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}})
1467	c.Assert(err, chk.IsNil)
1468
1469	validateSequenceNumberSet(c, blobURL)
1470}
1471
1472func (s *aztestsSuite) TestBlobSetSequenceNumberIfNoneMatchFalse(c *chk.C) {
1473	bsu := getBSU()
1474	containerURL, _ := createNewContainer(c, bsu)
1475	defer deleteContainer(c, containerURL)
1476	blobURL, _ := createNewPageBlob(c, containerURL)
1477
1478	resp, _ := blobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1479
1480	_, err := blobURL.UpdateSequenceNumber(ctx, SequenceNumberActionIncrement, 0,
1481		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
1482	validateStorageError(c, err, ServiceCodeConditionNotMet)
1483}
1484
1485func waitForIncrementalCopy(c *chk.C, copyBlobURL PageBlobURL, blobCopyResponse *PageBlobCopyIncrementalResponse) string {
1486	status := blobCopyResponse.CopyStatus()
1487	var getPropertiesAndMetadataResult *BlobGetPropertiesResponse
1488	// Wait for the copy to finish
1489	start := time.Now()
1490	for status != CopyStatusSuccess {
1491		getPropertiesAndMetadataResult, _ = copyBlobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1492		status = getPropertiesAndMetadataResult.CopyStatus()
1493		currentTime := time.Now()
1494		if currentTime.Sub(start) >= time.Minute {
1495			c.Fail()
1496		}
1497	}
1498	return getPropertiesAndMetadataResult.DestinationSnapshot()
1499}
1500
1501func setupStartIncrementalCopyTest(c *chk.C) (containerURL ContainerURL, blobURL PageBlobURL, copyBlobURL PageBlobURL, snapshot string) {
1502	bsu := getBSU()
1503	containerURL, _ = createNewContainer(c, bsu)
1504	containerURL.SetAccessPolicy(ctx, PublicAccessBlob, nil, ContainerAccessConditions{})
1505	blobURL, _ = createNewPageBlob(c, containerURL)
1506	resp, _ := blobURL.CreateSnapshot(ctx, nil, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1507	copyBlobURL, _ = getPageBlobURL(c, containerURL)
1508
1509	// Must create the incremental copy blob so that the access conditions work on it
1510	resp2, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), resp.Snapshot(), BlobAccessConditions{})
1511	c.Assert(err, chk.IsNil)
1512	waitForIncrementalCopy(c, copyBlobURL, resp2)
1513
1514	resp, _ = blobURL.CreateSnapshot(ctx, nil, BlobAccessConditions{}, ClientProvidedKeyOptions{}) // Take a new snapshot so the next copy will succeed
1515	snapshot = resp.Snapshot()
1516	return
1517}
1518
1519func validateIncrementalCopy(c *chk.C, copyBlobURL PageBlobURL, resp *PageBlobCopyIncrementalResponse) {
1520	t := waitForIncrementalCopy(c, copyBlobURL, resp)
1521
1522	// If we can access the snapshot without error, we are satisfied that it was created as a result of the copy
1523	copySnapshotURL := copyBlobURL.WithSnapshot(t)
1524	_, err := copySnapshotURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1525	c.Assert(err, chk.IsNil)
1526}
1527
1528func (s *aztestsSuite) TestBlobStartIncrementalCopySnapshotNotExist(c *chk.C) {
1529	bsu := getBSU()
1530	containerURL, _ := createNewContainer(c, bsu)
1531	defer deleteContainer(c, containerURL)
1532	blobURL, _ := createNewPageBlob(c, containerURL)
1533	copyBlobURL, _ := getPageBlobURL(c, containerURL)
1534
1535	snapshot := time.Now().UTC().Format(SnapshotTimeFormat)
1536	_, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), snapshot, BlobAccessConditions{})
1537	validateStorageError(c, err, ServiceCodeCannotVerifyCopySource)
1538}
1539
1540func (s *aztestsSuite) TestBlobStartIncrementalCopyIfModifiedSinceTrue(c *chk.C) {
1541	containerURL, blobURL, copyBlobURL, snapshot := setupStartIncrementalCopyTest(c)
1542
1543	defer deleteContainer(c, containerURL)
1544
1545	currentTime := getRelativeTimeGMT(-20)
1546
1547	resp, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), snapshot,
1548		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
1549	c.Assert(err, chk.IsNil)
1550
1551	validateIncrementalCopy(c, copyBlobURL, resp)
1552}
1553
1554func (s *aztestsSuite) TestBlobStartIncrementalCopyIfModifiedSinceFalse(c *chk.C) {
1555	containerURL, blobURL, copyBlobURL, snapshot := setupStartIncrementalCopyTest(c)
1556
1557	defer deleteContainer(c, containerURL)
1558
1559	currentTime := getRelativeTimeGMT(20)
1560
1561	_, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), snapshot,
1562		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfModifiedSince: currentTime}})
1563	validateStorageError(c, err, ServiceCodeConditionNotMet)
1564}
1565
1566func (s *aztestsSuite) TestBlobStartIncrementalCopyIfUnmodifiedSinceTrue(c *chk.C) {
1567	containerURL, blobURL, copyBlobURL, snapshot := setupStartIncrementalCopyTest(c)
1568
1569	defer deleteContainer(c, containerURL)
1570
1571	currentTime := getRelativeTimeGMT(20)
1572
1573	resp, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), snapshot,
1574		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1575	c.Assert(err, chk.IsNil)
1576
1577	validateIncrementalCopy(c, copyBlobURL, resp)
1578}
1579
1580func (s *aztestsSuite) TestBlobStartIncrementalCopyIfUnmodifiedSinceFalse(c *chk.C) {
1581	containerURL, blobURL, copyBlobURL, snapshot := setupStartIncrementalCopyTest(c)
1582
1583	defer deleteContainer(c, containerURL)
1584
1585	currentTime := getRelativeTimeGMT(-20)
1586
1587	_, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), snapshot,
1588		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
1589	validateStorageError(c, err, ServiceCodeConditionNotMet)
1590}
1591
1592func (s *aztestsSuite) TestBlobStartIncrementalCopyIfMatchTrue(c *chk.C) {
1593	containerURL, blobURL, copyBlobURL, snapshot := setupStartIncrementalCopyTest(c)
1594
1595	defer deleteContainer(c, containerURL)
1596
1597	resp, _ := copyBlobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1598
1599	resp2, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), snapshot,
1600		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: resp.ETag()}})
1601	c.Assert(err, chk.IsNil)
1602
1603	validateIncrementalCopy(c, copyBlobURL, resp2)
1604}
1605
1606func (s *aztestsSuite) TestBlobStartIncrementalCopyIfMatchFalse(c *chk.C) {
1607	containerURL, blobURL, copyBlobURL, snapshot := setupStartIncrementalCopyTest(c)
1608
1609	defer deleteContainer(c, containerURL)
1610
1611	_, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), snapshot,
1612		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfMatch: ETag("garbage")}})
1613	validateStorageError(c, err, ServiceCodeTargetConditionNotMet)
1614}
1615
1616func (s *aztestsSuite) TestBlobStartIncrementalCopyIfNoneMatchTrue(c *chk.C) {
1617	containerURL, blobURL, copyBlobURL, snapshot := setupStartIncrementalCopyTest(c)
1618
1619	defer deleteContainer(c, containerURL)
1620
1621	resp, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), snapshot,
1622		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: ETag("garbage")}})
1623	c.Assert(err, chk.IsNil)
1624
1625	validateIncrementalCopy(c, copyBlobURL, resp)
1626}
1627
1628func (s *aztestsSuite) TestBlobStartIncrementalCopyIfNoneMatchFalse(c *chk.C) {
1629	containerURL, blobURL, copyBlobURL, snapshot := setupStartIncrementalCopyTest(c)
1630
1631	defer deleteContainer(c, containerURL)
1632
1633	resp, _ := copyBlobURL.GetProperties(ctx, BlobAccessConditions{}, ClientProvidedKeyOptions{})
1634
1635	_, err := copyBlobURL.StartCopyIncremental(ctx, blobURL.URL(), snapshot,
1636		BlobAccessConditions{ModifiedAccessConditions: ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
1637	validateStorageError(c, err, ServiceCodeConditionNotMet)
1638}
1639