Revision 25c3841c

b/docs/source/client-lib.rst
1
Client Library
2
=============
3

  
4
.. automodule:: pithos.lib.client
b/docs/source/clients.rst
1
Clients
2
========
3

  
4
.. toctree::
5
   :maxdepth: 1
6
   
7
   client-lib
b/docs/source/index.rst
9 9
   devguide
10 10
   adminguide
11 11
   backends
12

  
12
   clients
13 13

  
14 14
Indices and tables
15 15
==================
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 pithos.lib.client import Client, Fault
34
from pithos.lib.client import Pithos_Client, Fault
35 35
import unittest
36 36
from django.utils import simplejson as json
37 37
from xml.dom import minidom
38
from StringIO import StringIO
38 39
import types
39 40
import hashlib
40 41
import os
......
59 60
class BaseTestCase(unittest.TestCase):
60 61
    #TODO unauthorized request
61 62
    def setUp(self):
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)
63
        self.client = Pithos_Client(DEFAULT_HOST, DEFAULT_AUTH, DEFAULT_USER, DEFAULT_API)
65 64
        self.headers = {
66 65
            'account': ('x-account-container-count',
67 66
                        'x-account-bytes-used',
68 67
                        'last-modified',
69 68
                        'content-length',
70 69
                        'date',
71
                        'content-type',
70
                        'content_type',
72 71
                        'server',),
73 72
            'object': ('etag',
74 73
                       'content-length',
75
                       'content-type',
74
                       'content_type',
76 75
                       'content-encoding',
77 76
                       'last-modified',
78 77
                       'date',
......
84 83
                       'server',),
85 84
            'container': ('x-container-object-count',
86 85
                          'x-container-bytes-used',
87
                          'content-type',
86
                          'content_type',
88 87
                          'last-modified',
89 88
                          'content-length',
90 89
                          'date',
......
96 95
                          'x-container-object-meta',
97 96
                          'x-container-policy-versioning',
98 97
                          'server',)}
99

  
98
        
100 99
        self.contentTypes = {'xml':'application/xml',
101 100
                             'json':'application/json',
102 101
                             '':'text/plain'}
......
114 113
                'content_encoding',
115 114
                'last_modified',)}
116 115
        self.return_codes = (400, 401, 404, 503,)
117

  
116
    
117
    def tearDown(self):
118
        for c in self.client.list_containers():
119
            for o in self.client.list_objects(c):
120
                self.client.delete_object(c, o)
121
            self.client.delete_container(c)
122
    
118 123
    def assert_status(self, status, codes):
119 124
        l = [elem for elem in self.return_codes]
120 125
        if type(codes) == types.ListType:
......
123 128
            l.append(codes)
124 129
        self.assertTrue(status in l)
125 130
    
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)
134
        else:
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):
145
        params = locals()
146
        params.pop('self')
147
        return self.assert_list('', 'account', limit, format, params, **headers)
148
    
149
    def list_objects(self, container, limit=10000, marker='',
150
                     prefix='', format='', path='', delimiter='', meta='',
151
                     **headers):
152
        params = locals()
153
        params.pop('self')
154
        params.pop('container')
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)
167

  
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)
171

  
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

  
131
    #def assert_list(self, path, entity, limit=10000, format='text', params=None, **headers):
132
    #    status, headers, data = self.client.get(path, format=format,
133
    #                                            headers=headers, params=params)
134
    #    
135
    #    self.assert_status(status, [200, 204, 304, 412])
136
    #    if format == 'text':
137
    #        data = data.strip().split('\n') if data else []
138
    #        self.assertTrue(len(data) <= limit)
139
    #    else:
140
    #        exp_content_type = self.contentTypes[format]
141
    #        self.assertEqual(headers['content_type'].find(exp_content_type), 0)
142
    #        #self.assert_extended(data, format, entity, limit)
143
    #        if format == 'json':
144
    #            data = json.loads(data) if data else []
145
    #        elif format == 'xml':
146
    #            data = minidom.parseString(data)
147
    #    return status, headers, data
148
    
199 149
    def assert_headers(self, headers, type, **exp_meta):
200 150
        prefix = 'x-%s-meta-' %type
201 151
        system_headers = [h for h in headers if not h.startswith(prefix)]
......
205 155
            elif exp_meta:
206 156
                k = k.split(prefix)[-1]
207 157
                self.assertEqual(v, exp_meta[k])
208

  
158
    
209 159
    #def assert_extended(self, data, format, type, size):
210 160
    #    if format == 'xml':
211 161
    #        self._assert_xml(data, type, size)
212 162
    #    elif format == 'json':
213 163
    #        self._assert_json(data, type, size)
214
    #
164
    
215 165
    #def _assert_json(self, data, type, size):
216 166
    #    print '#', data
217 167
    #    convert = lambda s: s.lower()
......
223 173
    #            if 'subdir' in i.keys():
224 174
    #                continue
225 175
    #            self.assertTrue(item in i.keys())
226
    #
176
    
227 177
    #def _assert_xml(self, data, type, size):
228 178
    #    print '#', data
229 179
    #    convert = lambda s: s.lower()
......
250 200
        except Fault, f:
251 201
            self.failUnless(f.status == status)
252 202
    
203
    def assert_container_exists(self, container):
204
        """
205
        asserts the existence of a container
206
        """
207
        try:
208
            self.client.retrieve_container_metadata(container)
209
        except Fault, f:
210
            self.failIf(f.status == 404)
211
    
253 212
    def assert_object_exists(self, container, object):
254 213
        """
255 214
        asserts the existence of an object
......
265 224
        """
266 225
        self.assert_raises_fault(404, self.client.retrieve_object_metadata,
267 226
                                 container, object)
268

  
227
    
269 228
    def upload_random_data(self, container, name, length=1024, type=None,
270 229
                           enc=None, **meta):
271 230
        data = get_random_data(length)
272 231
        return self.upload_data(container, name, data, type, enc, **meta)
273

  
232
    
274 233
    def upload_data(self, container, name, data, type=None, enc=None, etag=None,
275 234
                    **meta):
276 235
        obj = {}
......
279 238
            obj['data'] = data
280 239
            obj['hash'] = compute_md5_hash(obj['data'])
281 240
            
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']
241
            args = {}
242
            args['etag'] = etag if etag else obj['hash']
243
            
287 244
            guess = mimetypes.guess_type(name)
288 245
            type = type if type else guess[0]
289 246
            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
247
            args['content_type'] = type if type else 'plain/text'
248
            args['content_encoding'] = enc if enc else None
249
            
250
            obj['meta'] = args
293 251
            
294 252
            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'])
300
                return obj
253
            self.client.create_object(container, name, StringIO(obj['data']),
254
                                      meta, **args)
255
            
256
            return obj
301 257
        except IOError:
302 258
            return
303 259

  
......
307 263
        self.account = 'test'
