diff --git a/nova/test.py b/nova/test.py index feb489b30..9efbf40b0 100644 --- a/nova/test.py +++ b/nova/test.py @@ -141,86 +141,3 @@ class TestCase(testtools.TestCase): svc.start() self._services.append(svc) return svc - - # Useful assertions - def assertDictMatch(self, d1, d2, approx_equal=False, tolerance=0.001): - """Assert two dicts are equivalent. - - This is a 'deep' match in the sense that it handles nested - dictionaries appropriately. - - NOTE: - - If you don't care (or don't know) a given value, you can specify - the string DONTCARE as the value. This will cause that dict-item - to be skipped. - - """ - def raise_assertion(msg): - d1str = str(d1) - d2str = str(d2) - base_msg = ('Dictionaries do not match. %(msg)s d1: %(d1str)s ' - 'd2: %(d2str)s' % locals()) - raise AssertionError(base_msg) - - d1keys = set(d1.keys()) - d2keys = set(d2.keys()) - if d1keys != d2keys: - d1only = d1keys - d2keys - d2only = d2keys - d1keys - raise_assertion('Keys in d1 and not d2: %(d1only)s. ' - 'Keys in d2 and not d1: %(d2only)s' % locals()) - - for key in d1keys: - d1value = d1[key] - d2value = d2[key] - try: - error = abs(float(d1value) - float(d2value)) - within_tolerance = error <= tolerance - except (ValueError, TypeError): - # If both values aren't convertible to float, just ignore - # ValueError if arg is a str, TypeError if it's something else - # (like None) - within_tolerance = False - - if hasattr(d1value, 'keys') and hasattr(d2value, 'keys'): - self.assertDictMatch(d1value, d2value) - elif 'DONTCARE' in (d1value, d2value): - continue - elif approx_equal and within_tolerance: - continue - elif d1value != d2value: - raise_assertion("d1['%(key)s']=%(d1value)s != " - "d2['%(key)s']=%(d2value)s" % locals()) - - def assertDictListMatch(self, L1, L2, approx_equal=False, tolerance=0.001): - """Assert a list of dicts are equivalent.""" - def raise_assertion(msg): - L1str = str(L1) - L2str = str(L2) - base_msg = ('List of dictionaries do not match: %(msg)s ' - 'L1: %(L1str)s L2: %(L2str)s' % locals()) - raise AssertionError(base_msg) - - L1count = len(L1) - L2count = len(L2) - if L1count != L2count: - raise_assertion('Length mismatch: len(L1)=%(L1count)d != ' - 'len(L2)=%(L2count)d' % locals()) - - for d1, d2 in zip(L1, L2): - self.assertDictMatch(d1, d2, approx_equal=approx_equal, - tolerance=tolerance) - - def assertSubDictMatch(self, sub_dict, super_dict): - """Assert a sub_dict is subset of super_dict.""" - self.assertEqual(True, - set(sub_dict.keys()).issubset(set(super_dict.keys()))) - for k, sub_value in sub_dict.items(): - super_value = super_dict[k] - if isinstance(sub_value, dict): - self.assertSubDictMatch(sub_value, super_value) - elif 'DONTCARE' in (sub_value, super_value): - continue - else: - self.assertEqual(sub_value, super_value) diff --git a/nova/tests/scheduler/test_host_manager.py b/nova/tests/scheduler/test_host_manager.py index d7d732d34..0984cbf80 100644 --- a/nova/tests/scheduler/test_host_manager.py +++ b/nova/tests/scheduler/test_host_manager.py @@ -24,6 +24,7 @@ from nova import exception from nova.openstack.common import timeutils from nova.scheduler import host_manager from nova import test +from nova.tests import matchers from nova.tests.scheduler import fakes @@ -92,7 +93,7 @@ class HostManagerTestCase(test.TestCase): def test_update_service_capabilities(self): service_states = self.host_manager.service_states - self.assertDictMatch(service_states, {}) + self.assertEqual(len(service_states.keys()), 0) self.mox.StubOutWithMock(timeutils, 'utcnow') timeutils.utcnow().AndReturn(31337) timeutils.utcnow().AndReturn(31339) @@ -116,11 +117,11 @@ class HostManagerTestCase(test.TestCase): expected = {('host1', 'node1'): host1_compute_capabs, ('host2', 'node2'): host2_compute_capabs} - self.assertDictMatch(service_states, expected) + self.assertThat(service_states, matchers.DictMatches(expected)) def test_update_service_capabilities_node_key(self): service_states = self.host_manager.service_states - self.assertDictMatch(service_states, {}) + self.assertThat(service_states, matchers.DictMatches({})) host1_cap = {'hypervisor_hostname': 'host1-hvhn'} host2_cap = {} @@ -135,7 +136,7 @@ class HostManagerTestCase(test.TestCase): host2_cap['timestamp'] = 31338 expected = {('host1', 'host1-hvhn'): host1_cap, ('host2', None): host2_cap} - self.assertDictMatch(service_states, expected) + self.assertThat(service_states, matchers.DictMatches(expected)) def test_get_all_host_states(self): diff --git a/nova/tests/scheduler/test_least_cost.py b/nova/tests/scheduler/test_least_cost.py index 3689a30bd..1d180d718 100644 --- a/nova/tests/scheduler/test_least_cost.py +++ b/nova/tests/scheduler/test_least_cost.py @@ -19,6 +19,7 @@ from nova import context from nova.scheduler import host_manager from nova.scheduler import least_cost from nova import test +from nova.tests import matchers from nova.tests.scheduler import fakes @@ -92,11 +93,11 @@ class TestWeightedHost(test.TestCase): def test_dict_conversion_without_host_state(self): host = least_cost.WeightedHost('someweight') expected = {'weight': 'someweight'} - self.assertDictMatch(host.to_dict(), expected) + self.assertThat(host.to_dict(), matchers.DictMatches(expected)) def test_dict_conversion_with_host_state(self): host_state = host_manager.HostState('somehost', None) host = least_cost.WeightedHost('someweight', host_state) expected = {'weight': 'someweight', 'host': 'somehost'} - self.assertDictMatch(host.to_dict(), expected) + self.assertThat(host.to_dict(), matchers.DictMatches(expected)) diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index 6a0e93b7d..4de1c074a 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -36,6 +36,7 @@ from nova.openstack.common import timeutils from nova.scheduler import driver from nova.scheduler import manager from nova import test +from nova.tests import matchers from nova.tests.scheduler import fakes from nova import utils @@ -138,7 +139,7 @@ class SchedulerManagerTestCase(test.TestCase): 'local_gb_used': 512, 'memory_mb': 1024, 'memory_mb_used': 512}} - self.assertDictMatch(result, expected) + self.assertThat(result, matchers.DictMatches(expected)) def _mox_schedule_method_helper(self, method_name): # Make sure the method exists that we're going to test call @@ -721,7 +722,7 @@ class SchedulerDriverModuleTestCase(test.TestCase): result = driver.encode_instance(instance, True) expected = {'id': instance['id'], '_is_precooked': False} - self.assertDictMatch(result, expected) + self.assertThat(result, matchers.DictMatches(expected)) # Orig dict not changed self.assertNotEqual(result, instance) @@ -729,6 +730,6 @@ class SchedulerDriverModuleTestCase(test.TestCase): expected = {} expected.update(instance) expected['_is_precooked'] = True - self.assertDictMatch(result, expected) + self.assertThat(result, matchers.DictMatches(expected)) # Orig dict not changed self.assertNotEqual(result, instance) diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py index 6e0a97c0c..b2cd23a0c 100644 --- a/nova/tests/test_api.py +++ b/nova/tests/test_api.py @@ -41,6 +41,7 @@ from nova import exception from nova import flags from nova.openstack.common import timeutils from nova import test +from nova.tests import matchers FLAGS = flags.FLAGS @@ -163,7 +164,7 @@ class Ec2utilsTestCase(test.TestCase): 'virtual_name': 'ephemeral0'}}} out_dict = ec2utils.dict_from_dotted_str(in_str) - self.assertDictMatch(out_dict, expected_dict) + self.assertThat(out_dict, matchers.DictMatches(expected_dict)) def test_properties_root_defice_name(self): mappings = [{"device": "/dev/sda1", "virtual": "root"}] @@ -209,8 +210,8 @@ class Ec2utilsTestCase(test.TestCase): 'device': '/dev/sdc1'}, {'virtual': 'ephemeral1', 'device': '/dev/sdc1'}] - self.assertDictListMatch(block_device.mappings_prepend_dev(mappings), - expected_result) + self.assertThat(block_device.mappings_prepend_dev(mappings), + matchers.DictListMatches(expected_result)) class ApiEc2TestCase(test.TestCase): diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py index fb277bcb8..62943b59f 100644 --- a/nova/tests/test_db_api.py +++ b/nova/tests/test_db_api.py @@ -28,6 +28,7 @@ from nova import exception from nova import flags from nova.openstack.common import timeutils from nova import test +from nova.tests import matchers from nova import utils @@ -619,14 +620,16 @@ class AggregateDBApiTestCase(test.TestCase): ctxt = context.get_admin_context() result = _create_aggregate(context=ctxt) expected_metadata = db.aggregate_metadata_get(ctxt, result['id']) - self.assertDictMatch(expected_metadata, _get_fake_aggr_metadata()) + self.assertThat(expected_metadata, + matchers.DictMatches(_get_fake_aggr_metadata())) def test_aggregate_create_delete_create_with_metadata(self): """Ensure aggregate metadata is deleted bug 1052479.""" ctxt = context.get_admin_context() result = _create_aggregate(context=ctxt) expected_metadata = db.aggregate_metadata_get(ctxt, result['id']) - self.assertDictMatch(expected_metadata, _get_fake_aggr_metadata()) + self.assertThat(expected_metadata, + matchers.DictMatches(_get_fake_aggr_metadata())) db.aggregate_delete(ctxt, result['id']) result = _create_aggregate(metadata=None) expected_metadata = db.aggregate_metadata_get(ctxt, result['id']) @@ -748,7 +751,8 @@ class AggregateDBApiTestCase(test.TestCase): values['metadata'] = _get_fake_aggr_metadata() db.aggregate_update(ctxt, 1, values) expected = db.aggregate_metadata_get(ctxt, result.id) - self.assertDictMatch(_get_fake_aggr_metadata(), expected) + self.assertThat(_get_fake_aggr_metadata(), + matchers.DictMatches(expected)) def test_aggregate_update_with_existing_metadata(self): """Ensure an aggregate can be updated with existing metadata.""" @@ -759,7 +763,7 @@ class AggregateDBApiTestCase(test.TestCase): values['metadata']['fake_key1'] = 'foo' db.aggregate_update(ctxt, 1, values) expected = db.aggregate_metadata_get(ctxt, result.id) - self.assertDictMatch(values['metadata'], expected) + self.assertThat(values['metadata'], matchers.DictMatches(expected)) def test_aggregate_update_raise_not_found(self): """Ensure AggregateNotFound is raised when updating an aggregate.""" @@ -805,7 +809,7 @@ class AggregateDBApiTestCase(test.TestCase): metadata = _get_fake_aggr_metadata() db.aggregate_metadata_add(ctxt, result.id, metadata) expected = db.aggregate_metadata_get(ctxt, result.id) - self.assertDictMatch(metadata, expected) + self.assertThat(metadata, matchers.DictMatches(expected)) def test_aggregate_metadata_update(self): """Ensure we can update metadata for the aggregate.""" @@ -818,7 +822,7 @@ class AggregateDBApiTestCase(test.TestCase): db.aggregate_metadata_add(ctxt, result.id, new_metadata) expected = db.aggregate_metadata_get(ctxt, result.id) metadata[key] = 'foo' - self.assertDictMatch(metadata, expected) + self.assertThat(metadata, matchers.DictMatches(expected)) def test_aggregate_metadata_delete(self): """Ensure we can delete metadata for the aggregate.""" @@ -829,7 +833,7 @@ class AggregateDBApiTestCase(test.TestCase): db.aggregate_metadata_delete(ctxt, result.id, metadata.keys()[0]) expected = db.aggregate_metadata_get(ctxt, result.id) del metadata[metadata.keys()[0]] - self.assertDictMatch(metadata, expected) + self.assertThat(metadata, matchers.DictMatches(expected)) def test_aggregate_metadata_delete_raise_not_found(self): """Ensure AggregateMetadataNotFound is raised when deleting.""" diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index 6e49121f1..4c2886a49 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -45,6 +45,7 @@ from nova import test from nova.tests import fake_libvirt_utils from nova.tests import fake_network import nova.tests.image.fake +from nova.tests import matchers from nova import utils from nova.virt.disk import api as disk from nova.virt import driver @@ -630,7 +631,7 @@ class LibvirtConnTestCase(test.TestCase): 'id': 'fake' } result = conn.get_volume_connector(volume) - self.assertDictMatch(expected, result) + self.assertThat(expected, matchers.DictMatches(result)) def test_get_guest_config(self): conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) @@ -1923,11 +1924,11 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() return_value = conn.check_can_live_migrate_destination(self.context, instance_ref, compute_info, compute_info, True) - self.assertDictMatch(return_value, - {"filename": "file", - 'disk_available_mb': 409600, - "disk_over_commit": False, - "block_migration": True}) + self.assertThat({"filename": "file", + 'disk_available_mb': 409600, + "disk_over_commit": False, + "block_migration": True}, + matchers.DictMatches(return_value)) def test_check_can_live_migrate_dest_all_pass_no_block_migration(self): instance_ref = db.instance_create(self.context, self.test_instance) @@ -1949,11 +1950,11 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() return_value = conn.check_can_live_migrate_destination(self.context, instance_ref, compute_info, compute_info, False) - self.assertDictMatch(return_value, - {"filename": "file", - "block_migration": False, - "disk_over_commit": False, - "disk_available_mb": None}) + self.assertThat({"filename": "file", + "block_migration": False, + "disk_over_commit": False, + "disk_available_mb": None}, + matchers.DictMatches(return_value)) def test_check_can_live_migrate_dest_incompatible_cpu_raises(self): instance_ref = db.instance_create(self.context, self.test_instance) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index a145d1675..c1c8c1cbd 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -41,6 +41,7 @@ from nova.tests.db import fakes as db_fakes from nova.tests import fake_network from nova.tests import fake_utils import nova.tests.image.fake as fake_image +from nova.tests import matchers from nova.tests.xenapi import stubs from nova.virt import fake from nova.virt.xenapi import agent @@ -359,7 +360,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): } instance = self._create_instance() expected = self.conn.get_diagnostics(instance) - self.assertDictMatch(fake_diagnostics, expected) + self.assertThat(fake_diagnostics, matchers.DictMatches(expected)) def test_instance_snapshot_fails_with_no_primary_vdi(self): def create_bad_vbd(session, vm_ref, vdi_ref, userdevice, @@ -2090,7 +2091,8 @@ class XenAPIAggregateTestCase(stubs.XenAPITestBase): self.conn._pool.add_to_aggregate(self.context, aggregate, "host") result = db.aggregate_get(self.context, aggregate.id) self.assertTrue(fake_init_pool.called) - self.assertDictMatch(self.fake_metadata, result.metadetails) + self.assertThat(self.fake_metadata, + matchers.DictMatches(result.metadetails)) def test_join_slave(self): """Ensure join_slave gets called when the request gets to master.""" @@ -2168,8 +2170,9 @@ class XenAPIAggregateTestCase(stubs.XenAPITestBase): self.conn._pool.remove_from_aggregate(self.context, aggregate, "host") result = db.aggregate_get(self.context, aggregate.id) self.assertTrue(fake_clear_pool.called) - self.assertDictMatch({pool_states.POOL_FLAG: 'XenAPI', - pool_states.KEY: pool_states.ACTIVE}, result.metadetails) + self.assertThat({pool_states.POOL_FLAG: 'XenAPI', + pool_states.KEY: pool_states.ACTIVE}, + matchers.DictMatches(result.metadetails)) def test_remote_master_non_empty_pool(self): """Ensure AggregateError is raised if removing the master."""