1package azblob_test
2
3import (
4	"context"
5	"strings"
6	"time"
7
8	"github.com/Azure/azure-storage-blob-go/azblob"
9	chk "gopkg.in/check.v1" // go get gopkg.in/check.v1
10)
11
12func (s *aztestsSuite) TestListContainers(c *chk.C) {
13	sa := getBSU()
14	resp, err := sa.ListContainersSegment(context.Background(), azblob.Marker{}, azblob.ListContainersSegmentOptions{Prefix: containerPrefix})
15	c.Assert(err, chk.IsNil)
16	c.Assert(resp.Response().StatusCode, chk.Equals, 200)
17	c.Assert(resp.RequestID(), chk.Not(chk.Equals), "")
18	c.Assert(resp.Version(), chk.Not(chk.Equals), "")
19	c.Assert(len(resp.ContainerItems) >= 0, chk.Equals, true)
20	c.Assert(resp.ServiceEndpoint, chk.NotNil)
21
22	container, name := createNewContainer(c, sa)
23	defer delContainer(c, container)
24
25	md := azblob.Metadata{
26		"foo": "foovalue",
27		"bar": "barvalue",
28	}
29	_, err = container.SetMetadata(context.Background(), md, azblob.ContainerAccessConditions{})
30	c.Assert(err, chk.IsNil)
31
32	resp, err = sa.ListContainersSegment(context.Background(), azblob.Marker{}, azblob.ListContainersSegmentOptions{Detail: azblob.ListContainersDetail{Metadata: true}, Prefix: name})
33	c.Assert(err, chk.IsNil)
34	c.Assert(resp.ContainerItems, chk.HasLen, 1)
35	c.Assert(resp.ContainerItems[0].Name, chk.NotNil)
36	c.Assert(resp.ContainerItems[0].Properties, chk.NotNil)
37	c.Assert(resp.ContainerItems[0].Properties.LastModified, chk.NotNil)
38	c.Assert(resp.ContainerItems[0].Properties.Etag, chk.NotNil)
39	c.Assert(resp.ContainerItems[0].Properties.LeaseStatus, chk.Equals, azblob.LeaseStatusUnlocked)
40	c.Assert(resp.ContainerItems[0].Properties.LeaseState, chk.Equals, azblob.LeaseStateAvailable)
41	c.Assert(string(resp.ContainerItems[0].Properties.LeaseDuration), chk.Equals, "")
42	c.Assert(string(resp.ContainerItems[0].Properties.PublicAccess), chk.Equals, string(azblob.PublicAccessNone))
43	c.Assert(resp.ContainerItems[0].Metadata, chk.DeepEquals, md)
44}
45
46func (s *aztestsSuite) TestListContainersPaged(c *chk.C) {
47	sa := getBSU()
48
49	const numContainers = 4
50	const maxResultsPerPage = 2
51	const pagedContainersPrefix = "azblobspagedtest"
52
53	containers := make([]azblob.ContainerURL, numContainers)
54	for i := 0; i < numContainers; i++ {
55		containers[i], _ = createNewContainerWithSuffix(c, sa, pagedContainersPrefix)
56	}
57
58	defer func() {
59		for i := range containers {
60			delContainer(c, containers[i])
61		}
62	}()
63
64	marker := azblob.Marker{}
65	iterations := numContainers / maxResultsPerPage
66
67	for i := 0; i < iterations; i++ {
68		resp, err := sa.ListContainersSegment(context.Background(), marker, azblob.ListContainersSegmentOptions{MaxResults: maxResultsPerPage, Prefix: containerPrefix + pagedContainersPrefix})
69		c.Assert(err, chk.IsNil)
70		c.Assert(resp.ContainerItems, chk.HasLen, maxResultsPerPage)
71
72		hasMore := i < iterations-1
73		c.Assert(resp.NextMarker.NotDone(), chk.Equals, hasMore)
74		marker = resp.NextMarker
75	}
76}
77
78func (s *aztestsSuite) TestAccountListContainersEmptyPrefix(c *chk.C) {
79	bsu := getBSU()
80	containerURL1, _ := createNewContainer(c, bsu)
81	defer deleteContainer(c, containerURL1)
82	containerURL2, _ := createNewContainer(c, bsu)
83	defer deleteContainer(c, containerURL2)
84
85	response, err := bsu.ListContainersSegment(ctx, azblob.Marker{}, azblob.ListContainersSegmentOptions{})
86
87	c.Assert(err, chk.IsNil)
88	c.Assert(len(response.ContainerItems) >= 2, chk.Equals, true) // The response should contain at least the two created containers. Probably many more
89}
90
91func (s *aztestsSuite) TestAccountListContainersIncludeTypeMetadata(c *chk.C) {
92	bsu := getBSU()
93	containerURLNoMetadata, nameNoMetadata := createNewContainerWithSuffix(c, bsu, "a")
94	defer deleteContainer(c, containerURLNoMetadata)
95	containerURLMetadata, nameMetadata := createNewContainerWithSuffix(c, bsu, "b")
96	defer deleteContainer(c, containerURLMetadata)
97
98	// Test on containers with and without metadata
99	_, err := containerURLMetadata.SetMetadata(ctx, basicMetadata, azblob.ContainerAccessConditions{})
100	c.Assert(err, chk.IsNil)
101
102	// Also validates not specifying MaxResults
103	response, err := bsu.ListContainersSegment(ctx, azblob.Marker{},
104		azblob.ListContainersSegmentOptions{Prefix: containerPrefix, Detail: azblob.ListContainersDetail{Metadata: true}})
105	c.Assert(err, chk.IsNil)
106	c.Assert(response.ContainerItems[0].Name, chk.Equals, nameNoMetadata)
107	c.Assert(response.ContainerItems[0].Metadata, chk.HasLen, 0)
108	c.Assert(response.ContainerItems[1].Name, chk.Equals, nameMetadata)
109	c.Assert(response.ContainerItems[1].Metadata, chk.DeepEquals, basicMetadata)
110}
111
112func (s *aztestsSuite) TestAccountListContainersMaxResultsNegative(c *chk.C) {
113	bsu := getBSU()
114	containerURL, _ := createNewContainer(c, bsu)
115
116	defer deleteContainer(c, containerURL)
117	_, err := bsu.ListContainersSegment(ctx,
118		azblob.Marker{}, *(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: -2}))
119	c.Assert(err, chk.Not(chk.IsNil))
120}
121
122func (s *aztestsSuite) TestAccountListContainersMaxResultsZero(c *chk.C) {
123	bsu := getBSU()
124	containerURL, _ := createNewContainer(c, bsu)
125
126	defer deleteContainer(c, containerURL)
127
128	// Max Results = 0 means the value will be ignored, the header not set, and the server default used
129	resp, err := bsu.ListContainersSegment(ctx,
130		azblob.Marker{}, *(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 0}))
131
132	c.Assert(err, chk.IsNil)
133	// There could be existing container
134	c.Assert(len(resp.ContainerItems) >= 1, chk.Equals, true)
135}
136
137func (s *aztestsSuite) TestAccountListContainersMaxResultsExact(c *chk.C) {
138	// If this test fails, ensure there are no extra containers prefixed with go in the account. These may be left over if a test is interrupted.
139	bsu := getBSU()
140	containerURL1, containerName1 := createNewContainerWithSuffix(c, bsu, "a")
141	defer deleteContainer(c, containerURL1)
142	containerURL2, containerName2 := createNewContainerWithSuffix(c, bsu, "b")
143	defer deleteContainer(c, containerURL2)
144
145	response, err := bsu.ListContainersSegment(ctx,
146		azblob.Marker{}, *(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 2}))
147
148	c.Assert(err, chk.IsNil)
149	c.Assert(response.ContainerItems, chk.HasLen, 2)
150	c.Assert(response.ContainerItems[0].Name, chk.Equals, containerName1)
151	c.Assert(response.ContainerItems[1].Name, chk.Equals, containerName2)
152}
153
154func (s *aztestsSuite) TestAccountListContainersMaxResultsInsufficient(c *chk.C) {
155	bsu := getBSU()
156	containerURL1, _ := createNewContainer(c, bsu)
157	defer deleteContainer(c, containerURL1)
158	containerURL2, _ := createNewContainer(c, bsu)
159	defer deleteContainer(c, containerURL2)
160
161	response, err := bsu.ListContainersSegment(ctx, azblob.Marker{},
162		*(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 1}))
163
164	c.Assert(err, chk.IsNil)
165	c.Assert(len(response.ContainerItems), chk.Equals, 1)
166}
167
168func (s *aztestsSuite) TestAccountListContainersMaxResultsSufficient(c *chk.C) {
169	bsu := getBSU()
170	containerURL1, _ := createNewContainer(c, bsu)
171	defer deleteContainer(c, containerURL1)
172	containerURL2, _ := createNewContainer(c, bsu)
173	defer deleteContainer(c, containerURL2)
174
175	response, err := bsu.ListContainersSegment(ctx, azblob.Marker{},
176		*(&azblob.ListContainersSegmentOptions{Prefix: containerPrefix, MaxResults: 3}))
177
178	c.Assert(err, chk.IsNil)
179
180	// This case could be instable, there could be existing containers, so the count should be >= 2
181	c.Assert(len(response.ContainerItems) >= 2, chk.Equals, true)
182}
183
184func (s *aztestsSuite) TestAccountDeleteRetentionPolicy(c *chk.C) {
185	bsu := getBSU()
186
187	days := int32(5)
188	_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
189	c.Assert(err, chk.IsNil)
190
191	// From FE, 30 seconds is guaranteed t be enough.
192	time.Sleep(time.Second * 30)
193
194	resp, err := bsu.GetProperties(ctx)
195	c.Assert(err, chk.IsNil)
196	c.Assert(resp.DeleteRetentionPolicy.Enabled, chk.Equals, true)
197	c.Assert(*resp.DeleteRetentionPolicy.Days, chk.Equals, int32(5))
198
199	_, err = bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: false}})
200	c.Assert(err, chk.IsNil)
201
202	// From FE, 30 seconds is guaranteed t be enough.
203	time.Sleep(time.Second * 30)
204
205	resp, err = bsu.GetProperties(ctx)
206	c.Assert(err, chk.IsNil)
207	c.Assert(resp.DeleteRetentionPolicy.Enabled, chk.Equals, false)
208	c.Assert(resp.DeleteRetentionPolicy.Days, chk.IsNil)
209}
210
211func (s *aztestsSuite) TestAccountDeleteRetentionPolicyEmpty(c *chk.C) {
212	bsu := getBSU()
213
214	days := int32(5)
215	_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
216	c.Assert(err, chk.IsNil)
217
218	// From FE, 30 seconds is guaranteed t be enough.
219	time.Sleep(time.Second * 30)
220
221	resp, err := bsu.GetProperties(ctx)
222	c.Assert(err, chk.IsNil)
223	c.Assert(resp.DeleteRetentionPolicy.Enabled, chk.Equals, true)
224	c.Assert(*resp.DeleteRetentionPolicy.Days, chk.Equals, int32(5))
225
226	// Enabled should default to false and therefore disable the policy
227	_, err = bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{}})
228	c.Assert(err, chk.IsNil)
229
230	// From FE, 30 seconds is guaranteed t be enough.
231	time.Sleep(time.Second * 30)
232
233	resp, err = bsu.GetProperties(ctx)
234	c.Assert(err, chk.IsNil)
235	c.Assert(resp.DeleteRetentionPolicy.Enabled, chk.Equals, false)
236	c.Assert(resp.DeleteRetentionPolicy.Days, chk.IsNil)
237}
238
239func (s *aztestsSuite) TestAccountDeleteRetentionPolicyNil(c *chk.C) {
240	bsu := getBSU()
241
242	days := int32(5)
243	_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
244	c.Assert(err, chk.IsNil)
245
246	// From FE, 30 seconds is guaranteed t be enough.
247	time.Sleep(time.Second * 30)
248
249	resp, err := bsu.GetProperties(ctx)
250	c.Assert(err, chk.IsNil)
251	c.Assert(resp.DeleteRetentionPolicy.Enabled, chk.Equals, true)
252	c.Assert(*resp.DeleteRetentionPolicy.Days, chk.Equals, int32(5))
253
254	_, err = bsu.SetProperties(ctx, azblob.StorageServiceProperties{})
255	c.Assert(err, chk.IsNil)
256
257	// From FE, 30 seconds is guaranteed t be enough.
258	time.Sleep(time.Second * 30)
259
260	// If an element of service properties is not passed, the service keeps the current settings.
261	resp, err = bsu.GetProperties(ctx)
262	c.Assert(err, chk.IsNil)
263	c.Assert(resp.DeleteRetentionPolicy.Enabled, chk.Equals, true)
264	c.Assert(*resp.DeleteRetentionPolicy.Days, chk.Equals, int32(5))
265
266	// Disable for other tests
267	bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: false}})
268}
269
270func (s *aztestsSuite) TestAccountDeleteRetentionPolicyDaysTooSmall(c *chk.C) {
271	bsu := getBSU()
272
273	days := int32(0) // Minimum days is 1. Validated on the client.
274	_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
275	c.Assert(strings.Contains(err.Error(), validationErrorSubstring), chk.Equals, true)
276}
277
278func (s *aztestsSuite) TestAccountDeleteRetentionPolicyDaysTooLarge(c *chk.C) {
279	bsu := getBSU()
280
281	days := int32(366) // Max days is 365. Left to the service for validation.
282	_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true, Days: &days}})
283	validateStorageError(c, err, azblob.ServiceCodeInvalidXMLDocument)
284}
285
286func (s *aztestsSuite) TestAccountDeleteRetentionPolicyDaysOmitted(c *chk.C) {
287	bsu := getBSU()
288
289	// Days is required if enabled is true.
290	_, err := bsu.SetProperties(ctx, azblob.StorageServiceProperties{DeleteRetentionPolicy: &azblob.RetentionPolicy{Enabled: true}})
291	validateStorageError(c, err, azblob.ServiceCodeInvalidXMLDocument)
292}
293