Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / test / pithos.py @ c6da1ccc

History | View | Annotate | Download (34.8 kB)

1 24851aa5 Stavros Sachtouris
# Copyright 2013 GRNET S.A. All rights reserved.
2 c1004a00 Stavros Sachtouris
#
3 c1004a00 Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 c1004a00 Stavros Sachtouris
# without modification, are permitted provided that the following
5 c1004a00 Stavros Sachtouris
# conditions are met:
6 c1004a00 Stavros Sachtouris
#
7 c1004a00 Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 c1004a00 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 c1004a00 Stavros Sachtouris
#      disclaimer.
10 c1004a00 Stavros Sachtouris
#
11 c1004a00 Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 c1004a00 Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 c1004a00 Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 c1004a00 Stavros Sachtouris
#      provided with the distribution.
15 c1004a00 Stavros Sachtouris
#
16 c1004a00 Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 c1004a00 Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 c1004a00 Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 c1004a00 Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 c1004a00 Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 c1004a00 Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 c1004a00 Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 c1004a00 Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 c1004a00 Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 c1004a00 Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 c1004a00 Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 c1004a00 Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 c1004a00 Stavros Sachtouris
#
29 c1004a00 Stavros Sachtouris
# The views and conclusions contained in the software and
30 c1004a00 Stavros Sachtouris
# documentation are those of the authors and should not be
31 c1004a00 Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 c1004a00 Stavros Sachtouris
# or implied, of GRNET S.A.
33 c1004a00 Stavros Sachtouris
34 24851aa5 Stavros Sachtouris
from unittest import TestCase
35 c6da1ccc Stavros Sachtouris
from mock import patch, call
36 2a7292f1 Stavros Sachtouris
from tempfile import NamedTemporaryFile
37 2a7292f1 Stavros Sachtouris
from os import urandom
38 c1004a00 Stavros Sachtouris
39 24851aa5 Stavros Sachtouris
from kamaki.clients import ClientError
40 8c599ca2 Stavros Sachtouris
from kamaki.clients.pithos import PithosClient as PC
41 24851aa5 Stavros Sachtouris
from kamaki.clients.connection.kamakicon import KamakiHTTPConnection as C
42 24851aa5 Stavros Sachtouris
43 24851aa5 Stavros Sachtouris
user_id = 'ac0un7-1d-5tr1ng'
44 cb65588d Stavros Sachtouris
obj = 'obj3c7N4m3'
45 24851aa5 Stavros Sachtouris
46 24851aa5 Stavros Sachtouris
account_info = {
47 24851aa5 Stavros Sachtouris
    'content-language': 'en-us',
48 24851aa5 Stavros Sachtouris
    'content-type': 'text/html; charset=utf-8',
49 24851aa5 Stavros Sachtouris
    'date': 'Wed, 06 Mar 2013 13:25:51 GMT',
50 24851aa5 Stavros Sachtouris
    'last-modified': 'Mon, 04 Mar 2013 18:22:31 GMT',
51 24851aa5 Stavros Sachtouris
    'server': 'gunicorn/0.14.5',
52 24851aa5 Stavros Sachtouris
    'vary': 'Accept-Language',
53 24851aa5 Stavros Sachtouris
    'x-account-bytes-used': '751615526',
54 24851aa5 Stavros Sachtouris
    'x-account-container-count': 7,
55 24851aa5 Stavros Sachtouris
    'x-account-policy-quota': 53687091200,
56 24851aa5 Stavros Sachtouris
    'x-account-policy-versioning': 'auto'}
57 d12e8569 Stavros Sachtouris
container_info = {
58 d12e8569 Stavros Sachtouris
    'content-language': 'en-us',
59 d12e8569 Stavros Sachtouris
    'content-type': 'text/html; charset=utf-8',
60 d12e8569 Stavros Sachtouris
    'date': 'Wed, 06 Mar 2013 15:11:05 GMT',
61 d12e8569 Stavros Sachtouris
    'last-modified': 'Wed, 27 Feb 2013 15:56:13 GMT',
62 d12e8569 Stavros Sachtouris
    'server': 'gunicorn/0.14.5',
63 d12e8569 Stavros Sachtouris
    'vary': 'Accept-Language',
64 d12e8569 Stavros Sachtouris
    'x-container-block-hash': 'sha256',
65 d12e8569 Stavros Sachtouris
    'x-container-block-size': 4194304,
66 d12e8569 Stavros Sachtouris
    'x-container-bytes-used': 309528938,
67 d12e8569 Stavros Sachtouris
    'x-container-object-count': 14,
68 d12e8569 Stavros Sachtouris
    'x-container-object-meta': '',
69 d12e8569 Stavros Sachtouris
    'x-container-policy-quota': 53687091200,
70 d12e8569 Stavros Sachtouris
    'x-container-policy-versioning': 'auto'}
71 723e9d47 Stavros Sachtouris
object_info = {
72 723e9d47 Stavros Sachtouris
    'content-language': 'en-us',
73 723e9d47 Stavros Sachtouris
    'content-length': 254965,
74 723e9d47 Stavros Sachtouris
    'content-type': 'application/octet-stream',
75 723e9d47 Stavros Sachtouris
    'date': 'Thu, 07 Mar 2013 13:27:43 GMT',
76 723e9d47 Stavros Sachtouris
    'etag': '',
77 723e9d47 Stavros Sachtouris
    'last-modified': 'Mon, 04 Mar 2013 18:22:31 GMT',
78 723e9d47 Stavros Sachtouris
    'server': 'gunicorn/0.14.5',
79 723e9d47 Stavros Sachtouris
    'vary': 'Accept-Language',
80 723e9d47 Stavros Sachtouris
    'x-object-hash': 'obj3c7h45h1s0bj3c7h45h411r34dY',
81 723e9d47 Stavros Sachtouris
    'x-object-uuid': 'd0c747ca-34bd-49e0-8e98-1d07d8b0cbc7',
82 723e9d47 Stavros Sachtouris
    'x-object-version': '525996',
83 3e2e07be Stavros Sachtouris
    'x-object-version-timestamp': 'Mon, 04 Mar 2013 18:22:31 GMT',
84 3e2e07be Stavros Sachtouris
    'x-object-meta-k1': 'v1',
85 3e2e07be Stavros Sachtouris
    'x-object-meta-k2': 'v2'}
86 efaa8675 Stavros Sachtouris
container_list = [
87 efaa8675 Stavros Sachtouris
    dict(
88 efaa8675 Stavros Sachtouris
        count=2,
89 efaa8675 Stavros Sachtouris
        last_modified="2013-02-27T11:56:09.893033+00:00",
90 efaa8675 Stavros Sachtouris
        bytes=677076979,
91 efaa8675 Stavros Sachtouris
        name="pithos",
92 efaa8675 Stavros Sachtouris
        x_container_policy=dict(quota="21474836480", versioning="auto")),
93 efaa8675 Stavros Sachtouris
    dict(
94 efaa8675 Stavros Sachtouris
        count=0,
95 efaa8675 Stavros Sachtouris
        last_modified="2012-10-23T12:25:17.229187+00:00",
96 efaa8675 Stavros Sachtouris
        bytes=0,
97 efaa8675 Stavros Sachtouris
        name="trash",
98 efaa8675 Stavros Sachtouris
        x_container_policy=dict(quota="21474836480", versioning="auto"))]
99 39c737d4 Stavros Sachtouris
object_list = [
100 39c737d4 Stavros Sachtouris
    dict(hash="",
101 39c737d4 Stavros Sachtouris
        name="The_Secret_Garden.zip",
102 39c737d4 Stavros Sachtouris
        x_object_public="/public/wdp9p",
103 39c737d4 Stavros Sachtouris
        bytes=203304947,
104 39c737d4 Stavros Sachtouris
        x_object_version_timestamp="1360237915.7027509",
105 39c737d4 Stavros Sachtouris
        x_object_uuid="s0m3uu1df0r0bj0n3",
106 39c737d4 Stavros Sachtouris
        last_modified="2013-02-07T11:51:55.702751+00:00",
107 39c737d4 Stavros Sachtouris
        content_type="application/octet-stream",
108 39c737d4 Stavros Sachtouris
        x_object_hash="0afdf29f71cd53126225c3f54ca",
109 39c737d4 Stavros Sachtouris
        x_object_version=17737,
110 39c737d4 Stavros Sachtouris
        x_object_modified_by=user_id),
111 39c737d4 Stavros Sachtouris
    dict(hash="",
112 39c737d4 Stavros Sachtouris
        name="The_Revealed_Garden.zip",
113 39c737d4 Stavros Sachtouris
        x_object_public="/public/wpd7p",
114 39c737d4 Stavros Sachtouris
        bytes=20330947,
115 39c737d4 Stavros Sachtouris
        x_object_version_timestamp="13602915.7027509",
116 39c737d4 Stavros Sachtouris
        x_object_uuid="s0m3uu1df0r0bj70w",
117 39c737d4 Stavros Sachtouris
        last_modified="2013-02-07T11:51:55.702751+00:00",
118 39c737d4 Stavros Sachtouris
        content_type="application/octet-stream",
119 39c737d4 Stavros Sachtouris
        x_object_hash="0afdf29f71cd53126225c3f54ca",
120 39c737d4 Stavros Sachtouris
        x_object_version=17737,
121 39c737d4 Stavros Sachtouris
        x_object_modified_by=user_id)]
