Bladeren bron

Update unit tests, dropping eventlet

Lucian Petrut 2 weken geleden
bovenliggende
commit
7cbcc89f93

+ 1 - 1
coriolis/service.py

@@ -128,7 +128,7 @@ class WSGIService(service.ServiceBase):
             self._workers = (
                 CONF.api_migration_workers or processutils.get_worker_count())
 
-        self._loader = wsgi.Loader(CONF)
+        self._loader = oslo_wsgi.Loader(CONF)
         self._app = self._loader.load_app(name)
 
         bind_addr = (self._host, self._port)

+ 3 - 0
coriolis/tests/__init__.py

@@ -1,6 +1,7 @@
 # Copyright 2024 Cloudbase Solutions Srl
 # All Rights Reserved.
 
+from oslo_service import backend
 from oslotest import mock_fixture
 
 # NOTE(claudiub): this needs to be called before any mock.patch calls are
@@ -8,3 +9,5 @@ from oslotest import mock_fixture
 # the mock.patch autospec issue:
 # https://github.com/testing-cabal/mock/issues/396
 mock_fixture.patch_mock_module()
+
+backend.init_backend(backend.BackendType.THREADING)

+ 8 - 22
coriolis/tests/cron/test_cron.py

@@ -3,7 +3,7 @@
 
 import datetime
 import ddt
-import eventlet
+
 import schedule
 import sys
 import time
@@ -403,7 +403,7 @@ class CronTestCase(test_base.CoriolisBaseTestCase):
             self.cron._jobs
         )
 
-    @mock.patch.object(eventlet, 'spawn')
+    @mock.patch('coriolis.utils.start_thread')
     def test_check_jobs(self, mock_spawn):
         mock_job = mock.Mock()
         mock_job2 = mock.Mock()
@@ -415,7 +415,9 @@ class CronTestCase(test_base.CoriolisBaseTestCase):
 
         self.cron._check_jobs()
 
-        mock_spawn.assert_called_once_with(mock_job.start, self.cron._queue)
+        mock_spawn.assert_called_once_with(
+            mock_job.start,
+            args=[self.cron._queue])
 
     @mock.patch.object(time, 'sleep')
     @mock.patch.object(schedule, 'run_pending')
@@ -474,26 +476,11 @@ class CronTestCase(test_base.CoriolisBaseTestCase):
             self.cron._jobs
         )
 
-    @mock.patch.object(eventlet, 'kill')
-    @mock.patch.object(time, 'sleep')
-    def test_ripper(self, mock_sleep, mock_kill):
-        self.cron._should_stop = True
-        self.cron._eventlets = ['mock_event1', 'mock_event2']
-
-        self.cron._ripper()
-
-        self.assertEqual(
-            [],
-            self.cron._eventlets
-        )
-        mock_kill.assert_has_calls([
-            mock.call('mock_event1'), mock.call('mock_event2')])
-
-    @mock.patch.object(eventlet, 'spawn')
+    @mock.patch('coriolis.utils.start_thread')
     @mock.patch.object(schedule, 'every')
     def test_start(self, mock_every, mock_spawn):
         mock_spawn.side_effect = [
-            'spawn_loop', 'spawn_janitor', 'spawn_result_loop', 'spawn_ripper']
+            'spawn_loop', 'spawn_janitor', 'spawn_result_loop']
 
         self.cron.start()
 
@@ -503,11 +490,10 @@ class CronTestCase(test_base.CoriolisBaseTestCase):
             mock.call(self.cron._loop),
             mock.call(self.cron._janitor),
             mock.call(self.cron._result_loop),
-            mock.call(self.cron._ripper)
         ])
         self.assertEqual(
             ['spawn_loop', 'spawn_janitor', 'spawn_result_loop'],
-            self.cron._eventlets
+            self.cron._threads
         )
 
     def test_stop(self):

+ 22 - 29
coriolis/tests/providers/test_backup_writers.py

@@ -337,20 +337,20 @@ class SSHBackupWriterImplTestCase(test_base.CoriolisBaseTestCase):
         self.assertRaises(exception.CoriolisException, original_send_msg,
                           self.writer, mock.sentinel.data)
 
-    @mock.patch.object(backup_writers, 'eventlet')
+    @mock.patch('coriolis.utils.start_thread')
     @mock.patch.object(backup_writers.SSHBackupWriterImpl, '_encoder')
     @mock.patch.object(backup_writers.SSHBackupWriterImpl, '_sender')
     @mock.patch.object(backup_writers.SSHBackupWriterImpl, '_exec_helper_cmd')
     def test__open(self, mock_exec_helper_cmd, mock_sender, mock_encoder,
-                   mock_eventlet):
+                   mock_start_thread):
         self.writer._open()
 
         mock_exec_helper_cmd.assert_called_once()
