1 # Copyright 2013 GRNET S.A. All rights reserved.
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
7 # 1. Redistributions of source code must retain the above
8 # copyright notice, this list of conditions and the following
11 # 2. Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following
13 # disclaimer in the documentation and/or other materials
14 # provided with the distribution.
16 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
29 # The views and conclusions contained in the software and
30 # documentation are those of the authors and should not be
31 # interpreted as representing official policies, either expressed
32 # or implied, of GRNET S.A.
34 from unittest import TestCase
35 from mock import patch, call
36 from tempfile import NamedTemporaryFile
37 from os import urandom
38 from itertools import product
39 from random import randint
42 from collections import OrderedDict
44 from kamaki.clients.commisioning.utils.ordereddict import OrderedDict
46 from kamaki.clients import ClientError
47 from kamaki.clients.pithos import PithosClient, PithosRestClient
50 rest_pkg = 'kamaki.clients.pithos.rest_api.PithosRestClient'
51 pithos_pkg = 'kamaki.clients.pithos.PithosClient'
53 user_id = 'ac0un7-1d-5tr1ng'
57 'content-language': 'en-us',
58 'content-type': 'text/html; charset=utf-8',
59 'date': 'Wed, 06 Mar 2013 13:25:51 GMT',
60 'last-modified': 'Mon, 04 Mar 2013 18:22:31 GMT',
61 'server': 'gunicorn/0.14.5',
62 'vary': 'Accept-Language',
63 'x-account-bytes-used': '751615526',
64 'x-account-container-count': 7,
65 'x-account-policy-quota': 53687091200,
66 'x-account-policy-versioning': 'auto'}
68 'content-language': 'en-us',
69 'content-type': 'text/html; charset=utf-8',
70 'date': 'Wed, 06 Mar 2013 15:11:05 GMT',
71 'last-modified': 'Wed, 27 Feb 2013 15:56:13 GMT',
72 'server': 'gunicorn/0.14.5',
73 'vary': 'Accept-Language',
74 'x-container-block-hash': 'sha256',
75 'x-container-block-size': 4194304,
76 'x-container-bytes-used': 309528938,
77 'x-container-object-count': 14,
78 'x-container-object-meta': '',
79 'x-container-policy-quota': 53687091200,
80 'x-container-policy-versioning': 'auto'}
82 'content-language': 'en-us',
83 'content-length': 254965,
84 'content-type': 'application/octet-stream',
85 'date': 'Thu, 07 Mar 2013 13:27:43 GMT',
87 'last-modified': 'Mon, 04 Mar 2013 18:22:31 GMT',
88 'server': 'gunicorn/0.14.5',
89 'vary': 'Accept-Language',
90 'x-object-hash': 'obj3c7h45h1s0bj3c7h45h411r34dY',
91 'x-object-uuid': 'd0c747ca-34bd-49e0-8e98-1d07d8b0cbc7',
92 'x-object-version': '525996',
93 'x-object-version-timestamp': 'Mon, 04 Mar 2013 18:22:31 GMT',
94 'x-object-meta-k1': 'v1',
95 'x-object-meta-k2': 'v2'}
99 last_modified="2013-02-27T11:56:09.893033+00:00",
102 x_container_policy=dict(quota="21474836480", versioning="auto")),
105 last_modified="2012-10-23T12:25:17.229187+00:00",
108 x_container_policy=dict(quota="21474836480", versioning="auto"))]
111 name="The_Secret_Garden.zip",
112 x_object_public="/public/wdp9p",
114 x_object_version_timestamp="1360237915.7027509",
115 x_object_uuid="s0m3uu1df0r0bj0n3",
116 last_modified="2013-02-07T11:51:55.702751+00:00",
117 content_type="application/octet-stream",
118 x_object_hash="0afdf29f71cd53126225c3f54ca",
119 x_object_version=17737,
120 x_object_modified_by=user_id),
122 name="The_Revealed_Garden.zip",
123 x_object_public="/public/wpd7p",
125 x_object_version_timestamp="13602915.7027509",
126 x_object_uuid="s0m3uu1df0r0bj70w",
127 last_modified="2013-02-07T11:51:55.702751+00:00",
128 content_type="application/octet-stream",
129 x_object_hash="0afdf29f71cd53126225c3f54ca",
130 x_object_version=17737,
131 x_object_modified_by=user_id)]
132 object_hashmap = dict(
133 block_hash="sha256", block_size=4194304, bytes=33554432,
135 "4988438cc1c0292c085d289649b28cf547ba3db71c6efaac9f2df7e193d4d0af",
136 "b214244aa56df7d1df7c6cac066e7cef268d9c2beb4dcf7ce68af667b0626f91",
137 "17f365f25e0682565ded30576066bb13377a3d306967e4d74e06bb6bbc20f75f",
138 "2524ae208932669fff89adf8a2fc0df3b67736ca0d3aadce7a2ce640f142af37",
139 "5d807a2129d2fcd3c221c3da418ed52af3fc48d0817b62e0bb437acffccd3514",
140 "609de22ce842d997f645fc49d5f14e0e3766dd51a6cbe66383b2bab82c8dfcd0",
141 "3102851ac168c78be70e35ff5178c7b1ebebd589e5106d565ca1094d1ca8ff59",
142 "bfe306dd24e92a8d85caf7055643f250fd319e8c4cdd4755ddabbf3ff97e83c7"])
144 dict(last_modified="2013-01-29T16:50:06.084674+00:00", name="0b1a-82d5"),
145 dict(last_modified="2013-01-29T16:50:06.084674+00:00", name="0b2a-f2d5"),
146 dict(last_modified="2013-01-29T16:50:06.084674+00:00", name="2b1a-82d6")]
150 """FR stands for Fake Response"""
161 class PithosRest(TestCase):
164 self.url = 'https://www.example.com/pithos'
165 self.token = 'p17h0570k3n'
166 self.client = PithosRestClient(self.url, self.token)
167 self.client.account = user_id
168 self.client.container = 'c0nt@1n3r_i'
175 @patch('%s.set_param' % rest_pkg)
176 @patch('%s.set_header' % rest_pkg)
177 @patch('%s.head' % rest_pkg, return_value=FR())
178 def test_account_head(self, head, SH, SP):
179 for params in product(
181 (None, '50m3-07h3r-d473'),
182 (None, 'y37-4n7h3r-d473'),
183 ((), ('someval',), ('v1', 'v2',)),
184 (dict(), dict(success=200), dict(k='v', v='k'))):
185 args, kwargs = params[-2], params[-1]
187 self.client.account_head(*(params + args), **kwargs)
189 self.assertEqual(SP.mock_calls[-1], call('until', unt, iff=unt))
190 IMS, IUS = params[1], params[2]
191 self.assertEqual(SH.mock_calls[-2:], [
192 call('If-Modified-Since', IMS),
193 call('If-Unmodified-Since', IUS)])
194 self.assertEqual(head.mock_calls[-1], call(
195 '/%s' % self.client.account,
197 success=kwargs.pop('success', 204),
200 @patch('%s.set_param' % rest_pkg)
201 @patch('%s.set_header' % rest_pkg)
202 @patch('%s.get' % rest_pkg, return_value=FR())
203 def test_account_get(self, get, SH, SP):
204 keys = ('limit', 'marker', 'format', 'shared', 'until')
205 for params in product(
211 (None, '50m3-07h3r-d473'),
212 (None, 'y37-4n7h3r-d473'),
213 ((), ('someval',), ('v1', 'v2',)),
214 (dict(), dict(success=200), dict(k='v', v='k'))):
215 args, kwargs = params[-2], params[-1]
217 self.client.account_get(*(params + args), **kwargs)
218 self.assertEqual(SP.mock_calls[-5:],
219 [call(keys[i], iff=X) if (
221 keys[i], X, iff=X) for i, X in enumerate(params[:5])])
222 IMS, IUS = params[5], params[6]
223 self.assertEqual(SH.mock_calls[-2:], [
224 call('If-Modified-Since', IMS),
225 call('If-Unmodified-Since', IUS)])
226 self.assertEqual(get.mock_calls[-1], call(
227 '/%s' % self.client.account,
229 success=kwargs.pop('success', (200, 204)),
232 @patch('%s.set_param' % rest_pkg)
233 @patch('%s.set_header' % rest_pkg)
234 @patch('%s.post' % rest_pkg, return_value=FR())
235 def test_account_post(self, post, SH, SP):
236 #keys = ('update', 'groups', 'metadata', 'quota', 'versioning')
239 ({}, dict(g=['u1', 'u2']), dict(g1=[], g2=['u1', 'u2'])),
240 (None, dict(k1='v1', k2='v2', k3='v2'), dict(k='v')),
242 (None, 'v3r510n1ng'),
243 ((), ('someval',), ('v1', 'v2',)),
244 (dict(), dict(success=200), dict(k='v', v='k'))):
245 args, kwargs = pm[-2:]
247 self.client.account_post(*(pm + args), **kwargs)
249 self.assertEqual(SP.mock_calls[-1], call('update', iff=upd))
253 call('X-Account-Group-%s' % k, v) for k, v in pm[1].items()]
256 call('X-Account-Meta-%s' % k, v) for k, v in pm[2].items()]
258 call('X-Account-Policy-Quota', pm[3]),
259 call('X-Account-Policy-Versioning', pm[4])]
260 self.assertEqual(SH.mock_calls[- len(expected):], expected)
261 self.assertEqual(post.mock_calls[-1], call(
262 '/%s' % self.client.account,
264 success=kwargs.pop('success', 202),
267 @patch('%s.set_param' % rest_pkg)
268 @patch('%s.set_header' % rest_pkg)
269 @patch('%s.head' % rest_pkg, return_value=FR())
270 def test_container_head(self, head, SH, SP):
273 (None, '47h3r-d473'),
274 (None, 'y37-4n47h3r'),
276 (dict(), dict(success=200), dict(k='v', v='k'))):
277 args, kwargs = pm[-2:]
279 self.client.container_head(*(pm + args), **kwargs)
280 unt, ims, ius = pm[0:3]
281 self.assertEqual(SP.mock_calls[-1], call('until', unt, iff=unt))
282 self.assertEqual(SH.mock_calls[-2:], [
283 call('If-Modified-Since', ims),
284 call('If-Unmodified-Since', ius)])
285 self.assertEqual(head.mock_calls[-1], call(
286 '/%s/%s' % (self.client.account, self.client.container),
288 success=kwargs.pop('success', 204),
291 @patch('%s.set_param' % rest_pkg)
292 @patch('%s.set_header' % rest_pkg)
293 @patch('%s.get' % rest_pkg, return_value=FR())
294 def test_container_get(self, get, SH, SP):
298 (None, 'some/prefix'),
300 (None, '/some/path'),
301 ('json', 'some-format'),
302 ([], ['k1', 'k2', 'k3']),
304 (None, 'unt1l-d473'),
305 (None, 'y37-4n47h3r'),
306 (None, '4n47h3r-d473'),
308 (dict(), dict(success=400), dict(k='v', v='k'))):
309 args, kwargs = pm[-2:]
311 self.client.container_get(*(pm + args), **kwargs)
312 lmt, mrk, prfx, dlm, path, frmt, meta, shr, unt = pm[:-2]
313 exp = [call('limit', lmt, iff=lmt), call('marker', mrk, iff=mrk)]
314 exp += [call('path', path)] if path else [
315 call('prefix', prfx, iff=prfx),
316 call('delimiter', dlm, iff=dlm)]
317 exp += [call('format', frmt, iff=frmt), call('shared', iff=shr)]
319 exp += [call('meta', ','.join(meta))]
320 exp += [call('until', unt, iff=unt)]
321 self.assertEqual(SP.mock_calls[- len(exp):], exp)
323 self.assertEqual(SH.mock_calls[-2:], [
324 call('If-Modified-Since', ims),
325 call('If-Unmodified-Since', ius)])
326 self.assertEqual(get.mock_calls[-1], call(
327 '/%s/%s' % (self.client.account, self.client.container),
329 success=kwargs.pop('success', 200),
332 @patch('%s.set_header' % rest_pkg)
333 @patch('%s.put' % rest_pkg, return_value=FR())
334 def test_container_put(self, put, SH):
337 (None, 'v3r51on1ng'),
338 (dict(), dict(k1='v2'), dict(k2='v2', k3='v3')),
340 (dict(), dict(success=400), dict(k='v', v='k'))):
341 args, kwargs = pm[-2:]
343 self.client.container_put(*(pm + args), **kwargs)
344 quota, versioning, metas = pm[-3:]
346 call('X-Container-Policy-Quota', quota),
347 call('X-Container-Policy-Versioning', versioning)] + [
348 call('X-Container-Meta-%s' % k, v) for k, v in metas.items()]
349 self.assertEqual(SH.mock_calls[- len(exp):], exp)
350 self.assertEqual(put.mock_calls[-1], call(
351 '/%s/%s' % (self.client.account, self.client.container),
353 success=kwargs.pop('success', (201, 202)),
356 @patch('%s.set_param' % rest_pkg)
357 @patch('%s.set_header' % rest_pkg)
358 @patch('%s.post' % rest_pkg, return_value=FR())
359 def test_container_post(self, post, SH, SP):
362 ('json', 'some-format'),
364 (None, 'v3r51on1ng'),
365 (dict(), dict(k1='v2'), dict(k2='v2', k3='v3')),
366 (None, 'content-type'),
368 (None, 'transfer-encoding'),
370 (dict(), dict(success=400), dict(k='v', v='k'))):
371 args, kwargs = pm[-2:]
373 self.client.container_post(*(pm + args), **kwargs)
375 self.assertEqual(SP.mock_calls[-2:], [
376 call('update', iff=upd),
377 call('format', frmt, iff=frmt)])
378 qta, vrs, metas, ctype, clen, trenc = pm[2:]
379 prfx = 'X-Container-Meta-'
381 call('X-Container-Policy-Quota', qta),
382 call('X-Container-Policy-Versioning', vrs)] + [
383 call('%s%s' % (prfx, k), v) for k, v in metas.items()] + [
384 call('Content-Type', ctype),
385 call('Content-Length', clen),
386 call('Transfer-Encoding', trenc)]
387 self.assertEqual(SH.mock_calls[- len(exp):], exp)
389 self.assertEqual(post.mock_calls[-1], call(
390 '/%s/%s' % (self.client.account, self.client.container),
392 success=kwargs.pop('success', 202),
395 @patch('%s.set_param' % rest_pkg)
396 @patch('%s.delete' % rest_pkg, return_value=FR())
397 def test_container_delete(self, delete, SP):
402 (dict(), dict(success=400), dict(k='v', v='k'))):
403 args, kwargs = pm[-2:]
405 self.client.container_delete(*(pm + args), **kwargs)
407 self.assertEqual(SP.mock_calls[-2:], [
408 call('until', unt, iff=unt),
409 call('delimiter', dlm, iff=dlm)])
410 self.assertEqual(delete.mock_calls[-1], call(
411 '/%s/%s' % (self.client.account, self.client.container),
413 success=kwargs.pop('success', 204),
416 @patch('%s.set_param' % rest_pkg)
417 @patch('%s.set_header' % rest_pkg)
418 @patch('%s.head' % rest_pkg, return_value=FR())
419 def test_object_head(self, head, SH, SP):
424 (None, '1f-m0d-51nc3'),
425 (None, '1f-unm0d-51nc3'),
427 (dict(), dict(success=400), dict(k='v', v='k'))):
428 args, kwargs = pm[-2:]
430 self.client.object_head(obj, *(pm + args), **kwargs)
431 vrs, etag, netag, ims, ius = pm[:5]
434 call('version', vrs, iff=vrs))
435 self.assertEqual(SH.mock_calls[-4:], [
436 call('If-Match', etag),
437 call('If-None-Match', netag),
438 call('If-Modified-Since', ims),
439 call('If-Unmodified-Since', ius)])
440 acc, cont = self.client.account, self.client.container
441 self.assertEqual(head.mock_calls[-1], call(
442 '/%s/%s/%s' % (acc, cont, obj),
444 success=kwargs.pop('success', 200),
447 @patch('%s.set_param' % rest_pkg)
448 @patch('%s.set_header' % rest_pkg)
449 @patch('%s.get' % rest_pkg, return_value=FR())
450 def test_object_get(self, get, SH, SP):
455 (None, 'range=74-63'),
462 (dict(), dict(success=400), dict(k='v', v='k'))):
463 args, kwargs = pm[-2:]
465 self.client.object_get(obj, *(pm + args), **kwargs)
466 format, hashmap, version = pm[:3]
467 self.assertEqual(SP.mock_calls[-3:], [
468 call('format', format, iff=format),
469 call('hashmap', hashmap, iff=hashmap),
470 call('version', version, iff=version)])
471 rng, ifrng, im, inm, ims, ius = pm[-6:]
472 self.assertEqual(SH.mock_calls[-6:], [
474 call('If-Range', '', ifrng and rng),
475 call('If-Match', im),
476 call('If-None-Match', inm),
477 call('If-Modified-Since', ims),
478 call('If-Unmodified-Since', ius)])
479 acc, cont = self.client.account, self.client.container
480 self.assertEqual(get.mock_calls[-1], call(
481 '/%s/%s/%s' % (acc, cont, obj),
483 success=kwargs.pop('success', 200),
486 @patch('%s.set_param' % rest_pkg)
487 @patch('%s.set_header' % rest_pkg)
488 @patch('%s.put' % rest_pkg, return_value=FR())
489 def test_object_put(self, put, SH, SP):
494 (dict(), dict(read=['u1', 'g2'], write=['u1'])),
496 (dict(), dict(k2='v2', k3='v3')),
498 (dict(), dict(success=400), dict(k='v', v='k'))):
499 args, kwargs = pm[-2:]
502 for i in range(len(terms)):
504 terms[i] = 'val_%s' % randint(13, 1024)
505 self.client.object_put(
507 *(pm[:3] + tuple(terms) + pm[3:] + args),
509 format, hashmap, delimiter = pm[:3]
510 self.assertEqual(SP.mock_calls[-3:], [
511 call('format', format, iff=format),
512 call('hashmap', hashmap, iff=hashmap),
513 call('delimiter', delimiter, iff=delimiter)])
515 im, inm, etag, clen, ctype, trenc,
516 cp, mv, srcacc, srcvrs, conenc, condis, mnf) = terms
517 perms, public, metas = pm[3:]
519 call('If-Match', im),
520 call('If-None-Match', inm),
522 call('Content-Length', clen),
523 call('Content-Type', ctype),
524 call('Transfer-Encoding', trenc),
525 call('X-Copy-From', cp),
526 call('X-Move-From', mv),
527 call('X-Source-Account', srcacc),
528 call('X-Source-Version', srcvrs),
529 call('Content-Encoding', conenc),
530 call('Content-Disposition', condis),
531 call('X-Object-Manifest', mnf)]
534 for ptype, pval in perms.items():
536 perm_str += ';' if perm_str else ''
537 perm_str += '%s=%s' % (ptype, ','.join(pval))
538 exp += [call('X-Object-Sharing', perm_str)]
539 exp += [call('X-Object-Public', public)]
540 for k, v in metas.items():
541 exp += [call('X-Object-Meta-%s' % k, v)]
542 self.assertEqual(SH.mock_calls[- len(exp):], exp)
543 acc, cont = self.client.account, self.client.container
544 self.assertEqual(put.mock_calls[-1], call(
545 '/%s/%s/%s' % (acc, cont, obj),
547 success=kwargs.pop('success', 201),
550 @patch('%s.set_param' % rest_pkg)
551 @patch('%s.set_header' % rest_pkg)
552 @patch('%s.copy' % rest_pkg, return_value=FR())
553 def test_object_copy(self, copy, SH, SP):
559 (None, 'ifnonematch'),
560 (None, 'destinationaccount'),
561 (None, 'content-type'),
562 (None, 'content-encoding'),
563 (None, 'content-disp'),
564 (None, 'source-version'),
565 (dict(), dict(read=['u1', 'g2'], write=['u1'])),
567 (dict(), dict(k2='v2', k3='v3')),
569 (dict(), dict(success=400), dict(k='v', v='k'))):
570 args, kwargs = pm[-2:]
572 self.client.object_copy(obj, dest, *(pm + args), **kwargs)
574 self.assertEqual(SP.mock_calls[-2:], [
575 call('format', format, iff=format),
576 call('ignore_content_type', iff=ict)])
577 im, inm, da, ct, ce, cd, sv, perms, public, metas = pm[2:]
578 exp = [call('If-Match', im),
579 call('If-None-Match', inm),
580 call('Destination', dest),
581 call('Destination-Account', da),
582 call('Content-Type', ct),
583 call('Content-Encoding', ce),
584 call('Content-Disposition', cd),
585 call('X-Source-Version', sv)]
588 for ptype, pval in perms.items():
590 perm_str += ';' if perm_str else ''
591 perm_str += '%s=%s' % (ptype, ','.join(pval))
592 exp += [call('X-Object-Sharing', perm_str)]
593 exp += [call('X-Object-Public', public)]
594 for k, v in metas.items():
595 exp += [call('X-Object-Meta-%s' % k, v)]
596 self.assertEqual(SH.mock_calls[- len(exp):], exp)
597 acc, cont = self.client.account, self.client.container
598 self.assertEqual(copy.mock_calls[-1], call(
599 '/%s/%s/%s' % (acc, cont, obj),
601 success=kwargs.pop('success', 201),
605 class Pithos(TestCase):
609 def _create_temp_file(self, num_of_blocks):
610 self.files.append(NamedTemporaryFile())
611 tmpFile = self.files[-1]
612 file_size = num_of_blocks * 4 * 1024 * 1024
613 print('\n\tCreate tmp file')
614 tmpFile.write(urandom(file_size))
620 def assert_dicts_are_equal(self, d1, d2):
621 for k, v in d1.items():
622 self.assertTrue(k in d2)
623 if isinstance(v, dict):
624 self.assert_dicts_are_equal(v, d2[k])
626 self.assertEqual(unicode(v), unicode(d2[k]))
629 self.url = 'https://www.example.com/pithos'
630 self.token = 'p17h0570k3n'
631 self.client = PithosClient(self.url, self.token)
632 self.client.account = user_id
633 self.client.container = 'c0nt@1n3r_i'
643 # Pithos+ methods that extend storage API
645 @patch('%s.account_head' % pithos_pkg, return_value=FR())
646 def test_get_account_info(self, AH):
647 FR.headers = account_info
648 for until in (None, 'un71L-d473'):
649 r = self.client.get_account_info(until=until)
650 self.assert_dicts_are_equal(r, account_info)
651 self.assertEqual(AH.mock_calls[-1], call(until=until))
653 self.assertRaises(ClientError, self.client.get_account_info)
655 @patch('%s.account_post' % pithos_pkg, return_value=FR())
656 def test_del_account_meta(self, AP):
657 keys = ['k1', 'k2', 'k3']
659 self.client.del_account_meta(key)
662 call(update=True, metadata={key: ''}))
664 @patch('%s.container_head' % pithos_pkg, return_value=FR())
665 def test_get_container_info(self, CH):
666 FR.headers = container_info
667 r = self.client.get_container_info()
668 self.assert_dicts_are_equal(r, container_info)
670 r = self.client.get_container_info(until=u)
671 self.assertEqual(CH.mock_calls, [call(until=None), call(until=u)])
673 @patch('%s.account_get' % pithos_pkg, return_value=FR())
674 def test_list_containers(self, get):
675 FR.json = container_list
676 r = self.client.list_containers()
677 get.assert_called_once_with()
678 for i in range(len(r)):
679 self.assert_dicts_are_equal(r[i], container_list[i])
681 @patch('%s.get_container_info' % pithos_pkg, return_value=container_info)
682 @patch('%s.container_post' % pithos_pkg, return_value=FR())
683 @patch('%s.object_put' % pithos_pkg, return_value=FR())
684 def test_upload_object(self, OP, CP, GCI):
686 tmpFile = self._create_temp_file(num_of_blocks)
689 self.client.upload_object(obj, tmpFile)
690 self.assertEqual(GCI.mock_calls[-1], call())
691 [call1, call2] = OP.mock_calls
693 (args1, kwargs1) = call1[1:3]
694 (args2, kwargs2) = call2[1:3]
695 self.assertEqual(args1, (obj,))
701 hashes=['s0m3h@5h'] * num_of_blocks,
702 bytes=num_of_blocks * 4 * 1024 * 1024),
704 content_encoding=None,
705 content_type='application/octet-stream',
706 content_disposition=None,
709 for k, v in expected1.items():
711 self.assertEqual(len(v['hashes']), len(kwargs1[k]['hashes']))
712 self.assertEqual(v['bytes'], kwargs1[k]['bytes'])
714 self.assertEqual(v, kwargs1[k])
716 (args2, kwargs2) = call2[1:3]
717 self.assertEqual(args2, (obj,))
720 hashes=['s0m3h@5h'] * num_of_blocks,
721 bytes=num_of_blocks * 4 * 1024 * 1024),
722 content_type='application/octet-stream',
726 for k, v in expected2.items():
728 self.assertEqual(len(v['hashes']), len(kwargs2[k]['hashes']))
729 self.assertEqual(v['bytes'], kwargs2[k]['bytes'])
731 self.assertEqual(v, kwargs2[k])
737 from progress.bar import ShadyBar
738 blck_bar = ShadyBar('Mock blck calc.')
739 upld_bar = ShadyBar('Mock uplds')
744 if blck_bar and upld_bar:
747 for i in blck_bar.iter(range(n)):
752 for i in upld_bar.iter(range(n)):
757 self.client.upload_object(
759 hash_cb=blck_gen, upload_cb=upld_gen)
761 for i, c in enumerate(OP.mock_calls[-mock_offset:]):
762 self.assertEqual(OP.mock_calls[i], c)
767 sharing = dict(read=['u1', 'g1', 'u2'], write=['u1'])
768 self.client.upload_object(obj, tmpFile,
769 content_type=ctype, sharing=sharing)
770 self.assertEqual(OP.mock_calls[-1][2]['content_type'], ctype)
771 self.assert_dicts_are_equal(
772 OP.mock_calls[-2][2]['permissions'],
780 content_disposition=ctype + 'd15p051710n',
782 content_encoding='802.11')
783 self.client.upload_object(obj, tmpFile, **kwargs)
784 for arg, val in kwargs.items():
785 self.assertEqual(OP.mock_calls[-2][2][arg], val)
787 def test_get_object_info(self):
788 FR.headers = object_info
791 PithosClient, 'object_head',
792 return_value=FR()) as head:
793 r = self.client.get_object_info(obj)
794 self.assertEqual(r, object_info)
795 r = self.client.get_object_info(obj, version=version)
796 self.assertEqual(head.mock_calls, [
797 call(obj, version=None),
798 call(obj, version=version)])
800 PithosClient, 'object_head',
801 side_effect=ClientError('Obj not found', 404)):
804 self.client.get_object_info,
805 obj, version=version)
807 @patch('%s.get_object_info' % pithos_pkg, return_value=object_info)
808 def test_get_object_meta(self, GOI):
809 for version in (None, 'v3r510n'):
810 r = self.client.get_object_meta(obj, version)
811 for k in [k for k in object_info if k.startswith('x-object-meta')]:
812 self.assertEqual(r.pop(k), object_info[k])
813 self.assertFalse(len(r))
814 self.assertEqual(GOI.mock_calls[-1], call(obj, version=version))
816 @patch('%s.object_post' % pithos_pkg, return_value=FR())
817 def test_del_object_meta(self, post):
818 metakey = '50m3m3t4k3y'
819 self.client.del_object_meta(obj, metakey)
820 post.assert_called_once_with(obj, update=True, metadata={metakey: ''})
822 @patch('%s.object_put' % pithos_pkg, return_value=FR())
823 def test_copy_object(self, put):
824 src_cont = 'src-c0nt41n3r'
826 dst_cont = 'dst-c0nt41n3r'
833 copy_from='/%s/%s' % (src_cont, src_obj),
838 self.client.copy_object(src_cont, src_obj, dst_cont)
839 self.assertEqual(put.mock_calls[-1], expected)
840 self.client.copy_object(src_cont, src_obj, dst_cont, dst_obj)
841 self.assertEqual(put.mock_calls[-1][1], (dst_obj,))
843 source_version='src-v3r510n',
844 source_account='src-4cc0un7',
846 content_type='c0n73n7Typ3',
848 self.client.copy_object(src_cont, src_obj, dst_cont, **kwargs)
849 for k, v in kwargs.items():
850 self.assertEqual(v, put.mock_calls[-1][2][k])
852 @patch('%s.object_put' % pithos_pkg, return_value=FR())
853 def test_move_object(self, put):
854 src_cont = 'src-c0nt41n3r'
856 dst_cont = 'dst-c0nt41n3r'
863 move_from='/%s/%s' % (src_cont, src_obj),
868 self.client.move_object(src_cont, src_obj, dst_cont)
869 self.assertEqual(put.mock_calls[-1], expected)
870 self.client.move_object(src_cont, src_obj, dst_cont, dst_obj)
871 self.assertEqual(put.mock_calls[-1][1], (dst_obj,))
873 source_version='src-v3r510n',
874 source_account='src-4cc0un7',
876 content_type='c0n73n7Typ3',
878 self.client.move_object(src_cont, src_obj, dst_cont, **kwargs)
879 for k, v in kwargs.items():
880 self.assertEqual(v, put.mock_calls[-1][2][k])
882 # Pithos+ only methods
884 @patch('%s.container_delete' % pithos_pkg, return_value=FR())
885 def test_purge_container(self, CD):
886 self.client.purge_container()
887 self.assertTrue('until' in CD.mock_calls[-1][2])
888 cont = self.client.container
889 self.client.purge_container('another-container')
890 self.assertEqual(self.client.container, cont)
892 @patch('%s.object_put' % pithos_pkg, return_value=FR())
893 def test_upload_object_unchunked(self, put):
895 tmpFile = self._create_temp_file(num_of_blocks)
898 data=num_of_blocks * 4 * 1024 * 1024,
900 content_encoding='some content_encoding',
901 content_type='some content-type',
902 content_disposition='some content_disposition',
904 permissions=dict(read=['u1', 'g1', 'u2'], write=['u1']))
905 self.client.upload_object_unchunked(obj, tmpFile)
906 self.assertEqual(put.mock_calls[-1][1], (obj,))
908 sorted(put.mock_calls[-1][2].keys()),
909 sorted(expected.keys()))
910 kwargs = dict(expected)
911 kwargs.pop('success')
912 kwargs['size'] = kwargs.pop('data')
913 kwargs['sharing'] = kwargs.pop('permissions')
915 self.client.upload_object_unchunked(obj, tmpFile, **kwargs)
916 pmc = put.mock_calls[-1][2]
917 for k, v in expected.items():
919 self.assertEqual(len(pmc[k]), v)
921 self.assertEqual(pmc[k], v)
924 self.client.upload_object_unchunked,
925 obj, tmpFile, withHashFile=True)
927 @patch('%s.object_put' % pithos_pkg, return_value=FR())
928 def test_create_object_by_manifestation(self, put):
929 manifest = '%s/%s' % (self.client.container, obj)
932 content_encoding='some content_encoding',
933 content_type='some content-type',
934 content_disposition='some content_disposition',
936 sharing=dict(read=['u1', 'g1', 'u2'], write=['u1']))
937 self.client.create_object_by_manifestation(obj)
938 expected = dict(content_length=0, manifest=manifest)
940 expected['permissions' if k == 'sharing' else k] = None
941 self.assertEqual(put.mock_calls[-1], call(obj, **expected))
942 self.client.create_object_by_manifestation(obj, **kwargs)
943 expected.update(kwargs)
944 expected['permissions'] = expected.pop('sharing')
945 self.assertEqual(put.mock_calls[-1], call(obj, **expected))
947 @patch('%s.get_object_hashmap' % pithos_pkg, return_value=object_hashmap)
948 @patch('%s.object_get' % pithos_pkg, return_value=FR())
949 def test_download_object(self, GET, GOH):
951 tmpFile = self._create_temp_file(num_of_blocks)
952 FR.content = tmpFile.read(4 * 1024 * 1024)
953 tmpFile = self._create_temp_file(num_of_blocks)
954 num_of_blocks = len(object_hashmap['hashes'])
959 if_match='if and only if',
960 if_none_match='if and only not',
961 if_modified_since='what if not?',
962 if_unmodified_since='this happens if not!',
963 async_headers=dict(Range='bytes=0-88888888'))
965 self.client.download_object(obj, tmpFile)
966 self.assertEqual(len(GET.mock_calls), num_of_blocks)
967 self.assertEqual(GET.mock_calls[-1][1], (obj,))
968 for k, v in kwargs.items():
969 if k == 'async_headers':
970 self.assertTrue('Range' in GET.mock_calls[-1][2][k])
971 elif k in ('resume', 'range_str'):
974 self.assertEqual(GET.mock_calls[-1][2][k], None)
976 # Check ranges are consecutive
979 for c in GET.mock_calls:
980 rng_str = c[2]['async_headers']['Range']
981 (start, rng_str) = rng_str.split('=')
982 (start, end) = rng_str.split('-')
986 for i, start in enumerate(sorted(starts)):
988 int(ends[i - 1]) == int(start) - 1
992 from progress.bar import ShadyBar
993 dl_bar = ShadyBar('Mock dl')
1000 for i in dl_bar.iter(range(n)):
1005 self.client.download_object(obj, tmpFile, download_cb=blck_gen)
1006 self.assertEqual(len(GET.mock_calls), 2 * num_of_blocks)
1009 kwargs.pop('async_headers')
1010 kwargs.pop('resume')
1011 self.client.download_object(obj, tmpFile, **kwargs)
1012 for k, v in kwargs.items():
1013 if k == 'range_str':
1015 GET.mock_calls[-1][2]['data_range'],
1018 self.assertEqual(GET.mock_calls[-1][2][k], v)
1020 # ALl options on no tty
1026 tmpFile.isatty = foo
1027 self.client.download_object(obj, tmpFile, **kwargs)
1028 for k, v in kwargs.items():
1029 if k == 'range_str':
1030 self.assertTrue('data_range' in GET.mock_calls[-1][2])
1032 self.assertEqual(GET.mock_calls[-1][2][k], v)
1034 def test_get_object_hashmap(self):
1035 FR.json = object_hashmap
1036 for empty in (304, 412):
1038 PithosClient, 'object_get',
1039 side_effect=ClientError('Empty', status=empty)):
1040 r = self.client.get_object_hashmap(obj)
1041 self.assertEqual(r, {})
1047 if_etag_not_match=None,
1048 if_modified_since=None,
1049 if_unmodified_since=None)
1051 version='s0m3v3r51on',
1052 if_match='if match',
1053 if_none_match='if non match',
1054 if_modified_since='some date here',
1055 if_unmodified_since='some date here',
1058 PithosClient, 'object_get',
1059 return_value=FR()) as get:
1060 r = self.client.get_object_hashmap(obj)
1061 self.assertEqual(r, object_hashmap)
1062 self.assertEqual(get.mock_calls[-1], call(obj, **exp_args))
1063 r = self.client.get_object_hashmap(obj, **kwargs)
1064 exp_args['if_etag_match'] = kwargs.pop('if_match')
1065 exp_args['if_etag_not_match'] = kwargs.pop('if_none_match')
1066 exp_args.update(kwargs)
1067 self.assertEqual(get.mock_calls[-1], call(obj, **exp_args))
1069 @patch('%s.account_post' % pithos_pkg, return_value=FR())
1070 def test_set_account_group(self, post):
1071 (group, usernames) = ('aU53rGr0up', ['u1', 'u2', 'u3'])
1072 self.client.set_account_group(group, usernames)
1073 post.assert_called_once_with(update=True, groups={group: usernames})
1075 @patch('%s.account_post' % pithos_pkg, return_value=FR())
1076 def test_del_account_group(self, post):
1077 group = 'aU53rGr0up'
1078 self.client.del_account_group(group)
1079 post.assert_called_once_with(update=True, groups={group: []})
1081 @patch('%s.get_account_info' % pithos_pkg, return_value=account_info)
1082 def test_get_account_quota(self, GAI):
1083 key = 'x-account-policy-quota'
1084 r = self.client.get_account_quota()
1085 GAI.assert_called_once_with()
1086 self.assertEqual(r[key], account_info[key])
1088 @patch('%s.get_account_info' % pithos_pkg, return_value=account_info)
1089 def test_get_account_versioning(self, GAI):
1090 key = 'x-account-policy-versioning'
1091 r = self.client.get_account_versioning()
1092 GAI.assert_called_once_with()
1093 self.assertEqual(r[key], account_info[key])
1095 def test_get_account_meta(self):
1096 key = 'x-account-meta-'
1098 PithosClient, 'get_account_info',
1099 return_value=account_info):
1100 r = self.client.get_account_meta()
1101 keys = [k for k in r if k.startswith(key)]
1102 self.assertFalse(keys)
1103 acc_info = dict(account_info)
1104 acc_info['%sk1' % key] = 'v1'
1105 acc_info['%sk2' % key] = 'v2'
1106 acc_info['%sk3' % key] = 'v3'
1108 PithosClient, 'get_account_info',
1109 return_value=acc_info):
1110 r = self.client.get_account_meta()
1111 for k in [k for k in acc_info if k.startswith(key)]:
1112 self.assertEqual(r[k], acc_info[k])
1114 def test_get_account_group(self):
1115 key = 'x-account-group-'
1117 PithosClient, 'get_account_info',
1118 return_value=account_info):
1119 r = self.client.get_account_group()
1120 keys = [k for k in r if k.startswith(key)]
1121 self.assertFalse(keys)
1122 acc_info = dict(account_info)
1123 acc_info['%sk1' % key] = 'g1'
1124 acc_info['%sk2' % key] = 'g2'
1125 acc_info['%sk3' % key] = 'g3'
1127 PithosClient, 'get_account_info',
1128 return_value=acc_info):
1129 r = self.client.get_account_group()
1130 for k in [k for k in acc_info if k.startswith(key)]:
1131 self.assertEqual(r[k], acc_info[k])
1133 @patch('%s.account_post' % pithos_pkg, return_value=FR())
1134 def test_set_account_meta(self, post):
1135 metas = dict(k1='v1', k2='v2', k3='v3')
1136 self.client.set_account_meta(metas)
1137 post.assert_called_once_with(update=True, metadata=metas)
1139 @patch('%s.account_post' % pithos_pkg, return_value=FR())
1140 def test_set_account_quota(self, post):
1142 self.client.set_account_quota(qu)
1143 post.assert_called_once_with(update=True, quota=qu)
1145 @patch('%s.account_post' % pithos_pkg, return_value=FR())
1146 def test_set_account_versioning(self, post):
1147 vrs = 'n3wV3r51on1ngTyp3'
1148 self.client.set_account_versioning(vrs)
1149 post.assert_called_once_with(update=True, versioning=vrs)
1151 @patch('%s.container_delete' % pithos_pkg, return_value=FR())
1152 def test_del_container(self, delete):
1154 dict(delimiter=None, until=None),
1155 dict(delimiter='X', until='50m3d473')):
1156 self.client.del_container(**kwarg)
1157 expected = dict(kwarg)
1158 expected['success'] = (204, 404, 409)
1159 self.assertEqual(delete.mock_calls[-1], call(**expected))
1160 for status_code in (404, 409):
1161 FR.status_code = status_code
1162 self.assertRaises(ClientError, self.client.del_container)
1164 @patch('%s.get_container_info' % pithos_pkg, return_value=container_info)
1165 def test_get_container_versioning(self, GCI):
1166 key = 'x-container-policy-versioning'
1168 bu_cnt = self.client.container
1169 for container in (None, cont):
1170 r = self.client.get_container_versioning(container=container)
1171 self.assertEqual(r[key], container_info[key])
1172 self.assertEqual(GCI.mock_calls[-1], call())
1173 self.assertEqual(bu_cnt, self.client.container)
1175 @patch('%s.get_container_info' % pithos_pkg, return_value=container_info)
1176 def test_get_container_quota(self, GCI):
1177 key = 'x-container-policy-quota'
1179 bu_cnt = self.client.container
1180 for container in (None, cont):
1181 r = self.client.get_container_quota(container=container)
1182 self.assertEqual(r[key], container_info[key])
1183 self.assertEqual(GCI.mock_calls[-1], call())
1184 self.assertEqual(bu_cnt, self.client.container)
1186 def test_get_container_meta(self):
1187 somedate = '50m3d473'
1188 key = 'x-container-meta'
1189 metaval = '50m3m374v41'
1190 container_plus = dict(container_info)
1191 container_plus[key] = metaval
1192 for ret in ((container_info, {}), (container_plus, {key: metaval})):
1195 'get_container_info',
1196 return_value=ret[0]) as GCI:
1197 for until in (None, somedate):
1198 r = self.client.get_container_meta(until=until)
1199 self.assertEqual(r, ret[1])
1200 self.assertEqual(GCI.mock_calls[-1], call(until=until))
1202 def test_get_container_object_meta(self):
1203 somedate = '50m3d473'
1204 key = 'x-container-object-meta'
1205 metaval = '50m3m374v41'
1206 container_plus = dict(container_info)
1207 container_plus[key] = metaval
1209 (container_info, {key: ''}),
1210 (container_plus, {key: metaval})):
1213 'get_container_info',
1214 return_value=ret[0]) as GCI:
1215 for until in (None, somedate):
1216 r = self.client.get_container_object_meta(until=until)
1217 self.assertEqual(r, ret[1])
1218 self.assertEqual(GCI.mock_calls[-1], call(until=until))
1220 @patch('%s.container_post' % pithos_pkg, return_value=FR())
1221 def test_set_container_meta(self, post):
1222 metas = dict(k1='v1', k2='v2', k3='v3')
1223 self.client.set_container_meta(metas)
1224 post.assert_called_once_with(update=True, metadata=metas)
1226 @patch('%s.container_post' % pithos_pkg, return_value=FR())
1227 def test_del_container_meta(self, AP):
1228 self.client.del_container_meta('somekey')
1229 AP.assert_called_once_with(update=True, metadata={'somekey': ''})
1231 @patch('%s.container_post' % pithos_pkg, return_value=FR())
1232 def test_set_container_quota(self, post):
1234 self.client.set_container_quota(qu)
1235 post.assert_called_once_with(update=True, quota=qu)
1237 @patch('%s.container_post' % pithos_pkg, return_value=FR())
1238 def test_set_container_versioning(self, post):
1239 vrs = 'n3wV3r51on1ngTyp3'
1240 self.client.set_container_versioning(vrs)
1241 post.assert_called_once_with(update=True, versioning=vrs)
1243 @patch('%s.object_delete' % pithos_pkg, return_value=FR())
1244 def test_del_object(self, delete):
1246 dict(delimiter=None, until=None),
1247 dict(delimiter='X', until='50m3d473')):
1248 self.client.del_object(obj, **kwarg)
1249 self.assertEqual(delete.mock_calls[-1], call(obj, **kwarg))
1251 @patch('%s.object_post' % pithos_pkg, return_value=FR())
1252 def test_set_object_meta(self, post):
1253 metas = dict(k1='v1', k2='v2', k3='v3')
1256 self.client.set_object_meta,
1257 obj, 'Non dict arg')
1258 self.client.set_object_meta(obj, metas)
1259 post.assert_called_once_with(obj, update=True, metadata=metas)
1261 @patch('%s.object_post' % pithos_pkg, return_value=FR())
1262 def test_publish_object(self, post):
1263 oinfo = dict(object_info)
1265 oinfo['x-object-public'] = val
1267 PithosClient, 'get_object_info',
1268 return_value=oinfo) as GOF:
1269 r = self.client.publish_object(obj)
1271 post.mock_calls[-1],
1272 call(obj, public=True, update=True))
1273 self.assertEqual(GOF.mock_calls[-1], call(obj))
1274 self.assertEqual(r, '%s%s' % (self.url[:-6], val))
1276 @patch('%s.object_post' % pithos_pkg, return_value=FR())
1277 def test_unpublish_object(self, post):
1278 self.client.unpublish_object(obj)
1279 post.assert_called_once_with(obj, public=False, update=True)
1281 def test_get_object_sharing(self):
1282 info = dict(object_info)
1283 expected = dict(read='u1,g1,u2', write='u1')
1284 info['x-object-sharing'] = '; '.join(
1285 ['%s=%s' % (k, v) for k, v in expected.items()])
1287 PithosClient, 'get_object_info',
1288 return_value=info) as GOF:
1289 r = self.client.get_object_sharing(obj)
1290 self.assertEqual(GOF.mock_calls[-1], call(obj))
1291 self.assert_dicts_are_equal(r, expected)
1292 info['x-object-sharing'] = '//'.join(
1293 ['%s=%s' % (k, v) for k, v in expected.items()])
1296 self.client.get_object_sharing,
1298 info['x-object-sharing'] = '; '.join(
1299 ['%s:%s' % (k, v) for k, v in expected.items()])
1302 self.client.get_object_sharing,
1304 info['x-object-sharing'] = 'read=%s' % expected['read']
1305 r = self.client.get_object_sharing(obj)
1306 expected.pop('write')
1307 self.assert_dicts_are_equal(r, expected)
1309 @patch('%s.object_post' % pithos_pkg, return_value=FR())
1310 def test_set_object_sharing(self, OP):
1311 read_perms = ['u1', 'g1', 'u2', 'g2']
1312 write_perms = ['u1', 'g1']
1314 dict(read_permition=read_perms, write_permition=write_perms),
1315 dict(read_permition=read_perms),
1316 dict(write_permition=write_perms),
1318 self.client.set_object_sharing(obj, **kwargs)
1319 kwargs['read'] = kwargs.pop('read_permition', '')
1320 kwargs['write'] = kwargs.pop('write_permition', '')
1323 call(obj, update=True, permissions=kwargs))
1325 @patch('%s.set_object_sharing' % pithos_pkg)
1326 def test_del_object_sharing(self, SOS):
1327 self.client.del_object_sharing(obj)
1328 SOS.assert_called_once_with(obj)
1330 @patch('%s.get_container_info' % pithos_pkg, return_value=container_info)
1331 @patch('%s.object_post' % pithos_pkg, return_value=FR())
1332 def test_append_object(self, post, GCI):
1334 tmpFile = self._create_temp_file(num_of_blocks)
1336 file_size = tmpFile.tell()
1337 for turn in range(2):
1341 from progress.bar import ShadyBar
1342 apn_bar = ShadyBar('Mock append')
1349 for i in apn_bar.iter(range(n)):
1356 self.client.append_object(
1358 upload_cb=append_gen if turn else None)
1359 self.assertEqual((turn + 1) * num_of_blocks, len(post.mock_calls))
1360 (args, kwargs) = post.mock_calls[-1][1:3]
1361 self.assertEqual(args, (obj,))
1362 self.assertEqual(kwargs['content_length'], len(kwargs['data']))
1363 fsize = num_of_blocks * int(kwargs['content_length'])
1364 self.assertEqual(fsize, file_size)
1365 self.assertEqual(kwargs['content_range'], 'bytes */*')
1366 exp = 'application/octet-stream'
1367 self.assertEqual(kwargs['content_type'], exp)
1368 self.assertEqual(kwargs['update'], True)
1370 @patch('%s.object_post' % pithos_pkg, return_value=FR())
1371 def test_truncate_object(self, post):
1373 self.client.truncate_object(obj, upto_bytes)
1374 post.assert_called_once_with(
1377 object_bytes=upto_bytes,
1378 content_range='bytes 0-%s/*' % upto_bytes,
1379 content_type='application/octet-stream',
1380 source_object='/%s/%s' % (self.client.container, obj))
1382 @patch('%s.get_container_info' % pithos_pkg, return_value=container_info)
1383 @patch('%s.object_post' % pithos_pkg, return_value=FR())
1384 def test_overwrite_object(self, post, GCI):
1386 tmpFile = self._create_temp_file(num_of_blocks)
1388 file_size = tmpFile.tell()
1389 info = dict(object_info)
1390 info['content-length'] = file_size
1391 block_size = container_info['x-container-block-size']
1393 PithosClient, 'get_object_info',
1394 return_value=info) as GOI:
1397 (file_size + 1, file_size + 2)):
1401 self.client.overwrite_object,
1402 obj, start, end, tmpFile)
1403 for start, end in ((0, 144), (144, 233), (233, file_size)):
1406 exp_size = end - start + 1
1407 if not start or exp_size > block_size:
1409 from progress.bar import ShadyBar
1410 owr_bar = ShadyBar('Mock append')
1417 for i in owr_bar.iter(range(n)):
1421 if exp_size > block_size:
1422 exp_size = exp_size % block_size or block_size
1424 self.client.overwrite_object(obj, start, end, tmpFile, owr_gen)
1425 self.assertEqual(GOI.mock_calls[-1], call(obj))
1426 self.assertEqual(GCI.mock_calls[-1], call())
1427 (args, kwargs) = post.mock_calls[-1][1:3]
1428 self.assertEqual(args, (obj,))
1429 self.assertEqual(len(kwargs['data']), exp_size)
1430 self.assertEqual(kwargs['content_length'], exp_size)
1431 self.assertEqual(kwargs['update'], True)
1432 exp = 'application/octet-stream'
1433 self.assertEqual(kwargs['content_type'], exp)
1435 @patch('%s.set_param' % pithos_pkg)
1436 @patch('%s.get' % pithos_pkg, return_value=FR())
1437 def test_get_sharing_accounts(self, get, SP):
1441 dict(limit='50m3-11m17'),
1443 dict(limit='50m3-11m17', marker='X')):
1444 r = self.client.get_sharing_accounts(**kws)
1445 self.assertEqual(get.mock_calls[-1], call('', success=(200, 204)))
1446 self.assertEqual(SP.mock_calls[-3], call('format', 'json'))
1447 limit, marker = kws.get('limit', None), kws.get('marker', None)
1448 self.assertEqual(SP.mock_calls[-2], call(
1450 iff=limit is not None))
1451 self.assertEqual(SP.mock_calls[-1], call(
1453 iff=marker is not None))
1454 for i in range(len(r)):
1455 self.assert_dicts_are_equal(r[i], sharers[i])
1457 @patch('%s.object_get' % pithos_pkg, return_value=FR())
1458 def test_get_object_versionlist(self, get):
1459 info = dict(object_info)
1460 info['versions'] = ['v1', 'v2']
1462 r = self.client.get_object_versionlist(obj)
1463 get.assert_called_once_with(obj, format='json', version='list')
1464 self.assertEqual(r, info['versions'])
1466 if __name__ == '__main__':
1467 from sys import argv
1468 from kamaki.clients.test import runTestCase
1470 if not argv[1:] or argv[1] == 'Pithos':
1472 runTestCase(Pithos, 'Pithos Client', argv[2:])
1473 if not argv[1:] or argv[1] == 'PithosRest':
1475 runTestCase(PithosRest, 'PithosRest Client', argv[2:])
1477 print('TestCase %s not found' % argv[1])