Repository: zhmcclient/python-zhmcclient

Issue:
zhmccliet_mock framework- partition start stop works with different partition object
### Actual behavior
partition.delete() invokation followed with query of status parameter on Partition fails 

 File "nova_dpm/virt/dpm/vm.py", line 315, in destroy
        if (self.partition.properties['status'] == 'stopped'):
    KeyError: 'status'

Placed some debuglogs in _urihandler.py and vm.py to see if the partition object is same but doesnt seem to be so...
  ###############destroy function debug logs in vm.py###################
    destroy function
    /api/partitions/1
    140453452362448
#################logs from _urihandler.py############################
    PartitionStopHandler
    /api/partitions/1
    140453452274384
    stopped
    {'virtual-function-uris': [], 'hba-uris': ['/api/partitions/1/hbas/1'], 'object-uri': '/api/partitions/1', 'initial-memory': 512, 'nic-uris': [], 'status': 'stopped', 'ifl-processors': 1, 'name': 'OpenStack-fakemini-38400000-8cf0-11bd-b23e-10b96e4ef00d', 'object-id': '1', 'description': 'Partition #1 in CPC #2'}


### Expected behavior
partition.delete() with zhmcclient_mock is expected to have invoked the mocking framework's PartitionStopHandler function in _urihandler.py which is expected to add new parameter 'status' which is set with value "stopped"

### Execution environment
zhmccliet_mock

* zhmcclient version:
* Operating system (type+version):