122 b4e29772 Stavros Sachtouris
object_hashmap = dict(
123 b4e29772 Stavros Sachtouris
    block_hash="sha256", block_size=4194304, bytes=33554432,
124 b4e29772 Stavros Sachtouris
    hashes=[
125 b4e29772 Stavros Sachtouris
        "4988438cc1c0292c085d289649b28cf547ba3db71c6efaac9f2df7e193d4d0af",
126 b4e29772 Stavros Sachtouris
        "b214244aa56df7d1df7c6cac066e7cef268d9c2beb4dcf7ce68af667b0626f91",
127 b4e29772 Stavros Sachtouris
        "17f365f25e0682565ded30576066bb13377a3d306967e4d74e06bb6bbc20f75f",
128 b4e29772 Stavros Sachtouris
        "2524ae208932669fff89adf8a2fc0df3b67736ca0d3aadce7a2ce640f142af37",
129 b4e29772 Stavros Sachtouris
        "5d807a2129d2fcd3c221c3da418ed52af3fc48d0817b62e0bb437acffccd3514",
130 b4e29772 Stavros Sachtouris
        "609de22ce842d997f645fc49d5f14e0e3766dd51a6cbe66383b2bab82c8dfcd0",
131 b4e29772 Stavros Sachtouris
        "3102851ac168c78be70e35ff5178c7b1ebebd589e5106d565ca1094d1ca8ff59",
132 b4e29772 Stavros Sachtouris
        "bfe306dd24e92a8d85caf7055643f250fd319e8c4cdd4755ddabbf3ff97e83c7"])
133 24851aa5 Stavros Sachtouris
134 24851aa5 Stavros Sachtouris
135 c6da1ccc Stavros Sachtouris
class FR(object):
136 c6da1ccc Stavros Sachtouris
    """FR stands for Fake Response"""
137 c6da1ccc Stavros Sachtouris
    json = dict()
138 c6da1ccc Stavros Sachtouris
    headers = dict()
139 c6da1ccc Stavros Sachtouris
    content = json
140 c6da1ccc Stavros Sachtouris
    status = None
141 c6da1ccc Stavros Sachtouris
    status_code = 200
142 c6da1ccc Stavros Sachtouris
143 c6da1ccc Stavros Sachtouris
    def release(self):
144 c6da1ccc Stavros Sachtouris
        pass
145 24851aa5 Stavros Sachtouris
146 24851aa5 Stavros Sachtouris
147 c6da1ccc Stavros Sachtouris
class Pithos(TestCase):
148 c1004a00 Stavros Sachtouris
149 24851aa5 Stavros Sachtouris
    files = []
150 c1004a00 Stavros Sachtouris
151 cb65588d Stavros Sachtouris
    def _create_temp_file(self, num_of_blocks):
152 2a7292f1 Stavros Sachtouris
        self.files.append(NamedTemporaryFile())
153 2a7292f1 Stavros Sachtouris
        tmpFile = self.files[-1]
154 2a7292f1 Stavros Sachtouris
        file_size = num_of_blocks * 4 * 1024 * 1024
155 2a7292f1 Stavros Sachtouris
        print('\n\tCreate tmp file')
156 2a7292f1 Stavros Sachtouris
        tmpFile.write(urandom(file_size))
157 2a7292f1 Stavros Sachtouris
        tmpFile.flush()
158 2a7292f1 Stavros Sachtouris
        tmpFile.seek(0)
159 2a7292f1 Stavros Sachtouris
        print('\t\tDone')
160 2a7292f1 Stavros Sachtouris
        return tmpFile
161 2a7292f1 Stavros Sachtouris
162 24851aa5 Stavros Sachtouris
    def assert_dicts_are_equal(self, d1, d2):
163 24851aa5 Stavros Sachtouris
        for k, v in d1.items():
164 24851aa5 Stavros Sachtouris
            self.assertTrue(k in d2)
165 24851aa5 Stavros Sachtouris
            if isinstance(v, dict):
166 24851aa5 Stavros Sachtouris
                self.assert_dicts_are_equal(v, d2[k])
167 24851aa5 Stavros Sachtouris
            else:
168 24851aa5 Stavros Sachtouris
                self.assertEqual(unicode(v), unicode(d2[k]))
169 c1004a00 Stavros Sachtouris
170 24851aa5 Stavros Sachtouris
    def setUp(self):
171 24851aa5 Stavros Sachtouris
        self.url = 'https://www.example.com/pithos'
172 24851aa5 Stavros Sachtouris
        self.token = 'p17h0570k3n'
173 8c599ca2 Stavros Sachtouris
        self.client = PC(self.url, self.token)
174 24851aa5 Stavros Sachtouris
        self.client.account = user_id
175 24851aa5 Stavros Sachtouris
        self.client.container = 'c0nt@1n3r_i'
176 c1004a00 Stavros Sachtouris
177 c1004a00 Stavros Sachtouris
    def tearDown(self):
178 c6da1ccc Stavros Sachtouris
        FR.headers = dict()
179 c6da1ccc Stavros Sachtouris
        FR.status_code = 200
180 c6da1ccc Stavros Sachtouris
        FR.json = dict()
181 c6da1ccc Stavros Sachtouris
        FR.content = FR.json
182 cf687343 Stavros Sachtouris
        for f in self.files:
183 cf687343 Stavros Sachtouris
            f.close()
184 24851aa5 Stavros Sachtouris
185 2a7292f1 Stavros Sachtouris
    #  Pithos+ methods that extend storage API
186 2a7292f1 Stavros Sachtouris
187 c6da1ccc Stavros Sachtouris
    @patch('kamaki.clients.Client.set_param')
188 c6da1ccc Stavros Sachtouris
    def test_get_account_info(self, SP):
189 c6da1ccc Stavros Sachtouris
        FR.headers = account_info
190 c6da1ccc Stavros Sachtouris
        FR.status_code = 204
191 c6da1ccc Stavros Sachtouris
        with patch.object(C, 'perform_request', return_value=FR()):
192 24851aa5 Stavros Sachtouris
            r = self.client.get_account_info()
193 24851aa5 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
194 24851aa5 Stavros Sachtouris
            self.assertEqual(self.client.http_client.path, '/%s' % user_id)
195 24851aa5 Stavros Sachtouris
            self.assert_dicts_are_equal(r, account_info)
196 24851aa5 Stavros Sachtouris
            untils = ['date 1', 'date 2', 'date 3']
197 24851aa5 Stavros Sachtouris
            for unt in untils:
198 24851aa5 Stavros Sachtouris
                r = self.client.get_account_info(until=unt)
199 24851aa5 Stavros Sachtouris
                self.assert_dicts_are_equal(r, account_info)
200 24851aa5 Stavros Sachtouris
            for i in range(len(untils)):
201 24851aa5 Stavros Sachtouris
                self.assertEqual(
202 c6da1ccc Stavros Sachtouris
                    PC.set_param.mock_calls[i + 1],
203 24851aa5 Stavros Sachtouris
                    call('until', untils[i], iff=untils[i]))
204 c6da1ccc Stavros Sachtouris
            FR.status_code = 401
205 756e9de9 Stavros Sachtouris
            self.assertRaises(ClientError, self.client.get_account_info)
206 514f9b88 Stavros Sachtouris
207 c6da1ccc Stavros Sachtouris
    @patch('kamaki.clients.Client.set_header')
208 c6da1ccc Stavros Sachtouris
    def test_replace_account_meta(self, SH):
209 c6da1ccc Stavros Sachtouris
        FR.status_code = 202
210 514f9b88 Stavros Sachtouris
        metas = dict(k1='v1', k2='v2', k3='v3')
211 c6da1ccc Stavros Sachtouris
        with patch.object(C, 'perform_request', return_value=FR()):
212 514f9b88 Stavros Sachtouris
            self.client.replace_account_meta(metas)
213 514f9b88 Stavros Sachtouris
            self.assertEqual(self.client.http_client.url, self.url)
214 514f9b88 Stavros Sachtouris
            self.assertEqual(self.client.http_client.path, '/%s' % user_id)
215 514f9b88 Stavros Sachtouris
            prfx = 'X-Account-Meta-'
216 514f9b88 Stavros Sachtouris
            expected = [call('%s%s' % (prfx, k), v) for k, v in metas.items()]
217 8c599ca2 Stavros Sachtouris
            self.assertEqual(PC.set_header.mock_calls, expected)
218 8c599ca2 Stavros Sachtouris
219 8c599ca2 Stavros Sachtouris
    def test_del_account_meta(self):
220 8c599ca2 Stavros Sachtouris
        keys = ['k1', 'k2', 'k3']
221 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'account_post', return_value=FR()) as ap:
222 8c599ca2 Stavros Sachtouris
            expected = []
223 8c599ca2 Stavros Sachtouris
            for key in keys:
