Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / tests / pithos.py @ 773d61ca

History | View | Annotate | Download (42.3 kB)

1
# Copyright 2012-2013 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 time
35
import datetime
36
from os import urandom
37
from tempfile import NamedTemporaryFile
38

    
39
from kamaki.clients import tests, ClientError
40
from kamaki.clients.pithos import PithosClient
41

    
42

    
43
class Pithos(tests.Generic):
44

    
45
    files = []
46

    
47
    def setUp(self):
48
        self.client = PithosClient(
49
            self['store', 'url'],
50
            self['store', 'token'],
51
            self['store', 'account'])
52

    
53
        self.now = time.mktime(time.gmtime())
54
        self.now_unformated = datetime.datetime.utcnow()
55
        self._init_data()
56

    
57
        """Prepare an object to be shared - also its container"""
58
        self.client.container = self.c1
59
        self.client.object_post('test',
60
            update=True,
61
            permissions={'read': 'someUser'})
62

    
63
        self.create_remote_object(self.c1, 'another.test')
64

    
65
    def _init_data(self):
66
        self.c1 = 'c1_' + unicode(self.now)
67
        self.c2 = 'c2_' + unicode(self.now)
68
        self.c3 = 'c3_' + unicode(self.now)
69
        try:
70
            self.client.create_container(self.c2)
71
        except ClientError:
72
            pass
73
        try:
74
            self.client.create_container(self.c1)
75
        except ClientError:
76
            pass
77
        try:
78
            self.client.create_container(self.c3)
79
        except ClientError:
80
            pass
81

    
82
        self.create_remote_object(self.c1, 'test')
83
        self.create_remote_object(self.c2, 'test')
84
        self.create_remote_object(self.c1, 'test1')
85
        self.create_remote_object(self.c2, 'test1')
86

    
87
    def create_remote_object(self, container, obj):
88
        self.client.container = container
89
        self.client.object_put(obj,
90
            content_type='application/octet-stream',
91
            data='file %s that lives in %s' % (obj, container),
92
            metadata={'incontainer': container})
93

    
94
    def forceDeleteContainer(self, container):
95
        self.client.container = container
96
        try:
97
            r = self.client.list_objects()
98
        except ClientError:
99
            return
100
        for obj in r:
101
            name = obj['name']
102
            self.client.del_object(name)
103
        r = self.client.container_delete()
104
        self.container = ''
105

    
106
    def tearDown(self):
107
        """Destroy test cases"""
108
        for f in self.files:
109
            f.close()
110
        self.forceDeleteContainer(self.c1)
111
        self.forceDeleteContainer(self.c2)
112
        try:
113
            self.forceDeleteContainer(self.c3)
114
        except ClientError:
115
            pass
116
        self.client.container = ''
117

    
118
    def test_000(self):
119
        """Prepare a full Pithos+ test"""
120
        print('')
121
        super(self.__class__, self).test_000()
122

    
123
    def test_account_head(self):
124
        """Test account_HEAD"""
125
        self._test_0010_account_head()
126

    
127
    def _test_0010_account_head(self):
128
        r = self.client.account_head()
129
        self.assertEqual(r.status_code, 204)
130

    
131
        r = self.client.account_head(until='1000000000')
132
        self.assertEqual(r.status_code, 204)
133

    
134
        r = self.client.get_account_info(until='1000000000')
135
        datestring = unicode(r['x-account-until-timestamp'])
136
        self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
137

    
138
        r = self.client.get_account_quota()
139
        self.assertTrue('x-account-policy-quota' in r)
140

    
141
        r = self.client.get_account_versioning()
142
        self.assertTrue('x-account-policy-versioning' in r)
143

    
144
        """Check if(un)modified_since"""
145
        for format in self.client.DATE_FORMATS:
146
            now_formated = self.now_unformated.strftime(format)
147
            r1 = self.client.account_head(if_modified_since=now_formated,
148
                success=(204, 304, 412))
149
            sc1 = r1.status_code
150
            r1.release()
151
            r2 = self.client.account_head(if_unmodified_since=now_formated,
152
                success=(204, 304, 412))
153
            sc2 = r2.status_code
154
            r2.release()
155
            self.assertNotEqual(sc1, sc2)
156

    
157
    def test_account_get(self):
158
        """Test account_GET"""
159
        self._test_0020_account_get()
160

    
161
    def _test_0020_account_get(self):
162
        #r = self.client.account_get()
163
        #self.assertEqual(r.status_code, 200)
164
        r = self.client.list_containers()
165
        fullLen = len(r)
166
        self.assertTrue(fullLen > 2)
167

    
168
        r = self.client.account_get(limit=1)
169
        self.assertEqual(len(r.json), 1)
170

    
171
        r = self.client.account_get(marker='c2_')
172
        temp_c0 = r.json[0]['name']
173
        temp_c2 = r.json[2]['name']
174

    
175
        r = self.client.account_get(limit=2, marker='c2_')
176
        conames = [container['name'] for container in r.json \
177
            if container['name'].lower().startswith('c2_')]
178
        self.assertTrue(temp_c0 in conames)
179
        self.assertFalse(temp_c2 in conames)
180

    
181
        r = self.client.account_get(show_only_shared=True)
182
        self.assertTrue(self.c1 in [c['name'] for c in r.json])
183

    
184
        r = self.client.account_get(until=1342609206)
185
        self.assertTrue(len(r.json) <= fullLen)
186

    
187
        """Check if(un)modified_since"""
188
        for format in self.client.DATE_FORMATS:
189
            now_formated = self.now_unformated.strftime(format)
190
            r1 = self.client.account_get(if_modified_since=now_formated,
191
                success=(200, 304, 412))
