# -*- 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 part 1. """ from unittest.mock import MagicMock, call, patch import openlp.core.projectors.pjlink from openlp.core.projectors.pjlinkcommands import process_command from openlp.core.projectors.constants import E_NOT_CONNECTED, E_PARAMETER, E_UNKNOWN_SOCKET_ERROR, QSOCKET_STATE, \ S_CONNECTED, S_CONNECTING, S_NOT_CONNECTED, S_OK, S_ON, STATUS_CODE, STATUS_MSG @patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') def test_status_change(mock_changeStatus, pjlink): """ Test process_command call with ERR2 (Parameter) status """ # GIVEN: Test object # WHEN: process_command is called with "ERR2" status from projector process_command(projector=pjlink, cmd='POWR', data='ERR2') # THEN: change_status should have called change_status with E_UNDEFINED # as first parameter mock_changeStatus.called_with(E_PARAMETER, 'change_status should have been called ' 'with "{}"'.format(STATUS_CODE[E_PARAMETER])) @patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host') def test_socket_abort(mock_disconnect, pjlink): """ Test PJLink.socket_abort calls disconnect_from_host """ # GIVEN: Test object # WHEN: Calling socket_abort pjlink.socket_abort() # THEN: disconnect_from_host should be called assert mock_disconnect.called is True, 'Should have called disconnect_from_host' def test_poll_loop_not_connected(pjlink): """ Test PJLink.poll_loop not connected return """ # GIVEN: Test object pjlink.state = MagicMock() pjlink.timer = MagicMock() pjlink.state.return_value = False pjlink.ConnectedState = True # WHEN: PJLink.poll_loop called pjlink.poll_loop() # THEN: poll_loop should exit without calling any other method assert pjlink.timer.called is False, 'Should have returned without calling any other method' @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') def test_poll_loop_set_interval(mock_send_command, pjlink): """ Test PJLink.poll_loop makes correct calls """ # GIVEN: Test object and data pjlink.state = MagicMock() pjlink.state.return_value = QSOCKET_STATE[S_CONNECTED] pjlink.poll_timer = MagicMock() pjlink.poll_timer.interval.return_value = 10 pjlink.poll_time = 20 pjlink.power = S_ON pjlink.source_available = None pjlink.other_info = None pjlink.manufacturer = None pjlink.model = None pjlink.pjlink_name = None call_list = [ call('POWR'), call('ERST'), call('LAMP'), call('AVMT'), call('INPT'), call('INST'), call('INFO'), call('INF1'), call('INF2'), call('NAME'), ] # WHEN: PJLink.poll_loop is called pjlink.poll_loop() # THEN: proper calls were made to retrieve projector data # First, call to update the timer with the next interval assert pjlink.poll_timer.setInterval.called is True, 'Timer update interval should have been called' # Finally, should have called send_command with a list of projetctor status checks mock_send_command.assert_has_calls(call_list, 'Should have queued projector queries') @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') @patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_change_status_unknown_socket_error(mock_log, mock_changeStatus, mock_UpdateIcons, pjlink): """ Test change_status with connection error """ # GIVEN: Test object pjlink.projector_status = 0 pjlink.status_connect = 0 log_debug_calls = [ call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, status=STATUS_CODE[E_UNKNOWN_SOCKET_ERROR], msg=STATUS_MSG[E_UNKNOWN_SOCKET_ERROR])), call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[E_NOT_CONNECTED], msg=STATUS_MSG[E_NOT_CONNECTED])), call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=STATUS_MSG[S_OK])), call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[E_UNKNOWN_SOCKET_ERROR], msg=STATUS_MSG[E_UNKNOWN_SOCKET_ERROR]))] # WHEN: change_status called with unknown socket error pjlink.change_status(status=E_UNKNOWN_SOCKET_ERROR) # THEN: Proper settings should change and signals sent mock_log.debug.assert_has_calls(log_debug_calls) assert pjlink.projector_status == S_OK, 'Projector status should not have changed' assert pjlink.status_connect == E_NOT_CONNECTED, 'Status connect should be NOT CONNECTED' assert mock_UpdateIcons.emit.called is True, 'Should have called UpdateIcons' mock_changeStatus.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR, STATUS_MSG[E_UNKNOWN_SOCKET_ERROR]) @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') @patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_change_status_connection_status_connecting(mock_log, mock_changeStatus, mock_UpdateIcons, pjlink): """ Test change_status with connecting status """ # GIVEN: Test object pjlink.projector_status = 0 pjlink.status_connect = 0 log_debug_calls = [ call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, status=STATUS_CODE[S_CONNECTING], msg=STATUS_MSG[S_CONNECTING])), call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_CONNECTING], msg=STATUS_MSG[S_CONNECTING])), call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=STATUS_MSG[S_OK])), call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=STATUS_MSG[S_OK]))] # WHEN: change_status called with CONNECTING pjlink.change_status(status=S_CONNECTING) # THEN: Proper settings should change and signals sent mock_log.debug.assert_has_calls(log_debug_calls) mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, STATUS_MSG[S_CONNECTING]) assert pjlink.projector_status == S_OK, 'Projector status should not have changed' assert pjlink.status_connect == S_CONNECTING, 'Status connect should be CONNECTING' assert mock_UpdateIcons.emit.called is True, 'Should have called UpdateIcons' @patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_change_status_connection_status_connected(mock_log, mock_changeStatus, pjlink): """ Test change_status with connected status """ # GIVEN: Test object pjlink.projector_status = 0 pjlink.status_connect = 0 log_debug_calls = [ call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, status=STATUS_CODE[S_CONNECTED], msg=STATUS_MSG[S_CONNECTED])), call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_CONNECTED], msg=STATUS_MSG[S_CONNECTED])), call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=STATUS_MSG[S_OK])), call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=STATUS_MSG[S_OK]))] # WHEN: change_status called with CONNECTED pjlink.change_status(status=S_CONNECTED) # THEN: Proper settings should change and signals sent mock_log.debug.assert_has_calls(log_debug_calls) mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_CONNECTED, 'Connected') assert pjlink.projector_status == S_OK, 'Projector status should not have changed' assert pjlink.status_connect == S_CONNECTED, 'Status connect should be CONNECTED' @patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_change_status_connection_status_with_message(mock_log, mock_changeStatus, pjlink): """ Test change_status with connection status """ # GIVEN: Test object pjlink.projector_status = 0 pjlink.status_connect = 0 test_message = 'Different Status Message than default' log_debug_calls = [ call('({ip}) Changing status to {status} "{msg}"'.format(ip=pjlink.name, status=STATUS_CODE[S_ON], msg=test_message)), call('({ip}) status_connect: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=test_message)), call('({ip}) projector_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_ON], msg=test_message)), call('({ip}) error_status: {code}: "{msg}"'.format(ip=pjlink.name, code=STATUS_CODE[S_OK], msg=test_message))] # WHEN: change_status called with projector ON status pjlink.change_status(status=S_ON, msg=test_message) # THEN: Proper settings should change and signals sent mock_log.debug.assert_has_calls(log_debug_calls) mock_changeStatus.emit.assert_called_once_with(pjlink.ip, S_ON, test_message) assert pjlink.projector_status == S_ON, 'Projector status should be ON' assert pjlink.status_connect == S_OK, 'Status connect should not have changed' @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_av_mute_status(mock_log, mock_send_command, pjlink): """ Test sending command to retrieve shutter/audio state """ # GIVEN: Test object test_data = 'AVMT' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_av_mute_status is called pjlink.get_av_mute_status() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data, priority=False) @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_available_inputs(mock_log, mock_send_command, pjlink): """ Test sending command to retrieve avaliable inputs """ # GIVEN: Test object test_data = 'INST' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_available_inputs is called pjlink.get_available_inputs() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data) @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_error_status(mock_log, mock_send_command, pjlink): """ Test sending command to retrieve projector error status """ # GIVEN: Test object test_data = 'ERST' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_error_status is called pjlink.get_error_status() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data) @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_input_source(mock_log, mock_send_command, pjlink): """ Test sending command to retrieve current input """ # GIVEN: Test object test_data = 'INPT' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_input_source is called pjlink.get_input_source() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data) @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_lamp_status(mock_log, mock_send_command, pjlink): """ Test sending command to retrieve lamp(s) status """ # GIVEN: Test object test_data = 'LAMP' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_input_source is called pjlink.get_lamp_status() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data) @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_manufacturer(mock_log, mock_send_command, pjlink): """ Test sending command to retrieve manufacturer name """ # GIVEN: Test object test_data = 'INF1' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_input_source is called pjlink.get_manufacturer() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data) @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_model(mock_log, mock_send_command, pjlink): """ Test sending command to get model information """ # GIVEN: Test object test_data = 'INF2' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_input_source is called pjlink.get_model() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data) @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_name(mock_log, mock_send_command, pjlink): """ Test sending command to get user-assigned name """ # GIVEN: Test object test_data = 'NAME' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_input_source is called pjlink.get_name() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data) @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_other_info(mock_log, mock_send_command, pjlink): """ Test sending command to retrieve other information """ # GIVEN: Test object test_data = 'INFO' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_input_source is called pjlink.get_other_info() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data) @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') @patch.object(openlp.core.projectors.pjlink, 'log') def test_projector_get_power_status(mock_log, mock_send_command, pjlink): """ Test sending command to retrieve current power state """ # GIVEN: Test object test_data = 'POWR' log_debug_calls = [call('({ip}) Sending {cmd} command'.format(ip=pjlink.name, cmd=test_data))] # WHEN: get_input_source is called pjlink.get_power_status() # THEN: log data and send_command should have been called mock_log.debug.assert_has_calls(log_debug_calls) mock_send_command.assert_called_once_with(cmd=test_data, priority=False) def test_projector_get_status_invalid(pjlink): """ Test to check returned information for error code """ # GIVEN: Test object test_string = 'NaN test' # WHEN: get_status called code, message = pjlink._get_status(status=test_string) # THEN: Proper data should have been returned assert code == -1, 'Should have returned -1 as a bad status check' assert message is None, 'Invalid code type should have returned None for message' def test_projector_get_status_valid(pjlink): """ Test to check returned information for status codes """ # GIVEN: Test object test_message = 'Not Connected' # WHEN: get_status called code, message = pjlink._get_status(status=S_NOT_CONNECTED) # THEN: Proper strings should have been returned assert code == 'S_NOT_CONNECTED', 'Code returned should have been the same code that was sent' assert message == test_message, 'Description of code should have been returned' def test_projector_get_status_unknown(pjlink): """ Test to check returned information for unknown code """ # GIVEN: Test object # WHEN: get_status called code, message = pjlink._get_status(status=9999) # THEN: Proper strings should have been returned assert code is None, 'Code returned should have been the same code that was sent' assert message is None, 'Should have returned None as message'