diff --git a/openlp/core/projectors/pjlink.py b/openlp/core/projectors/pjlink.py index ef28f9850..20448a50b 100644 --- a/openlp/core/projectors/pjlink.py +++ b/openlp/core/projectors/pjlink.py @@ -73,7 +73,7 @@ SocketSTate = QtNetwork.QAbstractSocket.SocketState # Add prefix here, but defer linkclass expansion until later when we have the actual # PJLink class for the command -PJLINK_HEADER = '{prefix}{{linkclass}}'.format(prefix=PJLINK_PREFIX) +PJLINK_HEADER = f'{PJLINK_PREFIX}{{linkclass}}' class PJLinkUDP(QtNetwork.QUdpSocket): diff --git a/openlp/core/projectors/pjlinkcommands.py b/openlp/core/projectors/pjlinkcommands.py index 0184e304f..ac879d392 100644 --- a/openlp/core/projectors/pjlinkcommands.py +++ b/openlp/core/projectors/pjlinkcommands.py @@ -24,6 +24,22 @@ processing projector replies. NOTE: PJLink Class (version) checks are handled in the respective PJLink/PJLinkUDP classes. process_clss is the only exception. + +NOTE: Some commands are both commannd replies as well as UDP terminal-initiated status + messages. + + Ex: POWR + + CLSS1 (TCP): controller sends "POWR x", projector replies "POWR=xxxxx" + CLSS2 (UDP): projector sends "POWER=xxxx" + + Inn both instances, the messagege is processed the same. + + For CLSS1, we initiate communication, so we know which projecttor instance + the message is routed to. + + For CLSS2, the terminal initiates communication, so as part of the UDP process + we must find the projector that initiated the message. """ import logging @@ -51,31 +67,26 @@ def process_command(projector, cmd, data): :param cmd: Command to process :param data: Data being processed """ - log.debug('({ip}) Processing command "{cmd}" with data "{data}"'.format(ip=projector.entry.name, - cmd=cmd, - data=data)) + log.debug(f'({projector.entry.name}) Processing command "{cmd}" with data "{data}"') # cmd should already be in uppercase, but data may be in mixed-case. # Due to some replies should stay as mixed-case, validate using separate uppercase check _data = data.upper() # Check if we have a future command not available yet if cmd not in pjlink_functions: - log.warning('({ip}) Unable to process command="{cmd}" (Future option?)'.format(ip=projector.entry.name, - cmd=cmd)) + log.warning(f'({projector.entry.name}) Unable to process command="{cmd}" (Future option?)') return elif _data == 'OK': - log.debug('({ip}) Command "{cmd}" returned OK'.format(ip=projector.entry.name, cmd=cmd)) + log.debug(f'({projector.entry.name}) Command "{cmd}" returned OK') # A command returned successfully, so do a query on command to verify status return S_DATA_OK elif _data in PJLINK_ERRORS: # Oops - projector error - log.error('({ip}) {cmd}: {err}'.format(ip=projector.entry.name, - cmd=cmd, - err=STATUS_MSG[PJLINK_ERRORS[_data]])) + log.error(f'({projector.entry.name}) {cmd}: {STATUS_MSG[PJLINK_ERRORS[_data]]}') return PJLINK_ERRORS[_data] # Command checks already passed - log.debug('({ip}) Calling function for {cmd}'.format(ip=projector.entry.name, cmd=cmd)) + log.debug(f'({projector.entry.name}) Calling function for {cmd}') return pjlink_functions[cmd](projector=projector, data=data) @@ -83,6 +94,8 @@ def process_ackn(projector, data): """ Process the ACKN command. + UDP reply to SRCH command + :param projector: Projector instance :param data: Data in packet """ @@ -339,7 +352,7 @@ def process_lamp(projector, data): def process_lkup(projector, data): """ - Process reply indicating remote is available for connection + Process UDP request indicating remote is available for connection :param projector: Projector instance :param data: Data packet from remote @@ -496,6 +509,8 @@ def process_srch(projector=None, data=None): SRCH is processed by terminals so we ignore any packet. + UDP command to find active CLSS 2 projectors. Reply is ACKN. + :param projector: Projector instance (actually ignored for this command) :param data: Data in packet """ @@ -541,7 +556,7 @@ pjlink_functions = { 'INPT': process_inpt, 'INST': process_inst, 'LAMP': process_lamp, - 'LKUP': process_lkup, # Class 2 (reply only - no cmd) + 'LKUP': process_lkup, # Class 2 (terminal request only - no cmd) 'NAME': process_name, 'PJLINK': process_pjlink, 'POWR': process_powr, diff --git a/tests/openlp_core/projectors/messages/__init__.py b/tests/openlp_core/projectors/messages/__init__.py new file mode 100644 index 000000000..61818bcc0 --- /dev/null +++ b/tests/openlp_core/projectors/messages/__init__.py @@ -0,0 +1,23 @@ +# -*- 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 . # +########################################################################## +""" +:mod tests/openlp_core/projectors/commands: Tests for PJLink commands +""" diff --git a/tests/openlp_core/projectors/messages/test_routing.py b/tests/openlp_core/projectors/messages/test_routing.py new file mode 100644 index 000000000..44dc72cc9 --- /dev/null +++ b/tests/openlp_core/projectors/messages/test_routing.py @@ -0,0 +1,235 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# OpenLP - Open Source Lyrics Projection # +# ---------------------------------------------------------------------- # +# Copyright (c) 2008-2021 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 . # +########################################################################## +""" +Tests for PJLink command routing +""" + +import logging +import openlp.core.projectors.pjlinkcommands + +from unittest.mock import MagicMock, patch + +from openlp.core.projectors.pjlinkcommands import process_command +from openlp.core.projectors.constants import PJLINK_ERRORS, STATUS_CODE, \ + E_AUTHENTICATION, E_UNDEFINED, E_PARAMETER, E_UNAVAILABLE, E_PROJECTOR, \ + S_DATA_OK, STATUS_MSG + +test_module = openlp.core.projectors.pjlinkcommands.__name__ + + +def test_valid_command(pjlink, caplog): + """ + Test valid command routing + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + test_cmd = "CLSS" + test_data = "1" + test_return = None + logs = [(f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Processing command "{test_cmd}" with data "{test_data}"'), + (f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Calling function for {test_cmd}') + ] + caplog.clear() + with patch.dict(openlp.core.projectors.pjlinkcommands.pjlink_functions, + {test_cmd: MagicMock(return_value=None)}) as mock_clss: + # WHEN: called with CLSS command + chk = process_command(projector=pjlink, cmd=test_cmd, data=test_data) + + # THEN: Appropriate log entries should have been made and methods called/not called + assert chk is test_return, f'"{test_data}" reply should have returned {STATUS_CODE[test_return]}' + mock_clss[test_cmd].assert_called_with(projector=pjlink, data=test_data) + assert caplog.record_tuples == logs, 'Log entries mismatch' + + +def test_invalid_command(pjlink, caplog): + """ + Test invalid command + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + test_cmd = "DONTCARE" + test_data = "1" + test_return = None + logs = [(f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Processing command "{test_cmd}" with data "{test_data}"'), + (f'{test_module}', logging.WARNING, + f'({pjlink.name}) Unable to process command="DONTCARE" (Future option?)'), + ] + + # WHEN: called with invalid command and data + caplog.clear() + chk = process_command(projector=pjlink, cmd=test_cmd, data=test_data) + + # THEN: Appropriate log entries should have been made and methods called/not called + assert chk is test_return, 'Invalid command should have returned None' + assert caplog.record_tuples == logs, 'Log entries mismatch' + + +def test_data_ok(pjlink, caplog): + """ + Test data == 'OK' + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + test_cmd = "CLSS" + test_data = "OK" + test_reply = "OK" + test_return = S_DATA_OK + logs = [(f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Processing command "{test_cmd}" with data "{test_data}"'), + (f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Command "{test_cmd}" returned {test_reply}') + ] + + # WHEN: called with OK + caplog.clear() + chk = process_command(projector=pjlink, cmd=test_cmd, data=test_data) + + # THEN: Appropriate log entries should have been made and methods called/not called + assert chk is test_return, f'"{test_data}" reply should have returned {STATUS_CODE[test_return]}' + assert caplog.record_tuples == logs, 'Log entries mismatch' + + +def test_e_authentication(pjlink, caplog): + """ + Test data == ERRA + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + test_error = E_AUTHENTICATION + test_cmd = 'CLSS' + test_data = PJLINK_ERRORS[test_error] + test_reply = STATUS_MSG[test_error] + test_return = test_error + logs = [(f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Processing command "{test_cmd}" with data "{test_data}"'), + (f'{test_module}', logging.ERROR, + f'({pjlink.name}) {test_cmd}: {test_reply}') + ] + # WHEN: called with error + caplog.clear() + chk = process_command(projector=pjlink, cmd=test_cmd, data=test_data) + + # THEN: Appropriate log entries should have been made and methods called/not called + assert chk is test_return, f'"{PJLINK_ERRORS[test_error]}" reply should have returned {STATUS_CODE[test_error]}' + assert caplog.record_tuples == logs, 'Log entries mismatch' + + +def test_e_undefined(pjlink, caplog): + """ + Test data == ERR1 + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + test_error = E_UNDEFINED + test_cmd = 'CLSS' + test_data = PJLINK_ERRORS[test_error] + test_reply = STATUS_MSG[test_error] + test_return = test_error + logs = [(f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Processing command "{test_cmd}" with data "{test_data}"'), + (f'{test_module}', logging.ERROR, + f'({pjlink.name}) {test_cmd}: {test_reply}') + ] + # WHEN: called with error + caplog.clear() + chk = process_command(projector=pjlink, cmd=test_cmd, data=test_data) + + # THEN: Appropriate log entries should have been made and methods called/not called + assert chk is test_return, f'"{PJLINK_ERRORS[test_error]}" reply should have returned {STATUS_CODE[test_error]}' + assert caplog.record_tuples == logs, 'Log entries mismatch' + + +def test_e_parameter(pjlink, caplog): + """ + Test data == ERR2 + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + test_error = E_PARAMETER + test_cmd = 'CLSS' + test_data = PJLINK_ERRORS[test_error] + test_reply = STATUS_MSG[test_error] + test_return = test_error + logs = [(f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Processing command "{test_cmd}" with data "{test_data}"'), + (f'{test_module}', logging.ERROR, + f'({pjlink.name}) {test_cmd}: {test_reply}') + ] + # WHEN: called with error + caplog.clear() + chk = process_command(projector=pjlink, cmd=test_cmd, data=test_data) + + # THEN: Appropriate log entries should have been made and methods called/not called + assert chk is test_return, f'"{PJLINK_ERRORS[test_error]}" reply should have returned {STATUS_CODE[test_error]}' + assert caplog.record_tuples == logs, 'Log entries mismatch' + + +def test_e_unavailable(pjlink, caplog): + """ + Test data == ERR3 + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + test_error = E_UNAVAILABLE + test_cmd = 'CLSS' + test_data = PJLINK_ERRORS[test_error] + test_reply = STATUS_MSG[test_error] + test_return = test_error + logs = [(f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Processing command "{test_cmd}" with data "{test_data}"'), + (f'{test_module}', logging.ERROR, + f'({pjlink.name}) {test_cmd}: {test_reply}') + ] + # WHEN: called with error + caplog.clear() + chk = process_command(projector=pjlink, cmd=test_cmd, data=test_data) + + # THEN: Appropriate log entries should have been made and methods called/not called + assert chk is test_return, f'"{PJLINK_ERRORS[test_error]}" reply should have returned {STATUS_CODE[test_error]}' + assert caplog.record_tuples == logs, 'Log entries mismatch' + + +def test_e_projector(pjlink, caplog): + """ + Test data == ERR4 + """ + # GIVEN: Test setup + caplog.set_level(logging.DEBUG) + test_error = E_PROJECTOR + test_cmd = 'CLSS' + test_data = PJLINK_ERRORS[test_error] + test_reply = STATUS_MSG[test_error] + test_return = test_error + logs = [(f'{test_module}', logging.DEBUG, + f'({pjlink.name}) Processing command "{test_cmd}" with data "{test_data}"'), + (f'{test_module}', logging.ERROR, + f'({pjlink.name}) {test_cmd}: {test_reply}') + ] + # WHEN: called with error + caplog.clear() + chk = process_command(projector=pjlink, cmd=test_cmd, data=test_data) + + # THEN: Appropriate log entries should have been made and methods called/not called + assert chk is test_return, f'"{PJLINK_ERRORS[test_error]}" reply should have returned {STATUS_CODE[test_error]}' + assert caplog.record_tuples == logs, 'Log entries mismatch' diff --git a/tests/openlp_core/projectors/test_projector_bugfixes_01.py b/tests/openlp_core/projectors/test_projector_bugfixes_01.py deleted file mode 100644 index c99d18228..000000000 --- a/tests/openlp_core/projectors/test_projector_bugfixes_01.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- - -########################################################################## -# OpenLP - Open Source Lyrics Projection # -# ---------------------------------------------------------------------- # -# Copyright (c) 2008-2021 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 . # -########################################################################## -""" -Package to test the openlp.core.projectors.pjlink base package. -""" - - -def test_bug_1550891_process_clss_nonstandard_reply_1(): - """ - Bugfix 1550891: CLSS request returns non-standard reply with Optoma/Viewsonic projector - """ - # Test now part of test_projector_pjlink_commands_01 - # Keeping here for bug reference - pass - - -def test_bug_1550891_process_clss_nonstandard_reply_2(): - """ - Bugfix 1550891: CLSS request returns non-standard reply with BenQ projector - """ - # Test now part of test_projector_pjlink_commands_01 - # Keeping here for bug reference - pass - - -def test_bug_1593882_no_pin_authenticated_connection(): - """ - Test bug 1593882 no pin and authenticated request exception - """ - # Test now part of test_projector_pjlink_commands_02 - # Keeping here for bug reference - pass - - -def test_bug_1593883_pjlink_authentication(): - """ - Test bugfix 1593883 pjlink authentication and ticket 92187 - """ - # Test now part of test_projector_pjlink_commands_02 - # Keeping here for bug reference - pass - - -def test_bug_1734275_process_lamp_nonstandard_reply(): - """ - Test bugfix 17342785 non-standard LAMP response with one lamp hours only - """ - # Test now part of test_projector_pjlink_commands_01 - # Keeping here for bug reference - pass diff --git a/tests/openlp_core/projectors/test_projector_command_routing.py b/tests/openlp_core/projectors/test_projector_command_routing.py deleted file mode 100644 index 152681459..000000000 --- a/tests/openlp_core/projectors/test_projector_command_routing.py +++ /dev/null @@ -1,210 +0,0 @@ -# -*- coding: utf-8 -*- - -########################################################################## -# OpenLP - Open Source Lyrics Projection # -# ---------------------------------------------------------------------- # -# Copyright (c) 2008-2021 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 . # -########################################################################## -""" -Package to test the openlp.core.projectors.pjlink command routing. -""" -from unittest.mock import call, patch - -import openlp.core.projectors.pjlink -from openlp.core.projectors.pjlinkcommands import process_command -from openlp.core.projectors.constants import E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED, \ - S_DATA_OK, PJLINK_ERRORS, STATUS_MSG - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_routing_command(mock_log, pjlink): - """ - Test process_command receiving command not in function map - """ - # GIVEN: Test setup - log_warning_text = [] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "1"'.format(ip=pjlink.name)), - call('({ip}) Calling function for CLSS'.format(ip=pjlink.name)), - call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=pjlink.name))] - - # WHEN: called with valid command and data - chk = process_command(projector=pjlink, cmd='CLSS', data='1') - - # THEN: Appropriate log entries should have been made and methods called/not called - mock_log.warning.assert_has_calls(log_warning_text) - mock_log.debug.assert_has_calls(log_debug_text) - assert (chk is None), 'process_clss() should have returned None' - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'process_clss') -@patch.object(openlp.core.projectors.pjlinkcommands, 'pjlink_functions') -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_routing_command_unknown(mock_log, mock_functions, mock_clss, pjlink): - """ - Test process_command receiving command not in function map - """ - # GIVEN: Test setup - log_warning_text = [call('({ip}) Unable to process command="CLSS" ' - '(Future option?)'.format(ip=pjlink.name))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "?"'.format(ip=pjlink.name))] - # Fake CLSS command is not in list - mock_functions.__contains__.return_value = False - - # WHEN: called with unknown command - process_command(projector=pjlink, cmd='CLSS', data='?') - - # THEN: Appropriate log entries should have been made and methods called/not called - mock_log.warning.assert_has_calls(log_warning_text) - mock_log.debug.assert_has_calls(log_debug_text) - assert (mock_functions.__contains__.call_count == 1), 'pjlink_functions should have been accessed only once' - assert (not mock_clss.called), 'Should not have called process_clss' - - -@patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') -@patch.object(openlp.core.projectors.pjlinkcommands, 'process_clss') -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_routing_data_ok(mock_log, mock_clss, mock_send, pjlink): - """ - Test process_command calls function and sets appropriate value(s) in projector instance - """ - # GIVEN: Test setup - log_debug_text = [call('({ip}) Processing command "CLSS" with data "OK"'.format(ip=pjlink.name)), - call('({ip}) Command "CLSS" returned OK'.format(ip=pjlink.name)) - ] - - # WHEN: Command called with OK - chk = process_command(projector=pjlink, cmd='CLSS', data='OK') - - # THEN: Appropriate log entries should have been made and methods called/not called - mock_log.debug.asset_has_calls(log_debug_text) - mock_send.assert_not_called() - mock_clss.assert_not_called() - assert (chk == S_DATA_OK), 'Should have returned S_DATA_OK' - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_routing_pjink_err1(mock_log, pjlink): - """ - Test rouing when PJLink ERR1 received - """ - # GIVEN: Test setup - err_code = E_UNDEFINED - err_msg = STATUS_MSG[err_code] - err_str = PJLINK_ERRORS[err_code] - - log_error_text = [call('({ip}) CLSS: {err}'.format(ip=pjlink.name, err=err_msg))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=pjlink.name, - err=err_str))] - - # WHEN: routing called - chk = process_command(projector=pjlink, cmd='CLSS', data=err_str) - - # THEN: Appropriate log entries should have been made and methods called/not called - mock_log.error.assert_has_calls(log_error_text) - mock_log.debug.assert_has_calls(log_debug_text) - assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code]) - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_routing_pjink_err2(mock_log, pjlink): - """ - Test rouing when PJLink ERR2 received - """ - # GIVEN: Test setup - err_code = E_PARAMETER - err_msg = STATUS_MSG[err_code] - err_str = PJLINK_ERRORS[err_code] - - log_error_text = [call('({ip}) CLSS: {err}'.format(ip=pjlink.name, err=err_msg))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=pjlink.name, - err=err_str))] - - # WHEN: routing called - chk = process_command(projector=pjlink, cmd='CLSS', data=err_str) - - # THEN: Appropriate log entries should have been made and methods called/not called - mock_log.error.assert_has_calls(log_error_text) - mock_log.debug.assert_has_calls(log_debug_text) - assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code]) - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_routing_pjink_err3(mock_log, pjlink): - """ - Test rouing when PJLink ERR3 received - """ - # GIVEN: Test setup - err_code = E_UNAVAILABLE - err_msg = STATUS_MSG[err_code] - err_str = PJLINK_ERRORS[err_code] - - log_error_text = [call('({ip}) CLSS: {err}'.format(ip=pjlink.name, err=err_msg))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=pjlink.name, - err=err_str))] - - # WHEN: routing called - chk = process_command(projector=pjlink, cmd='CLSS', data=err_str) - - # THEN: Appropriate log entries should have been made and methods called/not called - mock_log.error.assert_has_calls(log_error_text) - mock_log.debug.assert_has_calls(log_debug_text) - assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code]) - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_routing_pjink_err4(mock_log, pjlink): - """ - Test rouing when PJLink ERR4 received - """ - # GIVEN: Test setup - err_code = E_PROJECTOR - err_msg = STATUS_MSG[err_code] - err_str = PJLINK_ERRORS[err_code] - - log_error_text = [call('({ip}) CLSS: {err}'.format(ip=pjlink.name, err=err_msg))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=pjlink.name, - err=err_str))] - - # WHEN: routing called - chk = process_command(projector=pjlink, cmd='CLSS', data=err_str) - - # THEN: Appropriate log entries should have been made and methods called/not called - mock_log.error.assert_has_calls(log_error_text) - mock_log.debug.assert_has_calls(log_debug_text) - assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code]) - - -@patch.object(openlp.core.projectors.pjlinkcommands, 'log') -def test_routing_pjink_errA(mock_log, pjlink): - """ - Test rouing when PJLink ERRA received - """ - # GIVEN: Test setup - err_code = E_AUTHENTICATION - err_msg = STATUS_MSG[err_code] - err_str = PJLINK_ERRORS[err_code] - - log_error_text = [call('({ip}) CLSS: {err}'.format(ip=pjlink.name, err=err_msg))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=pjlink.name, - err=err_str))] - - # WHEN: routing called - chk = process_command(projector=pjlink, cmd='CLSS', data=err_str) - - # THEN: Appropriate log entries should have been made and methods called/not called - mock_log.error.assert_has_calls(log_error_text) - mock_log.debug.assert_has_calls(log_debug_text) - assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code])