Discussion:
coveralls: 
[![Coverage Status](https://coveralls.io/builds/10680542/badge)](https://coveralls.io/builds/10680542)

Coverage decreased (-0.1%) to 88.626% when pulling **f0b45f6a790af1cb7778ff36a9a8a73e8a934ddb on andy/fix-mock** into **560cdaa7fda0f63688efa192cbfe711324a194ea on master**.


Patch:
diff --git a/docs/changes.rst b/docs/changes.rst
index c6b5f3b..4abc74c 100644
--- a/docs/changes.rst
+++ b/docs/changes.rst
@@ -33,8 +33,32 @@ Released: not yet
 
 * Added WWPN support in mocking framework (issue #212).
 
+* Fixed error in mock support where the `operation_timeout` argument to
+  `FakedSession.post()` was missing.
+
+* Fixed a bug in the unit test for the mock support, that caused incomplete
+  expected results not to be surfaced, and fixed the incomplete testcases.
+
 **Enhancements:**
 
+* Improved the mock support by adding the typical attributes of its superclass
+  `FakedBaseResource` to the `FakedHmc` class.
+
+* Improved the mock support by adding `__repr__()` methods to all `Faked*`
+  classes that return an object representation suitable for debugging.
+
+* In the mock support, the following resource properties are now auto-set if
+  not specified in the input properties:
+  - Cpc:
+    - 'dpm-enabled' is auto-set to `False`, if not specified.
+    - 'is-ensemble-member' is auto-set to `False`, if not specified.
+    - 'status' is auto-set, if not specified, as follows: If the
+      'dpm-enabled' property is `True`, it is set to 'active';
+      otherwise it is set to 'operating'.
+  - Partition: 'status' is auto-set to 'stopped', if not specified.
+  - Lpar: 'status' is auto-set to 'not-activated', if not specified.
+  - Adapter: 'status' is auto-set to 'active', if not specified.
+
 **Known Issues:**
 
 * See `list of open issues`_.
diff --git a/zhmcclient_mock/_hmc.py b/zhmcclient_mock/_hmc.py
index 450855e..74b45b0 100644
--- a/zhmcclient_mock/_hmc.py
+++ b/zhmcclient_mock/_hmc.py
@@ -25,6 +25,7 @@ try:
 except ImportError:
     from ordereddict import OrderedDict
 import six
+import pprint
 
 from ._idpool import IdPool
 
@@ -48,18 +49,47 @@ class FakedBaseResource(object):
     """
 
     def __init__(self, manager, properties):
-        self._manager = manager
-        self._properties = properties
+        self._manager = manager  # May be None
+        self._properties = properties.copy() if properties is not None \
+            else None
 
-        if self.manager.oid_prop not in self.properties:
-            new_oid = self.manager._new_oid()
-            self.properties[self.manager.oid_prop] = new_oid
-        self._oid = self.properties[self.manager.oid_prop]
+        if self.manager and self.properties:
 
-        if self.manager.uri_prop not in self.properties:
-            new_uri = self.manager.base_uri + '/' + self.oid
-            self.properties[self.manager.uri_prop] = new_uri
-        self._uri = self.properties[self.manager.uri_prop]
+            if self.manager.oid_prop not in self.properties:
+                new_oid = self.manager._new_oid()
+                self.properties[self.manager.oid_prop] = new_oid
+            self._oid = self.properties[self.manager.oid_prop]
+
+            if self.manager.uri_prop not in self.properties:
+                new_uri = self.manager.base_uri + '/' + self.oid
+                self.properties[self.manager.uri_prop] = new_uri
+            self._uri = self.properties[self.manager.uri_prop]
+
+        else:
+            self._oid = None
+            self._uri = None
+
+    def __repr__(self):
+        """
+        Return a string with the state of this faked resource, for debug
+        purposes.
+        """
+        ret = (
+            "{classname} at 0x{id:08x} (\n"
+            "  _manager = {manager_classname} at 0x{manager_id:08x}\n"
+            "  _manager._parent._uri = {parent_uri!r}\n"
+            "  _uri = {_uri!r}\n"
+            "  _properties = {_properties}\n"
+            ")".format(
+                classname=self.__class__.__name__,
+                id=id(self),
+                manager_classname=self._manager.__class__.__name__,
+                manager_id=id(self._manager),
+                parent_uri=self._manager.parent.uri,
+                _uri=self._uri,
+                _properties=pprint.pformat(self.properties, indent=4),
+            ))
+        return ret
 
     @property
     def manager(self):
@@ -122,6 +152,35 @@ class FakedBaseManager(object):
         self._uri_prop = uri_prop
         self._resources = OrderedDict()  # Resource objects, by object ID
 
+    def __repr__(self):
+        """
+        Return a string with the state of this faked manager, for debug
+        purposes.
+        """
+        ret = (
+            "{classname} at 0x{id:08x} (\n"
+            "  _hmc = {hmc_classname} at 0x{hmc_id:08x}\n"
+            "  _parent = {parent_classname} at 0x{parent_id:08x}\n"
+            "  _resource_class = {_resource_class!r}\n"
+            "  _base_uri = {_base_uri!r}\n"
+            "  _oid_prop = {_oid_prop!r}\n"
+            "  _uri_prop = {_uri_prop!r}\n"
+            "  _resources = {_resources}\n"
+            ")".format(
+                classname=self.__class__.__name__,
+                id=id(self),
+                hmc_classname=self._hmc.__class__.__name__,
+                hmc_id=id(self._hmc),
+                parent_classname=self._parent.__class__.__name__,
+                parent_id=id(self._parent),
+                _resource_class=self._resource_class,
+                _base_uri=self._base_uri,
+                _oid_prop=self._oid_prop,
+                _uri_prop=self._uri_prop,
+                _resources=pprint.pformat(self._resources, indent=4),
+            ))
+        return ret
+
     @property
     def hmc(self):
         """
@@ -260,12 +319,34 @@ class FakedHmc(FakedBaseResource):
     """
 
     def __init__(self, hmc_name, hmc_version, api_version):
+        super(FakedHmc, self).__init__(manager=None, properties=None)
         self.hmc_name = hmc_name
         self.hmc_version = hmc_version
         self.api_version = api_version
         self.cpcs = FakedCpcManager(hmc=self, client=self)
         self._resources = {}  # by URI
 
+    def __repr__(self):
+        """
+        Return a string with the state of this faked HMC, for debug purposes.
+        """
+        ret = (
+            "FakedHmc at 0x{id:08x} (\n"
+            "  hmc_name = {hmc_name!r}\n"
+            "  hmc_version = {hmc_version!r}\n"
+            "  api_version = {api_version!r}\n"
+            "  cpcs = {cpcs!r}\n"
+            "  _resources = {_resources!r}\n"
+            ")".format(
+                id=id(self),
+                hmc_name=self.hmc_name,
+                hmc_version=self.hmc_version,
+                api_version=self.api_version,
+                cpcs=self.cpcs,
+                _resources=self._resources,
+            ))
+        return ret
+
     def add_resources(self, resources):
         """
         Add faked resources to the faked HMC, from the provided resource
@@ -482,13 +563,14 @@ class FakedAdapterManager(FakedBaseManager):
               all instances of this resource type, if not specified.
             * 'object-uri' will be auto-generated based upon the object ID,
               if not specified.
+            * 'status' is auto-set to 'active', if not specified.
             * 'adapter-family' or 'type' is required to be specified, in order
               to determine whether the adapter is a network or storage adapter.
             * 'adapter-family' is auto-set based upon 'type', if not specified.
-            * 'network-port-uris' is auto-set to an empty list, if not set,
-              for network adapters.
-            * 'storage-port-uris' is auto-set to an empty list, if not set,
-              for storage adapters.
+            * For network adapters, 'network-port-uris' is auto-set to an empty
+              list, if not specified.
+            * For storage adapters, 'storage-port-uris' is auto-set to an empty
+              list, if not specified.
 
         Returns:
           :class:`~zhmcclient_mock.FakedAdapter`: The faked Adapter resource.
@@ -509,35 +591,35 @@ class FakedAdapter(FakedBaseResource):
         super(FakedAdapter, self).__init__(
             manager=manager,
             properties=properties)
-        if 'adapter-family' in properties:
-            family = properties['adapter-family']
+        if 'adapter-family' in self.properties:
+            family = self.properties['adapter-family']
             if family in ('osa', 'roce', 'hipersockets'):
                 self._adapter_kind = 'network'
             elif family in ('ficon',):
                 self._adapter_kind = 'storage'
             else:
                 self._adapter_kind = 'other'
-        elif 'type' in properties:
+        elif 'type' in self.properties:
             # because 'type' is more specific than 'adapter-family', we can
             # auto-set 'adapter-family' from 'type'.
-            type_ = properties['type']
+            type_ = self.properties['type']
             if type_ in ('osd', 'osm'):
-                self._properties['adapter-family'] = 'osa'
+                self.properties['adapter-family'] = 'osa'
                 self._adapter_kind = 'network'
             elif type_ == 'roce':
-                self._properties['adapter-family'] = 'roce'
+                self.properties['adapter-family'] = 'roce'
                 self._adapter_kind = 'network'
             elif type_ == 'hipersockets':
-                self._properties['adapter-family'] = 'hipersockets'
+                self.properties['adapter-family'] = 'hipersockets'
                 self._adapter_kind = 'network'
             elif type_ == 'fcp':
-                self._properties['adapter-family'] = 'ficon'
+                self.properties['adapter-family'] = 'ficon'
                 self._adapter_kind = 'storage'
             elif type_ == 'crypto':
-                self._properties['adapter-family'] = 'crypto'
+                self.properties['adapter-family'] = 'crypto'
                 self._adapter_kind = 'other'
             elif type_ == 'zedc':
-                self._properties['adapter-family'] = 'accelerator'
+                self.properties['adapter-family'] = 'accelerator'
                 self._adapter_kind = 'other'
             else:
                 raise ValueError("FakedAdapter with object-id=%s has an "
@@ -549,14 +631,16 @@ class FakedAdapter(FakedBaseResource):
                              self.oid)
         if self.adapter_kind == 'network':
             if 'network-port-uris' not in self.properties:
-                self._properties['network-port-uris'] = []
+                self.properties['network-port-uris'] = []
             self._ports = FakedPortManager(hmc=manager.hmc, adapter=self)
         elif self.adapter_kind == 'storage':
             if 'storage-port-uris' not in self.properties:
-                self._properties['storage-port-uris'] = []
+                self.properties['storage-port-uris'] = []
             self._ports = FakedPortManager(hmc=manager.hmc, adapter=self)
         else:
             self._ports = None
+        if 'status' not in self.properties:
+            self.properties['status'] = 'active'
 
     @property
     def ports(self):
@@ -616,6 +700,11 @@ class FakedCpcManager(FakedBaseManager):
               all instances of this resource type, if not specified.
             * 'object-uri' will be auto-generated based upon the object ID,
               if not specified.
+            * 'dpm-enabled' is auto-set to `False`, if not specified.
+            * 'is-ensemble-member' is auto-set to `False`, if not specified.
+            * 'status' is auto-set, if not specified, as follows: If the
+              'dpm-enabled' property is `True`, it is set to 'active';
+              otherwise it is set to 'operating'.
 
         Returns:
           :class:`~zhmcclient_mock.FakedCpc`: The faked CPC resource.
@@ -647,15 +736,24 @@ class FakedCpc(FakedBaseResource):
             hmc=manager.hmc, cpc=self, profile_type='image')
         self._load_activation_profiles = FakedActivationProfileManager(
             hmc=manager.hmc, cpc=self, profile_type='load')
+        if 'dpm-enabled' not in self.properties:
+            self.properties['dpm-enabled'] = False
+        if 'is-ensemble-member' not in self.properties:
+            self.properties['is-ensemble-member'] = False
+        if 'status' not in self.properties:
+            if self.dpm_enabled:
+                self.properties['status'] = 'active'
+            else:
+                self.properties['status'] = 'operating'
 
     @property
     def dpm_enabled(self):
         """
         bool: Indicates whether this CPC is in DPM mode.
 
-        This is based upon the 'dpm-enabled' property and defaults to `False`.
+        This returns the value of the 'dpm-enabled' property.
         """
-        return self.properties.get('dpm-enabled', False)
+        return self.properties['dpm-enabled']
 
     @property
     def lpars(self):
@@ -853,6 +951,7 @@ class FakedLparManager(FakedBaseManager):
               all instances of this resource type, if not specified.
             * 'object-uri' will be auto-generated based upon the object ID,
               if not specified.
+            * 'status' is auto-set to 'not-activated', if not specified.
 
         Returns:
           :class:`~zhmcclient_mock.FakedLpar`: The faked LPAR resource.
@@ -873,6 +972,8 @@ class FakedLpar(FakedBaseResource):
         super(FakedLpar, self).__init__(
             manager=manager,
             properties=properties)
+        if 'status' not in self.properties:
+            self.properties['status'] = 'not-activated'
 
 
 class FakedNicManager(FakedBaseManager):
@@ -1018,6 +1119,7 @@ class FakedPartitionManager(FakedBaseManager):
               specified.
             * 'virtual-function-uris' will be auto-generated as an empty array,
               if not specified.
+            * 'status' is auto-set to 'stopped', if not specified.
 
         Returns:
           :class:`~zhmcclient_mock.FakedPartition`: The faked Partition
@@ -1050,6 +1152,8 @@ class FakedPartition(FakedBaseResource):
             self.properties['nic-uris'] = []
         if 'virtual-function-uris' not in self.properties:
             self.properties['virtual-function-uris'] = []
+        if 'status' not in self.properties:
+            self.properties['status'] = 'stopped'
         self._nics = FakedNicManager(hmc=manager.hmc, partition=self)
         self._hbas = FakedHbaManager(hmc=manager.hmc, partition=self)
         self._virtual_functions = FakedVirtualFunctionManager(
diff --git a/zhmcclient_mock/_session.py b/zhmcclient_mock/_session.py
index 0471caa..140e70d 100644
--- a/zhmcclient_mock/_session.py
+++ b/zhmcclient_mock/_session.py
@@ -126,7 +126,7 @@ class FakedSession(zhmcclient.Session):
             raise zhmcclient.HTTPError(exc.response())
 
     def post(self, uri, body=None, logon_required=True,
-             wait_for_completion=True):
+             wait_for_completion=True, operation_timeout=None):
         """
         Perform the HTTP POST method against the resource identified by a URI,
         using a provided request body, on the faked HMC.
@@ -189,6 +189,18 @@ class FakedSession(zhmcclient.Session):
               HTTP POST method, regardless of whether the operation is
               synchronous or asynchronous.
 
+          operation_timeout (:term:`number`):
+            Timeout in seconds, when waiting for completion of an asynchronous
+            operation. The special value 0 means that no timeout is set. `None`
+            means that the default async operation timeout of the session is
+            used.
+
+            For `wait_for_completion=True`, a
+            :exc:`~zhmcclient.OperationTimeout` is raised when the timeout
+            expires.
+
+            For `wait_for_completion=False`, this parameter has no effect.
+
         Returns:
 
           :term:`json object`:


Test patch:
diff --git a/tests/unit/zhmcclient_mock/test_hmc.py b/tests/unit/zhmcclient_mock/test_hmc.py
index cde9768..2a3f05d 100755
--- a/tests/unit/zhmcclient_mock/test_hmc.py
+++ b/tests/unit/zhmcclient_mock/test_hmc.py
@@ -20,6 +20,7 @@ Unit tests for _hmc module of the zhmcclient_mock package.
 from __future__ import absolute_import, print_function
 
 import unittest
+import re
 
 from zhmcclient_mock._hmc import FakedHmc, \
     FakedActivationProfileManager, FakedActivationProfile, \
@@ -31,7 +32,8 @@ from zhmcclient_mock._hmc import FakedHmc, \
     FakedPartitionManager, FakedPartition, \
     FakedPortManager, FakedPort, \
     FakedVirtualFunctionManager, FakedVirtualFunction, \
-    FakedVirtualSwitchManager, FakedVirtualSwitch
+    FakedVirtualSwitchManager, FakedVirtualSwitch, \
+    FakedBaseManager, FakedBaseResource
 
 
 class FakedHmcTests(unittest.TestCase):
@@ -40,6 +42,45 @@ class FakedHmcTests(unittest.TestCase):
     def setUp(self):
         self.hmc = FakedHmc('fake-hmc', '2.13.1', '1.8')
 
+    def test_repr(self):
+
+        # The test approach is to check the repr() result for each attribute
+        # that is shown in the result, but leaving some flexibility in how that
+        # is formatted.
+
+        # Bring everything into one line, because regexp is line-oriented.
+        act_repr = repr(self.hmc).replace('\n', '\\n')
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*FakedHmc\s+at\s+0x{id:08x}\s+\(\\n.*'.
+            format(id=id(self.hmc)))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\shmc_name\s*=\s*{hmc_name!r}\\n.*'.
+            format(hmc_name=self.hmc.hmc_name))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\shmc_version\s*=\s*{hmc_version!r}\\n.*'.
+            format(hmc_version=self.hmc.hmc_version))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\sapi_version\s*=\s*{api_version!r}\\n.*'.
+            format(api_version=self.hmc.api_version))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\scpcs\s*=\s*FakedCpcManager\s.*')
+        # TODO: Check content of `cpcs`
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_resources\s*=\s.*')
+        # TODO: Check content of `_resources`
+
     def test_hmc(self):
         self.assertEqual(self.hmc.hmc_name, 'fake-hmc')
         self.assertEqual(self.hmc.hmc_version, '2.13.1')
@@ -55,12 +96,15 @@ class FakedHmcTests(unittest.TestCase):
         cpc1_in_props = {'name': 'cpc1'}
 
         # the function to be tested:
-        cpc1 = self.hmc.cpcs.add({'name': 'cpc1'})
+        cpc1 = self.hmc.cpcs.add(cpc1_in_props)
 
         cpc1_out_props = cpc1_in_props.copy()
         cpc1_out_props.update({
             'object-id': cpc1.oid,
             'object-uri': cpc1.uri,
+            'dpm-enabled': False,
+            'is-ensemble-member': False,
+            'status': 'operating',
         })
 
         # the function to be tested:
@@ -83,6 +127,9 @@ class FakedHmcTests(unittest.TestCase):
         cpc1_out_props.update({
             'object-id': cpc1.oid,
             'object-uri': cpc1.uri,
+            'dpm-enabled': False,
+            'is-ensemble-member': False,
+            'status': 'operating',
         })
 
         cpc2_in_props = {'name': 'cpc2'}
@@ -94,6 +141,9 @@ class FakedHmcTests(unittest.TestCase):
         cpc2_out_props.update({
             'object-id': cpc2.oid,
             'object-uri': cpc2.uri,
+            'dpm-enabled': False,
+            'is-ensemble-member': False,
+            'status': 'operating',
         })
 
         # the function to be tested:
@@ -145,6 +195,9 @@ class FakedHmcTests(unittest.TestCase):
         cpc1_out_props.update({
             'object-id': cpc1.oid,
             'object-uri': cpc1.uri,
+            'dpm-enabled': False,
+            'is-ensemble-member': False,
+            'status': 'operating',
         })
         self.assertIsInstance(cpc1, FakedCpc)
         self.assertEqual(cpc1.properties, cpc1_out_props)
@@ -153,22 +206,24 @@ class FakedHmcTests(unittest.TestCase):
         cpc1_adapters = cpc1.adapters.list()
 
         self.assertEqual(len(cpc1_adapters), 1)
-
         adapter1 = cpc1_adapters[0]
+
+        adapter1_ports = adapter1.ports.list()
+
+        self.assertEqual(len(adapter1_ports), 1)
+        port1 = adapter1_ports[0]
+
         adapter1_out_props = adapter1_in_props.copy()
         adapter1_out_props.update({
             'object-id': adapter1.oid,
             'object-uri': adapter1.uri,
+            'status': 'active',
+            'network-port-uris': [port1.uri],
         })
         self.assertIsInstance(adapter1, FakedAdapter)
         self.assertEqual(adapter1.properties, adapter1_out_props)
         self.assertEqual(adapter1.manager, cpc1.adapters)
 
-        adapter1_ports = adapter1.ports.list()
-
-        self.assertEqual(len(adapter1_ports), 1)
-
-        port1 = adapter1_ports[0]
         port1_out_props = port1_in_props.copy()
         port1_out_props.update({
             'element-id': port1.oid,
@@ -179,6 +234,151 @@ class FakedHmcTests(unittest.TestCase):
         self.assertEqual(port1.manager, adapter1.ports)
 
 
+class FakedBaseTests(unittest.TestCase):
+    """All tests for the FakedBaseManager and FakedBaseResource classes."""
+
+    def setUp(self):
+        self.hmc = FakedHmc('fake-hmc', '2.13.1', '1.8')
+        self.cpc1_in_props = {
+            # All properties that are otherwise defaulted (but with non-default
+            # values), plus 'name'.
+            'object-id': '42',
+            'object-uri': '/api/cpcs/42',
+            'dpm-enabled': True,
+            'is-ensemble-member': False,
+            'status': 'service',
+            'name': 'cpc1',
+        }
+        rd = {
+            'cpcs': [
+                {
+                    'properties': self.cpc1_in_props,
+                },
+            ]
+        }
+        self.hmc.add_resources(rd)
+        self.cpc_manager = self.hmc.cpcs
+        self.cpc_resource = self.hmc.cpcs.list()[0]
+        self.cpc1_out_props = self.cpc1_in_props.copy()
+
+    def test_manager_attr(self):
+        """Test FakedBaseManager attributes."""
+
+        self.assertIsInstance(self.cpc_manager, FakedBaseManager)
+
+        self.assertEqual(self.cpc_manager.hmc, self.hmc)
+        self.assertEqual(self.cpc_manager.parent, self.hmc)
+        self.assertEqual(self.cpc_manager.resource_class, FakedCpc)
+        self.assertEqual(self.cpc_manager.base_uri, '/api/cpcs')
+        self.assertEqual(self.cpc_manager.oid_prop, 'object-id')
+        self.assertEqual(self.cpc_manager.uri_prop, 'object-uri')
+
+    def test_resource_attr(self):
+        """Test FakedBaseResource attributes."""
+
+        self.assertIsInstance(self.cpc_resource, FakedBaseResource)
+
+        self.assertEqual(self.cpc_resource.manager, self.cpc_manager)
+        self.assertEqual(self.cpc_resource.properties, self.cpc1_out_props)
+        self.assertEqual(self.cpc_resource.oid,
+                         self.cpc1_out_props['object-id'])
+        self.assertEqual(self.cpc_resource.uri,
+                         self.cpc1_out_props['object-uri'])
+
+    def test_manager_repr(self):
+        """Test FakedBaseManager.__repr__()."""
+
+        # The test approach is to check the repr() result for each attribute
+        # that is shown in the result, but leaving some flexibility in how that
+        # is formatted.
+
+        # Bring everything into one line, because regexp is line-oriented.
+        act_repr = repr(self.cpc_manager).replace('\n', '\\n')
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*{classname}\s+at\s+0x{id:08x}\s+\(\\n.*'.
+            format(classname=self.cpc_manager.__class__.__name__,
+                   id=id(self.cpc_manager)))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_hmc\s*=\s*{hmc_classname}\s+at\s+0x{hmc_id:08x}\\n.*'.
+            format(hmc_classname=self.cpc_manager.hmc.__class__.__name__,
+                   hmc_id=id(self.cpc_manager.hmc)))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_parent\s*=\s*{p_classname}\s+at\s+0x{p_id:08x}\\n.*'.
+            format(p_classname=self.cpc_manager.parent.__class__.__name__,
+                   p_id=id(self.cpc_manager.parent)))
+
+        m = re.match(r'.*\s_resource_class\s*=\s*([^\\]+)\\n.*', act_repr)
+        if not m:
+            raise AssertionError("'_resource_class = ...' did not match "
+                                 "in: {!r}".format(act_repr))
+        act_resource_class = m.group(1)
+        self.assertEqual(act_resource_class,
+                         repr(self.cpc_manager.resource_class))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_base_uri\s*=\s*{_base_uri!r}\\n.*'.
+            format(_base_uri=self.cpc_manager.base_uri))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_oid_prop\s*=\s*{_oid_prop!r}\\n.*'.
+            format(_oid_prop=self.cpc_manager.oid_prop))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_uri_prop\s*=\s*{_uri_prop!r}\\n.*'.
+            format(_uri_prop=self.cpc_manager.uri_prop))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_resources\s*=\s.*')
+        # TODO: Check content of `_resources`
+
+    def test_resource_repr(self):
+        """Test FakedBaseResource.__repr__()."""
+
+        # The test approach is to check the repr() result for each attribute
+        # that is shown in the result, but leaving some flexibility in how that
+        # is formatted.
+
+        # Bring everything into one line, because regexp is line-oriented.
+        act_repr = repr(self.cpc_resource).replace('\n', '\\n')
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*{classname}\s+at\s+0x{id:08x}\s+\(\\n.*'.
+            format(classname=self.cpc_resource.__class__.__name__,
+                   id=id(self.cpc_resource)))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_manager\s*=\s*{m_classname}\s+at\s+0x{m_id:08x}\\n.*'.
+            format(m_classname=self.cpc_resource.manager.__class__.__name__,
+                   m_id=id(self.cpc_resource.manager)))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_manager._parent._uri\s*=\s*{p_uri!r}\\n.*'.
+            format(p_uri=self.cpc_resource.manager.parent.uri))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_uri\s*=\s*{_uri!r}\\n.*'.
+            format(_uri=self.cpc_resource.uri))
+
+        self.assertRegexpMatches(
+            act_repr,
+            r'.*\s_properties\s*=\s.*')
+        # TODO: Check content of `_properties`
+
+
 class FakedActivationProfileTests(unittest.TestCase):
     """All tests for the FakedActivationProfileManager and
     FakedActivationProfile classes."""
@@ -382,6 +582,9 @@ class FakedAdapterTests(unittest.TestCase):
         adapter1_out_props.update({
             'object-id': adapter1.oid,
             'object-uri': adapter1.uri,
+            'status': 'active',
+            'adapter-family': 'roce',
+            'network-port-uris': [],
         })
         self.assertIsInstance(adapter1, FakedAdapter)
         self.assertEqual(adapter1.properties, adapter1_out_props)
@@ -416,6 +619,8 @@ class FakedAdapterTests(unittest.TestCase):
         adapter2_out_props.update({
             'object-id': adapter2.oid,
             'object-uri': adapter2.uri,
+            'status': 'active',
+            'storage-port-uris': [],
         })
         self.assertIsInstance(adapter2, FakedAdapter)
         self.assertEqual(adapter2.properties, adapter2_out_props)
@@ -468,6 +673,9 @@ class FakedCpcTests(unittest.TestCase):
         cpc1_out_props.update({
             'object-id': cpc1.oid,
             'object-uri': cpc1.uri,
+            'dpm-enabled': False,
+            'is-ensemble-member': False,
+            'status': 'operating',
         })
         self.assertIsInstance(cpc1, FakedCpc)
         self.assertEqual(cpc1.properties, cpc1_out_props)
@@ -508,6 +716,9 @@ class FakedCpcTests(unittest.TestCase):
         cpc2_out_props.update({
             'object-id': cpc2.oid,
             'object-uri': cpc2.uri,
+            'dpm-enabled': False,
+            'is-ensemble-member': False,
+            'status': 'operating',
         })
         self.assertIsInstance(cpc2, FakedCpc)
         self.assertEqual(cpc2.properties, cpc2_out_props)
@@ -599,6 +810,8 @@ class FakedHbaTests(unittest.TestCase):
         hba1_out_props.update({
             'element-id': hba1.oid,
             'element-uri': hba1.uri,
+            'device-number': hba1.properties['device-number'],
+            'wwpn': hba1.properties['wwpn'],
         })
         self.assertIsInstance(hba1, FakedHba)
         self.assertEqual(hba1.properties, hba1_out_props)
@@ -617,6 +830,8 @@ class FakedHbaTests(unittest.TestCase):
             'element-id': '2',
             'name': 'hba2',
             'adapter-port-uri': '/api/adapters/1/storage-ports/1',
+            'device-number': '8001',
+            'wwpn': 'AFFEAFFE00008001',
         }
 
         # the function to be tested:
@@ -703,6 +918,7 @@ class FakedLparTests(unittest.TestCase):
         lpar1_out_props.update({
             'object-id': lpar1.oid,
             'object-uri': lpar1.uri,
+            'status': 'not-activated',
         })
         self.assertIsInstance(lpar1, FakedLpar)
         self.assertEqual(lpar1.properties, lpar1_out_props)
@@ -734,6 +950,7 @@ class FakedLparTests(unittest.TestCase):
         lpar2_out_props.update({
             'object-id': lpar2.oid,
             'object-uri': lpar2.uri,
+            'status': 'not-activated',
         })
         self.assertIsInstance(lpar2, FakedLpar)
         self.assertEqual(lpar2.properties, lpar2_out_props)
@@ -827,6 +1044,7 @@ class FakedNicTests(unittest.TestCase):
         nic1_out_props.update({
             'element-id': nic1.oid,
             'element-uri': nic1.uri,
+            'device-number': nic1.properties['device-number'],
         })
         self.assertIsInstance(nic1, FakedNic)
         self.assertEqual(nic1.properties, nic1_out_props)
@@ -863,6 +1081,7 @@ class FakedNicTests(unittest.TestCase):
         nic2_out_props.update({
             'element-id': nic2.oid,
             'element-uri': nic2.uri,
+            'device-number': nic2.properties['device-number'],
         })
         self.assertIsInstance(nic2, FakedNic)
         self.assertEqual(nic2.properties, nic2_out_props)
@@ -929,6 +1148,10 @@ class FakedPartitionTests(unittest.TestCase):
         partition1_out_props.update({
             'object-id': partition1.oid,
             'object-uri': partition1.uri,
+            'status': 'stopped',
+            'hba-uris': [],
+            'nic-uris': [],
+            'virtual-function-uris': [],
         })
         self.assertIsInstance(partition1, FakedPartition)
         self.assertEqual(partition1.properties, partition1_out_props)
@@ -961,6 +1184,10 @@ class FakedPartitionTests(unittest.TestCase):
         partition2_out_props.update({
             'object-id': partition2.oid,
             'object-uri': partition2.uri,
+            'status': 'stopped',
+            'hba-uris': [],
+            'nic-uris': [],
+            'virtual-function-uris': [],
         })
         self.assertIsInstance(partition2, FakedPartition)
         self.assertEqual(partition2.properties, partition2_out_props)
@@ -1148,6 +1375,7 @@ class FakedVirtualFunctionTests(unittest.TestCase):
         virtual_function1_out_props.update({
             'element-id': virtual_function1.oid,
             'element-uri': virtual_function1.uri,
+            'device-number': virtual_function1.properties['device-number'],
         })
         self.assertIsInstance(virtual_function1, FakedVirtualFunction)
         self.assertEqual(virtual_function1.properties,
@@ -1186,6 +1414,7 @@ class FakedVirtualFunctionTests(unittest.TestCase):
         virtual_function2_out_props.update({
             'element-id': virtual_function2.oid,
             'element-uri': virtual_function2.uri,
+            'device-number': virtual_function2.properties['device-number'],
         })
         self.assertIsInstance(virtual_function2, FakedVirtualFunction)
         self.assertEqual(virtual_function2.properties,
diff --git a/tests/unit/zhmcclient_mock/test_urihandler.py b/tests/unit/zhmcclient_mock/test_urihandler.py
index 6febc10..9d3ba3f 100755
--- a/tests/unit/zhmcclient_mock/test_urihandler.py
+++ b/tests/unit/zhmcclient_mock/test_urihandler.py
@@ -576,6 +576,7 @@ class GenericGetPropertiesHandlerTests(unittest.TestCase):
             'object-uri': '/api/cpcs/1',
             'name': 'cpc_1',
             'dpm-enabled': False,
+            'is-ensemble-member': False,
             'description': 'CPC #1 (classic mode)',
             'status': 'operating',
         }
@@ -678,6 +679,7 @@ class CpcHandlersTests(unittest.TestCase):
             'object-uri': '/api/cpcs/1',
             'name': 'cpc_1',
             'dpm-enabled': False,
+            'is-ensemble-member': False,
             'description': 'CPC #1 (classic mode)',
             'status': 'operating',
         }
@@ -822,12 +824,12 @@ class AdapterHandlersTests(unittest.TestCase):
                 {
                     'object-uri': '/api/adapters/2',
                     'name': 'fcp_2',
-                    # status not set in resource -> not in response
+                    'status': 'active',
                 },
                 {
                     'object-uri': '/api/adapters/3',
                     'name': 'roce_3',
-                    # status not set in resource -> not in response
+                    'status': 'active',
                 },
             ]
         }
@@ -1004,6 +1006,7 @@ class PartitionHandlersTests(unittest.TestCase):
             'object-id': '2',
             'object-uri': '/api/partitions/2',
             'name': 'partition_2',
+            'status': 'stopped',
             'hba-uris': [],
             'nic-uris': [],
             'virtual-function-uris': [],