Пример #1
0
    def test_projector_change_status_connection_status_connecting(self):
        """
        Test change_status with connecting status
        """
        # GIVEN: Test object and mocks
        with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons:

            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
            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'
    def test_process_command_future(self):
        """
        Test command valid but no method to process yet
        """
        # GIVEN: Test object
        with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:

            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
            pjlink.pjlink_functions = MagicMock()
            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 "Huh?"'.format(
                        ip=pjlink.name))
            ]

            # WHEN: Processing a possible future command
            pjlink.process_command(cmd='CLSS', data="Huh?")

            # THEN: Appropriate log entries should have been made and methods called/not called
            mock_log.debug.assert_has_calls(log_debug_text)
            mock_log.warning.assert_has_calls(log_warning_text)
            assert pjlink.pjlink_functions.called is False, 'Should not have accessed pjlink_functions'
            assert mock_process_clss.called is False, 'Should not have called process_clss'
Пример #3
0
    def test_projector_change_status_connection_status_with_message(self):
        """
        Test change_status with connection status
        """
        # GIVEN: Test object and mocks
        with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'changeStatus') as mock_changeStatus:

            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
            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'
    def test_process_command_erra(self):
        """
        Test ERRA - Authentication Error
        """
        # GIVEN: Test object
        with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'process_pjlink') as mock_process_pjlink, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host') as mock_disconnect, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorAuthentication') as mock_authentication:

            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
            log_error_calls = [
                call('({ip}) PJLINK: {msg}'.format(
                    ip=pjlink.name, msg=STATUS_MSG[E_AUTHENTICATION]))
            ]
            log_debug_calls = [
                call('({ip}) Processing command "PJLINK" with data "ERRA"'.
                     format(ip=pjlink.name))
            ]

            # WHEN: process_command called with ERRA
            pjlink.process_command(cmd='PJLINK',
                                   data=PJLINK_ERRORS[E_AUTHENTICATION])

            # THEN: Appropriate log entries should have been made and methods called/not called
            assert mock_disconnect.called is True, 'disconnect_from_host should have been called'
            mock_log.error.assert_has_calls(log_error_calls)
            mock_log.debug.assert_has_calls(log_debug_calls)
            mock_change_status.assert_called_once_with(status=E_AUTHENTICATION)
            mock_authentication.emit.assert_called_once_with(pjlink.name)
            mock_process_pjlink.assert_not_called()
    def test_process_command_err4(self):
        """
        Test ERR3 - Unavailable error
        """
        # GIVEN: Test object
        with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:

            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
            log_error_text = [
                call('({ip}) CLSS: {msg}'.format(ip=pjlink.name,
                                                 msg=STATUS_MSG[E_PROJECTOR]))
            ]
            log_debug_text = [
                call(
                    '({ip}) Processing command "CLSS" with data "ERR4"'.format(
                        ip=pjlink.name)),
                call('({ip}) Calling function for CLSS'.format(ip=pjlink.name))
            ]

            # WHEN: process_command called with ERR4
            pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])

            # THEN: Appropriate log entries should have been made and methods called
            mock_log.error.assert_has_calls(log_error_text)
            mock_log.debug.assert_has_calls(log_debug_text)
            mock_process_clss.assert_called_once_with(
                data=PJLINK_ERRORS[E_PROJECTOR])
Пример #6
0
    def test_poll_loop_not_connected(self):
        """
        Test PJLink.poll_loop not connected return
        """
        # GIVEN: Test object and mocks
        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
        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'
    def test_process_ackn_duplicate(self, mock_log):
        """
        Test process_ackn method with multiple calls with same data
        """
        # TODO: Change this to call pjlink_udp.get_datagram() so ACKN can be processed properly

        # GIVEN: Test setup
        pjlink = PJLink(projector=self.test_list[0])
        check_list = {TEST1_DATA['ip']: {'data': TEST1_DATA['mac_adx'], 'port': PJLINK_PORT}}
        log_warn_calls = [call('(___TEST_ONE___) Host {host} already replied - '
                               'ignoring'.format(host=TEST1_DATA['ip']))]
        log_debug_calls = [call('PJlinkCommands(args=() kwargs={})'),
                           call('(___TEST_ONE___) reset_information() connect status is S_NOT_CONNECTED'),
                           call('(___TEST_ONE___) Processing ACKN packet'),
                           call('(___TEST_ONE___) Adding {host} to ACKN list'.format(host=TEST1_DATA['ip'])),
                           call('(___TEST_ONE___) Processing ACKN packet')]

        # WHEN: process_ackn called twice with same data
        pjlink.process_ackn(data=TEST1_DATA['mac_adx'], host=TEST1_DATA['ip'], port=PJLINK_PORT)
        pjlink.process_ackn(data=TEST1_DATA['mac_adx'], host=TEST1_DATA['ip'], port=PJLINK_PORT)

        # THEN: pjlink_udp.ack_list should equal test_list
        # NOTE: This assert only returns AssertionError - does not list differences. Maybe add a compare function?
        if pjlink.ackn_list != check_list:
            # Check this way so we can print differences to stdout
            print('\nackn_list: ', pjlink.ackn_list)
            print('test_list: ', check_list, '\n')
            assert pjlink.ackn_list == check_list
        mock_log.debug.assert_has_calls(log_debug_calls)
        mock_log.warning.assert_has_calls(log_warn_calls)
    def test_get_data_unknown_command(self, mock_log):
        """
        Test not a valid command
        """
        # GIVEN: Test object
        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
        pjlink.pjlink_functions = MagicMock()
        log_warning_text = [
            call('({ip}) get_data(): Invalid packet - '
                 'unknown command "UNKN"'.format(ip=pjlink.name))
        ]
        log_debug_text = [
            call(
                'PJlink(projector="< Projector(id="None", ip="111.111.111.111", port="1111", '
                'mac_adx="11:11:11:11:11:11", pin="1111", name="___TEST_ONE___", '
                'location="location one", notes="notes one", pjlink_name="None", '
                'pjlink_class="None", manufacturer="None", model="None", serial_no="Serial Number 1", '
                'other="None", sources="None", source_list="[]", model_filter="Filter type 1", '
                'model_lamp="Lamp type 1", sw_version="Version 1") >", '
                'args="()" kwargs="{\'no_poll\': True}")'),
            call('PJlinkCommands(args=() kwargs={})'),
            call(
                '(___TEST_ONE___) reset_information() connect status is S_NOT_CONNECTED'
            ),
            call('(___TEST_ONE___) get_data(buffer="%1UNKN=Huh?"'),
            call('(___TEST_ONE___) get_data(): Checking new data "%1UNKN=Huh?"'
                 ),
            call('(___TEST_ONE___) get_data() header="%1UNKN" data="Huh?"'),
            call('(___TEST_ONE___) get_data() version="1" cmd="UNKN"'),
            call(
                '(___TEST_ONE___) Cleaning buffer - msg = "get_data(): Invalid packet - '
                'unknown command "UNKN""'),
            call(
                '(___TEST_ONE___) Finished cleaning buffer - 0 bytes dropped'),
            call(
                '(___TEST_ONE___) _send_command(): Nothing to send - returning'
            )
        ]

        # WHEN: get_data called with an unknown command
        pjlink.get_data(buff='{prefix}1UNKN=Huh?'.format(prefix=PJLINK_PREFIX))

        # 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 pjlink.pjlink_functions.called is False, 'Should not have accessed pjlink_functions'
    def test_process_pjlink_authenticate_pin_not_set_error(self):
        """
        Test process_pjlink authentication but pin not set
        """
        # GIVEN: Initial mocks and data
        mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
        mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
        mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()

        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
        pjlink.pin = None
        log_check = [call('({ip}) Authenticate connection but no PIN - aborting'.format(ip=pjlink.name)), ]

        # WHEN: process_pjlink called with no salt
        pjlink.process_pjlink(data='1 {salt}'.format(salt=TEST_SALT))

        # THEN: socket should be closed and invalid data logged
        mock_log.error.assert_has_calls(log_check)
        assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once'
        mock_send_command.assert_not_called()
    def test_process_pjlink_normal_with_salt_error(self):
        """
        Test process_pjlinnk called with no authentication but pin is set
        """
        # GIVEN: Initial mocks and data
        mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
        mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
        mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()

        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
        pjlink.pin = TEST_PIN
        log_check = [call('({ip}) Normal connection with extra information - aborting'.format(ip=pjlink.name)), ]

        # WHEN: process_pjlink called with invalid authentication scheme
        pjlink.process_pjlink(data='0 {salt}'.format(salt=TEST_SALT))

        # THEN: Proper calls should be made
        mock_log.error.assert_has_calls(log_check)
        assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once'
        mock_send_command.assert_not_called()