224 8c599ca2 Stavros Sachtouris
                self.client.del_account_meta(key)
225 8c599ca2 Stavros Sachtouris
                expected.append(call(update=True, metadata={key: ''}))
226 8c599ca2 Stavros Sachtouris
            self.assertEqual(ap.mock_calls, expected)
227 756e9de9 Stavros Sachtouris
228 756e9de9 Stavros Sachtouris
    def test_create_container(self):
229 c6da1ccc Stavros Sachtouris
        FR.status_code = 201
230 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'put', return_value=FR()) as put:
231 756e9de9 Stavros Sachtouris
            cont = 's0m3c0n731n3r'
232 756e9de9 Stavros Sachtouris
            self.client.create_container(cont)
233 756e9de9 Stavros Sachtouris
            expected = [call('/%s/%s' % (user_id, cont), success=(201, 202))]
234 756e9de9 Stavros Sachtouris
            self.assertEqual(put.mock_calls, expected)
235 c6da1ccc Stavros Sachtouris
            FR.status_code = 202
236 756e9de9 Stavros Sachtouris
            self.assertRaises(ClientError, self.client.create_container, cont)
237 d12e8569 Stavros Sachtouris
238 d12e8569 Stavros Sachtouris
    def test_get_container_info(self):
239 c6da1ccc Stavros Sachtouris
        FR.headers = container_info
240 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'container_head', return_value=FR()) as ch:
241 d12e8569 Stavros Sachtouris
            r = self.client.get_container_info()
242 d12e8569 Stavros Sachtouris
            self.assert_dicts_are_equal(r, container_info)
243 d12e8569 Stavros Sachtouris
            u = 'some date'
244 d12e8569 Stavros Sachtouris
            r = self.client.get_container_info(until=u)
245 d12e8569 Stavros Sachtouris
            self.assertEqual(ch.mock_calls, [call(until=None), call(until=u)])
246 5549c0ab Stavros Sachtouris
247 5549c0ab Stavros Sachtouris
    def test_delete_container(self):
248 c6da1ccc Stavros Sachtouris
        FR.status_code = 204
249 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'delete', return_value=FR()) as delete:
250 5549c0ab Stavros Sachtouris
            cont = 's0m3c0n731n3r'
251 5549c0ab Stavros Sachtouris
            self.client.delete_container(cont)
252 c6da1ccc Stavros Sachtouris
            FR.status_code = 404
253 5549c0ab Stavros Sachtouris
            self.assertRaises(ClientError, self.client.delete_container, cont)
254 c6da1ccc Stavros Sachtouris
            FR.status_code = 409
255 5549c0ab Stavros Sachtouris
            self.assertRaises(ClientError, self.client.delete_container, cont)
256 5549c0ab Stavros Sachtouris
            acall = call('/%s/%s' % (user_id, cont), success=(204, 404, 409))
257 5549c0ab Stavros Sachtouris
            self.assertEqual(delete.mock_calls, [acall] * 3)
258 efaa8675 Stavros Sachtouris
259 efaa8675 Stavros Sachtouris
    def test_list_containers(self):
260 c6da1ccc Stavros Sachtouris
        FR.json = container_list
261 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'account_get', return_value=FR()):
262 efaa8675 Stavros Sachtouris
            r = self.client.list_containers()
263 efaa8675 Stavros Sachtouris
            for i in range(len(r)):
264 efaa8675 Stavros Sachtouris
                self.assert_dicts_are_equal(r[i], container_list[i])
265 bcbf3cf0 Stavros Sachtouris
266 c6da1ccc Stavros Sachtouris
    @patch(
267 c6da1ccc Stavros Sachtouris
        'kamaki.clients.pithos.PithosClient.get_container_info',
268 c6da1ccc Stavros Sachtouris
        return_value=container_info)
269 c6da1ccc Stavros Sachtouris
    @patch(
270 c6da1ccc Stavros Sachtouris
        'kamaki.clients.pithos.PithosClient.container_post',
271 c6da1ccc Stavros Sachtouris
        return_value=FR())
272 c6da1ccc Stavros Sachtouris
    @patch(
273 c6da1ccc Stavros Sachtouris
        'kamaki.clients.pithos.PithosClient.object_put',
274 c6da1ccc Stavros Sachtouris
        return_value=FR())
275 c6da1ccc Stavros Sachtouris
    def test_upload_object(self, CI, CP, OP):
276 cb65588d Stavros Sachtouris
        num_of_blocks = 8
277 cb65588d Stavros Sachtouris
        tmpFile = self._create_temp_file(num_of_blocks)
278 cf687343 Stavros Sachtouris
279 2a7292f1 Stavros Sachtouris
        # Without kwargs
280 bcbf3cf0 Stavros Sachtouris
        self.client.upload_object(obj, tmpFile)
281 bcbf3cf0 Stavros Sachtouris
        self.assertEqual(PC.get_container_info.mock_calls, [call()])
282 bcbf3cf0 Stavros Sachtouris
        [call1, call2] = PC.object_put.mock_calls
283 bcbf3cf0 Stavros Sachtouris
284 cf687343 Stavros Sachtouris
        (args1, kwargs1) = call1[1:3]
285 cf687343 Stavros Sachtouris
        (args2, kwargs2) = call2[1:3]
286 cf687343 Stavros Sachtouris
        self.assertEqual(args1, (obj,))
287 cf687343 Stavros Sachtouris
        expected1 = dict(
288 bcbf3cf0 Stavros Sachtouris
            hashmap=True,
289 bcbf3cf0 Stavros Sachtouris
            success=(201, 409),
290 bcbf3cf0 Stavros Sachtouris
            format='json',
291 bcbf3cf0 Stavros Sachtouris
            json=dict(
292 bcbf3cf0 Stavros Sachtouris
                hashes=['s0m3h@5h'] * num_of_blocks,
293 cb65588d Stavros Sachtouris
                bytes=num_of_blocks * 4 * 1024 * 1024),
294 bcbf3cf0 Stavros Sachtouris
            etag=None,
295 bcbf3cf0 Stavros Sachtouris
            content_encoding=None,
296 bcbf3cf0 Stavros Sachtouris
            content_type='application/octet-stream',
297 bcbf3cf0 Stavros Sachtouris
            content_disposition=None,
298 bcbf3cf0 Stavros Sachtouris
            public=None,
299 bcbf3cf0 Stavros Sachtouris
            permissions=None)
300 cf687343 Stavros Sachtouris
        for k, v in expected1.items():
301 cf687343 Stavros Sachtouris
            if k == 'json':
302 cf687343 Stavros Sachtouris
                self.assertEqual(len(v['hashes']), len(kwargs1[k]['hashes']))
303 cf687343 Stavros Sachtouris
                self.assertEqual(v['bytes'], kwargs1[k]['bytes'])
304 cf687343 Stavros Sachtouris
            else:
305 cf687343 Stavros Sachtouris
                self.assertEqual(v, kwargs1[k])
306 cf687343 Stavros Sachtouris
307 cf687343 Stavros Sachtouris
        (args2, kwargs2) = call2[1:3]
308 cf687343 Stavros Sachtouris
        self.assertEqual(args2, (obj,))
309 cf687343 Stavros Sachtouris
        expected2 = dict(
310 cf687343 Stavros Sachtouris
            json=dict(
311 cf687343 Stavros Sachtouris
                hashes=['s0m3h@5h'] * num_of_blocks,
312 cb65588d Stavros Sachtouris
                bytes=num_of_blocks * 4 * 1024 * 1024),
313 cf687343 Stavros Sachtouris
            content_type='application/octet-stream',
314 cf687343 Stavros Sachtouris
            hashmap=True,
315 cf687343 Stavros Sachtouris
            success=201,
316 cf687343 Stavros Sachtouris
            format='json')
317 cf687343 Stavros Sachtouris
        for k, v in expected2.items():
318 bcbf3cf0 Stavros Sachtouris
            if k == 'json':
319 cf687343 Stavros Sachtouris
                self.assertEqual(len(v['hashes']), len(kwargs2[k]['hashes']))
320 cf687343 Stavros Sachtouris
                self.assertEqual(v['bytes'], kwargs2[k]['bytes'])
321 bcbf3cf0 Stavros Sachtouris
            else:
322 cf687343 Stavros Sachtouris
                self.assertEqual(v, kwargs2[k])
323 cf687343 Stavros Sachtouris
324 cf687343 Stavros Sachtouris
        OP = PC.object_put
325 cf687343 Stavros Sachtouris
        mock_offset = 2
326 cf687343 Stavros Sachtouris
327 cf687343 Stavros Sachtouris
        #  With progress bars
328 cf687343 Stavros Sachtouris
        try:
329 cf687343 Stavros Sachtouris
            from progress.bar import ShadyBar
330 cf687343 Stavros Sachtouris
            blck_bar = ShadyBar('Mock blck calc.')
331 cf687343 Stavros Sachtouris
            upld_bar = ShadyBar('Mock uplds')
332 cf687343 Stavros Sachtouris
        except ImportError:
333 cf687343 Stavros Sachtouris
            blck_bar = None
