Statistics
| Branch: | Tag: | Revision:

root / snf-pithos-app / pithos / api / manage_accounts / tests.py @ 5ec446aa

History | View | Annotate | Download (15.1 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.manage_accounts import ManageAccounts
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 ManageAccountsTests(unittest.TestCase):
51
    def setUp(self):
52
        self.utils = ManageAccounts()
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=None,
63
                       strict=True):
64
        expected = expected or {}
65
        self._verify_object_metadata(account, container, object,
66
                                     expected.get('meta'))
67
        self._verify_object_history(account, container, object,
68
                                    expected.get('versions'),
69
                                    strict=strict)
70
        self._verify_object_permissions(account, container, object,
71
                                        expected.get('permissions'))
72

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

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

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

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

    
95
        object_perms = perms_tuple[2]
96

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
368

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