308 264
        self.containers = ['apples', 'bananas', 'kiwis', 'oranges', 'pears']
309 265
        for item in self.containers:
310
            self.create_container(item)
311

  
312
    def tearDown(self):
313
        for c in  self.list_containers()[2]:
314
            self.client.delete_container(c)
315
        
266
            self.client.create_container(item)
267
    
316 268
    def test_get_account_meta(self):
317
        headers = self.get_account_meta()[1]
269
        meta = self.client.retrieve_account_metadata()
318 270
        
319
        containers = self.list_containers()[2]
271
        containers = self.client.list_containers()
320 272
        l = str(len(containers))
321
        self.assertEqual(headers['x-account-container-count'], l)
273
        self.assertEqual(meta['x-account-container-count'], l)
322 274
        size = 0
323 275
        for c in containers:
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))
327

  
276
            m = self.client.retrieve_container_metadata(c)
277
            size = size + int(m['x-container-bytes-used'])
278
        self.assertEqual(meta['x-account-bytes-used'], str(size))
279
    
328 280
    #def test_get_account_401(self):
329 281
    #    response = self.get_account_meta('non-existing-account')
330 282
    #    print response
......
337 289
        #create some containers
338 290
        self.containers = ['apples', 'bananas', 'kiwis', 'oranges', 'pears']
339 291
        for item in self.containers:
340
            self.create_container(item)
341

  
342
    def tearDown(self):
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)
347

  
292
            self.client.create_container(item)
293
    
348 294
    def test_list(self):
349 295
        #list containers
350
        containers = self.list_containers()[2]
296
        containers = self.client.list_containers()
351 297
        self.assertEquals(self.containers, containers)
352

  
298
    
353 299
    #def test_list_204(self):
354 300
    #    response = self.list_containers('non-existing-account')
355 301
    #    self.assertEqual(response.status_code, 204)
356

  
302
    
357 303
    def test_list_with_limit(self):
358 304
        limit = 2
359
        containers = self.list_containers(limit=limit)[2]
305
        containers = self.client.list_containers(limit=limit)
360 306
        self.assertEquals(len(containers), limit)
361 307
        self.assertEquals(self.containers[:2], containers)
362

  
308
    
363 309
    def test_list_with_marker(self):
364 310
        l = 2
365 311
        m = 'bananas'
366
        containers = self.list_containers(limit=l, marker=m)[2]
312
        containers = self.client.list_containers(limit=l, marker=m)
367 313
        i = self.containers.index(m) + 1
368 314
        self.assertEquals(self.containers[i:(i+l)], containers)
369 315
        
370 316
        m = 'oranges'
371
        containers = self.list_containers(limit=l, marker=m)[2]
317
        containers = self.client.list_containers(limit=l, marker=m)
372 318
        i = self.containers.index(m) + 1
373 319
        self.assertEquals(self.containers[i:(i+l)], containers)
374

  
320
    
375 321
    #def test_extended_list(self):
376 322
    #    self.list_containers(self.account, limit=3, format='xml')
377 323
    #    self.list_containers(self.account, limit=3, format='json')
378

  
324
    
379 325
    def test_list_json_with_marker(self):
380 326
        l = 2
381 327
        m = 'bananas'
382
        status, headers, containers = self.list_containers(limit=l, marker=m,
383
                                        format='json')
328
        containers = self.client.list_containers(limit=l, marker=m, detail=True)
384 329
        self.assertEqual(containers[0]['name'], 'kiwis')
385 330
        self.assertEqual(containers[1]['name'], 'oranges')
386

  
387
    def test_list_xml_with_marker(self):
388
        l = 2
389
        m = 'oranges'
390
        status, headers, xml = self.list_containers(limit=l, marker=m,
391
                                        format='xml')
392
        nodes = xml.getElementsByTagName('name')
393
        self.assertEqual(len(nodes), 1)
394
        self.assertEqual(nodes[0].childNodes[0].data, 'pears')
395

  
331
    
332
    #def test_list_xml_with_marker(self):
333
    #    l = 2
334
    #    m = 'oranges'
335
    #    status, headers, xml = self.list_containers(limit=l, marker=m, format='xml')
336
    #    nodes = xml.getElementsByTagName('name')
337
    #    self.assertEqual(len(nodes), 1)
338
    #    self.assertEqual(nodes[0].childNodes[0].data, 'pears')
339
    
396 340
    def test_if_modified_since(self):
397 341
        t = datetime.datetime.utcnow()
398 342
        t2 = t - datetime.timedelta(minutes=10)
399 343
        
400 344
        #add a new container
401
        self.create_container('dummy')
402

  
345
        self.client.create_container('dummy')
346
        
403 347
        for f in DATE_FORMATS:
404 348
            past = t2.strftime(f)
405
            
406
            headers = {'if-modified-since':'%s' %past}
407
            status, headers, data = self.list_containers(**headers)
408
            
409
            #assert get success
410
            self.assertEqual(status, 200)
411

  
349
            try:
350
                c = self.client.list_containers(if_modified_since=past)
351
                self.assertEqual(len(c), len(self.containers) + 1)
352
            except Fault, f:
353
                self.failIf(f.status == 304) #fail if not modified
354
    
412 355
    def test_if_modified_since_invalid_date(self):
413
        headers = {'if-modified-since':''}
414
        status, headers, data = self.list_containers(**headers)
415
            
416
        #assert get success
417
        self.assertEqual(status, 200)
418

  
356
        c = self.client.list_containers(if_modified_since='')
357
        self.assertEqual(len(c), len(self.containers))
358
    
419 359
    def test_if_not_modified_since(self):
420 360
        now = datetime.datetime.utcnow()
421 361
        since = now + datetime.timedelta(1)
422 362
        
423 363
        for f in DATE_FORMATS:
424
            headers = {'if-modified-since':'%s' %since.strftime(f)}
364
            args = {'if_modified_since':'%s' %since.strftime(f)}
365
            
425 366
            #assert not modified
426
            self.assert_raises_fault(304, self.list_containers, **headers)
427

  
367
            self.assert_raises_fault(304, self.client.list_containers, **args)
368
    
428 369
    def test_if_unmodified_since(self):
429 370
        now = datetime.datetime.utcnow()
430 371
        since = now + datetime.timedelta(1)
431 372
        
432 373
        for f in DATE_FORMATS:
433
            headers = {'if-unmodified-since':'%s' %since.strftime(f)}
434
            status, headers, data = self.list_containers(**headers)
374
            c = self.client.list_containers(if_unmodified_since=since.strftime(f))
435 375
            
436 376
            #assert success
437
            self.assertEqual(status, 200)
438
            self.assertEqual(self.containers, data)
439

  
377
            self.assertEqual(self.containers, c)
378
    
440 379
    def test_if_unmodified_since_precondition_failed(self):