192
            sc1 = r1.status_code
193
            r1.release()
194
            r2 = self.client.account_get(if_unmodified_since=now_formated,
195
                success=(200, 304, 412))
196
            sc2 = r2.status_code
197
            r2.release()
198
            self.assertNotEqual(sc1, sc2)
199

    
200
        """Check sharing_accounts"""
201
        r = self.client.get_sharing_accounts()
202
        self.assertTrue(len(r) > 0)
203

    
204
    def test_account_post(self):
205
        """Test account_POST"""
206
        self._test_0030_account_post()
207

    
208
    def _test_0030_account_post(self):
209
        r = self.client.account_post()
210
        self.assertEqual(r.status_code, 202)
211
        grpName = 'grp' + unicode(self.now)
212

    
213
        """Method set/del_account_meta and set_account_groupcall use
214
            account_post internally
215
        """
216
        self.client.set_account_group(grpName, ['u1', 'u2'])
217
        r = self.client.get_account_group()
218
        self.assertEqual(r['x-account-group-' + grpName], 'u1,u2')
219
        self.client.del_account_group(grpName)
220
        r = self.client.get_account_group()
221
        self.assertTrue('x-account-group-' + grpName not in r)
222

    
223
        mprefix = 'meta' + unicode(self.now)
224
        self.client.set_account_meta({mprefix + '1': 'v1',
225
            mprefix + '2': 'v2'})
226
        r = self.client.get_account_meta()
227
        self.assertEqual(r['x-account-meta-' + mprefix + '1'], 'v1')
228
        self.assertEqual(r['x-account-meta-' + mprefix + '2'], 'v2')
229

    
230
        self.client.del_account_meta(mprefix + '1')
231
        r = self.client.get_account_meta()
232
        self.assertTrue('x-account-meta-' + mprefix + '1' not in r)
233

    
234
        self.client.del_account_meta(mprefix + '2')
235
        r = self.client.get_account_meta()
236
        self.assertTrue('x-account-meta-' + mprefix + '2' not in r)
237

    
238
        """Missing testing for quota, versioning, because normally
239
        you don't have permissions to modify those at account level
240
        """
241

    
242
        newquota = 1000000
243
        self.client.set_account_quota(newquota)
244
        #r = self.client.get_account_info()
245
        #print(unicode(r))
246
        #r = self.client.get_account_quota()
247
        #self.assertEqual(r['x-account-policy-quota'], newquota)
248
        self.client.set_account_versioning('auto')
249

    
250
    def test_container_head(self):
251
        """Test container_HEAD"""
252
        self._test_0040_container_head()
253

    
254
    def _test_0040_container_head(self):
255
        self.client.container = self.c1
256

    
257
        r = self.client.container_head()
258
        self.assertEqual(r.status_code, 204)
259

    
260
        """Check until"""
261
        r = self.client.container_head(until=1000000, success=(204, 404))
262
        self.assertEqual(r.status_code, 404)
263

    
264
        """Check and if(un)modified_since"""
265
        for format in self.client.DATE_FORMATS:
266
            now_formated = self.now_unformated.strftime(format)
267
            r1 = self.client.container_head(if_modified_since=now_formated,
268
                success=(204, 304, 412))
269
            sc1 = r1.status_code
270
            r1.release()
271
            r2 = self.client.container_head(if_unmodified_since=now_formated,
272
                success=(204, 304, 412))
273
            sc2 = r2.status_code
274
            r2.release()
275
            self.assertNotEqual(sc1, sc2)
276

    
277
        """Check container object meta"""
278
        r = self.client.get_container_object_meta()
279
        self.assertEqual(r['x-container-object-meta'], 'Incontainer')
280

    
281
    def test_container_get(self):
282
        """Test container_GET"""
283
        self._test_0050_container_get()
284

    
285
    def _test_0050_container_get(self):
286
        self.client.container = self.c1
287

    
288
        r = self.client.container_get()
289
        self.assertEqual(r.status_code, 200)
290
        fullLen = len(r.json)
291

    
292
        r = self.client.container_get(prefix='test')
293
        lalobjects = [obj for obj in r.json if obj['name'].startswith('test')]
294
        self.assertTrue(len(r.json) > 1)
295
        self.assertEqual(len(r.json), len(lalobjects))
296

    
297
        r = self.client.container_get(limit=1)
298
        self.assertEqual(len(r.json), 1)
299

    
300
        r = self.client.container_get(marker='another')
301
        self.assertTrue(len(r.json) > 1)
302
        neobjects = [obj for obj in r.json if obj['name'] > 'another']
303
        self.assertEqual(len(r.json), len(neobjects))
304

    
305
        r = self.client.container_get(prefix='another.test', delimiter='.')
306
        self.assertTrue(fullLen > len(r.json))
307

    
308
        r = self.client.container_get(path='/')
309
        self.assertEqual(fullLen, len(r.json))
310

    
311
        r = self.client.container_get(format='xml')
312
        self.assertEqual(r.text.split()[4], 'name="' + self.c1 + '">')
313

    
314
        r = self.client.container_get(meta=['incontainer'])
315
        self.assertTrue(len(r.json) > 0)
316

    
317
        r = self.client.container_get(show_only_shared=True)
318
        self.assertTrue(len(r.json) < fullLen)
319

    
320
        try:
321
            r = self.client.container_get(until=1000000000)
322
            datestring = unicode(r.headers['x-account-until-timestamp'])
323
            self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
324

    
325
        except ClientError:
326

    
327
            pass
328

    
329
        """Check and if un/modified_since"""
330
        for format in self.client.DATE_FORMATS:
331
            now_formated = self.now_unformated.strftime(format)
