Revision f0eacc2c pithos/api/tests.py

b/pithos/api/tests.py
36 36
from django.utils import simplejson as json
37 37
from xml.dom import minidom
38 38
from StringIO import StringIO
39
import time as _time
39 40
import types
40 41
import hashlib
41 42
import os
......
45 46
import string
46 47
import re
47 48

  
48
#from pithos.backends import backend
49

  
50 49
DATE_FORMATS = ["%a %b %d %H:%M:%S %Y",
51 50
                "%A, %d-%b-%y %H:%M:%S GMT",
52 51
                "%a, %d %b %Y %H:%M:%S GMT"]
......
54 53
DEFAULT_HOST = 'pithos.dev.grnet.gr'
55 54
#DEFAULT_HOST = '127.0.0.1:8000'
56 55
DEFAULT_API = 'v1'
57
DEFAULT_USER = 'papagian'
58
DEFAULT_AUTH = '0004'
56
DEFAULT_USER = 'test'
57
DEFAULT_AUTH = '0000'
59 58

  
60 59
class BaseTestCase(unittest.TestCase):
61 60
    #TODO unauthorized request
62 61
    def setUp(self):
63
        self.client = Pithos_Client(DEFAULT_HOST, DEFAULT_AUTH, DEFAULT_USER, DEFAULT_API)
64
        self.headers = {
65
            'account': ('x-account-container-count',
66
                        'x-account-bytes-used',
67
                        'last-modified',
68
                        'content-length',
69
                        'date',
70
                        'content_type',
71
                        'server',),
72
            'object': ('etag',
73
                       'content-length',
74
                       'content_type',
75
                       'content-encoding',
76
                       'last-modified',
77
                       'date',
78
                       'x-object-manifest',
79
                       'content-range',
80
                       'x-object-modified-by',
81
                       'x-object-version',
82
                       'x-object-version-timestamp',
83
                       'server',),
84
            'container': ('x-container-object-count',
85
                          'x-container-bytes-used',
86
                          'content_type',
87
                          'last-modified',
88
                          'content-length',
89
                          'date',
90
                          'x-container-block-size',
91
                          'x-container-block-hash',
92
                          'x-container-policy-quota',
93
                          'x-container-policy-versioning',
94
                          'server',
95
                          'x-container-object-meta',
96
                          'x-container-policy-versioning',
97
                          'server',)}
98
        
99
        self.contentTypes = {'xml':'application/xml',
100
                             'json':'application/json',
101
                             '':'text/plain'}
62
        self.client = Pithos_Client(DEFAULT_HOST,
63
                                    DEFAULT_AUTH,
64
                                    DEFAULT_USER,
65
                                    DEFAULT_API)
66
        self.invalid_client = Pithos_Client(DEFAULT_HOST,
67
                                                  DEFAULT_AUTH,
68
                                                  'invalid',
69
                                                  DEFAULT_API)
70
        #self.headers = {
71
        #    'account': ('x-account-container-count',
72
        #                'x-account-bytes-used',
73
        #                'last-modified',
74
        #                'content-length',
75
        #                'date',
76
        #                'content_type',
77
        #                'server',),
78
        #    'object': ('etag',
79
        #               'content-length',
80
        #               'content_type',
81
        #               'content-encoding',
82
        #               'last-modified',
83
        #               'date',
84
        #               'x-object-manifest',
85
        #               'content-range',
86
        #               'x-object-modified-by',
87
        #               'x-object-version',
88
        #               'x-object-version-timestamp',
89
        #               'server',),
90
        #    'container': ('x-container-object-count',
91
        #                  'x-container-bytes-used',
92
        #                  'content_type',
93
        #                  'last-modified',
94
        #                  'content-length',
95
        #                  'date',
96
        #                  'x-container-block-size',
97
        #                  'x-container-block-hash',
98
        #                  'x-container-policy-quota',
99
        #                  'x-container-policy-versioning',
