Revision eea28492 snf-tools/synnefo_tools/burnin/pithos_tests.py

b/snf-tools/synnefo_tools/burnin/pithos_tests.py
36 36

  
37 37
"""
38 38

  
39
import os
40 39
import random
41
import tempfile
42 40
from datetime import datetime
41
from tempfile import NamedTemporaryFile
43 42

  
44 43
from synnefo_tools.burnin.common import BurninTests, Proper
45 44
from kamaki.clients import ClientError
46 45

  
47 46

  
47
def sample_block(f, block):
48
    block_size = 4 * 1024 * 1024
49
    f.seek(block * block_size)
50
    ch = [f.read(1)]
51
    f.seek(block_size / 2, 1)
52
    ch.append(f.read(1))
53
    f.seek((block + 1) * block_size - 1)
54
    ch.append(f.read(1))
55
    return ch
56

  
57

  
48 58
# Too many public methods. pylint: disable-msg=R0904
49 59
class PithosTestSuite(BurninTests):
50 60
    """Test Pithos functionality"""
......
52 62
    created_container = Proper(value=None)
53 63
    now_unformated = Proper(value=datetime.utcnow())
54 64
    obj_metakey = Proper(value=None)
65
    large_file = Proper(value=None)
55 66

  
56 67
    def test_005_account_head(self):
57 68
        """HEAD on pithos account"""
......
216 227
        self.info('Status code is OK')
217 228

  
218 229
        fullLen = len(r.json)
230
        self.assertGreater(fullLen, 0)
231
        self.info('There are enough (%s) containers' % fullLen)
232

  
219 233
        obj1 = 'test%s' % random.randint(1000, 9999)
220 234
        pithos.create_object(obj1)
221 235
        obj2 = 'test%s' % random.randint(1000, 9999)
......
375 389
        self.info('Set versioning works')
376 390

  
377 391
        f = self._create_large_file(1024 * 1024 * 100)
392
        self.large_file = f
378 393
        self.info('Created file %s of 100 MB' % f.name)
379 394

  
380 395
        pithos.create_directory('dir')
396
        self.info('Upload the file ...')
381 397
        r = pithos.upload_object('/dir/sample.file', f)
382 398
        for term in ('content-length', 'content-type', 'x-object-version'):
383 399
            self.assertTrue(term in r)
......
398 414
        self.assertFalse('x-object-meta-%s' % self.obj_metakey not in r)
399 415
        self.info('Metadata with update=False works')
400 416

  
401
    def test_050_stop_test(self):
417
    def test_040_container_delete(self):
418
        """Test container DELETE"""
419
        pithos = self.clients.pithos
420

  
421
        r = pithos.container_delete(success=409)
422
        self.assertEqual(r.status_code, 409)
423
        self.assertRaises(ClientError, pithos.container_delete)
424
        self.info('Successfully failed to delete non-empty container')
425

  
426
        r = pithos.container_delete(until='1000000000')
427
        self.assertEqual(r.status_code, 204)
428
        self.info('Successfully failed to delete old-timestamped container')
429

  
430
        obj_names = [o['name'] for o in pithos.container_get().json]
431
        pithos.del_container(delimiter='/')
432
        r = pithos.container_get()
433
        self.assertEqual(len(r.json), 0)
434
        self.info('Successfully emptied container')
435

  
436
        for obj in obj_names:
437
            r = pithos.get_object_versionlist(obj)
438
            self.assertTrue(len(r) > 0)
439
        self.info('Versions are still there')
440

  
441
        pithos.purge_container()
442
        for obj in obj_names:
443
            self.assertRaises(ClientError, pithos.get_object_versionlist, obj)
444
        self.info('Successfully purged container')
445

  
446
        self.temp_containers.remove(pithos.container)
447
        pithos.container = self.temp_containers[-1]
448

  
449
    def test_045_object_head(self):
450
        """Test object HEAD"""
451
        pithos = self.clients.pithos
452

  
453
        obj = 'dir/sample.file'
454
        r = pithos.object_head(obj)
455
        self.assertEqual(r.status_code, 200)
456
        self.info('Status code is OK')
457
        etag = r.headers['etag']
458
        real_version = r.headers['x-object-version']
459

  
460
        self.assertRaises(ClientError, pithos.object_head, obj, version=-10)
461
        r = pithos.object_head(obj, version=real_version)
462
        self.assertEqual(r.headers['x-object-version'], real_version)
463
        self.info('Version works')
464

  
465
        r = pithos.object_head(obj, if_etag_match=etag)
466
        self.assertEqual(r.status_code, 200)
467
        self.info('if-etag-match is OK')
468

  
469
        r = pithos.object_head(
470
            obj, if_etag_not_match=etag, success=(200, 412, 304))
471
        self.assertNotEqual(r.status_code, 200)
472
        self.info('if-etag-not-match works')
473

  
474
        r = pithos.object_head(
475
            obj, version=real_version, if_etag_match=etag, success=200)
476
        self.assertEqual(r.status_code, 200)
477
        self.info('Version with if-etag-match works')
478

  
479
        for format in pithos.DATE_FORMATS:
480
            now_formated = self.now_unformated.strftime(format)
481
            r1 = pithos.object_head(
482
                obj, if_modified_since=now_formated, success=(200, 304, 412))
483
            r2 = pithos.object_head(
484
                obj, if_unmodified_since=now_formated, success=(200, 304, 412))
485
            self.assertNotEqual(r1.status_code, r2.status_code)
486
        self.info('if-(un)modified-since works')
487

  
488
    def test_050_object_get(self):
489
        """Test object GET"""
490
        pithos = self.clients.pithos
491
        obj = 'dir/sample.file'
492

  
493
        r = pithos.object_get(obj)
494
        self.assertEqual(r.status_code, 200)
495
        self.info('Status code is OK')
496

  
497
        osize = int(r.headers['content-length'])
498
        etag = r.headers['etag']
499

  
500
        r = pithos.object_get(obj, hashmap=True)
501
        self.assertEqual(
502
            set(('hashes', 'block_size', 'block_hash', 'bytes')), set(r.json))
503
        self.info('Hashmap works')
504
        hash0 = r.json['hashes'][0]
505

  
506
        r = pithos.object_get(obj, format='xml', hashmap=True)
507
        self.assertTrue(r.text.split('hash>')[1].startswith(hash0))
508
        self.info('Hashmap with XML format works')
509

  
510
        rangestr = 'bytes=%s-%s' % (osize / 3, osize / 2)
511
        r = pithos.object_get(obj, data_range=rangestr, success=(200, 206))
512
        partsize = int(r.headers['content-length'])
513
        self.assertTrue(0 < partsize and partsize <= 1 + osize / 3)
514
        self.info('Range x-y works')
515
        orig = r.text
516

  
517
        rangestr = 'bytes=%s' % (osize / 3)
518
        r = pithos.object_get(
519
            obj, data_range=rangestr, if_range=True, success=(200, 206))
520
        partsize = int(r.headers['content-length'])
521
        self.assertTrue(partsize, 1 + (osize / 3))
522
        diff = set(r.text).symmetric_difference(set(orig[:partsize]))
523
        self.assertEqual(len(diff), 0)
524
        self.info('Range x works')
525

  
526
        rangestr = 'bytes=-%s' % (osize / 3)
527
        r = pithos.object_get(
528
            obj, data_range=rangestr, if_range=True, success=(200, 206))
529
        partsize = int(r.headers['content-length'])
530
        self.assertTrue(partsize, osize / 3)
531
        diff = set(r.text).symmetric_difference(set(orig[-partsize:]))
532
        self.assertEqual(len(diff), 0)
533
        self.info('Range -x works')
534

  
535
        r = pithos.object_get(obj, if_etag_match=etag)
536
        self.assertEqual(r.status_code, 200)
537
        self.info('if-etag-match works')
538

  
539
        r = pithos.object_get(obj, if_etag_not_match=etag + 'LALALA')
540
        self.assertEqual(r.status_code, 200)
541
        self.info('if-etag-not-match works')
542

  
543
        for format in pithos.DATE_FORMATS:
544
            now_formated = self.now_unformated.strftime(format)
545
            r1 = pithos.object_get(
546
                obj, if_modified_since=now_formated, success=(200, 304, 412))
547
            r2 = pithos.object_get(
548
                obj, if_unmodified_since=now_formated, success=(200, 304, 412))
549
            self.assertNotEqual(r1.status_code, r2.status_code)
550
        self.info('if(un)modified-since works')
551

  
552
        obj, dnl_f = 'dir/sample.file', NamedTemporaryFile()
553
        self.info('Download %s as %s ...' % (obj, dnl_f.name))
554
        pithos.download_object(obj, dnl_f)
555
        self.info('Download is completed')
556

  
557
        f_size = len(orig)
558
        for pos in (0, f_size / 2, f_size - 128):
559
            dnl_f.seek(pos)
560
            self.large_file.seek(pos)
561
            self.assertEqual(self.large_file.read(64), dnl_f.read(64))
562
        self.info('Sampling shows that files match')
563

  
564
        """Upload a boring file"""
565
        self.info('Create a boring file of 42 blocks...')
566
        bor_f = self._create_boring_file(42)
567
        trg_fname = 'dir/uploaded.file'
568
        self.info('Now, upload the boring file as %s...' % trg_fname)
569
        pithos.upload_object(trg_fname, bor_f)
570
        self.info('Boring file %s is uploaded as %s' % (bor_f.name, trg_fname))
571
        dnl_f = NamedTemporaryFile()
572
        self.info('Download boring file as %s' % dnl_f.name)
573
        pithos.download_object(trg_fname, dnl_f)
574
        self.info('File is downloaded')
575

  
576
        for i in range(42):
577
            self.assertEqual(sample_block(bor_f, i), sample_block(dnl_f, i))
578

  
579
    def test_150_stop_test(self):
402 580
        """STOP TESTING ALREADY"""
403 581
        self.assertTrue(False)
404 582

  
405
    def test_051_list_containers(self):
406
        """Test container list actually returns containers"""
407
        self.containers = self._get_list_of_containers()
408
        self.assertGreater(len(self.containers), 0)
409
        self.lala = 1
410

  
411
    def test_052_unique_containers(self):
583
    def test_152_unique_containers(self):
412 584
        """Test if containers have unique names"""
413 585
        names = [n['name'] for n in self.containers]
414 586
        names = sorted(names)
415 587
        self.assertEqual(sorted(list(set(names))), names)
416 588

  
417
    def test_054_upload_file(self):
418
        """Test uploading a txt file to Pithos"""
419
        # Create a tmp file
420
        with tempfile.TemporaryFile(dir=self.temp_directory) as fout:
421
            fout.write("This is a temp file")
422
            fout.seek(0, 0)
423
            # Upload the file,
424
            # The container is the one choosen during the `create_container'
425
            self.clients.pithos.upload_object("test.txt", fout)
426
            # Verify quotas
427
            self._check_quotas(diskspace=+os.fstat(fout.fileno()).st_size)
428

  
429
    def test_055_download_file(self):
430
        """Test downloading the file from Pithos"""
431
        # Create a tmp directory to save the file
432
        with tempfile.TemporaryFile(dir=self.temp_directory) as fout:
433
            self.clients.pithos.download_object("test.txt", fout)
434
            # Now read the file
435
            fout.seek(0, 0)
436
            contents = fout.read()
437
            # Compare results
438
            self.info("Comparing contents with the uploaded file")
439
            self.assertEqual(contents, "This is a temp file")
440

  
441
    def test_056_remove(self):
442
        """Test removing files and containers from Pithos"""
443
        self.info("Removing the file %s from container %s",
444
                  "test.txt", self.created_container)
445
        # The container is the one choosen during the `create_container'
446
        content_length = \
447
            self.clients.pithos.get_object_info("test.txt")['content-length']
448
        self.clients.pithos.del_object("test.txt")
449

  
450
        # Verify quotas
451
        self._check_quotas(diskspace=-int(content_length))
452

  
453
        self.info("Removing the container %s", self.created_container)
454
        self.clients.pithos.purge_container()
455

  
456
        # List containers
457
        containers = self._get_list_of_containers()
458
        self.info("Check that the container %s has been deleted",
459
                  self.created_container)
460
        names = [n['name'] for n in containers]
461
        self.assertNotIn(self.created_container, names)
462
        # We successfully deleted our container, no need to do it
463
        # in our clean up phase
464
        self.created_container = None
465

  
466 589
    @classmethod
467 590
    def tearDownClass(cls):  # noqa
468 591
        """Clean up"""

Also available in: Unified diff