332
            r1 = self.client.container_get(if_modified_since=now_formated,
333
                success=(200, 304, 412))
334
            sc1 = r1.status_code
335
            r1.release()
336
            r2 = self.client.container_get(if_unmodified_since=now_formated,
337
                success=(200, 304, 412))
338
            sc2 = r2.status_code
339
            r2.release()
340
            self.assertNotEqual(sc1, sc2)
341

    
342
    def test_container_put(self):
343
        """Test container_PUT"""
344
        self._test_0050_container_put()
345

    
346
    def _test_0050_container_put(self):
347
        self.client.container = self.c2
348

    
349
        r = self.client.container_put()
350
        self.assertEqual(r.status_code, 202)
351

    
352
        r = self.client.get_container_quota(self.client.container)
353
        cquota = r.values()[0]
354
        newquota = 2 * int(cquota)
355

    
356
        r = self.client.container_put(quota=newquota)
357
        self.assertEqual(r.status_code, 202)
358

    
359
        r = self.client.get_container_quota(self.client.container)
360
        xquota = int(r.values()[0])
361
        self.assertEqual(newquota, xquota)
362

    
363
        r = self.client.container_put(versioning='auto')
364
        self.assertEqual(r.status_code, 202)
365

    
366
        r = self.client.get_container_versioning(self.client.container)
367
        nvers = r.values()[0]
368
        self.assertEqual('auto', nvers)
369

    
370
        r = self.client.container_put(versioning='none')
371
        self.assertEqual(r.status_code, 202)
372

    
373
        r = self.client.get_container_versioning(self.client.container)
374
        nvers = r.values()[0]
375
        self.assertEqual('none', nvers)
376

    
377
        r = self.client.container_put(metadata={'m1': 'v1', 'm2': 'v2'})
378
        self.assertEqual(r.status_code, 202)
379

    
380
        r = self.client.get_container_meta(self.client.container)
381
        self.assertTrue('x-container-meta-m1' in r)
382
        self.assertEqual(r['x-container-meta-m1'], 'v1')
383
        self.assertTrue('x-container-meta-m2' in r)
384
        self.assertEqual(r['x-container-meta-m2'], 'v2')
385

    
386
        r = self.client.container_put(metadata={'m1': '', 'm2': 'v2a'})
387
        self.assertEqual(r.status_code, 202)
388

    
389
        r = self.client.get_container_meta(self.client.container)
390
        self.assertTrue('x-container-meta-m1' not in r)
391
        self.assertTrue('x-container-meta-m2' in r)
392
        self.assertEqual(r['x-container-meta-m2'], 'v2a')
393

    
394
        self.client.del_container_meta(self.client.container)
395

    
396
    def test_container_post(self):
397
        """Test container_POST"""
398
        self._test_0060_container_post()
399

    
400
    def _test_0060_container_post(self):
401
        self.client.container = self.c2
402

    
403
        """Simple post"""
404
        r = self.client.container_post()
405
        self.assertEqual(r.status_code, 202)
406

    
407
        """post meta"""
408
        self.client.set_container_meta({'m1': 'v1', 'm2': 'v2'})
409
        r = self.client.get_container_meta(self.client.container)
410
        self.assertTrue('x-container-meta-m1' in r)
411
        self.assertEqual(r['x-container-meta-m1'], 'v1')
412
        self.assertTrue('x-container-meta-m2' in r)
413
        self.assertEqual(r['x-container-meta-m2'], 'v2')
414

    
415
        """post/2del meta"""
416
        r = self.client.del_container_meta('m1')
417
        r = self.client.set_container_meta({'m2': 'v2a'})
418
        r = self.client.get_container_meta(self.client.container)
419
        self.assertTrue('x-container-meta-m1' not in r)
420
        self.assertTrue('x-container-meta-m2' in r)
421
        self.assertEqual(r['x-container-meta-m2'], 'v2a')
422

    
423
        """check quota"""
424
        r = self.client.get_container_quota(self.client.container)
425
        cquota = r.values()[0]
426
        newquota = 2 * int(cquota)
427
        r = self.client.set_container_quota(newquota)
428
        r = self.client.get_container_quota(self.client.container)
429
        xquota = int(r.values()[0])
430
        self.assertEqual(newquota, xquota)
431
        r = self.client.set_container_quota(cquota)
432
        r = self.client.get_container_quota(self.client.container)
433
        xquota = r.values()[0]
434
        self.assertEqual(cquota, xquota)
435

    
436
        """Check versioning"""
437
        self.client.set_container_versioning('auto')
438
        r = self.client.get_container_versioning(self.client.container)
439
        nvers = r.values()[0]
440
        self.assertEqual('auto', nvers)
441
        self.client.set_container_versioning('none')
442
        r = self.client.get_container_versioning(self.client.container)
443
        nvers = r.values()[0]
444
        self.assertEqual('none', nvers)
445

    
446
        """put_block uses content_type and content_length to
447
        post blocks of data 2 container. All that in upload_object"""
448
        """Change a file at fs"""
449
        f = self.create_large_file(1024 * 1024 * 100)
450
        """Upload it at a directory in container"""
451
        self.client.create_directory('dir')
452
        self.client.upload_object('/dir/sample.file', f)
453
        """Check if file has been uploaded"""
454
        r = self.client.get_object_info('/dir/sample.file')
455
        self.assertTrue(int(r['content-length']) > 100000000)
456

    
457
        """What is tranfer_encoding? What should I check about it? """
458
        #TODO
459

    
460
        """Check update=False"""
461
        r = self.client.object_post('test',
462
            update=False,
463
            metadata={'newmeta': 'newval'})
