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