-        mock_eventlet.spawn.assert_has_calls(
+        mock_start_thread.assert_has_calls(
             [mock.call(mock_sender), mock.call(mock_encoder),
              mock.call(mock_encoder), mock.call(mock_encoder)])
 
-        self.assertEqual(len(self.writer._encoder_evt), 3)
+        self.assertEqual(len(self.writer._encoder_threads), 3)
 
     def test_seek(self):
         self.writer.seek(mock.sentinel.offset)
@@ -473,32 +473,24 @@ class SSHBackupWriterImplTestCase(test_base.CoriolisBaseTestCase):
         self.assertIsNone(self.writer._ssh)
 
     @mock.patch.object(backup_writers.SSHBackupWriterImpl, '_wait_for_queues')
-    @mock.patch.object(backup_writers, 'eventlet')
-    def test_close_with_sender_evt(self, mock_eventlet, mock_wait_for_queues):
+    def test_close_with_sender_thread(self, mock_wait_for_queues):
         mock_wait_for_queues.return_value = None
-        mock_sender_evt = mock.MagicMock()
-        self.writer._sender_evt = mock_sender_evt
+        self.writer._sender_thread = mock.MagicMock()
         self.writer._ssh = None
 
         self.writer.close()
 
-        mock_eventlet.kill.assert_called_once_with(mock_sender_evt)
-        self.assertIsNone(self.writer._sender_evt)
+        self.assertIsNone(self.writer._sender_thread)
 
     @mock.patch.object(backup_writers.SSHBackupWriterImpl, '_wait_for_queues')
-    @mock.patch.object(backup_writers, 'eventlet')
-    def test_close_with_encoder_evt(self, mock_eventlet, mock_wait_for_queues):
+    def test_close_with_encoder_threads(self, mock_wait_for_queues):
         mock_wait_for_queues.return_value = None
-        mock_encoder_evt = [mock.MagicMock(), mock.MagicMock()]
-        self.writer._encoder_evt = mock_encoder_evt
+        self.writer._encoder_threads = [mock.MagicMock(), mock.MagicMock()]
         self.writer._ssh = None
 
         self.writer.close()
 
-        mock_eventlet.kill.assert_has_calls([
-            mock.call(mock_encoder_evt[0]),
-            mock.call(mock_encoder_evt[1])])
-        self.assertEqual(self.writer._encoder_evt, [])
+        self.assertEqual(self.writer._encoder_threads, [])
 
     def test__handle_exception_with_exit_status(self):
         self.writer._stdout.channel.exit_status_ready.return_value = True
@@ -834,15 +826,15 @@ class HTTPBackupWriterImplTestCase(test_base.CoriolisBaseTestCase):
 
     @mock.patch.object(backup_writers.HTTPBackupWriterImpl, '_init_session')
     @mock.patch.object(backup_writers.HTTPBackupWriterImpl, '_acquire')
-    @mock.patch.object(backup_writers, 'eventlet')
-    def test__open(self, mock_eventlet, mock_acquire, mock_init_session):
+    @mock.patch('coriolis.utils.start_thread')
+    def test__open(self, mock_start_thread, mock_acquire, mock_init_session):
         self.writer._compressor_count = None
 
         self.writer._open()
 
         mock_init_session.assert_called_once()
         mock_acquire.assert_called_once()
-        mock_eventlet.spawn.assert_has_calls(
+        mock_start_thread.assert_has_calls(
             [mock.call(self.writer._sender),
              mock.call(self.writer._compressor)])
 
@@ -850,16 +842,17 @@ class HTTPBackupWriterImplTestCase(test_base.CoriolisBaseTestCase):
 
     @mock.patch.object(backup_writers.HTTPBackupWriterImpl, '_init_session')
     @mock.patch.object(backup_writers.HTTPBackupWriterImpl, '_acquire')
-    @mock.patch.object(backup_writers, 'eventlet')
+    @mock.patch('coriolis.utils.start_thread')
     def test__open_compressor_count_not_none_or_zero(
-            self, mock_eventlet, mock_acquire, mock_init_session):
+            self, mock_start_thread, mock_acquire, mock_init_session):
         self.writer._compressor_count = 2
 
         self.writer._open()
 
         self.assertEqual(
-            len(self.writer._compressor_evt), self.writer._compressor_count)
-        self.assertEqual(mock_eventlet.spawn.call_count, 3)
+            len(self.writer._compressor_threads),
+            self.writer._compressor_count)
+        self.assertEqual(mock_start_thread.call_count, 3)
 
     def test_seek(self):
         self.writer.seek(mock.sentinel.offset)
