Merge branch 'projector-manager-tests' into 'master'

refactor tests for projector manager 2022-02-21

See merge request openlp/openlp!420
This commit is contained in:
Tim Bentley 2022-02-24 19:04:00 +00:00
commit 6ee7c33805
10 changed files with 541 additions and 323 deletions

View File

@ -332,9 +332,9 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
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))
log.warning(f'UDP Listener for port {port} already added - skipping')
else:
log.debug('Adding UDP listener on port {port}'.format(port=port))
log.debug(f'Adding UDP listener on port {port}')
self.pjlink_udp[port] = PJLinkUDP(port=port)
Registry().execute('udp_broadcast_add', port=port, callback=self.pjlink_udp[port].check_settings)
@ -344,20 +344,20 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
NOTE: Check if PJLinkUDP port needs to be closed/stopped when deleting
"""
log.debug('Checking for UDP port {port} listener deletion'.format(port=port))
log.debug(f'Checking for UDP port {port} listener deletion')
if port not in self.pjlink_udp:
log.warning('UDP listener for port {port} not there - skipping delete'.format(port=port))
log.warning(f'UDP listener for port {port} not there - skipping delete')
return
keep_port = False
for item in self.projector_list:
if port == item.link.port:
keep_port = True
if keep_port:
log.warning('UDP listener for port {port} needed for other projectors - skipping delete'.format(port=port))
log.warning(f'UDP listener for port {port} needed for other projectors - skipping delete')
return
Registry().execute('udp_broadcast_remove', port=port)
del self.pjlink_udp[port]
log.debug('UDP listener for port {port} deleted'.format(port=port))
log.debug(f'UDP listener for port {port} deleted')
def get_settings(self):
"""
@ -382,7 +382,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
real_projector = item.data(QtCore.Qt.UserRole)
projector_name = str(item.text())
visible = real_projector.link.status_connect >= S_CONNECTED
log.debug('({name}) Building menu - visible = {visible}'.format(name=projector_name, visible=visible))
log.debug(f'({projector_name}) Building menu - visible = {visible}')
self.delete_action.setVisible(True)
self.edit_action.setVisible(True)
self.connect_action.setVisible(not visible)
@ -424,7 +424,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
projectordb=self.projectordb,
edit=edit)
source = source_select_form.exec(projector.link)
log.debug('({ip}) source_select_form() returned {data}'.format(ip=projector.link.ip, data=source))
log.debug(f'({projector.link.ip}) source_select_form() returned {source}')
if source is not None and source > 0:
projector.link.set_input_source(str(source))
return
@ -465,10 +465,10 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
projector = item.data(QtCore.Qt.UserRole)
if QSOCKET_STATE[projector.link.state()] != S_CONNECTED:
try:
log.debug('ProjectorManager: Calling connect_to_host() on "{ip}"'.format(ip=projector.link.ip))
log.debug(f'ProjectorManager: Calling connect_to_host() on "{projector.link.ip}"')
projector.link.connect_to_host()
except Exception:
log.debug('ProjectorManager: "{ip}" already connected - skipping'.format(ip=projector.link.ip))
log.debug(f'ProjectorManager: "{projector.link.ip}" already connected - skipping')
return
def on_connect_projector(self, opt=None):
@ -501,9 +501,9 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
projector = list_item.data(QtCore.Qt.UserRole)
msg = QtWidgets.QMessageBox()
msg.setText(translate('OpenLP.ProjectorManager',
'Delete projector ({ip}) {name}?'.format(ip=projector.link.ip,
name=projector.link.name)))
msg.setInformativeText(translate('OpenLP.ProjectorManager', 'Are you sure you want to delete this projector?'))
f'Delete projector ({projector.link.ip}) {projector.link.name}?'))
msg.setInformativeText(translate('OpenLP.ProjectorManager',
'Are you sure you want to delete this projector?'))
msg.setStandardButtons(msg.Cancel | msg.Ok)
msg.setDefaultButton(msg.Cancel)
ans = msg.exec()
@ -541,16 +541,16 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
new_list = []
for item in self.projector_list:
if item.link.db_item.id == projector.link.db_item.id:
log.debug('Removing projector "{item}"'.format(item=item.link.name))
log.debug(f'Removing projector "{item.link.name}"')
continue
new_list.append(item)
self.projector_list = new_list
list_item = self.projector_list_widget.takeItem(self.projector_list_widget.currentRow())
list_item = None
if not self.projectordb.delete_projector(projector.db_item):
log.warning('Delete projector {item} failed'.format(item=projector.db_item))
log.warning(f'Delete projector {projector.db_item} failed')
for item in self.projector_list:
log.debug('New projector list - item: {ip} {name}'.format(ip=item.link.ip, name=item.link.name))
log.debug(f'New projector list - item: {item.link.ip} {item.link.name}')
self.udp_listen_delete(old_port)
def on_disconnect_projector(self, opt=None):
@ -760,7 +760,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
if start:
item.link.connect_to_host()
for item in self.projector_list:
log.debug('New projector list - item: ({ip}) {name}'.format(ip=item.link.ip, name=item.link.name))
log.debug(f'New projector list - item: ({item.link.ip}) {item.link.name}')
@QtCore.pyqtSlot(str)
def add_projector_from_wizard(self, ip, opts=None):
@ -770,7 +770,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
:param ip: IP address of new record item to find
:param opts: Needed by PyQt5
"""
log.debug('add_projector_from_wizard(ip={ip})'.format(ip=ip))
log.debug(f'add_projector_from_wizard(ip={ip})')
item = self.projectordb.get_projector_by_ip(ip)
self.add_projector(item)
@ -781,7 +781,7 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
:param projector: Projector() instance of projector with updated information
"""
log.debug('edit_projector_from_wizard(ip={ip})'.format(ip=projector.ip))
log.debug(f'edit_projector_from_wizard(ip={projector.ip})')
old_port = self.old_projector.link.port
old_ip = self.old_projector.link.ip
self.old_projector.link.name = projector.name
@ -836,22 +836,22 @@ class ProjectorManager(QtWidgets.QWidget, RegistryBase, UiProjectorManager, LogM
item = list_item
break
if item is None:
log.error('ProjectorManager: Unknown item "{ip}" - not updating status'.format(ip=ip))
log.error(f'ProjectorManager: Unknown item "{ip}" - not updating status')
return
elif item.status == status:
log.debug('ProjectorManager: No status change for "{ip}" - not updating status'.format(ip=ip))
log.debug(f'ProjectorManager: No status change for "{ip}" - not updating status')
return
item.status = status
item.icon = self.status_icons[status]
log.debug('({name}) Updating icon with {code}'.format(name=item.link.name, code=STATUS_CODE[status]))
log.debug(f'({item.link.name}) Updating icon with {STATUS_CODE[status]}')
item.widget.setIcon(item.icon)
return self.update_icons()
def get_toolbar_item(self, name, enabled=False, hidden=False):
item = self.one_toolbar.findChild(QtWidgets.QAction, name)
if item == 0:
log.debug('No item found with name "{name}"'.format(name=name))
log.debug(f'No item found with name "{name}"')
return
item.setVisible(False if hidden else True)
item.setEnabled(True if enabled else False)

View File

@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
:mod tests/openlp_core/projectors: Tests for projector code
"""

View File

@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
:mod tests/openlp_core/projectors/commands: Tests for PJLink commands
"""

View File

@ -19,12 +19,63 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
Package to test the openlp.core.projectors.pjlink command routing.
Fixtures for projector tests
"""
import pytest
from openlp.core.projectors.db import Projector
from unittest.mock import patch
from openlp.core.projectors.db import Projector, ProjectorDB
from openlp.core.projectors.manager import ProjectorManager
from openlp.core.projectors.pjlink import PJLink
from tests.resources.projector.data import TEST1_DATA
from tests.resources.projector.data import TEST_DB, TEST1_DATA
'''
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(...)
'''
@pytest.fixture()
def projector_manager(settings):
with patch('openlp.core.projectors.db.init_url') as mocked_init_url:
mocked_init_url.return_value = 'sqlite:///%s' % TEST_DB
projectordb = ProjectorDB()
proj_manager = ProjectorManager(projectordb=projectordb)
yield proj_manager
projectordb.session.close()
del proj_manager
@pytest.fixture()
def projector_manager_nodb(settings):
proj_manager = ProjectorManager(projectordb=None)
yield proj_manager
del proj_manager
@pytest.fixture()
def projector_manager_mtdb(settings):
with patch('openlp.core.projectors.db.init_url') as mock_url:
mock_url.return_value = 'sqlite:///%s' % TEST_DB
t_db = ProjectorDB()
# Ensure we have an empty DB at the beginning of the test
for itm in t_db.get_projector_all():
t_db.delete_projector(itm)
t_db.session.commit()
t_manager = ProjectorManager(projectordb=t_db)
yield t_manager
t_db.session.close()
del t_db
del t_manager
@pytest.fixture()

View File

@ -0,0 +1,153 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
Test ProjectorManager.bootstrap_* methods
"""
import logging
import openlp.core.projectors.manager
from unittest.mock import DEFAULT, MagicMock, patch
test_module = openlp.core.projectors.manager.__name__
@patch('openlp.core.projectors.manager.ProjectorDB')
def test_bootstrap_initialise(mock_db, projector_manager, caplog):
"""
Test ProjectorManager initializes with existing ProjectorDB instance
"""
# GIVEN: Test setup
caplog.set_level(logging.DEBUG)
logs = [(test_module, logging.DEBUG, 'Using existing ProjectorDB() instance')]
with patch.multiple(projector_manager,
setup_ui=DEFAULT,
get_settings=DEFAULT) as mock_manager:
# WHEN: we call bootstrap_initialise
caplog.clear()
projector_manager.bootstrap_initialise()
# THEN: Appropriate entries and actions
assert caplog.record_tuples == logs, 'Invalid log entries'
mock_manager['setup_ui'].assert_called_once()
mock_manager['get_settings'].assert_called_once()
mock_db.assert_not_called()
@patch('openlp.core.projectors.manager.ProjectorDB')
def test_bootstrap_initialise_nodb(mock_db, projector_manager_nodb, caplog):
"""
Test ProjectorManager initializes with a new ProjectorDB instance
"""
# GIVEN: Test setup
caplog.set_level(logging.DEBUG)
logs = [(test_module, logging.DEBUG, 'Creating new ProjectorDB() instance')]
with patch.multiple(projector_manager_nodb,
setup_ui=DEFAULT,
get_settings=DEFAULT) as mock_manager:
# WHEN: we call bootstrap_initialise
caplog.clear()
projector_manager_nodb.bootstrap_initialise()
# THEN: Appropriate entries and actions
assert caplog.record_tuples == logs, 'Invalid log entries'
mock_manager['setup_ui'].assert_called_once()
mock_manager['get_settings'].assert_called_once()
mock_db.assert_called_once()
@patch('openlp.core.projectors.manager.ProjectorEditForm')
@patch('openlp.core.projectors.manager.QtCore.QTimer')
def test_bootstrap_post_set_up_autostart_false(mock_timer, mocked_edit, projector_manager, settings, caplog):
"""
Test post-initialize calls proper setups
"""
# GIVEN: Test setup
caplog.set_level(logging.DEBUG)
logs = [(test_module, logging.DEBUG, 'Loading all projectors')]
mock_newProjector = MagicMock()
mock_editProjector = MagicMock()
mock_edit = MagicMock()
mock_edit.newProjector = mock_newProjector
mock_edit.editProjector = mock_editProjector
mocked_edit.return_value = mock_edit
settings.setValue('projector/connect on start', False)
projector_manager.bootstrap_initialise()
with patch.multiple(projector_manager,
_load_projectors=DEFAULT,
projector_list_widget=DEFAULT) as mock_manager:
# WHEN: Call to initialize is run
caplog.clear()
projector_manager.bootstrap_post_set_up()
# THEN: verify calls and logs
mock_timer.assert_not_called()
mock_newProjector.connect.assert_called_once()
mock_editProjector.connect.assert_called_once()
mock_manager['_load_projectors'].assert_called_once(),
mock_manager['projector_list_widget'].itemSelectionChanged.connect.assert_called_once()
assert caplog.record_tuples == logs, 'Invalid log entries'
@patch('openlp.core.projectors.manager.ProjectorEditForm')
@patch('openlp.core.projectors.manager.QtCore.QTimer')
def test_bootstrap_post_set_up_autostart_true(mock_timer, mocked_edit, projector_manager, settings, caplog):
"""
Test post-initialize calls proper setups
"""
# GIVEN: Test setup
caplog.set_level(logging.DEBUG)
logs = [(test_module, logging.DEBUG, 'Delaying 1.5 seconds before loading all projectors')]
mock_newProjector = MagicMock()
mock_editProjector = MagicMock()
mock_edit = MagicMock()
mock_edit.newProjector = mock_newProjector
mock_edit.editProjector = mock_editProjector
settings.setValue('projector/connect on start', True)
projector_manager.bootstrap_initialise()
with patch.multiple(projector_manager,
_load_projectors=DEFAULT,
projector_list_widget=DEFAULT) as mock_manager:
mocked_edit.return_value = mock_edit
# WHEN: Call to initialize is run
caplog.clear()
projector_manager.bootstrap_post_set_up()
# THEN: verify calls and logs
mock_timer.assert_called_once()
mock_timer.return_value.singleShot.assert_called_once_with(1500, projector_manager._load_projectors)
mock_newProjector.connect.assert_called_once()
mock_editProjector.connect.assert_called_once()
mock_manager['_load_projectors'].assert_not_called(),
mock_manager['projector_list_widget'].itemSelectionChanged.connect.assert_called_once()
assert caplog.record_tuples == logs, 'Invalid log entries'

View File

@ -0,0 +1,157 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
Test misc. functions with few test paths
"""
from unittest.mock import DEFAULT, patch
from openlp.core.projectors.db import Projector
from tests.resources.projector.data import TEST1_DATA, TEST2_DATA, TEST3_DATA
def test_private_load_projectors(projector_manager_mtdb):
"""
Test that _load_projectors() retrieves all entries from projector database
"""
# GIVEN: Test environment
t_db = projector_manager_mtdb.projectordb # Shortcut helper
for itm in (TEST1_DATA, TEST2_DATA, TEST3_DATA):
t_db.add_projector(Projector(**itm))
t_db.session.commit()
t_list = t_db.get_projector_all()
# Mock to keep from getting event not registered error in Registry()
# during bootstrap_post_set_up()
# Although we're testing _load_projectors, need to mock
# it first to get past bootstrap_post_set_up() before test
with patch.multiple(projector_manager_mtdb,
udp_listen_add=DEFAULT,
udp_listen_delete=DEFAULT,
_load_projectors=DEFAULT) as mock_manager:
# Satisfy Flake8 linting
mock_manager['udp_listen_add'].return_value = None
projector_manager_mtdb.bootstrap_initialise()
projector_manager_mtdb.bootstrap_post_set_up()
# WHEN: Called
projector_manager_mtdb._load_projectors()
assert len(projector_manager_mtdb.projector_list) == len(t_list), \
'Invalid number of entries between check and list'
# Isolate the DB entries used to create projector_manager.projector_list
t_chk = []
for dbitem in projector_manager_mtdb.projector_list:
t_chk.append(dbitem.db_item)
assert t_chk == t_list, 'projector_list DB items do not match test items'
def test_on_edit_input(projector_manager):
"""
Test calling edit projector input GUI from input selection icon makes appropriate calls
"""
# GIVEN: Test environment
with patch.object(projector_manager, 'on_select_input') as mock_edit:
# WHEN: Called
projector_manager.on_edit_input()
# THEN: select input called with edit option
mock_edit.assert_called_with(opt=None, edit=True)
def test_on_add_projector(projector_manager):
"""
Test add new projector edit GUI is called properly
"""
# GIVEN: Test environment
# Mock to keep from getting event not registered error in Registry()
# during bootstrap_post_set_up()
with patch.multiple(projector_manager,
udp_listen_add=DEFAULT,
udp_listen_delete=DEFAULT) as mock_manager:
# Satisfy Flake8 linting
mock_manager['udp_listen_add'].return_value = None
projector_manager.bootstrap_initialise()
projector_manager.bootstrap_post_set_up()
with patch.object(projector_manager, 'projector_form') as mock_form:
# WHEN called
projector_manager.on_add_projector()
# THEN: projector form called
mock_form.exec.assert_called_once()
def test_add_projector_from_wizard(projector_manager):
"""
Test when add projector from GUI, appropriate method is called correctly
"""
# GIVEN: Test environment
with patch.multiple(projector_manager,
projectordb=DEFAULT,
add_projector=DEFAULT) as mock_manager:
t_item = Projector(**TEST1_DATA)
mock_manager['projectordb'].get_projector_by_ip.return_value = t_item
# WHEN: Called
projector_manager.add_projector_from_wizard(ip=t_item.ip)
# THEN: appropriate calls made
mock_manager['add_projector'].assert_called_with(t_item)
def test_get_projector_list(projector_manager_mtdb):
"""
Test get_projector_list() returns valid entries
"""
# GIVEN: Test environment
t_db = projector_manager_mtdb.projectordb # Shortcut helper
for itm in (TEST1_DATA, TEST2_DATA, TEST3_DATA):
t_db.add_projector(Projector(**itm))
t_list = t_db.get_projector_all()
# Mock to keep from getting event not registered error in Registry()
# during bootstrap_post_set_up()
with patch.multiple(projector_manager_mtdb,
udp_listen_add=DEFAULT,
udp_listen_delete=DEFAULT) as mock_manager:
# Satisfy Flake8 linting
mock_manager['udp_listen_add'].return_value = None
projector_manager_mtdb.bootstrap_initialise()
projector_manager_mtdb.bootstrap_post_set_up()
# WHEN: Called
t_chk = projector_manager_mtdb.get_projector_list()
# THEN: DB items for both t_list and projector_list are the same
assert len(t_chk) == len(t_list), 'projector_list length mismatch with test items length'
# Isolate the DB entries used to create projector_manager.projector_list
t_chk_list = []
for dbitem in t_chk:
t_chk_list.append(dbitem.db_item)
assert t_list == t_chk_list, 'projector_list DB items do not match test items'

View File

@ -0,0 +1,133 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
Test ProjectorManager udp methods
"""
import logging
from unittest.mock import MagicMock, patch
from tests.resources.projector.data import FakePJLinkUDP, FakeProjector
def test_udp_listen_add_duplicate(projector_manager, caplog):
"""
Test adding UDP port listener to port already registered
"""
# GIVEN: Initial setup
caplog.set_level(logging.DEBUG)
log_entries = ['UDP Listener for port 10 already added - skipping']
port_list = {10: 'port1', 20: 'port2'}
projector_manager.pjlink_udp = port_list
# WHEN: udp_listen_add is called with duplicate port number
caplog.clear()
projector_manager.udp_listen_add(port=10)
# THEN: Verify log entry and registry entry not called
assert projector_manager.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, mock_udp, projector_manager, caplog):
"""
Test adding new UDP port listener
"""
# GIVEN: Initial setup
caplog.set_level(logging.DEBUG)
mocked_registry = MagicMock()
mock_registry.return_value = mocked_registry
mock_udp.return_value = FakePJLinkUDP()
log_entries = ['Adding UDP listener on port 20']
projector_manager.pjlink_udp = {10: 'port1'}
# WHEN: Adding new listener
caplog.clear()
projector_manager.udp_listen_add(port=20)
# THEN: Appropriate listener and log entries
assert 20 in projector_manager.pjlink_udp, "Port not added"
assert 2 == len(projector_manager.pjlink_udp), "Invalid ports in list"
assert type(projector_manager.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, caplog):
"""
Test deleting UDP port listener not in list
"""
# GIVEN: Initial setup
caplog.set_level(logging.DEBUG)
projector_manager.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.udp_listen_delete(port=20)
# THEN: Log missing port and exit method
assert projector_manager.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, 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.pjlink_udp = {10: 'port1', **port_list}
projector_manager.projector_list = [FakeProjector(port=20)]
# WHEN: deleting a listener
caplog.clear()
projector_manager.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.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, 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.pjlink_udp = port_list
projector_manager.projector_list = [FakeProjector(port=10),
FakeProjector(port=20)]
# WHEN: deleting a listener
caplog.clear()
projector_manager.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.pjlink_udp == port_list, 'Invalid ports in list'