464

    
465
        r = self.client.get_object_info('test')
466
        self.assertTrue('x-object-meta-newmeta' in r)
467
        self.assertFalse('x-object-meta-incontainer' in r)
468

    
469
        r = self.client.del_container_meta('m2')
470

    
471
    def test_container_delete(self):
472
        """Test container_DELETE"""
473
        self._test_0070_container_delete()
474

    
475
    def _test_0070_container_delete(self):
476

    
477
        """Fail to delete a non-empty container"""
478
        self.client.container = self.c2
479
        r = self.client.container_delete(success=409)
480
        self.assertEqual(r.status_code, 409)
481

    
482
        """Fail to delete c3 (empty) container"""
483
        self.client.container = self.c3
484
        r = self.client.container_delete(until='1000000000')
485
        self.assertEqual(r.status_code, 204)
486

    
487
        """Delete c3 (empty) container"""
488
        r = self.client.container_delete()
489
        self.assertEqual(r.status_code, 204)
490

    
491
        """Purge container(empty a container), check versionlist"""
492
        self.client.container = self.c1
493
        r = self.client.object_head('test', success=(200, 404))
494
        self.assertEqual(r.status_code, 200)
495
        self.client.del_container(delimiter='/')
496
        r = self.client.object_head('test', success=(200, 404))
497
        self.assertEqual(r.status_code, 404)
498
        r = self.client.get_object_versionlist('test')
499
        self.assertTrue(len(r) > 0)
500
        self.assertTrue(len(r[0]) > 1)
501
        self.client.purge_container()
502
        self.assertRaises(ClientError,
503
            self.client.get_object_versionlist,
504
            'test')
505

    
506
    def _test_0080_recreate_deleted_data(self):
507
        self._init_data()
508

    
509
    def test_object_head(self):
510
        """Test object_HEAD"""
511
        self._test_0090_object_head()
512

    
513
    def _test_0090_object_head(self):
514
        self.client.container = self.c2
515
        obj = 'test'
516

    
517
        r = self.client.object_head(obj)
518
        self.assertEqual(r.status_code, 200)
519
        etag = r.headers['etag']
520

    
521
        r = self.client.object_head(obj, version=40)
522
        self.assertEqual(r.headers['x-object-version'], '40')
523

    
524
        r = self.client.object_head(obj, if_etag_match=etag)
525
        self.assertEqual(r.status_code, 200)
526

    
527
        r = self.client.object_head(obj,
528
            if_etag_not_match=etag,
529
            success=(200, 412, 304))
530
        self.assertNotEqual(r.status_code, 200)
531

    
532
        r = self.client.object_head(obj,
533
            version=40,
534
            if_etag_match=etag,
535
            success=412)
536
        self.assertEqual(r.status_code, 412)
537

    
538
        """Check and if(un)modified_since"""
539
        for format in self.client.DATE_FORMATS:
540
            now_formated = self.now_unformated.strftime(format)
541
            r1 = self.client.object_head(obj, if_modified_since=now_formated,
542
                success=(200, 304, 412))
543
            sc1 = r1.status_code
544
            r1.release()
545
            r2 = self.client.object_head(obj, if_unmodified_since=now_formated,
546
                success=(200, 304, 412))
547
            sc2 = r2.status_code
548
            r2.release()
549
            self.assertNotEqual(sc1, sc2)
550

    
551
    def test_object_get(self):
552
        """Test object_GET"""
553
        self._test_0100_object_get()
554

    
555
    def _test_0100_object_get(self):
556
        self.client.container = self.c1
557
        obj = 'test'
558

    
559
        r = self.client.object_get(obj)
560
        self.assertEqual(r.status_code, 200)
561

    
562
        osize = int(r.headers['content-length'])
563
        etag = r.headers['etag']
564

    
565
        r = self.client.object_get(obj, hashmap=True)
566
        self.assertTrue('hashes' in r.json\
567
            and 'block_hash' in r.json\
568
            and 'block_size' in r.json\
569
            and 'bytes' in r.json)
570

    
571
        r = self.client.object_get(obj, format='xml', hashmap=True)
572
        self.assertEqual(len(r.text.split('hash>')), 3)
573

    
574
        rangestr = 'bytes=%s-%s' % (osize / 3, osize / 2)
575
        r = self.client.object_get(obj,
576
            data_range=rangestr,
577
            success=(200, 206))
578
        partsize = int(r.headers['content-length'])
579
        self.assertTrue(0 < partsize and partsize <= 1 + osize / 3)
580

    
581
        rangestr = 'bytes=%s-%s' % (osize / 3, osize / 2)
582
        r = self.client.object_get(obj,
583
            data_range=rangestr,
584
            if_range=True,
585
            success=(200, 206))
586
        partsize = int(r.headers['content-length'])
587
        self.assertTrue(0 < partsize and partsize <= 1 + osize / 3)
588

    
589
        r = self.client.object_get(obj, if_etag_match=etag)
590
        self.assertEqual(r.status_code, 200)
591

    
592
        r = self.client.object_get(obj, if_etag_not_match=etag + 'LALALA')
593
        self.assertEqual(r.status_code, 200)
594

    
595
        """Check and if(un)modified_since"""
596
        for format in self.client.DATE_FORMATS:
597
            now_formated = self.now_unformated.strftime(format)
598
            r1 = self.client.object_get(obj, if_modified_since=now_formated,
599
                success=(200, 304, 412))
600
            sc1 = r1.status_code
601
            r1.release()
602
            r2 = self.client.object_get(obj,
603
                if_unmodified_since=now_formated,
604
                success=(200, 304, 412))
605
            sc2 = r2.status_code
606
            r2.release()
607
            self.assertNotEqual(sc1, sc2)
608

    
609
        """Upload an object to download"""
610
        trg_fname = 'remotefile_%s' % self.now
611
        f_size = 59247824
612
        src_f = self.create_large_file(f_size)
613
        print('\tUploading...')
614
        self.client.upload_object(trg_fname, src_f)
615
        print('\tDownloading...')
616
        self.files.append(NamedTemporaryFile())
617
        dnl_f = self.files[-1]
618
        self.client.download_object(trg_fname, dnl_f)
619

    
620
        print('\tCheck if files match...')
621
        for pos in (0, f_size / 2, f_size - 20):
622
            src_f.seek(pos)
623
            dnl_f.seek(pos)
624
            self.assertEqual(src_f.read(10), dnl_f.read(10))
625

    
626
    def test_object_put(self):
627
        """Test object_PUT"""
628
        self._test_object_put()
629

    
630
    def _test_object_put(self):
631
        self.client.container = self.c2
632
        obj = 'another.test'
633

    
634
        self.client.create_object(obj + '.FAKE')
635
        r = self.client.get_object_info(obj + '.FAKE')
636
        self.assertEqual(r['content-type'], 'application/octet-stream')
637

    
638
        """create the object"""
639
        r = self.client.object_put(obj,
640
            data='a',
641
            content_type='application/octer-stream',
642
            permissions={
643
                'read': ['accX:groupA', 'u1', 'u2'],
644
                'write': ['u2', 'u3']},
645
            metadata={'key1': 'val1', 'key2': 'val2'},
646
            content_encoding='UTF-8',
647
            content_disposition='attachment; filename="fname.ext"')
648
        self.assertEqual(r.status_code, 201)
649
        etag = r.headers['etag']
650

    
651
        """Check content-disposition"""
652
        r = self.client.get_object_info(obj)
653
        self.assertTrue('content-disposition' in r)
654

    
655
        """Check permissions"""
656
        r = self.client.get_object_sharing(obj)
657
        self.assertTrue('accx:groupa' in r['read'])
658
        self.assertTrue('u1' in r['read'])
659
        self.assertTrue('u2' in r['write'])
660
        self.assertTrue('u3' in r['write'])
661

    
662
        """Check metadata"""
663
        r = self.client.get_object_meta(obj)
664
        self.assertEqual(r['x-object-meta-key1'], 'val1')
665
        self.assertEqual(r['x-object-meta-key2'], 'val2')
666

    
667
        """Check public and if_etag_match"""
668
        r = self.client.object_put(obj, if_etag_match=etag, data='b',
669
            content_type='application/octet-stream', public=True)
670

    
671
        r = self.client.object_get(obj)
672
        self.assertTrue('x-object-public' in r.headers)
673
        vers2 = int(r.headers['x-object-version'])
674
        etag = r.headers['etag']
675
        self.assertEqual(r.text, 'b')
676

    
677
        """Check if_etag_not_match"""
678
        r = self.client.object_put(obj, if_etag_not_match=etag, data='c',
679
            content_type='application/octet-stream', success=(201, 412))
680
        self.assertEqual(r.status_code, 412)
681

    
682
        """Check content_type and content_length"""
683
        tmpdir = 'dir' + unicode(self.now)
684
        r = self.client.object_put(tmpdir,
685
            content_type='application/directory',
686
            content_length=0)
687

    
688
        r = self.client.get_object_info(tmpdir)
689
        self.assertEqual(r['content-type'], 'application/directory')
690

    
691
        """Check copy_from, content_encoding"""
692
        r = self.client.object_put('%s/%s' % (tmpdir, obj),
693
            format=None,
694
            copy_from='/%s/%s' % (self.client.container, obj),
695
            content_encoding='application/octet-stream',
696
            source_account=self.client.account,
697
            content_length=0, success=201)
698
        self.assertEqual(r.status_code, 201)
699

    
700
        """Test copy_object for cross-conctainer copy"""
701
        self.client.copy_object(src_container=self.c2,
702
            src_object='%s/%s' % (tmpdir, obj),
703
            dst_container=self.c1,
704
            dst_object=obj)
705
        self.client.container = self.c1
706
        r1 = self.client.get_object_info(obj)
707
        self.client.container = self.c2
708
        r2 = self.client.get_object_info('%s/%s' % (tmpdir, obj))
709
        self.assertEqual(r1['x-object-hash'], r2['x-object-hash'])
710

    
711
        """Check cross-container copy_from, content_encoding"""
712
        self.client.container = self.c1
713
        fromstr = '/%s/%s/%s' % (self.c2, tmpdir, obj)
714
        r = self.client.object_put(obj,
715
            format=None,
716
            copy_from=fromstr,
717
            content_encoding='application/octet-stream',
718
            source_account=self.client.account,
719
            content_length=0, success=201)
720

    
721
        self.assertEqual(r.status_code, 201)
722
        r = self.client.get_object_info(obj)
723
        self.assertEqual(r['etag'], etag)
724

    
725
        """Check source_account"""
726
        self.client.container = self.c2
727
        fromstr = '/%s/%s' % (self.c1, obj)
728
        r = self.client.object_put(obj + 'v2',
729
            format=None,
730
            move_from=fromstr,
731
            content_encoding='application/octet-stream',
732
            source_account='nonExistendAddress@NeverLand.com',
733
            content_length=0,
734
            success=(201, 403))
735
        self.assertEqual(r.status_code, 403)
736

    
737
        """Check cross-container move_from"""
738
        self.client.container = self.c1
739
        r1 = self.client.get_object_info(obj)
740
        self.client.container = self.c2
741
        self.client.move_object(src_container=self.c1,
742
            src_object=obj,
743
            dst_container=self.c2,
744
            dst_object=obj + 'v0')
745
        r0 = self.client.get_object_info(obj + 'v0')
746
        self.assertEqual(r1['x-object-hash'], r0['x-object-hash'])
747

    
748
        """Check move_from"""
749
        r = self.client.object_put(obj + 'v1',
750
            format=None,
751
            move_from='/%s/%s' % (self.c2, obj),
752
            source_version=vers2,
753
            content_encoding='application/octet-stream',
754
            content_length=0, success=201)
755

    
756
        """Check manifest"""
757
        mobj = 'manifest.test'
758
        txt = ''
759
        for i in range(10):
760
            txt += '%s' % i
761
            r = self.client.object_put('%s/%s' % (mobj, i),
762
                data='%s' % i,
763
                content_length=1,
764
                success=201,
765
                content_type='application/octet-stream',
766
                content_encoding='application/octet-stream')
767

    
768
        r = self.client.object_put(mobj,
769
            content_length=0,
770
            content_type='application/octet-stream',
771
            manifest='%s/%s' % (self.client.container, mobj))
772

    
773
        r = self.client.object_get(mobj)
774
        self.assertEqual(r.text, txt)
775

    
776
        """Upload a local file with one request"""
777
        newf = self.create_large_file(1024 * 10)
778
        self.client.upload_object('sample.file', newf)
779
        """Check if file has been uploaded"""
780
        r = self.client.get_object_info('sample.file')
781
        self.assertEqual(int(r['content-length']), 10240)
782

    
783
        """Some problems with transfer-encoding?"""
784

    
785
    def test_object_copy(self):
786
        """Test object_COPY"""
787
        self._test_0110_object_copy()
788

    
789
    def _test_0110_object_copy(self):
790
        self.client.container = self.c2
791
        obj = 'test2'
792

    
793
        data = '{"key1":"val1", "key2":"val2"}'
794
        r = self.client.object_put(obj + 'orig',
795
            content_type='application/octet-stream',
796
            data=data,
797
            metadata={'mkey1': 'mval1', 'mkey2': 'mval2'},
798
            permissions={
799
                'read': ['accX:groupA', 'u1', 'u2'],
800
                'write': ['u2', 'u3']},
801
            content_disposition='attachment; filename="fname.ext"')
802

    
803
        r = self.client.object_copy(obj + 'orig',
804
            destination='/%s/%s' % (self.client.container, obj),
805
            ignore_content_type=False, content_type='application/json',
806
            metadata={'mkey2': 'mval2a', 'mkey3': 'mval3'},
807
            permissions={'write': ['u5', 'accX:groupB']})
808
        self.assertEqual(r.status_code, 201)
809

    
810
        """Check content-disposition"""
811
        r = self.client.get_object_info(obj)
812
        self.assertTrue('content-disposition' in r)
813

    
814
        """Check Metadata"""
815
        r = self.client.get_object_meta(obj)
816
        self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
817
        self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
818
        self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
819

    
820
        """Check permissions"""
821
        r = self.client.get_object_sharing(obj)
822
        self.assertFalse('read' in r or 'u2' in r['write'])
823
        self.assertTrue('accx:groupb' in r['write'])
824

    
825
        """Check destination account"""
826
        r = self.client.object_copy(obj,
827
            destination='/%s/%s' % (self.c1, obj),
828
            content_encoding='utf8',
829
            content_type='application/json',
830
            destination_account='nonExistendAddress@NeverLand.com',
831
            success=(201, 403))
832
        self.assertEqual(r.status_code, 403)
833

    
834
        """Check destination being another container
835
        and also content_type and content encoding"""
836
        r = self.client.object_copy(obj,
837
            destination='/%s/%s' % (self.c1, obj),
838
            content_encoding='utf8',
839
            content_type='application/json')
840
        self.assertEqual(r.status_code, 201)
841
        self.assertEqual(r.headers['content-type'],
842
            'application/json; charset=UTF-8')
843

    
844
        """Check ignore_content_type and content_type"""
845
        r = self.client.object_get(obj)
846
        etag = r.headers['etag']
847
        ctype = r.headers['content-type']
848
        self.assertEqual(ctype, 'application/json')
849

    
850
        r = self.client.object_copy(obj + 'orig',
851
            destination='/%s/%s0' % (self.client.container, obj),
852
            ignore_content_type=True,
853
            content_type='application/json')
854
        self.assertEqual(r.status_code, 201)
855
        self.assertNotEqual(r.headers['content-type'], 'application/json')
856

    
857
        """Check if_etag_(not_)match"""
858
        r = self.client.object_copy(obj,
859
            destination='/%s/%s1' % (self.client.container, obj),
860
            if_etag_match=etag)
861
        self.assertEqual(r.status_code, 201)
862

    
863
        r = self.client.object_copy(obj,
864
            destination='/%s/%s2' % (self.client.container, obj),
865
            if_etag_not_match='lalala')
866
        self.assertEqual(r.status_code, 201)
867
        vers2 = r.headers['x-object-version']
868

    
869
        """Check source_version, public and format """
870
        r = self.client.object_copy(obj + '2',
871
            destination='/%s/%s3' % (self.client.container, obj),
872
            source_version=vers2,
873
            format='xml',
874
            public=True)
875
        self.assertEqual(r.status_code, 201)
876
        self.assertTrue(r.headers['content-type'].index('xml') > 0)
877

    
878
        r = self.client.get_object_info(obj + '3')
879
        self.assertTrue('x-object-public' in r)
880

    
881
    def test_object_move(self):
882
        """Test object_MOVE"""
883
        self._test_0120_object_move()
884

    
885
    def _test_0120_object_move(self):
886
        self.client.container = self.c2
887
        obj = 'test2'
888

    
889
        data = '{"key1": "val1", "key2": "val2"}'
890
        r = self.client.object_put(obj + 'orig',
891
            content_type='application/octet-stream',
892
            data=data,
893
            metadata={'mkey1': 'mval1', 'mkey2': 'mval2'},
894
            permissions={'read': ['accX:groupA', 'u1', 'u2'],
895
                'write': ['u2', 'u3']})
896

    
897
        r = self.client.object_move(obj + 'orig',
898
            destination='/%s/%s' % (self.client.container, obj),
899
            ignore_content_type=False,
900
            content_type='application/json',
901
            metadata={'mkey2': 'mval2a', 'mkey3': 'mval3'},
902
            permissions={'write': ['u5', 'accX:groupB']})
903
        self.assertEqual(r.status_code, 201)
904

    
905
        """Check Metadata"""
906
        r = self.client.get_object_meta(obj)
907
        self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
908
        self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
909
        self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
910

    
911
        """Check permissions"""
912
        r = self.client.get_object_sharing(obj)
913
        self.assertFalse('read' in r)
914
        self.assertTrue('u5' in r['write'])
915
        self.assertTrue('accx:groupb' in r['write'])
916

    
917
        """Check destination account"""
918
        r = self.client.object_move(obj,
919
            destination='/%s/%s' % (self.c1, obj),
920
            content_encoding='utf8',
921
            content_type='application/json',
922
            destination_account='nonExistendAddress@NeverLand.com',
923
            success=(201, 403))
924
        self.assertEqual(r.status_code, 403)
925

    
926
        """Check destination being another container and also
927
        content_type, content_disposition and content encoding"""
928
        r = self.client.object_move(obj,
929
            destination='/%s/%s' % (self.c1, obj),
930
            content_encoding='utf8',
931
            content_type='application/json',
932
            content_disposition='attachment; filename="fname.ext"')
933
        self.assertEqual(r.status_code, 201)
934
        self.assertEqual(r.headers['content-type'],
935
            'application/json; charset=UTF-8')
936
        self.client.container = self.c1
937
        r = self.client.get_object_info(obj)
938
        self.assertTrue('content-disposition' in r\
939
            and 'fname.ext' in r['content-disposition'])
940
        etag = r['etag']
941
        ctype = r['content-type']
942
        self.assertEqual(ctype, 'application/json')
943

    
944
        """Check ignore_content_type and content_type"""
945
        r = self.client.object_move(obj,
946
            destination='/%s/%s' % (self.c2, obj),
947
            ignore_content_type=True,
948
            content_type='application/json')
949
        self.assertEqual(r.status_code, 201)
950
        self.assertNotEqual(r.headers['content-type'], 'application/json')
951

    
952
        """Check if_etag_(not_)match"""
953
        self.client.container = self.c2
954
        r = self.client.object_move(obj,
955
            destination='/%s/%s0' % (self.client.container, obj),
956
            if_etag_match=etag)
957
        self.assertEqual(r.status_code, 201)
958

    
959
        r = self.client.object_move(obj + '0',
960
            destination='/%s/%s1' % (self.client.container, obj),
961
            if_etag_not_match='lalala')
962
        self.assertEqual(r.status_code, 201)
963

    
964
        """Check public and format """
965
        r = self.client.object_move(obj + '1',
966
            destination='/%s/%s2' % (self.client.container, obj),
967
            format='xml', public=True)
968
        self.assertEqual(r.status_code, 201)
969
        self.assertTrue(r.headers['content-type'].index('xml') > 0)
970

    
971
        r = self.client.get_object_info(obj + '2')
972
        self.assertTrue('x-object-public' in r)
973

    
974
    def test_object_post(self):
975
        """Test object_POST"""
976
        self._test_0130_object_post()
977

    
978
    def _test_0130_object_post(self):
979
        self.client.container = self.c2
980
        obj = 'test2'
981
        """create a filesystem file"""
982
        self.files.append(NamedTemporaryFile())
983
        newf = self.files[-1]
984
        newf.writelines(['ello!\n',
985
            'This is a test line\n',
986
            'inside a test file\n'])
987
        """create a file on container"""
988
        r = self.client.object_put(obj,
989
            content_type='application/octet-stream',
990
            data='H',
991
            metadata={'mkey1': 'mval1', 'mkey2': 'mval2'},
992
            permissions={'read': ['accX:groupA', 'u1', 'u2'],
993
                'write': ['u2', 'u3']})
994

    
995
        """Append tests update, content_range, content_type, content_length"""
996
        newf.seek(0)
997
        self.client.append_object(obj, newf)
998
        r = self.client.object_get(obj)
999
        self.assertTrue(r.text.startswith('Hello!'))
1000

    
1001
        """Overwrite tests update,
1002
            content_type, content_length, content_range
1003
        """
1004
        newf.seek(0)
1005
        r = self.client.overwrite_object(obj, 0, 10, newf)
1006
        r = self.client.object_get(obj)
1007
        self.assertTrue(r.text.startswith('ello!'))
1008

    
1009
        """Truncate tests update,
1010
            content_range, content_type, object_bytes and source_object"""
1011
        r = self.client.truncate_object(obj, 5)
1012
        r = self.client.object_get(obj)
1013
        self.assertEqual(r.text, 'ello!')
1014

    
1015
        """Check metadata"""
1016
        self.client.set_object_meta(obj, {'mkey2': 'mval2a', 'mkey3': 'mval3'})
1017
        r = self.client.get_object_meta(obj)
1018
        self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
1019
        self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
