Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / storage / test.py @ edf8ad52

History | View | Annotate | Download (16.6 kB)

1 3e6f33ca Stavros Sachtouris
# Copyright 2013 GRNET S.A. All rights reserved.
2 3e6f33ca Stavros Sachtouris
#
3 3e6f33ca Stavros Sachtouris
# Redistribution and use in source and binary forms, with or
4 3e6f33ca Stavros Sachtouris
# without modification, are permitted provided that the following
5 3e6f33ca Stavros Sachtouris
# conditions are met:
6 3e6f33ca Stavros Sachtouris
#
7 3e6f33ca Stavros Sachtouris
#   1. Redistributions of source code must retain the above
8 3e6f33ca Stavros Sachtouris
#      copyright notice, this list of conditions and the following
9 3e6f33ca Stavros Sachtouris
#      disclaimer.
10 3e6f33ca Stavros Sachtouris
#
11 3e6f33ca Stavros Sachtouris
#   2. Redistributions in binary form must reproduce the above
12 3e6f33ca Stavros Sachtouris
#      copyright notice, this list of conditions and the following
13 3e6f33ca Stavros Sachtouris
#      disclaimer in the documentation and/or other materials
14 3e6f33ca Stavros Sachtouris
#      provided with the distribution.
15 3e6f33ca Stavros Sachtouris
#
16 3e6f33ca Stavros Sachtouris
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 3e6f33ca Stavros Sachtouris
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 3e6f33ca Stavros Sachtouris
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 3e6f33ca Stavros Sachtouris
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 3e6f33ca Stavros Sachtouris
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 3e6f33ca Stavros Sachtouris
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 3e6f33ca Stavros Sachtouris
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 3e6f33ca Stavros Sachtouris
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 3e6f33ca Stavros Sachtouris
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 3e6f33ca Stavros Sachtouris
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 3e6f33ca Stavros Sachtouris
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 3e6f33ca Stavros Sachtouris
# POSSIBILITY OF SUCH DAMAGE.
28 3e6f33ca Stavros Sachtouris
#
29 3e6f33ca Stavros Sachtouris
# The views and conclusions contained in the software and
30 3e6f33ca Stavros Sachtouris
# documentation are those of the authors and should not be
31 3e6f33ca Stavros Sachtouris
# interpreted as representing official policies, either expressed
32 3e6f33ca Stavros Sachtouris
# or implied, of GRNET S.A.
33 3e6f33ca Stavros Sachtouris
34 3e6f33ca Stavros Sachtouris
from unittest import TestCase
35 3e6f33ca Stavros Sachtouris
from mock import patch, call
36 3e6f33ca Stavros Sachtouris
from tempfile import NamedTemporaryFile
37 3e6f33ca Stavros Sachtouris
from os import urandom
38 3e6f33ca Stavros Sachtouris
39 3e6f33ca Stavros Sachtouris
from kamaki.clients import ClientError
40 3e6f33ca Stavros Sachtouris
from kamaki.clients.storage import StorageClient as SC
41 3e6f33ca Stavros Sachtouris
42 3e6f33ca Stavros Sachtouris
client_pkg = 'kamaki.clients.Client'
43 3e6f33ca Stavros Sachtouris
storage_pkg = 'kamaki.clients.storage.StorageClient'
44 3e6f33ca Stavros Sachtouris
45 3e6f33ca Stavros Sachtouris
user_id = 'ac0un7-1d-5tr1ng'
46 3e6f33ca Stavros Sachtouris
obj = 'obj3c7N4m3'
47 3e6f33ca Stavros Sachtouris
48 3e6f33ca Stavros Sachtouris
account_info = {
49 3e6f33ca Stavros Sachtouris
    'content-language': 'en-us',
50 3e6f33ca Stavros Sachtouris
    'content-type': 'text/html; charset=utf-8',
51 3e6f33ca Stavros Sachtouris
    'date': 'Wed, 06 Mar 2013 13:25:51 GMT',
52 3e6f33ca Stavros Sachtouris
    'last-modified': 'Mon, 04 Mar 2013 18:22:31 GMT',
53 3e6f33ca Stavros Sachtouris
    'server': 'gunicorn/0.14.5',
54 3e6f33ca Stavros Sachtouris
    'vary': 'Accept-Language',
55 3e6f33ca Stavros Sachtouris
    'x-account-bytes-used': '751615526',
56 3e6f33ca Stavros Sachtouris
    'x-account-container-count': 7,
57 3e6f33ca Stavros Sachtouris
    'x-account-policy-quota': 53687091200,
58 3e6f33ca Stavros Sachtouris
    'x-account-policy-versioning': 'auto',
59 3e6f33ca Stavros Sachtouris
    'x-account-meta-k1': 'val1',
60 3e6f33ca Stavros Sachtouris
    'x-account-meta-k2': 'val2',
61 3e6f33ca Stavros Sachtouris
    'x-account-meta-k3': 'val3'}