Пример #11
0
    def test_projector_get_status_unknown(self):
        """
        Test to check returned information for unknown code
        """
        # GIVEN: Test object
        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)

        # 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'
Пример #12
0
    def test_socket_abort(self):
        """
        Test PJLink.socket_abort calls disconnect_from_host
        """
        # GIVEN: Test object
        with patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host') as mock_disconnect:
            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)

            # 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'
Пример #13
0
    def test_projector_get_status_invalid(self):
        """
        Test to check returned information for error code
        """
        # GIVEN: Test object
        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
        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'
Пример #14
0
    def test_projector_get_status_valid(self):
        """
        Test to check returned information for status codes
        """
        # GIVEN: Test object
        test_message = 'Not Connected'
        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)

        # 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_local_send_command_no_data(self, mock_log):
        """
        Test _send_command with no data to send
        """
        # GIVEN: Test object
        log_debug_calls = [
            call(
                'PJlink(projector="< Projector(id="None", ip="111.111.111.111", port="1111", '
                'mac_adx="11:11:11:11:11:11", pin="1111", name="___TEST_ONE___", '
                'location="location one", notes="notes one", pjlink_name="None", '
                'pjlink_class="None", manufacturer="None", model="None", '
                'serial_no="Serial Number 1", other="None", sources="None", source_list="[]", '
                'model_filter="Filter type 1", model_lamp="Lamp type 1", '
                'sw_version="Version 1") >", args="()" kwargs="{\'no_poll\': True}")'
            ),
            call('PJlinkCommands(args=() kwargs={})'),
            call(
                '(___TEST_ONE___) reset_information() connect status is S_NOT_CONNECTED'
            ),
            call(
                '(___TEST_ONE___) _send_command(): Nothing to send - returning'
            )
        ]

        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
        pjlink.send_queue = []
        pjlink.priority_queue = []

        # WHEN: _send_command called with no data and queue's emtpy
        # Patch here since pjlink does not have socket_timer until after instantiation
        with patch.object(pjlink, 'socket_timer') as mock_timer:
            pjlink._send_command(data=None, utf8=False)

            # THEN:
            mock_log.debug.assert_has_calls(log_debug_calls)
            assert mock_timer.called is False
    def test_send_command_no_data(self, mock_log, mock_send_command,
                                  mock_reset, mock_state):
        """
        Test _send_command with no data to send
        """
        # GIVEN: Test object
        log_warning_calls = [
            call('({ip}) send_command(): Not connected - returning'.format(
                ip=TEST1_DATA['name']))
        ]

        log_debug_calls = [
            call(
                'PJlink(projector="< Projector(id="None", ip="111.111.111.111", port="1111", '
                'mac_adx="11:11:11:11:11:11", pin="1111", name="___TEST_ONE___", '
                'location="location one", notes="notes one", pjlink_name="None", '
                'pjlink_class="None", manufacturer="None", model="None", '
                'serial_no="Serial Number 1", other="None", sources="None", source_list="[]", '
                'model_filter="Filter type 1", model_lamp="Lamp type 1", '
                'sw_version="Version 1") >", args="()" kwargs="{\'no_poll\': True}")'
            ),
            call('PJlinkCommands(args=() kwargs={})')
        ]
        mock_state.return_value = S_NOT_CONNECTED
        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
        pjlink.send_queue = []
        pjlink.priority_queue = []

        # WHEN: _send_command called with no data and queue's empty
        pjlink.send_command(cmd='DONTCARE')

        # THEN:
        mock_log.debug.assert_has_calls(log_debug_calls)
        mock_log.warning.assert_has_calls(log_warning_calls)
        assert mock_reset.called is True
        assert mock_reset.called is True
    def test_process_pjlink_normal(self):
        """
        Test initial connection prompt with no authentication
        """
        # GIVEN: Initial mocks and data
        mock_log = patch.object(openlp.core.projectors.pjlink, "log").start()
        mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
        mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()
        mock_readyRead = patch('openlp.core.projectors.pjlink.PJLink.readyRead').start()
        mock_change_status = patch('openlp.core.projectors.pjlink.PJLink.change_status').start()

        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
        pjlink.pin = None
        log_check = [call('({ip}) process_pjlink(): Sending "CLSS" initial command'.format(ip=pjlink.name)), ]

        # WHEN: process_pjlink called with no authentication required
        pjlink.process_pjlink(data="0")

        # THEN: proper processing should have occured
        mock_log.debug.has_calls(log_check)
        mock_disconnect_from_host.assert_not_called()
        assert 1 == mock_readyRead.connect.call_count, 'Should have only been called once'
        mock_change_status.assert_called_once_with(S_CONNECTED)
        mock_send_command.assert_called_with(cmd='CLSS', priority=True, salt=None)
