Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-app / pithos / api / test / accounts.py @ 3a19e99b

History | View | Annotate | Download (19.6 kB)

1
#!/usr/bin/env python
2
#coding=utf8
3

    
4
# Copyright 2011-2013 GRNET S.A. All rights reserved.
5
#
6
# Redistribution and use in source and binary forms, with or
7
# without modification, are permitted provided that the following
8
# conditions are met:
9
#
10
#   1. Redistributions of source code must retain the above
11
#      copyright notice, this list of conditions and the following
12
#      disclaimer.
13
#
14
#   2. Redistributions in binary form must reproduce the above
15
#      copyright notice, this list of conditions and the following
16
#      disclaimer in the documentation and/or other materials
17
#      provided with the distribution.
18
#
19
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
20
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
23
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
# POSSIBILITY OF SUCH DAMAGE.
31
#
32
# The views and conclusions contained in the software and
33
# documentation are those of the authors and should not be
34
# interpreted as representing official policies, either expressed
35
# or implied, of GRNET S.A.
36

    
37
from pithos.api.test import PithosAPITest, AssertMappingInvariant,\
38
    DATE_FORMATS
39

    
40
from synnefo.lib import join_urls
41

    
42
import time as _time
43
import datetime
44

    
45

    
46
class AccountHead(PithosAPITest):
47
    def test_get_account_meta(self):
48
        cnames = ['apples', 'bananas', 'kiwis', 'oranges', 'pears']
49

    
50
        # create containers
51
        uploaded_bytes = 0
52
        for cname in cnames:
53
            self.create_container(cname)
54

    
55
            # upload object
56
            name, data, resp = self.upload_object(cname)
57
            uploaded_bytes += len(data)
58

    
59
        # set account meta
60
        self.update_account_meta({'foo': 'bar'})
61

    
62
        account_info = self.get_account_info()
63
        self.assertTrue('X-Account-Meta-Foo' in account_info)
64
        self.assertEqual(account_info['X-Account-Meta-Foo'], 'bar')
65

    
66
        # list containers
67
        containers = self.list_containers()
68
        self.assertEqual(int(account_info['X-Account-Container-Count']),
69
                         len(containers))
70
        usage = 0
71
        for c in containers:
72
            # list objects
73
            objects = self.list_objects(c['name'])
74
            self.assertEqual(c['count'], len(objects))
75
            csum = sum([o['bytes'] for o in objects])
76
            self.assertEqual(int(c['bytes']), csum)
77
            usage += int(c['bytes'])
78

    
79
        self.assertEqual(
80
            int(account_info['x-account-bytes-used']) + uploaded_bytes,
81
            usage)
82

    
83
    def test_get_account_meta_until(self):
84
        self.update_account_meta({'foo': 'bar'})
85

    
86
        account_info = self.get_account_info()
87
        t = datetime.datetime.strptime(account_info['Last-Modified'],
88
                                       DATE_FORMATS[2])
89
        t1 = t + datetime.timedelta(seconds=1)
90
        until = int(_time.mktime(t1.timetuple()))
91

    
92
        _time.sleep(2)
93
        self.update_account_meta({'quality': 'AAA'})
94

    
95
        account_info = self.get_account_info()
96
        t = datetime.datetime.strptime(account_info['Last-Modified'],
97
                                       DATE_FORMATS[-1])
98
        last_modified = int(_time.mktime(t.timetuple()))
99
        assert until < last_modified
100

    
101
        self.assertTrue('X-Account-Meta-Quality' in account_info)
102
        self.assertTrue('X-Account-Meta-Foo' in account_info)
103

    
104
        account_info = self.get_account_info(until=until)
105
        self.assertTrue('X-Account-Meta-Quality' not in account_info)
106
        self.assertTrue('X-Account-Meta-Foo' in account_info)
107
        self.assertTrue('X-Account-Until-Timestamp' in account_info)
108
        t = datetime.datetime.strptime(
109
            account_info['X-Account-Until-Timestamp'], DATE_FORMATS[2])
110
        self.assertTrue(int(_time.mktime(t1.timetuple())) <= until)
111

    
112
    def test_get_account_meta_until_invalid_date(self):
113
        self.update_account_meta({'quality': 'AAA'})
114
        meta = self.get_account_meta(until='-1')
115
        self.assertTrue('X-Account-Meta-Quality' in meta)