62 3e6f33ca Stavros Sachtouris
container_info = {
63 3e6f33ca Stavros Sachtouris
    'content-language': 'en-us',
64 3e6f33ca Stavros Sachtouris
    'content-type': 'text/html; charset=utf-8',
65 3e6f33ca Stavros Sachtouris
    'date': 'Wed, 06 Mar 2013 15:11:05 GMT',
66 3e6f33ca Stavros Sachtouris
    'last-modified': 'Wed, 27 Feb 2013 15:56:13 GMT',
67 3e6f33ca Stavros Sachtouris
    'server': 'gunicorn/0.14.5',
68 3e6f33ca Stavros Sachtouris
    'vary': 'Accept-Language',
69 3e6f33ca Stavros Sachtouris
    'x-container-block-hash': 'sha256',
70 3e6f33ca Stavros Sachtouris
    'x-container-block-size': 4194304,
71 3e6f33ca Stavros Sachtouris
    'x-container-bytes-used': 309528938,
72 3e6f33ca Stavros Sachtouris
    'x-container-object-count': 14,
73 3e6f33ca Stavros Sachtouris
    'x-container-object-meta': '',
74 3e6f33ca Stavros Sachtouris
    'x-container-policy-quota': 53687091200,
75 3e6f33ca Stavros Sachtouris
    'x-container-policy-versioning': 'auto'}
76 3e6f33ca Stavros Sachtouris
object_info = {
77 3e6f33ca Stavros Sachtouris
    'content-language': 'en-us',
78 3e6f33ca Stavros Sachtouris
    'content-length': 254965,
79 3e6f33ca Stavros Sachtouris
    'content-type': 'application/octet-stream',
80 3e6f33ca Stavros Sachtouris
    'date': 'Thu, 07 Mar 2013 13:27:43 GMT',
81 3e6f33ca Stavros Sachtouris
    'etag': '',
82 3e6f33ca Stavros Sachtouris
    'last-modified': 'Mon, 04 Mar 2013 18:22:31 GMT',
83 3e6f33ca Stavros Sachtouris
    'server': 'gunicorn/0.14.5',
84 3e6f33ca Stavros Sachtouris
    'vary': 'Accept-Language',
85 3e6f33ca Stavros Sachtouris
    'x-object-hash': 'obj3c7h45h1s0bj3c7h45h411r34dY',
86 3e6f33ca Stavros Sachtouris
    'x-object-uuid': 'd0c747ca-34bd-49e0-8e98-1d07d8b0cbc7',
87 3e6f33ca Stavros Sachtouris
    'x-object-version': '525996',
88 3e6f33ca Stavros Sachtouris
    'x-object-version-timestamp': 'Mon, 04 Mar 2013 18:22:31 GMT',
89 3e6f33ca Stavros Sachtouris
    'x-object-meta-k1': 'v1',
90 3e6f33ca Stavros Sachtouris
    'x-object-meta-k2': 'v2'}
91 3e6f33ca Stavros Sachtouris
container_list = [
92 3e6f33ca Stavros Sachtouris
    dict(
93 3e6f33ca Stavros Sachtouris
        count=2,
94 3e6f33ca Stavros Sachtouris
        last_modified="2013-02-27T11:56:09.893033+00:00",
95 3e6f33ca Stavros Sachtouris
        bytes=677076979,
96 3e6f33ca Stavros Sachtouris
        name="pithos",
97 3e6f33ca Stavros Sachtouris
        x_container_policy=dict(quota="21474836480", versioning="auto")),
98 3e6f33ca Stavros Sachtouris
    dict(
99 3e6f33ca Stavros Sachtouris
        count=0,
100 3e6f33ca Stavros Sachtouris
        last_modified="2012-10-23T12:25:17.229187+00:00",
101 3e6f33ca Stavros Sachtouris
        bytes=0,
102 3e6f33ca Stavros Sachtouris
        name="trash",
103 3e6f33ca Stavros Sachtouris
        x_container_policy=dict(quota="21474836480", versioning="auto"))]
