From 4f229832c0b9309b822d6cb071622f778e575773 Mon Sep 17 00:00:00 2001
From: "ChangBo Guo(gcb)" <eric.guo@easystack.cn>
Date: Sat, 4 Feb 2017 15:30:23 +0800
Subject: [PATCH] Test:Use unittest.mock on Python 3

The mock module has been added to Python 3.3 as unittest.mock.
The third party mock module doesn't seem to be maintained anymore.
This is follow up of 72c501454ea33b603918de35565a66dda8abd66a and
add hacking rule to avoid regression issue.

oslotest prepares mock for six in oslotest/__init__.py as follow:
six.add_move(six.MovedModule('mock', 'mock', 'unittest.mock')) and
oslo_messaging/tests/__init__.py imports oslotest before importing
test submodules to setup six.moves for mock, then "from six.moves
import mock" works well.

Note: unittest.mock also detects wrong usage of method
assert_called_once_with.

Change-Id: I3d09733789cfa2550cf47c24f2553357d36bcc0d
---
 oslo_messaging/hacking/checks.py              | 14 ++++++
 oslo_messaging/tests/__init__.py              |  5 ++-
 .../tests/drivers/pika/test_message.py        | 45 +++++++++----------
 .../tests/drivers/pika/test_poller.py         |  2 +-
 .../tests/drivers/test_impl_kafka.py          |  4 +-
 .../tests/drivers/zmq/test_zmq_ack_manager.py |  2 +-
 .../tests/drivers/zmq/test_zmq_async.py       |  2 +-
 .../drivers/zmq/test_zmq_transport_url.py     |  2 +-
 .../tests/notify/test_impl_messaging.py       |  2 +-
 oslo_messaging/tests/rpc/test_client.py       |  3 +-
 oslo_messaging/tests/rpc/test_server.py       |  2 +-
 oslo_messaging/tests/test_opts.py             |  3 +-
 oslo_messaging/tests/test_transport.py        |  2 +-
 13 files changed, 51 insertions(+), 37 deletions(-)

diff --git a/oslo_messaging/hacking/checks.py b/oslo_messaging/hacking/checks.py
index 2df8fb919..5cb4b3b64 100644
--- a/oslo_messaging/hacking/checks.py
+++ b/oslo_messaging/hacking/checks.py
@@ -20,6 +20,8 @@ import six
 oslo_namespace_imports_dot = re.compile(r"import[\s]+oslo[.][^\s]+")
 oslo_namespace_imports_from_dot = re.compile(r"from[\s]+oslo[.]")
 oslo_namespace_imports_from_root = re.compile(r"from[\s]+oslo[\s]+import[\s]+")
+mock_imports_directly = re.compile(r"import[\s]+mock")
+mock_imports_direclty_from = re.compile(r"from[\s]+mock[\s]+import[\s]+")
 
 
 def check_oslo_namespace_imports(logical_line):
@@ -40,6 +42,17 @@ def check_oslo_namespace_imports(logical_line):
         yield(0, msg)
 
 