116

    
117

    
118
class AccountGet(PithosAPITest):
119
    def setUp(self):
120
        PithosAPITest.setUp(self)
121
        cnames = ['apples', 'bananas', 'kiwis', 'oranges', 'pears']
122

    
123
        # create containers
124
        uploaded_bytes = 0
125
        for cname in cnames:
126
            self.create_container(cname)
127

    
128
            # upload object
129
            name, data, resp = self.upload_object(cname)
130
            uploaded_bytes += len(data)
131

    
132
    def test_list(self):
133
        #list containers: row format
134
        containers = self.list_containers(format=None)
135
        self.assertEquals(containers,
136
                          ['apples', 'bananas', 'kiwis', 'oranges', 'pears'])
137

    
138
    def test_list_shared(self):
139
        # upload and publish object
140
        oname, data, resp = self.upload_object('apples')
141
        url = join_urls(self.pithos_path, self.user, 'apples', oname)
142
        r = self.post(url, content_type='', HTTP_X_OBJECT_PUBLIC='true')
143
        self.assertEqual(r.status_code, 202)
144

    
145
        # upload and share object
146
        other, data, resp = self.upload_object('bananas')
147
        url = join_urls(self.pithos_path, self.user, 'bananas', other)
148
        r = self.post(url, content_type='', HTTP_X_OBJECT_SHARING='read=alice')
149
        self.assertEqual(r.status_code, 202)
150

    
151
        url = join_urls(self.pithos_path, self.user)
152

    
153
        # list shared containers
154
        r = self.get('%s?public=' % url)
155
        objects = r.content.split('\n')
156
        if '' in objects:
157
            objects.remove('')
158
        self.assertEqual(objects, ['apples'])
159

    
160
        # list shared containers
161
        r = self.get('%s?shared=' % url)
162
        objects = r.content.split('\n')
163
        if '' in objects:
164
            objects.remove('')
165
        self.assertEqual(objects, ['bananas'])
166

    
167
        # list public and shared containers
168
        r = self.get('%s?public=&shared=' % url)
169
        objects = r.content.split('\n')
170
        if '' in objects:
171
            objects.remove('')
172
        self.assertEqual(objects, ['apples', 'bananas'])
173

    
174
        # assert forbidden public container listing
175
        r = self.get('%s?public=' % url, user='alice')
176
        self.assertEqual(r.status_code, 403)
177

    
178
        # assert forbidden shared & public container listing
179
        r = self.get('%s?public=&shared=' % url, user='alice')
180
        self.assertEqual(r.status_code, 403)
181

    
182
    def test_list_with_limit(self):
183
        containers = self.list_containers(format=None, limit=2)
184
        self.assertEquals(len(containers), 2)
185
        self.assertEquals(containers, ['apples', 'bananas'])
186

    
187
    def test_list_with_marker(self):
188
        containers = self.list_containers(format=None, limit=2,
189
                                          marker='bananas')
190
        self.assertEquals(containers, ['kiwis', 'oranges'])
191

    
192
        containers = self.list_containers(format=None, limit=2,
193
                                          marker='oranges')
194
        self.assertEquals(containers, ['pears'])
195

    
196
    def test_list_json_with_marker(self):
197
        containers = self.list_containers(format='json', limit=2,
198
                                          marker='bananas')
199
        self.assert_extended(containers, 'json', 'container', 2)
200
        self.assertEqual(containers[0]['name'], 'kiwis')
201
        self.assertEqual(containers[1]['name'], 'oranges')
202

    
203
        containers = self.list_containers(format='json', limit=2,
204
                                          marker='oranges')
205
        self.assert_extended(containers, 'json', 'container', 1)
206
        self.assertEqual(containers[0]['name'], 'pears')
207

    
208
    def test_list_xml_with_marker(self):
209
        xml = self.list_containers(format='xml', limit=2, marker='bananas')
210
        self.assert_extended(xml, 'xml', 'container', 2)
211
        nodes = xml.getElementsByTagName('name')
212
        self.assertTrue(len(nodes) <= 2)
213
        names = [n.childNodes[0].data for n in nodes]
214
        self.assertEqual(names, ['kiwis', 'oranges'])
215

    
216
        xml = self.list_containers(format='xml', limit=2, marker='oranges')
