1package azblob_test
2
3import (
4	"context"
5	"io/ioutil"
6	"time"
7
8	"crypto/md5"
9
10	"bytes"
11	"strings"
12
13	"github.com/Azure/azure-storage-blob-go/azblob"
14	chk "gopkg.in/check.v1" // go get gopkg.in/check.v1
15)
16
17func (b *aztestsSuite) TestAppendBlock(c *chk.C) {
18	bsu := getBSU()
19	container, _ := createNewContainer(c, bsu)
20	defer delContainer(c, container)
21
22	blob := container.NewAppendBlobURL(generateBlobName())
23
24	resp, err := blob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
25	c.Assert(err, chk.IsNil)
26	c.Assert(resp.StatusCode(), chk.Equals, 201)
27
28	appendResp, err := blob.AppendBlock(context.Background(), getReaderToRandomBytes(1024), azblob.AppendBlobAccessConditions{}, nil)
29	c.Assert(err, chk.IsNil)
30	c.Assert(appendResp.Response().StatusCode, chk.Equals, 201)
31	c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "0")
32	c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
33	c.Assert(appendResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
34	c.Assert(appendResp.LastModified().IsZero(), chk.Equals, false)
35	c.Assert(appendResp.ContentMD5(), chk.Not(chk.Equals), "")
36	c.Assert(appendResp.RequestID(), chk.Not(chk.Equals), "")
37	c.Assert(appendResp.Version(), chk.Not(chk.Equals), "")
38	c.Assert(appendResp.Date().IsZero(), chk.Equals, false)
39
40	appendResp, err = blob.AppendBlock(context.Background(), getReaderToRandomBytes(1024), azblob.AppendBlobAccessConditions{}, nil)
41	c.Assert(err, chk.IsNil)
42	c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "1024")
43	c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(2))
44}
45
46func (b *aztestsSuite) TestAppendBlockWithMD5(c *chk.C) {
47	bsu := getBSU()
48	container, _ := createNewContainer(c, bsu)
49	defer delContainer(c, container)
50
51	// set up blob to test
52	blob := container.NewAppendBlobURL(generateBlobName())
53	resp, err := blob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
54	c.Assert(err, chk.IsNil)
55	c.Assert(resp.StatusCode(), chk.Equals, 201)
56
57	// test append block with valid MD5 value
58	readerToBody, body := getRandomDataAndReader(1024)
59	md5Value := md5.Sum(body)
60	appendResp, err := blob.AppendBlock(context.Background(), readerToBody, azblob.AppendBlobAccessConditions{}, md5Value[:])
61	c.Assert(err, chk.IsNil)
62	c.Assert(appendResp.Response().StatusCode, chk.Equals, 201)
63	c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "0")
64	c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
65	c.Assert(appendResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
66	c.Assert(appendResp.LastModified().IsZero(), chk.Equals, false)
67	c.Assert(appendResp.ContentMD5(), chk.DeepEquals, md5Value[:])
68	c.Assert(appendResp.RequestID(), chk.Not(chk.Equals), "")
69	c.Assert(appendResp.Version(), chk.Not(chk.Equals), "")
70	c.Assert(appendResp.Date().IsZero(), chk.Equals, false)
71
72	// test append block with bad MD5 value
73	readerToBody, body = getRandomDataAndReader(1024)
74	_, badMD5 := getRandomDataAndReader(16)
75	appendResp, err = blob.AppendBlock(context.Background(), readerToBody, azblob.AppendBlobAccessConditions{}, badMD5[:])
76	validateStorageError(c, err, azblob.ServiceCodeMd5Mismatch)
77}
78
79func (b *aztestsSuite) TestAppendBlockFromURL(c *chk.C) {
80	bsu := getBSU()
81	credential, err := getGenericCredential("")
82	if err != nil {
83		c.Fatal("Invalid credential")
84	}
85	container, _ := createNewContainer(c, bsu)
86	defer delContainer(c, container)
87
88	testSize := 4 * 1024 * 1024 // 4MB
89	r, sourceData := getRandomDataAndReader(testSize)
90	ctx := context.Background() // Use default Background context
91	srcBlob := container.NewAppendBlobURL(generateName("appendsrc"))
92	destBlob := container.NewAppendBlobURL(generateName("appenddest"))
93
94	// Prepare source blob for copy.
95	cResp1, err := srcBlob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
96	c.Assert(err, chk.IsNil)
97	c.Assert(cResp1.StatusCode(), chk.Equals, 201)
98	appendResp, err := srcBlob.AppendBlock(context.Background(), r, azblob.AppendBlobAccessConditions{}, nil)
99	c.Assert(err, chk.IsNil)
100	c.Assert(appendResp.Response().StatusCode, chk.Equals, 201)
101	c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "0")
102	c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
103	c.Assert(appendResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
104	c.Assert(appendResp.LastModified().IsZero(), chk.Equals, false)
105	c.Assert(appendResp.ContentMD5(), chk.Not(chk.Equals), "")
106	c.Assert(appendResp.RequestID(), chk.Not(chk.Equals), "")
107	c.Assert(appendResp.Version(), chk.Not(chk.Equals), "")
108	c.Assert(appendResp.Date().IsZero(), chk.Equals, false)
109
110	// Get source blob URL with SAS for AppendBlockFromURL.
111	srcBlobParts := azblob.NewBlobURLParts(srcBlob.URL())
112
113	srcBlobParts.SAS, err = azblob.BlobSASSignatureValues{
114		Protocol:      azblob.SASProtocolHTTPS,              // Users MUST use HTTPS (not HTTP)
115		ExpiryTime:    time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
116		ContainerName: srcBlobParts.ContainerName,
117		BlobName:      srcBlobParts.BlobName,
118		Permissions:   azblob.BlobSASPermissions{Read: true}.String(),
119	}.NewSASQueryParameters(credential)
120	if err != nil {
121		c.Fatal(err)
122	}
123
124	srcBlobURLWithSAS := srcBlobParts.URL()
125
126	// Append block from URL.
127	cResp2, err := destBlob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
128	c.Assert(err, chk.IsNil)
129	c.Assert(cResp2.StatusCode(), chk.Equals, 201)
130	appendFromURLResp, err := destBlob.AppendBlockFromURL(ctx, srcBlobURLWithSAS, 0, int64(testSize), azblob.AppendBlobAccessConditions{}, azblob.ModifiedAccessConditions{}, nil)
131	c.Assert(err, chk.IsNil)
132	c.Assert(appendFromURLResp.Response().StatusCode, chk.Equals, 201)
133	c.Assert(appendFromURLResp.BlobAppendOffset(), chk.Equals, "0")
134	c.Assert(appendFromURLResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
135	c.Assert(appendFromURLResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
136	c.Assert(appendFromURLResp.LastModified().IsZero(), chk.Equals, false)
137	c.Assert(appendFromURLResp.ContentMD5(), chk.Not(chk.Equals), "")
138	c.Assert(appendFromURLResp.RequestID(), chk.Not(chk.Equals), "")
139	c.Assert(appendFromURLResp.Version(), chk.Not(chk.Equals), "")
140	c.Assert(appendFromURLResp.Date().IsZero(), chk.Equals, false)
141
142	// Check data integrity through downloading.
143	downloadResp, err := destBlob.BlobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
144	c.Assert(err, chk.IsNil)
145	destData, err := ioutil.ReadAll(downloadResp.Body(azblob.RetryReaderOptions{}))
146	c.Assert(err, chk.IsNil)
147	c.Assert(destData, chk.DeepEquals, sourceData)
148}
149
150func (b *aztestsSuite) TestAppendBlockFromURLWithMD5(c *chk.C) {
151	bsu := getBSU()
152	credential, err := getGenericCredential("")
153	if err != nil {
154		c.Fatal("Invalid credential")
155	}
156	container, _ := createNewContainer(c, bsu)
157	defer delContainer(c, container)
158
159	testSize := 4 * 1024 * 1024 // 4MB
160	r, sourceData := getRandomDataAndReader(testSize)
161	md5Value := md5.Sum(sourceData)
162	ctx := context.Background() // Use default Background context
163	srcBlob := container.NewAppendBlobURL(generateName("appendsrc"))
164	destBlob := container.NewAppendBlobURL(generateName("appenddest"))
165
166	// Prepare source blob for copy.
167	cResp1, err := srcBlob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
168	c.Assert(err, chk.IsNil)
169	c.Assert(cResp1.StatusCode(), chk.Equals, 201)
170	appendResp, err := srcBlob.AppendBlock(context.Background(), r, azblob.AppendBlobAccessConditions{}, nil)
171	c.Assert(err, chk.IsNil)
172	c.Assert(appendResp.Response().StatusCode, chk.Equals, 201)
173	c.Assert(appendResp.BlobAppendOffset(), chk.Equals, "0")
174	c.Assert(appendResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
175	c.Assert(appendResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
176	c.Assert(appendResp.LastModified().IsZero(), chk.Equals, false)
177	c.Assert(appendResp.ContentMD5(), chk.Not(chk.Equals), "")
178	c.Assert(appendResp.RequestID(), chk.Not(chk.Equals), "")
179	c.Assert(appendResp.Version(), chk.Not(chk.Equals), "")
180	c.Assert(appendResp.Date().IsZero(), chk.Equals, false)
181
182	// Get source blob URL with SAS for AppendBlockFromURL.
183	srcBlobParts := azblob.NewBlobURLParts(srcBlob.URL())
184
185	srcBlobParts.SAS, err = azblob.BlobSASSignatureValues{
186		Protocol:      azblob.SASProtocolHTTPS,              // Users MUST use HTTPS (not HTTP)
187		ExpiryTime:    time.Now().UTC().Add(48 * time.Hour), // 48-hours before expiration
188		ContainerName: srcBlobParts.ContainerName,
189		BlobName:      srcBlobParts.BlobName,
190		Permissions:   azblob.BlobSASPermissions{Read: true}.String(),
191	}.NewSASQueryParameters(credential)
192	if err != nil {
193		c.Fatal(err)
194	}
195
196	srcBlobURLWithSAS := srcBlobParts.URL()
197
198	// Append block from URL.
199	cResp2, err := destBlob.Create(context.Background(), azblob.BlobHTTPHeaders{}, nil, azblob.BlobAccessConditions{})
200	c.Assert(err, chk.IsNil)
201	c.Assert(cResp2.StatusCode(), chk.Equals, 201)
202	appendFromURLResp, err := destBlob.AppendBlockFromURL(ctx, srcBlobURLWithSAS, 0, int64(testSize), azblob.AppendBlobAccessConditions{}, azblob.ModifiedAccessConditions{}, md5Value[:])
203	c.Assert(err, chk.IsNil)
204	c.Assert(appendFromURLResp.Response().StatusCode, chk.Equals, 201)
205	c.Assert(appendFromURLResp.BlobAppendOffset(), chk.Equals, "0")
206	c.Assert(appendFromURLResp.BlobCommittedBlockCount(), chk.Equals, int32(1))
207	c.Assert(appendFromURLResp.ETag(), chk.Not(chk.Equals), azblob.ETagNone)
208	c.Assert(appendFromURLResp.LastModified().IsZero(), chk.Equals, false)
209	c.Assert(appendFromURLResp.ContentMD5(), chk.DeepEquals, md5Value[:])
210	c.Assert(appendFromURLResp.RequestID(), chk.Not(chk.Equals), "")
211	c.Assert(appendFromURLResp.Version(), chk.Not(chk.Equals), "")
212	c.Assert(appendFromURLResp.Date().IsZero(), chk.Equals, false)
213
214	// Check data integrity through downloading.
215	downloadResp, err := destBlob.BlobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)
216	c.Assert(err, chk.IsNil)
217	destData, err := ioutil.ReadAll(downloadResp.Body(azblob.RetryReaderOptions{}))
218	c.Assert(err, chk.IsNil)
219	c.Assert(destData, chk.DeepEquals, sourceData)
220
221	// Test append block from URL with bad MD5 value
222	_, badMD5 := getRandomDataAndReader(16)
223	_, err = destBlob.AppendBlockFromURL(ctx, srcBlobURLWithSAS, 0, int64(testSize), azblob.AppendBlobAccessConditions{}, azblob.ModifiedAccessConditions{}, badMD5)
224	validateStorageError(c, err, azblob.ServiceCodeMd5Mismatch)
225}
226
227func (s *aztestsSuite) TestBlobCreateAppendMetadataNonEmpty(c *chk.C) {
228	bsu := getBSU()
229	containerURL, _ := createNewContainer(c, bsu)
230	defer deleteContainer(c, containerURL)
231	blobURL, _ := getAppendBlobURL(c, containerURL)
232
233	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata, azblob.BlobAccessConditions{})
234	c.Assert(err, chk.IsNil)
235
236	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
237	c.Assert(err, chk.IsNil)
238	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
239}
240
241func (s *aztestsSuite) TestBlobCreateAppendMetadataEmpty(c *chk.C) {
242	bsu := getBSU()
243	containerURL, _ := createNewContainer(c, bsu)
244	defer deleteContainer(c, containerURL)
245	blobURL, _ := getAppendBlobURL(c, containerURL)
246
247	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, azblob.Metadata{}, azblob.BlobAccessConditions{})
248	c.Assert(err, chk.IsNil)
249
250	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
251	c.Assert(err, chk.IsNil)
252	c.Assert(resp.NewMetadata(), chk.HasLen, 0)
253}
254
255func (s *aztestsSuite) TestBlobCreateAppendMetadataInvalid(c *chk.C) {
256	bsu := getBSU()
257	containerURL, _ := createNewContainer(c, bsu)
258	defer deleteContainer(c, containerURL)
259	blobURL, _ := getAppendBlobURL(c, containerURL)
260
261	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, azblob.Metadata{"In valid!": "bar"}, azblob.BlobAccessConditions{})
262	c.Assert(strings.Contains(err.Error(), invalidHeaderErrorSubstring), chk.Equals, true)
263}
264
265func (s *aztestsSuite) TestBlobCreateAppendHTTPHeaders(c *chk.C) {
266	bsu := getBSU()
267	containerURL, _ := createNewContainer(c, bsu)
268	defer deleteContainer(c, containerURL)
269	blobURL, _ := getAppendBlobURL(c, containerURL)
270
271	_, err := blobURL.Create(ctx, basicHeaders, nil, azblob.BlobAccessConditions{})
272	c.Assert(err, chk.IsNil)
273
274	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
275	c.Assert(err, chk.IsNil)
276	h := resp.NewHTTPHeaders()
277	c.Assert(h, chk.DeepEquals, basicHeaders)
278}
279
280func validateAppendBlobPut(c *chk.C, blobURL azblob.AppendBlobURL) {
281	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
282	c.Assert(err, chk.IsNil)
283	c.Assert(resp.NewMetadata(), chk.DeepEquals, basicMetadata)
284}
285
286func (s *aztestsSuite) TestBlobCreateAppendIfModifiedSinceTrue(c *chk.C) {
287	bsu := getBSU()
288	containerURL, _ := createNewContainer(c, bsu)
289	defer deleteContainer(c, containerURL)
290	blobURL, _ := createNewAppendBlob(c, containerURL)
291
292	currentTime := getRelativeTimeGMT(-10)
293
294	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
295		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
296	c.Assert(err, chk.IsNil)
297
298	validateAppendBlobPut(c, blobURL)
299}
300
301func (s *aztestsSuite) TestBlobCreateAppendIfModifiedSinceFalse(c *chk.C) {
302	bsu := getBSU()
303	containerURL, _ := createNewContainer(c, bsu)
304	defer deleteContainer(c, containerURL)
305	blobURL, _ := createNewAppendBlob(c, containerURL)
306
307	currentTime := getRelativeTimeGMT(10)
308
309	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
310		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}})
311	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
312}
313
314func (s *aztestsSuite) TestBlobCreateAppendIfUnmodifiedSinceTrue(c *chk.C) {
315	bsu := getBSU()
316	containerURL, _ := createNewContainer(c, bsu)
317	defer deleteContainer(c, containerURL)
318	blobURL, _ := createNewAppendBlob(c, containerURL)
319
320	currentTime := getRelativeTimeGMT(10)
321
322	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
323		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
324	c.Assert(err, chk.IsNil)
325
326	validateAppendBlobPut(c, blobURL)
327}
328
329func (s *aztestsSuite) TestBlobCreateAppendIfUnmodifiedSinceFalse(c *chk.C) {
330	bsu := getBSU()
331	containerURL, _ := createNewContainer(c, bsu)
332	defer deleteContainer(c, containerURL)
333	blobURL, _ := createNewAppendBlob(c, containerURL)
334
335	currentTime := getRelativeTimeGMT(-10)
336
337	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
338		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}})
339	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
340}
341
342func (s *aztestsSuite) TestBlobCreateAppendIfMatchTrue(c *chk.C) {
343	bsu := getBSU()
344	containerURL, _ := createNewContainer(c, bsu)
345	defer deleteContainer(c, containerURL)
346	blobURL, _ := createNewAppendBlob(c, containerURL)
347
348	resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
349
350	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
351		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}})
352	c.Assert(err, chk.IsNil)
353
354	validateAppendBlobPut(c, blobURL)
355}
356
357func (s *aztestsSuite) TestBlobCreateAppendIfMatchFalse(c *chk.C) {
358	bsu := getBSU()
359	containerURL, _ := createNewContainer(c, bsu)
360	defer deleteContainer(c, containerURL)
361	blobURL, _ := createNewAppendBlob(c, containerURL)
362
363	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
364		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}})
365	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
366}
367
368func (s *aztestsSuite) TestBlobCreateAppendIfNoneMatchTrue(c *chk.C) {
369	bsu := getBSU()
370	containerURL, _ := createNewContainer(c, bsu)
371	defer deleteContainer(c, containerURL)
372	blobURL, _ := createNewAppendBlob(c, containerURL)
373
374	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
375		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}})
376	c.Assert(err, chk.IsNil)
377
378	validateAppendBlobPut(c, blobURL)
379}
380
381func (s *aztestsSuite) TestBlobCreateAppendIfNoneMatchFalse(c *chk.C) {
382	bsu := getBSU()
383	containerURL, _ := createNewContainer(c, bsu)
384	defer deleteContainer(c, containerURL)
385	blobURL, _ := createNewAppendBlob(c, containerURL)
386
387	resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
388
389	_, err := blobURL.Create(ctx, azblob.BlobHTTPHeaders{}, basicMetadata,
390		azblob.BlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}})
391	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
392}
393
394func (s *aztestsSuite) TestBlobAppendBlockNilBody(c *chk.C) {
395	bsu := getBSU()
396	containerURL, _ := createNewContainer(c, bsu)
397	defer deleteContainer(c, containerURL)
398	blobURL, _ := createNewAppendBlob(c, containerURL)
399
400	_, err := blobURL.AppendBlock(ctx, bytes.NewReader(nil), azblob.AppendBlobAccessConditions{}, nil)
401	c.Assert(err, chk.NotNil)
402	validateStorageError(c, err, azblob.ServiceCodeInvalidHeaderValue)
403}
404
405func (s *aztestsSuite) TestBlobAppendBlockEmptyBody(c *chk.C) {
406	bsu := getBSU()
407	containerURL, _ := createNewContainer(c, bsu)
408	defer deleteContainer(c, containerURL)
409	blobURL, _ := createNewAppendBlob(c, containerURL)
410
411	_, err := blobURL.AppendBlock(ctx, strings.NewReader(""), azblob.AppendBlobAccessConditions{}, nil)
412	validateStorageError(c, err, azblob.ServiceCodeInvalidHeaderValue)
413}
414
415func (s *aztestsSuite) TestBlobAppendBlockNonExistantBlob(c *chk.C) {
416	bsu := getBSU()
417	containerURL, _ := createNewContainer(c, bsu)
418	defer deleteContainer(c, containerURL)
419	blobURL, _ := getAppendBlobURL(c, containerURL)
420
421	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), azblob.AppendBlobAccessConditions{}, nil)
422	validateStorageError(c, err, azblob.ServiceCodeBlobNotFound)
423}
424
425func validateBlockAppended(c *chk.C, blobURL azblob.AppendBlobURL, expectedSize int) {
426	resp, err := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
427	c.Assert(err, chk.IsNil)
428	c.Assert(resp.ContentLength(), chk.Equals, int64(expectedSize))
429}
430
431func (s *aztestsSuite) TestBlobAppendBlockIfModifiedSinceTrue(c *chk.C) {
432	bsu := getBSU()
433	containerURL, _ := createNewContainer(c, bsu)
434	defer deleteContainer(c, containerURL)
435	blobURL, _ := createNewAppendBlob(c, containerURL)
436
437	currentTime := getRelativeTimeGMT(-10)
438
439	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
440		azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}, nil)
441	c.Assert(err, chk.IsNil)
442
443	validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
444}
445
446func (s *aztestsSuite) TestBlobAppendBlockIfModifiedSinceFalse(c *chk.C) {
447	bsu := getBSU()
448	containerURL, _ := createNewContainer(c, bsu)
449	defer deleteContainer(c, containerURL)
450	blobURL, _ := createNewAppendBlob(c, containerURL)
451
452	currentTime := getRelativeTimeGMT(10)
453	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
454		azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfModifiedSince: currentTime}}, nil)
455	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
456}
457
458func (s *aztestsSuite) TestBlobAppendBlockIfUnmodifiedSinceTrue(c *chk.C) {
459	bsu := getBSU()
460	containerURL, _ := createNewContainer(c, bsu)
461	defer deleteContainer(c, containerURL)
462	blobURL, _ := createNewAppendBlob(c, containerURL)
463
464	currentTime := getRelativeTimeGMT(10)
465	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
466		azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, nil)
467	c.Assert(err, chk.IsNil)
468
469	validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
470}
471
472func (s *aztestsSuite) TestBlobAppendBlockIfUnmodifiedSinceFalse(c *chk.C) {
473	bsu := getBSU()
474	containerURL, _ := createNewContainer(c, bsu)
475	defer deleteContainer(c, containerURL)
476	blobURL, _ := createNewAppendBlob(c, containerURL)
477
478	currentTime := getRelativeTimeGMT(-10)
479	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
480		azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfUnmodifiedSince: currentTime}}, nil)
481	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
482}
483
484func (s *aztestsSuite) TestBlobAppendBlockIfMatchTrue(c *chk.C) {
485	bsu := getBSU()
486	containerURL, _ := createNewContainer(c, bsu)
487	defer deleteContainer(c, containerURL)
488	blobURL, _ := createNewAppendBlob(c, containerURL)
489
490	resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
491
492	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
493		azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: resp.ETag()}}, nil)
494	c.Assert(err, chk.IsNil)
495
496	validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
497}
498
499func (s *aztestsSuite) TestBlobAppendBlockIfMatchFalse(c *chk.C) {
500	bsu := getBSU()
501	containerURL, _ := createNewContainer(c, bsu)
502	defer deleteContainer(c, containerURL)
503	blobURL, _ := createNewAppendBlob(c, containerURL)
504
505	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
506		azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfMatch: azblob.ETag("garbage")}}, nil)
507	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
508}
509
510func (s *aztestsSuite) TestBlobAppendBlockIfNoneMatchTrue(c *chk.C) {
511	bsu := getBSU()
512	containerURL, _ := createNewContainer(c, bsu)
513	defer deleteContainer(c, containerURL)
514	blobURL, _ := createNewAppendBlob(c, containerURL)
515
516	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
517		azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: azblob.ETag("garbage")}}, nil)
518	c.Assert(err, chk.IsNil)
519
520	validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
521}
522
523func (s *aztestsSuite) TestBlobAppendBlockIfNoneMatchFalse(c *chk.C) {
524	bsu := getBSU()
525	containerURL, _ := createNewContainer(c, bsu)
526	defer deleteContainer(c, containerURL)
527	blobURL, _ := createNewAppendBlob(c, containerURL)
528
529	resp, _ := blobURL.GetProperties(ctx, azblob.BlobAccessConditions{})
530
531	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
532		azblob.AppendBlobAccessConditions{ModifiedAccessConditions: azblob.ModifiedAccessConditions{IfNoneMatch: resp.ETag()}}, nil)
533	validateStorageError(c, err, azblob.ServiceCodeConditionNotMet)
534}
535
536func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchTrueNegOne(c *chk.C) {
537	bsu := getBSU()
538	containerURL, _ := createNewContainer(c, bsu)
539	defer deleteContainer(c, containerURL)
540	blobURL, _ := createNewAppendBlob(c, containerURL)
541
542	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
543		azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: -1}}, nil) // This will cause the library to set the value of the header to 0
544	c.Assert(err, chk.IsNil)
545
546	validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
547}
548
549func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchZero(c *chk.C) {
550	bsu := getBSU()
551	containerURL, _ := createNewContainer(c, bsu)
552	defer deleteContainer(c, containerURL)
553	blobURL, _ := createNewAppendBlob(c, containerURL)
554
555	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), azblob.AppendBlobAccessConditions{}, nil) // The position will not match, but the condition should be ignored
556	c.Assert(err, chk.IsNil)
557	_, err = blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
558		azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: 0}}, nil)
559	c.Assert(err, chk.IsNil)
560
561	validateBlockAppended(c, blobURL, 2*len(blockBlobDefaultData))
562}
563
564func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchTrueNonZero(c *chk.C) {
565	bsu := getBSU()
566	containerURL, _ := createNewContainer(c, bsu)
567	defer deleteContainer(c, containerURL)
568	blobURL, _ := createNewAppendBlob(c, containerURL)
569
570	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), azblob.AppendBlobAccessConditions{}, nil)
571	c.Assert(err, chk.IsNil)
572	_, err = blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
573		azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: int64(len(blockBlobDefaultData))}}, nil)
574	c.Assert(err, chk.IsNil)
575
576	validateBlockAppended(c, blobURL, len(blockBlobDefaultData)*2)
577}
578
579func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchFalseNegOne(c *chk.C) {
580	bsu := getBSU()
581	containerURL, _ := createNewContainer(c, bsu)
582	defer deleteContainer(c, containerURL)
583	blobURL, _ := createNewAppendBlob(c, containerURL)
584
585	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData), azblob.AppendBlobAccessConditions{}, nil)
586	c.Assert(err, chk.IsNil)
587	_, err = blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
588		azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: -1}}, nil) // This will cause the library to set the value of the header to 0
589	validateStorageError(c, err, azblob.ServiceCodeAppendPositionConditionNotMet)
590}
591
592func (s *aztestsSuite) TestBlobAppendBlockIfAppendPositionMatchFalseNonZero(c *chk.C) {
593	bsu := getBSU()
594	containerURL, _ := createNewContainer(c, bsu)
595	defer deleteContainer(c, containerURL)
596	blobURL, _ := createNewAppendBlob(c, containerURL)
597
598	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
599		azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfAppendPositionEqual: 12}}, nil)
600	validateStorageError(c, err, azblob.ServiceCodeAppendPositionConditionNotMet)
601}
602
603func (s *aztestsSuite) TestBlobAppendBlockIfMaxSizeTrue(c *chk.C) {
604	bsu := getBSU()
605	containerURL, _ := createNewContainer(c, bsu)
606	defer deleteContainer(c, containerURL)
607	blobURL, _ := createNewAppendBlob(c, containerURL)
608
609	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
610		azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfMaxSizeLessThanOrEqual: int64(len(blockBlobDefaultData) + 1)}}, nil)
611	c.Assert(err, chk.IsNil)
612
613	validateBlockAppended(c, blobURL, len(blockBlobDefaultData))
614}
615
616func (s *aztestsSuite) TestBlobAppendBlockIfMaxSizeFalse(c *chk.C) {
617	bsu := getBSU()
618	containerURL, _ := createNewContainer(c, bsu)
619	defer deleteContainer(c, containerURL)
620	blobURL, _ := createNewAppendBlob(c, containerURL)
621
622	_, err := blobURL.AppendBlock(ctx, strings.NewReader(blockBlobDefaultData),
623		azblob.AppendBlobAccessConditions{AppendPositionAccessConditions: azblob.AppendPositionAccessConditions{IfMaxSizeLessThanOrEqual: int64(len(blockBlobDefaultData) - 1)}}, nil)
624	validateStorageError(c, err, azblob.ServiceCodeMaxBlobSizeConditionNotMet)
625}
626