Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-app / pithos / api / swiss_army / tests.py @ 99c11993

History | View | Annotate | Download (15 kB)

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

    
34
import unittest
35
import uuid
36
import random
37
import string
38
import os
39

    
40
from collections import defaultdict
41

    
42
from pithos.api.swiss_army import SwissArmy
43

    
44

    
45
def get_random_data(length=500):
46
    char_set = string.ascii_uppercase + string.digits
47
    return ''.join(random.choice(char_set) for x in xrange(length))
48

    
49

    
50
class SwissArmyTests(unittest.TestCase):
51
    def setUp(self):
52
        self.utils = SwissArmy()
53
        self.accounts = ('account1', 'Account1', 'account2', 'account3')
54
        for i in self.accounts:
55
            self.utils.create_account(i)
56

    
57
    def tearDown(self):
58
        for i in self.accounts:
59
            self.utils._delete_account(i)
60
        self.utils.cleanup()
61

    
62
    def _verify_object(self, account, container, object, expected={},
63
                       strict=True):
64
        self._verify_object_metadata(account, container, object,
65
                                     expected.get('meta'))
66
        self._verify_object_history(account, container, object,
67
                                    expected.get('versions'),
68
                                    strict=strict)
69
        self._verify_object_permissions(account, container, object,
70
                                        expected.get('permissions'))
71

    
72
    def _verify_object_metadata(self, account, container, object, expected):
73
        object_meta = self.utils.backend.get_object_meta(
74
            account, account, container, object, 'pithos')
75
        for k in expected:
76
            self.assertTrue(k in object_meta)
77
            self.assertEquals(object_meta[k], expected[k])
78

    
79
    def _verify_object_history(self, account, container, object, expected,
80
                               strict=True):
81
        history = self.utils.list_past_versions(account, container, object)
82
        if strict:
83
            self.assertEquals(sorted(expected), history)
84
        else:
85
            self.assertTrue(set(expected) <= set(history))
86

    
87
    def _verify_object_permissions(self, account, container, object, expected):
88
        expected = expected or {}
89
        perms_tuple = self.utils.backend.get_object_permissions(
90
            account, account, container, object)
91

    
92
        self.assertEqual(len(perms_tuple), 3)
93

    
94
        object_perms = perms_tuple[2]
95

    
96
        for k in expected:
97
            self.assertTrue(set(expected.get(k)) <= set(object_perms.get(k)))
98

    
99
        for holder in expected.get('read', []):
100
            if holder == '*':
101
                continue
102
            try:
103
                # check first for a group permission
104
                owner, group = holder.split(':')
105
            except ValueError:
106
                holders = [holder]
107
            else:
108
                holders = self.utils.backend.permissions.group_members(owner,
109
                                                                       group)
110

    
111
            for h in holders:
112
                try:
113
                    self.utils.backend.get_object_meta(
114
                        holder, account, container, object, 'pithos')
115
                except Exception, e:
116
                    self.fail(e)
117

    
118
    def test_existing_accounts(self):
119
        accounts = self.utils.existing_accounts()
120
        self.assertEquals(sorted(accounts), accounts)
121
        self.assertTrue(set(['account1', 'account2']) <= set(accounts))
122

    
123
    def test_duplicate_accounts(self):
124
        duplicates = self.utils.duplicate_accounts()
125
        self.assertTrue(['Account1', 'account1'] in duplicates)
126

    
127
    def test_list_all_containers(self):
128
        step = 10
129
        containers = []
130
        append = containers.append
131
        for i in range(3 * step + 1):
132
            while 1:
133
                cname = unicode(uuid.uuid4())
134
                if cname not in containers:
135
                    append(cname)
136
                    break
137
            self.utils.backend.put_container('account1', 'account1', cname)
138
        self.assertEquals(sorted(containers),
139
                          self.utils.list_all_containers('account1',
140
                                                         step=step))
141

    
142
    def test_list_all_container_objects(self):
143
        containers = ('container1', 'container2')
144
        objects = defaultdict(list)
145
        for c in containers:
146
            self.utils.backend.put_container('account1', 'account1', c)
147
            step = 10
148
            append = objects[c].append
149
            content_type = 'application/octet-stream'
