Revision 23028d31

b/pithos/api/tests.py
31 31
# interpreted as representing official policies, either expressed
32 32
# or implied, of GRNET S.A.
33 33

  
34
from django.test.client import Client
35
from django.test import TestCase
34
from pithos.lib.client import Client, Fault
35
import unittest
36 36
from django.utils import simplejson as json
37 37
from xml.dom import minidom
38 38
import types
......
42 42
import random
43 43
import datetime
44 44
import string
45
from pithos.backends import backend
45
import re
46

  
47
#from pithos.backends import backend
46 48

  
47 49
DATE_FORMATS = ["%a %b %d %H:%M:%S %Y",
48 50
                "%A, %d-%b-%y %H:%M:%S GMT",
49 51
                "%a, %d %b %Y %H:%M:%S GMT"]
50 52

  
51
class AaiClient(Client):
52
    def request(self, **request):
53
        request['HTTP_X_AUTH_TOKEN'] = '0000'
54
        return super(AaiClient, self).request(**request)
53
DEFAULT_HOST = 'pithos.dev.grnet.gr'
54
#DEFAULT_HOST = '127.0.0.1:8000'
55
DEFAULT_API = 'v1'
56
DEFAULT_USER = 'papagian'
57
DEFAULT_AUTH = '0004'
55 58

  
56
class BaseTestCase(TestCase):
59
class BaseTestCase(unittest.TestCase):
57 60
    #TODO unauthorized request
58 61
    def setUp(self):
59
        self.client = AaiClient()
62
        self.client = Client(DEFAULT_HOST, DEFAULT_AUTH, DEFAULT_USER, DEFAULT_API)
63
        self.invalid_client = Client(DEFAULT_HOST, DEFAULT_AUTH, 'non-existing', DEFAULT_API)
64
        self.unauthorised_client = Client(DEFAULT_HOST, '', DEFAULT_USER, DEFAULT_API)
60 65
        self.headers = {
61
            'account':(
62
                'X-Account-Container-Count',
63
                'X-Account-Bytes-Used',
64
                'Last-Modified',
65
                'Content-Length',
66
                'Date',
67
                'Content-Type',),
68
            'container':(
69
                'X-Container-Object-Count',
70
                'X-Container-Bytes-Used',
71
                'Content-Type',
72
                'Last-Modified',
73
                'Content-Length',
74
                'Date',
75
                'X-Container-Block-Size',
76
                'X-Container-Block-Hash',
77
                'X-Container-Policy-Quota',
78
                'X-Container-Policy-Versioning',),
79
            'object':(
80
                'ETag',
81
                'Content-Length',
82
                'Content-Type',
83
                'Content-Encoding',
84
                'Last-Modified',
85
                'Date',
86
                'X-Object-Manifest',
87
                'Content-Range',
88
                'X-Object-Modified-By',
89
                'X-Object-Version',
90
                'X-Object-Version-Timestamp',)}
66
            'account': ('x-account-container-count',
67
                        'x-account-bytes-used',
68
                        'last-modified',
69
                        'content-length',
70
                        'date',
71
                        'content-type',
72
                        'server',),
73
            'object': ('etag',
74
                       'content-length',
75
                       'content-type',
76
                       'content-encoding',
77
                       'last-modified',
78
                       'date',
79
                       'x-object-manifest',
80
                       'content-range',
81
                       'x-object-modified-by',
82
                       'x-object-version',
83
                       'x-object-version-timestamp',
84
                       'server',),
85
            'container': ('x-container-object-count',
86
                          'x-container-bytes-used',
87
                          'content-type',
88
                          'last-modified',
89
                          'content-length',
90
                          'date',
91
                          'x-container-block-size',
92
                          'x-container-block-hash',
93
                          'x-container-policy-quota',
94
                          'x-container-policy-versioning',
95
                          'server',
96
                          'x-container-object-meta',
97
                          'x-container-policy-versioning',
98
                          'server',)}
99

  
91 100
        self.contentTypes = {'xml':'application/xml',
92 101
                             'json':'application/json',
93 102
                             '':'text/plain'}
......
106 115
                'last_modified',)}
107 116
        self.return_codes = (400, 401, 404, 503,)
108 117

  
109
    def assertFault(self, response, status_code, name):
110
        self.assertEqual(response.status_code, status_code)
111

  
112
    def assertBadRequest(self, response):
113
        self.assertFault(response, 400, 'badRequest')
114

  
115
    def assertItemNotFound(self, response):
116
        self.assertFault(response, 404, 'itemNotFound')
117

  
118
    def assertUnauthorized(self, response):
119
        self.assertFault(response, 401, 'unauthorized')
120

  
121
    def assertServiceUnavailable(self, response):
122
        self.assertFault(response, 503, 'serviceUnavailable')
123

  
124
    def assertNonEmpty(self, response):
125
        self.assertFault(response, 409, 'nonEmpty')
126

  
127
    def assert_status(self, response, codes):
118
    def assert_status(self, status, codes):
128 119
        l = [elem for elem in self.return_codes]
129 120
        if type(codes) == types.ListType:
130 121
            l.extend(codes)
131 122
        else:
132 123
            l.append(codes)
133
        self.assertTrue(response.status_code in l)
134

  
135
    def get_account_meta(self, account, exp_meta={}):
136
        path = '/v1/%s' % account
137
        response = self.client.head(path)
138
        self.assert_status(response, 204)
139
        self.assert_headers(response, 'account', exp_meta)
140
        return response
141

  
142
    def list_containers(self, account, limit=10000, marker='', format='',
143
                        **headers):
144
        params = locals()
145
        params.pop('self')
146
        params.pop('account')
147
        path = '/v1/%s' % account
148
        response = self.client.get(path, params, **headers)
149
        self.assert_status(response, [200, 204, 304, 412])
150
        response.content = response.content.strip()
151
        if format:
152
            self.assert_extended(response, format, 'container', limit)
124
        self.assertTrue(status in l)
125
    
126
    def assert_list(self, path, entity, limit=10000, format='text', params=None, **headers):
127
        status, headers, data = self.client.get(path, format=format,
128
                                                headers=headers, params=params)
129
        
130
        self.assert_status(status, [200, 204, 304, 412])
131
        if format == 'text':
132
            data = data.strip().split('\n') if data else []
133
            self.assertTrue(len(data) <= limit)
153 134
        else:
154
            names = get_content_splitted(response)
155
            self.assertTrue(len(names) <= limit)
156
        return response
157

  
158
    def update_account_meta(self, account, **metadata):
159
        path = '/v1/%s' % account
160
        response = self.client.post(path, **metadata)
161
        response.content = response.content
162
        self.assert_status(response, 202)
163
        return response
164

  
165
    def get_container_meta(self, account, container, exp_meta={}):
135
            exp_content_type = self.contentTypes[format]
136
            self.assertEqual(headers['content-type'].find(exp_content_type), 0)
137
            #self.assert_extended(data, format, entity, limit)
138
            if format == 'json':
139
                data = json.loads(data) if data else []
140
            elif format == 'xml':
141
                data = minidom.parseString(data)
142
        return status, headers, data
143

  
144
    def list_containers(self, limit=10000, marker='', format='text', **headers):
166 145
        params = locals()
167 146
        params.pop('self')
168
        params.pop('account')
169
        params.pop('container')
170
        path = '/v1/%s/%s' %(account, container)
171
        response = self.client.head(path, params)
172
        response.content = response.content
173
        self.assert_status(response, 204)
174
        if response.status_code == 204:
175
            self.assert_headers(response, 'container', exp_meta)
176
        return response