217
        self.assert_extended(xml, 'xml', 'container', 1)
218
        nodes = xml.getElementsByTagName('name')
219
        self.assertTrue(len(nodes) <= 2)
220
        names = [n.childNodes[0].data for n in nodes]
221
        self.assertEqual(names, ['pears'])
222

    
223
    def test_if_modified_since(self):
224
        account_info = self.get_account_info()
225
        last_modified = account_info['Last-Modified']
226
        t1 = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1])
227
        t1_formats = map(t1.strftime, DATE_FORMATS)
228

    
229
        # Check not modified
230
        url = join_urls(self.pithos_path, self.user)
231
        for t in t1_formats:
232
            r = self.get(url, HTTP_IF_MODIFIED_SINCE=t)
233
            self.assertEqual(r.status_code, 304)
234

    
235
        # modify account: add container
236
        _time.sleep(1)
237
        self.create_container('c1')
238

    
239
        # Check modified
240
        for t in t1_formats:
241
            r = self.get(url, HTTP_IF_MODIFIED_SINCE=t)
242
            self.assertEqual(r.status_code, 200)
243
            self.assertEqual(
244
                r.content.split('\n')[:-1],
245
                ['apples', 'bananas', 'c1', 'kiwis', 'oranges', 'pears'])
246

    
247
        account_info = self.get_account_info()
248
        last_modified = account_info['Last-Modified']
249
        t2 = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1])
250
        t2_formats = map(t2.strftime, DATE_FORMATS)
251

    
252
        # modify account: update account meta
253
        _time.sleep(1)
254
        self.update_account_meta({'foo': 'bar'})
255

    
256
        # Check modified
257
        for t in t2_formats:
258
            r = self.get(url, HTTP_IF_MODIFIED_SINCE=t)
259
            self.assertEqual(r.status_code, 200)
260
            self.assertEqual(
261
                r.content.split('\n')[:-1],
262
                ['apples', 'bananas', 'c1', 'kiwis', 'oranges', 'pears'])
263

    
264
    def test_if_modified_since_invalid_date(self):
265
        url = join_urls(self.pithos_path, self.user)
266
        r = self.get(url, HTTP_IF_MODIFIED_SINCE='Monday')
267
        self.assertEqual(r.status_code, 200)
268
        self.assertEqual(
269
            r.content.split('\n')[:-1],
270
            ['apples', 'bananas', 'kiwis', 'oranges', 'pears'])
271

    
272
    def test_if_not_modified_since(self):
273
        url = join_urls(self.pithos_path, self.user)
274
        account_info = self.get_account_info()
275
        last_modified = account_info['Last-Modified']
276
        t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1])
277

    
278
        # Check unmodified
279
        t1 = t + datetime.timedelta(seconds=1)
280
        t1_formats = map(t1.strftime, DATE_FORMATS)
281
        for t in t1_formats:
282
            r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=t)
283
            self.assertEqual(r.status_code, 200)
284
            self.assertEqual(
285
                r.content.split('\n')[:-1],
286
                ['apples', 'bananas', 'kiwis', 'oranges', 'pears'])
287

    
288
        # modify account: add container
289
        _time.sleep(2)
290
        self.create_container('c1')
291

    
292
        account_info = self.get_account_info()
293
        last_modified = account_info['Last-Modified']
294
        t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1])
295
        t2 = t - datetime.timedelta(seconds=1)
296
        t2_formats = map(t2.strftime, DATE_FORMATS)
297

    
298
        # Check modified
299
        for t in t2_formats:
300
            r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=t)
301
            self.assertEqual(r.status_code, 412)
302

    
303
        # modify account: update account meta
304
        _time.sleep(1)
305
        self.update_account_meta({'foo': 'bar'})
306

    
307
        account_info = self.get_account_info()
308
        last_modified = account_info['Last-Modified']
309
        t = datetime.datetime.strptime(last_modified, DATE_FORMATS[-1])
310
        t3 = t - datetime.timedelta(seconds=1)
311
        t3_formats = map(t3.strftime, DATE_FORMATS)
312

    
313
        # Check modified
314
        for t in t3_formats:
315
            r = self.get(url, HTTP_IF_UNMODIFIED_SINCE=t)
316
            self.assertEqual(r.status_code, 412)
317

    
318
    def test_if_unmodified_since_invalid_date(self):