Пример #18
0
    def test_status_change(self):
        """
        Test process_command call with ERR2 (Parameter) status
        """
        # GIVEN: Test object
        with patch('openlp.core.projectors.pjlink.PJLink.changeStatus') as mock_changeStatus:

            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)

            # WHEN: process_command is called with "ERR2" status from projector
            pjlink.process_command('POWR', '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]))
Пример #19
0
    def test_projector_get_power_status(self):
        """
        Test sending command to retrieve current power state
        """
        # GIVEN: Test object and mocks
        with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command:
            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
            test_data = 'POWR'
            log_debug_calls = [call('({ip}) reset_information() connect status is '
                                    '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])),
                               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_process_pjlink_invalid_authentication_scheme_length_error(self):
        """
        Test initial connection prompt with authentication scheme longer than 1 character
        """
        # GIVEN: Initial mocks and data
        mock_log = patch.object(openlp.core.projectors.pjlink, 'log').start()
        mock_disconnect_from_host = patch('openlp.core.projectors.pjlink.PJLink.disconnect_from_host').start()
        mock_send_command = patch('openlp.core.projectors.pjlink.PJLink.send_command').start()

        pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
        log_check = [call('({ip}) Invalid initial authentication scheme - aborting'.format(ip=pjlink.name)), ]

        # WHEN: process_pjlink called with invalid authentication scheme
        pjlink.process_pjlink(data='01')

        # THEN: socket should be closed and invalid data logged
        mock_log.error.assert_has_calls(log_check)
        assert 1 == mock_disconnect_from_host.call_count, 'Should have only been called once'
        mock_send_command.assert_not_called()
    def test_process_command_call_clss(self):
        """
        Test process_command calls proper function
        """
        # GIVEN: Test object and mocks
        with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \
                patch.object(openlp.core.projectors.pjlink.PJLink, 'process_clss') as mock_process_clss:

            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
            log_debug_calls = [
                call('({ip}) Processing command "CLSS" with data "1"'.format(
                    ip=pjlink.name)),
                call('({ip}) Calling function for CLSS'.format(ip=pjlink.name))
            ]

            # WHEN: process_command is called with valid function and data
            pjlink.process_command(cmd='CLSS', data='1')

            # THEN: Appropriate log entries should have been made and methods called
            mock_log.debug.assert_has_calls(log_debug_calls)
            mock_process_clss.assert_called_once_with(data='1')
Пример #22
0
 def setUp(self):
     """
     Setup test environment
     """
     self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
Пример #23
0
class TestPJLinkRouting(TestCase):
    """
    Tests for the PJLink module command routing
    """
    def setUp(self):
        """
        Setup test environment
        """
        self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)

    def tearDown(self):
        """
        Reset test environment
        """
        del (self.pjlink)

    @patch.object(openlp.core.projectors.pjlinkcommands, 'process_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_projector_get_data_invalid_version(self, mock_log,
                                                mock_process_cmd):
        """
        Test projector received valid command invalid version
        """
        # GIVEN: Test object
        log_warning_text = [
            call('({ip}) _send_command(): Nothing to send - returning'.format(
                ip=self.pjlink.name)),
            call('({ip}) get_data() Command reply version does not match '
                 'a valid command version'.format(ip=self.pjlink.name))
        ]
        log_debug_text = [
            call('({ip}) get_data(buffer="{pre}XCLSS=X"'.format(
                ip=self.pjlink.name, pre=PJLINK_PREFIX)),
            call('({ip}) get_data(): Checking new data "{pre}XCLSS=X"'.format(
                ip=self.pjlink.name, pre=PJLINK_PREFIX)),
            call('({ip}) get_data() header="{pre}XCLSS" data="X"'.format(
                ip=self.pjlink.name, pre=PJLINK_PREFIX)),
            call('({ip}) get_data() version="X" cmd="CLSS" data="X"'.format(
                ip=self.pjlink.name)),
            call(
                '({ip}) Cleaning buffer - msg = "get_data() Command reply version does '
                'not match a valid command version"'.format(
                    ip=self.pjlink.name)),
            call('({ip}) Finished cleaning buffer - 0 bytes dropped'.format(
                ip=self.pjlink.name))
        ]
        # WHEN: get_data called with an unknown command
        self.pjlink.get_data(buff='{prefix}XCLSS=X'.format(
            prefix=PJLINK_PREFIX))

        # 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_process_cmd.call_count == 0
                ), 'process_command should not have been called'

    @patch.object(openlp.core.projectors.pjlinkcommands, 'process_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_projector_get_data_unknown_command(self, mock_log,
                                                mock_process_cmd):
        """
        Test projector receiving invalid command
        """
        # GIVEN: Test object
        log_warning_text = [
            call('({ip}) _send_command(): Nothing to send - '
                 'returning'.format(ip=self.pjlink.name)),
            call('({ip}) get_data(): Invalid packet - '
                 'unknown command "UNKN"'.format(ip=self.pjlink.name))
        ]
        log_debug_text = [
            call('({ip}) get_data(buffer="{pre}1UNKN=Huh?"'.format(
                ip=self.pjlink.name, pre=PJLINK_PREFIX)),
            call('({ip}) get_data(): Checking new data "{pre}1UNKN=Huh?"'.
                 format(ip=self.pjlink.name, pre=PJLINK_PREFIX)),
            call('({ip}) get_data() header="{pre}1UNKN" data="Huh?"'.format(
                ip=self.pjlink.name, pre=PJLINK_PREFIX)),
            call('({ip}) get_data() version="1" cmd="UNKN" data="Huh?"'.format(
                ip=self.pjlink.name)),
            call(
                '({ip}) Cleaning buffer - msg = "get_data(): Invalid packet - '
                'unknown command "UNKN""'.format(ip=self.pjlink.name)),
            call('({ip}) Finished cleaning buffer - 0 bytes dropped'.format(
                ip=self.pjlink.name))
        ]

        # WHEN: get_data called with an unknown command
        self.pjlink.get_data(buff='{prefix}1UNKN=Huh?'.format(
            prefix=PJLINK_PREFIX))

        # 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_process_cmd.call_count == 0
                ), 'process_command should not have been called'

    @patch.object(openlp.core.projectors.pjlinkcommands, 'process_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_projector_get_data_version_mismatch(self, mock_log,
                                                 mock_process_cmd):
        """
        Test projector received valid command with command version higher than projector
        """
        # GIVEN: Test object
        log_warning_text = [
            call('({ip}) _send_command(): Nothing to send - returning'.format(
                ip=self.pjlink.name)),
            call(
                '({ip}) get_data(): Projector returned class reply higher than projector '
                'stated class'.format(ip=self.pjlink.name))
        ]

        log_debug_text = [
            call('({ip}) get_data(buffer="{pre}2ACKN=X"'.format(
                ip=self.pjlink.name, pre=PJLINK_PREFIX)),
            call('({ip}) get_data(): Checking new data "{pre}2ACKN=X"'.format(
                ip=self.pjlink.name, pre=PJLINK_PREFIX)),
            call('({ip}) get_data() header="{pre}2ACKN" data="X"'.format(
                ip=self.pjlink.name, pre=PJLINK_PREFIX)),
            call('({ip}) get_data() version="2" cmd="ACKN" data="X"'.format(
                ip=self.pjlink.name))
        ]
        self.pjlink.pjlink_class = '1'

        # WHEN: get_data called with an unknown command
        self.pjlink.get_data(buff='{prefix}2ACKN=X'.format(
            prefix=PJLINK_PREFIX))

        # 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_process_cmd.call_count == 0
                ), 'process_command should not have been called'