104 3e6f33ca Stavros Sachtouris
object_list = [
105 3e6f33ca Stavros Sachtouris
    dict(hash="",
106 3e6f33ca Stavros Sachtouris
        name="The_Secret_Garden.zip",
107 3e6f33ca Stavros Sachtouris
        x_object_public="/public/wdp9p",
108 3e6f33ca Stavros Sachtouris
        bytes=203304947,
109 3e6f33ca Stavros Sachtouris
        x_object_version_timestamp="1360237915.7027509",
110 3e6f33ca Stavros Sachtouris
        x_object_uuid="s0m3uu1df0r0bj0n3",
111 3e6f33ca Stavros Sachtouris
        last_modified="2013-02-07T11:51:55.702751+00:00",
112 3e6f33ca Stavros Sachtouris
        content_type="application/octet-stream",
113 3e6f33ca Stavros Sachtouris
        x_object_hash="0afdf29f71cd53126225c3f54ca",
114 3e6f33ca Stavros Sachtouris
        x_object_version=17737,
115 3e6f33ca Stavros Sachtouris
        x_object_modified_by=user_id),
116 3e6f33ca Stavros Sachtouris
    dict(hash="",
117 3e6f33ca Stavros Sachtouris
        name="The_Revealed_Garden.zip",
118 3e6f33ca Stavros Sachtouris
        x_object_public="/public/wpd7p",
119 3e6f33ca Stavros Sachtouris
        bytes=20330947,
120 3e6f33ca Stavros Sachtouris
        x_object_version_timestamp="13602915.7027509",
121 3e6f33ca Stavros Sachtouris
        x_object_uuid="s0m3uu1df0r0bj70w",
122 3e6f33ca Stavros Sachtouris
        last_modified="2013-02-07T11:51:55.702751+00:00",
123 3e6f33ca Stavros Sachtouris
        content_type="application/octet-stream",
124 3e6f33ca Stavros Sachtouris
        x_object_hash="0afdf29f71cd53126225c3f54ca",
125 3e6f33ca Stavros Sachtouris
        x_object_version=17737,
126 3e6f33ca Stavros Sachtouris
        x_object_modified_by=user_id)]
127 3e6f33ca Stavros Sachtouris
128 3e6f33ca Stavros Sachtouris
129 3e6f33ca Stavros Sachtouris
class FR(object):
130 3e6f33ca Stavros Sachtouris
    """FR stands for Fake Response"""
131 3e6f33ca Stavros Sachtouris
    json = dict()
132 3e6f33ca Stavros Sachtouris
    headers = dict()
133 3e6f33ca Stavros Sachtouris
    content = json
134 3e6f33ca Stavros Sachtouris
    status = None
135 3e6f33ca Stavros Sachtouris
    status_code = 200
136 3e6f33ca Stavros Sachtouris
137 3e6f33ca Stavros Sachtouris
    def release(self):
138 3e6f33ca Stavros Sachtouris
        pass
139 3e6f33ca Stavros Sachtouris
140 3e6f33ca Stavros Sachtouris
141 3e6f33ca Stavros Sachtouris
class Storage(TestCase):
142 3e6f33ca Stavros Sachtouris
143 3e6f33ca Stavros Sachtouris
    files = []
144 3e6f33ca Stavros Sachtouris
145 3e6f33ca Stavros Sachtouris
    def _create_temp_file(self, num_of_blocks):
146 3e6f33ca Stavros Sachtouris
        self.files.append(NamedTemporaryFile())
147 3e6f33ca Stavros Sachtouris
        tmpFile = self.files[-1]
148 3e6f33ca Stavros Sachtouris
        file_size = num_of_blocks * 4 * 1024 * 1024
149 3e6f33ca Stavros Sachtouris
        print('\n\tCreate tmp file')
150 3e6f33ca Stavros Sachtouris
        tmpFile.write(urandom(file_size))
151 3e6f33ca Stavros Sachtouris
        tmpFile.flush()
152 3e6f33ca Stavros Sachtouris
        tmpFile.seek(0)
153 3e6f33ca Stavros Sachtouris
        print('\t\tDone')
154 3e6f33ca Stavros Sachtouris
        return tmpFile
155 3e6f33ca Stavros Sachtouris
156 3e6f33ca Stavros Sachtouris
    def assert_dicts_are_equal(self, d1, d2):
157 3e6f33ca Stavros Sachtouris
        for k, v in d1.items():
158 3e6f33ca Stavros Sachtouris
            self.assertTrue(k in d2)
159 3e6f33ca Stavros Sachtouris
            if isinstance(v, dict):
160 3e6f33ca Stavros Sachtouris
                self.assert_dicts_are_equal(v, d2[k])
161 3e6f33ca Stavros Sachtouris
            else:
162 3e6f33ca Stavros Sachtouris
                self.assertEqual(unicode(v), unicode(d2[k]))
163 3e6f33ca Stavros Sachtouris
164 3e6f33ca Stavros Sachtouris
    def setUp(self):
165 3e6f33ca Stavros Sachtouris
        self.url = 'https://www.example.com/pithos'
166 3e6f33ca Stavros Sachtouris
        self.token = 'p17h0570k3n'
167 3e6f33ca Stavros Sachtouris
        self.client = SC(self.url, self.token)
168 3e6f33ca Stavros Sachtouris
        self.client.account = user_id
169 3e6f33ca Stavros Sachtouris
        self.client.container = 'c0nt@1n3r_i'
