Revision 53b1eea6

b/api/tests.py
2 2
# Copyright (c) 2010 Greek Research and Technology Network
3 3
#
4 4

  
5
from __future__ import with_statement
6

  
7
from collections import defaultdict
5 8
from email.utils import parsedate
6 9
from random import choice, randint, sample
7 10
from time import mktime
......
365 368
            state='ACTIVE',
366 369
            owner=choice(users))
367 370

  
371
def create_image_metadata(n=1):
372
    images = Image.objects.all()
373
    for i in range(n):
374
        ImageMetadata.objects.create(
375
            meta_key='Key%d' % (i + 1),
376
            meta_value='Value %d' % (i + 1),
377
            image = choice(images))
378

  
368 379
def create_servers(n=1):
369 380
    users = SynnefoUser.objects.all()
370 381
    flavors = Flavor.objects.all()
......
388 399
            vm = choice(servers))
389 400

  
390 401

  
402
class AssertInvariant(object):
403
    def __init__(self, callable, *args, **kwargs):
404
        self.callable = callable
405
        self.args = args
406
        self.kwargs = kwargs
407
    
408
    def __enter__(self):
409
        self.value = self.callable(*self.args, **self.kwargs)
410
        return self.value
411
    
412
    def __exit__(self, type, value, tb):
413
        assert self.value == self.callable(*self.args, **self.kwargs)
414

  
415

  
391 416
class BaseTestCase(TestCase):
392 417
    USERS = 1
393 418
    FLAVORS = 1
394 419
    IMAGES = 1
395 420
    SERVERS = 1
396 421
    SERVER_METADATA = 0
422
    IMAGE_METADATA = 0
397 423
    
398 424
    def setUp(self):
399 425
        self.client = Client()
400 426
        create_users(self.USERS)
401 427
        create_flavors(self.FLAVORS)
402 428
        create_images(self.IMAGES)
429
        create_image_metadata(self.IMAGE_METADATA)
403 430
        create_servers(self.SERVERS)
404 431
        create_server_metadata(self.SERVER_METADATA)
405 432
    
......
414 441
    def assertItemNotFound(self, response):
415 442
        self.assertFault(response, 404, 'itemNotFound')
416 443
    
417
    def get_server_metadata(self, server_id):
418
        vm_meta = VirtualMachineMetadata.objects.filter(vm=int(server_id))
419
        return dict((m.meta_key, m.meta_value) for m in vm_meta)
420 444
    
421
    def verify_server_metadata(self, server_id, metadata):
422
        server_metadata = self.get_server_metadata(server_id)
423
        self.assertEqual(server_metadata, metadata)
424

  
425

  
426
class ListServerMetadata(BaseTestCase):
427
    SERVERS = 4
428
    
429
    def list_metadata(self, server_id):
430
        response = self.client.get('/api/v1.1/servers/%d/meta' % server_id)
445
    def list_metadata(self, path):
446
        response = self.client.get(path)
431 447
        self.assertTrue(response.status_code in (200, 203))
432 448
        reply = json.loads(response.content)
433 449
        self.assertEqual(reply.keys(), ['metadata'])
434 450
        self.assertEqual(reply['metadata'].keys(), ['values'])
435 451
        return reply['metadata']['values']
436 452
    
437
    def verify_all_metadata(self):
438
        for vm in VirtualMachine.objects.all():
439
            server_metadata = self.get_server_metadata(vm.id)
440
            response_metadata = self.list_metadata(vm.id)
441
            self.assertEqual(response_metadata, server_metadata)
453
    def list_server_metadata(self, server_id):
454
        path = '/api/v1.1/servers/%d/meta' % server_id
455
        return self.list_metadata(path)
442 456
    
443
    def test_list_metadata(self):
444
        self.verify_all_metadata()
445
        create_server_metadata(100)
446
        self.verify_all_metadata()
447
    
448
    def test_invalid_server(self):
449
        response = self.client.get('/api/v1.1/servers/100/meta')
450
        self.assertItemNotFound(response)
