From 2d0855f9757119238acf8466083cf20037be7617 Mon Sep 17 00:00:00 2001 From: Ken Roberts Date: Mon, 31 Jan 2022 02:36:14 +0000 Subject: [PATCH] Tests for ProjectorManager 2022-01-23 --- openlp/core/projectors/manager.py | 4 + .../projectors/test_projectormanager.py | 139 +++++++++++++++--- 2 files changed, 124 insertions(+), 19 deletions(-) diff --git a/openlp/core/projectors/manager.py b/openlp/core/projectors/manager.py index eb81da5ac..a5972ae0d 100644 --- a/openlp/core/projectors/manager.py +++ b/openlp/core/projectors/manager.py @@ -328,6 +328,8 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM def udp_listen_add(self, port=PJLINK_PORT): """ Add UDP broadcast listener + + NOTE: Check if PJLinkUDP port needs to be started when adding """ if port in self.pjlink_udp: log.warning('UDP Listener for port {port} already added - skipping'.format(port=port)) @@ -339,6 +341,8 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM def udp_listen_delete(self, port): """ Remove a UDP broadcast listener + + NOTE: Check if PJLinkUDP port needs to be closed/stopped when deleting """ log.debug('Checking for UDP port {port} listener deletion'.format(port=port)) if port not in self.pjlink_udp: diff --git a/tests/openlp_core/projectors/test_projectormanager.py b/tests/openlp_core/projectors/test_projectormanager.py index a126d101c..e69ede002 100644 --- a/tests/openlp_core/projectors/test_projectormanager.py +++ b/tests/openlp_core/projectors/test_projectormanager.py @@ -21,17 +21,50 @@ """ Interface tests to test the themeManager class and related methods. """ + import pytest import logging from unittest.mock import MagicMock, patch -from openlp.core.projectors.constants import PJLINK_PORT from openlp.core.projectors.db import ProjectorDB from openlp.core.projectors.editform import ProjectorEditForm from openlp.core.projectors.manager import ProjectorManager from tests.resources.projector.data import TEST_DB +''' +NOTE: Since Registry is a singleton, sleight of hand allows us to verify + calls to Registry.methods() + +@patch(path.to.imported.Registry) +def test_function(mock_registry): + mocked_registry = MagicMock() + mock_registry.return_value = mocked_registry + ... + assert mocked_registry.method.has_call(...) +''' + + +class FakeProjector(object): + """ + Helper test class + """ + def __init__(self, port=4352, name="Faker"): + self.link = self + self.port = port + self.name = name + + +class FakePJLinkUDP(object): + """ + Helper test class + """ + def __init__(self, *args, **kwargs): + pass + + def check_settings(self, *args, **kwargs): + pass + @pytest.fixture() def projector_manager(settings): @@ -67,13 +100,12 @@ def test_bootstrap_initialise_nodb(projector_manager_nodb, caplog): Test log entry creating new projector DB """ caplog.set_level(logging.DEBUG) - + log_entries = 'Creating new ProjectorDB() instance' # WHEN: ProjectorManager created with no DB set caplog.clear() projector_manager_nodb.bootstrap_initialise() # THEN: Log should indicate new DB being created - assert caplog.record_tuples[3] == ('openlp.core.projectors.manager', 10, 'Creating new ProjectorDB() instance'), \ - "ProjectorManager should have indicated a new DB being created" + assert caplog.messages[3] == log_entries, "ProjectorManager should have indicated a new DB being created" def test_bootstrap_post_set_up(projector_manager): @@ -103,6 +135,7 @@ def test_bootstrap_post_set_up_autostart_projector(projector_manager_nodb, caplo # GIVEN: Setup mocks with patch('openlp.core.projectors.manager.QtCore.QTimer.singleShot') as mock_timer: caplog.set_level(logging.DEBUG) + log_entries = 'Delaying 1.5 seconds before loading all projectors' # WHEN: Initializations called projector_manager_nodb.bootstrap_initialise() projector_manager_nodb.autostart = True @@ -110,41 +143,109 @@ def test_bootstrap_post_set_up_autostart_projector(projector_manager_nodb, caplo # THEN: verify log entries and timer calls mock_timer.assert_called_once_with(1500, projector_manager_nodb._load_projectors) - assert caplog.record_tuples[-1] == ('openlp.core.projectors.manager', 10, - 'Delaying 1.5 seconds before loading all projectors'), \ - "Last log entry should be autoloading entry" + assert caplog.messages[-1] == log_entries, "Invalid log entries" -def test_udp_listen_add_duplicate_port(projector_manager_nodb, caplog): +def test_udp_listen_add_duplicate(projector_manager_nodb, caplog): """ Test adding UDP port listener to port already registered """ # GIVEN: Initial setup caplog.set_level(logging.DEBUG) - projector_manager_nodb.pjlink_udp[PJLINK_PORT] = "Something to set index item" + log_entries = ['UDP Listener for port 10 already added - skipping'] + port_list = {10: 'port1', 20: 'port2'} + projector_manager_nodb.pjlink_udp = port_list # WHEN: udp_listen_add is called with duplicate port number caplog.clear() - projector_manager_nodb.udp_listen_add(port=PJLINK_PORT) + projector_manager_nodb.udp_listen_add(port=10) # THEN: Verify log entry and registry entry not called - assert caplog.record_tuples[0] == ('openlp.core.projectors.manager', 30, - 'UDP Listener for port 4352 already added - skipping') + assert projector_manager_nodb.pjlink_udp == port_list, "Invalid ports in list" + assert caplog.messages == log_entries, "Invalid log entries" +@patch('openlp.core.projectors.manager.PJLinkUDP') @patch('openlp.core.projectors.manager.Registry') -def test_udp_listen_add_new(mock_registry, projector_manager_nodb, caplog): +def test_udp_listen_add_new(mock_registry, mock_udp, projector_manager_nodb, caplog): """ Test adding new UDP port listener """ # GIVEN: Initial setup caplog.set_level(logging.DEBUG) - log_entries = [('openlp.core.projectors.manager', 10, 'Adding UDP listener on port 4352'), - ('openlp.core.projectors.pjlink', 10, '(UDP:4352) PJLinkUDP() Initialized')] + mocked_registry = MagicMock() + mock_registry.return_value = mocked_registry + mock_udp.return_value = FakePJLinkUDP() + log_entries = ['Adding UDP listener on port 20'] + projector_manager_nodb.pjlink_udp = {10: 'port1'} # WHEN: Adding new listener caplog.clear() - projector_manager_nodb.udp_listen_add(port=PJLINK_PORT) - + projector_manager_nodb.udp_listen_add(port=20) # THEN: Appropriate listener and log entries - mock_registry.execute.called_with('udp_broadcast_add', port=PJLINK_PORT) - assert caplog.record_tuples == log_entries, 'Invalid log entries' + assert 20 in projector_manager_nodb.pjlink_udp, "Port not added" + assert 2 == len(projector_manager_nodb.pjlink_udp), "Invalid ports in list" + assert type(projector_manager_nodb.pjlink_udp[20]) == FakePJLinkUDP, \ + 'PJLinkUDP instance should have been added' + assert mocked_registry.execute.has_call('udp_broadcast_add', port=20) + assert caplog.messages == log_entries, 'Invalid log entries' + + +def test_udp_listen_delete_missing(projector_manager_nodb, caplog): + """ + Test deleting UDP port listener not in list + """ + # GIVEN: Initial setup + caplog.set_level(logging.DEBUG) + projector_manager_nodb.pjlink_udp = {10: 'port1'} + log_entries = ['Checking for UDP port 20 listener deletion', + 'UDP listener for port 20 not there - skipping delete'] + # WHEN: Deleting port listener from dictinary + projector_manager_nodb.udp_listen_delete(port=20) + # THEN: Log missing port and exit method + assert projector_manager_nodb.pjlink_udp == {10: 'port1'}, "Invalid ports in list" + assert caplog.messages == log_entries, "Invalid log entries" + + +@patch('openlp.core.projectors.manager.Registry') +def test_udp_listen_delete_single(mock_registry, projector_manager_nodb, caplog): + """ + Test deleting UDP listener + """ + # GIVEN: Initial setup + mocked_registry = MagicMock() + mock_registry.return_value = mocked_registry + caplog.set_level(logging.DEBUG) + log_entries = ['Checking for UDP port 10 listener deletion', + 'UDP listener for port 10 deleted'] + port_list = {20: 'port2'} + projector_manager_nodb.pjlink_udp = {10: 'port1', **port_list} + projector_manager_nodb.projector_list = [FakeProjector(port=20)] + # WHEN: deleting a listener + caplog.clear() + projector_manager_nodb.udp_listen_delete(port=10) + # THEN: pjlink_udp and logs should have appropriate entries + assert caplog.messages == log_entries, 'Invalid log entries' + assert projector_manager_nodb.pjlink_udp == port_list, 'Invalid ports in list' + assert mocked_registry.execute.has_call('udp_broadcast_delete', port=10) + + +def test_udp_listen_delete_skip(projector_manager_nodb, caplog): + """ + Test not deleting UDP listener + """ + # GIVEN: Initial setup + caplog.set_level(logging.DEBUG) + log_entries = ['Checking for UDP port 10 listener deletion', + 'UDP listener for port 10 needed for other projectors - skipping delete'] + port_list = {10: 'port1', 20: 'port2'} + projector_manager_nodb.pjlink_udp = port_list + projector_manager_nodb.projector_list = [FakeProjector(port=10), + FakeProjector(port=20)] + # WHEN: deleting a listener + caplog.clear() + projector_manager_nodb.udp_listen_delete(port=10) + print(projector_manager_nodb.pjlink_udp) + print(caplog.record_tuples) + # THEN: pjlink_udp and logs should have appropriate entries + assert caplog.messages == log_entries, 'Invalid log entries' + assert projector_manager_nodb.pjlink_udp == port_list, 'Invalid ports in list'