1# -*- coding: utf-8 -*-
2# Copyright (c) 2013, Google, Inc.
3# All rights reserved.
4#
5# Permission is hereby granted, free of charge, to any person obtaining a
6# copy of this software and associated documentation files (the
7# "Software"), to deal in the Software without restriction, including
8# without limitation the rights to use, copy, modify, merge, publish, dis-
9# tribute, sublicense, and/or sell copies of the Software, and to permit
10# persons to whom the Software is furnished to do so, subject to the fol-
11# lowing conditions:
12#
13# The above copyright notice and this permission notice shall be included
14# in all copies or substantial portions of the Software.
15#
16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
18# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22# IN THE SOFTWARE.
23
24"""Integration tests for GS versioning support."""
25
26import StringIO
27import os
28import tempfile
29from xml import sax
30
31from boto import handler
32from boto.exception import GSResponseError
33from boto.gs.acl import ACL
34from tests.integration.gs.testcase import GSTestCase
35
36
37# HTTP Error returned when a generation precondition fails.
38VERSION_MISMATCH = "412"
39
40
41class GSGenerationConditionalsTest(GSTestCase):
42
43    def testConditionalSetContentsFromFile(self):
44        b = self._MakeBucket()
45        k = b.new_key("foo")
46        s1 = "test1"
47        fp = StringIO.StringIO(s1)
48        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
49            k.set_contents_from_file(fp, if_generation=999)
50
51        fp = StringIO.StringIO(s1)
52        k.set_contents_from_file(fp, if_generation=0)
53        g1 = k.generation
54
55        s2 = "test2"
56        fp = StringIO.StringIO(s2)
57        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
58            k.set_contents_from_file(fp, if_generation=int(g1)+1)
59
60        fp = StringIO.StringIO(s2)
61        k.set_contents_from_file(fp, if_generation=g1)
62        self.assertEqual(k.get_contents_as_string(), s2)
63
64    def testConditionalSetContentsFromString(self):
65        b = self._MakeBucket()
66        k = b.new_key("foo")
67        s1 = "test1"
68        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
69            k.set_contents_from_string(s1, if_generation=999)
70
71        k.set_contents_from_string(s1, if_generation=0)
72        g1 = k.generation
73
74        s2 = "test2"
75        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
76            k.set_contents_from_string(s2, if_generation=int(g1)+1)
77
78        k.set_contents_from_string(s2, if_generation=g1)
79        self.assertEqual(k.get_contents_as_string(), s2)
80
81    def testConditionalSetContentsFromFilename(self):
82        s1 = "test1"
83        s2 = "test2"
84        f1 = tempfile.NamedTemporaryFile(prefix="boto-gs-test", delete=False)
85        f2 = tempfile.NamedTemporaryFile(prefix="boto-gs-test", delete=False)
86        fname1 = f1.name
87        fname2 = f2.name
88        f1.write(s1)
89        f1.close()
90        f2.write(s2)
91        f2.close()
92
93        try:
94            b = self._MakeBucket()
95            k = b.new_key("foo")
96
97            with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
98                k.set_contents_from_filename(fname1, if_generation=999)
99
100            k.set_contents_from_filename(fname1, if_generation=0)
101            g1 = k.generation
102
103            with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
104                k.set_contents_from_filename(fname2, if_generation=int(g1)+1)
105
106            k.set_contents_from_filename(fname2, if_generation=g1)
107            self.assertEqual(k.get_contents_as_string(), s2)
108        finally:
109            os.remove(fname1)
110            os.remove(fname2)
111
112    def testBucketConditionalSetAcl(self):
113        b = self._MakeVersionedBucket()
114        k = b.new_key("foo")
115        s1 = "test1"
116        k.set_contents_from_string(s1)
117
118        g1 = k.generation
119        mg1 = k.metageneration
120        self.assertEqual(str(mg1), "1")
121        b.set_acl("public-read", key_name="foo")
122
123        k = b.get_key("foo")
124        g2 = k.generation
125        mg2 = k.metageneration
126
127        self.assertEqual(g2, g1)
128        self.assertGreater(mg2, mg1)
129
130        with self.assertRaisesRegexp(ValueError, ("Received if_metageneration "
131                                                  "argument with no "
132                                                  "if_generation argument")):
133            b.set_acl("bucket-owner-full-control", key_name="foo",
134                      if_metageneration=123)
135
136        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
137            b.set_acl("bucket-owner-full-control", key_name="foo",
138                      if_generation=int(g2) + 1)
139
140        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
141            b.set_acl("bucket-owner-full-control", key_name="foo",
142                      if_generation=g2, if_metageneration=int(mg2) + 1)
143
144        b.set_acl("bucket-owner-full-control", key_name="foo", if_generation=g2)
145
146        k = b.get_key("foo")
147        g3 = k.generation
148        mg3 = k.metageneration
149        self.assertEqual(g3, g2)
150        self.assertGreater(mg3, mg2)
151
152        b.set_acl("public-read", key_name="foo", if_generation=g3,
153                  if_metageneration=mg3)
154
155    def testConditionalSetContentsFromStream(self):
156        b = self._MakeBucket()
157        k = b.new_key("foo")
158        s1 = "test1"
159        fp = StringIO.StringIO(s1)
160        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
161            k.set_contents_from_stream(fp, if_generation=999)
162
163        fp = StringIO.StringIO(s1)
164        k.set_contents_from_stream(fp, if_generation=0)
165        g1 = k.generation
166
167        k = b.get_key("foo")
168        s2 = "test2"
169        fp = StringIO.StringIO(s2)
170        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
171            k.set_contents_from_stream(fp, if_generation=int(g1)+1)
172
173        fp = StringIO.StringIO(s2)
174        k.set_contents_from_stream(fp, if_generation=g1)
175        self.assertEqual(k.get_contents_as_string(), s2)
176
177    def testBucketConditionalSetCannedAcl(self):
178        b = self._MakeVersionedBucket()
179        k = b.new_key("foo")
180        s1 = "test1"
181        k.set_contents_from_string(s1)
182
183        g1 = k.generation
184        mg1 = k.metageneration
185        self.assertEqual(str(mg1), "1")
186        b.set_canned_acl("public-read", key_name="foo")
187
188        k = b.get_key("foo")
189        g2 = k.generation
190        mg2 = k.metageneration
191
192        self.assertEqual(g2, g1)
193        self.assertGreater(mg2, mg1)
194
195        with self.assertRaisesRegexp(ValueError, ("Received if_metageneration "
196                                                  "argument with no "
197                                                  "if_generation argument")):
198            b.set_canned_acl("bucket-owner-full-control", key_name="foo",
199                      if_metageneration=123)
200
201        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
202            b.set_canned_acl("bucket-owner-full-control", key_name="foo",
203                      if_generation=int(g2) + 1)
204
205        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
206            b.set_canned_acl("bucket-owner-full-control", key_name="foo",
207                      if_generation=g2, if_metageneration=int(mg2) + 1)
208
209        b.set_canned_acl("bucket-owner-full-control", key_name="foo",
210                         if_generation=g2)
211
212        k = b.get_key("foo")
213        g3 = k.generation
214        mg3 = k.metageneration
215        self.assertEqual(g3, g2)
216        self.assertGreater(mg3, mg2)
217
218        b.set_canned_acl("public-read", key_name="foo", if_generation=g3,
219                  if_metageneration=mg3)
220
221    def testBucketConditionalSetXmlAcl(self):
222        b = self._MakeVersionedBucket()
223        k = b.new_key("foo")
224        s1 = "test1"
225        k.set_contents_from_string(s1)
226
227        g1 = k.generation
228        mg1 = k.metageneration
229        self.assertEqual(str(mg1), "1")
230
231        acl_xml = (
232            '<ACCESSControlList><EntrIes><Entry>'    +
233            '<Scope type="AllUsers"></Scope><Permission>READ</Permission>' +
234            '</Entry></EntrIes></ACCESSControlList>')
235        acl = ACL()
236        h = handler.XmlHandler(acl, b)
237        sax.parseString(acl_xml, h)
238        acl = acl.to_xml()
239
240        b.set_xml_acl(acl, key_name="foo")
241
242        k = b.get_key("foo")
243        g2 = k.generation
244        mg2 = k.metageneration
245
246        self.assertEqual(g2, g1)
247        self.assertGreater(mg2, mg1)
248
249        with self.assertRaisesRegexp(ValueError, ("Received if_metageneration "
250                                                  "argument with no "
251                                                  "if_generation argument")):
252            b.set_xml_acl(acl, key_name="foo", if_metageneration=123)
253
254        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
255            b.set_xml_acl(acl, key_name="foo", if_generation=int(g2) + 1)
256
257        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
258            b.set_xml_acl(acl, key_name="foo", if_generation=g2,
259                          if_metageneration=int(mg2) + 1)
260
261        b.set_xml_acl(acl, key_name="foo", if_generation=g2)
262
263        k = b.get_key("foo")
264        g3 = k.generation
265        mg3 = k.metageneration
266        self.assertEqual(g3, g2)
267        self.assertGreater(mg3, mg2)
268
269        b.set_xml_acl(acl, key_name="foo", if_generation=g3,
270                      if_metageneration=mg3)
271
272    def testObjectConditionalSetAcl(self):
273        b = self._MakeVersionedBucket()
274        k = b.new_key("foo")
275        k.set_contents_from_string("test1")
276
277        g1 = k.generation
278        mg1 = k.metageneration
279        self.assertEqual(str(mg1), "1")
280        k.set_acl("public-read")
281
282        k = b.get_key("foo")
283        g2 = k.generation
284        mg2 = k.metageneration
285
286        self.assertEqual(g2, g1)
287        self.assertGreater(mg2, mg1)
288
289        with self.assertRaisesRegexp(ValueError, ("Received if_metageneration "
290                                                  "argument with no "
291                                                  "if_generation argument")):
292            k.set_acl("bucket-owner-full-control", if_metageneration=123)
293
294        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
295            k.set_acl("bucket-owner-full-control", if_generation=int(g2) + 1)
296
297        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
298            k.set_acl("bucket-owner-full-control", if_generation=g2,
299                      if_metageneration=int(mg2) + 1)
300
301        k.set_acl("bucket-owner-full-control", if_generation=g2)
302
303        k = b.get_key("foo")
304        g3 = k.generation
305        mg3 = k.metageneration
306        self.assertEqual(g3, g2)
307        self.assertGreater(mg3, mg2)
308
309        k.set_acl("public-read", if_generation=g3, if_metageneration=mg3)
310
311    def testObjectConditionalSetCannedAcl(self):
312        b = self._MakeVersionedBucket()
313        k = b.new_key("foo")
314        k.set_contents_from_string("test1")
315
316        g1 = k.generation
317        mg1 = k.metageneration
318        self.assertEqual(str(mg1), "1")
319        k.set_canned_acl("public-read")
320
321        k = b.get_key("foo")
322        g2 = k.generation
323        mg2 = k.metageneration
324
325        self.assertEqual(g2, g1)
326        self.assertGreater(mg2, mg1)
327
328        with self.assertRaisesRegexp(ValueError, ("Received if_metageneration "
329                                                  "argument with no "
330                                                  "if_generation argument")):
331            k.set_canned_acl("bucket-owner-full-control",
332                             if_metageneration=123)
333
334        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
335            k.set_canned_acl("bucket-owner-full-control",
336                             if_generation=int(g2) + 1)
337
338        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
339            k.set_canned_acl("bucket-owner-full-control", if_generation=g2,
340                      if_metageneration=int(mg2) + 1)
341
342        k.set_canned_acl("bucket-owner-full-control", if_generation=g2)
343
344        k = b.get_key("foo")
345        g3 = k.generation
346        mg3 = k.metageneration
347        self.assertEqual(g3, g2)
348        self.assertGreater(mg3, mg2)
349
350        k.set_canned_acl("public-read", if_generation=g3, if_metageneration=mg3)
351
352    def testObjectConditionalSetXmlAcl(self):
353        b = self._MakeVersionedBucket()
354        k = b.new_key("foo")
355        s1 = "test1"
356        k.set_contents_from_string(s1)
357
358        g1 = k.generation
359        mg1 = k.metageneration
360        self.assertEqual(str(mg1), "1")
361
362        acl_xml = (
363            '<ACCESSControlList><EntrIes><Entry>'    +
364            '<Scope type="AllUsers"></Scope><Permission>READ</Permission>' +
365            '</Entry></EntrIes></ACCESSControlList>')
366        acl = ACL()
367        h = handler.XmlHandler(acl, b)
368        sax.parseString(acl_xml, h)
369        acl = acl.to_xml()
370
371        k.set_xml_acl(acl)
372
373        k = b.get_key("foo")
374        g2 = k.generation
375        mg2 = k.metageneration
376
377        self.assertEqual(g2, g1)
378        self.assertGreater(mg2, mg1)
379
380        with self.assertRaisesRegexp(ValueError, ("Received if_metageneration "
381                                                  "argument with no "
382                                                  "if_generation argument")):
383            k.set_xml_acl(acl, if_metageneration=123)
384
385        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
386            k.set_xml_acl(acl, if_generation=int(g2) + 1)
387
388        with self.assertRaisesRegexp(GSResponseError, VERSION_MISMATCH):
389            k.set_xml_acl(acl, if_generation=g2, if_metageneration=int(mg2) + 1)
390
391        k.set_xml_acl(acl, if_generation=g2)
392
393        k = b.get_key("foo")
394        g3 = k.generation
395        mg3 = k.metageneration
396        self.assertEqual(g3, g2)
397        self.assertGreater(mg3, mg2)
398
399        k.set_xml_acl(acl, if_generation=g3, if_metageneration=mg3)
400