451

  
452

  
453
class UpdateServerMetadata(BaseTestCase):
454
    SERVER_METADATA = 10
457
    def list_image_metadata(self, image_id):
458
        path = '/api/v1.1/images/%d/meta' % image_id
459
        return self.list_metadata(path)
455 460
    
456
    def update_meta(self, metadata):
457
        path = '/api/v1.1/servers/1/meta'
461
    def update_metadata(self, path, metadata):
458 462
        data = json.dumps({'metadata': metadata})
459 463
        response = self.client.post(path, data, content_type='application/json')
460 464
        self.assertEqual(response.status_code, 201)
......
462 466
        self.assertEqual(reply.keys(), ['metadata'])
463 467
        return reply['metadata']
464 468
    
469
    def update_server_metadata(self, server_id, metadata):
470
        path = '/api/v1.1/servers/%d/meta' % server_id
471
        return self.update_metadata(path, metadata)
472
    
473
    def update_image_metadata(self, image_id, metadata):
474
        path = '/api/v1.1/images/%d/meta' % image_id
475
        return self.update_metadata(path, metadata)
476
    
477
    def create_server_meta(self, server_id, meta):
478
        key = meta.keys()[0]
479
        path = '/api/v1.1/servers/%d/meta/%s' % (server_id, key)
480
        data = json.dumps({'meta': meta})
481
        response = self.client.put(path, data, content_type='application/json')
482
        self.assertEqual(response.status_code, 201)
483
        reply = json.loads(response.content)
484
        self.assertEqual(reply.keys(), ['meta'])
485
        response_meta = reply['meta']
486
        self.assertEqual(response_meta, meta)
487
    
488
    def get_all_server_metadata(self):
489
        metadata = defaultdict(dict)
490
        for m in VirtualMachineMetadata.objects.all():
491
            metadata[m.vm.id][m.meta_key] = m.meta_value
492
        return metadata
493
    
494
    def get_all_image_metadata(self):
495
        metadata = defaultdict(dict)
496
        for m in ImageMetadata.objects.all():
497
            metadata[m.image.id][m.meta_key] = m.meta_value
498
        return metadata
499

  
500

  
501
class ListServerMetadata(BaseTestCase):
502
    SERVERS = 5
503
    SERVER_METADATA = 100
504
    
505
    def test_list_metadata(self):
506
        with AssertInvariant(self.get_all_server_metadata) as metadata:
507
            for vm in VirtualMachine.objects.all():
508
                response_metadata = self.list_server_metadata(vm.id)
509
                self.assertEqual(response_metadata, metadata[vm.id])
510
    
511
    def test_invalid_server(self):
512
        with AssertInvariant(self.get_all_server_metadata):
513
            response = self.client.get('/api/v1.1/servers/0/meta')
514
            self.assertItemNotFound(response)
515

  
516

  
517
class UpdateServerMetadata(BaseTestCase):
518
    SERVER_METADATA = 10
519
    
465 520
    def test_update_metadata(self):
466
        metadata = self.get_server_metadata(1)
521
        metadata = self.get_all_server_metadata()
522
        server_id = choice(metadata.keys())
467 523
        new_metadata = {}
468
        for key in sample(metadata.keys(), 3):
524
        for key in sample(metadata[server_id].keys(), 3):
469 525
            new_metadata[key] = 'New %s value' % key
470
        response_metadata = self.update_meta(new_metadata)
526
        response_metadata = self.update_server_metadata(server_id, new_metadata)
471 527
        self.assertEqual(response_metadata, new_metadata)
472
        metadata.update(new_metadata)
473
        self.verify_server_metadata(1, metadata)
528
        metadata[server_id].update(new_metadata)
529
        self.assertEqual(metadata, self.get_all_server_metadata())
474 530
    
475 531
    def test_does_not_create(self):
476
        metadata = self.get_server_metadata(1)
477
        new_metadata = {'Foo': 'Bar'}
478
        response_metadata = self.update_meta(new_metadata)