441 380
        t = datetime.datetime.utcnow()
442 381
        t2 = t - datetime.timedelta(minutes=10)
443 382
        
444 383
        #add a new container
445
        self.create_container('dummy')
384
        self.client.create_container('dummy')
446 385
        
447 386
        for f in DATE_FORMATS:
448 387
            past = t2.strftime(f)
449 388
            
450
            headers = {'if-unmodified-since':'%s' %past}
389
            args = {'if_unmodified_since':'%s' %past}
390
            
451 391
            #assert precondition failed
452
            self.assert_raises_fault(412, self.list_containers, **headers)
453

  
392
            self.assert_raises_fault(412, self.client.list_containers, **args)
393
    
454 394
class AccountPost(BaseTestCase):
455 395
    def setUp(self):
456 396
        BaseTestCase.setUp(self)
457 397
        self.account = 'test'
458 398
        self.containers = ['apples', 'bananas', 'kiwis', 'oranges', 'pears']
459 399
        for item in self.containers:
460
            self.create_container(item)
461

  
462
    def tearDown(self):
463
        containers = self.list_containers()[2]
464
        for c in  containers:
465
            self.client.delete_container(c)
466

  
400
            self.client.create_container(item)
401
    
467 402
    def test_update_meta(self):
468 403
        meta = {'test':'test', 'tost':'tost'}
469
        status, headers, data = self.get_account_meta(**meta)
404
        self.client.update_account_metadata(**meta)
405
        self.assertEqual(meta, self.client.retrieve_account_metadata(restricted=True))
470 406
    
471 407
    #def test_invalid_account_update_meta(self):
472 408
    #    with AssertMappingInvariant(self.get_account_meta, self.account):
473 409
    #        meta = {'HTTP_X_ACCOUNT_META_TEST':'test',
474 410
    #               'HTTP_X_ACCOUNT_META_TOST':'tost'}
475 411
    #        response = self.update_account_meta('non-existing-account', **meta)
476
    
412

  
477 413
class ContainerHead(BaseTestCase):
478 414
    def setUp(self):
479 415
        BaseTestCase.setUp(self)
480 416
        self.account = 'test'
481 417
        self.container = 'apples'
482
        status = self.create_container(self.container)[0]
483

  
484
    def tearDown(self):
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)
488

  
418
        self.client.create_container(self.container)
419
    
489 420
    def test_get_meta(self):
490 421
        meta = {'trash':'true'}
491 422
        t1 = datetime.datetime.utcnow()
492 423
        o = self.upload_random_data(self.container, o_names[0], **meta)
493 424
        if o:
494
            status, headers, data = self.get_container_meta(self.container)
425
            headers = self.client.retrieve_container_metadata(self.container)
495 426
            self.assertEqual(headers['x-container-object-count'], '1')
496 427
            self.assertEqual(headers['x-container-bytes-used'], str(len(o['data'])))
497 428
            t2 = datetime.datetime.strptime(headers['last-modified'], DATE_FORMATS[2])
......
507 438
        self.account = 'test'
508 439
        self.container = ['pears', 'apples']
509 440
        for c in self.container:
510
            self.create_container(c)
441
            self.client.create_container(c)
511 442
        self.obj = []
512 443
        for o in o_names[:8]:
513 444
            self.obj.append(self.upload_random_data(self.container[0], o))
514 445
        for o in o_names[8:]:
515 446
            self.obj.append(self.upload_random_data(self.container[1], o))
516

  
517
    def tearDown(self):
518
        for c in self.container:
519
            for obj in self.list_objects(c)[2]:
520
                self.client.delete_object(c, obj)
521
            self.client.delete_container(c)
522

  
447
    
523 448
    def test_list_objects(self):
524
        objects = self.list_objects(self.container[0])[2]
449
        objects = self.client.list_objects(self.container[0])
525 450
        l = [elem['name'] for elem in self.obj[:8]]
526 451
        l.sort()
527 452
        self.assertEqual(objects, l)
528

  
453
    
529 454
    def test_list_objects_with_limit_marker(self):
530
        objects = self.list_objects(self.container[0], limit=2)[2]
455
        objects = self.client.list_objects(self.container[0], limit=2)
531 456
        l = [elem['name'] for elem in self.obj[:8]]
532 457
        l.sort()
533 458
        self.assertEqual(objects, l[:2])
......
536 461
                   'moms_birthday.jpg']
537 462
        limit = 4
538 463
        for m in markers:
539
            objects = self.list_objects(self.container[0], limit=limit,
540
                                        marker=m)[2]
464
            objects = self.client.list_objects(self.container[0], limit=limit,
465
                                               marker=m)
541 466
            l = [elem['name'] for elem in self.obj[:8]]
542 467
            l.sort()
543 468
            start = l.index(m) + 1
544 469
            end = start + limit
545 470
            end = len(l) >= end and end or len(l)
546 471
            self.assertEqual(objects, l[start:end])
547

  
472
    
548 473
    def test_list_pseudo_hierarchical_folders(self):
549
        objects = self.list_objects(self.container[1], prefix='photos',
550
                                     delimiter='/')[2]
474
        objects = self.client.list_objects(self.container[1], prefix='photos',
475
                                           delimiter='/')
551 476
        self.assertEquals(['photos/animals/', 'photos/me.jpg',
552 477
                           'photos/plants/'], objects)
553 478
        
554
        objects = self.list_objects(self.container[1], prefix='photos/animals',
555
                                     delimiter='/')[2]
479
        objects = self.client.list_objects(self.container[1],
480
                                           prefix='photos/animals',
481
                                           delimiter='/')
556 482
        l = ['photos/animals/cats/', 'photos/animals/dogs/']
557 483
        self.assertEquals(l, objects)
558 484
        
559
        objects = self.list_objects(self.container[1], path='photos')[2]
485
        objects = self.client.list_objects(self.container[1], path='photos')
560 486
        self.assertEquals(['photos/me.jpg'], objects)
561

  
487
    
562 488
    def test_extended_list_json(self):
563
        objects = self.list_objects(self.container[1],
564
                                     format='json', limit=2,
565
                                     prefix='photos/animals',
566
                                     delimiter='/')[2]
489
        objects = self.client.list_objects(self.container[1], detail=True,
490
                                           limit=2, prefix='photos/animals',
491
                                           delimiter='/')
567 492
        self.assertEqual(objects[0]['subdir'], 'photos/animals/cats/')
568 493
        self.assertEqual(objects[1]['subdir'], 'photos/animals/dogs/')
569

  
570
    def test_extended_list_xml(self):
571
        xml = self.list_objects(self.container[1], format='xml', limit=4,
572
                                prefix='photos', delimiter='/')[2]
573
        dirs = xml.getElementsByTagName('subdir')
574
        self.assertEqual(len(dirs), 2)