+def check_mock_imports(logical_line):
+    if re.match(mock_imports_directly, logical_line):
+        msg = ("O324: '%s' must be used instead of '%s'.") % (
+            logical_line.replace('import mock', 'from six.moves import mock'),
+            logical_line)
+        yield(0, msg)
+    elif re.match(mock_imports_direclty_from, logical_line):
+        msg = "O324: Use mock from six.moves."
+        yield(0, msg)
+
+
 class BaseASTChecker(ast.NodeVisitor):
     """Provides a simple framework for writing AST-based checks.
 
@@ -347,3 +360,4 @@ class CheckForLoggingIssues(BaseASTChecker):
 def factory(register):
     register(CheckForLoggingIssues)
     register(check_oslo_namespace_imports)
+    register(check_mock_imports)
diff --git a/oslo_messaging/tests/__init__.py b/oslo_messaging/tests/__init__.py
index 25e8f9721..7564f2688 100644
--- a/oslo_messaging/tests/__init__.py
+++ b/oslo_messaging/tests/__init__.py
@@ -16,5 +16,8 @@
 import eventlet
 eventlet.monkey_patch()
 
-# Import oslotest before importing test submodules to setup six.moves for mock
+# oslotest prepares mock for six in oslotest/__init__.py as follow:
+# six.add_move(six.MovedModule('mock', 'mock', 'unittest.mock')) and
+# oslo.messaging imports oslotest before importing test submodules to
+# setup six.moves for mock, then "from six.moves import mock" works well.
 import oslotest
diff --git a/oslo_messaging/tests/drivers/pika/test_message.py b/oslo_messaging/tests/drivers/pika/test_message.py
index 40d2c51b7..3722f875a 100644
--- a/oslo_messaging/tests/drivers/pika/test_message.py
+++ b/oslo_messaging/tests/drivers/pika/test_message.py
@@ -16,11 +16,10 @@ import functools
 import unittest
 
 from concurrent import futures
-from mock import mock
-from mock import patch
 from oslo_serialization import jsonutils
 from oslo_utils import timeutils
 import pika
+from six.moves import mock
 
 import oslo_messaging
 from oslo_messaging._drivers.pika_driver import pika_commons as pika_drv_cmns
@@ -151,8 +150,8 @@ class RpcPikaIncomingMessageTestCase(unittest.TestCase):
         self.assertEqual("payload_value",
                          message.message.get("payload_key", None))
 
-    @patch(("oslo_messaging._drivers.pika_driver.pika_message."
-            "PikaOutgoingMessage.send"))
+    @mock.patch(("oslo_messaging._drivers.pika_driver.pika_message."
+                 "PikaOutgoingMessage.send"))
     def test_reply_for_cast_message(self, send_reply_mock):
         message = pika_drv_msg.RpcPikaIncomingMessage(
             self._pika_engine, self._channel, self._method, self._properties,
@@ -171,9 +170,9 @@ class RpcPikaIncomingMessageTestCase(unittest.TestCase):
 
         self.assertEqual(0, send_reply_mock.call_count)
 
-    @patch("oslo_messaging._drivers.pika_driver.pika_message."
-           "RpcReplyPikaOutgoingMessage")
-    @patch("tenacity.retry")
+    @mock.patch("oslo_messaging._drivers.pika_driver.pika_message."
+                "RpcReplyPikaOutgoingMessage")
+    @mock.patch("tenacity.retry")
     def test_positive_reply_for_call_message(self,
                                              retry_mock,
                                              outgoing_message_mock):
@@ -206,9 +205,9 @@ class RpcPikaIncomingMessageTestCase(unittest.TestCase):
             stop=mock.ANY, retry=mock.ANY, wait=mock.ANY
         )
 
-    @patch("oslo_messaging._drivers.pika_driver.pika_message."
-           "RpcReplyPikaOutgoingMessage")
-    @patch("tenacity.retry")
+    @mock.patch("oslo_messaging._drivers.pika_driver.pika_message."
+                "RpcReplyPikaOutgoingMessage")
+    @mock.patch("tenacity.retry")
     def test_negative_reply_for_call_message(self,
                                              retry_mock,
                                              outgoing_message_mock):
@@ -319,8 +318,8 @@ class PikaOutgoingMessageTestCase(unittest.TestCase):
         self._message = {"msg_type": 1, "msg_str": "hello"}
         self._context = {"request_id": 555, "token": "it is a token"}
 
-    @patch("oslo_serialization.jsonutils.dump_as_bytes",
-           new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
+    @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
+                new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
     def test_send_with_confirmation(self):
         message = pika_drv_msg.PikaOutgoingMessage(
             self._pika_engine, self._message, self._context
@@ -363,8 +362,8 @@ class PikaOutgoingMessageTestCase(unittest.TestCase):
         self.assertEqual({'version': '1.0'}, props.headers)
         self.assertTrue(props.message_id)
 
-    @patch("oslo_serialization.jsonutils.dump_as_bytes",
-           new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
+    @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
+                new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
     def test_send_without_confirmation(self):
         message = pika_drv_msg.PikaOutgoingMessage(
             self._pika_engine, self._message, self._context
@@ -421,8 +420,8 @@ class RpcPikaOutgoingMessageTestCase(unittest.TestCase):
         self._message = {"msg_type": 1, "msg_str": "hello"}
         self._context = {"request_id": 555, "token": "it is a token"}
 
-    @patch("oslo_serialization.jsonutils.dump_as_bytes",
-           new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
+    @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
+                new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
     def test_send_cast_message(self):
         message = pika_drv_msg.RpcPikaOutgoingMessage(
             self._pika_engine, self._message, self._context
@@ -467,8 +466,8 @@ class RpcPikaOutgoingMessageTestCase(unittest.TestCase):
         self.assertIsNone(props.reply_to)
         self.assertTrue(props.message_id)
 
-    @patch("oslo_serialization.jsonutils.dump_as_bytes",
-           new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
+    @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
+                new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
     def test_send_call_message(self):
         message = pika_drv_msg.RpcPikaOutgoingMessage(
             self._pika_engine, self._message, self._context
@@ -542,8 +541,8 @@ class RpcReplyPikaOutgoingMessageTestCase(unittest.TestCase):
 
         self._msg_id = 12345567
 
-    @patch("oslo_serialization.jsonutils.dump_as_bytes",
-           new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
+    @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
+                new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
     def test_success_message_send(self):
         message = pika_drv_msg.RpcReplyPikaOutgoingMessage(
             self._pika_engine, self._msg_id, reply="all_fine"
@@ -571,9 +570,9 @@ class RpcReplyPikaOutgoingMessageTestCase(unittest.TestCase):
         self.assertIsNone(props.reply_to)
         self.assertTrue(props.message_id)
 
-    @patch("traceback.format_exception", new=lambda x, y, z: z)
-    @patch("oslo_serialization.jsonutils.dump_as_bytes",
-           new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
+    @mock.patch("traceback.format_exception", new=lambda x, y, z: z)
+    @mock.patch("oslo_serialization.jsonutils.dump_as_bytes",
+                new=functools.partial(jsonutils.dump_as_bytes, sort_keys=True))
     def test_failure_message_send(self):
         failure_info = (oslo_messaging.MessagingException,
                         oslo_messaging.MessagingException("Error message"),
diff --git a/oslo_messaging/tests/drivers/pika/test_poller.py b/oslo_messaging/tests/drivers/pika/test_poller.py
index 445b33860..7957bec8d 100644
--- a/oslo_messaging/tests/drivers/pika/test_poller.py
+++ b/oslo_messaging/tests/drivers/pika/test_poller.py
@@ -17,7 +17,7 @@ import time
 import unittest
 
 from concurrent import futures
-import mock
+from six.moves import mock
 
 from oslo_messaging._drivers.pika_driver import pika_exceptions as pika_drv_exc
 from oslo_messaging._drivers.pika_driver import pika_poller
diff --git a/oslo_messaging/tests/drivers/test_impl_kafka.py b/oslo_messaging/tests/drivers/test_impl_kafka.py
index 8d76cdc13..0d90faf66 100644
--- a/oslo_messaging/tests/drivers/test_impl_kafka.py
+++ b/oslo_messaging/tests/drivers/test_impl_kafka.py
@@ -13,7 +13,7 @@
 # under the License.
 import kafka
 import kafka.errors
-import mock
+from six.moves import mock
 import testscenarios
 
 import oslo_messaging
@@ -117,7 +117,7 @@ class TestKafkaDriver(test_utils.BaseTestCase):
         self.driver.listeners.extend(listeners)
         self.driver.cleanup()
         for listener in listeners:
-            listener.close.assert_called_once()
+            listener.close.assert_called_once_with()
 
 
 class TestKafkaConnection(test_utils.BaseTestCase):
diff --git a/oslo_messaging/tests/drivers/zmq/test_zmq_ack_manager.py b/oslo_messaging/tests/drivers/zmq/test_zmq_ack_manager.py
index bea9870ec..918de2792 100644
--- a/oslo_messaging/tests/drivers/zmq/test_zmq_ack_manager.py
+++ b/oslo_messaging/tests/drivers/zmq/test_zmq_ack_manager.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import mock
+from six.moves import mock
 import testtools
 import time
 
diff --git a/oslo_messaging/tests/drivers/zmq/test_zmq_async.py b/oslo_messaging/tests/drivers/zmq/test_zmq_async.py
index 5d8159deb..a4dccd9ec 100644
--- a/oslo_messaging/tests/drivers/zmq/test_zmq_async.py
+++ b/oslo_messaging/tests/drivers/zmq/test_zmq_async.py
@@ -10,7 +10,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import mock
+from six.moves import mock
 import testtools
 
 from oslo_messaging._drivers.zmq_driver.poller import green_poller
diff --git a/oslo_messaging/tests/drivers/zmq/test_zmq_transport_url.py b/oslo_messaging/tests/drivers/zmq/test_zmq_transport_url.py
index 35b2f5221..45df7967b 100644
--- a/oslo_messaging/tests/drivers/zmq/test_zmq_transport_url.py
+++ b/oslo_messaging/tests/drivers/zmq/test_zmq_transport_url.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import mock
+from six.moves import mock
 import testtools
 
 import oslo_messaging
diff --git a/oslo_messaging/tests/notify/test_impl_messaging.py b/oslo_messaging/tests/notify/test_impl_messaging.py
index 3a8eacb90..351410ad2 100644
--- a/oslo_messaging/tests/notify/test_impl_messaging.py
+++ b/oslo_messaging/tests/notify/test_impl_messaging.py
@@ -12,7 +12,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import mock
+from six.moves import mock
 
 from oslo_messaging.tests import utils as test_utils
 
diff --git a/oslo_messaging/tests/rpc/test_client.py b/oslo_messaging/tests/rpc/test_client.py
index 16bf42749..4fd41c575 100755
--- a/oslo_messaging/tests/rpc/test_client.py
+++ b/oslo_messaging/tests/rpc/test_client.py
@@ -13,9 +13,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
-import mock
-
 from oslo_config import cfg
+from six.moves import mock
 import testscenarios
 
 import oslo_messaging
diff --git a/oslo_messaging/tests/rpc/test_server.py b/oslo_messaging/tests/rpc/test_server.py
index 82cdeb8ee..4aa8b36ec 100644
--- a/oslo_messaging/tests/rpc/test_server.py
+++ b/oslo_messaging/tests/rpc/test_server.py
@@ -17,9 +17,9 @@ import eventlet
 import threading
 
 from oslo_config import cfg
+from six.moves import mock
 import testscenarios
 
-import mock
 import oslo_messaging
 from oslo_messaging import rpc
 from oslo_messaging.rpc import server as rpc_server_module
diff --git a/oslo_messaging/tests/test_opts.py b/oslo_messaging/tests/test_opts.py
index f7137388c..06e7d6fd1 100644
--- a/oslo_messaging/tests/test_opts.py
+++ b/oslo_messaging/tests/test_opts.py
@@ -12,11 +12,10 @@
 #    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 six.moves import mock
 import stevedore
 import testtools
 
-import mock
-
 from oslo_messaging import server
 try:
     from oslo_messaging import opts
diff --git a/oslo_messaging/tests/test_transport.py b/oslo_messaging/tests/test_transport.py
index 1c75da50d..71ff9ec4d 100755
--- a/oslo_messaging/tests/test_transport.py
+++ b/oslo_messaging/tests/test_transport.py
@@ -14,9 +14,9 @@
 #    under the License.
 
 import fixtures
-import mock
 from oslo_config import cfg
 import six
+from six.moves import mock
 from stevedore import driver
 import testscenarios