Пример #24
0
class TestPJLinkBase(TestCase):
    """
    Tests for the PJLink module
    """
    def setUp(self):
        """
        Initialize test state(s)
        """
        # Default PJLink instance for tests
        self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)

    def tearDown(self):
        """
        Cleanup test state(s)
        """
        del (self.pjlink)

    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_projector_reset_information(self, mock_log):
        """
        Test reset_information() resets all information and stops timers
        """
        # GIVEN: Test object
        log_debug_calls = [
            call('({ip}) reset_information() connect status is '
                 'S_NOT_CONNECTED'.format(ip=self.pjlink.name)),
            call('({ip}): Calling poll_timer.stop()'.format(
                ip=self.pjlink.name)),
            call('({ip}): Calling socket_timer.stop()'.format(
                ip=self.pjlink.name)),
            call('({ip}): Calling status_timer.stop()'.format(
                ip=self.pjlink.name))
        ]

        # Attributes not available until instantiation, so mock here
        with patch.object(self.pjlink, 'socket_timer') as mock_socket_timer, \
                patch.object(self.pjlink, 'status_timer') as mock_status_timer, \
                patch.object(self.pjlink, 'poll_timer') as mock_poll_timer, \
                patch.object(self.pjlink, 'state') as mock_state:
            mock_state.return_value = QSOCKET_STATE[S_NOT_CONNECTED]
            # Set attributes to something other than None or {} or []
            self.pjlink.fan = True
            self.pjlink.filter_time = True
            self.pjlink.lamp = True
            self.pjlink.mac_adx_received = 'Some random MAC'
            self.pjlink.manufacturer = 'PJLINK'
            self.pjlink.model = '1'
            self.pjlink.model_filter = 'Filter'
            self.pjlink.model_lamp = 'Lamp'
            self.pjlink.mute = True
            self.pjlink.other_info = 'Another Test'
            self.pjlink.pjlink_class = 2
            self.pjlink.pjlink_name = 'OPENLPTEST'
            self.pjlink.power = S_ON
            self.pjlink.projector_errors = {'test1': True, 'test2': False}
            self.pjlink.serial_no = 'Some Number'
            self.pjlink.serial_no_received = 'Some Other Number'
            self.pjlink.sw_version = 'Some Version'
            self.pjlink.sw_version_received = 'Some Other Version'
            self.pjlink.shutter = True
            self.pjlink.source_available = True
            self.pjlink.source = True
            self.pjlink.status_timer_checks = {
                'test1': object(),
                'test2': object()
            }
            self.pjlink.send_busy = False
            self.pjlink.send_queue = ['test1', 'test2']
            self.pjlink.priority_queue = ['test1', 'test2']

            # WHEN: reset_information() is called
            self.pjlink.reset_information()

            # THEN: All information should be reset and timers stopped
            mock_log.debug.assert_has_calls(log_debug_calls)
            assert self.pjlink.fan is None, 'fan should be None'
            assert self.pjlink.filter_time is None, 'filter_time should be None'
            assert self.pjlink.lamp is None, 'lamp should be None'
            assert self.pjlink.mac_adx_received is None, 'mac_adx_received should be None'
            assert self.pjlink.manufacturer is None, 'manufacturer should be None'
            assert self.pjlink.model is None, 'model should be None'
            assert self.pjlink.model_filter is None, 'model_filter should be None'
            assert self.pjlink.model_lamp is None, 'model_lamp should be None'
            assert not self.pjlink.mute, 'mute should be False'
            assert self.pjlink.other_info is None, 'other should be None'
            assert self.pjlink.pjlink_class == PJLINK_CLASS, 'pjlink_class should be {cls}'.format(
                cls=PJLINK_CLASS)
            assert self.pjlink.pjlink_name is None, 'pjlink_name should be None'
            assert self.pjlink.power == S_OFF, 'power should be {data}'.format(
                data=STATUS_CODE[S_OFF])
            assert self.pjlink.projector_errors == {}, 'projector_errors should be an empty dict'
            assert self.pjlink.serial_no is None, 'serial_no should be None'
            assert self.pjlink.serial_no_received is None, 'serial_no_received should be None'
            assert self.pjlink.sw_version is None, 'sw_version should be None'
            assert self.pjlink.sw_version_received is None, 'sw_version_received should be None'
            assert not self.pjlink.shutter, 'shutter should be False'
            assert self.pjlink.source_available is None, 'source_available should be None'
            assert self.pjlink.source is None, 'source should be None'
            assert self.pjlink.status_timer_checks == {}, 'status_timer_checks should be an empty dict'
            assert not self.pjlink.send_busy, 'send_busy should be False'
            assert self.pjlink.send_queue == [], 'send_queue should be an empty list'
            assert self.pjlink.priority_queue == [], 'priority_queue should be an empty list'
            assert mock_socket_timer.stop.called, 'socket_timer.stop() should have been called'
            assert mock_status_timer.stop.called, 'status_timer.stop() should have been called'
            assert mock_poll_timer.stop.called, 'poll_timer.stop() should have been called'