170 3e6f33ca Stavros Sachtouris
171 3e6f33ca Stavros Sachtouris
    def tearDown(self):
172 3e6f33ca Stavros Sachtouris
        FR.headers = dict()
173 3e6f33ca Stavros Sachtouris
        FR.status_code = 200
174 3e6f33ca Stavros Sachtouris
        FR.json = dict()
175 3e6f33ca Stavros Sachtouris
        FR.content = FR.json
176 3e6f33ca Stavros Sachtouris
        for f in self.files:
177 3e6f33ca Stavros Sachtouris
            f.close()
178 3e6f33ca Stavros Sachtouris
179 3e6f33ca Stavros Sachtouris
    #  Pithos+ methods that extend storage API
180 3e6f33ca Stavros Sachtouris
181 3e6f33ca Stavros Sachtouris
    @patch('%s.head' % client_pkg, return_value=FR())
182 3e6f33ca Stavros Sachtouris
    def test_get_account_info(self, head):
183 3e6f33ca Stavros Sachtouris
        FR.headers = account_info
184 3e6f33ca Stavros Sachtouris
        r = self.client.get_account_info()
185 3e6f33ca Stavros Sachtouris
        self.assert_dicts_are_equal(account_info, r)
186 3e6f33ca Stavros Sachtouris
        self.assertEqual(
187 3e6f33ca Stavros Sachtouris
            head.mock_calls[-1],
188 3e6f33ca Stavros Sachtouris
            call('/%s' % self.client.account, success=(204, 401)))
189 3e6f33ca Stavros Sachtouris
        FR.status_code = 401
190 3e6f33ca Stavros Sachtouris
        self.assertRaises(ClientError, self.client.get_account_info)
191 3e6f33ca Stavros Sachtouris
192 3e6f33ca Stavros Sachtouris
    @patch('%s.post' % storage_pkg, return_value=FR())
193 3e6f33ca Stavros Sachtouris
    @patch('%s.set_header' % storage_pkg)
194 3e6f33ca Stavros Sachtouris
    def test_replace_account_meta(self, SH, post):
195 3e6f33ca Stavros Sachtouris
        metas = dict(k1='v1', k2='v2', k3='v3')
196 3e6f33ca Stavros Sachtouris
        self.client.replace_account_meta(metas)
197 3e6f33ca Stavros Sachtouris
        prfx = 'X-Account-Meta-'
198 3e6f33ca Stavros Sachtouris
        expected = [call('%s%s' % (prfx, k), v) for k, v in metas.items()]
199 3e6f33ca Stavros Sachtouris
        self.assertEqual(SH.mock_calls, expected)
200 3e6f33ca Stavros Sachtouris
        self.assertEqual(
201 3e6f33ca Stavros Sachtouris
            post.mock_calls[-1],
202 3e6f33ca Stavros Sachtouris
            call('/%s' % self.client.account, success=202))
203 3e6f33ca Stavros Sachtouris
204 3e6f33ca Stavros Sachtouris
    @patch('%s.post' % storage_pkg, return_value=FR())
205 3e6f33ca Stavros Sachtouris
    @patch('%s.get_account_info' % storage_pkg, return_value=account_info)
206 3e6f33ca Stavros Sachtouris
    def test_del_account_meta(self, GAI, post):
207 3e6f33ca Stavros Sachtouris
        prfx = 'x-account-meta-'
208 3e6f33ca Stavros Sachtouris
        keys = [k[len(prfx):] for k in account_info if k.startswith(prfx)]
209 3e6f33ca Stavros Sachtouris
        for key in keys:
210 3e6f33ca Stavros Sachtouris
            self.client.del_account_meta(key)
211 3e6f33ca Stavros Sachtouris
            self.assertEqual(
212 3e6f33ca Stavros Sachtouris
                post.mock_calls[-1],
213 3e6f33ca Stavros Sachtouris
                call('/%s' % self.client.account, success=202))
214 3e6f33ca Stavros Sachtouris
        self.assertEqual(len(keys), len(post.mock_calls))
215 3e6f33ca Stavros Sachtouris
        self.assertRaises(ClientError, self.client.del_account_meta, 'k4')
216 3e6f33ca Stavros Sachtouris
217 96befbfd Stavros Sachtouris
    @patch('%s.put' % storage_pkg, return_value=FR())
218 3e6f33ca Stavros Sachtouris
    def test_create_container(self, put):
219 3e6f33ca Stavros Sachtouris
        cont = 's0m3c0n731n3r'
220 3e6f33ca Stavros Sachtouris
        self.client.create_container(cont)
221 96befbfd Stavros Sachtouris
        expected = call('/%s/%s' % (user_id, cont), success=(201, 202))
222 96befbfd Stavros Sachtouris
        self.assertEqual(put.mock_calls[-1], expected)