150
            for i in range(3 * step + 1):
151
                while 1:
152
                    oname = unicode(uuid.uuid4())
153
                    if oname not in objects:
154
                        append(oname)
155
                        break
156
                data = get_random_data(int(random.random()))
157
                self.utils.create_update_object('account1', c, oname,
158
                                                content_type, data)
159

    
160
        (self.assertEquals(sorted(objects.get(c)),
161
                           self.utils.list_all_container_objects('account1', c)
162
                           ) for c in containers)
163

    
164
    def test_list_all_objects(self):
165
        containers = ('container1', 'container2')
166
        objects = []
167
        append = objects.append
168
        for c in containers:
169
            self.utils.backend.put_container('account1', 'account1', c)
170
            step = 10
171
            content_type = 'application/octet-stream'
172
            for i in range(3 * step + 1):
173
                while 1:
174
                    oname = unicode(uuid.uuid4())
175
                    if oname not in objects:
176
                        append(os.path.join(c, oname))
177
                        break
178
                data = get_random_data(int(random.random()))
179
                self.utils.create_update_object('account1', c, oname,
180
                                                content_type, data)
181

    
182
        self.assertEquals(len(objects),
183
                          len(self.utils.list_all_objects('account1')))
184
        self.assertEquals(sorted(objects),
185
                          self.utils.list_all_objects('account1'))
186

    
187
    def test_list_past_versions(self):
188
        self.utils.backend.put_container('account1', 'account1', 'container1')
189
        versions = []
190
        append = versions.append
191
        for i in range(5):
192
            data = get_random_data(int(random.random()))
193
            append(self.utils.create_update_object('account1', 'container1',
194
                                                   'object1',
195
                                                   'application/octet-stream',
196
                                                   data))
197
        self.assertEquals(sorted(versions[:-1]),
198
                          self.utils.list_past_versions('account1',
199
                                                        'container1',
200
                                                        'object1'))
201

    
202
    def test_move(self):
203
        # create containers
204
        self.utils.backend.put_container('account1', 'account1', 'container1')
205
        self.utils.backend.put_container('Account1', 'Account1', 'container1')
206

    
207
        # add group
208
        self.utils.backend.update_account_groups('Account1', 'Account1',
209
                                                 {'test': ['account3']})
210

    
211
        # upload object and update it several times
212
        versions = []
213
        append = versions.append
214
        meta = {'foo': 'bar'}
215
        permissions = {'read': ['account1', 'account2', 'Account1:test'],
216
                       'write': ['account2', 'Account1:test']}
217
        for i in range(5):
218
            data = get_random_data(int(random.random()))
219
            append(self.utils.create_update_object('Account1', 'container1',
220
                                                   'object1',
221
                                                   'application/octet-stream',
222
                                                   data, meta, permissions))
223

    
224
        self.utils.move_object('Account1', 'container1', 'object1', 'account1',
225
                               dry=False, silent=True)
226

    
227
        expected = {'meta': meta,
228
                    'versions': versions[:-1],
229
                    'permissions': permissions}
230
        self._verify_object('account1', 'container1', 'object1', expected)
231

    
232
    def test_merge(self):
233
        # create container
234
        self.utils.backend.put_container('Account1', 'Account1', 'container0')
235
        self.utils.backend.put_container('Account1', 'Account1', 'container1')
236

    
237
        # add group
238
        self.utils.backend.update_account_groups('Account1', 'Account1',
239
                                                 {'test': ['account3']})
240

    
241
        # upload objects and update them several times
242
        versions = defaultdict(list)
243
        meta = {'foo': 'bar'}
244
        permissions = {'read': ['account2', 'Account1:test'],
245
                       'write': ['account2', 'Account1:test']}
246

    
247
        for i in range(2):
248
            container = 'container%s' % i
249
            versions[container] = {}
250
            for j in range(3):
251
                object = 'object%s' % j
252
                versions[container][object] = []
253
                append = versions[container][object].append
254
                for k in range(5):
255
                    data = get_random_data(int(random.random()))
256
                    append(self.utils.create_update_object(
257
                        'Account1', container, object,
258
                        'application/octet-stream', data, meta, permissions))