334 cf687343 Stavros Sachtouris
            upld_bar = None
335 cf687343 Stavros Sachtouris
336 cf687343 Stavros Sachtouris
        if blck_bar and upld_bar:
337 cf687343 Stavros Sachtouris
338 cf687343 Stavros Sachtouris
            def blck_gen(n):
339 cf687343 Stavros Sachtouris
                for i in blck_bar.iter(range(n)):
340 cf687343 Stavros Sachtouris
                    yield
341 cf687343 Stavros Sachtouris
                yield
342 cf687343 Stavros Sachtouris
343 cf687343 Stavros Sachtouris
            def upld_gen(n):
344 cf687343 Stavros Sachtouris
                for i in upld_bar.iter(range(n)):
345 cf687343 Stavros Sachtouris
                    yield
346 cf687343 Stavros Sachtouris
                yield
347 cf687343 Stavros Sachtouris
348 cf687343 Stavros Sachtouris
            tmpFile.seek(0)
349 cf687343 Stavros Sachtouris
            self.client.upload_object(
350 cf687343 Stavros Sachtouris
                obj, tmpFile,
351 cf687343 Stavros Sachtouris
                hash_cb=blck_gen, upload_cb=upld_gen)
352 cf687343 Stavros Sachtouris
353 cf687343 Stavros Sachtouris
            for i, c in enumerate(OP.mock_calls[-mock_offset:]):
354 cf687343 Stavros Sachtouris
                self.assertEqual(OP.mock_calls[i], c)
355 cf687343 Stavros Sachtouris
356 cf687343 Stavros Sachtouris
        #  With content-type
357 cf687343 Stavros Sachtouris
        tmpFile.seek(0)
358 cf687343 Stavros Sachtouris
        ctype = 'video/mpeg'
359 cf687343 Stavros Sachtouris
        sharing = dict(read=['u1', 'g1', 'u2'], write=['u1'])
360 cf687343 Stavros Sachtouris
        self.client.upload_object(obj, tmpFile,
361 cf687343 Stavros Sachtouris
            content_type=ctype, sharing=sharing)
362 cf687343 Stavros Sachtouris
        self.assertEqual(OP.mock_calls[-1][2]['content_type'], ctype)
363 cf687343 Stavros Sachtouris
        self.assert_dicts_are_equal(
364 cf687343 Stavros Sachtouris
            OP.mock_calls[-2][2]['permissions'],
365 cf687343 Stavros Sachtouris
            sharing)
366 cf687343 Stavros Sachtouris
367 cf687343 Stavros Sachtouris
        # With other args
368 cf687343 Stavros Sachtouris
        tmpFile.seek(0)
369 cf687343 Stavros Sachtouris
        kwargs = dict(
370 cf687343 Stavros Sachtouris
            etag='s0m3E74g',
371 cf687343 Stavros Sachtouris
            content_type=ctype,
372 cf687343 Stavros Sachtouris
            content_disposition=ctype + 'd15p051710n',
373 cf687343 Stavros Sachtouris
            public=True,
374 cf687343 Stavros Sachtouris
            content_encoding='802.11')
375 cf687343 Stavros Sachtouris
        self.client.upload_object(obj, tmpFile, **kwargs)
376 cf687343 Stavros Sachtouris
        for arg, val in kwargs.items():
377 cf687343 Stavros Sachtouris
            self.assertEqual(OP.mock_calls[-2][2][arg], val)
378 b4780663 Stavros Sachtouris
379 c6da1ccc Stavros Sachtouris
    @patch('kamaki.clients.Client.set_header')
380 c6da1ccc Stavros Sachtouris
    def test_create_object(self, SH):
381 b4780663 Stavros Sachtouris
        cont = self.client.container
382 b4780663 Stavros Sachtouris
        ctype = 'c0n73n7/typ3'
383 b4780663 Stavros Sachtouris
        exp_shd = [
384 b4780663 Stavros Sachtouris
            call('Content-Type', 'application/octet-stream'),
385 b4780663 Stavros Sachtouris
            call('Content-length', '0'),
386 b4780663 Stavros Sachtouris
            call('Content-Type', ctype), call('Content-length', '42')]
387 b4780663 Stavros Sachtouris
        exp_put = [call('/%s/%s/%s' % (user_id, cont, obj), success=201)] * 2
388 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'put', return_value=FR()) as put:
389 b4780663 Stavros Sachtouris
            self.client.create_object(obj)
390 b4780663 Stavros Sachtouris
            self.client.create_object(obj,
391 b4780663 Stavros Sachtouris
                content_type=ctype, content_length=42)
392 b4780663 Stavros Sachtouris
            self.assertEqual(PC.set_header.mock_calls, exp_shd)
393 b4780663 Stavros Sachtouris
            self.assertEqual(put.mock_calls, exp_put)
394 4227e4be Stavros Sachtouris
395 c6da1ccc Stavros Sachtouris
    @patch('kamaki.clients.Client.set_header')
396 c6da1ccc Stavros Sachtouris
    def test_create_directory(self, SH):
397 4227e4be Stavros Sachtouris
        cont = self.client.container
398 4227e4be Stavros Sachtouris
        exp_shd = [
399 4227e4be Stavros Sachtouris
            call('Content-Type', 'application/directory'),
400 4227e4be Stavros Sachtouris
            call('Content-length', '0')]
401 4227e4be Stavros Sachtouris
        exp_put = [call('/%s/%s/%s' % (user_id, cont, obj), success=201)]
402 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'put', return_value=FR()) as put:
403 4227e4be Stavros Sachtouris
            self.client.create_directory(obj)
404 4227e4be Stavros Sachtouris
            self.assertEqual(PC.set_header.mock_calls, exp_shd)
405 4227e4be Stavros Sachtouris
            self.assertEqual(put.mock_calls, exp_put)
406 723e9d47 Stavros Sachtouris
407 723e9d47 Stavros Sachtouris
    def test_get_object_info(self):
408 c6da1ccc Stavros Sachtouris
        FR.headers = object_info
409 723e9d47 Stavros Sachtouris
        version = 'v3r510n'
410 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'object_head', return_value=FR()) as head:
411 723e9d47 Stavros Sachtouris
            r = self.client.get_object_info(obj)
412 723e9d47 Stavros Sachtouris
            self.assertEqual(r, object_info)
413 723e9d47 Stavros Sachtouris
            r = self.client.get_object_info(obj, version=version)
414 723e9d47 Stavros Sachtouris
            self.assertEqual(head.mock_calls, [
415 723e9d47 Stavros Sachtouris
                call(obj, version=None),
416 723e9d47 Stavros Sachtouris
                call(obj, version=version)])
417 723e9d47 Stavros Sachtouris
        with patch.object(
418 723e9d47 Stavros Sachtouris
                PC,
419 723e9d47 Stavros Sachtouris
                'object_head',
420 723e9d47 Stavros Sachtouris
                side_effect=ClientError('Obj not found', 404)):
421 723e9d47 Stavros Sachtouris
            self.assertRaises(
422 723e9d47 Stavros Sachtouris
                ClientError,
423 723e9d47 Stavros Sachtouris
                self.client.get_object_info,
424 723e9d47 Stavros Sachtouris
                obj, version=version)
425 3e2e07be Stavros Sachtouris
426 3e2e07be Stavros Sachtouris
    def test_get_object_meta(self):
427 3e2e07be Stavros Sachtouris
        expected = dict()
428 3e2e07be Stavros Sachtouris
        for k, v in object_info.items():
429 3e2e07be Stavros Sachtouris
            expected[k] = v
430 3e2e07be Stavros Sachtouris
        with patch.object(
431 3e2e07be Stavros Sachtouris
                PC,
432 3e2e07be Stavros Sachtouris
                'get_object_info',
433 3e2e07be Stavros Sachtouris
                return_value=object_info):
434 3e2e07be Stavros Sachtouris
            r = self.client.get_object_meta(obj)
435 3e2e07be Stavros Sachtouris
            self.assert_dicts_are_equal(r, expected)
436 da1597b9 Stavros Sachtouris
437 da1597b9 Stavros Sachtouris
    def test_del_object_meta(self):
438 da1597b9 Stavros Sachtouris
        metakey = '50m3m3t4k3y'
439 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'object_post', return_value=FR()) as post:
440 da1597b9 Stavros Sachtouris
            self.client.del_object_meta(obj, metakey)
441 da1597b9 Stavros Sachtouris
            self.assertEqual(
442 da1597b9 Stavros Sachtouris
                post.mock_calls,
443 da1597b9 Stavros Sachtouris
                [call(obj, update=True, metadata={metakey: ''})])
444 bd3a524f Stavros Sachtouris
445 c6da1ccc Stavros Sachtouris
    @patch('kamaki.clients.Client.set_header')
446 c6da1ccc Stavros Sachtouris
    def test_replace_object_meta(self, SH):
447 bd3a524f Stavros Sachtouris
        metas = dict(k1='new1', k2='new2', k3='new3')
448 bd3a524f Stavros Sachtouris
        cont = self.client.container