Пример #25
0
    def test_poll_loop_set_interval(self):
        """
        Test PJLink.poll_loop makes correct calls
        """
        # GIVEN: Mocks and test data
        with patch('openlp.core.projectors.pjlink.PJLink.send_command') as mock_send_command:

            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
            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')
    def test_projector_reset_information(self):
        """
        Test reset_information() resets all information and stops timers
        """
        # GIVEN: Test object
        with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log:
            pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
            log_debug_calls = [call('({ip}): Calling poll_timer.stop()'.format(ip=pjlink.name)),
                               call('({ip}): Calling socket_timer.stop()'.format(ip=pjlink.name))]
            # timer and socket_timer not available until instantiation, so mock here
            with patch.object(pjlink, 'socket_timer') as mock_socket_timer, \
                    patch.object(pjlink, 'poll_timer') as mock_timer:

                pjlink.power = S_ON
                pjlink.pjlink_name = 'OPENLPTEST'
                pjlink.manufacturer = 'PJLINK'
                pjlink.model = '1'
                pjlink.shutter = True
                pjlink.mute = True
                pjlink.lamp = True
                pjlink.fan = True
                pjlink.source_available = True
                pjlink.other_info = 'ANOTHER TEST'
                pjlink.send_queue = True
                pjlink.send_busy = True

                # WHEN: reset_information() is called
                pjlink.reset_information()

                # THEN: All information should be reset and timers stopped
                assert pjlink.power == S_OFF, 'Projector power should be OFF'
                assert pjlink.pjlink_name is None, 'Projector pjlink_name should be None'
                assert pjlink.manufacturer is None, 'Projector manufacturer should be None'
                assert pjlink.model is None, 'Projector model should be None'
                assert pjlink.shutter is None, 'Projector shutter should be None'
                assert pjlink.mute is None, 'Projector shuttter should be None'
                assert pjlink.lamp is None, 'Projector lamp should be None'
                assert pjlink.fan is None, 'Projector fan should be None'
                assert pjlink.source_available is None, 'Projector source_available should be None'
                assert pjlink.source is None, 'Projector source should be None'
                assert pjlink.other_info is None, 'Projector other_info should be None'
                assert pjlink.send_queue == [], 'Projector send_queue should be an empty list'
                assert pjlink.send_busy is False, 'Projector send_busy should be False'
                assert mock_timer.stop.called is True, 'Projector timer.stop()  should have been called'
                assert mock_socket_timer.stop.called is True, 'Projector socket_timer.stop() should have been called'
                mock_log.debug.assert_has_calls(log_debug_calls)
Пример #27
0
 def setUp(self):
     """
     Initialize test state(s)
     """
     # Default PJLink instance for tests
     self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
Пример #28
0
 def setUp(self):
     """
     Initial test setup
     """
     self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)