100
        #                  'server',
101
        #                  'x-container-object-meta',
102
        #                  'x-container-policy-versioning',
103
        #                  'server',)}
104
        #
105
        #self.contentTypes = {'xml':'application/xml',
106
        #                     'json':'application/json',
107
        #                     '':'text/plain'}
102 108
        self.extended = {
103 109
            'container':(
104 110
                'name',
......
146 152
    #            data = minidom.parseString(data)
147 153
    #    return status, headers, data
148 154
    
149
    def assert_headers(self, headers, type, **exp_meta):
150
        prefix = 'x-%s-meta-' %type
151
        system_headers = [h for h in headers if not h.startswith(prefix)]
152
        for k,v in headers.items():
153
            if k in system_headers:
154
                self.assertTrue(k in headers[type])
155
            elif exp_meta:
156
                k = k.split(prefix)[-1]
157
                self.assertEqual(v, exp_meta[k])
158
    
159
    #def assert_extended(self, data, format, type, size):
160
    #    if format == 'xml':
161
    #        self._assert_xml(data, type, size)
162
    #    elif format == 'json':
163
    #        self._assert_json(data, type, size)
164
    
165
    #def _assert_json(self, data, type, size):
166
    #    print '#', data
167
    #    convert = lambda s: s.lower()
168
    #    info = [convert(elem) for elem in self.extended[type]]
169
    #    data = json.loads(data)
170
    #    self.assertTrue(len(data) <= size)
171
    #    for item in info:
172
    #        for i in data:
173
    #            if 'subdir' in i.keys():
174
    #                continue
175
    #            self.assertTrue(item in i.keys())
176
    
177
    #def _assert_xml(self, data, type, size):
178
    #    print '#', data
179
    #    convert = lambda s: s.lower()
180
    #    info = [convert(elem) for elem in self.extended[type]]
181
    #    try:
182
    #        info.remove('content_encoding')
183
    #    except ValueError:
184
    #        pass
185
    #    xml = minidom.parseString(data)
186
    #    entities = xml.getElementsByTagName(type)
187
    #    self.assertTrue(len(entities) <= size)
188
    #    for e in entities:
189
    #        for item in info:
190
    #            self.assertTrue(e.hasAttribute(item))
155
    #def assert_headers(self, headers, type, **exp_meta):
156
    #    prefix = 'x-%s-meta-' %type
157
    #    system_headers = [h for h in headers if not h.startswith(prefix)]
158
    #    for k,v in headers.items():
159
    #        if k in system_headers:
160
    #            self.assertTrue(k in headers[type])
161
    #        elif exp_meta:
162
    #            k = k.split(prefix)[-1]
163
    #            self.assertEqual(v, exp_meta[k])
164
    
165
    def assert_extended(self, data, format, type, size):
166
        if format == 'xml':
167
            self._assert_xml(data, type, size)
168
        elif format == 'json':
169
            self._assert_json(data, type, size)
170
    
171
    def _assert_json(self, data, type, size):
172
        print '#', data
173
        convert = lambda s: s.lower()
174
        info = [convert(elem) for elem in self.extended[type]]
175
        self.assertTrue(len(data) <= size)
176
        for item in info:
177
            for i in data:
178
                if 'subdir' in i.keys():
179
                    continue
180
                self.assertTrue(item in i.keys())
181
    
182
    def _assert_xml(self, data, type, size):
183
        convert = lambda s: s.lower()
184
        info = [convert(elem) for elem in self.extended[type]]
185
        try:
186
            info.remove('content_encoding')
187
        except ValueError:
188
            pass
189
        xml = data
190
        entities = xml.getElementsByTagName(type)
191
        self.assertTrue(len(entities) <= size)
192
        for e in entities:
193
            for item in info:
194
                print '#', item
195
                self.assertTrue(e.hasAttribute(item))
191 196
    
192 197
    def assert_raises_fault(self, status, callableObj, *args, **kwargs):
193 198
        """
......
265 270
        for item in self.containers:
266 271
            self.client.create_container(item)
267 272
    
273
    def tearDown(self):
274
        self.client.delete_account_metadata(['foo'])
275
        BaseTestCase.tearDown(self)
276
    
268 277
    def test_get_account_meta(self):
269 278
        meta = self.client.retrieve_account_metadata()
270 279
        
......
277 286
            size = size + int(m['x-container-bytes-used'])
278 287
        self.assertEqual(meta['x-account-bytes-used'], str(size))
279 288
    
280
    #def test_get_account_401(self):
281
    #    response = self.get_account_meta('non-existing-account')
282
    #    print response
283
    #    self.assertEqual(response.status_code, 401)
289
    def test_get_account_401(self):
290
        self.assert_raises_fault(401,
291
                                 self.invalid_client.retrieve_account_metadata)
292
    
293
    def test_get_account_meta_until(self):
294
        t = datetime.datetime.utcnow()
295
        past = t - datetime.timedelta(minutes=-15)
296
        past = int(_time.mktime(past.timetuple()))
297
        
298
        meta = {'foo':'bar'}
299
        self.client.update_account_metadata(**meta)
300
        meta = self.client.retrieve_account_metadata(restricted=True,
301
                                                     until=past)
302
        self.assertTrue('foo' not in meta)
303
        
304
        meta = self.client.retrieve_account_metadata(restricted=True)
305
        self.assertTrue('foo' in meta)
306
    
307
    def test_get_account_meta_until_invalid_date(self):
308
        meta = {'foo':'bar'}
309
        self.client.update_account_metadata(**meta)
310
        meta = self.client.retrieve_account_metadata(restricted=True,
311
                                                     until='kshfksfh')
312
        self.assertTrue('foo' in meta)
284 313

  
285 314
class AccountGet(BaseTestCase):
286 315
    def setUp(self):
......
296 325
        containers = self.client.list_containers()
297 326
        self.assertEquals(self.containers, containers)
298 327
    
299
    #def test_list_204(self):
300
    #    response = self.list_containers('non-existing-account')
301
    #    self.assertEqual(response.status_code, 204)
328
    def test_list_401(self):
329
        self.assert_raises_fault(401, self.invalid_client.list_containers)
302 330
    
303 331
    def test_list_with_limit(self):
304 332
        limit = 2
......
318 346
        i = self.containers.index(m) + 1
319 347
        self.assertEquals(self.containers[i:(i+l)], containers)
320 348
    
321
    #def test_extended_list(self):
322
    #    self.list_containers(self.account, limit=3, format='xml')
323
    #    self.list_containers(self.account, limit=3, format='json')
324
    
325 349
    def test_list_json_with_marker(self):
326 350
        l = 2
327 351
        m = 'bananas'
328
        containers = self.client.list_containers(limit=l, marker=m, detail=True)
352
        containers = self.client.list_containers(limit=l, marker=m, format='json')
353
        self.assert_extended(containers, 'json', 'container', l)
329 354
        self.assertEqual(containers[0]['name'], 'kiwis')
330 355
        self.assertEqual(containers[1]['name'], 'oranges')
331 356
    
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')
357
    def test_list_xml_with_marker(self):
358
        l = 2
359
        m = 'oranges'
360
        xml = self.client.list_containers(limit=l, marker=m, format='xml')
361
        #self.assert_extended(xml, 'xml', 'container', l)
362
        nodes = xml.getElementsByTagName('name')
363
        self.assertEqual(len(nodes), 1)
364
        self.assertEqual(nodes[0].childNodes[0].data, 'pears')
339 365
    
340 366
    def test_if_modified_since(self):
341 367
        t = datetime.datetime.utcnow()
......
404 430
        self.client.update_account_metadata(**meta)
405 431
        self.assertEqual(meta, self.client.retrieve_account_metadata(restricted=True))
406 432
    
407
    #def test_invalid_account_update_meta(self):
408
    #    with AssertMappingInvariant(self.get_account_meta, self.account):
409
    #        meta = {'HTTP_X_ACCOUNT_META_TEST':'test',
410
    #               'HTTP_X_ACCOUNT_META_TOST':'tost'}
411
    #        response = self.update_account_meta('non-existing-account', **meta)
433
    def test_invalid_account_update_meta(self):
434
        meta = {'HTTP_X_ACCOUNT_META_TEST':'test',
435
               'HTTP_X_ACCOUNT_META_TOST':'tost'}
436
        self.assert_raises_fault(401,
437
                                 self.invalid_client.update_account_metadata,
438
                                 **meta)
412 439

  
413 440
class ContainerHead(BaseTestCase):
414 441
    def setUp(self):
......
486 513
        self.assertEquals(['photos/me.jpg'], objects)
487 514
    
488 515
    def test_extended_list_json(self):
489
        objects = self.client.list_objects(self.container[1], detail=True,
516
        objects = self.client.list_objects(self.container[1], format='json',
490 517
                                           limit=2, prefix='photos/animals',
491 518
                                           delimiter='/')
492 519
        self.assertEqual(objects[0]['subdir'], 'photos/animals/cats/')
493 520
        self.assertEqual(objects[1]['subdir'], 'photos/animals/dogs/')
494 521
    
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')
522
    def test_extended_list_xml(self):
523
        xml = self.client.list_objects(self.container[1], format='xml', limit=4,
524
                                       prefix='photos', delimiter='/')
525
        dirs = xml.getElementsByTagName('subdir')
526
        self.assertEqual(len(dirs), 2)
527
        self.assertEqual(dirs[0].attributes['name'].value, 'photos/animals/')
528
        self.assertEqual(dirs[1].attributes['name'].value, 'photos/plants/')
529
        
530
        objects = xml.getElementsByTagName('name')
531
        self.assertEqual(len(objects), 1)
532
        self.assertEqual(objects[0].childNodes[0].data, 'photos/me.jpg')
506 533
    
507 534
    def test_list_meta_double_matching(self):
508 535
        meta = {'quality':'aaa', 'stock':'true'}
......
978 1005
        fname = 'largefile'
979 1006
        o = self.upload_random_data(self.containers[1], fname, l)
980 1007
        if o:
981
            data = self.client.retrieve_object(self.containers[1], fname, detail=True)
1008
            data = self.client.retrieve_object(self.containers[1], fname,
1009
                                               format='json')
982 1010
            body = json.loads(data)
983 1011
            hashes = body['hashes']
984 1012
            block_size = body['block_size']
......
1026 1054
        self.assert_raises_fault(422, self.upload_random_data, self.container,
1027 1055
                                 o_names[0], **meta)
1028 1056
    
1029
    def test_chucked_transfer(self):
1057
    def test_chunked_transfer(self):
1030 1058
        data = get_random_data()
1031 1059
        objname = 'object'
1032 1060
        self.client.create_object_using_chunks(self.container, objname,
......
1197 1225
                                    self.containers[0], self.obj['name']):
1198 1226
            self.test_update_object(499, 0, True)
1199 1227
    
1200
    #no use if the server resets the content-legth
1201 1228
    def test_update_object_invalid_range_and_length(self):
1202 1229
        with AssertContentInvariant(self.client.retrieve_object,
1203 1230
                                    self.containers[0], self.obj['name']):
1204 1231
            self.test_update_object(499, 0, True, -1)
1205 1232
    
1206
    #no use if the server resets the content-legth
1207 1233
    def test_update_object_invalid_range_with_no_content_length(self):
1208 1234
        with AssertContentInvariant(self.client.retrieve_object,
1209 1235
                                    self.containers[0], self.obj['name']):

Also available in: Unified diff