449 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'post', return_value=FR()) as post:
450 bd3a524f Stavros Sachtouris
            self.client.replace_object_meta(metas)
451 bd3a524f Stavros Sachtouris
            self.assertEqual(post.mock_calls, [
452 bd3a524f Stavros Sachtouris
                call('/%s/%s' % (user_id, cont),
453 bd3a524f Stavros Sachtouris
                success=202)])
454 bd3a524f Stavros Sachtouris
            prfx = 'X-Object-Meta-'
455 bd3a524f Stavros Sachtouris
            expected = [call('%s%s' % (prfx, k), v) for k, v in metas.items()]
456 bd3a524f Stavros Sachtouris
            self.assertEqual(PC.set_header.mock_calls, expected)
457 33487500 Stavros Sachtouris
458 33487500 Stavros Sachtouris
    def test_copy_object(self):
459 33487500 Stavros Sachtouris
        src_cont = 'src-c0nt41n3r'
460 33487500 Stavros Sachtouris
        src_obj = 'src-0bj'
461 33487500 Stavros Sachtouris
        dst_cont = 'dst-c0nt41n3r'
462 33487500 Stavros Sachtouris
        dst_obj = 'dst-0bj'
463 33487500 Stavros Sachtouris
        expected = call(
464 33487500 Stavros Sachtouris
            src_obj,
465 33487500 Stavros Sachtouris
            content_length=0,
466 33487500 Stavros Sachtouris
            source_account=None,
467 33487500 Stavros Sachtouris
            success=201,
468 33487500 Stavros Sachtouris
            copy_from='/%s/%s' % (src_cont, src_obj),
469 33487500 Stavros Sachtouris
            delimiter=None,
470 33487500 Stavros Sachtouris
            content_type=None,
471 33487500 Stavros Sachtouris
            source_version=None,
472 33487500 Stavros Sachtouris
            public=False)
473 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'object_put', return_value=FR()) as put:
474 33487500 Stavros Sachtouris
            self.client.copy_object(src_cont, src_obj, dst_cont)
475 33487500 Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1], expected)
476 33487500 Stavros Sachtouris
            self.client.copy_object(src_cont, src_obj, dst_cont, dst_obj)
477 33487500 Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1][1], (dst_obj,))
478 33487500 Stavros Sachtouris
            kwargs = dict(
479 33487500 Stavros Sachtouris
                source_version='src-v3r510n',
480 33487500 Stavros Sachtouris
                source_account='src-4cc0un7',
481 33487500 Stavros Sachtouris
                public=True,
482 33487500 Stavros Sachtouris
                content_type='c0n73n7Typ3',
483 33487500 Stavros Sachtouris
                delimiter='5')
484 33487500 Stavros Sachtouris
            self.client.copy_object(src_cont, src_obj, dst_cont, **kwargs)
485 33487500 Stavros Sachtouris
            for k, v in kwargs.items():
486 33487500 Stavros Sachtouris
                self.assertEqual(v, put.mock_calls[-1][2][k])
487 898e6fb7 Stavros Sachtouris
488 898e6fb7 Stavros Sachtouris
    def test_move_object(self):
489 898e6fb7 Stavros Sachtouris
        src_cont = 'src-c0nt41n3r'
490 898e6fb7 Stavros Sachtouris
        src_obj = 'src-0bj'
491 898e6fb7 Stavros Sachtouris
        dst_cont = 'dst-c0nt41n3r'
492 898e6fb7 Stavros Sachtouris
        dst_obj = 'dst-0bj'
493 898e6fb7 Stavros Sachtouris
        expected = call(
494 898e6fb7 Stavros Sachtouris
            src_obj,
495 898e6fb7 Stavros Sachtouris
            content_length=0,
496 898e6fb7 Stavros Sachtouris
            source_account=None,
497 898e6fb7 Stavros Sachtouris
            success=201,
498 898e6fb7 Stavros Sachtouris
            move_from='/%s/%s' % (src_cont, src_obj),
499 898e6fb7 Stavros Sachtouris
            delimiter=None,
500 898e6fb7 Stavros Sachtouris
            content_type=None,
501 898e6fb7 Stavros Sachtouris
            source_version=None,
502 898e6fb7 Stavros Sachtouris
            public=False)
503 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'object_put', return_value=FR()) as put:
504 898e6fb7 Stavros Sachtouris
            self.client.move_object(src_cont, src_obj, dst_cont)
505 898e6fb7 Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1], expected)
506 898e6fb7 Stavros Sachtouris
            self.client.move_object(src_cont, src_obj, dst_cont, dst_obj)
507 898e6fb7 Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1][1], (dst_obj,))
508 898e6fb7 Stavros Sachtouris
            kwargs = dict(
509 898e6fb7 Stavros Sachtouris
                source_version='src-v3r510n',
510 898e6fb7 Stavros Sachtouris
                source_account='src-4cc0un7',
511 898e6fb7 Stavros Sachtouris
                public=True,
512 898e6fb7 Stavros Sachtouris
                content_type='c0n73n7Typ3',
513 898e6fb7 Stavros Sachtouris
                delimiter='5')
514 898e6fb7 Stavros Sachtouris
            self.client.move_object(src_cont, src_obj, dst_cont, **kwargs)
515 898e6fb7 Stavros Sachtouris
            for k, v in kwargs.items():
516 898e6fb7 Stavros Sachtouris
                self.assertEqual(v, put.mock_calls[-1][2][k])
517 39c737d4 Stavros Sachtouris
518 39c737d4 Stavros Sachtouris
    def test_delete_object(self):
519 39c737d4 Stavros Sachtouris
        cont = self.client.container
520 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'delete', return_value=FR()) as delete:
521 39c737d4 Stavros Sachtouris
            self.client.delete_object(obj)
522 39c737d4 Stavros Sachtouris
            self.assertEqual(delete.mock_calls, [
523 39c737d4 Stavros Sachtouris
                call('/%s/%s/%s' % (user_id, cont, obj), success=(204, 404))])
524 c6da1ccc Stavros Sachtouris
            FR.status_code = 404
525 39c737d4 Stavros Sachtouris
            self.assertRaises(ClientError, self.client.delete_object, obj)
526 39c737d4 Stavros Sachtouris
527 c6da1ccc Stavros Sachtouris
    @patch('kamaki.clients.Client.set_param')
528 c6da1ccc Stavros Sachtouris
    def test_list_objects(self, SP):
529 c6da1ccc Stavros Sachtouris
        FR.json = object_list
530 39c737d4 Stavros Sachtouris
        acc = self.client.account
531 39c737d4 Stavros Sachtouris
        cont = self.client.container
532 39c737d4 Stavros Sachtouris
        SP = PC.set_param
533 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'get', return_value=FR()) as get:
534 39c737d4 Stavros Sachtouris
            r = self.client.list_objects()
535 39c737d4 Stavros Sachtouris
            for i in range(len(r)):
536 39c737d4 Stavros Sachtouris
                self.assert_dicts_are_equal(r[i], object_list[i])
537 39c737d4 Stavros Sachtouris
            self.assertEqual(get.mock_calls, [
538 39c737d4 Stavros Sachtouris
                call('/%s/%s' % (acc, cont), success=(200, 204, 304, 404))])
539 39c737d4 Stavros Sachtouris
            self.assertEqual(SP.mock_calls, [call('format', 'json')])
540 c6da1ccc Stavros Sachtouris
            FR.status_code = 304
541 39c737d4 Stavros Sachtouris
            self.assertEqual(self.client.list_objects(), [])
542 c6da1ccc Stavros Sachtouris
            FR.status_code = 404
543 39c737d4 Stavros Sachtouris
            self.assertRaises(ClientError, self.client.list_objects)
544 5ffdab56 Stavros Sachtouris
545 c6da1ccc Stavros Sachtouris
    @patch('kamaki.clients.Client.set_param')
546 c6da1ccc Stavros Sachtouris
    def test_list_objects_in_path(self, SP):
547 c6da1ccc Stavros Sachtouris
        FR.json = object_list
548 5ffdab56 Stavros Sachtouris
        path = '/some/awsome/path'
549 5ffdab56 Stavros Sachtouris
        acc = self.client.account
550 5ffdab56 Stavros Sachtouris
        cont = self.client.container
551 5ffdab56 Stavros Sachtouris
        SP = PC.set_param
552 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'get', return_value=FR()) as get:
553 5ffdab56 Stavros Sachtouris
            self.client.list_objects_in_path(path)
554 5ffdab56 Stavros Sachtouris
            self.assertEqual(get.mock_calls, [
555 5ffdab56 Stavros Sachtouris
                call('/%s/%s' % (acc, cont), success=(200, 204, 404))])
556 5ffdab56 Stavros Sachtouris
            self.assertEqual(SP.mock_calls, [
557 5ffdab56 Stavros Sachtouris
                call('format', 'json'), call('path', path)])
558 c6da1ccc Stavros Sachtouris
            FR.status_code = 404
559 5ffdab56 Stavros Sachtouris
            self.assertRaises(ClientError, self.client.list_objects)
560 2a7292f1 Stavros Sachtouris
561 2a7292f1 Stavros Sachtouris
    #  Pithos+ only methods