View File

@ -1,251 +0,0 @@
# -*- coding: utf-8 -*-
##########################################################################
# OpenLP - Open Source Lyrics Projection #
# ---------------------------------------------------------------------- #
# Copyright (c) 2008-2022 OpenLP Developers #
# ---------------------------------------------------------------------- #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
##########################################################################
"""
Interface tests to test the themeManager class and related methods.
"""
import pytest
import logging
from unittest.mock import MagicMock, patch
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):
with patch('openlp.core.projectors.db.init_url') as mocked_init_url:
mocked_init_url.return_value = 'sqlite:///%s' % TEST_DB
projectordb = ProjectorDB()
proj_manager = ProjectorManager(projectordb=projectordb)
yield proj_manager
projectordb.session.close()
del proj_manager
@pytest.fixture()
def projector_manager_nodb(settings):
proj_manager = ProjectorManager(projectordb=None)
yield proj_manager
del proj_manager
def test_bootstrap_initialise(projector_manager):
"""
Test initialize calls correct startup functions
"""
# WHEN: we call bootstrap_initialise
projector_manager.bootstrap_initialise()
# THEN: ProjectorDB is setup
assert type(projector_manager.projectordb) == ProjectorDB, \
'Initialization should have created a ProjectorDB() instance'
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.messages[3] == log_entries, "ProjectorManager should have indicated a new DB being created"
def test_bootstrap_post_set_up(projector_manager):
"""
Test post-initialize calls proper setups
"""
# GIVEN: setup mocks
projector_manager._load_projectors = MagicMock()
# WHEN: Call to initialize is run
projector_manager.bootstrap_initialise()
projector_manager.bootstrap_post_set_up()
# THEN: verify calls to retrieve saved projectors and edit page initialized
assert 1 == projector_manager._load_projectors.call_count, \
'Initialization should have called load_projectors()'
assert type(projector_manager.projector_form) == ProjectorEditForm, \
'Initialization should have created a Projector Edit Form'
assert projector_manager.projectordb is projector_manager.projector_form.projectordb, \
'ProjectorEditForm should be using same ProjectorDB() instance as ProjectorManager'
def test_bootstrap_post_set_up_autostart_projector(projector_manager_nodb, caplog):
"""
Test post-initialize calling log and QTimer on autostart
"""
# 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
projector_manager_nodb.bootstrap_post_set_up()
# THEN: verify log entries and timer calls
mock_timer.assert_called_once_with(1500, projector_manager_nodb._load_projectors)
assert caplog.messages[-1] == log_entries, "Invalid log entries"
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)
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=10)
# THEN: Verify log entry and registry entry not called
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, mock_udp, projector_manager_nodb, caplog):
"""
Test adding new UDP port listener
"""
# GIVEN: Initial setup
caplog.set_level(logging.DEBUG)
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=20)
# THEN: Appropriate listener and 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'

View File

@ -283,3 +283,24 @@ TEST_VIDEO_CODES = {
'6Y': 'Internal Y',
'6Z': 'Internal Z'
}
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