575
        self.assertEqual(dirs[0].attributes['name'].value, 'photos/animals/')
576
        self.assertEqual(dirs[1].attributes['name'].value, 'photos/plants/')
577
        
578
        objects = xml.getElementsByTagName('name')
579
        self.assertEqual(len(objects), 1)
580
        self.assertEqual(objects[0].childNodes[0].data, 'photos/me.jpg')
581

  
494
    
495
    #def test_extended_list_xml(self):
496
    #    xml = self.client.list_objects(self.container[1], format='xml', limit=4,
497
    #                                   prefix='photos', delimiter='/')
498
    #    dirs = xml.getElementsByTagName('subdir')
499
    #    self.assertEqual(len(dirs), 2)
500
    #    self.assertEqual(dirs[0].attributes['name'].value, 'photos/animals/')
501
    #    self.assertEqual(dirs[1].attributes['name'].value, 'photos/plants/')
502
    #    
503
    #    objects = xml.getElementsByTagName('name')
504
    #    self.assertEqual(len(objects), 1)
505
    #    self.assertEqual(objects[0].childNodes[0].data, 'photos/me.jpg')
506
    
582 507
    def test_list_meta_double_matching(self):
583 508
        meta = {'quality':'aaa', 'stock':'true'}
584 509
        self.client.update_object_metadata(self.container[0],
585 510
                                           self.obj[0]['name'], **meta)
586
        obj = self.list_objects(self.container[0], meta='Quality,Stock')[2]
511
        obj = self.client.list_objects(self.container[0], meta='Quality,Stock')
587 512
        self.assertEqual(len(obj), 1)
588 513
        self.assertTrue(obj, self.obj[0]['name'])
589

  
514
    
590 515
    def test_list_using_meta(self):
591 516
        meta = {'quality':'aaa'}
592 517
        for o in self.obj[:2]:
......
597 522
            self.client.update_object_metadata(self.container[0], o['name'],
598 523
                                               **meta)
599 524
        
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]])
525
        obj = self.client.list_objects(self.container[0], meta='Quality')
526
        self.assertEqual(len(obj), 2)
527
        self.assertTrue(obj, [o['name'] for o in self.obj[:2]])
605 528
        
606 529
        # test case insensitive
607
        status, headers, obj = self.list_objects(self.container[0],
608
                                                  meta='quality')
609
        self.assertEqual(status, 200)
530
        obj = self.client.list_objects(self.container[0], meta='quality')
610 531
        self.assertEqual(len(obj), 2)
611 532
        self.assertTrue(obj, [o['name'] for o in self.obj[:2]])
612 533
        
613 534
        # test multiple matches
614
        status, headers, obj = self.list_objects(self.container[0],
615
                                                  meta='Quality,Stock')
616
        self.assertEqual(status, 200)
535
        obj = self.client.list_objects(self.container[0], meta='Quality,Stock')
617 536
        self.assertEqual(len(obj), 4)
618 537
        self.assertTrue(obj, [o['name'] for o in self.obj[:4]])
619 538
        
620 539
        # test non 1-1 multiple match
621
        status, headers, obj = self.list_objects(self.container[0],
622
                                                  meta='Quality,aaaa')
623
        self.assertEqual(status, 200)
540
        obj = self.client.list_objects(self.container[0], meta='Quality,aaaa')
624 541
        self.assertEqual(len(obj), 2)
625 542
        self.assertTrue(obj, [o['name'] for o in self.obj[:2]])
626

  
543
    
627 544
    def test_if_modified_since(self):
628 545
        t = datetime.datetime.utcnow()
629 546
        t2 = t - datetime.timedelta(minutes=10)
630 547
        
631 548
        #add a new object
632 549
        self.upload_random_data(self.container[0], o_names[0])
633

  
550
        
634 551
        for f in DATE_FORMATS:
635 552
            past = t2.strftime(f)
636
            
637
            headers = {'if-modified-since':'%s' %past}
638
            status, headers, data = self.list_objects(self.container[0],
639
                                                      **headers)
640
            
641
            #assert get success
642
            self.assertEqual(status, 200)
643

  
553
            try:
554
                o = self.client.list_objects(self.container[0],
555
                                            if_modified_since=past)
556
                self.assertEqual(o,
557
                                 self.client.list_objects(self.container[0]))
558
            except Fault, f:
559
                self.failIf(f.status == 304) #fail if not modified
560
    
644 561
    def test_if_modified_since_invalid_date(self):
645 562
        headers = {'if-modified-since':''}
646
        status, headers, data = self.list_objects(self.container[0], **headers)
647
        
648
        #assert get success
649
        self.assertEqual(status, 200)
650

  
563
        o = self.client.list_objects(self.container[0], if_modified_since='')
564
        self.assertEqual(o, self.client.list_objects(self.container[0]))
565
    
651 566
    def test_if_not_modified_since(self):
652 567
        now = datetime.datetime.utcnow()
653 568
        since = now + datetime.timedelta(1)
654 569
        
655 570
        for f in DATE_FORMATS:
656
            headers = {'if-modified-since':'%s' %since.strftime(f)}
571
            args = {'if_modified_since':'%s' %since.strftime(f)}
572
            
657 573
            #assert not modified
658
            self.assert_raises_fault(304, self.list_objects, self.container[0],
659
                                     **headers)
574
            self.assert_raises_fault(304, self.client.list_objects,
575
                                     self.container[0], **args)
660 576
    
661 577
    def test_if_unmodified_since(self):
662 578
        now = datetime.datetime.utcnow()
663 579
        since = now + datetime.timedelta(1)
664 580
        
665 581
        for f in DATE_FORMATS:
666
            headers = {'if-unmodified-since':'%s' %since.strftime(f)}
667
            status, headers, data = self.list_objects(self.container[0], **headers)
582
            obj = self.client.list_objects(self.container[0],
583
                                           if_unmodified_since=since.strftime(f))
668 584
            
669
            #assert success
670
            self.assertEqual(status, 200)
671
            objlist = self.list_objects(self.container[0])[2]
672
            self.assertEqual(data, objlist)
673

  
585
            #assert unmodified
586
            self.assertEqual(obj, self.client.list_objects(self.container[0]))
587
    
674 588
    def test_if_unmodified_since_precondition_failed(self):
675 589
        t = datetime.datetime.utcnow()
676 590
        t2 = t - datetime.timedelta(minutes=10)
677 591
        
678 592
        #add a new container
679
        self.create_container('dummy')
680

  
593
        self.client.create_container('dummy')
594
        
681 595
        for f in DATE_FORMATS:
682 596
            past = t2.strftime(f)
683 597
            
684
            headers = {'if-unmodified-since':'%s' %past}
598
            args = {'if_unmodified_since':'%s' %past}
599
            
685 600
            #assert precondition failed
686
            self.assert_raises_fault(412, self.list_objects, self.container[0],
687
                                     **headers)