223 3e6f33ca Stavros Sachtouris
        FR.status_code = 202
224 3e6f33ca Stavros Sachtouris
        self.assertRaises(ClientError, self.client.create_container, cont)
225 3e6f33ca Stavros Sachtouris
226 f3671186 Stavros Sachtouris
    @patch('%s.head' % storage_pkg, return_value=FR())
227 f3671186 Stavros Sachtouris
    def test_get_container_info(self, head):
228 3e6f33ca Stavros Sachtouris
        FR.headers = container_info
229 f3671186 Stavros Sachtouris
        cont = self.client.container
230 f3671186 Stavros Sachtouris
        r = self.client.get_container_info(cont)
231 3e6f33ca Stavros Sachtouris
        self.assert_dicts_are_equal(r, container_info)
232 f3671186 Stavros Sachtouris
        path = '/%s/%s' % (self.client.account, cont)
233 f3671186 Stavros Sachtouris
        self.assertEqual(head.mock_calls[-1], call(path, success=(204, 404)))
234 f3671186 Stavros Sachtouris
        FR.status_code = 404
235 f3671186 Stavros Sachtouris
        self.assertRaises(ClientError, self.client.get_container_info, cont)
236 3e6f33ca Stavros Sachtouris
237 d15e5249 Stavros Sachtouris
    @patch('%s.delete' % storage_pkg, return_value=FR())
238 3e6f33ca Stavros Sachtouris
    def test_delete_container(self, delete):
239 3e6f33ca Stavros Sachtouris
        FR.status_code = 204
240 3e6f33ca Stavros Sachtouris
        cont = 's0m3c0n731n3r'
241 3e6f33ca Stavros Sachtouris
        self.client.delete_container(cont)
242 3e6f33ca Stavros Sachtouris
        for err_code in (404, 409):
243 3e6f33ca Stavros Sachtouris
            FR.status_code = err_code
244 3e6f33ca Stavros Sachtouris
            self.assertRaises(ClientError, self.client.delete_container, cont)
245 3e6f33ca Stavros Sachtouris
        acall = call('/%s/%s' % (user_id, cont), success=(204, 404, 409))
246 3e6f33ca Stavros Sachtouris
        self.assertEqual(delete.mock_calls, [acall] * 3)
247 3e6f33ca Stavros Sachtouris
248 7601a4d5 Stavros Sachtouris
    @patch('%s.get' % storage_pkg, return_value=FR())
249 7601a4d5 Stavros Sachtouris
    @patch('%s.set_param' % storage_pkg)
250 7601a4d5 Stavros Sachtouris
    def test_list_containers(self, SP, get):
251 3e6f33ca Stavros Sachtouris
        FR.json = container_list
252 3e6f33ca Stavros Sachtouris
        r = self.client.list_containers()
253 3e6f33ca Stavros Sachtouris
        for i in range(len(r)):
254 3e6f33ca Stavros Sachtouris
            self.assert_dicts_are_equal(r[i], container_list[i])
255 7601a4d5 Stavros Sachtouris
        self.assertEqual(SP.mock_calls[-1], call('format', 'json'))
256 7601a4d5 Stavros Sachtouris
        self.assertEqual(
257 7601a4d5 Stavros Sachtouris
            get.mock_calls[-1],
258 7601a4d5 Stavros Sachtouris
            call('/%s' % self.client.account, success=(200., 204)))
259 3e6f33ca Stavros Sachtouris
260 c2bf1c19 Stavros Sachtouris
    @patch('%s.put' % storage_pkg, return_value=FR())
261 c2bf1c19 Stavros Sachtouris
    def test_upload_object(self, put):
262 c2bf1c19 Stavros Sachtouris
        (acc, cont) = (self.client.account, self.client.container)
263 c2bf1c19 Stavros Sachtouris
        num_of_blocks = 4
264 3e6f33ca Stavros Sachtouris
        tmpFile = self._create_temp_file(num_of_blocks)
265 c2bf1c19 Stavros Sachtouris
        tmpFile.seek(0, 2)
266 c2bf1c19 Stavros Sachtouris
        sizes = [None, (tmpFile.tell() / num_of_blocks) / 2]
267 c2bf1c19 Stavros Sachtouris
        for size in sizes:
268 3e6f33ca Stavros Sachtouris
            tmpFile.seek(0)
269 c2bf1c19 Stavros Sachtouris
            self.client.upload_object(obj, tmpFile, size)
270 c2bf1c19 Stavros Sachtouris
            tmpFile.seek(0)
271 c2bf1c19 Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1], call(
272 c2bf1c19 Stavros Sachtouris
                '/%s/%s/%s' % (acc, cont, obj),
273 c2bf1c19 Stavros Sachtouris
                data=tmpFile.read(size) if size else tmpFile.read(),
274 c2bf1c19 Stavros Sachtouris
                success=201))