319
        url = join_urls(self.pithos_path, self.user)
320
        r = self.get(url, HTTP_IF_UNMODIFIED_SINCE='Monday')
321
        self.assertEqual(r.status_code, 200)
322
        self.assertEqual(
323
            r.content.split('\n')[:-1],
324
            ['apples', 'bananas', 'kiwis', 'oranges', 'pears'])
325

    
326

    
327
class AccountPost(PithosAPITest):
328
    def setUp(self):
329
        PithosAPITest.setUp(self)
330
        cnames = ['apples', 'bananas', 'kiwis', 'oranges', 'pears']
331

    
332
        # create containers
333
        uploaded_bytes = 0
334
        for cname in cnames:
335
            self.create_container(cname)
336

    
337
            # upload object
338
            name, data, resp = self.upload_object(cname)
339
            uploaded_bytes += len(data)
340

    
341
        # set account meta
342
        self.update_account_meta({'foo': 'bar'})
343

    
344
    def test_update_meta(self):
345
        url = join_urls(self.pithos_path, self.user)
346
        with AssertMappingInvariant(self.get_account_groups):
347
            initial = self.get_account_meta()
348

    
349
            meta = {'test': 'tost', 'ping': 'pong'}
350
            kwargs = dict(('HTTP_X_ACCOUNT_META_%s' % k, str(v))
351
                          for k, v in meta.items())
352
            r = self.post('%s?update=' % url, **kwargs)
353
            self.assertEqual(r.status_code, 202)
354

    
355
            meta.update(initial)
356
            account_meta = self.get_account_meta()
357
            (self.assertTrue('X-Account-Meta-%s' % k in account_meta) for
358
                k in meta.keys())
359
            (self.assertEqual(account_meta['X-Account-Meta-%s' % k], v) for
360
                k, v in meta.items())
361

    
362
    def test_reset_meta(self):
363
        url = join_urls(self.pithos_path, self.user)
364
        with AssertMappingInvariant(self.get_account_groups):
365
            meta = {'test': 'tost', 'ping': 'pong'}
366
            self.update_account_meta(meta)
367

    
368
            new_meta = {'test': 'test33'}
369
            kwargs = dict((
370
                'HTTP_X_ACCOUNT_META_%s' % k, str(v)
371
            ) for k, v in new_meta.items())
372
            r = self.post(url, **kwargs)
373
            self.assertEqual(r.status_code, 202)
374

    
375
            account_meta = self.get_account_meta()
376
            (self.assertTrue('X-Account-Meta-%s' % k in account_meta) for
377
                k in new_meta.keys())
378
            (self.assertEqual(account_meta['X-Account-Meta-%s' % k], v) for
379
                k, v in new_meta.items())
380

    
381
            (self.assertTrue('X-Account-Meta-%s' % k not in account_meta) for
382
                k in meta.keys())
383

    
384
    def test_delete_meta(self):
385
        url = join_urls(self.pithos_path, self.user)
386
        with AssertMappingInvariant(self.get_account_groups):
387
            meta = {'test': 'tost', 'ping': 'pong'}
388
            self.update_account_meta(meta)
389

    
390
            kwargs = dict(
391
                ('HTTP_X_ACCOUNT_META_%s' % k, '') for k, v in meta.items())
392
            r = self.post('%s?update=' % url, **kwargs)
393
            self.assertEqual(r.status_code, 202)
394

    
395
            account_meta = self.get_account_meta()
396

    
397
            (self.assertTrue('X-Account-Meta-%s' % k not in account_meta) for
398
                k in meta.keys())
399

    
400
    def test_set_account_groups(self):
401
        url = join_urls(self.pithos_path, self.user)
402
        with AssertMappingInvariant(self.get_account_meta):
403
            pithosdevs = ['verigak', 'gtsouk', 'chazapis']
404
            r = self.post('%s?update=' % url,
405
                          HTTP_X_ACCOUNT_GROUP_PITHOSDEV=','.join(pithosdevs))
406
            self.assertEqual(r.status_code, 202)
407

    
408
            account_groups = self.get_account_groups()
409
            self.assertTrue(
410
                'X-Account-Group-Pithosdev' in self.get_account_groups())
411
            self.assertEqual(
412
                account_groups['X-Account-Group-Pithosdev'],
413
                ','.join(sorted(pithosdevs)))