601
            self.assert_raises_fault(412, self.client.list_objects,
602
                                     self.container[0], **args)
688 603

  
689 604
class ContainerPut(BaseTestCase):
690 605
    def setUp(self):
691 606
        BaseTestCase.setUp(self)
692 607
        self.account = 'test'
693 608
        self.containers = ['c1', 'c2']
694

  
695
    def tearDown(self):
696
        for c in self.list_containers()[2]:
697
            r = self.client.delete_container(c)
698

  
609
    
699 610
    def test_create(self):
700
        status = self.create_container(self.containers[0])[0]
701
        self.assertEqual(status, 201)
702
        
703
        containers = self.list_containers()[2]
611
        self.client.create_container(self.containers[0])
612
        containers = self.client.list_containers()
704 613
        self.assertTrue(self.containers[0] in containers)
705
        status = self.get_container_meta(self.containers[0])[0]
706
        self.assertEqual(status, 204)
707

  
614
        self.assert_container_exists(self.containers[0])
615
    
708 616
    def test_create_twice(self):
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)
713

  
617
        self.client.create_container(self.containers[0])
618
        self.assertTrue(not self.client.create_container(self.containers[0]))
619
    
714 620
class ContainerPost(BaseTestCase):
715 621
    def setUp(self):
716 622
        BaseTestCase.setUp(self)
717 623
        self.account = 'test'
718 624
        self.container = 'apples'
719
        self.create_container(self.container)
720

  
721
    def tearDown(self):
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)
725

  
625
        self.client.create_container(self.container)
626
    
726 627
    def test_update_meta(self):
727 628
        meta = {'test':'test33',
728 629
                'tost':'tost22'}
729 630
        self.client.update_container_metadata(self.container, **meta)
730
        headers = self.get_container_meta(self.container)[1]
631
        headers = self.client.retrieve_container_metadata(self.container)
731 632
        for k,v in meta.items():
732 633
            k = 'x-container-meta-%s' % k
733 634
            self.assertTrue(headers[k])
......
739 640
        self.account = 'test'
740 641
        self.containers = ['c1', 'c2']
741 642
        for c in self.containers:
742
            self.create_container(c)
643
            self.client.create_container(c)
743 644
        self.upload_random_data(self.containers[1], o_names[0])
744

  
745
    def tearDown(self):
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)
750

  
645
    
751 646
    def test_delete(self):
752 647
        status = self.client.delete_container(self.containers[0])[0]
753 648
        self.assertEqual(status, 204)
754

  
649
    
755 650
    def test_delete_non_empty(self):
756 651
        self.assert_raises_fault(409, self.client.delete_container,
757 652
                                 self.containers[1])
758

  
653
    
759 654
    def test_delete_invalid(self):
760 655
        self.assert_raises_fault(404, self.client.delete_container, 'c3')
761 656

  
......
769 664
        self.containers = ['c1', 'c2']
770 665
        #create some containers
771 666
        for c in self.containers:
772
            self.create_container(c)
667
            self.client.create_container(c)
773 668
        
774 669
        #upload a file
775 670
        names = ('obj1', 'obj2')
776 671
        self.objects = []
777 672
        for n in names:
778 673
            self.objects.append(self.upload_random_data(self.containers[1], n))
779

  
780
    def tearDown(self):
781
        for c in self.containers:
782
            for o in self.list_objects(c)[2]:
783
                self.client.delete_object(c, o)
784
            self.client.delete_container(c)
785

  
674
    
786 675
    def test_get(self):
787 676
        #perform get
788
        status, headers, data = self.get_object(self.containers[1],
789
                            self.objects[0]['name'],
790
                            self.objects[0]['meta'])
791
        #assert success
792
        self.assertEqual(status, 200)
793
        
794
        #assert content-type
795
        self.assertEqual(headers['content-type'],
796
                         self.objects[0]['meta']['content-type'])
797

  
677
        o = self.client.retrieve_object(self.containers[1],
678
                                        self.objects[0]['name'],
679
                                        self.objects[0]['meta'])
680
        self.assertEqual(o, self.objects[0]['data'])
681
    
798 682
    def test_get_invalid(self):
799
        self.assert_raises_fault(404, self.get_object, self.containers[0],
800
                                 self.objects[0]['name'])
801

  
683
        self.assert_raises_fault(404, self.client.retrieve_object,
684
                                 self.containers[0], self.objects[0]['name'])
685
    
802 686
    def test_get_partial(self):
803 687
        #perform get with range
804
        headers = {'range':'bytes=0-499'}
805
        status, headers, data = self.get_object(self.containers[1],
806
                                                self.objects[0]['name'],
807
                                                **headers)
688
        status, headers, data = self.client.request_object(self.containers[1],
689
                                                            self.objects[0]['name'],
690
                                                            range='bytes=0-499')
808 691
        
809 692
        #assert successful partial content
810 693
        self.assertEqual(status, 206)
811 694
        
812 695
        #assert content-type
813 696
        self.assertEqual(headers['content-type'],
814
                         self.objects[0]['meta']['content-type'])
697
                         self.objects[0]['meta']['content_type'])
815 698
        
816 699
        #assert content length
817 700
        self.assertEqual(int(headers['content-length']), 500)
818 701
        
819 702
        #assert content
820 703
        self.assertEqual(self.objects[0]['data'][:500], data)
821

  
704
    
822 705
    def test_get_final_500(self):
823 706
        #perform get with range
824 707
        headers = {'range':'bytes=-500'}
825
        status, headers, data = self.get_object(self.containers[1],
826
                                                self.objects[0]['name'],
827
                                                **headers)
708
        status, headers, data = self.client.request_object(self.containers[1],
709
                                                            self.objects[0]['name'],
710
                                                            range='bytes=-500')
828 711
        
829 712
        #assert successful partial content
830 713
        self.assertEqual(status, 206)
831 714
        
832 715
        #assert content-type
833 716
        self.assertEqual(headers['content-type'],
834
                         self.objects[0]['meta']['content-type'])
717
                         self.objects[0]['meta']['content_type'])
835 718
        
836 719
        #assert content length
837 720
        self.assertEqual(int(headers['content-length']), 500)
838 721
        
839 722
        #assert content
840 723
        self.assertTrue(self.objects[0]['data'][-500:], data)
841

  
724
    
842 725
    def test_get_rest(self):
843 726
        #perform get with range
844 727
        offset = len(self.objects[0]['data']) - 500
845
        headers = {'range':'bytes=%s-' %offset}
846
        status, headers, data = self.get_object(self.containers[1],
728
        status, headers, data = self.client.request_object(self.containers[1],
847 729
                                                self.objects[0]['name'],
848
                                                **headers)
730
                                                range='bytes=%s-' %offset)
849 731
        
850 732
        #assert successful partial content
851 733
        self.assertEqual(status, 206)
