Statistics
| Branch: | Tag: | Revision:

root / kamaki / clients / livetest / pithos.py @ c2b5da2f

History | View | Annotate | Download (43.9 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 livetest, ClientError
40
from kamaki.clients.pithos import PithosClient
41
from kamaki.clients.astakos import AstakosClient
42

    
43

    
44
class Pithos(livetest.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(
64
            'test',
65
            update=True,
66
            permissions={'read': [self.client.account]})
67

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

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

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

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

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

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

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

    
129
    def test_account_head(self):
130
        """Test account_HEAD"""
131
        self._test_0010_account_head()
132

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

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

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

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

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

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

    
163
    def test_account_get(self):
164
        """Test account_GET"""
165
        self._test_0020_account_get()
166

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

    
174
        r = self.client.account_get(limit=1)
175
        self.assertEqual(len(r.json), 1)
176

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

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

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

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

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

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

    
210
    def test_account_post(self):
211
        """Test account_POST"""
212
        self._test_0030_account_post()
213

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

    
219
        """Method set/del_account_meta and set_account_groupcall use
220
            account_post internally
221
        """
222
        u1 = self.client.account
223
        #  Invalid display name
224
        u2 = '1nc0r3c7-d15p14y-n4m3'
225
        #  valid display name
226
        u3 = '6488c1b2-cb06-40a8-a02a-d474b8d29c59'
227
        self.assertRaises(
228
            ClientError,
229
            self.client.set_account_group,
230
            grpName, [u1, u2])
231
        self.client.set_account_group(grpName, [u1])
232
        r = self.client.get_account_group()
233
        self.assertEqual(r['x-account-group-' + grpName], '%s' % u1)
234
        try:
235
            self.client.set_account_group(grpName, [u1, u3])
236
            r = self.client.get_account_group()
237
            self.assertEqual(
238
                r['x-account-group-' + grpName],
239
                '%s,%s' % (u1, u3))
240
        except:
241
            print('\tInvalid user id %s (it is ok, though)' % u3)
242
        self.client.del_account_group(grpName)
243
        r = self.client.get_account_group()
244
        self.assertTrue('x-account-group-' + grpName not in r)
245

    
246
        mprefix = 'meta' + unicode(self.now)
247
        self.client.set_account_meta({
248
            mprefix + '1': 'v1',
249
            mprefix + '2': 'v2'})
250
        r = self.client.get_account_meta()
251
        self.assertEqual(r['x-account-meta-' + mprefix + '1'], 'v1')
252
        self.assertEqual(r['x-account-meta-' + mprefix + '2'], 'v2')
253

    
254
        self.client.del_account_meta(mprefix + '1')
255
        r = self.client.get_account_meta()
256
        self.assertTrue('x-account-meta-' + mprefix + '1' not in r)
257

    
258
        self.client.del_account_meta(mprefix + '2')
259
        r = self.client.get_account_meta()
260
        self.assertTrue('x-account-meta-' + mprefix + '2' not in r)
261

    
262
        """Missing testing for quota, versioning, because normally
263
        you don't have permissions to modify those at account level
264
        """
265

    
266
        newquota = 1000000
267
        self.client.set_account_quota(newquota)
268
        #r = self.client.get_account_info()
269
        #print(unicode(r))
270
        #r = self.client.get_account_quota()
271
        #self.assertEqual(r['x-account-policy-quota'], newquota)
272
        self.client.set_account_versioning('auto')
273

    
274
    def test_container_head(self):
275
        """Test container_HEAD"""
276
        self._test_0040_container_head()
277

    
278
    def _test_0040_container_head(self):
279
        self.client.container = self.c1
280

    
281
        r = self.client.container_head()
282
        self.assertEqual(r.status_code, 204)
283

    
284
        """Check until"""
285
        r = self.client.container_head(until=1000000, success=(204, 404))
286
        self.assertEqual(r.status_code, 404)
287

    
288
        """Check and if(un)modified_since"""
289
        for format in self.client.DATE_FORMATS:
290
            now_formated = self.now_unformated.strftime(format)
291
            r1 = self.client.container_head(
292
                if_modified_since=now_formated,
293
                success=(204, 304, 412))
294
            sc1 = r1.status_code
295
            r2 = self.client.container_head(
296
                if_unmodified_since=now_formated,
297
                success=(204, 304, 412))
298
            sc2 = r2.status_code
299
            self.assertNotEqual(sc1, sc2)
300

    
301
        """Check container object meta"""
302
        r = self.client.get_container_object_meta()
303
        self.assertEqual(r['x-container-object-meta'], 'Incontainer')
304

    
305
    def test_container_get(self):
306
        """Test container_GET"""
307
        self._test_0050_container_get()
308

    
309
    def _test_0050_container_get(self):
310
        self.client.container = self.c1
311

    
312
        r = self.client.container_get()
313
        self.assertEqual(r.status_code, 200)
314
        fullLen = len(r.json)
315

    
316
        r = self.client.container_get(prefix='test')
317
        lalobjects = [obj for obj in r.json if obj['name'].startswith('test')]
318
        self.assertTrue(len(r.json) > 1)
319
        self.assertEqual(len(r.json), len(lalobjects))
320

    
321
        r = self.client.container_get(limit=1)
322
        self.assertEqual(len(r.json), 1)
323

    
324
        r = self.client.container_get(marker='another')
325
        self.assertTrue(len(r.json) > 1)
326
        neobjects = [obj for obj in r.json if obj['name'] > 'another']
327
        self.assertEqual(len(r.json), len(neobjects))
328

    
329
        r = self.client.container_get(prefix='another.test', delimiter='.')
330
        self.assertTrue(fullLen > len(r.json))
331

    
332
        r = self.client.container_get(path='/')
333
        self.assertEqual(fullLen, len(r.json))
334

    
335
        r = self.client.container_get(format='xml')
336
        self.assertEqual(r.text.split()[4], 'name="' + self.c1 + '">')
337

    
338
        r = self.client.container_get(meta=['incontainer'])
339
        self.assertTrue(len(r.json) > 0)
340

    
341
        r = self.client.container_get(show_only_shared=True)
342
        self.assertTrue(len(r.json) < fullLen)
343

    
344
        try:
345
            r = self.client.container_get(until=1000000000)
346
            datestring = unicode(r.headers['x-account-until-timestamp'])
347
            self.assertEqual(u'Sun, 09 Sep 2001 01:46:40 GMT', datestring)
348

    
349
        except ClientError:
350

    
351
            pass
352

    
353
        """Check and if un/modified_since"""
354
        for format in self.client.DATE_FORMATS:
355
            now_formated = self.now_unformated.strftime(format)
356
            r1 = self.client.container_get(
357
                if_modified_since=now_formated,
358
                success=(200, 304, 412))
359
            sc1 = r1.status_code
360
            r2 = self.client.container_get(
361
                if_unmodified_since=now_formated,
362
                success=(200, 304, 412))
363
            sc2 = r2.status_code
364
            self.assertNotEqual(sc1, sc2)
365

    
366
    def test_container_put(self):
367
        """Test container_PUT"""
368
        self._test_0050_container_put()
369

    
370
    def _test_0050_container_put(self):
371
        self.client.container = self.c2
372

    
373
        r = self.client.container_put()
374
        self.assertEqual(r.status_code, 202)
375

    
376
        r = self.client.get_container_quota(self.client.container)
377
        cquota = r.values()[0]
378
        newquota = 2 * int(cquota)
379

    
380
        r = self.client.container_put(quota=newquota)
381
        self.assertEqual(r.status_code, 202)
382

    
383
        r = self.client.get_container_quota(self.client.container)
384
        xquota = int(r.values()[0])
385
        self.assertEqual(newquota, xquota)
386

    
387
        r = self.client.container_put(versioning='auto')
388
        self.assertEqual(r.status_code, 202)
389

    
390
        r = self.client.get_container_versioning(self.client.container)
391
        nvers = r.values()[0]
392
        self.assertEqual('auto', nvers)
393

    
394
        r = self.client.container_put(versioning='none')
395
        self.assertEqual(r.status_code, 202)
396

    
397
        r = self.client.get_container_versioning(self.client.container)
398
        nvers = r.values()[0]
399
        self.assertEqual('none', nvers)
400

    
401
        r = self.client.container_put(metadata={'m1': 'v1', 'm2': 'v2'})
402
        self.assertEqual(r.status_code, 202)
403

    
404
        r = self.client.get_container_meta(self.client.container)
405
        self.assertTrue('x-container-meta-m1' in r)
406
        self.assertEqual(r['x-container-meta-m1'], 'v1')
407
        self.assertTrue('x-container-meta-m2' in r)
408
        self.assertEqual(r['x-container-meta-m2'], 'v2')
409

    
410
        r = self.client.container_put(metadata={'m1': '', 'm2': 'v2a'})
411
        self.assertEqual(r.status_code, 202)
412

    
413
        r = self.client.get_container_meta(self.client.container)
414
        self.assertTrue('x-container-meta-m1' not in r)
415
        self.assertTrue('x-container-meta-m2' in r)
416
        self.assertEqual(r['x-container-meta-m2'], 'v2a')
417

    
418
        self.client.del_container_meta(self.client.container)
419

    
420
    def test_container_post(self):
421
        """Test container_POST"""
422
        self._test_0060_container_post()
423

    
424
    def _test_0060_container_post(self):
425
        self.client.container = self.c2
426

    
427
        """Simple post"""
428
        r = self.client.container_post()
429
        self.assertEqual(r.status_code, 202)
430

    
431
        """post meta"""
432
        self.client.set_container_meta({'m1': 'v1', 'm2': 'v2'})
433
        r = self.client.get_container_meta(self.client.container)
434
        self.assertTrue('x-container-meta-m1' in r)
435
        self.assertEqual(r['x-container-meta-m1'], 'v1')
436
        self.assertTrue('x-container-meta-m2' in r)
437
        self.assertEqual(r['x-container-meta-m2'], 'v2')
438

    
439
        """post/2del meta"""
440
        r = self.client.del_container_meta('m1')
441
        r = self.client.set_container_meta({'m2': 'v2a'})
442
        r = self.client.get_container_meta(self.client.container)
443
        self.assertTrue('x-container-meta-m1' not in r)
444
        self.assertTrue('x-container-meta-m2' in r)
445
        self.assertEqual(r['x-container-meta-m2'], 'v2a')
446

    
447
        """check quota"""
448
        r = self.client.get_container_quota(self.client.container)
449
        cquota = r.values()[0]
450
        newquota = 2 * int(cquota)
451
        r = self.client.set_container_quota(newquota)
452
        r = self.client.get_container_quota(self.client.container)
453
        xquota = int(r.values()[0])
454
        self.assertEqual(newquota, xquota)
455
        r = self.client.set_container_quota(cquota)
456
        r = self.client.get_container_quota(self.client.container)
457
        xquota = r.values()[0]
458
        self.assertEqual(cquota, xquota)
459

    
460
        """Check versioning"""
461
        self.client.set_container_versioning('auto')
462
        r = self.client.get_container_versioning(self.client.container)
463
        nvers = r.values()[0]
464
        self.assertEqual('auto', nvers)
465
        self.client.set_container_versioning('none')
466
        r = self.client.get_container_versioning(self.client.container)
467
        nvers = r.values()[0]
468
        self.assertEqual('none', nvers)
469

    
470
        """put_block uses content_type and content_length to
471
        post blocks of data 2 container. All that in upload_object"""
472
        """Change a file at fs"""
473
        f = self.create_large_file(1024 * 1024 * 100)
474
        """Upload it at a directory in container"""
475
        self.client.create_directory('dir')
476
        self.client.upload_object('/dir/sample.file', f)
477
        """Check if file has been uploaded"""
478
        r = self.client.get_object_info('/dir/sample.file')
479
        self.assertTrue(int(r['content-length']) > 100000000)
480

    
481
        """What is tranfer_encoding? What should I check about it? """
482
        #TODO
483

    
484
        """Check update=False"""
485
        r = self.client.object_post(
486
            'test',
487
            update=False,
488
            metadata={'newmeta': 'newval'})
489

    
490
        r = self.client.get_object_info('test')
491
        self.assertTrue('x-object-meta-newmeta' in r)
492
        self.assertFalse('x-object-meta-incontainer' in r)
493

    
494
        r = self.client.del_container_meta('m2')
495

    
496
    def test_container_delete(self):
497
        """Test container_DELETE"""
498
        self._test_0070_container_delete()
499

    
500
    def _test_0070_container_delete(self):
501

    
502
        """Fail to delete a non-empty container"""
503
        self.client.container = self.c2
504
        r = self.client.container_delete(success=409)
505
        self.assertEqual(r.status_code, 409)
506

    
507
        """Fail to delete c3 (empty) container"""
508
        self.client.container = self.c3
509
        r = self.client.container_delete(until='1000000000')
510
        self.assertEqual(r.status_code, 204)
511

    
512
        """Delete c3 (empty) container"""
513
        r = self.client.container_delete()
514
        self.assertEqual(r.status_code, 204)
515

    
516
        """Purge container(empty a container), check versionlist"""
517
        self.client.container = self.c1
518
        r = self.client.object_head('test', success=(200, 404))
519
        self.assertEqual(r.status_code, 200)
520
        self.client.del_container(delimiter='/')
521
        r = self.client.object_head('test', success=(200, 404))
522
        self.assertEqual(r.status_code, 404)
523
        r = self.client.get_object_versionlist('test')
524
        self.assertTrue(len(r) > 0)
525
        self.assertTrue(len(r[0]) > 1)
526
        self.client.purge_container()
527
        self.assertRaises(
528
            ClientError,
529
            self.client.get_object_versionlist,
530
            'test')
531

    
532
    def _test_0080_recreate_deleted_data(self):
533
        self._init_data()
534

    
535
    def test_object_head(self):
536
        """Test object_HEAD"""
537
        self._test_0090_object_head()
538

    
539
    def _test_0090_object_head(self):
540
        self.client.container = self.c2
541
        obj = 'test'
542

    
543
        r = self.client.object_head(obj)
544
        self.assertEqual(r.status_code, 200)
545
        etag = r.headers['etag']
546

    
547
        r = self.client.object_head(obj, version=40)
548
        self.assertEqual(r.headers['x-object-version'], '40')
549

    
550
        r = self.client.object_head(obj, if_etag_match=etag)
551
        self.assertEqual(r.status_code, 200)
552

    
553
        r = self.client.object_head(
554
            obj,
555
            if_etag_not_match=etag,
556
            success=(200, 412, 304))
557
        self.assertNotEqual(r.status_code, 200)
558

    
559
        r = self.client.object_head(
560
            obj,
561
            version=40,
562
            if_etag_match=etag,
563
            success=412)
564
        self.assertEqual(r.status_code, 412)
565

    
566
        """Check and if(un)modified_since"""
567
        for format in self.client.DATE_FORMATS:
568
            now_formated = self.now_unformated.strftime(format)
569
            r1 = self.client.object_head(
570
                obj,
571
                if_modified_since=now_formated,
572
                success=(200, 304, 412))
573
            sc1 = r1.status_code
574
            r2 = self.client.object_head(
575
                obj,
576
                if_unmodified_since=now_formated,
577
                success=(200, 304, 412))
578
            sc2 = r2.status_code
579
            self.assertNotEqual(sc1, sc2)
580

    
581
    def test_object_get(self):
582
        """Test object_GET"""
583
        self._test_0100_object_get()
584

    
585
    def _test_0100_object_get(self):
586
        self.client.container = self.c1
587
        obj = 'test'
588

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

    
592
        osize = int(r.headers['content-length'])
593
        etag = r.headers['etag']
594

    
595
        r = self.client.object_get(obj, hashmap=True)
596
        for term in ('hashes', 'block_hash', 'block_hash', 'bytes'):
597
            self.assertTrue(term in r.json)
598

    
599
        r = self.client.object_get(obj, format='xml', hashmap=True)
600
        self.assertEqual(len(r.text.split('hash>')), 3)
601

    
602
        rangestr = 'bytes=%s-%s' % (osize / 3, osize / 2)
603
        r = self.client.object_get(
604
            obj,
605
            data_range=rangestr,
606
            success=(200, 206))
607
        partsize = int(r.headers['content-length'])
608
        self.assertTrue(0 < partsize and partsize <= 1 + osize / 3)
609

    
610
        rangestr = 'bytes=%s-%s' % (osize / 3, osize / 2)
611
        r = self.client.object_get(
612
            obj,
613
            data_range=rangestr,
614
            if_range=True,
615
            success=(200, 206))
616
        partsize = int(r.headers['content-length'])
617
        self.assertTrue(0 < partsize and partsize <= 1 + osize / 3)
618

    
619
        r = self.client.object_get(obj, if_etag_match=etag)
620
        self.assertEqual(r.status_code, 200)
621

    
622
        r = self.client.object_get(obj, if_etag_not_match=etag + 'LALALA')
623
        self.assertEqual(r.status_code, 200)
624

    
625
        """Check and if(un)modified_since"""
626
        for format in self.client.DATE_FORMATS:
627
            now_formated = self.now_unformated.strftime(format)
628
            r1 = self.client.object_get(
629
                obj,
630
                if_modified_since=now_formated,
631
                success=(200, 304, 412))
632
            sc1 = r1.status_code
633
            r2 = self.client.object_get(
634
                obj,
635
                if_unmodified_since=now_formated,
636
                success=(200, 304, 412))
637
            sc2 = r2.status_code
638
            self.assertNotEqual(sc1, sc2)
639

    
640
        """Upload an object to download"""
641
        trg_fname = 'remotefile_%s' % self.now
642
        f_size = 59247824
643
        src_f = self.create_large_file(f_size)
644
        print('\tUploading...')
645
        self.client.upload_object(trg_fname, src_f)
646
        print('\tDownloading...')
647
        self.files.append(NamedTemporaryFile())
648
        dnl_f = self.files[-1]
649
        self.client.download_object(trg_fname, dnl_f)
650

    
651
        print('\tCheck if files match...')
652
        for pos in (0, f_size / 2, f_size - 20):
653
            src_f.seek(pos)
654
            dnl_f.seek(pos)
655
            self.assertEqual(src_f.read(10), dnl_f.read(10))
656

    
657
    def test_object_put(self):
658
        """Test object_PUT"""
659
        self._test_object_put()
660

    
661
    def _test_object_put(self):
662
        self.client.container = self.c2
663
        obj = 'another.test'
664

    
665
        self.client.create_object(obj + '.FAKE')
666
        r = self.client.get_object_info(obj + '.FAKE')
667
        self.assertEqual(r['content-type'], 'application/octet-stream')
668

    
669
        """create the object"""
670
        r = self.client.object_put(
671
            obj,
672
            data='a',
673
            content_type='application/octer-stream',
674
            permissions=dict(
675
                read=['accX:groupA', 'u1', 'u2'],
676
                write=['u2', 'u3']),
677
            metadata=dict(key1='val1', key2='val2'),
678
            content_encoding='UTF-8',
679
            content_disposition='attachment; filename="fname.ext"')
680
        self.assertEqual(r.status_code, 201)
681
        etag = r.headers['etag']
682

    
683
        """Check content-disposition"""
684
        r = self.client.get_object_info(obj)
685
        self.assertTrue('content-disposition' in r)
686

    
687
        """Check permissions"""
688
        r = self.client.get_object_sharing(obj)
689
        self.assertTrue('accx:groupa' in r['read'])
690
        self.assertTrue('u1' in r['read'])
691
        self.assertTrue('u2' in r['write'])
692
        self.assertTrue('u3' in r['write'])
693

    
694
        """Check metadata"""
695
        r = self.client.get_object_meta(obj)
696
        self.assertEqual(r['x-object-meta-key1'], 'val1')
697
        self.assertEqual(r['x-object-meta-key2'], 'val2')
698

    
699
        """Check public and if_etag_match"""
700
        r = self.client.object_put(
701
            obj,
702
            if_etag_match=etag,
703
            data='b',
704
            content_type='application/octet-stream',
705
            public=True)
706

    
707
        r = self.client.object_get(obj)
708
        self.assertTrue('x-object-public' in r.headers)
709
        vers2 = int(r.headers['x-object-version'])
710
        etag = r.headers['etag']
711
        self.assertEqual(r.text, 'b')
712

    
713
        """Check if_etag_not_match"""
714
        r = self.client.object_put(
715
            obj,
716
            if_etag_not_match=etag,
717
            data='c',
718
            content_type='application/octet-stream',
719
            success=(201, 412))
720
        self.assertEqual(r.status_code, 412)
721

    
722
        """Check content_type and content_length"""
723
        tmpdir = 'dir' + unicode(self.now)
724
        r = self.client.object_put(
725
            tmpdir,
726
            content_type='application/directory',
727
            content_length=0)
728

    
729
        r = self.client.get_object_info(tmpdir)
730
        self.assertEqual(r['content-type'], 'application/directory')
731

    
732
        """Check copy_from, content_encoding"""
733
        r = self.client.object_put(
734
            '%s/%s' % (tmpdir, obj),
735
            format=None,
736
            copy_from='/%s/%s' % (self.client.container, obj),
737
            content_encoding='application/octet-stream',
738
            source_account=self.client.account,
739
            content_length=0,
740
            success=201)
741
        self.assertEqual(r.status_code, 201)
742

    
743
        """Test copy_object for cross-conctainer copy"""
744
        self.client.copy_object(
745
            src_container=self.c2,
746
            src_object='%s/%s' % (tmpdir, obj),
747
            dst_container=self.c1,
748
            dst_object=obj)
749
        self.client.container = self.c1
750
        r1 = self.client.get_object_info(obj)
751
        self.client.container = self.c2
752
        r2 = self.client.get_object_info('%s/%s' % (tmpdir, obj))
753
        self.assertEqual(r1['x-object-hash'], r2['x-object-hash'])
754

    
755
        """Check cross-container copy_from, content_encoding"""
756
        self.client.container = self.c1
757
        fromstr = '/%s/%s/%s' % (self.c2, tmpdir, obj)
758
        r = self.client.object_put(
759
            obj,
760
            format=None,
761
            copy_from=fromstr,
762
            content_encoding='application/octet-stream',
763
            source_account=self.client.account,
764
            content_length=0,
765
            success=201)
766

    
767
        self.assertEqual(r.status_code, 201)
768
        r = self.client.get_object_info(obj)
769
        self.assertEqual(r['etag'], etag)
770

    
771
        """Check source_account"""
772
        self.client.container = self.c2
773
        fromstr = '/%s/%s' % (self.c1, obj)
774
        r = self.client.object_put(
775
            '%sv2' % obj,
776
            format=None,
777
            move_from=fromstr,
778
            content_encoding='application/octet-stream',
779
            source_account='nonExistendAddress@NeverLand.com',
780
            content_length=0,
781
            success=(201, 403))
782
        self.assertEqual(r.status_code, 403)
783

    
784
        """Check cross-container move_from"""
785
        self.client.container = self.c1
786
        r1 = self.client.get_object_info(obj)
787
        self.client.container = self.c2
788
        self.client.move_object(
789
            src_container=self.c1,
790
            src_object=obj,
791
            dst_container=self.c2,
792
            dst_object=obj + 'v0')
793
        r0 = self.client.get_object_info(obj + 'v0')
794
        self.assertEqual(r1['x-object-hash'], r0['x-object-hash'])
795

    
796
        """Check move_from"""
797
        r = self.client.object_put(
798
            '%sv1' % obj,
799
            format=None,
800
            move_from='/%s/%s' % (self.c2, obj),
801
            source_version=vers2,
802
            content_encoding='application/octet-stream',
803
            content_length=0, success=201)
804

    
805
        """Check manifest"""
806
        mobj = 'manifest.test'
807
        txt = ''
808
        for i in range(10):
809
            txt += '%s' % i
810
            r = self.client.object_put(
811
                '%s/%s' % (mobj, i),
812
                data='%s' % i,
813
                content_length=1,
814
                success=201,
815
                content_type='application/octet-stream',
816
                content_encoding='application/octet-stream')
817

    
818
        r = self.client.object_put(
819
            mobj,
820
            content_length=0,
821
            content_type='application/octet-stream',
822
            manifest='%s/%s' % (self.client.container, mobj))
823

    
824
        r = self.client.object_get(mobj)
825
        self.assertEqual(r.text, txt)
826

    
827
        """Upload a local file with one request"""
828
        newf = self.create_large_file(1024 * 10)
829
        self.client.upload_object('sample.file', newf)
830
        """Check if file has been uploaded"""
831
        r = self.client.get_object_info('sample.file')
832
        self.assertEqual(int(r['content-length']), 10240)
833

    
834
        """Some problems with transfer-encoding?"""
835

    
836
    def test_object_copy(self):
837
        """Test object_COPY"""
838
        self._test_0110_object_copy()
839

    
840
    def _test_0110_object_copy(self):
841
        #  TODO: check with source_account option
842
        self.client.container = self.c2
843
        obj = 'test2'
844

    
845
        data = '{"key1":"val1", "key2":"val2"}'
846
        r = self.client.object_put(
847
            '%sorig' % obj,
848
            content_type='application/octet-stream',
849
            data=data,
850
            metadata=dict(mkey1='mval1', mkey2='mval2'),
851
            permissions=dict(
852
                read=['accX:groupA', 'u1', 'u2'],
853
                write=['u2', 'u3']),
854
            content_disposition='attachment; filename="fname.ext"')
855

    
856
        r = self.client.object_copy(
857
            '%sorig' % obj,
858
            destination='/%s/%s' % (self.client.container, obj),
859
            ignore_content_type=False, content_type='application/json',
860
            metadata={'mkey2': 'mval2a', 'mkey3': 'mval3'},
861
            permissions={'write': ['u5', 'accX:groupB']})
862
        self.assertEqual(r.status_code, 201)
863

    
864
        """Check content-disposition"""
865
        r = self.client.get_object_info(obj)
866
        self.assertTrue('content-disposition' in r)
867

    
868
        """Check Metadata"""
869
        r = self.client.get_object_meta(obj)
870
        self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
871
        self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
872
        self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
873

    
874
        """Check permissions"""
875
        r = self.client.get_object_sharing(obj)
876
        self.assertFalse('read' in r or 'u2' in r['write'])
877
        self.assertTrue('accx:groupb' in r['write'])
878

    
879
        """Check destination account"""
880
        r = self.client.object_copy(
881
            obj,
882
            destination='/%s/%s' % (self.c1, obj),
883
            content_encoding='utf8',
884
            content_type='application/json',
885
            destination_account='nonExistendAddress@NeverLand.com',
886
            success=(201, 403))
887
        self.assertEqual(r.status_code, 403)
888

    
889
        """Check destination being another container
890
        and also content_type and content encoding"""
891
        r = self.client.object_copy(
892
            obj,
893
            destination='/%s/%s' % (self.c1, obj),
894
            content_encoding='utf8',
895
            content_type='application/json')
896
        self.assertEqual(r.status_code, 201)
897
        self.assertEqual(
898
            r.headers['content-type'],
899
            'application/json; charset=UTF-8')
900

    
901
        """Check ignore_content_type and content_type"""
902
        r = self.client.object_get(obj)
903
        etag = r.headers['etag']
904
        ctype = r.headers['content-type']
905
        self.assertEqual(ctype, 'application/json')
906

    
907
        r = self.client.object_copy(
908
            '%sorig' % obj,
909
            destination='/%s/%s0' % (self.client.container, obj),
910
            ignore_content_type=True,
911
            content_type='application/json')
912
        self.assertEqual(r.status_code, 201)
913
        self.assertNotEqual(r.headers['content-type'], 'application/json')
914

    
915
        """Check if_etag_(not_)match"""
916
        r = self.client.object_copy(
917
            obj,
918
            destination='/%s/%s1' % (self.client.container, obj),
919
            if_etag_match=etag)
920
        self.assertEqual(r.status_code, 201)
921

    
922
        r = self.client.object_copy(
923
            obj,
924
            destination='/%s/%s2' % (self.client.container, obj),
925
            if_etag_not_match='lalala')
926
        self.assertEqual(r.status_code, 201)
927
        vers2 = r.headers['x-object-version']
928

    
929
        """Check source_version, public and format """
930
        r = self.client.object_copy(
931
            '%s2' % obj,
932
            destination='/%s/%s3' % (self.client.container, obj),
933
            source_version=vers2,
934
            format='xml',
935
            public=True)
936
        self.assertEqual(r.status_code, 201)
937
        self.assertTrue(r.headers['content-type'].index('xml') > 0)
938

    
939
        r = self.client.get_object_info(obj + '3')
940
        self.assertTrue('x-object-public' in r)
941

    
942
    def test_object_move(self):
943
        """Test object_MOVE"""
944
        self._test_0120_object_move()
945

    
946
    def _test_0120_object_move(self):
947
        self.client.container = self.c2
948
        obj = 'test2'
949

    
950
        data = '{"key1": "val1", "key2": "val2"}'
951
        r = self.client.object_put(
952
            '%sorig' % obj,
953
            content_type='application/octet-stream',
954
            data=data,
955
            metadata=dict(mkey1='mval1', mkey2='mval2'),
956
            permissions=dict(
957
                read=['accX:groupA', 'u1', 'u2'],
958
                write=['u2', 'u3']))
959

    
960
        r = self.client.object_move(
961
            '%sorig' % obj,
962
            destination='/%s/%s' % (self.client.container, obj),
963
            ignore_content_type=False,
964
            content_type='application/json',
965
            metadata=dict(mkey2='mval2a', mkey3='mval3'),
966
            permissions=dict(write=['u5', 'accX:groupB']))
967
        self.assertEqual(r.status_code, 201)
968

    
969
        """Check Metadata"""
970
        r = self.client.get_object_meta(obj)
971
        self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
972
        self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
973
        self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
974

    
975
        """Check permissions"""
976
        r = self.client.get_object_sharing(obj)
977
        self.assertFalse('read' in r)
978
        self.assertTrue('u5' in r['write'])
979
        self.assertTrue('accx:groupb' in r['write'])
980

    
981
        """Check destination account"""
982
        r = self.client.object_move(
983
            obj,
984
            destination='/%s/%s' % (self.c1, obj),
985
            content_encoding='utf8',
986
            content_type='application/json',
987
            destination_account='nonExistendAddress@NeverLand.com',
988
            success=(201, 403))
989
        self.assertEqual(r.status_code, 403)
990

    
991
        """Check destination being another container and also
992
        content_type, content_disposition and content encoding"""
993
        r = self.client.object_move(
994
            obj,
995
            destination='/%s/%s' % (self.c1, obj),
996
            content_encoding='utf8',
997
            content_type='application/json',
998
            content_disposition='attachment; filename="fname.ext"')
999
        self.assertEqual(r.status_code, 201)
1000
        self.assertEqual(
1001
            r.headers['content-type'],
1002
            'application/json; charset=UTF-8')
1003
        self.client.container = self.c1
1004
        r = self.client.get_object_info(obj)
1005
        self.assertTrue('content-disposition' in r)
1006
        self.assertTrue('fname.ext' in r['content-disposition'])
1007
        etag = r['etag']
1008
        ctype = r['content-type']
1009
        self.assertEqual(ctype, 'application/json')
1010

    
1011
        """Check ignore_content_type and content_type"""
1012
        r = self.client.object_move(
1013
            obj,
1014
            destination='/%s/%s' % (self.c2, obj),
1015
            ignore_content_type=True,
1016
            content_type='application/json')
1017
        self.assertEqual(r.status_code, 201)
1018
        self.assertNotEqual(r.headers['content-type'], 'application/json')
1019

    
1020
        """Check if_etag_(not_)match"""
1021
        self.client.container = self.c2
1022
        r = self.client.object_move(
1023
            obj,
1024
            destination='/%s/%s0' % (self.client.container, obj),
1025
            if_etag_match=etag)
1026
        self.assertEqual(r.status_code, 201)
1027

    
1028
        r = self.client.object_move(
1029
            '%s0' % obj,
1030
            destination='/%s/%s1' % (self.client.container, obj),
1031
            if_etag_not_match='lalala')
1032
        self.assertEqual(r.status_code, 201)
1033

    
1034
        """Check public and format """
1035
        r = self.client.object_move(
1036
            '%s1' % obj,
1037
            destination='/%s/%s2' % (self.client.container, obj),
1038
            format='xml',
1039
            public=True)
1040
        self.assertEqual(r.status_code, 201)
1041
        self.assertTrue(r.headers['content-type'].index('xml') > 0)
1042

    
1043
        r = self.client.get_object_info(obj + '2')
1044
        self.assertTrue('x-object-public' in r)
1045

    
1046
    def test_object_post(self):
1047
        """Test object_POST"""
1048
        self._test_0130_object_post()
1049

    
1050
    def _test_0130_object_post(self):
1051
        self.client.container = self.c2
1052
        obj = 'test2'
1053
        """create a filesystem file"""
1054
        self.files.append(NamedTemporaryFile())
1055
        newf = self.files[-1]
1056
        newf.writelines([
1057
            'ello!\n',
1058
            'This is a test line\n',
1059
            'inside a test file\n'])
1060
        """create a file on container"""
1061
        r = self.client.object_put(
1062
            obj,
1063
            content_type='application/octet-stream',
1064
            data='H',
1065
            metadata=dict(mkey1='mval1', mkey2='mval2'),
1066
            permissions=dict(
1067
                read=['accX:groupA', 'u1', 'u2'],
1068
                write=['u2', 'u3']))
1069

    
1070
        """Append livetest update, content_[range|type|length]"""
1071
        newf.seek(0)
1072
        self.client.append_object(obj, newf)
1073
        r = self.client.object_get(obj)
1074
        self.assertTrue(r.text.startswith('Hello!'))
1075

    
1076
        """Overwrite livetest update,
1077
            content_type, content_length, content_range
1078
        """
1079
        newf.seek(0)
1080
        r = self.client.overwrite_object(obj, 0, 10, newf)
1081
        r = self.client.object_get(obj)
1082
        self.assertTrue(r.text.startswith('ello!'))
1083

    
1084
        """Truncate livetest update,
1085
            content_range, content_type, object_bytes and source_object"""
1086
        r = self.client.truncate_object(obj, 5)
1087
        r = self.client.object_get(obj)
1088
        self.assertEqual(r.text, 'ello!')
1089

    
1090
        """Check metadata"""
1091
        self.client.set_object_meta(obj, {'mkey2': 'mval2a', 'mkey3': 'mval3'})
1092
        r = self.client.get_object_meta(obj)
1093
        self.assertEqual(r['x-object-meta-mkey1'], 'mval1')
1094
        self.assertEqual(r['x-object-meta-mkey2'], 'mval2a')
1095
        self.assertEqual(r['x-object-meta-mkey3'], 'mval3')
1096
        self.client.del_object_meta(obj, 'mkey1')
1097
        r = self.client.get_object_meta(obj)
1098
        self.assertFalse('x-object-meta-mkey1' in r)
1099

    
1100
        """Check permissions"""
1101
        self.client.set_object_sharing(
1102
            obj,
1103
            read_permition=['u4', 'u5'],
1104
            write_permition=['u4'])
1105
        r = self.client.get_object_sharing(obj)
1106
        self.assertTrue('read' in r)
1107
        self.assertTrue('u5' in r['read'])
1108
        self.assertTrue('write' in r)
1109
        self.assertTrue('u4' in r['write'])
1110
        self.client.del_object_sharing(obj)
1111
        r = self.client.get_object_sharing(obj)
1112
        self.assertTrue(len(r) == 0)
1113

    
1114
        """Check publish"""
1115
        self.client.publish_object(obj)
1116
        r = self.client.get_object_info(obj)
1117
        self.assertTrue('x-object-public' in r)
1118
        self.client.unpublish_object(obj)
1119
        r = self.client.get_object_info(obj)
1120
        self.assertFalse('x-object-public' in r)
1121

    
1122
        """Check if_etag_(not)match"""
1123
        etag = r['etag']
1124
        """
1125
        r = self.client.object_post(
1126
            obj,
1127
            update=True,
1128
            public=True,
1129
            if_etag_not_match=etag,
1130
            success=(412, 202, 204))
1131
        self.assertEqual(r.status_code, 412)
1132
        """
1133

    
1134
        r = self.client.object_post(
1135
            obj,
1136
            update=True,
1137
            public=True,
1138
            if_etag_match=etag,
1139
            content_encoding='application/json')
1140

    
1141
        r = self.client.get_object_info(obj)
1142
        helloVersion = r['x-object-version']
1143
        self.assertTrue('x-object-public' in r)
1144
        self.assertEqual(r['content-encoding'], 'application/json')
1145

    
1146
        """Check source_version and source_account and content_disposition"""
1147
        r = self.client.object_post(
1148
            obj,
1149
            update=True,
1150
            content_type='application/octet-srteam',
1151
            content_length=5,
1152
            content_range='bytes 1-5/*',
1153
            source_object='/%s/%s' % (self.c2, obj),
1154
            source_account='thisAccountWillNeverExist@adminland.com',
1155
            source_version=helloVersion,
1156
            data='12345',
1157
            success=(403, 202, 204))
1158
        self.assertEqual(r.status_code, 403)
1159

    
1160
        r = self.client.object_post(
1161
            obj,
1162
            update=True,
1163
            content_type='application/octet-srteam',
1164
            content_length=5,
1165
            content_range='bytes 1-5/*',
1166
            source_object='/%s/%s' % (self.c2, obj),
1167
            source_account=self.client.account,
1168
            source_version=helloVersion,
1169
            data='12345',
1170
            content_disposition='attachment; filename="fname.ext"')
1171

    
1172
        r = self.client.object_get(obj)
1173
        self.assertEqual(r.text, 'eello!')
1174
        self.assertTrue('content-disposition' in r.headers)
1175
        self.assertTrue('fname.ext' in r.headers['content-disposition'])
1176

    
1177
        """Check manifest"""
1178
        mobj = 'manifest.test'
1179
        txt = ''
1180
        for i in range(10):
1181
            txt += '%s' % i
1182
            r = self.client.object_put(
1183
                '%s/%s' % (mobj, i),
1184
                data='%s' % i,
1185
                content_length=1,
1186
                success=201,
1187
                content_encoding='application/octet-stream',
1188
                content_type='application/octet-stream')
1189

    
1190
        self.client.create_object_by_manifestation(
1191
            mobj,
1192
            content_type='application/octet-stream')
1193

    
1194
        r = self.client.object_post(
1195
            mobj,
1196
            manifest='%s/%s' % (self.client.container, mobj))
1197

    
1198
        r = self.client.object_get(mobj)
1199
        self.assertEqual(r.text, txt)
1200

    
1201
        """We need to check transfer_encoding """
1202

    
1203
    def test_object_delete(self):
1204
        """Test object_DELETE"""
1205
        self._test_0140_object_delete()
1206

    
1207
    def _test_0140_object_delete(self):
1208
        self.client.container = self.c2
1209
        obj = 'test2'
1210
        """create a file on container"""
1211
        r = self.client.object_put(
1212
            obj,
1213
            content_type='application/octet-stream',
1214
            data='H',
1215
            metadata=dict(mkey1='mval1', mkey2='mval2'),
1216
            permissions=dict(
1217
                read=['accX:groupA', 'u1', 'u2'],
1218
                write=['u2', 'u3']))
1219

    
1220
        """Check with false until"""
1221
        r = self.client.object_delete(obj, until=1000000)
1222

    
1223
        r = self.client.object_get(obj, success=(200, 404))
1224
        self.assertEqual(r.status_code, 200)
1225

    
1226
        """Check normal case"""
1227
        r = self.client.object_delete(obj)
1228
        self.assertEqual(r.status_code, 204)
1229

    
1230
        r = self.client.object_get(obj, success=(200, 404))
1231
        self.assertEqual(r.status_code, 404)
1232

    
1233
    def create_large_file(self, size):
1234
        """Create a large file at fs"""
1235
        self.files.append(NamedTemporaryFile())
1236
        f = self.files[-1]
1237
        Ki = size / 8
1238
        bytelist = [b * Ki for b in range(size / Ki)]
1239

    
1240
        def append2file(step):
1241
            f.seek(step)
1242
            f.write(urandom(Ki))
1243
            f.flush()
1244
        self.do_with_progress_bar(
1245
            append2file,
1246
            ' create rand file %s (%sB): ' % (f.name, size),
1247
            bytelist)
1248
        f.seek(0)
1249
        return f