275 3e6f33ca Stavros Sachtouris
276 52228b49 Stavros Sachtouris
    @patch('%s.put' % storage_pkg, return_value=FR())
277 52228b49 Stavros Sachtouris
    @patch('%s.set_header' % storage_pkg)
278 3e6f33ca Stavros Sachtouris
    def test_create_object(self, SH, put):
279 3e6f33ca Stavros Sachtouris
        cont = self.client.container
280 3e6f33ca Stavros Sachtouris
        ctype = 'c0n73n7/typ3'
281 3e6f33ca Stavros Sachtouris
        exp_shd = [
282 3e6f33ca Stavros Sachtouris
            call('Content-Type', 'application/octet-stream'),
283 3e6f33ca Stavros Sachtouris
            call('Content-length', '0'),
284 3e6f33ca Stavros Sachtouris
            call('Content-Type', ctype), call('Content-length', '42')]
285 3e6f33ca Stavros Sachtouris
        exp_put = [call('/%s/%s/%s' % (user_id, cont, obj), success=201)] * 2
286 3e6f33ca Stavros Sachtouris
        self.client.create_object(obj)
287 3e6f33ca Stavros Sachtouris
        self.client.create_object(obj, content_type=ctype, content_length=42)
288 52228b49 Stavros Sachtouris
        self.assertEqual(SH.mock_calls, exp_shd)
289 3e6f33ca Stavros Sachtouris
        self.assertEqual(put.mock_calls, exp_put)
290 3e6f33ca Stavros Sachtouris
291 f13ae956 Stavros Sachtouris
    @patch('%s.put' % storage_pkg, return_value=FR())
292 3e6f33ca Stavros Sachtouris
    @patch('%s.set_header' % client_pkg)
293 3e6f33ca Stavros Sachtouris
    def test_create_directory(self, SH, put):
294 3e6f33ca Stavros Sachtouris
        cont = self.client.container
295 3e6f33ca Stavros Sachtouris
        exp_shd = [
296 3e6f33ca Stavros Sachtouris
            call('Content-Type', 'application/directory'),
297 3e6f33ca Stavros Sachtouris
            call('Content-length', '0')]
298 3e6f33ca Stavros Sachtouris
        exp_put = [call('/%s/%s/%s' % (user_id, cont, obj), success=201)]
299 3e6f33ca Stavros Sachtouris
        self.client.create_directory(obj)
300 f13ae956 Stavros Sachtouris
        self.assertEqual(SH.mock_calls, exp_shd)
301 3e6f33ca Stavros Sachtouris
        self.assertEqual(put.mock_calls, exp_put)
302 3e6f33ca Stavros Sachtouris
303 aa9c7402 Stavros Sachtouris
    @patch('%s.head' % storage_pkg, return_value=FR())
304 aa9c7402 Stavros Sachtouris
    def test_get_object_info(self, head):
305 3e6f33ca Stavros Sachtouris
        FR.headers = object_info
306 aa9c7402 Stavros Sachtouris
        path = '/%s/%s/%s' % (self.client.account, self.client.container, obj)
307 aa9c7402 Stavros Sachtouris
        r = self.client.get_object_info(obj)
308 aa9c7402 Stavros Sachtouris
        self.assertEqual(r, object_info)
309 aa9c7402 Stavros Sachtouris
        self.assertEqual(head.mock_calls[-1], call(path, success=200))
310 3e6f33ca Stavros Sachtouris
311 5ea1e2ac Stavros Sachtouris
    @patch('%s.get_object_info' % storage_pkg, return_value=object_info)
312 3e6f33ca Stavros Sachtouris
    def test_get_object_meta(self, GOI):
313 3e6f33ca Stavros Sachtouris
        r = self.client.get_object_meta(obj)
314 5ea1e2ac Stavros Sachtouris
        prfx = 'x-object-meta-'
315 5ea1e2ac Stavros Sachtouris
        for k in [k for k in object_info if k.startswith(prfx)]:
316 5ea1e2ac Stavros Sachtouris
            self.assertEqual(r.pop(k[len(prfx):]), object_info[k])
317 5ea1e2ac Stavros Sachtouris
        self.assertFalse(len(r))
318 5ea1e2ac Stavros Sachtouris
        self.assertEqual(GOI.mock_calls[-1], call(obj))
319 3e6f33ca Stavros Sachtouris
320 2b752353 Stavros Sachtouris
    @patch('%s.post' % storage_pkg, return_value=FR())
321 2b752353 Stavros Sachtouris
    @patch('%s.set_header' % storage_pkg)
322 2b752353 Stavros Sachtouris
    def test_del_object_meta(self, SH, post):
323 2b752353 Stavros Sachtouris
        key = '50m3m3t4k3y'