177

  
178
    def list_objects(self, account, container, limit=10000, marker='',
147
        return self.assert_list('', 'account', limit, format, params, **headers)
148
    
149
    def list_objects(self, container, limit=10000, marker='',
179 150
                     prefix='', format='', path='', delimiter='', meta='',
180 151
                     **headers):
181 152
        params = locals()
182 153
        params.pop('self')
183
        params.pop('account')
184 154
        params.pop('container')
185
        path = '/v1/%s/%s' % (account, container)
186
        response = self.client.get(path, params, **headers)
187
        response.content = response.content.strip()
188
        if format:
189
            self.assert_extended(response, format, 'object', limit)
190
        self.assert_status(response, [200, 204, 304, 412])
191
        return response
192

  
193
    def create_container(self, account, name, **meta):
194
        path = '/v1/%s/%s' %(account, name)
195
        response = self.client.put(path, **meta)
196
        response.content = response.content
197
        self.assert_status(response, [201, 202])
198
        return response
199

  
200
    def update_container_meta(self, account, name, **meta):
201
        path = '/v1/%s/%s' %(account, name)
202
        response = self.client.post(path,
203
                                    data=None,
204
                                    content_type='text/xml',
205
                                    follow=False, **meta)
206
        response.content = response.content
207
        self.assert_status(response, 202)
208
        return response
209

  
210
    def delete_container(self, account, container):
211
        path = '/v1/%s/%s' %(account, container)
212
        response = self.client.delete(path)
213
        response.content = response.content
214
        self.assert_status(response, [204, 409])
215
        return response
216

  
217
    def get_object_meta(self, account, container, name):
218
        path = '/v1/%s/%s/%s' %(account, container, name)
219
        response = self.client.head(path)
220
        response.content = response.content
221
        self.assert_status(response, 200)
222
        return response
223

  
224
    def get_object(self, account, container, name, format='', **headers):
225
        path = '/v1/%s/%s/%s' %(account, container, name)
226
        response = self.client.get(path, {'format':format}, **headers)
227
        response.content = response.content
228
        self.assert_status(response, [200, 206, 304, 412, 416])
229
        if response.status_code in [200, 206]:
230
            self.assert_headers(response, 'object')
231
        return response
232

  
233
    def upload_object(self, account, container, name, data, content_type='',
234
                      **headers):
235
        path = '/v1/%s/%s/%s' %(account, container, name)
236
        response = self.client.put(path, data, content_type, **headers)
237
        response.content = response.content
238
        self.assert_status(response, [201, 411, 422])
239
        if response.status_code == 201:
240
            self.assertTrue(response['Etag'])
241
        return response
242

  
243
    def copy_object(self, account, container, name, src, **headers):
244
        path = '/v1/%s/%s/%s' %(account, container, name)
245
        headers['HTTP_X_COPY_FROM'] = src
246
        response = self.client.put(path, **headers)
247
        response.content = response.content
248
        self.assert_status(response, 201)
249
        return response
250

  
251
    def move_object(self, account, container, name, src, **headers):
252
        path = '/v1/%s/%s/%s' % (account, container, name)
253
        headers['HTTP_X_MOVE_FROM'] = src
254
        response = self.client.put(path, **headers)
255
        response.content = response.content
256
        self.assert_status(response, 201)
257
        return response
258

  
259
    def update_object(self, account, container, name, data='',
260
                      content_type='', **headers):
261
        path = '/v1/%s/%s/%s' %(account, container, name)
262
        response = self.client.post(path, data, content_type, **headers)
263
        response.content = response.content
264
        self.assert_status(response, [202, 204, 416])
265
        return response
266

  
267
    def delete_object(self, account, container, name):
268
        path = '/v1/%s/%s/%s' %(account, container, name)
269
        response = self.client.delete(path)
270
        response.content = response.content
271
        self.assert_status(response, 204)
272
        return response
273

  
274
    def assert_headers(self, response, type, exp_meta={}):
275
        entities = ['Account', 'Container', 'Container-Object', 'Object']
276
        user_defined_meta = ['X-%s-Meta' %elem for elem in entities]
277
        headers = [item for item in response._headers.values()]
278
        t = tuple(user_defined_meta)
279
        system_headers = [h for h in headers if not h[0].startswith(t)]
280
        for h in system_headers:
281
            self.assertTrue(h[0] in self.headers[type])
282
            if exp_meta:
283
                self.assertEqual(h[1], exp_meta[h[0]])
284

  
285
    def assert_extended(self, response, format, type, size):
286
        exp_content_type = self.contentTypes[format]
287
        self.assertEqual(response['Content-Type'].find(exp_content_type), 0)
288
        if format == 'xml':
289
            self.assert_xml(response, type, size)
290
        elif format == 'json':
291
            self.assert_json(response, type, size)
292

  
293
    def assert_json(self, response, type, size):
294
        convert = lambda s: s.lower()
295
        info = [convert(elem) for elem in self.extended[type]]
296
        data = json.loads(response.content)
297
        self.assertTrue(len(data) <= size)
298
        for item in info:
299
            for i in data:
300
                if 'subdir' in i.keys():
301
                    continue
302
                self.assertTrue(item in i.keys())
303

  
304
    def assert_xml(self, response, type, size):
305
        convert = lambda s: s.lower()
306
        info = [convert(elem) for elem in self.extended[type]]
307
        try:
308
            info.remove('content_encoding')
309
        except ValueError:
310
            pass
311
        xml = minidom.parseString(response.content)
312
        for item in info:
313
            nodes = xml.getElementsByTagName(item)
314
            self.assertTrue(nodes)
315
            self.assertTrue(len(nodes) <= size)
316
            
155
        path = '/' + container
156
        format = 'text' if format == '' else format
157
        return self.assert_list(path, 'container', limit, format, params, **headers)
158
    
159
    def _assert_get_meta(self, path, entity, params=None, **exp_meta):
160
        status, headers, data = self.client.head(path, params)
161
        self.assert_status(status, 204)
162
        #self.assert_headers(headers, entity, **exp_meta)
163
        return status, headers, data
164
    
165
    def get_account_meta(self, params=None, **exp_meta):
166
        return self._assert_get_meta('', 'account', params, **exp_meta)
317 167

  
318
    def upload_os_file(self, account, container, fullpath, meta={}):
319
        try:
320
            f = open(fullpath, 'r')
321
            data = f.read()
322
            name = os.path.split(fullpath)[-1]
323
            return self.upload_data(account, container, name, data)    
324
        except IOError:
325
            return
168
    def get_container_meta(self, container, params=None, **exp_meta):
169
        path = '/%s' % container
170
        return self._assert_get_meta(path, 'container', params, **exp_meta)
326 171

  
327
    def upload_random_data(self, account, container, name, length=1024,
328
                           meta={}):
172
    def create_container(self, name, **meta):
173
        headers = {}
174
        for k,v in meta.items():
175
            headers['x-container-meta-%s' %k.strip().upper()] = v.strip()
176
        status, header, data = self.client.put('/' + name, headers=headers)
177
        self.assert_status(status, [201, 202])
178
        return status, header, data
179
    
180
    def get_object(self, container, name, format='', version=None, **headers):
181
        path = '/%s/%s' % (container, name)
182
        params = {'version':version} if version else None 
183
        status, headers, data = self.client.get(path, format, headers, params)
184
        self.assert_status(status, [200, 206, 304, 412, 416])
185
        #if status in [200, 206]:
186
        #    self.assert_headers(headers, 'object')
187
        return status, headers, data
188
    
189
    def update_object(self, container, name, data='', content_type='', **headers):
190
        if content_type != '':
191
            headers['content-type'] = content_type
192
        status, headers, data = self.client.update_object_data(container,
193
                                                               name,
194
                                                               data,
195
                                                               headers)
196
        self.assert_status(status, [202, 204, 416])
197
        return status, headers, data
198

  
199
    def assert_headers(self, headers, type, **exp_meta):
200
        prefix = 'x-%s-meta-' %type
201
        system_headers = [h for h in headers if not h.startswith(prefix)]
202
        for k,v in headers.items():
203
            if k in system_headers:
204
                self.assertTrue(k in headers[type])
205
            elif exp_meta:
206
                k = k.split(prefix)[-1]
207
                self.assertEqual(v, exp_meta[k])
208

  
209
    #def assert_extended(self, data, format, type, size):
210
    #    if format == 'xml':
211
    #        self._assert_xml(data, type, size)
212
    #    elif format == 'json':
213
    #        self._assert_json(data, type, size)
214
    #
215
    #def _assert_json(self, data, type, size):
216
    #    print '#', data
217
    #    convert = lambda s: s.lower()
218
    #    info = [convert(elem) for elem in self.extended[type]]
219
    #    data = json.loads(data)
220
    #    self.assertTrue(len(data) <= size)
221
    #    for item in info:
222
    #        for i in data:
223
    #            if 'subdir' in i.keys():
224
    #                continue
225
    #            self.assertTrue(item in i.keys())
226
    #
227
    #def _assert_xml(self, data, type, size):
228
    #    print '#', data
229
    #    convert = lambda s: s.lower()
230
    #    info = [convert(elem) for elem in self.extended[type]]
231
    #    try:
232
    #        info.remove('content_encoding')
233
    #    except ValueError:
234
    #        pass
235
    #    xml = minidom.parseString(data)
236
    #    entities = xml.getElementsByTagName(type)
237
    #    self.assertTrue(len(entities) <= size)
238
    #    for e in entities:
239
    #        for item in info:
240
    #            self.assertTrue(e.hasAttribute(item))
241
    
242
    def assert_raises_fault(self, status, callableObj, *args, **kwargs):
243
        """
244
        asserts that a Fault with a specific status is raised
245
        when callableObj is called with the specific arguments
246
        """
247
        try:
248
            callableObj(*args, **kwargs)
249
            self.fail('Should never reach here')
250
        except Fault, f:
251
            self.failUnless(f.status == status)
252
    
253
    def assert_object_exists(self, container, object):
254
        """
255
        asserts the existence of an object
256
        """
257
        try:
258
            self.client.retrieve_object_metadata(container, object)
259
        except Fault, f:
260
            self.failIf(f.status == 404)
261
    
262
    def assert_object_not_exists(self, container, object):
263
        """
264
        asserts there is no such an object
265
        """
266
        self.assert_raises_fault(404, self.client.retrieve_object_metadata,
267
                                 container, object)
268

  
269
    def upload_random_data(self, container, name, length=1024, type=None,
270
                           enc=None, **meta):
329 271
        data = get_random_data(length)
330
        return self.upload_data(account, container, name, data, meta)
272
        return self.upload_data(container, name, data, type, enc, **meta)
331 273

  
332
    def upload_data(self, account, container, name, data, meta={}):
274
    def upload_data(self, container, name, data, type=None, enc=None, etag=None,
275
                    **meta):
333 276
        obj = {}
334 277
        obj['name'] = name
335 278
        try:
336 279
            obj['data'] = data
337 280
            obj['hash'] = compute_md5_hash(obj['data'])
338
            meta.update({'HTTP_X_OBJECT_META_TEST':'test1',
339
                         'HTTP_ETAG':obj['hash']})
340
            type, enc = mimetypes.guess_type(name)
341
            meta['HTTP_CONTENT_TYPE'] = type and type or 'plain/text'
342
            if enc:
343
                meta['HTTP_CONTENT_ENCODING'] = enc
344 281
            
345
            obj['meta'] = meta
346
            r = self.upload_object(account,
347
                               container,
348
                               obj['name'],
349
                               obj['data'],
350
                               meta['HTTP_CONTENT_TYPE'],
351
                               **meta)
352
            if r.status_code == 201:
282
            headers = {}
283
            for k,v in meta.items():
284
                key = 'x-object-meta-%s' % k
285
                headers[key] = v
286
            headers['etag'] = etag if etag else obj['hash']
287
            guess = mimetypes.guess_type(name)
288
            type = type if type else guess[0]
289
            enc = enc if enc else guess[1]
290
            headers['content-type'] = type if type else 'plain/text'
291
            headers['content-encoding'] = enc if enc else None
292
            obj['meta'] = headers
293
            
294
            path = '/%s/%s' % (container, name)
295
            status, headers, data = self.client.put(path, obj['data'],
296
                                                    headers=headers)
297
            if status == 201:
298
                self.assertTrue('etag' in headers)
299
                self.assertEqual(obj['hash'], headers['etag'])
353 300
                return obj
354 301
        except IOError:
355 302
            return
......
360 307
        self.account = 'test'
361 308
        self.containers = ['apples', 'bananas', 'kiwis', 'oranges', 'pears']
362 309
        for item in self.containers:
363
            self.create_container(self.account, item)
310
            self.create_container(item)
364 311

  
365 312
    def tearDown(self):
366
        for c in  get_content_splitted(self.list_containers(self.account)):
367
            self.delete_container(self.account, c)
368

  
313
        for c in  self.list_containers()[2]:
314
            self.client.delete_container(c)
315
        
369 316
    def test_get_account_meta(self):
370
        response = self.get_account_meta(self.account)
371
        r2 = self.list_containers(self.account)
372
        containers =  get_content_splitted(r2)
317
        headers = self.get_account_meta()[1]
318
        
319
        containers = self.list_containers()[2]
373 320
        l = str(len(containers))
374
        self.assertEqual(response['X-Account-Container-Count'], l)
321
        self.assertEqual(headers['x-account-container-count'], l)
375 322
        size = 0
376 323
        for c in containers:
377
            r = self.get_container_meta(self.account, c)
378
            size = size + int(r['X-Container-Bytes-Used'])
379
        self.assertEqual(response['X-Account-Bytes-Used'], str(size))
324
            h = self.get_container_meta(c)[1]
325
            size = size + int(h['x-container-bytes-used'])
326
        self.assertEqual(headers['x-account-bytes-used'], str(size))
380 327

  
381 328
    #def test_get_account_401(self):
382 329
    #    response = self.get_account_meta('non-existing-account')
......
390 337
        #create some containers
391 338
        self.containers = ['apples', 'bananas', 'kiwis', 'oranges', 'pears']
392 339
        for item in self.containers:
393
            self.create_container(self.account, item)
340
            self.create_container(item)
394 341

  
395 342
    def tearDown(self):
396
        for c in get_content_splitted(self.list_containers(self.account)):
397
            response = self.delete_container(self.account, c)
343
        for c in self.list_containers()[2]:
344
            for o in self.list_objects(c)[2]:
345
                self.client.delete_object(c, o)
346
            self.client.delete_container(c)
398 347

  
399 348
    def test_list(self):
400 349
        #list containers
401
        response = self.list_containers(self.account)
402
        containers = get_content_splitted(response)
350
        containers = self.list_containers()[2]
403 351
        self.assertEquals(self.containers, containers)
404 352

  
405 353
    #def test_list_204(self):
......
408 356

  
409 357
    def test_list_with_limit(self):
410 358
        limit = 2
411
        response = self.list_containers(self.account, limit=limit)
412
        containers = get_content_splitted(response)
359
        containers = self.list_containers(limit=limit)[2]
413 360
        self.assertEquals(len(containers), limit)
414 361
        self.assertEquals(self.containers[:2], containers)
415 362

  
416 363
    def test_list_with_marker(self):
417 364
        l = 2
418 365
        m = 'bananas'
419
        response = self.list_containers(self.account, limit=l, marker=m)
420
        containers =  get_content_splitted(response)
366
        containers = self.list_containers(limit=l, marker=m)[2]
421 367
        i = self.containers.index(m) + 1
422 368
        self.assertEquals(self.containers[i:(i+l)], containers)
423 369
        
424 370
        m = 'oranges'
425
        response = self.list_containers(self.account, limit=l, marker=m)
426
        containers = get_content_splitted(response)
371
        containers = self.list_containers(limit=l, marker=m)[2]
427 372
        i = self.containers.index(m) + 1
428 373
        self.assertEquals(self.containers[i:(i+l)], containers)
429 374

  
......
434 379
    def test_list_json_with_marker(self):
435 380
        l = 2
436 381
        m = 'bananas'
437
        response = self.list_containers(self.account, limit=l, marker=m,
382
        status, headers, containers = self.list_containers(limit=l, marker=m,
438 383
                                        format='json')
439
        containers = json.loads(response.content)
440 384
        self.assertEqual(containers[0]['name'], 'kiwis')
441 385
        self.assertEqual(containers[1]['name'], 'oranges')
442 386

  
443 387
    def test_list_xml_with_marker(self):
444 388
        l = 2
445 389
        m = 'oranges'
446
        response = self.list_containers(self.account, limit=l, marker=m,
390
        status, headers, xml = self.list_containers(limit=l, marker=m,
447 391
                                        format='xml')
448
        xml = minidom.parseString(response.content)
449 392
        nodes = xml.getElementsByTagName('name')
450 393
        self.assertEqual(len(nodes), 1)
451 394
        self.assertEqual(nodes[0].childNodes[0].data, 'pears')
......
455 398
        t2 = t - datetime.timedelta(minutes=10)
456 399
        
457 400
        #add a new container
458
        self.create_container(self.account,
459
                              'dummy')
401
        self.create_container('dummy')
460 402

  
461 403
        for f in DATE_FORMATS:
462 404
            past = t2.strftime(f)
463 405
            
464
            headers = {'HTTP_IF_MODIFIED_SINCE':'%s' %past}
465
            r = self.list_containers(self.account, **headers)
406
            headers = {'if-modified-since':'%s' %past}
407
            status, headers, data = self.list_containers(**headers)
466 408
            
467 409
            #assert get success
468
            self.assertEqual(r.status_code, 200)
410
            self.assertEqual(status, 200)
469 411

  
470 412
    def test_if_modified_since_invalid_date(self):
471
        headers = {'HTTP_IF_MODIFIED_SINCE':''}
472
        r = self.list_containers(self.account, **headers)
413
        headers = {'if-modified-since':''}
414
        status, headers, data = self.list_containers(**headers)
473 415
            
474 416
        #assert get success
475
        self.assertEqual(r.status_code, 200)
417
        self.assertEqual(status, 200)
476 418

  
477 419
    def test_if_not_modified_since(self):
478 420
        now = datetime.datetime.utcnow()
479 421
        since = now + datetime.timedelta(1)
480 422
        
481 423
        for f in DATE_FORMATS:
482
            headers = {'HTTP_IF_MODIFIED_SINCE':'%s' %since.strftime(f)}
483
            r = self.list_containers(self.account, **headers)
484
            
424
            headers = {'if-modified-since':'%s' %since.strftime(f)}
485 425
            #assert not modified
486
            self.assertEqual(r.status_code, 304)
426
            self.assert_raises_fault(304, self.list_containers, **headers)
487 427

  
488 428
    def test_if_unmodified_since(self):
489 429
        now = datetime.datetime.utcnow()
490 430
        since = now + datetime.timedelta(1)
491 431
        
492 432
        for f in DATE_FORMATS:
493
            headers = {'HTTP_IF_UNMODIFIED_SINCE':'%s' %since.strftime(f)}
494
            r = self.list_containers(self.account, **headers)
433
            headers = {'if-unmodified-since':'%s' %since.strftime(f)}
434
            status, headers, data = self.list_containers(**headers)
495 435
            
496 436
            #assert success
497
            self.assertEqual(r.status_code, 200)
498
            self.assertEqual(self.containers, get_content_splitted(r))
437
            self.assertEqual(status, 200)
438
            self.assertEqual(self.containers, data)
499 439

  
500 440
    def test_if_unmodified_since_precondition_failed(self):
501 441
        t = datetime.datetime.utcnow()
502 442
        t2 = t - datetime.timedelta(minutes=10)
503 443
        
504 444
        #add a new container
505
        self.create_container(self.account,
506
                              'dummy')
445
        self.create_container('dummy')
507 446
        
508 447
        for f in DATE_FORMATS:
509 448
            past = t2.strftime(f)
510 449
            
511
            headers = {'HTTP_IF_UNMODIFIED_SINCE':'%s' %past}
512
            r = self.list_containers(self.account, **headers)
513
            
514
            #assert get success
515
            self.assertEqual(r.status_code, 412)
450
            headers = {'if-unmodified-since':'%s' %past}
451
            #assert precondition failed
452
            self.assert_raises_fault(412, self.list_containers, **headers)
516 453

  
517 454
class AccountPost(BaseTestCase):
518 455
    def setUp(self):
......
520 457
        self.account = 'test'
521 458
        self.containers = ['apples', 'bananas', 'kiwis', 'oranges', 'pears']
522 459
        for item in self.containers:
523
            self.create_container(self.account, item)
460
            self.create_container(item)
524 461

  
525 462
    def tearDown(self):
526
        for c in  get_content_splitted(self.list_containers(self.account)):
527
            self.delete_container(self.account, c)
463
        containers = self.list_containers()[2]
464
        for c in  containers:
465
            self.client.delete_container(c)
528 466

  
529 467
    def test_update_meta(self):
530
        meta = {'HTTP_X_ACCOUNT_META_TEST':'test',
531
                'HTTP_X_ACCOUNT_META_TOST':'tost'}
532
        response = self.update_account_meta(self.account, **meta)
533
        response = self.get_account_meta(self.account)
534
        for k,v in meta.items():
535
            key = '-'.join(elem.capitalize() for elem in k.split('_')[1:])
536
            self.assertTrue(response[key])
537
            self.assertEqual(response[key], v)
538

  
468
        meta = {'test':'test', 'tost':'tost'}
469
        status, headers, data = self.get_account_meta(**meta)
470
    
539 471
    #def test_invalid_account_update_meta(self):
540
    #    with AssertInvariant(self.get_account_meta, self.account):
472
    #    with AssertMappingInvariant(self.get_account_meta, self.account):
541 473
    #        meta = {'HTTP_X_ACCOUNT_META_TEST':'test',
542 474
    #               'HTTP_X_ACCOUNT_META_TOST':'tost'}
543 475
    #        response = self.update_account_meta('non-existing-account', **meta)
544

  
476
    
545 477
class ContainerHead(BaseTestCase):
546 478
    def setUp(self):
547 479
        BaseTestCase.setUp(self)
548 480
        self.account = 'test'
549 481
        self.container = 'apples'
550
        self.create_container(self.account, self.container)
482
        status = self.create_container(self.container)[0]
551 483

  
552 484
    def tearDown(self):
553
        for o in self.list_objects(self.account, self.container):
554
            self.delete_object(self.account, self.container, o)
555
        self.delete_container(self.account, self.container)
485
        for o in self.list_objects(self.container)[2]:
486
            self.client.delete_object(self.container, o)
487
        self.client.delete_container(self.container)
556 488

  
557 489
    def test_get_meta(self):
558
        headers = {'HTTP_X_OBJECT_META_TRASH':'true'}
490
        meta = {'trash':'true'}
559 491
        t1 = datetime.datetime.utcnow()
560
        o = self.upload_random_data(self.account,
561
                                self.container,
562
                                'McIntosh.jpg',
563
                                meta=headers)
492
        o = self.upload_random_data(self.container, o_names[0], **meta)
564 493
        if o:
565
            r = self.get_container_meta(self.account,
566
                                        self.container)
567
            self.assertEqual(r['X-Container-Object-Count'], '1')
568
            self.assertEqual(r['X-Container-Bytes-Used'], str(len(o['data'])))
569
            t2 = datetime.datetime.strptime(r['Last-Modified'], DATE_FORMATS[2])
494
            status, headers, data = self.get_container_meta(self.container)
495
            self.assertEqual(headers['x-container-object-count'], '1')
496
            self.assertEqual(headers['x-container-bytes-used'], str(len(o['data'])))
497
            t2 = datetime.datetime.strptime(headers['last-modified'], DATE_FORMATS[2])
570 498
            delta = (t2 - t1)
571 499
            threashold = datetime.timedelta(seconds=1) 
572 500
            self.assertTrue(delta < threashold)
573
            self.assertTrue(r['X-Container-Object-Meta'])
574
            self.assertTrue('Trash' in r['X-Container-Object-Meta'])
501
            self.assertTrue(headers['x-container-object-meta'])
502
            self.assertTrue('Trash' in headers['x-container-object-meta'])
575 503

  
576 504
class ContainerGet(BaseTestCase):
577 505
    def setUp(self):
......
579 507
        self.account = 'test'
580 508
        self.container = ['pears', 'apples']
581 509
        for c in self.container:
582
            self.create_container(self.account, c)
510
            self.create_container(c)
583 511
        self.obj = []
584 512
        for o in o_names[:8]:
585
            self.obj.append(self.upload_random_data(self.account,
586
                                                    self.container[0],
587
                                                    o))
513
            self.obj.append(self.upload_random_data(self.container[0], o))
588 514
        for o in o_names[8:]:
589
            self.obj.append(self.upload_random_data(self.account,
590
                                                    self.container[1],
591
                                                    o))
515
            self.obj.append(self.upload_random_data(self.container[1], o))
592 516

  
593 517
    def tearDown(self):
594 518
        for c in self.container:
595
            for obj in get_content_splitted(self.list_objects(self.account, c)):
596
                self.delete_object(self.account, c, obj)
597
            self.delete_container(self.account, c)
519
            for obj in self.list_objects(c)[2]:
520
                self.client.delete_object(c, obj)
521
            self.client.delete_container(c)
598 522

  
599 523
    def test_list_objects(self):
600
        response = self.list_objects(self.account, self.container[0])
601
        objects = get_content_splitted(response)
524
        objects = self.list_objects(self.container[0])[2]
602 525
        l = [elem['name'] for elem in self.obj[:8]]
603 526
        l.sort()
604 527
        self.assertEqual(objects, l)
605 528

  
606 529
    def test_list_objects_with_limit_marker(self):
607
        response = self.list_objects(self.account, self.container[0], limit=2)
608
        objects = get_content_splitted(response)
530
        objects = self.list_objects(self.container[0], limit=2)[2]
609 531
        l = [elem['name'] for elem in self.obj[:8]]
610 532
        l.sort()
611 533
        self.assertEqual(objects, l[:2])
......
614 536
                   'moms_birthday.jpg']
615 537
        limit = 4
616 538
        for m in markers:
617
            response = self.list_objects(self.account, self.container[0],
618
                                         limit=limit, marker=m)
619
            objects = get_content_splitted(response)
539
            objects = self.list_objects(self.container[0], limit=limit,
540
                                        marker=m)[2]
620 541
            l = [elem['name'] for elem in self.obj[:8]]
621 542
            l.sort()
622 543
            start = l.index(m) + 1
......
625 546
            self.assertEqual(objects, l[start:end])
626 547

  
627 548
    def test_list_pseudo_hierarchical_folders(self):
628
        response = self.list_objects(self.account, self.container[1],
629
                                     prefix='photos', delimiter='/')
630
        objects = get_content_splitted(response)
549
        objects = self.list_objects(self.container[1], prefix='photos',
550
                                     delimiter='/')[2]
631 551
        self.assertEquals(['photos/animals/', 'photos/me.jpg',
632 552
                           'photos/plants/'], objects)
633 553
        
634
        response = self.list_objects(self.account, self.container[1],
635
                                     prefix='photos/animals', delimiter='/')
636
        objs = get_content_splitted(response)
554
        objects = self.list_objects(self.container[1], prefix='photos/animals',
555
                                     delimiter='/')[2]
637 556
        l = ['photos/animals/cats/', 'photos/animals/dogs/']
638
        self.assertEquals(l, objs)
557
        self.assertEquals(l, objects)
639 558
        
640
        response = self.list_objects(self.account, self.container[1],
641
                                     path='photos')
642
        objects = get_content_splitted(response)
559
        objects = self.list_objects(self.container[1], path='photos')[2]
643 560
        self.assertEquals(['photos/me.jpg'], objects)
644 561

  
645 562
    def test_extended_list_json(self):
646
        response = self.list_objects(self.account,
647
                                     self.container[1],
563
        objects = self.list_objects(self.container[1],
648 564
                                     format='json', limit=2,
649 565
                                     prefix='photos/animals',
650
                                     delimiter='/')
651
        objects = json.loads(response.content)
566
                                     delimiter='/')[2]
652 567
        self.assertEqual(objects[0]['subdir'], 'photos/animals/cats/')
653 568
        self.assertEqual(objects[1]['subdir'], 'photos/animals/dogs/')
654 569

  
655 570
    def test_extended_list_xml(self):
656
        response = self.list_objects(self.account, self.container[1],
657
                                     format='xml', limit=4, prefix='photos',
658
                                     delimiter='/')
659
        xml = minidom.parseString(response.content)
571
        xml = self.list_objects(self.container[1], format='xml', limit=4,
572
                                prefix='photos', delimiter='/')[2]
660 573
        dirs = xml.getElementsByTagName('subdir')
661 574
        self.assertEqual(len(dirs), 2)
662 575
        self.assertEqual(dirs[0].attributes['name'].value, 'photos/animals/')
......
667 580
        self.assertEqual(objects[0].childNodes[0].data, 'photos/me.jpg')
668 581

  
669 582
    def test_list_meta_double_matching(self):
670
        meta = {'HTTP_X_OBJECT_META_QUALITY':'aaa',
671
                'HTTP_X_OBJECT_META_STOCK':'true'}
672
        r = self.update_object(self.account,
673
                                    self.container[0],
674
                                    self.obj[0]['name'],
675
                                    
676
                                    **meta)
677
        r = self.list_objects(self.account,
678
                          self.container[0],
679
                          meta='Quality,Stock')
680
        self.assertEqual(r.status_code, 200)
681
        obj = get_content_splitted(r)
583
        meta = {'quality':'aaa', 'stock':'true'}
584
        self.client.update_object_metadata(self.container[0],
585
                                           self.obj[0]['name'], **meta)
586
        obj = self.list_objects(self.container[0], meta='Quality,Stock')[2]
682 587
        self.assertEqual(len(obj), 1)
683 588
        self.assertTrue(obj, self.obj[0]['name'])
684 589

  
685 590
    def test_list_using_meta(self):
686
        meta = {'HTTP_X_OBJECT_META_QUALITY':'aaa'}
591
        meta = {'quality':'aaa'}
687 592
        for o in self.obj[:2]:
688
            r = self.update_object(self.account,
689
                                    self.container[0],
690
                                    o['name'],
691
                                    **meta)
692
        meta = {'HTTP_X_OBJECT_META_STOCK':'true'}
593
            self.client.update_object_metadata(self.container[0], o['name'],
594
                                               **meta)
595
        meta = {'stock':'true'}
693 596
        for o in self.obj[3:5]:
694
            r = self.update_object(self.account,
695
                                    self.container[0],
696
                                    o['name'],
697
                                    **meta)
698
        
699
        r = self.list_objects(self.account,
700
                          self.container[0],
701
                          meta='Quality')
702
        self.assertEqual(r.status_code, 200)
703
        obj = get_content_splitted(r)
704
        self.assertEqual(len(obj), 2)
705
        self.assertTrue(obj, [o['name'] for o in self.obj[:2]])
597
            self.client.update_object_metadata(self.container[0], o['name'],
598
                                               **meta)
599
        
600
        status, headers, data = self.list_objects(self.container[0],
601
                                                  meta='Quality')
602
        self.assertEqual(status, 200)
603
        self.assertEqual(len(data), 2)
604
        self.assertTrue(data, [o['name'] for o in self.obj[:2]])
706 605
        
707 606
        # test case insensitive
708
        r = self.list_objects(self.account,
709
                          self.container[0],
710
                          meta='quality')
711
        self.assertEqual(r.status_code, 200)
712
        obj = get_content_splitted(r)
607
        status, headers, obj = self.list_objects(self.container[0],
608
                                                  meta='quality')
609
        self.assertEqual(status, 200)
713 610
        self.assertEqual(len(obj), 2)
714 611
        self.assertTrue(obj, [o['name'] for o in self.obj[:2]])
715 612
        
716 613
        # test multiple matches
717
        r = self.list_objects(self.account,
718
                          self.container[0],
719
                          meta='Quality,Stock')
720
        self.assertEqual(r.status_code, 200)
721
        obj = get_content_splitted(r)
614
        status, headers, obj = self.list_objects(self.container[0],
615
                                                  meta='Quality,Stock')
616
        self.assertEqual(status, 200)
722 617
        self.assertEqual(len(obj), 4)
723 618
        self.assertTrue(obj, [o['name'] for o in self.obj[:4]])
724 619
        
725 620
        # test non 1-1 multiple match
726
        r = self.list_objects(self.account,
727
                          self.container[0],
728
                          meta='Quality,aaaa')
729
        self.assertEqual(r.status_code, 200)
730
        obj = get_content_splitted(r)
621
        status, headers, obj = self.list_objects(self.container[0],
622
                                                  meta='Quality,aaaa')
623
        self.assertEqual(status, 200)
731 624
        self.assertEqual(len(obj), 2)
732 625
        self.assertTrue(obj, [o['name'] for o in self.obj[:2]])
733 626

  
......
735 628
        t = datetime.datetime.utcnow()
736 629
        t2 = t - datetime.timedelta(minutes=10)
737 630
        
738
        #add a new container
739
        self.upload_random_data(self.account,
740
                                self.container[0],
741
                                'dummy.txt')
631
        #add a new object
632
        self.upload_random_data(self.container[0], o_names[0])
742 633

  
743 634
        for f in DATE_FORMATS:
744 635
            past = t2.strftime(f)
745 636
            
746
            headers = {'HTTP_IF_MODIFIED_SINCE':'%s' %past}
747
            r = self.list_objects(self.account,
748
                                  self.container[0], **headers)
637
            headers = {'if-modified-since':'%s' %past}
638
            status, headers, data = self.list_objects(self.container[0],
639
                                                      **headers)
749 640
            
750 641
            #assert get success
751
            self.assertEqual(r.status_code, 200)
642
            self.assertEqual(status, 200)
752 643

  
753 644
    def test_if_modified_since_invalid_date(self):
754
        headers = {'HTTP_IF_MODIFIED_SINCE':''}
755
        r = self.list_objects(self.account,
756
                              self.container[0], **headers)
645
        headers = {'if-modified-since':''}
646
        status, headers, data = self.list_objects(self.container[0], **headers)
757 647
        
758 648
        #assert get success
759
        self.assertEqual(r.status_code, 200)
649
        self.assertEqual(status, 200)
760 650

  
761 651
    def test_if_not_modified_since(self):
762 652
        now = datetime.datetime.utcnow()
763 653
        since = now + datetime.timedelta(1)
764 654
        
765 655
        for f in DATE_FORMATS:
766
            headers = {'HTTP_IF_MODIFIED_SINCE':'%s' %since.strftime(f)}
767
            r = self.list_objects(self.account,
768
                              self.container[0], **headers)
769
        
656
            headers = {'if-modified-since':'%s' %since.strftime(f)}
770 657
            #assert not modified
771
            self.assertEqual(r.status_code, 304)
772

  
658
            self.assert_raises_fault(304, self.list_objects, self.container[0],
659
                                     **headers)
660
    
773 661
    def test_if_unmodified_since(self):
774 662
        now = datetime.datetime.utcnow()
775 663
        since = now + datetime.timedelta(1)
776 664
        
777 665
        for f in DATE_FORMATS:
778
            headers = {'HTTP_IF_UNMODIFIED_SINCE':'%s' %since.strftime(f)}
779
            r = self.list_objects(self.account,
780
                              self.container[0], **headers)
781
        
666
            headers = {'if-unmodified-since':'%s' %since.strftime(f)}
667
            status, headers, data = self.list_objects(self.container[0], **headers)
668
            
782 669
            #assert success
783
            self.assertEqual(r.status_code, 200)
784
            objlist = self.list_objects(self.account, self.container[0])
785
            self.assertEqual(get_content_splitted(r),
786
                             get_content_splitted(objlist))
670
            self.assertEqual(status, 200)
671
            objlist = self.list_objects(self.container[0])[2]
672
            self.assertEqual(data, objlist)
787 673

  
788 674
    def test_if_unmodified_since_precondition_failed(self):
789 675
        t = datetime.datetime.utcnow()
790 676
        t2 = t - datetime.timedelta(minutes=10)
791 677
        
792 678
        #add a new container
793
        self.create_container(self.account,
794
                              'dummy')
679
        self.create_container('dummy')
795 680

  
796 681
        for f in DATE_FORMATS:
797 682
            past = t2.strftime(f)
798 683
            
799
            headers = {'HTTP_IF_UNMODIFIED_SINCE':'%s' %past}
800
            r = self.list_objects(self.account,
801
                              self.container[0], **headers)
802
        
803
            #assert get success
804
            self.assertEqual(r.status_code, 412)
684
            headers = {'if-unmodified-since':'%s' %past}
685
            #assert precondition failed
686
            self.assert_raises_fault(412, self.list_objects, self.container[0],
687
                                     **headers)
805 688

  
806 689
class ContainerPut(BaseTestCase):
807 690
    def setUp(self):
......
810 693
        self.containers = ['c1', 'c2']
811 694

  
812 695
    def tearDown(self):
813
        for c in self.containers:
814
            r = self.delete_container(self.account, c)
696
        for c in self.list_containers()[2]:
697
            r = self.client.delete_container(c)
815 698

  
816 699
    def test_create(self):
817
        response = self.create_container(self.account, self.containers[0])
818
        if response.status_code == 201:
819
            response = self.list_containers(self.account)
820
            content = get_content_splitted(response)
821
            self.assertTrue(self.containers[0] in content)
822
            r = self.get_container_meta(self.account, self.containers[0])
823
            self.assertEqual(r.status_code, 204)
700
        status = self.create_container(self.containers[0])[0]
701
        self.assertEqual(status, 201)
702
        
703
        containers = self.list_containers()[2]
704
        self.assertTrue(self.containers[0] in containers)
705
        status = self.get_container_meta(self.containers[0])[0]
706
        self.assertEqual(status, 204)
824 707

  
825 708
    def test_create_twice(self):
826
        response = self.create_container(self.account, self.containers[0])
827
        if response.status_code == 201:
828
            r = self.create_container(self.account, self.containers[0])
829
            self.assertTrue(r.status_code, 202)
709
        status, header, data = self.create_container(self.containers[0])
710
        if status == 201:
711
            status, header, data = self.create_container(self.containers[0])
712
            self.assertTrue(status, 202)
830 713

  
831 714
class ContainerPost(BaseTestCase):
832 715
    def setUp(self):
833 716
        BaseTestCase.setUp(self)
834 717
        self.account = 'test'
835 718
        self.container = 'apples'
836
        self.create_container(self.account, self.container)
719
        self.create_container(self.container)
837 720

  
838 721
    def tearDown(self):
839
        for o in self.list_objects(self.account, self.container):
840
            self.delete_object(self.account, self.container, o)
841
        self.delete_container(self.account, self.container)
722
        for o in self.list_objects(self.container)[2]:
723
            self.client.delete_object(self.account, self.container, o)
724
        self.client.delete_container(self.container)
842 725

  
843 726
    def test_update_meta(self):
844
        meta = {'HTTP_X_CONTAINER_META_TEST':'test33',
845
                'HTTP_X_CONTAINER_META_TOST':'tost22'}
846
        response = self.update_container_meta(self.account, self.container,
847
                                              **meta)
848
        response = self.get_container_meta(self.account, self.container)
727
        meta = {'test':'test33',
728
                'tost':'tost22'}
729
        self.client.update_container_metadata(self.container, **meta)
730
        headers = self.get_container_meta(self.container)[1]
849 731
        for k,v in meta.items():
850
            key = '-'.join(elem.capitalize() for elem in k.split('_')[1:])
851
            self.assertTrue(response[key])
852
            self.assertEqual(response[key], v)
732
            k = 'x-container-meta-%s' % k
733
            self.assertTrue(headers[k])
734
            self.assertEqual(headers[k], v)
853 735

  
854 736
class ContainerDelete(BaseTestCase):
855 737
    def setUp(self):
......
857 739
        self.account = 'test'
858 740
        self.containers = ['c1', 'c2']
859 741
        for c in self.containers:
860
            self.create_container(self.account, c)
861
        self.upload_random_data(self.account,
862
                                self.containers[1],
863
                                'nice.jpg')
742
            self.create_container(c)
743
        self.upload_random_data(self.containers[1], o_names[0])
864 744

  
865 745
    def tearDown(self):
866
        for c in self.containers:
867
            for o in get_content_splitted(self.list_objects(self.account, c)):
868
                self.delete_object(self.account, c, o)
869
            self.delete_container(self.account, c)
746
        for c in self.list_containers()[2]:
747
            for o in self.list_objects(c)[2]:
748
                self.client.delete_object(c, o)
749
            self.client.delete_container(c)
870 750

  
871 751
    def test_delete(self):
872
        r = self.delete_container(self.account, self.containers[0])
873
        self.assertEqual(r.status_code, 204)
752
        status = self.client.delete_container(self.containers[0])[0]
753
        self.assertEqual(status, 204)
874 754

  
875 755
    def test_delete_non_empty(self):
876
        r = self.delete_container(self.account, self.containers[1])
877
        self.assertNonEmpty(r)
756
        self.assert_raises_fault(409, self.client.delete_container,
757
                                 self.containers[1])
878 758

  
879 759
    def test_delete_invalid(self):
880
        self.assertItemNotFound(self.delete_container(self.account, 'c3'))
760
        self.assert_raises_fault(404, self.client.delete_container, 'c3')
881 761

  
882 762
class ObjectHead(BaseTestCase):
883 763
    pass
......
889 769
        self.containers = ['c1', 'c2']
890 770
        #create some containers
891 771
        for c in self.containers:
892
            self.create_container(self.account, c)
772
            self.create_container(c)
893 773
        
894 774
        #upload a file
775
        names = ('obj1', 'obj2')
895 776
        self.objects = []
896
        self.objects.append(self.upload_os_file(self.account,
897
                            self.containers[1],
898
                            './api/tests.py'))
899
        self.objects.append(self.upload_os_file(self.account,
900
                            self.containers[1],
901
                            'settings.py'))
777
        for n in names:
778
            self.objects.append(self.upload_random_data(self.containers[1], n))
902 779

  
903 780
    def tearDown(self):
904 781
        for c in self.containers:
905
            for o in get_content_splitted(self.list_objects(self.account, c)):
906
                self.delete_object(self.account, c, o)
907
            self.delete_container(self.account, c)
782
            for o in self.list_objects(c)[2]:
783
                self.client.delete_object(c, o)
784
            self.client.delete_container(c)
908 785

  
909 786
    def test_get(self):
910 787
        #perform get
911
        r = self.get_object(self.account,
912
                            self.containers[1],
788
        status, headers, data = self.get_object(self.containers[1],
913 789
                            self.objects[0]['name'],
914 790
                            self.objects[0]['meta'])
915 791
        #assert success
916
        self.assertEqual(r.status_code, 200)
792
        self.assertEqual(status, 200)
917 793
        
918 794
        #assert content-type
919
        self.assertEqual(r['Content-Type'],
920
                         self.objects[0]['meta']['HTTP_CONTENT_TYPE'])
795
        self.assertEqual(headers['content-type'],
796
                         self.objects[0]['meta']['content-type'])
921 797

  
922 798
    def test_get_invalid(self):
923
        r = self.get_object(self.account,
924
                            self.containers[0],
925
                            self.objects[0]['name'])
926
        self.assertItemNotFound(r)
799
        self.assert_raises_fault(404, self.get_object, self.containers[0],
800
                                 self.objects[0]['name'])
927 801

  
928 802
    def test_get_partial(self):
929 803
        #perform get with range
930
        headers = {'HTTP_RANGE':'bytes=0-499'}
931
        r = self.get_object(self.account,
932
                        self.containers[1],
933
                        self.objects[0]['name'],
934
                        **headers)
804
        headers = {'range':'bytes=0-499'}
805
        status, headers, data = self.get_object(self.containers[1],
806
                                                self.objects[0]['name'],
807
                                                **headers)
935 808
        
936 809
        #assert successful partial content
937
        self.assertEqual(r.status_code, 206)
810
        self.assertEqual(status, 206)
938 811
        
939 812
        #assert content-type
940
        self.assertEqual(r['Content-Type'],
941
                         self.objects[0]['meta']['HTTP_CONTENT_TYPE'])
813
        self.assertEqual(headers['content-type'],
814
                         self.objects[0]['meta']['content-type'])
942 815
        
943 816
        #assert content length
944
        self.assertEqual(int(r['Content-Length']), 500)
817
        self.assertEqual(int(headers['content-length']), 500)
945 818
        
946 819
        #assert content
947
        self.assertEqual(self.objects[0]['data'][:500], r.content)
820
        self.assertEqual(self.objects[0]['data'][:500], data)
948 821

  
949 822
    def test_get_final_500(self):
950 823
        #perform get with range
951
        headers = {'HTTP_RANGE':'bytes=-500'}
952
        r = self.get_object(self.account,
953
                        self.containers[1],
954
                        self.objects[0]['name'],
955
                        **headers)
824
        headers = {'range':'bytes=-500'}
825
        status, headers, data = self.get_object(self.containers[1],
826
                                                self.objects[0]['name'],
827
                                                **headers)
956 828
        
957 829
        #assert successful partial content
958
        self.assertEqual(r.status_code, 206)
830
        self.assertEqual(status, 206)
959 831
        
960 832
        #assert content-type
961
        self.assertEqual(r['Content-Type'],
962
                         self.objects[0]['meta']['HTTP_CONTENT_TYPE'])
833
        self.assertEqual(headers['content-type'],
834
                         self.objects[0]['meta']['content-type'])
963 835
        
964 836
        #assert content length
965
        self.assertEqual(int(r['Content-Length']), 500)
837
        self.assertEqual(int(headers['content-length']), 500)
966 838
        
967 839
        #assert content
968
        self.assertTrue(self.objects[0]['data'][-500:], r.content)
840
        self.assertTrue(self.objects[0]['data'][-500:], data)
969 841

  
970 842
    def test_get_rest(self):
971 843
        #perform get with range
972 844
        offset = len(self.objects[0]['data']) - 500
973
        headers = {'HTTP_RANGE':'bytes=%s-' %offset}
974
        r = self.get_object(self.account,
975
                        self.containers[1],
976
                        self.objects[0]['name'],
977
                        **headers)
845
        headers = {'range':'bytes=%s-' %offset}
846
        status, headers, data = self.get_object(self.containers[1],
847
                                                self.objects[0]['name'],
848
                                                **headers)
978 849
        
979 850
        #assert successful partial content
980
        self.assertEqual(r.status_code, 206)
851
        self.assertEqual(status, 206)
981 852
        
982 853
        #assert content-type
983
        self.assertEqual(r['Content-Type'],
984
                         self.objects[0]['meta']['HTTP_CONTENT_TYPE'])
854
        self.assertEqual(headers['content-type'],
855
                         self.objects[0]['meta']['content-type'])
985 856
        
986 857
        #assert content length
987
        self.assertEqual(int(r['Content-Length']), 500)
858
        self.assertEqual(int(headers['content-length']), 500)
988 859
        
989 860
        #assert content
990
        self.assertTrue(self.objects[0]['data'][-500:], r.content)
861
        self.assertTrue(self.objects[0]['data'][-500:], data)
991 862

  
992 863
    def test_get_range_not_satisfiable(self):
993 864
        #perform get with range
994 865
        offset = len(self.objects[0]['data']) + 1
995
        headers = {'HTTP_RANGE':'bytes=0-%s' %offset}
996
        r = self.get_object(self.account,
997
                        self.containers[1],
998
                        self.objects[0]['name'],
999
                        **headers)
866
        headers = {'range':'bytes=0-%s' %offset}
1000 867
        
1001
        #assert Range Not Satisfiable
1002
        self.assertEqual(r.status_code, 416)
868
        #assert range not satisfiable
869
        self.assert_raises_fault(416, self.get_object, self.containers[1],
870
                                 self.objects[0]['name'], **headers)
1003 871

  
1004 872
    def test_multiple_range(self):
1005 873
        #perform get with multiple range
1006 874
        ranges = ['0-499', '-500', '1000-']
1007
        headers = {'HTTP_RANGE' : 'bytes=%s' % ','.join(ranges)}
1008
        r = self.get_object(self.account,
1009
                        self.containers[1],
1010
                        self.objects[0]['name'],
1011
                        **headers)
875
        headers = {'range' : 'bytes=%s' % ','.join(ranges)}
876
        status, headers, data = self.get_object(self.containers[1],
877
                                                self.objects[0]['name'],
878
                                                **headers)
1012 879
        
1013 880
        # assert partial content
1014
        self.assertEqual(r.status_code, 206)
881
        self.assertEqual(status, 206)
1015 882
        
1016 883
        # assert Content-Type of the reply will be multipart/byteranges
1017
        self.assertTrue(r['Content-Type'])
1018
        content_type_parts = r['Content-Type'].split()
884
        self.assertTrue(headers['content-type'])
885
        content_type_parts = headers['content-type'].split()
1019 886
        self.assertEqual(content_type_parts[0], ('multipart/byteranges;'))
1020 887
        
1021 888
        boundary = '--%s' %content_type_parts[1].split('=')[-1:][0]
1022
        cparts = r.content.split(boundary)[1:-1]
889
        cparts = data.split(boundary)[1:-1]
1023 890
        
1024 891
        # assert content parts are exactly 2
1025 892
        self.assertEqual(len(cparts), len(ranges))
......
1054 921
        #perform get with multiple range
1055 922
        out_of_range = len(self.objects[0]['data']) + 1
1056 923
        ranges = ['0-499', '-500', '%d-' %out_of_range]
1057
        headers = {'HTTP_RANGE' : 'bytes=%s' % ','.join(ranges)}
1058
        r = self.get_object(self.account,
1059
                        self.containers[1],
1060
                        self.objects[0]['name'],
1061
                        **headers)
924
        headers = {'range' : 'bytes=%s' % ','.join(ranges)}
1062 925
        
1063 926
        # assert partial content
1064
        self.assertEqual(r.status_code, 416)
927
        self.assert_raises_fault(416, self.get_object, self.containers[1],
928
                            self.objects[0]['name'], **headers)
929

  
1065 930

  
1066 931
    def test_get_with_if_match(self):
1067 932
        #perform get with If-Match
1068
        headers = {'HTTP_IF_MATCH':self.objects[0]['hash']}
1069
        r = self.get_object(self.account,
1070
                        self.containers[1],
1071
                        self.objects[0]['name'],
1072
                        **headers)
933
        headers = {'if-match':self.objects[0]['hash']}
934
        status, headers, data = self.get_object(self.containers[1],
935
                                                self.objects[0]['name'],
936
                                                **headers)
1073 937
        #assert get success
1074
        self.assertEqual(r.status_code, 200)
938
        self.assertEqual(status, 200)
1075 939
        
1076 940
        #assert content-type
1077
        self.assertEqual(r['Content-Type'],
1078
                         self.objects[0]['meta']['HTTP_CONTENT_TYPE'])
941
        self.assertEqual(headers['content-type'],
942
                         self.objects[0]['meta']['content-type'])
1079 943
        
1080 944
        #assert response content
1081
        self.assertEqual(self.objects[0]['data'].strip(), r.content.strip())
945
        self.assertEqual(self.objects[0]['data'], data)
1082 946

  
1083 947
    def test_get_with_if_match_star(self):
1084 948
        #perform get with If-Match *
1085
        headers = {'HTTP_IF_MATCH':'*'}
1086
        r = self.get_object(self.account,
1087
                        self.containers[1],
1088
                        self.objects[0]['name'],
1089
                        **headers)
949
        headers = {'if-match':'*'}
950
        status, headers, data = self.get_object(self.containers[1],
951
                                                self.objects[0]['name'],
952
                                                **headers)
1090 953
        #assert get success
1091
        self.assertEqual(r.status_code, 200)
954
        self.assertEqual(status, 200)
1092 955
        
1093 956
        #assert content-type
1094
        self.assertEqual(r['Content-Type'],
1095
                         self.objects[0]['meta']['HTTP_CONTENT_TYPE'])
957
        self.assertEqual(headers['content-type'],
958
                         self.objects[0]['meta']['content-type'])
1096 959
        
1097 960
        #assert response content
1098
        self.assertEqual(self.objects[0]['data'].strip(), r.content.strip())
961
        self.assertEqual(self.objects[0]['data'], data)
1099 962

  
1100 963
    def test_get_with_multiple_if_match(self):
1101 964
        #perform get with If-Match
1102 965
        etags = [i['hash'] for i in self.objects if i]
1103 966
        etags = ','.join('"%s"' % etag for etag in etags)
1104
        headers = {'HTTP_IF_MATCH':etags}
1105
        r = self.get_object(self.account,
1106
                        self.containers[1],
1107
                        self.objects[0]['name'],
1108
                        **headers)
967
        headers = {'if-match':etags}
968
        status, headers, data = self.get_object(self.containers[1],
969
                                                self.objects[0]['name'],
970
                                                **headers)
1109 971
        #assert get success
1110
        self.assertEqual(r.status_code, 200)
972
        self.assertEqual(status, 200)
1111 973
        
1112 974
        #assert content-type
1113
        self.assertEqual(r['Content-Type'],
1114
                         self.objects[0]['meta']['HTTP_CONTENT_TYPE'])
975
        self.assertEqual(headers['content-type'],
976
                         self.objects[0]['meta']['content-type'])
1115 977
        
1116 978
        #assert content-type
1117
        self.assertEqual(r['Content-Type'],
1118
                         self.objects[0]['meta']['HTTP_CONTENT_TYPE'])
979
        self.assertEqual(headers['content-type'],
980
                         self.objects[0]['meta']['content-type'])
1119 981
        
1120 982
        #assert response content
1121
        self.assertEqual(self.objects[0]['data'].strip(), r.content.strip())
983
        self.assertEqual(self.objects[0]['data'], data)
1122 984

  
1123 985
    def test_if_match_precondition_failed(self):
1124 986
        #perform get with If-Match
1125
        headers = {'HTTP_IF_MATCH':'123'}
1126
        r = self.get_object(self.account,
1127
                        self.containers[1],
1128
                        self.objects[0]['name'],
1129
                        **headers)
1130
        #assert precondition failed 
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff