Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / tests / pithos.py @ 1f5debf7

History | View | Annotate | Download (42.5 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
from kamaki.clients.astakos import AstakosClient
42

    
43

    
44
class Pithos(tests.Generic):
45

    
46
    files = []
47

    
48
    def setUp(self):
49
        self.client = PithosClient(
50
            self['store', 'url'],
51
            self['store', 'token'],
52
            AstakosClient(
53
                self['astakos', 'url'],
54
                self['store', 'token']
55
            ).term('uuid'))
56

    
57
        self.now = time.mktime(time.gmtime())
58
        self.now_unformated = datetime.datetime.utcnow()
59
        self._init_data()
60

    
61
        """Prepare an object to be shared - also its container"""
62
        self.client.container = self.c1
63
        self.client.object_post('test',
64
            update=True,
65
            permissions={'read': [self.client.account]})
66

    
67
        self.create_remote_object(self.c1, 'another.test')
68

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

    
86
        self.create_remote_object(self.c1, 'test')
87
        self.create_remote_object(self.c2, 'test')
88
        self.create_remote_object(self.c1, 'test1')
89
        self.create_remote_object(self.c2, 'test1')
90

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

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

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

    
122
    def test_000(self):
123
        """Prepare a full Pithos+ test"""
124
        print('')
125
        super(self.__class__, self).test_000()
126

    
127
    def test_account_head(self):
128
        """Test account_HEAD"""
129
        self._test_0010_account_head()
130

    
131
    def _test_0010_account_head(self):
132
        r = self.client.account_head()
133
        self.assertEqual(r.status_code, 204)
134

    
135
        r = self.client.account_head(until='1000000000')
136
        self.assertEqual(r.status_code, 204)
137

    
138
        r = self.client.get_account_info(until='1000000000')
139
        datestring = unicode(r['x-account-until-timestamp'])
140
        self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
141

    
142
        r = self.client.get_account_quota()
143
        self.assertTrue('x-account-policy-quota' in r)
144

    
145
        r = self.client.get_account_versioning()
146
        self.assertTrue('x-account-policy-versioning' in r)
147

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

    
161
    def test_account_get(self):
162
        """Test account_GET"""
163
        self._test_0020_account_get()
164

    
165
    def _test_0020_account_get(self):
166
        #r = self.client.account_get()
167
        #self.assertEqual(r.status_code, 200)
168
        r = self.client.list_containers()
169
        fullLen = len(r)
170
        self.assertTrue(fullLen > 2)
171

    
172
        r = self.client.account_get(limit=1)
173
        self.assertEqual(len(r.json), 1)
174

    
175
        r = self.client.account_get(marker='c2_')
176
        temp_c0 = r.json[0]['name']
177
        temp_c2 = r.json[2]['name']
178

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

    
185
        r = self.client.account_get(show_only_shared=True)
186
        self.assertTrue(self.c1 in [c['name'] for c in r.json])
187

    
188
        r = self.client.account_get(until=1342609206)
189
        self.assertTrue(len(r.json) <= fullLen)
190

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

    
204
        """Check sharing_accounts"""
205
        r = self.client.get_sharing_accounts()
206
        self.assertTrue(len(r) > 0)
207

    
208
    def test_account_post(self):
209
        """Test account_POST"""
210
        self._test_0030_account_post()
211

    
212
    def _test_0030_account_post(self):
213
        r = self.client.account_post()
214
        self.assertEqual(r.status_code, 202)
215
        grpName = 'grp' + unicode(self.now)
216

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

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

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

    
238
        self.client.del_account_meta(mprefix + '2')
239
        r = self.client.get_account_meta()
240
        self.assertTrue('x-account-meta-' + mprefix + '2' not in r)
241

    
242
        """Missing testing for quota, versioning, because normally
243
        you don't have permissions to modify those at account level
244
        """
245

    
246
        newquota = 1000000
247
        self.client.set_account_quota(newquota)
248
        #r = self.client.get_account_info()
249
        #print(unicode(r))
250
        #r = self.client.get_account_quota()
251
        #self.assertEqual(r['x-account-policy-quota'], newquota)
252
        self.client.set_account_versioning('auto')
253

    
254
    def test_container_head(self):
255
        """Test container_HEAD"""
256
        self._test_0040_container_head()
257

    
258
    def _test_0040_container_head(self):
259
        self.client.container = self.c1
260

    
261
        r = self.client.container_head()
262
        self.assertEqual(r.status_code, 204)
263

    
264
        """Check until"""
265
        r = self.client.container_head(until=1000000, success=(204, 404))
266
        self.assertEqual(r.status_code, 404)
267

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

    
281
        """Check container object meta"""
282
        r = self.client.get_container_object_meta()
283
        self.assertEqual(r['x-container-object-meta'], 'Incontainer')
284

    
285
    def test_container_get(self):
286
        """Test container_GET"""
287
        self._test_0050_container_get()
288

    
289
    def _test_0050_container_get(self):
290
        self.client.container = self.c1
291

    
292
        r = self.client.container_get()
293
        self.assertEqual(r.status_code, 200)
294
        fullLen = len(r.json)
295

    
296
        r = self.client.container_get(prefix='test')
297
        lalobjects = [obj for obj in r.json if obj['name'].startswith('test')]
298
        self.assertTrue(len(r.json) > 1)
299
        self.assertEqual(len(r.json), len(lalobjects))
300

    
301
        r = self.client.container_get(limit=1)
302
        self.assertEqual(len(r.json), 1)
303

    
304
        r = self.client.container_get(marker='another')
305
        self.assertTrue(len(r.json) > 1)
306
        neobjects = [obj for obj in r.json if obj['name'] > 'another']
307
        self.assertEqual(len(r.json), len(neobjects))
308

    
309
        r = self.client.container_get(prefix='another.test', delimiter='.')
310
        self.assertTrue(fullLen > len(r.json))
311

    
312
        r = self.client.container_get(path='/')
313
        self.assertEqual(fullLen, len(r.json))
314

    
315
        r = self.client.container_get(format='xml')
316
        self.assertEqual(r.text.split()[4], 'name="' + self.c1 + '">')
317

    
318
        r = self.client.container_get(meta=['incontainer'])
319
        self.assertTrue(len(r.json) > 0)
320

    
321
        r = self.client.container_get(show_only_shared=True)
322
        self.assertTrue(len(r.json) < fullLen)
323

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

    
329
        except ClientError:
330

    
331
            pass
332

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

    
346
    def test_container_put(self):
347
        """Test container_PUT"""
348
        self._test_0050_container_put()
349

    
350
    def _test_0050_container_put(self):
351
        self.client.container = self.c2
352

    
353
        r = self.client.container_put()
354
        self.assertEqual(r.status_code, 202)
355

    
356
        r = self.client.get_container_quota(self.client.container)
357
        cquota = r.values()[0]
358
        newquota = 2 * int(cquota)
359

    
360
        r = self.client.container_put(quota=newquota)
361
        self.assertEqual(r.status_code, 202)
362

    
363
        r = self.client.get_container_quota(self.client.container)
364
        xquota = int(r.values()[0])
365
        self.assertEqual(newquota, xquota)
366

    
367
        r = self.client.container_put(versioning='auto')
368
        self.assertEqual(r.status_code, 202)
369

    
370
        r = self.client.get_container_versioning(self.client.container)
371
        nvers = r.values()[0]
372
        self.assertEqual('auto', nvers)
373

    
374
        r = self.client.container_put(versioning='none')
375
        self.assertEqual(r.status_code, 202)
376

    
377
        r = self.client.get_container_versioning(self.client.container)
378
        nvers = r.values()[0]
379
        self.assertEqual('none', nvers)
380

    
381
        r = self.client.container_put(metadata={'m1': 'v1', 'm2': 'v2'})
382
        self.assertEqual(r.status_code, 202)
383

    
384
        r = self.client.get_container_meta(self.client.container)
385
        self.assertTrue('x-container-meta-m1' in r)
386
        self.assertEqual(r['x-container-meta-m1'], 'v1')
387
        self.assertTrue('x-container-meta-m2' in r)
388
        self.assertEqual(r['x-container-meta-m2'], 'v2')
389

    
390
        r = self.client.container_put(metadata={'m1': '', 'm2': 'v2a'})
391
        self.assertEqual(r.status_code, 202)
392

    
393
        r = self.client.get_container_meta(self.client.container)
394
        self.assertTrue('x-container-meta-m1' not in r)
395
        self.assertTrue('x-container-meta-m2' in r)
396
        self.assertEqual(r['x-container-meta-m2'], 'v2a')
397

    
398
        self.client.del_container_meta(self.client.container)
399

    
400
    def test_container_post(self):
401
        """Test container_POST"""
402
        self._test_0060_container_post()
403

    
404
    def _test_0060_container_post(self):
405
        self.client.container = self.c2
406

    
407
        """Simple post"""
408
        r = self.client.container_post()
409
        self.assertEqual(r.status_code, 202)
410

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

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

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

    
440
        """Check versioning"""
441
        self.client.set_container_versioning('auto')
442
        r = self.client.get_container_versioning(self.client.container)
443
        nvers = r.values()[0]
444
        self.assertEqual('auto', nvers)
445
        self.client.set_container_versioning('none')
446
        r = self.client.get_container_versioning(self.client.container)
447
        nvers = r.values()[0]
448
        self.assertEqual('none', nvers)
449

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

    
461
        """What is tranfer_encoding? What should I check about it? """
462
        #TODO
463

    
464
        """Check update=False"""
465
        r = self.client.object_post('test',
466
            update=False,
467
            metadata={'newmeta': 'newval'})
468

    
469
        r = self.client.get_object_info('test')
470
        self.assertTrue('x-object-meta-newmeta' in r)
471
        self.assertFalse('x-object-meta-incontainer' in r)
472

    
473
        r = self.client.del_container_meta('m2')
474

    
475
    def test_container_delete(self):
476
        """Test container_DELETE"""
477
        self._test_0070_container_delete()
478

    
479
    def _test_0070_container_delete(self):
480

    
481
        """Fail to delete a non-empty container"""
482
        self.client.container = self.c2
483
        r = self.client.container_delete(success=409)
484
        self.assertEqual(r.status_code, 409)
485

    
486
        """Fail to delete c3 (empty) container"""
487
        self.client.container = self.c3
488
        r = self.client.container_delete(until='1000000000')
489
        self.assertEqual(r.status_code, 204)
490

    
491
        """Delete c3 (empty) container"""
492
        r = self.client.container_delete()
493
        self.assertEqual(r.status_code, 204)
494

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

    
510
    def _test_0080_recreate_deleted_data(self):
511
        self._init_data()
512

    
513
    def test_object_head(self):
514
        """Test object_HEAD"""
515
        self._test_0090_object_head()
516

    
517
    def _test_0090_object_head(self):
518
        self.client.container = self.c2
519
        obj = 'test'
520

    
521
        r = self.client.object_head(obj)
522
        self.assertEqual(r.status_code, 200)
523
        etag = r.headers['etag']
524

    
525
        r = self.client.object_head(obj, version=40)
526
        self.assertEqual(r.headers['x-object-version'], '40')
527

    
528
        r = self.client.object_head(obj, if_etag_match=etag)
529
        self.assertEqual(r.status_code, 200)
530

    
531
        r = self.client.object_head(obj,
532
            if_etag_not_match=etag,
533
            success=(200, 412, 304))
534
        self.assertNotEqual(r.status_code, 200)
535

    
536
        r = self.client.object_head(obj,
537
            version=40,
538
            if_etag_match=etag,
539
            success=412)
540
        self.assertEqual(r.status_code, 412)
541

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

    
555
    def test_object_get(self):
556
        """Test object_GET"""
557
        self._test_0100_object_get()
558

    
559
    def _test_0100_object_get(self):
560
        self.client.container = self.c1
561
        obj = 'test'
562

    
563
        r = self.client.object_get(obj)
564
        self.assertEqual(r.status_code, 200)
565

    
566
        osize = int(r.headers['content-length'])
567
        etag = r.headers['etag']
568

    
569
        r = self.client.object_get(obj, hashmap=True)
570
        self.assertTrue('hashes' in r.json\
571
            and 'block_hash' in r.json\
572
            and 'block_size' in r.json\
573
            and 'bytes' in r.json)
574

    
575
        r = self.client.object_get(obj, format='xml', hashmap=True)
576
        self.assertEqual(len(r.text.split('hash>')), 3)
577

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

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

    
593
        r = self.client.object_get(obj, if_etag_match=etag)
594
        self.assertEqual(r.status_code, 200)
595

    
596
        r = self.client.object_get(obj, if_etag_not_match=etag + 'LALALA')
597
        self.assertEqual(r.status_code, 200)
598

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

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

    
624
        print('\tCheck if files match...')
625
        for pos in (0, f_size / 2, f_size - 20):
626
            src_f.seek(pos)
627
            dnl_f.seek(pos)
628
            self.assertEqual(src_f.read(10), dnl_f.read(10))
629

    
630
    def test_object_put(self):
631
        """Test object_PUT"""
632
        self._test_object_put()
633

    
634
    def _test_object_put(self):
635
        self.client.container = self.c2
636
        obj = 'another.test'
637

    
638
        self.client.create_object(obj + '.FAKE')
639
        r = self.client.get_object_info(obj + '.FAKE')
640
        self.assertEqual(r['content-type'], 'application/octet-stream')
641

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

    
655
        """Check content-disposition"""
656
        r = self.client.get_object_info(obj)
657
        self.assertTrue('content-disposition' in r)
658

    
659
        """Check permissions"""
660
        r = self.client.get_object_sharing(obj)
661
        self.assertTrue('accx:groupa' in r['read'])
662
        self.assertTrue('u1' in r['read'])
663
        self.assertTrue('u2' in r['write'])
664
        self.assertTrue('u3' in r['write'])
665

    
666
        """Check metadata"""
667
        r = self.client.get_object_meta(obj)
668
        self.assertEqual(r['x-object-meta-key1'], 'val1')
669
        self.assertEqual(r['x-object-meta-key2'], 'val2')
670

    
671
        """Check public and if_etag_match"""
672
        r = self.client.object_put(obj, if_etag_match=etag, data='b',
673
            content_type='application/octet-stream', public=True)
674

    
675
        r = self.client.object_get(obj)
676
        self.assertTrue('x-object-public' in r.headers)
677
        vers2 = int(r.headers['x-object-version'])
678
        etag = r.headers['etag']
679
        self.assertEqual(r.text, 'b')
680

    
681
        """Check if_etag_not_match"""
682
        r = self.client.object_put(obj, if_etag_not_match=etag, data='c',
683
            content_type='application/octet-stream', success=(201, 412))
684
        self.assertEqual(r.status_code, 412)
685

    
686
        """Check content_type and content_length"""
687
        tmpdir = 'dir' + unicode(self.now)
688
        r = self.client.object_put(tmpdir,
689
            content_type='application/directory',
690
            content_length=0)
691

    
692
        r = self.client.get_object_info(tmpdir)
693
        self.assertEqual(r['content-type'], 'application/directory')
694

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

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

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

    
725
        self.assertEqual(r.status_code, 201)
726
        r = self.client.get_object_info(obj)
727
        self.assertEqual(r['etag'], etag)
728

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

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

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

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

    
772
        r = self.client.object_put(mobj,
773
            content_length=0,
774
            content_type='application/octet-stream',
775
            manifest='%s/%s' % (self.client.container, mobj))
776

    
777
        r = self.client.object_get(mobj)
778
        self.assertEqual(r.text, txt)
779

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

    
787
        """Some problems with transfer-encoding?"""
788

    
789
    def test_object_copy(self):
790
        """Test object_COPY"""
791
        self._test_0110_object_copy()
792

    
793
    def _test_0110_object_copy(self):
794
        self.client.container = self.c2
795
        obj = 'test2'
796

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

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

    
814
        """Check content-disposition"""
815
        r = self.client.get_object_info(obj)
816
        self.assertTrue('content-disposition' in r)
817

    
818
        """Check Metadata"""
819
        r = self.client.get_object_meta(obj)
820
        self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
821
        self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
822
        self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
823

    
824
        """Check permissions"""
825
        r = self.client.get_object_sharing(obj)
826
        self.assertFalse('read' in r or 'u2' in r['write'])
827
        self.assertTrue('accx:groupb' in r['write'])
828

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

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

    
848
        """Check ignore_content_type and content_type"""
849
        r = self.client.object_get(obj)
850
        etag = r.headers['etag']
851
        ctype = r.headers['content-type']
852
        self.assertEqual(ctype, 'application/json')
853

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

    
861
        """Check if_etag_(not_)match"""
862
        r = self.client.object_copy(obj,
863
            destination='/%s/%s1' % (self.client.container, obj),
864
            if_etag_match=etag)
865
        self.assertEqual(r.status_code, 201)
866

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

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

    
882
        r = self.client.get_object_info(obj + '3')
883
        self.assertTrue('x-object-public' in r)
884

    
885
    def test_object_move(self):
886
        """Test object_MOVE"""
887
        self._test_0120_object_move()
888

    
889
    def _test_0120_object_move(self):
890
        self.client.container = self.c2
891
        obj = 'test2'
892

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

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

    
909
        """Check Metadata"""
910
        r = self.client.get_object_meta(obj)
911
        self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
912
        self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
913
        self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
914

    
915
        """Check permissions"""
916
        r = self.client.get_object_sharing(obj)
917
        self.assertFalse('read' in r)
918
        self.assertTrue('u5' in r['write'])
919
        self.assertTrue('accx:groupb' in r['write'])
920

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

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

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

    
956
        """Check if_etag_(not_)match"""
957
        self.client.container = self.c2
958
        r = self.client.object_move(obj,
959
            destination='/%s/%s0' % (self.client.container, obj),
960
            if_etag_match=etag)
961
        self.assertEqual(r.status_code, 201)
962

    
963
        r = self.client.object_move(obj + '0',
964
            destination='/%s/%s1' % (self.client.container, obj),
965
            if_etag_not_match='lalala')
966
        self.assertEqual(r.status_code, 201)
967

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

    
975
        r = self.client.get_object_info(obj + '2')
976
        self.assertTrue('x-object-public' in r)
977

    
978
    def test_object_post(self):
979
        """Test object_POST"""
980
        self._test_0130_object_post()
981

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

    
999
        """Append tests update, content_range, content_type, content_length"""
1000
        newf.seek(0)
1001
        self.client.append_object(obj, newf)
1002
        r = self.client.object_get(obj)
1003
        self.assertTrue(r.text.startswith('Hello!'))
1004

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

    
1013
        """Truncate tests update,
1014
            content_range, content_type, object_bytes and source_object"""
1015
        r = self.client.truncate_object(obj, 5)
1016
        r = self.client.object_get(obj)
1017
        self.assertEqual(r.text, 'ello!')
1018

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

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

    
1041
        """Check publish"""
1042
        self.client.publish_object(obj)
1043
        r = self.client.get_object_info(obj)
1044
        self.assertTrue('x-object-public' in r)
1045
        self.client.unpublish_object(obj)
1046
        r = self.client.get_object_info(obj)
1047
        self.assertFalse('x-object-public' in r)
1048

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

    
1060
        r = self.client.object_post(obj, update=True, public=True,
1061
            if_etag_match=etag, content_encoding='application/json')
1062

    
1063
        r = self.client.get_object_info(obj)
1064
        helloVersion = r['x-object-version']
1065
        self.assertTrue('x-object-public' in r)
1066
        self.assertEqual(r['content-encoding'], 'application/json')
1067

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

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

    
1092
        r = self.client.object_get(obj)
1093
        self.assertEqual(r.text, 'eello!')
1094
        self.assertTrue('content-disposition' in r.headers\
1095
            and 'fname.ext' in r.headers['content-disposition'])
1096

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

    
1109
        self.client.create_object_by_manifestation(mobj,
1110
            content_type='application/octet-stream')
1111

    
1112
        r = self.client.object_post(mobj,
1113
            manifest='%s/%s' % (self.client.container, mobj))
1114

    
1115
        r = self.client.object_get(mobj)
1116
        self.assertEqual(r.text, txt)
1117

    
1118
        """We need to check transfer_encoding """
1119

    
1120
    def test_object_delete(self):
1121
        """Test object_DELETE"""
1122
        self._test_0140_object_delete()
1123

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

    
1135
        """Check with false until"""
1136
        r = self.client.object_delete(obj, until=1000000)
1137

    
1138
        r = self.client.object_get(obj, success=(200, 404))
1139
        self.assertEqual(r.status_code, 200)
1140

    
1141
        """Check normal case"""
1142
        r = self.client.object_delete(obj)
1143
        self.assertEqual(r.status_code, 204)
1144

    
1145
        r = self.client.object_get(obj, success=(200, 404))
1146
        self.assertEqual(r.status_code, 404)
1147

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

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