852 734
        
853 735
        #assert content-type
854 736
        self.assertEqual(headers['content-type'],
855
                         self.objects[0]['meta']['content-type'])
737
                         self.objects[0]['meta']['content_type'])
856 738
        
857 739
        #assert content length
858 740
        self.assertEqual(int(headers['content-length']), 500)
859 741
        
860 742
        #assert content
861 743
        self.assertTrue(self.objects[0]['data'][-500:], data)
862

  
744
    
863 745
    def test_get_range_not_satisfiable(self):
864 746
        #perform get with range
865 747
        offset = len(self.objects[0]['data']) + 1
866
        headers = {'range':'bytes=0-%s' %offset}
867 748
        
868 749
        #assert range not satisfiable
869
        self.assert_raises_fault(416, self.get_object, self.containers[1],
870
                                 self.objects[0]['name'], **headers)
871

  
750
        self.assert_raises_fault(416, self.client.retrieve_object,
751
                                 self.containers[1], self.objects[0]['name'],
752
                                 range='bytes=0-%s' %offset)
753
    
872 754
    def test_multiple_range(self):
873 755
        #perform get with multiple range
874 756
        ranges = ['0-499', '-500', '1000-']
875
        headers = {'range' : 'bytes=%s' % ','.join(ranges)}
876
        status, headers, data = self.get_object(self.containers[1],
877
                                                self.objects[0]['name'],
878
                                                **headers)
757
        bytes = 'bytes=%s' % ','.join(ranges)
758
        status, headers, data = self.client.request_object(self.containers[1],
759
                                                           self.objects[0]['name'],
760
                                                           range=bytes)
879 761
        
880 762
        # assert partial content
881 763
        self.assertEqual(status, 206)
......
916 798
            self.assertEqual(len(fdata), len(sdata))
917 799
            self.assertEquals(fdata, sdata)
918 800
            i+=1
919

  
801
    
920 802
    def test_multiple_range_not_satisfiable(self):
921 803
        #perform get with multiple range
922 804
        out_of_range = len(self.objects[0]['data']) + 1
923 805
        ranges = ['0-499', '-500', '%d-' %out_of_range]
924
        headers = {'range' : 'bytes=%s' % ','.join(ranges)}
806
        bytes = 'bytes=%s' % ','.join(ranges)
925 807
        
926 808
        # assert partial content
927
        self.assert_raises_fault(416, self.get_object, self.containers[1],
928
                            self.objects[0]['name'], **headers)
929

  
930

  
809
        self.assert_raises_fault(416, self.client.retrieve_object,
810
                                 self.containers[1],
811
                                 self.objects[0]['name'], range=bytes)
812
    
931 813
    def test_get_with_if_match(self):
932 814
        #perform get with If-Match
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)
815
        etag = self.objects[0]['hash']
816
        status, headers, data = self.client.request_object(self.containers[1],
817
                                                           self.objects[0]['name'],
818
                                                           if_match=etag)
937 819
        #assert get success
938 820
        self.assertEqual(status, 200)
939 821
        
940 822
        #assert content-type
941 823
        self.assertEqual(headers['content-type'],
942
                         self.objects[0]['meta']['content-type'])
824
                         self.objects[0]['meta']['content_type'])
943 825
        
944 826
        #assert response content
945 827
        self.assertEqual(self.objects[0]['data'], data)
946

  
828
    
947 829
    def test_get_with_if_match_star(self):
948 830
        #perform get with If-Match *
949 831
        headers = {'if-match':'*'}
950
        status, headers, data = self.get_object(self.containers[1],
832
        status, headers, data = self.client.request_object(self.containers[1],
951 833
                                                self.objects[0]['name'],
952 834
                                                **headers)
953 835
        #assert get success
......
955 837
        
956 838
        #assert content-type
957 839
        self.assertEqual(headers['content-type'],
958
                         self.objects[0]['meta']['content-type'])
840
                         self.objects[0]['meta']['content_type'])
959 841
        
960 842
        #assert response content
961 843
        self.assertEqual(self.objects[0]['data'], data)
962

  
844
    
963 845
    def test_get_with_multiple_if_match(self):
964 846
        #perform get with If-Match
965 847
        etags = [i['hash'] for i in self.objects if i]
966 848
        etags = ','.join('"%s"' % etag for etag in etags)
967
        headers = {'if-match':etags}
968
        status, headers, data = self.get_object(self.containers[1],
969
                                                self.objects[0]['name'],
970
                                                **headers)
849
        status, headers, data = self.client.request_object(self.containers[1],
850
                                                           self.objects[0]['name'],
851
                                                           if_match=etags)
971 852
        #assert get success
972 853
        self.assertEqual(status, 200)
973 854
        
974 855
        #assert content-type
975 856
        self.assertEqual(headers['content-type'],
976
                         self.objects[0]['meta']['content-type'])
857
                         self.objects[0]['meta']['content_type'])
977 858
        
978 859
        #assert content-type
979 860
        self.assertEqual(headers['content-type'],
980
                         self.objects[0]['meta']['content-type'])
861
                         self.objects[0]['meta']['content_type'])
981 862
        
982 863
        #assert response content
983 864
        self.assertEqual(self.objects[0]['data'], data)
984

  
865
    
985 866
    def test_if_match_precondition_failed(self):
986
        #perform get with If-Match
987
        headers = {'if-match':'123'}
988
        
989 867
        #assert precondition failed
990
        self.assert_raises_fault(412, self.get_object, self.containers[1],
991
                                 self.objects[0]['name'], **headers)
992
        
993

  
868
        self.assert_raises_fault(412, self.client.retrieve_object,
869
                                 self.containers[1],
870
                                 self.objects[0]['name'], if_match='123')
871
    
994 872
    def test_if_none_match(self):
995 873
        #perform get with If-None-Match
996
        headers = {'if-none-match':'123'}
997
        status, headers, data = self.get_object(self.containers[1],
998
                                                self.objects[0]['name'],
999
                                                **headers)
874
        status, headers, data = self.client.request_object(self.containers[1],
875
                                                           self.objects[0]['name'],
876
                                                           if_none_match='123')
1000 877
        
1001 878
        #assert get success
1002 879
        self.assertEqual(status, 200)
1003 880
        
1004 881
        #assert content-type
1005
        self.assertEqual(headers['content-type'],
1006
                         self.objects[0]['meta']['content-type'])
1007

  
882
        self.assertEqual(headers['content_type'],
883
                         self.objects[0]['meta']['content_type'])
884
    
1008 885
    def test_if_none_match(self):
1009
        #perform get with If-None-Match *
1010
        headers = {'if-none-match':'*'}
1011
        
1012
        #assert not modified
1013
        self.assert_raises_fault(304, self.get_object, self.containers[1],
1014
                            self.objects[0]['name'],
1015
                            **headers)