562 2a7292f1 Stavros Sachtouris
563 2a7292f1 Stavros Sachtouris
    def test_purge_container(self):
564 2a7292f1 Stavros Sachtouris
        with patch.object(
565 2a7292f1 Stavros Sachtouris
                PC,
566 2a7292f1 Stavros Sachtouris
                'container_delete',
567 c6da1ccc Stavros Sachtouris
                return_value=FR()) as cd:
568 2a7292f1 Stavros Sachtouris
            self.client.purge_container()
569 2a7292f1 Stavros Sachtouris
            self.assertTrue('until' in cd.mock_calls[-1][2])
570 2a7292f1 Stavros Sachtouris
            cont = self.client.container
571 2a7292f1 Stavros Sachtouris
            self.client.purge_container('another-container')
572 2a7292f1 Stavros Sachtouris
            self.assertEqual(self.client.container, cont)
573 2a7292f1 Stavros Sachtouris
574 2a7292f1 Stavros Sachtouris
    def test_upload_object_unchunked(self):
575 cb65588d Stavros Sachtouris
        num_of_blocks = 8
576 cb65588d Stavros Sachtouris
        tmpFile = self._create_temp_file(num_of_blocks)
577 2a7292f1 Stavros Sachtouris
        expected = dict(
578 2a7292f1 Stavros Sachtouris
                success=201,
579 cb65588d Stavros Sachtouris
                data=num_of_blocks * 4 * 1024 * 1024,
580 2a7292f1 Stavros Sachtouris
                etag='some-etag',
581 2a7292f1 Stavros Sachtouris
                content_encoding='some content_encoding',
582 2a7292f1 Stavros Sachtouris
                content_type='some content-type',
583 2a7292f1 Stavros Sachtouris
                content_disposition='some content_disposition',
584 2a7292f1 Stavros Sachtouris
                public=True,
585 2a7292f1 Stavros Sachtouris
                permissions=dict(read=['u1', 'g1', 'u2'], write=['u1']))
586 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'object_put', return_value=FR()) as put:
587 2a7292f1 Stavros Sachtouris
            self.client.upload_object_unchunked(obj, tmpFile)
588 2a7292f1 Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1][1], (obj,))
589 2a7292f1 Stavros Sachtouris
            self.assertEqual(
590 2a7292f1 Stavros Sachtouris
                sorted(put.mock_calls[-1][2].keys()),
591 2a7292f1 Stavros Sachtouris
                sorted(expected.keys()))
592 2a7292f1 Stavros Sachtouris
            kwargs = dict(expected)
593 2a7292f1 Stavros Sachtouris
            kwargs.pop('success')
594 2a7292f1 Stavros Sachtouris
            kwargs['size'] = kwargs.pop('data')
595 2a7292f1 Stavros Sachtouris
            kwargs['sharing'] = kwargs.pop('permissions')
596 2a7292f1 Stavros Sachtouris
            tmpFile.seek(0)
597 2a7292f1 Stavros Sachtouris
            self.client.upload_object_unchunked(obj, tmpFile, **kwargs)
598 2a7292f1 Stavros Sachtouris
            pmc = put.mock_calls[-1][2]
599 2a7292f1 Stavros Sachtouris
            for k, v in expected.items():
600 2a7292f1 Stavros Sachtouris
                if k == 'data':
601 2a7292f1 Stavros Sachtouris
                    self.assertEqual(len(pmc[k]), v)
602 2a7292f1 Stavros Sachtouris
                else:
603 2a7292f1 Stavros Sachtouris
                    self.assertEqual(pmc[k], v)
604 e82edbb0 Stavros Sachtouris
            self.assertRaises(
605 e82edbb0 Stavros Sachtouris
                ClientError,
606 e82edbb0 Stavros Sachtouris
                self.client.upload_object_unchunked,
607 e82edbb0 Stavros Sachtouris
                obj, tmpFile, withHashFile=True)
608 e82edbb0 Stavros Sachtouris
609 e82edbb0 Stavros Sachtouris
    def test_create_object_by_manifestation(self):
610 e82edbb0 Stavros Sachtouris
        manifest = '%s/%s' % (self.client.container, obj)
611 e82edbb0 Stavros Sachtouris
        kwargs = dict(
612 e82edbb0 Stavros Sachtouris
                etag='some-etag',
613 e82edbb0 Stavros Sachtouris
                content_encoding='some content_encoding',
614 e82edbb0 Stavros Sachtouris
                content_type='some content-type',
615 e82edbb0 Stavros Sachtouris
                content_disposition='some content_disposition',
616 e82edbb0 Stavros Sachtouris
                public=True,
617 e82edbb0 Stavros Sachtouris
                sharing=dict(read=['u1', 'g1', 'u2'], write=['u1']))
618 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'object_put', return_value=FR()) as put:
619 e82edbb0 Stavros Sachtouris
            self.client.create_object_by_manifestation(obj)
620 e82edbb0 Stavros Sachtouris
            expected = dict(content_length=0, manifest=manifest)
621 e82edbb0 Stavros Sachtouris
            for k in kwargs:
622 e82edbb0 Stavros Sachtouris
                expected['permissions' if k == 'sharing' else k] = None
623 e82edbb0 Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1], call(obj, **expected))
624 e82edbb0 Stavros Sachtouris
            self.client.create_object_by_manifestation(obj, **kwargs)
625 e82edbb0 Stavros Sachtouris
            expected.update(kwargs)
626 e82edbb0 Stavros Sachtouris
            expected['permissions'] = expected.pop('sharing')
627 e82edbb0 Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1], call(obj, **expected))
628 b4e29772 Stavros Sachtouris
629 c6da1ccc Stavros Sachtouris
    @patch(
630 c6da1ccc Stavros Sachtouris
        'kamaki.clients.pithos.PithosClient.get_object_hashmap',
631 c6da1ccc Stavros Sachtouris
        return_value=object_hashmap)
632 c6da1ccc Stavros Sachtouris
    @patch(
633 c6da1ccc Stavros Sachtouris
        'kamaki.clients.pithos.PithosClient.object_get',
634 c6da1ccc Stavros Sachtouris
        return_value=FR())
635 c6da1ccc Stavros Sachtouris
    def test_download_object(self, GOH, GET):
636 cb65588d Stavros Sachtouris
        num_of_blocks = 8
637 cb65588d Stavros Sachtouris
        tmpFile = self._create_temp_file(num_of_blocks)
638 c6da1ccc Stavros Sachtouris
        FR.content = tmpFile.read(4 * 1024 * 1024)
639 cb65588d Stavros Sachtouris
        tmpFile = self._create_temp_file(num_of_blocks)
640 b4e29772 Stavros Sachtouris
        GET = PC.object_get
641 b4e29772 Stavros Sachtouris
        num_of_blocks = len(object_hashmap['hashes'])
642 b4e29772 Stavros Sachtouris
        kwargs = dict(
643 b4e29772 Stavros Sachtouris
            resume=True,
644 cb65588d Stavros Sachtouris
            version='version',
645 b4e29772 Stavros Sachtouris
            range_str='10-20',
646 b4e29772 Stavros Sachtouris
            if_match='if and only if',
647 b4e29772 Stavros Sachtouris
            if_none_match='if and only not',
648 b4e29772 Stavros Sachtouris
            if_modified_since='what if not?',
649 b4e29772 Stavros Sachtouris
            if_unmodified_since='this happens if not!',
650 b4e29772 Stavros Sachtouris
            async_headers=dict(Range='bytes=0-88888888'))
651 b4e29772 Stavros Sachtouris
652 b4e29772 Stavros Sachtouris
        self.client.download_object(obj, tmpFile)
653 b4e29772 Stavros Sachtouris
        self.assertEqual(len(GET.mock_calls), num_of_blocks)
654 b4e29772 Stavros Sachtouris
        self.assertEqual(GET.mock_calls[-1][1], (obj,))
655 b4e29772 Stavros Sachtouris
        for k, v in kwargs.items():
656 b4e29772 Stavros Sachtouris
            if k == 'async_headers':
657 b4e29772 Stavros Sachtouris
                self.assertTrue('Range' in GET.mock_calls[-1][2][k])
658 b4e29772 Stavros Sachtouris
            elif k in ('resume', 'range_str'):
659 b4e29772 Stavros Sachtouris
                continue
660 b4e29772 Stavros Sachtouris
            else:
661 b4e29772 Stavros Sachtouris
                self.assertEqual(GET.mock_calls[-1][2][k], None)
662 b4e29772 Stavros Sachtouris
663 b4e29772 Stavros Sachtouris
        #  Check ranges are consecutive
664 b4e29772 Stavros Sachtouris
        starts = []
665 b4e29772 Stavros Sachtouris
        ends = []
666 b4e29772 Stavros Sachtouris
        for c in GET.mock_calls:
667 b4e29772 Stavros Sachtouris
            rng_str = c[2]['async_headers']['Range']
668 b4e29772 Stavros Sachtouris
            (start, rng_str) = rng_str.split('=')