479
        self.assertEqual(response_metadata, {})
480
        self.verify_server_metadata(1, metadata)
532
        with AssertInvariant(self.get_all_server_metadata) as metadata:
533
            server_id = choice(metadata.keys())
534
            new_metadata = {'Foo': 'Bar'}
535
            response_metadata = self.update_server_metadata(server_id, new_metadata)
536
            self.assertEqual(response_metadata, {})
481 537
    
482 538
    def test_invalid_data(self):
483
        metadata = self.get_server_metadata(1)
484
        path = '/api/v1.1/servers/1/meta'
485
        response = self.client.post(path, 'metadata', content_type='application/json')
486
        self.assertBadRequest(response)
487
        self.verify_server_metadata(1, metadata)
539
        with AssertInvariant(self.get_all_server_metadata) as metadata:
540
            server_id = choice(metadata.keys())
541
            path = '/api/v1.1/servers/%d/meta' % server_id
542
            response = self.client.post(path, 'metadata', content_type='application/json')
543
            self.assertBadRequest(response)
488 544
    
489 545
    def test_invalid_server(self):
490
        metadata = self.get_server_metadata(1)
491
        path = '/api/v1.1/servers/2/meta'
492
        data = json.dumps({'metadata': {'Key1': 'A Value'}})
493
        response = self.client.post(path, data, content_type='application/json')
494
        self.assertItemNotFound(response)
495
        self.verify_server_metadata(1, metadata)
546
        with AssertInvariant(self.get_all_server_metadata):
547
            path = '/api/v1.1/servers/0/meta'
548
            data = json.dumps({'metadata': {'Key1': 'A Value'}})
549
            response = self.client.post(path, data, content_type='application/json')
550
            self.assertItemNotFound(response)
496 551

  
497 552

  
498 553
class GetServerMetadataItem(BaseTestCase):
499
    SERVER_METADATA = 10
554
    SERVERS = 5
555
    SERVER_METADATA = 100
500 556
    
501 557
    def test_get_metadata_item(self):
502
        metadata = self.get_server_metadata(1)
503
        key = choice(metadata.keys())
504
        path = '/api/v1.1/servers/1/meta/' + key
505
        response = self.client.get(path)
506
        self.assertTrue(response.status_code in (200, 203))
507
        reply = json.loads(response.content)
508
        self.assertEqual(reply['meta'], {key: metadata[key]})
509
        self.verify_server_metadata(1, metadata)
558
        with AssertInvariant(self.get_all_server_metadata) as metadata:
559
            server_id = choice(metadata.keys())
560
            key = choice(metadata[server_id].keys())
561
            path = '/api/v1.1/servers/%d/meta/%s' % (server_id, key)
562
            response = self.client.get(path)
563
            self.assertTrue(response.status_code in (200, 203))
564
            reply = json.loads(response.content)
565
            self.assertEqual(reply['meta'], {key: metadata[server_id][key]})
510 566
    
511 567
    def test_invalid_key(self):
512
        metadata = self.get_server_metadata(1)
513
        response = self.client.get('/api/v1.1/servers/1/meta/foo')
514
        self.assertItemNotFound(response)
515
        self.verify_server_metadata(1, metadata)
568
        with AssertInvariant(self.get_all_server_metadata) as metadata:
569
            server_id = choice(metadata.keys())
570
            response = self.client.get('/api/v1.1/servers/%d/meta/foo' % server_id)
571
            self.assertItemNotFound(response)
516 572
    
517 573
    def test_invalid_server(self):
518
        metadata = self.get_server_metadata(1)
519
        response = self.client.get('/api/v1.1/servers/2/meta/foo')
520
        self.assertItemNotFound(response)
521
        self.verify_server_metadata(1, metadata)
574
        with AssertInvariant(self.get_all_server_metadata):
575
            response = self.client.get('/api/v1.1/servers/0/meta/foo')
576
            self.assertItemNotFound(response)
522 577

  
523 578

  
524 579
class CreateServerMetadataItem(BaseTestCase):
525 580
    SERVER_METADATA = 10