324 2b752353 Stavros Sachtouris
        self.client.del_object_meta(obj, key)
325 2b752353 Stavros Sachtouris
        prfx = 'X-Object-Meta-'
326 2b752353 Stavros Sachtouris
        self.assertEqual(SH.mock_calls[-1], call('%s%s' % (prfx, key), ''))
327 2b752353 Stavros Sachtouris
        self.assertEqual(post.mock_calls[-1], call(
328 2b752353 Stavros Sachtouris
            '/%s/%s/%s' % (self.client.account, self.client.container, obj),
329 2b752353 Stavros Sachtouris
            success=202))
330 3e6f33ca Stavros Sachtouris
331 3e6f33ca Stavros Sachtouris
    @patch('%s.post' % client_pkg, return_value=FR())
332 3e6f33ca Stavros Sachtouris
    @patch('%s.set_header' % client_pkg)
333 3e6f33ca Stavros Sachtouris
    def test_replace_object_meta(self, SH, post):
334 3e6f33ca Stavros Sachtouris
        metas = dict(k1='new1', k2='new2', k3='new3')
335 3e6f33ca Stavros Sachtouris
        cont = self.client.container
336 3e6f33ca Stavros Sachtouris
        self.client.replace_object_meta(metas)
337 3e6f33ca Stavros Sachtouris
        expected = call('/%s/%s' % (user_id, cont), success=202)
338 3e6f33ca Stavros Sachtouris
        self.assertEqual(post.mock_calls[-1], expected)
339 3e6f33ca Stavros Sachtouris
        prfx = 'X-Object-Meta-'
340 3e6f33ca Stavros Sachtouris
        expected = [call('%s%s' % (prfx, k), v) for k, v in metas.items()]
341 3941857a Stavros Sachtouris
        self.assertEqual(SH.mock_calls, expected)
342 3e6f33ca Stavros Sachtouris
343 324fee8f Stavros Sachtouris
    @patch('%s.put' % storage_pkg, return_value=FR())
344 324fee8f Stavros Sachtouris
    @patch('%s.set_header' % storage_pkg)
345 324fee8f Stavros Sachtouris
    def test_copy_object(self, SH, put):
346 3e6f33ca Stavros Sachtouris
        src_cont = 'src-c0nt41n3r'
347 3e6f33ca Stavros Sachtouris
        src_obj = 'src-0bj'
348 3e6f33ca Stavros Sachtouris
        dst_cont = 'dst-c0nt41n3r'
349 324fee8f Stavros Sachtouris
        for dst_obj in (None, 'dst-0bj'):
350 324fee8f Stavros Sachtouris
            dst_path = dst_obj or src_obj
351 324fee8f Stavros Sachtouris
            path = '/%s/%s/%s' % (self.client.account, dst_cont, dst_path)
352 324fee8f Stavros Sachtouris
            self.client.copy_object(src_cont, src_obj, dst_cont, dst_obj)
353 324fee8f Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1], call(path, success=201))
354 324fee8f Stavros Sachtouris
            kwargs = {
355 324fee8f Stavros Sachtouris
                'X-Copy-From': '/%s/%s' % (src_cont, src_obj),
356 324fee8f Stavros Sachtouris
                'Content-Length': 0}
357 324fee8f Stavros Sachtouris
            self.assertEqual(
358 324fee8f Stavros Sachtouris
                SH.mock_calls[-2:],
359 324fee8f Stavros Sachtouris
                [call(k, v) for k, v in kwargs.items()])
360 3e6f33ca Stavros Sachtouris
361 73fcb6a2 Stavros Sachtouris
    @patch('%s.put' % storage_pkg, return_value=FR())
362 73fcb6a2 Stavros Sachtouris
    @patch('%s.set_header' % storage_pkg)
363 73fcb6a2 Stavros Sachtouris
    def test_move_object(self, SH, put):
364 3e6f33ca Stavros Sachtouris
        src_cont = 'src-c0nt41n3r'
365 3e6f33ca Stavros Sachtouris
        src_obj = 'src-0bj'
366 3e6f33ca Stavros Sachtouris
        dst_cont = 'dst-c0nt41n3r'
367 73fcb6a2 Stavros Sachtouris
        for dst_obj in (None, 'dst-0bj'):
368 73fcb6a2 Stavros Sachtouris
            dst_path = dst_obj or src_obj
369 73fcb6a2 Stavros Sachtouris
            path = '/%s/%s/%s' % (self.client.account, dst_cont, dst_path)
370 73fcb6a2 Stavros Sachtouris
            self.client.move_object(src_cont, src_obj, dst_cont, dst_obj)
371 73fcb6a2 Stavros Sachtouris
            self.assertEqual(put.mock_calls[-1], call(path, success=201))
