+ def tearDown(self):
+ FR.headers = dict()
+ FR.json = dict()
+ FR.content = FR.json
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.head' % rest_pkg, return_value=FR())
+ def test_account_head(self, head, SH, SP):
+ for params in product(
+ (None, '50m3-d473'),
+ (None, '50m3-07h3r-d473'),
+ (None, 'y37-4n7h3r-d473'),
+ ((), ('someval',), ('v1', 'v2',)),
+ (dict(), dict(success=200), dict(k='v', v='k'))):
+ args, kwargs = params[-2], params[-1]
+ params = params[:-2]
+ self.client.account_head(*(params + args), **kwargs)
+ unt = params[0]
+ self.assertEqual(SP.mock_calls[-1], call('until', unt, iff=unt))
+ IMS, IUS = params[1], params[2]
+ self.assertEqual(SH.mock_calls[-2:], [
+ call('If-Modified-Since', IMS),
+ call('If-Unmodified-Since', IUS)])
+ self.assertEqual(head.mock_calls[-1], call(
+ '/%s' % self.client.account,
+ *args,
+ success=kwargs.pop('success', 204),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.get' % rest_pkg, return_value=FR())
+ def test_account_get(self, get, SH, SP):
+ keys = ('limit', 'marker', 'format', 'shared', 'until')
+ for params in product(
+ (None, 42),
+ (None, 'X'),
+ ('json', 'xml'),
+ (False, True),
+ (None, '50m3-d473'),
+ (None, '50m3-07h3r-d473'),
+ (None, 'y37-4n7h3r-d473'),
+ ((), ('someval',), ('v1', 'v2',)),
+ (dict(), dict(success=200), dict(k='v', v='k'))):
+ args, kwargs = params[-2], params[-1]
+ params = params[:-2]
+ self.client.account_get(*(params + args), **kwargs)
+ self.assertEqual(SP.mock_calls[-5:],
+ [call(keys[i], iff=X) if (
+ i == 3) else call(
+ keys[i], X, iff=X) for i, X in enumerate(params[:5])])
+ IMS, IUS = params[5], params[6]
+ self.assertEqual(SH.mock_calls[-2:], [
+ call('If-Modified-Since', IMS),
+ call('If-Unmodified-Since', IUS)])
+ self.assertEqual(get.mock_calls[-1], call(
+ '/%s' % self.client.account,
+ *args,
+ success=kwargs.pop('success', (200, 204)),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.post' % rest_pkg, return_value=FR())
+ def test_account_post(self, post, SH, SP):
+ #keys = ('update', 'groups', 'metadata', 'quota', 'versioning')
+ for pm in product(
+ (True, False),
+ ({}, dict(g=['u1', 'u2']), dict(g1=[], g2=['u1', 'u2'])),
+ (None, dict(k1='v1', k2='v2', k3='v2'), dict(k='v')),
+ (None, 42),
+ (None, 'v3r510n1ng'),
+ ((), ('someval',), ('v1', 'v2',)),
+ (dict(), dict(success=200), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.account_post(*(pm + args), **kwargs)
+ upd = pm[0]
+ self.assertEqual(SP.mock_calls[-1], call('update', iff=upd))
+ expected = []
+ if pm[1]:
+ expected += [
+ call('X-Account-Group-%s' % k, v) for k, v in pm[1].items()]
+ if pm[2]:
+ expected = [
+ call('X-Account-Meta-%s' % k, v) for k, v in pm[2].items()]
+ expected = [
+ call('X-Account-Policy-Quota', pm[3]),
+ call('X-Account-Policy-Versioning', pm[4])]
+ self.assertEqual(SH.mock_calls[- len(expected):], expected)
+ self.assertEqual(post.mock_calls[-1], call(
+ '/%s' % self.client.account,
+ *args,
+ success=kwargs.pop('success', 202),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.head' % rest_pkg, return_value=FR())
+ def test_container_head(self, head, SH, SP):
+ for pm in product(
+ (None, '4-d473'),
+ (None, '47h3r-d473'),
+ (None, 'y37-4n47h3r'),
+ ((), ('someval',)),
+ (dict(), dict(success=200), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.container_head(*(pm + args), **kwargs)
+ unt, ims, ius = pm[0:3]
+ self.assertEqual(SP.mock_calls[-1], call('until', unt, iff=unt))
+ self.assertEqual(SH.mock_calls[-2:], [
+ call('If-Modified-Since', ims),
+ call('If-Unmodified-Since', ius)])
+ self.assertEqual(head.mock_calls[-1], call(
+ '/%s/%s' % (self.client.account, self.client.container),
+ *args,
+ success=kwargs.pop('success', 204),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.get' % rest_pkg, return_value=FR())
+ def test_container_get(self, get, SH, SP):
+ for pm in product(
+ (None, 42),
+ (None, 'X'),
+ (None, 'some/prefix'),
+ (None, 'delimiter'),
+ (None, '/some/path'),
+ ('json', 'some-format'),
+ ([], ['k1', 'k2', 'k3']),
+ (False, True),
+ (None, 'unt1l-d473'),
+ (None, 'y37-4n47h3r'),
+ (None, '4n47h3r-d473'),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.container_get(*(pm + args), **kwargs)
+ lmt, mrk, prfx, dlm, path, frmt, meta, shr, unt = pm[:-2]
+ exp = [call('limit', lmt, iff=lmt), call('marker', mrk, iff=mrk)]
+ exp += [call('path', path)] if path else [
+ call('prefix', prfx, iff=prfx),
+ call('delimiter', dlm, iff=dlm)]
+ exp += [call('format', frmt, iff=frmt), call('shared', iff=shr)]
+ if meta:
+ exp += [call('meta', ','.join(meta))]
+ exp += [call('until', unt, iff=unt)]
+ self.assertEqual(SP.mock_calls[- len(exp):], exp)
+ ims, ius = pm[-2:]
+ self.assertEqual(SH.mock_calls[-2:], [
+ call('If-Modified-Since', ims),
+ call('If-Unmodified-Since', ius)])
+ self.assertEqual(get.mock_calls[-1], call(
+ '/%s/%s' % (self.client.account, self.client.container),
+ *args,
+ success=kwargs.pop('success', 200),
+ **kwargs))
+
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.put' % rest_pkg, return_value=FR())
+ def test_container_put(self, put, SH):
+ for pm in product(
+ (None, 42),
+ (None, 'v3r51on1ng'),
+ (dict(), dict(k1='v2'), dict(k2='v2', k3='v3')),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.container_put(*(pm + args), **kwargs)
+ quota, versioning, metas = pm[-3:]
+ exp = [
+ call('X-Container-Policy-Quota', quota),
+ call('X-Container-Policy-Versioning', versioning)] + [
+ call('X-Container-Meta-%s' % k, v) for k, v in metas.items()]
+ self.assertEqual(SH.mock_calls[- len(exp):], exp)
+ self.assertEqual(put.mock_calls[-1], call(
+ '/%s/%s' % (self.client.account, self.client.container),
+ *args,
+ success=kwargs.pop('success', (201, 202)),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.post' % rest_pkg, return_value=FR())
+ def test_container_post(self, post, SH, SP):
+ for pm in product(
+ (True, False),
+ ('json', 'some-format'),
+ (None, 'quota'),
+ (None, 'v3r51on1ng'),
+ (dict(), dict(k1='v2'), dict(k2='v2', k3='v3')),
+ (None, 'content-type'),
+ (None, 42),
+ (None, 'transfer-encoding'),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.container_post(*(pm + args), **kwargs)
+ upd, frmt = pm[:2]
+ self.assertEqual(SP.mock_calls[-2:], [
+ call('update', iff=upd),
+ call('format', frmt, iff=frmt)])
+ qta, vrs, metas, ctype, clen, trenc = pm[2:]
+ prfx = 'X-Container-Meta-'
+ exp = [
+ call('X-Container-Policy-Quota', qta),
+ call('X-Container-Policy-Versioning', vrs)] + [
+ call('%s%s' % (prfx, k), v) for k, v in metas.items()] + [
+ call('Content-Type', ctype),
+ call('Content-Length', clen),
+ call('Transfer-Encoding', trenc)]
+ self.assertEqual(SH.mock_calls[- len(exp):], exp)
+ ims, ius = pm[-2:]
+ self.assertEqual(post.mock_calls[-1], call(
+ '/%s/%s' % (self.client.account, self.client.container),
+ *args,
+ success=kwargs.pop('success', 202),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.delete' % rest_pkg, return_value=FR())
+ def test_container_delete(self, delete, SP):
+ for pm in product(
+ (None, 'd473'),
+ (None, 'd3l1m'),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.container_delete(*(pm + args), **kwargs)
+ unt, dlm = pm[-2:]
+ self.assertEqual(SP.mock_calls[-2:], [
+ call('until', unt, iff=unt),
+ call('delimiter', dlm, iff=dlm)])
+ self.assertEqual(delete.mock_calls[-1], call(
+ '/%s/%s' % (self.client.account, self.client.container),
+ *args,
+ success=kwargs.pop('success', 204),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.head' % rest_pkg, return_value=FR())
+ def test_object_head(self, head, SH, SP):
+ for pm in product(
+ (None, 'v3r510n'),
+ (None, '1f-374g'),
+ (None, '1f-n0-74g'),
+ (None, '1f-m0d-51nc3'),
+ (None, '1f-unm0d-51nc3'),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.object_head(obj, *(pm + args), **kwargs)
+ vrs, etag, netag, ims, ius = pm[:5]
+ self.assertEqual(
+ SP.mock_calls[-1],
+ call('version', vrs, iff=vrs))
+ self.assertEqual(SH.mock_calls[-4:], [
+ call('If-Match', etag),
+ call('If-None-Match', netag),
+ call('If-Modified-Since', ims),
+ call('If-Unmodified-Since', ius)])
+ acc, cont = self.client.account, self.client.container
+ self.assertEqual(head.mock_calls[-1], call(
+ '/%s/%s/%s' % (acc, cont, obj),
+ *args,
+ success=kwargs.pop('success', 200),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.get' % rest_pkg, return_value=FR())
+ def test_object_get(self, get, SH, SP):
+ for pm in product(
+ ('json', 'f0rm47'),
+ (False, True),
+ (None, 'v3r510n'),
+ (None, 'range=74-63'),
+ (False, True),
+ (None, '3746'),
+ (None, 'non-3746'),
+ (None, '1f-m0d'),
+ (None, '1f-unm0d'),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.object_get(obj, *(pm + args), **kwargs)
+ format, hashmap, version = pm[:3]
+ self.assertEqual(SP.mock_calls[-3:], [
+ call('format', format, iff=format),
+ call('hashmap', hashmap, iff=hashmap),
+ call('version', version, iff=version)])
+ rng, ifrng, im, inm, ims, ius = pm[-6:]
+ self.assertEqual(SH.mock_calls[-6:], [
+ call('Range', rng),
+ call('If-Range', '', ifrng and rng),
+ call('If-Match', im),
+ call('If-None-Match', inm),
+ call('If-Modified-Since', ims),
+ call('If-Unmodified-Since', ius)])
+ acc, cont = self.client.account, self.client.container
+ self.assertEqual(get.mock_calls[-1], call(
+ '/%s/%s/%s' % (acc, cont, obj),
+ *args,
+ success=kwargs.pop('success', 200),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.put' % rest_pkg, return_value=FR())
+ def test_object_put(self, put, SH, SP):
+ for pm in product(
+ ('json', 'f0rm47'),
+ (False, True),
+ (None, 'delim',),
+ (dict(), dict(read=['u1', 'g2'], write=['u1'])),
+ (False, True),
+ (dict(), dict(k2='v2', k3='v3')),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ terms = [None] * 13
+ for i in range(len(terms)):
+ if randint(0, 2):
+ terms[i] = 'val_%s' % randint(13, 1024)
+ self.client.object_put(
+ obj,
+ *(pm[:3] + tuple(terms) + pm[3:] + args),
+ **kwargs)
+ format, hashmap, delimiter = pm[:3]
+ self.assertEqual(SP.mock_calls[-3:], [
+ call('format', format, iff=format),
+ call('hashmap', hashmap, iff=hashmap),
+ call('delimiter', delimiter, iff=delimiter)])
+ (
+ im, inm, etag, clen, ctype, trenc,
+ cp, mv, srcacc, srcvrs, conenc, condis, mnf) = terms
+ perms, public, metas = pm[3:]
+ exp = [
+ call('If-Match', im),
+ call('If-None-Match', inm),
+ call('ETag', etag),
+ call('Content-Length', clen),
+ call('Content-Type', ctype),
+ call('Transfer-Encoding', trenc),
+ call('X-Copy-From', cp),
+ call('X-Move-From', mv),
+ call('X-Source-Account', srcacc),
+ call('X-Source-Version', srcvrs),
+ call('Content-Encoding', conenc),
+ call('Content-Disposition', condis),
+ call('X-Object-Manifest', mnf)]
+ if perms:
+ perm_str = ''
+ for ptype, pval in perms.items():
+ if pval:
+ perm_str += ';' if perm_str else ''
+ perm_str += '%s=%s' % (ptype, ','.join(pval))
+ exp += [call('X-Object-Sharing', perm_str)]
+ exp += [call('X-Object-Public', public)]
+ for k, v in metas.items():
+ exp += [call('X-Object-Meta-%s' % k, v)]
+ self.assertEqual(SH.mock_calls[- len(exp):], exp)
+ acc, cont = self.client.account, self.client.container
+ self.assertEqual(put.mock_calls[-1], call(
+ '/%s/%s/%s' % (acc, cont, obj),
+ *args,
+ success=kwargs.pop('success', 201),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.copy' % rest_pkg, return_value=FR())
+ def test_object_copy(self, copy, SH, SP):
+ dest = 'dest1n4710n'
+ for pm in product(
+ ('json', 'f0rm47'),
+ (False, True),
+ (None, 'ifmatch'),
+ (None, 'ifnonematch'),
+ (None, 'destinationaccount'),
+ (None, 'content-type'),
+ (None, 'content-encoding'),
+ (None, 'content-disp'),
+ (None, 'source-version'),
+ (dict(), dict(read=['u1', 'g2'], write=['u1'])),
+ (False, True),
+ (dict(), dict(k2='v2', k3='v3')),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.object_copy(obj, dest, *(pm + args), **kwargs)
+ format, ict = pm[:2]
+ self.assertEqual(SP.mock_calls[-2:], [
+ call('format', format, iff=format),
+ call('ignore_content_type', iff=ict)])
+ im, inm, da, ct, ce, cd, sv, perms, public, metas = pm[2:]
+ exp = [call('If-Match', im),
+ call('If-None-Match', inm),
+ call('Destination', dest),
+ call('Destination-Account', da),
+ call('Content-Type', ct),
+ call('Content-Encoding', ce),
+ call('Content-Disposition', cd),
+ call('X-Source-Version', sv)]
+ if perms:
+ perm_str = ''
+ for ptype, pval in perms.items():
+ if pval:
+ perm_str += ';' if perm_str else ''
+ perm_str += '%s=%s' % (ptype, ','.join(pval))
+ exp += [call('X-Object-Sharing', perm_str)]
+ exp += [call('X-Object-Public', public)]
+ for k, v in metas.items():
+ exp += [call('X-Object-Meta-%s' % k, v)]
+ self.assertEqual(SH.mock_calls[- len(exp):], exp)
+ acc, cont = self.client.account, self.client.container
+ self.assertEqual(copy.mock_calls[-1], call(
+ '/%s/%s/%s' % (acc, cont, obj),
+ *args,
+ success=kwargs.pop('success', 201),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.move' % rest_pkg, return_value=FR())
+ def test_object_move(self, move, SH, SP):
+ for pm in product(
+ ('json', 'f0rm47'),
+ (False, True),
+ (None, 'ifmatch'),
+ (None, 'ifnonematch'),
+ (None, 'destination'),
+ (None, 'destinationaccount'),
+ (None, 'content-type'),
+ (None, 'content-encoding'),
+ (None, 'content-disp'),
+ (dict(), dict(read=['u1', 'g2'], write=['u1'])),
+ (False, True),
+ (dict(), dict(k2='v2', k3='v3')),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.object_move(obj, *(pm + args), **kwargs)
+ format, ict = pm[:2]
+ self.assertEqual(SP.mock_calls[-2:], [
+ call('format', format, iff=format),
+ call('ignore_content_type', iff=ict)])
+ im, inm, d, da, ct, ce, cd, perms, public, metas = pm[2:]
+ exp = [call('If-Match', im),
+ call('If-None-Match', inm),
+ call('Destination', d),
+ call('Destination-Account', da),
+ call('Content-Type', ct),
+ call('Content-Encoding', ce),
+ call('Content-Disposition', cd)]
+ if perms:
+ perm_str = ''
+ for ptype, pval in perms.items():
+ if pval:
+ perm_str += ';' if perm_str else ''
+ perm_str += '%s=%s' % (ptype, ','.join(pval))
+ exp += [call('X-Object-Sharing', perm_str)]
+ exp += [call('X-Object-Public', public)]
+ for k, v in metas.items():
+ exp += [call('X-Object-Meta-%s' % k, v)]
+ self.assertEqual(SH.mock_calls[- len(exp):], exp)
+ acc, cont = self.client.account, self.client.container
+ self.assertEqual(move.mock_calls[-1], call(
+ '/%s/%s/%s' % (acc, cont, obj),
+ *args,
+ success=kwargs.pop('success', 201),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.set_header' % rest_pkg)
+ @patch('%s.post' % rest_pkg, return_value=FR())
+ def test_object_post(self, post, SH, SP):
+ for pm in product(
+ ('json', 'f0rm47'),
+ (False, True),
+ (dict(), dict(read=['u1', 'g2'], write=['u1'])),
+ (False, True),
+ (dict(), dict(k2='v2', k3='v3')),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ terms = [None] * 13
+ for i in range(len(terms)):
+ if randint(0, 2):
+ terms[i] = 'val_%s' % randint(13, 1024)
+ self.client.object_post(
+ obj,
+ *(pm[:2] + tuple(terms) + pm[2:] + args),
+ **kwargs)
+ format, update = pm[:2]
+ self.assertEqual(SP.mock_calls[-2:], [
+ call('format', format, iff=format),
+ call('update', iff=update)])
+ (
+ im, inm, clen, ctype, crng, trenc, cenc,
+ condis, srcobj, srcacc, srcvrs, obytes, mnfs) = terms
+ exp = [
+ call('If-Match', im),
+ call('If-None-Match', inm),
+ call('Content-Length', clen, iff=not trenc),
+ call('Content-Type', ctype),
+ call('Content-Range', crng),
+ call('Transfer-Encoding', trenc),
+ call('Content-Encoding', cenc),
+ call('Content-Disposition', condis),
+ call('X-Source-Object', srcobj),
+ call('X-Source-Account', srcacc),
+ call('X-Source-Version', srcvrs),
+ call('X-Object-Bytes', obytes),
+ call('X-Object-Manifest', mnfs)]
+ perms, public, metas = pm[2:]
+ if perms:
+ perm_str = ''
+ for ptype, pval in perms.items():
+ if pval:
+ perm_str += ';' if perm_str else ''
+ perm_str += '%s=%s' % (ptype, ','.join(pval))
+ exp += [call('X-Object-Sharing', perm_str)]
+ exp += [call('X-Object-Public', public)]
+ for k, v in metas.items():
+ exp += [call('X-Object-Meta-%s' % k, v)]
+ self.assertEqual(SH.mock_calls[- len(exp):], exp)
+ acc, cont = self.client.account, self.client.container
+ self.assertEqual(post.mock_calls[-1], call(
+ '/%s/%s/%s' % (acc, cont, obj),
+ *args,
+ success=kwargs.pop('success', (202, 204)),
+ **kwargs))
+
+ @patch('%s.set_param' % rest_pkg)
+ @patch('%s.delete' % rest_pkg, return_value=FR())
+ def test_object_delete(self, delete, SP):
+ for pm in product(
+ (None, 'until'),
+ (None, 'delim'),
+ ((), ('someval',)),
+ (dict(), dict(success=400), dict(k='v', v='k'))):
+ args, kwargs = pm[-2:]
+ pm = pm[:-2]
+ self.client.object_delete(
+ obj,
+ *(pm + args),
+ **kwargs)
+ until, dlm = pm[-2:]
+ self.assertEqual(SP.mock_calls[-2:], [
+ call('until', until, iff=until),
+ call('delimiter', dlm, iff=dlm)])
+ acc, cont = self.client.account, self.client.container
+ self.assertEqual(delete.mock_calls[-1], call(
+ '/%s/%s/%s' % (acc, cont, obj),
+ *args,
+ success=kwargs.pop('success', 204),
+ **kwargs))
+
+
+class PithosClient(TestCase):