526 581
    
527
    def create_meta(self, meta):
528
        key = meta.keys()[0]
529
        path = '/api/v1.1/servers/1/meta/' + key
530
        data = json.dumps({'meta': meta})
531
        response = self.client.put(path, data, content_type='application/json')
532
        self.assertEqual(response.status_code, 201)
533
        reply = json.loads(response.content)
534
        self.assertEqual(reply.keys(), ['meta'])
535
        response_meta = reply['meta']
536
        self.assertEqual(response_meta, meta)
537
    
538 582
    def test_create_metadata(self):
539
        metadata = self.get_server_metadata(1)
583
        metadata = self.get_all_server_metadata()
584
        server_id = choice(metadata.keys())
540 585
        meta = {'Foo': 'Bar'}
541
        self.create_meta(meta)
542
        metadata.update(meta)
543
        self.verify_server_metadata(1, metadata)
586
        self.create_server_meta(server_id, meta)
587
        metadata[server_id].update(meta)
588
        self.assertEqual(metadata, self.get_all_server_metadata())
544 589
    
545 590
    def test_update_metadata(self):
546
        metadata = self.get_server_metadata(1)
547
        key = choice(metadata.keys())
591
        metadata = self.get_all_server_metadata()
592
        server_id = choice(metadata.keys())
593
        key = choice(metadata[server_id].keys())
548 594
        meta = {key: 'New Value'}
549
        self.create_meta(meta)
550
        metadata.update(meta)
551
        self.verify_server_metadata(1, metadata)
595
        self.create_server_meta(server_id, meta)
596
        metadata[server_id].update(meta)
597
        self.assertEqual(metadata, self.get_all_server_metadata())
552 598
    
553 599
    def test_invalid_server(self):
554
        metadata = self.get_server_metadata(1)
555
        path = '/api/v1.1/servers/2/meta/foo'
556
        data = json.dumps({'meta': {'foo': 'bar'}})
557
        response = self.client.put(path, data, content_type='application/json')
558
        self.assertItemNotFound(response)
559
        self.verify_server_metadata(1, metadata)
600
        with AssertInvariant(self.get_all_server_metadata):
601
            path = '/api/v1.1/servers/0/meta/foo'
602
            data = json.dumps({'meta': {'foo': 'bar'}})
603
            response = self.client.put(path, data, content_type='application/json')
604
            self.assertItemNotFound(response)
560 605
    
561 606
    def test_invalid_key(self):
562
        metadata = self.get_server_metadata(1)
563
        path = '/api/v1.1/servers/1/meta/baz'
564
        data = json.dumps({'meta': {'foo': 'bar'}})
565
        response = self.client.put(path, data, content_type='application/json')
566
        self.assertBadRequest(response)
567
        self.verify_server_metadata(1, metadata)
607
        with AssertInvariant(self.get_all_server_metadata):
608
            path = '/api/v1.1/servers/1/meta/baz'
609
            data = json.dumps({'meta': {'foo': 'bar'}})
610
            response = self.client.put(path, data, content_type='application/json')
611
            self.assertBadRequest(response)
568 612
    
569 613
    def test_invalid_data(self):
570
        metadata = self.get_server_metadata(1)
571
        path = '/api/v1.1/servers/1/meta/foo'
572
        response = self.client.put(path, 'meta', content_type='application/json')
573
        self.assertBadRequest(response)
574
        self.verify_server_metadata(1, metadata)
614
        with AssertInvariant(self.get_all_server_metadata):
615
            path = '/api/v1.1/servers/1/meta/foo'
616
            response = self.client.put(path, 'meta', content_type='application/json')
617
            self.assertBadRequest(response)
575 618

  
576 619

  
577 620
class DeleteServerMetadataItem(BaseTestCase):
578 621
    SERVER_METADATA = 10
579 622
    
580 623
    def test_delete_metadata(self):
581
        metadata = self.get_server_metadata(1)
582
        key = choice(metadata.keys())
