summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2015-09-18 23:47:11 +0000
committerGerrit Code Review <review@openstack.org>2015-09-18 23:47:11 +0000
commitd34f5d857a0f33cafcb530ea83cb494e4eb7f1bd (patch)
tree11b99e14fab6302e50d4df0a3cf7084e932a0572
parent9a8111f5d2d50b5b3d692100f69dc5242f883168 (diff)
parent1285baee1c91eda75984099b6f1fd8244aaa0258 (diff)
downloadironic-python-agent-d34f5d857a0f33cafcb530ea83cb494e4eb7f1bd.tar.gz
Merge "Create a SerializableComparable class"
-rw-r--r--ironic_python_agent/encoding.py18
-rw-r--r--ironic_python_agent/extensions/base.py2
-rw-r--r--ironic_python_agent/hardware.py8
-rw-r--r--ironic_python_agent/tests/unit/test_encoding.py62
4 files changed, 85 insertions, 5 deletions
diff --git a/ironic_python_agent/encoding.py b/ironic_python_agent/encoding.py
index 9022afd5..715d1341 100644
--- a/ironic_python_agent/encoding.py
+++ b/ironic_python_agent/encoding.py
@@ -25,6 +25,24 @@ class Serializable(object):
return dict((f, getattr(self, f)) for f in self.serializable_fields)
+class SerializableComparable(Serializable):
+ """A Serializable class which supports some comparison operators
+
+ This class supports the '__eq__' and '__ne__' comparison operators, but
+ intentionally disables the '__hash__' operator as some child classes may be
+ mutable. The addition of these comparison operators is mainly used to
+ assist with unit testing.
+ """
+
+ __hash__ = None
+
+ def __eq__(self, other):
+ return self.serialize() == other.serialize()
+
+ def __ne__(self, other):
+ return self.serialize() != other.serialize()
+
+
class RESTJSONEncoder(json.JSONEncoder):
"""A slightly customized JSON encoder."""
def encode(self, o):
diff --git a/ironic_python_agent/extensions/base.py b/ironic_python_agent/extensions/base.py
index baac978a..6f7de8e7 100644
--- a/ironic_python_agent/extensions/base.py
+++ b/ironic_python_agent/extensions/base.py
@@ -35,7 +35,7 @@ class AgentCommandStatus(object):
CLEAN_VERSION_MISMATCH = u'CLEAN_VERSION_MISMATCH'
-class BaseCommandResult(encoding.Serializable):
+class BaseCommandResult(encoding.SerializableComparable):
"""Base class for command result."""
serializable_fields = ('id', 'command_name', 'command_params',
diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py
index ace35303..69d7e0ab 100644
--- a/ironic_python_agent/hardware.py
+++ b/ironic_python_agent/hardware.py
@@ -99,7 +99,7 @@ class HardwareType(object):
MAC_ADDRESS = 'mac_address'
-class BlockDevice(encoding.Serializable):
+class BlockDevice(encoding.SerializableComparable):
serializable_fields = ('name', 'model', 'size', 'rotational')
def __init__(self, name, model, size, rotational):
@@ -109,7 +109,7 @@ class BlockDevice(encoding.Serializable):
self.rotational = rotational
-class NetworkInterface(encoding.Serializable):
+class NetworkInterface(encoding.SerializableComparable):
serializable_fields = ('name', 'mac_address', 'switch_port_descr',
'switch_chassis_descr', 'ipv4_address')
@@ -122,7 +122,7 @@ class NetworkInterface(encoding.Serializable):
self.switch_chassis_descr = None
-class CPU(encoding.Serializable):
+class CPU(encoding.SerializableComparable):
serializable_fields = ('model_name', 'frequency', 'count', 'architecture')
def __init__(self, model_name, frequency, count, architecture):
@@ -132,7 +132,7 @@ class CPU(encoding.Serializable):
self.architecture = architecture
-class Memory(encoding.Serializable):
+class Memory(encoding.SerializableComparable):
serializable_fields = ('total', 'physical_mb')
# physical = total + kernel binary + reserved space
diff --git a/ironic_python_agent/tests/unit/test_encoding.py b/ironic_python_agent/tests/unit/test_encoding.py
new file mode 100644
index 00000000..522dc968
--- /dev/null
+++ b/ironic_python_agent/tests/unit/test_encoding.py
@@ -0,0 +1,62 @@
+# Copyright (C) 2015 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from oslotest import base as test_base
+
+from ironic_python_agent import encoding
+
+
+class SerializableTesting(encoding.Serializable):
+ serializable_fields = ('jack', 'jill')
+
+ def __init__(self, jack, jill):
+ self.jack = jack
+ self.jill = jill
+
+
+class SerializableComparableTesting(encoding.SerializableComparable):
+ serializable_fields = ('jack', 'jill')
+
+ def __init__(self, jack, jill):
+ self.jack = jack
+ self.jill = jill
+
+
+class TestSerializable(test_base.BaseTestCase):
+ def test_baseclass_serialize(self):
+ obj = encoding.Serializable()
+ self.assertEqual({}, obj.serialize())
+
+ def test_childclass_serialize(self):
+ expected = {'jack': 'hello', 'jill': 'world'}
+ obj = SerializableTesting('hello', 'world')
+ self.assertEqual(expected, obj.serialize())
+
+
+class TestSerializableComparable(test_base.BaseTestCase):
+
+ def test_childclass_equal(self):
+ obj1 = SerializableComparableTesting('hello', 'world')
+ obj2 = SerializableComparableTesting('hello', 'world')
+ self.assertEqual(obj1, obj2)
+
+ def test_childclass_notequal(self):
+ obj1 = SerializableComparableTesting('hello', 'world')
+ obj2 = SerializableComparableTesting('hello', 'world2')
+ self.assertNotEqual(obj1, obj2)
+
+ def test_childclass_hash(self):
+ # Ensure __hash__ is None
+ obj = SerializableComparableTesting('hello', 'world')
+ self.assertEqual(None, obj.__hash__)