669 b4e29772 Stavros Sachtouris
            (start, end) = rng_str.split('-')
670 b4e29772 Stavros Sachtouris
            starts.append(start)
671 b4e29772 Stavros Sachtouris
            ends.append(end)
672 b4e29772 Stavros Sachtouris
        ends = sorted(ends)
673 b4e29772 Stavros Sachtouris
        for i, start in enumerate(sorted(starts)):
674 b4e29772 Stavros Sachtouris
            if i:
675 b4e29772 Stavros Sachtouris
                int(ends[i - 1]) == int(start) - 1
676 b4e29772 Stavros Sachtouris
677 b4e29772 Stavros Sachtouris
        #  With progress bars
678 b4e29772 Stavros Sachtouris
        try:
679 b4e29772 Stavros Sachtouris
            from progress.bar import ShadyBar
680 b4e29772 Stavros Sachtouris
            dl_bar = ShadyBar('Mock dl')
681 b4e29772 Stavros Sachtouris
        except ImportError:
682 b4e29772 Stavros Sachtouris
            dl_bar = None
683 b4e29772 Stavros Sachtouris
684 b4e29772 Stavros Sachtouris
        if dl_bar:
685 b4e29772 Stavros Sachtouris
686 b4e29772 Stavros Sachtouris
            def blck_gen(n):
687 b4e29772 Stavros Sachtouris
                for i in dl_bar.iter(range(n)):
688 b4e29772 Stavros Sachtouris
                    yield
689 b4e29772 Stavros Sachtouris
                yield
690 b4e29772 Stavros Sachtouris
691 b4e29772 Stavros Sachtouris
            tmpFile.seek(0)
692 b4e29772 Stavros Sachtouris
            self.client.download_object(obj, tmpFile, download_cb=blck_gen)
693 b4e29772 Stavros Sachtouris
            self.assertEqual(len(GET.mock_calls), 2 * num_of_blocks)
694 b4e29772 Stavros Sachtouris
695 b4e29772 Stavros Sachtouris
        tmpFile.seek(0)
696 b4e29772 Stavros Sachtouris
        kwargs.pop('async_headers')
697 b4e29772 Stavros Sachtouris
        kwargs.pop('resume')
698 b4e29772 Stavros Sachtouris
        self.client.download_object(obj, tmpFile, **kwargs)
699 b4e29772 Stavros Sachtouris
        for k, v in kwargs.items():
700 b4e29772 Stavros Sachtouris
            if k == 'range_str':
701 b4e29772 Stavros Sachtouris
                self.assertEqual(
702 b4e29772 Stavros Sachtouris
                    GET.mock_calls[-1][2]['data_range'],
703 b4e29772 Stavros Sachtouris
                    'bytes=%s' % v)
704 b4e29772 Stavros Sachtouris
            else:
705 b4e29772 Stavros Sachtouris
                self.assertEqual(GET.mock_calls[-1][2][k], v)
706 b4e29772 Stavros Sachtouris
707 b4e29772 Stavros Sachtouris
        #  ALl options on no tty
708 b4e29772 Stavros Sachtouris
709 b4e29772 Stavros Sachtouris
        def foo():
710 b4e29772 Stavros Sachtouris
            return True
711 b4e29772 Stavros Sachtouris
712 b4e29772 Stavros Sachtouris
        tmpFile.seek(0)
713 b4e29772 Stavros Sachtouris
        tmpFile.isatty = foo
714 b4e29772 Stavros Sachtouris
        self.client.download_object(obj, tmpFile, **kwargs)
715 b4e29772 Stavros Sachtouris
        for k, v in kwargs.items():
716 b4e29772 Stavros Sachtouris
            if k == 'range_str':
717 b4e29772 Stavros Sachtouris
                self.assertTrue('data_range' in GET.mock_calls[-1][2])
718 b4e29772 Stavros Sachtouris
            else:
719 b4e29772 Stavros Sachtouris
                self.assertEqual(GET.mock_calls[-1][2][k], v)
720 cb65588d Stavros Sachtouris
721 cb65588d Stavros Sachtouris
    def test_get_object_hashmap(self):
722 c6da1ccc Stavros Sachtouris
        FR.json = object_hashmap
723 cb65588d Stavros Sachtouris
        for empty in (304, 412):
724 cb65588d Stavros Sachtouris
            with patch.object(
725 cb65588d Stavros Sachtouris
                    PC, 'object_get',
726 cb65588d Stavros Sachtouris
                    side_effect=ClientError('Empty', status=empty)):
727 cb65588d Stavros Sachtouris
                r = self.client.get_object_hashmap(obj)
728 cb65588d Stavros Sachtouris
                self.assertEqual(r, {})
729 cb65588d Stavros Sachtouris
        exp_args = dict(
730 cb65588d Stavros Sachtouris
            hashmap=True,
731 cb65588d Stavros Sachtouris
            data_range=None,
732 cb65588d Stavros Sachtouris
            version=None,
733 cb65588d Stavros Sachtouris
            if_etag_match=None,
734 cb65588d Stavros Sachtouris
            if_etag_not_match=None,
735 cb65588d Stavros Sachtouris
            if_modified_since=None,
736 cb65588d Stavros Sachtouris
            if_unmodified_since=None)
737 cb65588d Stavros Sachtouris
        kwargs = dict(
738 cb65588d Stavros Sachtouris
            version='s0m3v3r51on',
739 cb65588d Stavros Sachtouris
            if_match='if match',
740 cb65588d Stavros Sachtouris
            if_none_match='if non match',
741 cb65588d Stavros Sachtouris
            if_modified_since='some date here',
742 cb65588d Stavros Sachtouris
            if_unmodified_since='some date here',
743 cb65588d Stavros Sachtouris
            data_range='10-20')
744 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'object_get', return_value=FR()) as get:
745 cb65588d Stavros Sachtouris
            r = self.client.get_object_hashmap(obj)
746 cb65588d Stavros Sachtouris
            self.assertEqual(r, object_hashmap)
747 cb65588d Stavros Sachtouris
            self.assertEqual(get.mock_calls[-1], call(obj, **exp_args))
748 cb65588d Stavros Sachtouris
            r = self.client.get_object_hashmap(obj, **kwargs)
749 cb65588d Stavros Sachtouris
            exp_args['if_etag_match'] = kwargs.pop('if_match')
750 cb65588d Stavros Sachtouris
            exp_args['if_etag_not_match'] = kwargs.pop('if_none_match')
751 cb65588d Stavros Sachtouris
            exp_args.update(kwargs)
752 cb65588d Stavros Sachtouris
            self.assertEqual(get.mock_calls[-1], call(obj, **exp_args))
753 8b71426c Stavros Sachtouris
754 8b71426c Stavros Sachtouris
    def test_set_account_group(self):
755 8b71426c Stavros Sachtouris
        group = 'aU53rGr0up'
756 8b71426c Stavros Sachtouris
        usernames = ['u1', 'u2', 'u3']
757 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'account_post', return_value=FR()) as post:
758 8b71426c Stavros Sachtouris
            self.client.set_account_group(group, usernames)
759 8b71426c Stavros Sachtouris
            self.assertEqual(
760 8b71426c Stavros Sachtouris
                post.mock_calls[-1],
761 8b71426c Stavros Sachtouris
                call(update=True, groups={group: usernames}))
762 419fa6c4 Stavros Sachtouris
763 419fa6c4 Stavros Sachtouris
    def test_del_account_group(self):
764 419fa6c4 Stavros Sachtouris
        group = 'aU53rGr0up'
765 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'account_post', return_value=FR()) as post:
766 419fa6c4 Stavros Sachtouris
            self.client.del_account_group(group)
767 419fa6c4 Stavros Sachtouris
            self.assertEqual(
768 419fa6c4 Stavros Sachtouris
                post.mock_calls[-1],
769 419fa6c4 Stavros Sachtouris
                call(update=True, groups={group: []}))
770 34f48ce0 Stavros Sachtouris
771 34f48ce0 Stavros Sachtouris
    def test_get_account_quota(self):
772 34f48ce0 Stavros Sachtouris
        key = 'x-account-policy-quota'
773 34f48ce0 Stavros Sachtouris
        with patch.object(PC, 'get_account_info', return_value=account_info):
774 34f48ce0 Stavros Sachtouris
            r = self.client.get_account_quota()
775 34f48ce0 Stavros Sachtouris
            self.assertEqual(r[key], account_info[key])
776 16b77981 Stavros Sachtouris
777 16b77981 Stavros Sachtouris
    def test_get_account_versioning(self):
778 16b77981 Stavros Sachtouris
        key = 'x-account-policy-versioning'
779 16b77981 Stavros Sachtouris
        with patch.object(PC, 'get_account_info', return_value=account_info):
780 16b77981 Stavros Sachtouris
            r = self.client.get_account_versioning()
781 16b77981 Stavros Sachtouris
            self.assertEqual(r[key], account_info[key])
782 de27950a Stavros Sachtouris
783 de27950a Stavros Sachtouris
    def test_get_account_meta(self):
784 e78922d9 Stavros Sachtouris
        key = 'x-account-meta-'