@@ -1039,17 +1032,17 @@ class HTTPBackupWriterImplTestCase(test_base.CoriolisBaseTestCase):
         self.writer._closing = True
 
         self.writer._session = mock.MagicMock()
-        self.writer._sender_evt = mock.MagicMock()
+        self.writer._sender_thread = mock.MagicMock()
         self.writer._comp_q = mock.MagicMock()
-        self.writer._compressor_evt = [mock.MagicMock(), mock.MagicMock()]
+        self.writer._compressor_threads = [mock.MagicMock(), mock.MagicMock()]
 
         self.writer.close()
 
         mock_wait_for_queues.assert_called_once()
         mock_release.assert_called_once()
         self.assertIsNone(self.writer._session)
-        self.assertIsNone(self.writer._sender_evt)
-        self.assertIsNone(self.writer._compressor_evt)
+        self.assertIsNone(self.writer._sender_thread)
+        self.assertIsNone(self.writer._compressor_threads)
 
     @mock.patch.object(backup_writers.HTTPBackupWriterImpl, '_wait_for_queues')
     @mock.patch.object(backup_writers.HTTPBackupWriterImpl, '_release')

+ 5 - 6
coriolis/tests/taskflow/test_runner.py

@@ -1,8 +1,6 @@
 # Copyright 2023 Cloudbase Solutions Srl
 # All Rights Reserved.
 
-
-import eventlet
 import logging
 import multiprocessing
 import sys
@@ -157,7 +155,7 @@ class TaskFlowRunnerTestCase(test_base.CoriolisBaseTestCase):
         result = self.runner._handle_mp_log_events(mock_p, self.mock_mp_log_q)
         self.assertIsNone(result)
 
-    @mock.patch.object(eventlet, 'spawn')
+    @mock.patch('coriolis.utils.start_thread')
     @mock.patch.object(multiprocessing, "get_context")
     def test_spawn_process_flow(self, mock_get_context, mock_spawn):
         mock_process = mock.Mock()
@@ -175,9 +173,10 @@ class TaskFlowRunnerTestCase(test_base.CoriolisBaseTestCase):
             target=self.runner._run_flow_in_process,
             args=(self.mock_flow, mock_mp_ctx.Queue.return_value, self.store))
         mock_process.start.assert_called_once_with()
-        mock_spawn.assert_called_once_with(self.runner._handle_mp_log_events,
-                                           mock_process,
-                                           mock_mp_ctx.Queue.return_value)
+        mock_spawn.assert_called_once_with(
+            target=self.runner._handle_mp_log_events,
+            args=(mock_process, mock_mp_ctx.Queue.return_value),
+            daemon=True)
 
     @mock.patch.object(runner.TaskFlowRunner, '_spawn_process_flow')
     def test_run_flow_in_background(self, mock_spawn_process_flow):

+ 1 - 1
coriolis/tests/test_rpc.py

@@ -81,7 +81,7 @@ class RpcTestCase(test_base.CoriolisBaseTestCase):
         mock_context_serializer.assert_called_once_with(serializer)
         mock_get_rpc_server.assert_called_once_with(
             mock_get_transport.return_value, target, endpoints,
-            executor='eventlet', serializer=serializer)
+            executor='threading', serializer=serializer)
         self.assertEqual(result, mock_get_rpc_server.return_value)
 
     @mock.patch('coriolis.rpc.messaging.get_transport')

+ 10 - 14
coriolis/tests/test_service.py

@@ -68,7 +68,7 @@ class ServiceTestCase(test_base.CoriolisBaseTestCase):
 class WSGIServiceTestCase(test_base.CoriolisBaseTestCase):
     """Test suite for the Coriolis WSGIService class."""
 
-    @mock.patch.object(service.wsgi.Loader, 'load_app')
+    @mock.patch('oslo_service.wsgi.Loader.load_app')
     @mock.patch.object(service, 'rpc')
     @mock.patch.object(service, 'CONF')
     @mock.patch.object(service.wsgi, 'Server')