Пример #29
0
class TestPJLinkBase(TestCase):
    """
    Tests for the PJLink module
    """
    def setUp(self):
        """
        Initialize test state(s)
        """
        # Default PJLink instance for tests
        self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True)

    def tearDown(self):
        """
        Cleanup test state(s)
        """
        del (self.pjlink)

    # ------------ Test PJLink._underscore_send_command ----------
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_local_send_command_network_error(self, mock_log, mock_reset,
                                              mock_state, mock_disconnect,
                                              mock_write, mock_change_status):
        """
        Test _underscore_send_command when possible network error occured
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = [
            call('({ip}) _send_command(): -1 received - '
                 'disconnecting from host'.format(ip=self.pjlink.name))
        ]
        log_debug_calls = [
            call('({ip}) _send_command(data="None")'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): priority_queue: []'.format(
                ip=self.pjlink.name)),
            call("({ip}) _send_command(): send_queue: ['{data}\\r']".format(
                ip=self.pjlink.name, data=test_command.strip())),
            call('({ip}) _send_command(): Connection status: S_CONNECTED'.
                 format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Getting normal queued packet'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): Sending "{data}"'.format(
                ip=self.pjlink.name, data=test_command.strip()))
        ]

        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        mock_write.return_value = -1
        self.pjlink.send_queue = [test_command]
        self.pjlink.priority_queue = []

        # WHEN: _send_command called with no data and queue's emtpy
        # Patch some attributes here since they are not available until after instantiation
        with patch.object(self.pjlink, 'socket_timer') as mock_timer, \
                patch.object(self.pjlink, 'waitForBytesWritten') as mock_waitBytes:
            mock_waitBytes.return_value = True
            self.pjlink._send_command()

            # THEN:
            mock_log.error.assert_has_calls(log_error_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.debug.assert_has_calls(log_debug_calls)
            mock_change_status.called_with(
                E_NETWORK, 'Error while sending data to projector')
            assert not self.pjlink.send_queue, 'Send queue should be empty'
            assert not self.pjlink.priority_queue, 'Priority queue should be empty'
            assert mock_timer.start.called, 'Timer should have been called'
            assert not mock_reset.called, 'reset_information() should not should have been called'
            assert mock_disconnect.called, 'disconnect_from_host() should have been called'
            assert self.pjlink.send_busy, 'send_busy should be True'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_local_send_command_no_data(self, mock_log, mock_reset,
                                        mock_state):
        """
        Test _underscore_send_command with no data to send
        """
        # GIVEN: Test object
        log_error_calls = []
        log_warning_calls = [
            call('({ip}) _send_command(): Nothing to send - returning'.format(
                ip=self.pjlink.name))
        ]
        log_debug_calls = []
        mock_state.return_value = S_CONNECTED
        self.pjlink.send_queue = []
        self.pjlink.priority_queue = []

        # WHEN: _send_command called with no data and queue's emtpy
        # Patch some attributes here since they are not available until after instantiation
        with patch.object(self.pjlink, 'socket_timer') as mock_timer:
            self.pjlink._send_command()

            # THEN:
            mock_log.error.assert_has_calls(log_error_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.debug.assert_has_calls(log_debug_calls)
            assert not self.pjlink.send_queue, 'Send queue should be empty'
            assert not self.pjlink.priority_queue, 'Priority queue should be empty'
            assert not mock_timer.called, 'Timer should not have been called'
            assert not mock_reset.called, 'reset_information() should not have been called'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_local_send_command_normal_send(self, mock_log, mock_reset,
                                            mock_state, mock_disconnect,
                                            mock_write):
        """
        Test _underscore_send_command using normal queue
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = []
        log_debug_calls = [
            call('({ip}) _send_command(data="None")'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): priority_queue: []'.format(
                ip=self.pjlink.name)),
            call("({ip}) _send_command(): send_queue: ['{data}\\r']".format(
                ip=self.pjlink.name, data=test_command.strip())),
            call('({ip}) _send_command(): Connection status: S_CONNECTED'.
                 format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Getting normal queued packet'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): Sending "{data}"'.format(
                ip=self.pjlink.name, data=test_command.strip()))
        ]

        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        mock_write.return_value = len(test_command)
        self.pjlink.send_queue = [test_command]
        self.pjlink.priority_queue = []

        # WHEN: _send_command called with no data and queue's emtpy
        # Patch some attributes here since they are not available until after instantiation
        with patch.object(self.pjlink, 'socket_timer') as mock_timer, \
                patch.object(self.pjlink, 'waitForBytesWritten') as mock_waitBytes:
            mock_waitBytes.return_value = True
            self.pjlink._send_command()

            # THEN:
            mock_log.error.assert_has_calls(log_error_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.debug.assert_has_calls(log_debug_calls)
            assert not self.pjlink.send_queue, 'Send queue should be empty'
            assert not self.pjlink.priority_queue, 'Priority queue should be empty'
            assert mock_timer.start.called, 'Timer should have been called'
            assert not mock_reset.called, 'reset_information() should not have been called'
            assert not mock_disconnect.called, 'disconnect_from_host() should not have been called'
            assert self.pjlink.send_busy, 'send_busy flag should be True'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_local_send_command_not_connected(self, mock_log, mock_reset,
                                              mock_state, mock_disconnect):
        """
        Test _underscore_send_command when not connected
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = [
            call('({ip}) _send_command() Not connected - abort'.format(
                ip=self.pjlink.name))
        ]
        log_debug_calls = [
            call('({ip}) _send_command(data="None")'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): priority_queue: []'.format(
                ip=self.pjlink.name)),
            call("({ip}) _send_command(): send_queue: ['%1CLSS ?\\r']".format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): Connection status: S_OK'.format(
                ip=self.pjlink.name))
        ]
        mock_state.return_value = S_NOT_CONNECTED
        self.pjlink.send_queue = [test_command]
        self.pjlink.priority_queue = []

        # WHEN: _send_command called with no data and queue's emtpy
        # Patch here since pjlink does not have socket_timer until after instantiation
        with patch.object(self.pjlink, 'socket_timer') as mock_timer:
            self.pjlink._send_command()

            # THEN:
            mock_log.error.assert_has_calls(log_error_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.debug.assert_has_calls(log_debug_calls)
            assert self.pjlink.send_queue == [
                test_command
            ], 'Send queue should have one entry'
            assert not self.pjlink.priority_queue, 'Priority queue should be empty'
            assert not mock_timer.called, 'Timer should not have been called'
            assert not mock_reset.called, 'reset_information() should not have been called'
            assert mock_disconnect.called, 'disconnect_from_host() should have been called'
            assert not self.pjlink.send_busy, 'send_busy flag should be False'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_local_send_command_priority_send(self, mock_log, mock_reset,
                                              mock_state, mock_disconnect,
                                              mock_write):
        """
        Test _underscore_send_command with priority queue
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = []
        log_debug_calls = [
            call('({ip}) _send_command(data="{data}")'.format(
                ip=self.pjlink.name, data=test_command.strip())),
            call('({ip}) _send_command(): priority_queue: []'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): send_queue: []'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): Connection status: S_CONNECTED'.
                 format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Priority packet - '
                 'adding to priority queue'.format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Getting priority queued packet'.
                 format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Sending "{data}"'.format(
                ip=self.pjlink.name, data=test_command.strip()))
        ]

        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        mock_write.return_value = len(test_command)
        self.pjlink.send_queue = []
        self.pjlink.priority_queue = []

        # WHEN: _send_command called with no data and queue's emtpy
        # Patch some attributes here since they are not available until after instantiation
        with patch.object(self.pjlink, 'socket_timer') as mock_timer, \
                patch.object(self.pjlink, 'waitForBytesWritten') as mock_waitBytes:
            mock_waitBytes.return_value = True
            self.pjlink._send_command(data=test_command)

            # THEN:
            mock_log.error.assert_has_calls(log_error_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.debug.assert_has_calls(log_debug_calls)
            assert not self.pjlink.send_queue, 'Send queue should be empty'
            assert not self.pjlink.priority_queue, 'Priority queue should be empty'
            assert mock_timer.start.called, 'Timer should have been called'
            assert not mock_reset.called, 'reset_information() should not have been called'
            assert not mock_disconnect.called, 'disconnect_from_host() should not have been called'
            assert self.pjlink.send_busy, 'send_busy flag should be True'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'write')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'disconnect_from_host')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_local_send_command_priority_send_with_normal_queue(
            self, mock_log, mock_reset, mock_state, mock_disconnect,
            mock_write):
        """
        Test _underscore_send_command with priority queue when normal queue active
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = []
        log_debug_calls = [
            call('({ip}) _send_command(data="{data}")'.format(
                ip=self.pjlink.name, data=test_command.strip())),
            call('({ip}) _send_command(): priority_queue: []'.format(
                ip=self.pjlink.name)),
            call("({ip}) _send_command(): send_queue: ['{data}\\r']".format(
                ip=self.pjlink.name, data=test_command.strip())),
            call('({ip}) _send_command(): Connection status: S_CONNECTED'.
                 format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Priority packet - '
                 'adding to priority queue'.format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Getting priority queued packet'.
                 format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Sending "{data}"'.format(
                ip=self.pjlink.name, data=test_command.strip()))
        ]

        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        mock_write.return_value = len(test_command)
        self.pjlink.send_queue = [test_command]
        self.pjlink.priority_queue = []

        # WHEN: _send_command called with no data and queue's emtpy
        # Patch some attributes here since they are not available until after instantiation
        with patch.object(self.pjlink, 'socket_timer') as mock_timer, \
                patch.object(self.pjlink, 'waitForBytesWritten') as mock_waitBytes:
            mock_waitBytes.return_value = True
            self.pjlink._send_command(data=test_command)

            # THEN:
            mock_log.error.assert_has_calls(log_error_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.debug.assert_has_calls(log_debug_calls)
            assert self.pjlink.send_queue, 'Send queue should have one entry'
            assert not self.pjlink.priority_queue, 'Priority queue should be empty'
            assert mock_timer.start.called, 'Timer should have been called'
            assert not mock_reset.called, 'reset_information() should not have been called'
            assert not mock_disconnect.called, 'disconnect_from_host() should not have been called'
            assert self.pjlink.send_busy, 'send_busy flag should be True'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_local_send_command_send_busy_normal_queue(self, mock_log,
                                                       mock_reset, mock_state):
        """
        Test _underscore_send_command send_busy flag with normal queue
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = []
        log_debug_calls = [
            call('({ip}) _send_command(data="None")'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): priority_queue: []'.format(
                ip=self.pjlink.name)),
            call("({ip}) _send_command(): send_queue: ['{data}\\r']".format(
                ip=self.pjlink.name, data=test_command.strip())),
            call('({ip}) _send_command(): Connection status: S_CONNECTED'.
                 format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Still busy, returning'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): Priority queue = []'.format(
                ip=self.pjlink.name)),
            call("({ip}) _send_command(): Normal queue = "
                 "['{data}\\r']".format(ip=self.pjlink.name,
                                        data=test_command.strip()))
        ]

        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        self.pjlink.send_busy = True
        self.pjlink.send_queue = [test_command]
        self.pjlink.priority_queue = []

        # WHEN: _send_command called with no data and queue's emtpy
        # Patch some attributes here since they are not available until after instantiation
        with patch.object(self.pjlink, 'socket_timer') as mock_timer:
            self.pjlink._send_command()

            # THEN:
            mock_log.error.assert_has_calls(log_error_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.debug.assert_has_calls(log_debug_calls)
            assert self.pjlink.send_queue, 'Send queue should have one entry'
            assert not self.pjlink.priority_queue, 'Priority queue should be empty'
            assert not mock_timer.start.called, 'Timer should not have been called'
            assert not mock_reset.called, 'reset_information() should not have been called'
            assert self.pjlink.send_busy, 'send_busy flag should be True'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_local_send_command_send_busy_priority_queue(
            self, mock_log, mock_reset, mock_state):
        """
        Test _underscore_send_command send_busy flag with priority queue
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = []
        log_debug_calls = [
            call('({ip}) _send_command(data="None")'.format(
                ip=self.pjlink.name)),
            call("({ip}) _send_command(): priority_queue: "
                 "['{data}\\r']".format(ip=self.pjlink.name,
                                        data=test_command.strip())),
            call('({ip}) _send_command(): send_queue: []'.format(
                ip=self.pjlink.name)),
            call('({ip}) _send_command(): Connection status: S_CONNECTED'.
                 format(ip=self.pjlink.name)),
            call('({ip}) _send_command(): Still busy, returning'.format(
                ip=self.pjlink.name)),
            call("({ip}) _send_command(): Priority queue = "
                 "['{data}\\r']".format(ip=self.pjlink.name,
                                        data=test_command.strip())),
            call('({ip}) _send_command(): Normal queue = []'.format(
                ip=self.pjlink.name))
        ]

        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        self.pjlink.send_busy = True
        self.pjlink.send_queue = []
        self.pjlink.priority_queue = [test_command]

        # WHEN: _send_command called with no data and queue's emtpy
        # Patch some attributes here since they are not available until after instantiation
        with patch.object(self.pjlink, 'socket_timer') as mock_timer:
            self.pjlink._send_command()

            # THEN:
            mock_log.error.assert_has_calls(log_error_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.debug.assert_has_calls(log_debug_calls)
            assert not self.pjlink.send_queue, 'Send queue should be empty'
            assert self.pjlink.priority_queue, 'Priority queue should have one entry'
            assert not mock_timer.start.called, 'Timer should not have been called'
            assert not mock_reset.called, 'reset_information() should not have been called'
            assert self.pjlink.send_busy, 'send_busy flag should be True'

    # ------------ Test PJLink.send_command ----------
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink.PJLink, '_send_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_send_command_add_normal_command(self, mock_log, mock_send_command,
                                             mock_reset, mock_state):
        """
        Test send_command adding normal queue item
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = []
        log_debug_calls = [
            call('({ip}) send_command(): Building cmd="CLSS" opts="?" '.format(
                ip=self.pjlink.name)),
            call('({ip}) send_command(): Adding to normal queue'.format(
                ip=self.pjlink.name))
        ]
        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]

        # Patch here since pjlink does not have priority or send queue's until instantiated
        with patch.object(self.pjlink, 'send_queue') as mock_send, \
                patch.object(self.pjlink, 'priority_queue') as mock_priority:

            # WHEN: send_command called with valid normal command
            self.pjlink.send_command(cmd='CLSS')

            # THEN:
            mock_send.append.called_with(test_command)
            mock_priority.append.called is False
            mock_log.debug.assert_has_calls(log_debug_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.error.assert_has_calls(log_error_calls)
            assert not mock_reset.called, 'reset_information() should not have been called'
            assert mock_send_command.called, '_underscore_send_command() should have been called'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink.PJLink, '_send_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_send_command_add_priority_command(self, mock_log,
                                               mock_send_command, mock_reset,
                                               mock_state):
        """
        Test _send_command adding priority queue item
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = []
        log_debug_calls = [
            call('({ip}) send_command(): Building cmd="CLSS" opts="?" '.format(
                ip=self.pjlink.name)),
            call('({ip}) send_command(): Adding to priority queue'.format(
                ip=self.pjlink.name))
        ]
        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]

        # Patch here since pjlink does not have priority or send queue's until instantiated
        with patch.object(self.pjlink, 'send_queue') as mock_send, \
                patch.object(self.pjlink, 'priority_queue') as mock_priority:

            # WHEN: send_command called with valid priority command
            self.pjlink.send_command(cmd='CLSS', priority=True)

            # THEN:
            mock_log.debug.assert_has_calls(log_debug_calls)
            mock_log.warning.assert_has_calls(log_warning_calls)
            mock_log.error.assert_has_calls(log_error_calls)
            mock_priority.append.assert_called_with(test_command)
            assert not mock_send.append.called, 'send_queue should not have changed'
            assert not mock_reset.called, 'reset_information() should not have been called'
            assert mock_send_command.called, '_underscore_send_command() should have been called'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink.PJLink, '_send_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_send_command_duplicate_normal_command(self, mock_log,
                                                   mock_send_command,
                                                   mock_reset, mock_state):
        """
        Test send_command with duplicate item for normal queue
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = [
            call('({ip}) send_command(): Already in normal queue - '
                 'skipping'.format(ip=self.pjlink.name))
        ]
        log_debug_calls = [
            call('({ip}) send_command(cmd="CLSS" opts="?" salt="None" '
                 'priority=False'.format(ip=self.pjlink.name)),
            call('({ip}) send_command(): Building cmd="CLSS" opts="?" '.format(
                ip=self.pjlink.name))
        ]
        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        self.pjlink.send_queue = [test_command]
        self.pjlink.priority_queue = []

        # WHEN: send_command called with same command in normal queue
        self.pjlink.send_command(cmd='CLSS')

        # THEN:
        mock_log.debug.assert_has_calls(log_debug_calls)
        mock_log.warning.assert_has_calls(log_warning_calls)
        mock_log.error.assert_has_calls(log_error_calls)
        assert self.pjlink.send_queue == [test_command
                                          ], 'Send queue should have one entry'
        assert not self.pjlink.priority_queue, 'Priority queue should be empty'
        assert not mock_reset.called, 'reset_information() should not have been called'
        assert mock_send_command.called, '_underscore_send_command() should have been called'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink.PJLink, '_send_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_send_command_duplicate_priority_command(self, mock_log,
                                                     mock_send_command,
                                                     mock_reset, mock_state):
        """
        Test send_command with duplicate item for priority queue
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = []
        log_warning_calls = [
            call('({ip}) send_command(): Already in priority queue - '
                 'skipping'.format(ip=self.pjlink.name))
        ]
        log_debug_calls = [
            call('({ip}) send_command(cmd="CLSS" opts="?" salt="None" '
                 'priority=True'.format(ip=self.pjlink.name)),
            call('({ip}) send_command(): Building cmd="CLSS" opts="?" '.format(
                ip=self.pjlink.name))
        ]
        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        self.pjlink.send_queue = []
        self.pjlink.priority_queue = [test_command]

        # WHEN: send_command called with same command in priority queue
        self.pjlink.send_command(cmd='CLSS', priority=True)

        # THEN:
        mock_log.debug.assert_has_calls(log_debug_calls)
        mock_log.warning.assert_has_calls(log_warning_calls)
        mock_log.error.assert_has_calls(log_error_calls)
        assert not self.pjlink.send_queue, 'Send queue should be empty'
        assert self.pjlink.priority_queue == [
            test_command
        ], 'Priority queue should have one entry'
        assert not mock_reset.called, 'reset_information() should not have been called'
        assert mock_send_command.called, '_underscore_send_command() should have been called'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink.PJLink, '_send_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_send_command_invalid_command_empty_queues(self, mock_log,
                                                       mock_send_command,
                                                       mock_reset, mock_state):
        """
        Test send_command with invalid command
        """
        # GIVEN: Test object
        log_error_calls = [
            call('({ip}) send_command(): Invalid command requested - '
                 'ignoring.'.format(ip=self.pjlink.name))
        ]
        log_warning_calls = []
        log_debug_calls = []
        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        self.pjlink.send_queue = []
        self.pjlink.priority_queue = []

        # WHEN: send_command with invalid command
        self.pjlink.send_command(cmd='DONTCARE')

        # THEN:
        mock_log.debug.assert_has_calls(log_debug_calls)
        mock_log.warning.assert_has_calls(log_warning_calls)
        mock_log.error.assert_has_calls(log_error_calls)
        assert not self.pjlink.send_queue, 'Send queue should be empty'
        assert not self.pjlink.priority_queue, 'Priority queue should be empty'
        assert not mock_reset.called, 'reset_information() should not have been called'
        assert not mock_send_command.called, '_underscore_send_command() should not have been called'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink.PJLink, '_send_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_send_command_invalid_command_normal_queue(self, mock_log,
                                                       mock_send_command,
                                                       mock_reset, mock_state):
        """
        Test _send_command with invalid command for normal queue
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = [
            call('({ip}) send_command(): Invalid command requested - '
                 'ignoring.'.format(ip=self.pjlink.name))
        ]
        log_warning_calls = []
        log_debug_calls = []
        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        self.pjlink.send_queue = [test_command]
        self.pjlink.priority_queue = []

        # WHEN: send_command with invalid command
        self.pjlink.send_command(cmd='DONTCARE')

        # THEN:
        mock_log.debug.assert_has_calls(log_debug_calls)
        mock_log.warning.assert_has_calls(log_warning_calls)
        mock_log.error.assert_has_calls(log_error_calls)
        assert self.pjlink.send_queue, 'Send queue should have one entry'
        assert not self.pjlink.priority_queue, 'Priority queue should be empty'
        assert not mock_reset.called, 'reset_information() should not have been called'
        assert mock_send_command.called, '_underscore_send_command() should have been called'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink.PJLink, '_send_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_send_command_invalid_command_priority_queue(
            self, mock_log, mock_send_command, mock_reset, mock_state):
        """
        Test _send_command with invalid command for priority queue
        """
        # GIVEN: Test object
        test_command = '{prefix}{clss}CLSS ?{suff}'.format(
            prefix=PJLINK_PREFIX,
            clss=self.pjlink.pjlink_class,
            suff=PJLINK_SUFFIX)
        log_error_calls = [
            call('({ip}) send_command(): Invalid command requested - '
                 'ignoring.'.format(ip=self.pjlink.name))
        ]
        log_warning_calls = []
        log_debug_calls = []
        mock_state.return_value = QSOCKET_STATE[S_CONNECTED]
        self.pjlink.send_queue = []
        self.pjlink.priority_queue = [test_command]

        # WHEN: send_command with invalid command
        self.pjlink.send_command(cmd='DONTCARE', priority=True)

        # THEN:
        mock_log.debug.assert_has_calls(log_debug_calls)
        mock_log.warning.assert_has_calls(log_warning_calls)
        mock_log.error.assert_has_calls(log_error_calls)
        assert not self.pjlink.send_queue, 'Send queue should be empty'
        assert self.pjlink.priority_queue, 'Priority queue should have one entry'
        assert not mock_reset.called, 'reset_information() should not have been called'
        assert mock_send_command.called, '_underscore_send_command() should have been called'

    @patch.object(openlp.core.projectors.pjlink.PJLink, 'state')
    @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information')
    @patch.object(openlp.core.projectors.pjlink.PJLink, '_send_command')
    @patch.object(openlp.core.projectors.pjlink, 'log')
    def test_send_command_not_connected(self, mock_log, mock_send_command,
                                        mock_reset, mock_state):
        """
        Test send_command when not connected
        """
        # GIVEN: Test object
        log_error_calls = []
        log_warning_calls = [
            call('({ip}) send_command(): Not connected - returning'.format(
                ip=self.pjlink.name))
        ]
        log_debug_calls = []
        mock_state.return_value = S_NOT_CONNECTED
        self.pjlink.send_queue = []
        self.pjlink.priority_queue = []

        # WHEN: send_command called when not connected
        self.pjlink.send_command(cmd=None)

        # THEN:
        mock_log.debug.assert_has_calls(log_debug_calls)
        mock_log.warning.assert_has_calls(log_warning_calls)
        mock_log.error.assert_has_calls(log_error_calls)
        assert not self.pjlink.send_queue, 'Send queue should be empty'
        assert not self.pjlink.priority_queue, 'Priority queue should be empty'
        assert mock_reset.called, 'reset_information() should have been called'
        assert not mock_send_command.called, '_underscore_send_command() should not have been called'