583
        path = '/api/v1.1/servers/1/meta/' + key
624
        metadata = self.get_all_server_metadata()
625
        server_id = choice(metadata.keys())
626
        key = choice(metadata[server_id].keys())
627
        path = '/api/v1.1/servers/%d/meta/%s' % (server_id, key)
584 628
        response = self.client.delete(path)
585 629
        self.assertEqual(response.status_code, 204)
586
        metadata.pop(key)
587
        self.verify_server_metadata(1, metadata)
630
        metadata[server_id].pop(key)
631
        self.assertEqual(metadata, self.get_all_server_metadata())
588 632
    
589 633
    def test_invalid_server(self):
590
        metadata = self.get_server_metadata(1)
591
        response = self.client.delete('/api/v1.1/servers/2/meta/Key1')
592
        self.assertItemNotFound(response)
593
        self.verify_server_metadata(1, metadata)
634
        with AssertInvariant(self.get_all_server_metadata):
635
            response = self.client.delete('/api/v1.1/servers/9/meta/Key1')
636
            self.assertItemNotFound(response)
594 637
    
595 638
    def test_invalid_key(self):
596
        metadata = self.get_server_metadata(1)
597
        response = self.client.delete('/api/v1.1/servers/1/meta/foo')
598
        self.assertItemNotFound(response)
599
        self.verify_server_metadata(1, metadata)
639
        with AssertInvariant(self.get_all_server_metadata) as metadata:
640
            server_id = choice(metadata.keys())
641
            path = '/api/v1.1/servers/%d/meta/foo' % server_id
642
            response = self.client.delete(path)
643
            self.assertItemNotFound(response)
644

  
645

  
646
class ListImageMetadata(BaseTestCase):
647
    IMAGES = 5
648
    IMAGE_METADATA = 100
649

  
650
    def test_list_metadata(self):
651
        with AssertInvariant(self.get_all_image_metadata) as metadata:
652
            for image in Image.objects.all():
653
                response_metadata = self.list_image_metadata(image.id)
654
                self.assertEqual(response_metadata, metadata[image.id])
655

  
656
    def test_invalid_image(self):
657
        with AssertInvariant(self.get_all_image_metadata):
658
            response = self.client.get('/api/v1.1/images/0/meta')
659
            self.assertItemNotFound(response)
660

  
661
class UpdateImageMetadata(BaseTestCase):
662
    IMAGE_METADATA = 10
663

  
664
    def test_update_metadata(self):
665
        metadata = self.get_all_image_metadata()
666
        image_id = choice(metadata.keys())
667
        new_metadata = {}
668
        for key in sample(metadata[image_id].keys(), 3):
669
            new_metadata[key] = 'New %s value' % key
670
        response_metadata = self.update_image_metadata(image_id, new_metadata)
671
        self.assertEqual(response_metadata, new_metadata)
672
        metadata[image_id].update(new_metadata)
673
        self.assertEqual(metadata, self.get_all_image_metadata())
674

  
675
    def test_does_not_create(self):
676
        with AssertInvariant(self.get_all_image_metadata) as metadata:
677
            image_id = choice(metadata.keys())
678
            new_metadata = {'Foo': 'Bar'}
679
            response_metadata = self.update_image_metadata(image_id, new_metadata)
680
            self.assertEqual(response_metadata, {})
681

  
682
    def test_invalid_data(self):
683
        with AssertInvariant(self.get_all_image_metadata) as metadata:
684
            image_id = choice(metadata.keys())
685
            path = '/api/v1.1/images/%d/meta' % image_id
686
            response = self.client.post(path, 'metadata', content_type='application/json')
687
            self.assertBadRequest(response)
688

  
689
    def test_invalid_server(self):
690
        with AssertInvariant(self.get_all_image_metadata):
691
            path = '/api/v1.1/images/0/meta'
692
            data = json.dumps({'metadata': {'Key1': 'A Value'}})
693
            response = self.client.post(path, data, content_type='application/json')
694
            self.assertItemNotFound(response)

Also available in: Unified diff