@@ -85,11 +85,12 @@ class WSGIServiceTestCase(test_base.CoriolisBaseTestCase):
         mock_rpc.init.assert_called_once_with()
         mock_load_app.assert_called_once_with(mock.sentinel.name)
         mock_server.assert_called_once_with(
-            mock_conf,
-            mock.sentinel.name,
-            mock_load_app.return_value,
-            host=mock_conf.api_migration_listen,
-            port=mock_conf.api_migration_listen_port)
+            server_name=mock.sentinel.name,
+            wsgi_app=mock_load_app.return_value,
+            bind_addr=(
+                mock_conf.api_migration_listen,
+                mock_conf.api_migration_listen_port),
+        )
         self.assertEqual(wsgi_service._host, mock_conf.api_migration_listen)
         self.assertEqual(wsgi_service._port,
                          mock_conf.api_migration_listen_port)
@@ -136,15 +137,11 @@ class WSGIServiceTestCase(test_base.CoriolisBaseTestCase):
     @mock.patch.object(service, 'CONF')
     @mock.patch('oslo_service.wsgi.Loader.load_app')
     @mock.patch('coriolis.rpc.messaging.get_transport')
-    @mock.patch('eventlet.listen')
-    def test_service_methods(self, mock_listen, mock_get_transport,
+    def test_service_methods(self, mock_get_transport,
                              mock_load_app, mock_conf):
         mock_conf.api_migration_workers = 10
         mock_load_app.return_value = mock.MagicMock()
         mock_get_transport.return_value = mock.MagicMock()
-        mock_socket = mock.MagicMock()
-        mock_socket.getsockname.return_value = ('localhost', 8080)
-        mock_listen.return_value = mock_socket
 
         result = service.WSGIService('test_service', None, True)
 
@@ -154,16 +151,15 @@ class WSGIServiceTestCase(test_base.CoriolisBaseTestCase):
                          mock_conf.api_migration_workers)
 
         result.start()
-        result._server.start.assert_called_once()
+        result._server.serve.assert_called_once()
 
         result.stop()
         result._server.stop.assert_called_once()
 
         result.wait()
-        result._server.wait.assert_called_once()
 
+        # no-op, no greenpool to adjust.
         result.reset()
-        result._server.reset.assert_called_once()
 
 
 class MessagingServiceTestCase(test_base.CoriolisBaseTestCase):

+ 7 - 5
coriolis/tests/worker/rpc/test_server.py

@@ -8,7 +8,6 @@ import tempfile
 from unittest import mock
 
 import ddt
-import eventlet
 from oslo_log import log as logging
 import psutil
 from six.moves import queue
@@ -128,10 +127,12 @@ class WorkerServerEndpointTestCase(test_base.CoriolisBaseTestCase):
         mock_get_diagnostics.assert_called_once()
         self.assertEqual(result, expected_result)
 
+    @mock.patch.object(server.WorkerServerEndpoint,
+                       "_wait_for_process")
     @mock.patch.object(server.WorkerServerEndpoint,
                        "_start_process_with_custom_library_paths")
     @mock.patch.object(server, "_task_process")
-    @mock.patch.object(eventlet, "spawn")
+    @mock.patch('coriolis.utils.start_thread')
     @mock.patch.object(server.WorkerServerEndpoint, "_rpc_conductor_client")
     @mock.patch.object(
         server.WorkerServerEndpoint, "_get_extra_library_paths_for_providers"
@@ -145,6 +146,7 @@ class WorkerServerEndpointTestCase(test_base.CoriolisBaseTestCase):
         mock_spawn,
         mock_task_process,
         mock_start_process,
+        mock_wait_process,
     ):
         def call_exec_task_process(report_to_conductor=True):
             return self.server._exec_task_process(
@@ -223,16 +225,16 @@ class WorkerServerEndpointTestCase(test_base.CoriolisBaseTestCase):
         # Returns the spawned process result
         mock_rpc_client.set_task_host.side_effect = None
         result = call_exec_task_process()
-        self.assertEqual(result, mock_spawn.return_value.wait.return_value)
+        self.assertEqual(result, mock_wait_process.return_value)
 
         # if return value is None, raise TaskProcessCanceledException
-        mock_spawn.return_value.wait.return_value = None
+        mock_wait_process.return_value = None
         self.assertRaises(
             exception.TaskProcessCanceledException, call_exec_task_process
         )
 
         # if return value is string, raise TaskProcessException
-        mock_spawn.return_value.wait.return_value = "Test string"
+        mock_wait_process.return_value = "Test string"
         self.assertRaises(
             exception.TaskProcessException, call_exec_task_process
         )