414

    
415
            clientdevs = ['pkanavos', 'mvasilak']
416
            r = self.post('%s?update=' % url,
417
                          HTTP_X_ACCOUNT_GROUP_CLIENTSDEV=','.join(clientdevs))
418
            self.assertEqual(r.status_code, 202)
419

    
420
            account_groups = self.get_account_groups()
421
            self.assertTrue(
422
                'X-Account-Group-Pithosdev' in account_groups)
423
            self.assertTrue(
424
                'X-Account-Group-Clientsdev' in account_groups)
425
            self.assertEqual(
426
                account_groups['X-Account-Group-Pithosdev'],
427
                ','.join(sorted(pithosdevs)))
428
            self.assertEqual(
429
                account_groups['X-Account-Group-Clientsdev'],
430
                ','.join(sorted(clientdevs)))
431

    
432
            clientdevs = ['mvasilak']
433
            r = self.post('%s?update=' % url,
434
                          HTTP_X_ACCOUNT_GROUP_CLIENTSDEV=''.join(clientdevs))
435
            self.assertEqual(r.status_code, 202)
436

    
437
            account_groups = self.get_account_groups()
438
            self.assertTrue(
439
                'X-Account-Group-Pithosdev' in account_groups)
440
            self.assertTrue(
441
                'X-Account-Group-Clientsdev' in account_groups)
442
            self.assertEqual(
443
                account_groups['X-Account-Group-Pithosdev'],
444
                ','.join(sorted(pithosdevs)))
445
            self.assertEqual(
446
                account_groups['X-Account-Group-Clientsdev'],
447
                ','.join(sorted(clientdevs)))
448

    
449
    def test_reset_account_groups(self):
450
        url = join_urls(self.pithos_path, self.user)
451
        with AssertMappingInvariant(self.get_account_meta):
452
            groups = {'pithosdev': ['verigak', 'gtsouk', 'chazapis'],
453
                      'clientsdev': ['pkanavos', 'mvasilak']}
454
            headers = dict(('HTTP_X_ACCOUNT_GROUP_%s' % k, ','.join(v))
455
                           for k, v in groups.iteritems())
456
            r = self.post('%s?update=' % url, **headers)
457
            self.assertEqual(r.status_code, 202)
458

    
459
            groups = {'pithosdev': ['verigak',
460
                                    'gtsouk',
461
                                    'chazapis',
462
                                    'papagian']}
463
            headers = dict(('HTTP_X_ACCOUNT_GROUP_%s' % k, ','.join(v))
464
                           for k, v in groups.iteritems())
465
            account_meta = self.get_account_meta()
466
            headers.update(dict(('HTTP_%s' % k.upper().replace('-', '_'), v)
467
                           for k, v in account_meta.iteritems()))
468
            r = self.post(url, **headers)
469
            self.assertEqual(r.status_code, 202)
470

    
471
            account_groups = self.get_account_groups()
472
            self.assertTrue(
473
                'X-Account-Group-Pithosdev' in account_groups)
474
            self.assertTrue(
475
                'X-Account-Group-Clientsdev' not in account_groups)
476
            self.assertEqual(
477
                account_groups['X-Account-Group-Pithosdev'],
478
                ','.join(sorted(groups['pithosdev'])))
479

    
480
    def test_delete_account_groups(self):
481
        url = join_urls(self.pithos_path, self.user)
482
        with AssertMappingInvariant(self.get_account_meta):
483
            groups = {'pithosdev': ['verigak', 'gtsouk', 'chazapis'],
484
                      'clientsdev': ['pkanavos', 'mvasilak']}
485
            headers = dict(('HTTP_X_ACCOUNT_GROUP_%s' % k, ','.join(v))
486
                           for k, v in groups.iteritems())
487
            self.post('%s?update=' % url, **headers)
488

    
489
            kwargs = dict(('HTTP_X_ACCOUNT_GROUP_%s' % k, '')
490
                          for k, v in groups.items())
491
            r = self.post('%s?update=' % url, **kwargs)
492
            self.assertEqual(r.status_code, 202)
493

    
494
            account_groups = self.get_account_groups()
495
            self.assertTrue(
496
                'X-Account-Group-Pithosdev' not in account_groups)
497
            self.assertTrue(
498
                'X-Account-Group-Clientsdev' not in account_groups)