785 de27950a Stavros Sachtouris
        with patch.object(PC, 'get_account_info', return_value=account_info):
786 de27950a Stavros Sachtouris
            r = self.client.get_account_meta()
787 e78922d9 Stavros Sachtouris
            keys = [k for k in r if k.startswith(key)]
788 e78922d9 Stavros Sachtouris
            self.assertFalse(keys)
789 de27950a Stavros Sachtouris
        acc_info = dict(account_info)
790 e78922d9 Stavros Sachtouris
        acc_info['%sk1' % key] = 'v1'
791 e78922d9 Stavros Sachtouris
        acc_info['%sk2' % key] = 'v2'
792 e78922d9 Stavros Sachtouris
        acc_info['%sk3' % key] = 'v3'
793 de27950a Stavros Sachtouris
        with patch.object(PC, 'get_account_info', return_value=acc_info):
794 de27950a Stavros Sachtouris
            r = self.client.get_account_meta()
795 e78922d9 Stavros Sachtouris
            for k in [k for k in acc_info if k.startswith(key)]:
796 e78922d9 Stavros Sachtouris
                self.assertEqual(r[k], acc_info[k])
797 e78922d9 Stavros Sachtouris
798 e78922d9 Stavros Sachtouris
    def test_get_account_group(self):
799 e78922d9 Stavros Sachtouris
        key = 'x-account-group-'
800 e78922d9 Stavros Sachtouris
        with patch.object(PC, 'get_account_info', return_value=account_info):
801 e78922d9 Stavros Sachtouris
            r = self.client.get_account_group()
802 e78922d9 Stavros Sachtouris
            keys = [k for k in r if k.startswith(key)]
803 e78922d9 Stavros Sachtouris
            self.assertFalse(keys)
804 e78922d9 Stavros Sachtouris
        acc_info = dict(account_info)
805 e78922d9 Stavros Sachtouris
        acc_info['%sk1' % key] = 'g1'
806 e78922d9 Stavros Sachtouris
        acc_info['%sk2' % key] = 'g2'
807 e78922d9 Stavros Sachtouris
        acc_info['%sk3' % key] = 'g3'
808 e78922d9 Stavros Sachtouris
        with patch.object(PC, 'get_account_info', return_value=acc_info):
809 e78922d9 Stavros Sachtouris
            r = self.client.get_account_group()
810 e78922d9 Stavros Sachtouris
            for k in [k for k in acc_info if k.startswith(key)]:
811 e78922d9 Stavros Sachtouris
                self.assertEqual(r[k], acc_info[k])
812 84817ae5 Stavros Sachtouris
813 84817ae5 Stavros Sachtouris
    def test_set_account_meta(self):
814 84817ae5 Stavros Sachtouris
        metas = dict(k1='v1', k2='v2', k3='v3')
815 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'account_post', return_value=FR()) as post:
816 84817ae5 Stavros Sachtouris
            self.client.set_account_meta(metas)
817 84817ae5 Stavros Sachtouris
            self.assertEqual(
818 84817ae5 Stavros Sachtouris
                post.mock_calls[-1],
819 84817ae5 Stavros Sachtouris
                call(update=True, metadata=metas))
820 edd209d3 Stavros Sachtouris
821 edd209d3 Stavros Sachtouris
    def test_set_account_quota(self):
822 edd209d3 Stavros Sachtouris
        qu = 1024
823 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'account_post', return_value=FR()) as post:
824 edd209d3 Stavros Sachtouris
            self.client.set_account_quota(qu)
825 edd209d3 Stavros Sachtouris
            self.assertEqual(post.mock_calls[-1], call(update=True, quota=qu))
826 a6439733 Stavros Sachtouris
827 a6439733 Stavros Sachtouris
    def test_set_account_versioning(self):
828 a6439733 Stavros Sachtouris
        vrs = 'n3wV3r51on1ngTyp3'
829 c6da1ccc Stavros Sachtouris
        with patch.object(PC, 'account_post', return_value=FR()) as post:
830 a6439733 Stavros Sachtouris
            self.client.set_account_versioning(vrs)
831 a6439733 Stavros Sachtouris
            self.assertEqual(
832 a6439733 Stavros Sachtouris
                post.mock_calls[-1],
833 a6439733 Stavros Sachtouris
                call(update=True, versioning=vrs))
834 843afe1f Stavros Sachtouris
835 843afe1f Stavros Sachtouris
    def test_del_container(self):
836 843afe1f Stavros Sachtouris
        kwarg_list = [
837 843afe1f Stavros Sachtouris
            dict(delimiter=None, until=None),
838 843afe1f Stavros Sachtouris
            dict(delimiter='X', until='50m3d473')]
839 843afe1f Stavros Sachtouris
        with patch.object(
840 843afe1f Stavros Sachtouris
                PC,
841 843afe1f Stavros Sachtouris
                'container_delete',
842 c6da1ccc Stavros Sachtouris
                return_value=FR()) as delete:
843 843afe1f Stavros Sachtouris
            for kwarg in kwarg_list:
844 843afe1f Stavros Sachtouris
                self.client.del_container(**kwarg)
845 843afe1f Stavros Sachtouris
                expected = dict(kwarg)
846 843afe1f Stavros Sachtouris
                expected['success'] = (204, 404, 409)
847 843afe1f Stavros Sachtouris
                self.assertEqual(delete.mock_calls[-1], call(**expected))
848 843afe1f Stavros Sachtouris
            for status_code in (404, 409):
849 c6da1ccc Stavros Sachtouris
                FR.status_code = status_code
850 843afe1f Stavros Sachtouris
                self.assertRaises(ClientError, self.client.del_container)
851 bae347d3 Stavros Sachtouris
852 bae347d3 Stavros Sachtouris
    def test_get_container_versioning(self):
853 bae347d3 Stavros Sachtouris
        key = 'x-container-policy-versioning'
854 bae347d3 Stavros Sachtouris
        cont = 'c0n7-417'
855 1879e310 Stavros Sachtouris
        bu_cnt = self.client.container
856 bae347d3 Stavros Sachtouris
        with patch.object(
857 bae347d3 Stavros Sachtouris
                PC,
858 bae347d3 Stavros Sachtouris
                'get_container_info',
859 bae347d3 Stavros Sachtouris
                return_value=container_info) as gci:
860 bae347d3 Stavros Sachtouris
            for container in (None, cont):
861 bae347d3 Stavros Sachtouris
                r = self.client.get_container_versioning(container=container)
862 bae347d3 Stavros Sachtouris
                self.assertEqual(r[key], container_info[key])
863 bae347d3 Stavros Sachtouris
                self.assertEqual(gci.mock_calls[-1], call())
864 1879e310 Stavros Sachtouris
                self.assertEqual(bu_cnt, self.client.container)
865 bae347d3 Stavros Sachtouris
866 1879e310 Stavros Sachtouris
    def test_get_container_quota(self):
867 1879e310 Stavros Sachtouris
        key = 'x-container-policy-quota'
868 1879e310 Stavros Sachtouris
        cont = 'c0n7-417'
869 1879e310 Stavros Sachtouris
        bu_cnt = self.client.container
870 1879e310 Stavros Sachtouris
        with patch.object(
871 1879e310 Stavros Sachtouris
                PC,
872 1879e310 Stavros Sachtouris
                'get_container_info',
873 1879e310 Stavros Sachtouris
                return_value=container_info) as gci:
874 1879e310 Stavros Sachtouris
            for container in (None, cont):
875 1879e310 Stavros Sachtouris
                r = self.client.get_container_quota(container=container)
876 1879e310 Stavros Sachtouris
                self.assertEqual(r[key], container_info[key])
877 1879e310 Stavros Sachtouris
                self.assertEqual(gci.mock_calls[-1], call())
878 1879e310 Stavros Sachtouris
                self.assertEqual(bu_cnt, self.client.container)
879 c297102c Stavros Sachtouris
880 c297102c Stavros Sachtouris
    def test_get_container_meta(self):
881 c297102c Stavros Sachtouris
        somedate = '50m3d473'
882 c297102c Stavros Sachtouris
        key = 'x-container-meta'
883 c297102c Stavros Sachtouris
        metaval = '50m3m374v41'
884 c297102c Stavros Sachtouris
        container_plus = dict(container_info)
885 c297102c Stavros Sachtouris
        container_plus[key] = metaval
886 c297102c Stavros Sachtouris
        for ret in ((container_info, {}), (container_plus, {key: metaval})):
887 c297102c Stavros Sachtouris
            with patch.object(
888 c297102c Stavros Sachtouris
                    PC,
889 c297102c Stavros Sachtouris
                    'get_container_info',
890 c297102c Stavros Sachtouris
                    return_value=ret[0]) as gci:
891 c297102c Stavros Sachtouris
                for until in (None, somedate):
892 c297102c Stavros Sachtouris
                    r = self.client.get_container_meta(until=until)
893 c297102c Stavros Sachtouris
                    self.assertEqual(r, ret[1])
894 c297102c Stavros Sachtouris
                    self.assertEqual(gci.mock_calls[-1], call(until=until))