1020
        self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1021
        self.client.del_object_meta(obj, 'mkey1')
1022
        r = self.client.get_object_meta(obj)
1023
        self.assertFalse('x-object-meta-mkey1' in r)
1024

    
1025
        """Check permissions"""
1026
        self.client.set_object_sharing(obj,
1027
            read_permition=['u4', 'u5'], write_permition=['u4'])
1028
        r = self.client.get_object_sharing(obj)
1029
        self.assertTrue('read' in r)
1030
        self.assertTrue('u5' in r['read'])
1031
        self.assertTrue('write' in r)
1032
        self.assertTrue('u4' in r['write'])
1033
        self.client.del_object_sharing(obj)
1034
        r = self.client.get_object_sharing(obj)
1035
        self.assertTrue(len(r) == 0)
1036

    
1037
        """Check publish"""
1038
        self.client.publish_object(obj)
1039
        r = self.client.get_object_info(obj)
1040
        self.assertTrue('x-object-public' in r)
1041
        self.client.unpublish_object(obj)
1042
        r = self.client.get_object_info(obj)
1043
        self.assertFalse('x-object-public' in r)
1044

    
1045
        """Check if_etag_(not)match"""
1046
        etag = r['etag']
1047
        """
1048
        r = self.client.object_post(obj,
1049
            update=True,
1050
            public=True,
1051
            if_etag_not_match=etag,
1052
            success=(412, 202, 204))
1053
        self.assertEqual(r.status_code, 412)
1054
        """
1055

    
1056
        r = self.client.object_post(obj, update=True, public=True,
1057
            if_etag_match=etag, content_encoding='application/json')
1058

    
1059
        r = self.client.get_object_info(obj)
1060
        helloVersion = r['x-object-version']
1061
        self.assertTrue('x-object-public' in r)
1062
        self.assertEqual(r['content-encoding'], 'application/json')
1063

    
1064
        """Check source_version and source_account and content_disposition"""
1065
        r = self.client.object_post(obj,
1066
            update=True,
1067
            content_type='application/octet-srteam',
1068
            content_length=5,
1069
            content_range='bytes 1-5/*',
1070
            source_object='/%s/%s' % (self.c2, obj),
1071
            source_account='thisAccountWillNeverExist@adminland.com',
1072
            source_version=helloVersion,
1073
            data='12345',
1074
            success=(403, 202, 204))
1075
        self.assertEqual(r.status_code, 403)
1076

    
1077
        r = self.client.object_post(obj,
1078
            update=True,
1079
            content_type='application/octet-srteam',
1080
            content_length=5,
1081
            content_range='bytes 1-5/*',
1082
            source_object='/%s/%s' % (self.c2, obj),
1083
            source_account=self.client.account,
1084
            source_version=helloVersion,
1085
            data='12345',
1086
            content_disposition='attachment; filename="fname.ext"')
1087

    
1088
        r = self.client.object_get(obj)
1089
        self.assertEqual(r.text, 'eello!')
1090
        self.assertTrue('content-disposition' in r.headers\
1091
            and 'fname.ext' in r.headers['content-disposition'])
1092

    
1093
        """Check manifest"""
1094
        mobj = 'manifest.test'
1095
        txt = ''
1096
        for i in range(10):
1097
            txt += '%s' % i
1098
            r = self.client.object_put('%s/%s' % (mobj, i),
1099
            data='%s' % i,
1100
            content_length=1,
1101
            success=201,
1102
            content_encoding='application/octet-stream',
1103
            content_type='application/octet-stream')
1104

    
1105
        self.client.create_object_by_manifestation(mobj,
1106
            content_type='application/octet-stream')
1107

    
1108
        r = self.client.object_post(mobj,
1109
            manifest='%s/%s' % (self.client.container, mobj))
1110

    
1111
        r = self.client.object_get(mobj)
1112
        self.assertEqual(r.text, txt)
1113

    
1114
        """We need to check transfer_encoding """
1115

    
1116
    def test_object_delete(self):
1117
        """Test object_DELETE"""
1118
        self._test_0140_object_delete()
1119

    
1120
    def _test_0140_object_delete(self):
1121
        self.client.container = self.c2
1122
        obj = 'test2'
1123
        """create a file on container"""
1124
        r = self.client.object_put(obj,
1125
            content_type='application/octet-stream',
1126
            data='H',
1127
            metadata={'mkey1': 'mval1', 'mkey2': 'mval2'},
1128
            permissions={'read': ['accX:groupA', 'u1', 'u2'],
1129
                'write': ['u2', 'u3']})
1130

    
1131
        """Check with false until"""
1132
        r = self.client.object_delete(obj, until=1000000)
1133

    
1134
        r = self.client.object_get(obj, success=(200, 404))
1135
        self.assertEqual(r.status_code, 200)
1136

    
1137
        """Check normal case"""
1138
        r = self.client.object_delete(obj)
1139
        self.assertEqual(r.status_code, 204)
1140

    
1141
        r = self.client.object_get(obj, success=(200, 404))
1142
        self.assertEqual(r.status_code, 404)
1143

    
1144
    def create_large_file(self, size):
1145
        """Create a large file at fs"""
1146
        self.files.append(NamedTemporaryFile())
1147
        f = self.files[-1]
1148
        Ki = size / 8
1149
        bytelist = [b * Ki for b in range(size / Ki)]
1150

    
1151
        def append2file(step):
1152
            f.seek(step)
1153
            f.write(urandom(Ki))
1154
            f.flush()
1155
        self.do_with_progress_bar(
1156
            append2file,
1157
            ' create rand file %s (%sB): ' % (f.name, size),
1158
            bytelist)
1159
        f.seek(0)
1160
        return f