259

    
260
        self.utils.merge_account('Account1', 'account1', only_stats=False,
261
                                 dry=False, silent=True)
262

    
263
        self.assertTrue('Account1' in self.utils.existing_accounts())
264
        self.assertTrue('account1' in self.utils.existing_accounts())
265

    
266
        # assert container has been created
267
        try:
268
            self.utils.backend.get_container_meta('account1', 'account1',
269
                                                  'container1', 'pithos')
270
        except NameError, e:
271
            self.fail(e)
272

    
273
        expected = {'meta': meta,
274
                    'permissions': permissions}
275
        for c, o_dict in versions.iteritems():
276
            for o, versions in o_dict.iteritems():
277
                expected['versions'] = versions[:-1]
278
                self._verify_object('account1', c, o, expected)
279

    
280
    def test_merge_existing_dest_container(self):
281
        # create container
282
        self.utils.backend.put_container('Account1', 'Account1', 'container1')
283
        self.utils.backend.put_container('account1', 'account1', 'container1')
284

    
285
        # add group
286
        self.utils.backend.update_account_groups('Account1', 'Account1',
287
                                                 {'test': ['account3']})
288

    
289
        # upload objects and update them several times
290
        versions = defaultdict(list)
291
        meta = {'foo': 'bar'}
292
        permissions = {'read': ['account2', 'Account1:test'],
293
                       'write': ['account2', 'Account1:test']}
294

    
295
        versions = []
296
        append = versions.append
297
        for k in range(5):
298
            data = get_random_data(int(random.random()))
299
            append(self.utils.create_update_object(
300
                'Account1', 'container1', 'object1',
301
                'application/octet-stream', data, meta, permissions))
302

    
303
        self.utils.merge_account('Account1', 'account1', only_stats=False,
304
                                 dry=False, silent=True)
305

    
306
        self.assertTrue('Account1' in self.utils.existing_accounts())
307
        self.assertTrue('account1' in self.utils.existing_accounts())
308

    
309
        try:
310
            self.utils.backend.get_container_meta('account1', 'account1',
311
                                                  'container1', 'pithos')
312
        except NameError, e:
313
            self.fail(e)
314

    
315
        expected = {'meta': meta,
316
                    'versions': versions[:-1],
317
                    'permissions': permissions}
318
        self._verify_object('account1', 'container1', 'object1', expected)
319

    
320
    def test_merge_existing_dest_object(self):
321
        # create container
322
        self.utils.backend.put_container('Account1', 'Account1', 'container1')
323
        self.utils.backend.put_container('account1', 'account1', 'container1')
324

    
325
        # add group
326
        self.utils.backend.update_account_groups('Account1', 'Account1',
327
                                                 {'test': ['account3']})
328

    
329
        # upload objects and update them several times
330
        versions = defaultdict(list)
331
        meta = {'foo': 'bar'}
332
        permissions = {'read': ['account2', 'Account1:test'],
333
                       'write': ['account2', 'Account1:test']}
334

    
335
        container = 'container1'
336
        object = 'object1'
337
        versions = []
338
        append = versions.append
339
        for k in range(5):
340
            data = get_random_data(int(random.random()))
341
            append(self.utils.create_update_object(
342
                   'Account1', container, object,
343
                   'application/octet-stream', data, meta, permissions))
344
            data = get_random_data(int(random.random()))
345
            self.utils.create_update_object(
346
                   'account1', container, object,
347
                   'application/octet-stream', data, meta, permissions)
348

    
349
        self.utils.merge_account('Account1', 'account1', only_stats=False,
350
                                 dry=False, silent=True)
351

    
352
        self.assertTrue('Account1' in self.utils.existing_accounts())
353
        self.assertTrue('account1' in self.utils.existing_accounts())
354

    
355
        try:
356
            self.utils.backend.get_container_meta('account1', 'account1',
357
                                                  'container1', 'pithos')
358
        except NameError, e:
359
            self.fail(e)
360

    
361
        expected = {'meta': meta,
362
                    'permissions': permissions,
363
                    'versions': versions[:-1]}
364
        self._verify_object('account1', container, object, expected,
365
                            strict=False)
366

    
367

    
368
if __name__ == '__main__':
369
    unittest.main()