1016

  
886
        #perform get with If-None-Match * and assert not modified
887
        self.assert_raises_fault(304, self.client.retrieve_object,
888
                                 self.containers[1],
889
                                 self.objects[0]['name'],
890
                                 if_none_match='*')
891
    
1017 892
    def test_if_none_match_not_modified(self):
1018
        #perform get with If-None-Match
1019
        headers = {'if-none-match':'%s' %self.objects[0]['hash']}
1020
        
1021
        #assert not modified
1022
        self.assert_raises_fault(304, self.get_object, self.containers[1],
1023
                            self.objects[0]['name'],
1024
                            **headers)
1025
        
1026
        headers = self.get_object(self.containers[1],
1027
                                  self.objects[0]['name'])[1]
1028
        self.assertEqual(headers['etag'], self.objects[0]['hash'])
1029

  
893
        #perform get with If-None-Match and assert not modified
894
        self.assert_raises_fault(304, self.client.retrieve_object,
895
                                 self.containers[1],
896
                                 self.objects[0]['name'],
897
                                 if_none_match=self.objects[0]['hash'])
898
        
899
        meta = self.client.retrieve_object_metadata(self.containers[1],
900
                                                    self.objects[0]['name'])
901
        self.assertEqual(meta['etag'], self.objects[0]['hash'])
902
    
1030 903
    def test_if_modified_since(self):
1031 904
        t = datetime.datetime.utcnow()
1032 905
        t2 = t - datetime.timedelta(minutes=10)
......
1040 913
            past = t2.strftime(f)
1041 914
            
1042 915
            headers = {'if-modified-since':'%s' %past}
1043
            status, headers, data = self.get_object(self.containers[1],
1044
                                                    self.objects[0]['name'],
1045
                                                    **headers)
1046
            
1047
            #assert get success
1048
            self.assertEqual(status, 200)
1049
            
1050
            #assert content-type
1051
            self.assertEqual(headers['content-type'],
1052
                             self.objects[0]['meta']['content-type'])   
1053

  
1054
    def test_if_modified_since_invalid_date(self):
1055
        headers = {'if-modified-since':''}
1056
        status, headers, data = self.get_object(self.containers[1],
916
            try:
917
                o = self.client.retrieve_object(self.containers[1],
1057 918
                                                self.objects[0]['name'],
1058
                                                **headers)
1059
        
1060
        #assert get success
1061
        self.assertEqual(status, 200)
1062
        
1063
        #assert content-type
1064
        self.assertEqual(headers['content-type'],
1065
                         self.objects[0]['meta']['content-type'])
1066

  
919
                                                if_modified_since=past)
920
                self.assertEqual(o,
921
                                 self.client.retrieve_object(self.containers[1],
922
                                                             self.objects[0]['name']))
923
            except Fault, f:
924
                self.failIf(f.status == 304)
925
    
926
    def test_if_modified_since_invalid_date(self):
927
        o = self.client.retrieve_object(self.containers[1],
928
                                        self.objects[0]['name'],
929
                                        if_modified_since='')
930
        self.assertEqual(o, self.client.retrieve_object(self.containers[1],
931
                                                        self.objects[0]['name']))
932
            
1067 933
    def test_if_not_modified_since(self):
1068 934
        now = datetime.datetime.utcnow()
1069 935
        since = now + datetime.timedelta(1)
1070 936
        
1071 937
        for f in DATE_FORMATS:
1072
            headers = {'if-modified-since':'%s' %since.strftime(f)}
1073
            
1074 938
            #assert not modified
1075
            self.assert_raises_fault(304, self.get_object, self.containers[1],
1076
                            self.objects[0]['name'], **headers)
1077

  
1078

  
939
            self.assert_raises_fault(304, self.client.retrieve_object,
940
                                     self.containers[1], self.objects[0]['name'],
941
                                     if_modified_since=since.strftime(f))
942
    
1079 943
    def test_if_unmodified_since(self):
1080 944
        now = datetime.datetime.utcnow()
1081 945
        since = now + datetime.timedelta(1)
1082 946
        
1083 947
        for f in DATE_FORMATS:
1084
            headers = {'if-unmodified-since':'%s' %since.strftime(f)}
1085
            status, headers, data = self.get_object(self.containers[1],
1086
                                                    self.objects[0]['name'],
1087
                                                    **headers)
948
            t = since.strftime(f)
949
            status, headers, data = self.client.request_object(self.containers[1],
950
                                                               self.objects[0]['name'],
951
                                                               if_unmodified_since=t)
1088 952
            #assert success
1089 953
            self.assertEqual(status, 200)
1090 954
            self.assertEqual(self.objects[0]['data'], data)
1091 955
            
1092 956
            #assert content-type
1093 957
            self.assertEqual(headers['content-type'],
1094
                             self.objects[0]['meta']['content-type'])
1095

  
958
                             self.objects[0]['meta']['content_type'])
959
    
1096 960
    def test_if_unmodified_since_precondition_failed(self):
1097 961
        t = datetime.datetime.utcnow()
1098 962
        t2 = t - datetime.timedelta(minutes=10)
......
1104 968
        
1105 969
        for f in DATE_FORMATS:
1106 970
            past = t2.strftime(f)
1107
            
1108
            headers = {'if-unmodified-since':'%s' %past}
1109
            
1110 971
            #assert precondition failed
1111
            self.assert_raises_fault(412, self.get_object, self.containers[1],
1112
                            self.objects[0]['name'], **headers)
1113

  
1114

  
972
            self.assert_raises_fault(412, self.client.retrieve_object,
973
                                     self.containers[1], self.objects[0]['name'],
974
                                     if_unmodified_since=past)
975
    
1115 976
    def test_hashes(self):
1116 977
        l = 8388609
1117 978
        fname = 'largefile'
1118 979
        o = self.upload_random_data(self.containers[1], fname, l)
1119 980
        if o:
1120
            data = self.get_object(self.containers[1],
1121
                                fname,
1122
                                'json')[2]
981
            data = self.client.retrieve_object(self.containers[1], fname, detail=True)
1123 982
            body = json.loads(data)
1124 983
            hashes = body['hashes']
1125 984
            block_size = body['block_size']
......
1139 998
        BaseTestCase.setUp(self)
1140 999
        self.account = 'test'
1141 1000
        self.container = 'c1'
1142
        self.create_container(self.container)
1001
        self.client.create_container(self.container)
1143 1002
    
1144
    def tearDown(self):
1145
        objects = self.list_objects(self.container)[2]
1146
        for o in objects:
1147
            self.client.delete_object(self.container, o)
1148
        self.client.delete_container(self.container)
1149

  
1150 1003
    def test_upload(self):
1151 1004
        name = o_names[0]
1152 1005
        meta = {'test':'test1'}
......
1159 1012
        self.assertEqual(headers['test'], meta['test'])