372 73fcb6a2 Stavros Sachtouris
            kwargs = {
373 73fcb6a2 Stavros Sachtouris
                'X-Move-From': '/%s/%s' % (src_cont, src_obj),
374 73fcb6a2 Stavros Sachtouris
                'Content-Length': 0}
375 73fcb6a2 Stavros Sachtouris
            self.assertEqual(
376 73fcb6a2 Stavros Sachtouris
                SH.mock_calls[-2:],
377 73fcb6a2 Stavros Sachtouris
                [call(k, v) for k, v in kwargs.items()])
378 3e6f33ca Stavros Sachtouris
379 b23d2558 Stavros Sachtouris
    @patch('%s.delete' % storage_pkg, return_value=FR())
380 3e6f33ca Stavros Sachtouris
    def test_delete_object(self, delete):
381 3e6f33ca Stavros Sachtouris
        cont = self.client.container
382 3e6f33ca Stavros Sachtouris
        self.client.delete_object(obj)
383 3e6f33ca Stavros Sachtouris
        self.assertEqual(
384 3e6f33ca Stavros Sachtouris
            delete.mock_calls[-1],
385 3e6f33ca Stavros Sachtouris
            call('/%s/%s/%s' % (user_id, cont, obj), success=(204, 404)))
386 3e6f33ca Stavros Sachtouris
        FR.status_code = 404
387 3e6f33ca Stavros Sachtouris
        self.assertRaises(ClientError, self.client.delete_object, obj)
388 3e6f33ca Stavros Sachtouris
389 3e6f33ca Stavros Sachtouris
    @patch('%s.get' % client_pkg, return_value=FR())
390 3e6f33ca Stavros Sachtouris
    @patch('%s.set_param' % client_pkg)
391 3e6f33ca Stavros Sachtouris
    def test_list_objects(self, SP, get):
392 3e6f33ca Stavros Sachtouris
        FR.json = object_list
393 7d15ffe9 Stavros Sachtouris
        acc, cont = self.client.account, self.client.container
394 3e6f33ca Stavros Sachtouris
        r = self.client.list_objects()
395 3e6f33ca Stavros Sachtouris
        for i in range(len(r)):
396 3e6f33ca Stavros Sachtouris
            self.assert_dicts_are_equal(r[i], object_list[i])
397 7d15ffe9 Stavros Sachtouris
        self.assertEqual(
398 7d15ffe9 Stavros Sachtouris
            get.mock_calls[-1],
399 7d15ffe9 Stavros Sachtouris
            call('/%s/%s' % (acc, cont), success=(200, 204, 304, 404)))
400 7d15ffe9 Stavros Sachtouris
        self.assertEqual(SP.mock_calls[-1], call('format', 'json'))
401 3e6f33ca Stavros Sachtouris
        FR.status_code = 304
402 3e6f33ca Stavros Sachtouris
        self.assertEqual(self.client.list_objects(), [])
403 3e6f33ca Stavros Sachtouris
        FR.status_code = 404
404 3e6f33ca Stavros Sachtouris
        self.assertRaises(ClientError, self.client.list_objects)
405 3e6f33ca Stavros Sachtouris
406 3e6f33ca Stavros Sachtouris
    @patch('%s.get' % client_pkg, return_value=FR())
407 3e6f33ca Stavros Sachtouris
    @patch('%s.set_param' % client_pkg)
408 3e6f33ca Stavros Sachtouris
    def test_list_objects_in_path(self, SP, get):
409 3e6f33ca Stavros Sachtouris
        FR.json = object_list
410 3e6f33ca Stavros Sachtouris
        path = '/some/awsome/path'
411 e3b8f796 Stavros Sachtouris
        acc, cont = self.client.account, self.client.container
412 3e6f33ca Stavros Sachtouris
        self.client.list_objects_in_path(path)
413 e3b8f796 Stavros Sachtouris
        self.assertEqual(
414 e3b8f796 Stavros Sachtouris
            get.mock_calls[-1],
415 e3b8f796 Stavros Sachtouris
            call('/%s/%s' % (acc, cont), success=(200, 204, 404)))
416 3e6f33ca Stavros Sachtouris
        self.assertEqual(SP.mock_calls, [
417 3e6f33ca Stavros Sachtouris
            call('format', 'json'), call('path', path)])
418 3e6f33ca Stavros Sachtouris
        FR.status_code = 404
419 3e6f33ca Stavros Sachtouris
        self.assertRaises(ClientError, self.client.list_objects)
420 3e6f33ca Stavros Sachtouris
421 3e6f33ca Stavros Sachtouris
if __name__ == '__main__':
422 3e6f33ca Stavros Sachtouris
    from sys import argv
423 3e6f33ca Stavros Sachtouris
    from kamaki.clients.test import runTestCase
424 3e6f33ca Stavros Sachtouris
    runTestCase(Storage, 'Storage Client', argv[1:])