1160 1013
        
1161 1014
        #assert uploaded content
1162
        status, headers, content = self.get_object(self.container, name)
1163
        self.assertEqual(len(o['data']), int(headers['content-length']))
1164
        self.assertEqual(o['data'], content)
1165

  
1015
        status, h, data = self.client.request_object(self.container, name)
1016
        self.assertEqual(len(o['data']), int(h['content-length']))
1017
        self.assertEqual(o['data'], data)
1018
        
1019
        #assert content-type
1020
        self.assertEqual(h['content-type'], o['meta']['content_type'])
1021
    
1166 1022
    def test_upload_unprocessable_entity(self):
1167 1023
        meta={'etag':'123', 'test':'test1'}
1168 1024
        
1169 1025
        #assert unprocessable entity
1170
        self.assert_raises_fault(422, self.upload_random_data,self.container,
1026
        self.assert_raises_fault(422, self.upload_random_data, self.container,
1171 1027
                                 o_names[0], **meta)
1172

  
1028
    
1173 1029
    def test_chucked_transfer(self):
1174
        fname = './api/tests.py'
1175
        objname = os.path.split(fname)[-1:][0]
1176
        f = open(fname, 'r')
1177
        status = self.client.create_object(self.container,
1178
                                           objname,
1179
                                           f,
1180
                                           chunked=True)[0]
1181
        self.assertEqual(status, 201)
1030
        data = get_random_data()
1031
        objname = 'object'
1032
        self.client.create_object_using_chunks(self.container, objname,
1033
                                               StringIO(data))
1182 1034
        
1183
        uploaded_data = self.get_object(self.container,
1184
                                        objname)[2]
1185
        f = open(fname, 'r')
1186
        actual_data = f.read()
1187
        self.assertEqual(actual_data, uploaded_data)
1035
        uploaded_data = self.client.retrieve_object(self.container, objname)
1036
        self.assertEqual(data, uploaded_data)
1188 1037

  
1189 1038
class ObjectCopy(BaseTestCase):
1190 1039
    def setUp(self):
......
1192 1041
        self.account = 'test'
1193 1042
        self.containers = ['c1', 'c2']
1194 1043
        for c in self.containers:
1195
            self.create_container(c)
1044
            self.client.create_container(c)
1196 1045
        self.obj = self.upload_random_data(self.containers[0], o_names[0])
1197

  
1198
    def tearDown(self):
1199
        for c in self.containers:
1200
            for o in self.list_objects(c)[2]:
1201
                self.client.delete_object(c, o)
1202
            self.client.delete_container(c)
1203

  
1046
    
1204 1047
    def test_copy(self):
1205 1048
        with AssertMappingInvariant(self.client.retrieve_object_metadata,
1206 1049
                             self.containers[0], self.obj['name']):
......
1226 1069
            
1227 1070
            #assert src object still exists
1228 1071
            self.assert_object_exists(self.containers[0], self.obj['name'])
1229

  
1072
    
1230 1073
    def test_copy_from_different_container(self):
1231 1074
        with AssertMappingInvariant(self.client.retrieve_object_metadata,
1232 1075
                             self.containers[0], self.obj['name']):
......
1247 1090
            
1248 1091
            #assert src object still exists
1249 1092
            self.assert_object_exists(self.containers[0], self.obj['name'])
1250

  
1093
    
1251 1094
    def test_copy_invalid(self):
1252 1095
        #copy from invalid object
1253 1096
        meta = {'test':'testcopy'}
......
1290 1133
        self.account = 'test'
1291 1134
        self.containers = ['c1', 'c2']
1292 1135
        for c in self.containers:
1293
            self.create_container(c)
1136
            self.client.create_container(c)
1294 1137
        self.obj = self.upload_random_data(self.containers[0], o_names[0])
1295

  
1296
    def tearDown(self):
1297
        for c in self.containers:
1298
            for o in self.list_objects(c)[2]:
1299
                self.client.delete_object(c, o)
1300
            self.client.delete_container(c)
1301

  
1138
    
1302 1139
    def test_update_meta(self):
1303 1140
        #perform update metadata
1304 1141
        more = {'foo':'foo', 'bar':'bar'}
......
1316 1153
        for k,v in more.items():
1317 1154
            self.assertTrue(k in headers.keys())
1318 1155
            self.assertTrue(headers[k], v)
1319

  
1156
    
1320 1157
    def test_update_object(self,
1321 1158
                           first_byte_pos=0,
1322 1159
                           last_byte_pos=499,
......
1329 1166
                                       length)
1330 1167
        partial = last_byte_pos - first_byte_pos + 1
1331 1168
        data = get_random_data(partial)
1332
        headers = {'content-range':range,
1333
                   'content-type':'application/octet-stream'}
1169
        args = {'content_type':'application/octet-stream',
1170
                'content_range':'%s' %range}
1334 1171
        if content_length:
1335
            headers.update({'content-length':'%s' % content_length})
1336
        
1337
        status = self.client.update_object_data(self.containers[0],
1338
                                                self.obj['name'],
1339
                                                data,
1340
                                                headers)[0]
1341
        
1172
            args['content_length'] = content_length
1173
        status = self.client.update_object(self.containers[0], self.obj['name'],
1174
                                  StringIO(data), **args)[0]
1342 1175
        
1343 1176
        if partial < 0 or (instance_length and l <= last_byte_pos):
1344 1177
            self.assertEqual(status, 202)    
1345 1178
        else:
1346
            self.assertEqual(status, 204)
1347
            
1179
            self.assertEqual(status, 204)           
1348 1180
            #check modified object
1349
            content = self.get_object(self.containers[0], self.obj['name'])[2]
1181
            content = self.client.retrieve_object(self.containers[0],
1182
                                              self.obj['name'])
1350 1183
            self.assertEqual(content[0:partial], data)
1351 1184
            self.assertEqual(content[partial:l], self.obj['data'][partial:l])
1352

  
1185
    
1353 1186
    def test_update_object_no_content_length(self):
1354 1187
        self.test_update_object(content_length = None)
1355

  
1356

  
1357
    #fails if the server resets the content-legth
1358
    #def test_update_object_invalid_content_length(self):
1359
    #    with AssertContentInvariant(self.get_object, self.containers[0],
1360
    #                                self.obj['name']):
1361
    #        self.test_update_object(content_length = 1000)
1362

  
1363
    def test_update_object_with_unknown_instance_length(self):
1364
        self.test_update_object(instance_length = False)
1365

  
1188
    
1189
    def test_update_object_invalid_content_length(self):
1190
        with AssertContentInvariant(self.client.retrieve_object,
1191
                                    self.containers[0], self.obj['name']):
1192
            self.assert_raises_fault(400, self.test_update_object,
1193
                                     content_length = 1000)
1194
    
1366 1195
    def test_update_object_invalid_range(self):
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff