Merge lp:~alisonken1/openlp/pjlink2-i into lp:openlp

Proposed by Ken Roberts
Status: Merged
Approved by: Raoul Snyman
Approved revision: 2760
Merged at revision: 2760
Proposed branch: lp:~alisonken1/openlp/pjlink2-i
Merge into: lp:openlp
Diff against target: 1078 lines (+690/-117)
3 files modified
openlp/core/lib/projector/pjlink.py (+45/-35)
tests/functional/openlp_core_lib/test_projector_pjlink_cmd_routing.py (+1/-1)
tests/functional/openlp_core_lib/test_projector_pjlink_commands.py (+644/-81)
To merge this branch: bzr merge lp:~alisonken1/openlp/pjlink2-i
Reviewer Review Type Date Requested Status
Raoul Snyman Approve
Tomas Groth Approve
Tim Bentley Pending
Review via email: mp+328951@code.launchpad.net

This proposal supersedes a proposal from 2017-08-12.

Commit message

PJLink2 update I

Description of the change

More minor code cleanups

- Renamed get_shutter_status to get_av_mute_status (checks shutter and audio)
- Renamed shutter/audio mute test
- Update socket read to get 1K bytes in buffer
- Updated get_status for valid input
- Updated process_sver check valid length
- Update change_status to not use NETWORK_SENDING as a connection status check
- Added read check for packet length > allowed max
- Added test for process_inf1
- Added test for process_inf2
- Added test for process_info
- Added test for process_inst
- Added test for process_lamp with invalid data
- Update tests for process_powr
- Added test for process_powr_invalid
- Added tests for process_sver
- Added tests for change_status
- Added test for get_av_mute_status
- Added test for get_available_inputs
- Added test for get_error_status
- Added test for get_input_source
- Added test for get_lamp_status
- Added test for get_manufacturer
- Added test for get_model
- Added test for get_name
- Added test for get_other_info
- Added test for get_power_status
- Added tests for get_status
- Added test for process_inf1
- Added test for get_process_inf2
- Added test for get_process_info
- Added test for reset_information
- Fix deprecated log calls

--------------------------------
lp:~alisonken1/openlp/pjlink2-i (revision 2760)
[SUCCESS] https://ci.openlp.io/job/Branch-01-Pull/2162/
[SUCCESS] https://ci.openlp.io/job/Branch-02-Functional-Tests/2067/
[SUCCESS] https://ci.openlp.io/job/Branch-03-Interface-Tests/1955/
[SUCCESS] https://ci.openlp.io/job/Branch-04a-Code_Analysis/1328/
[SUCCESS] https://ci.openlp.io/job/Branch-04b-Test_Coverage/1166/
[SUCCESS] https://ci.openlp.io/job/Branch-04c-Code_Analysis2/296/
[FAILURE] https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/141/

To post a comment you must log in.
Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

See inline

review: Needs Fixing
Revision history for this message
Tomas Groth (tomasgroth) wrote :

Looks ok to me.

review: Approve
Revision history for this message
Raoul Snyman (raoul-snyman) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openlp/core/lib/projector/pjlink.py'
--- openlp/core/lib/projector/pjlink.py 2017-08-11 11:04:33 +0000
+++ openlp/core/lib/projector/pjlink.py 2017-08-12 21:17:39 +0000
@@ -57,7 +57,7 @@
57 E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, E_OK, \57 E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, E_OK, \
58 E_PARAMETER, E_PROJECTOR, E_SOCKET_TIMEOUT, E_UNAVAILABLE, E_UNDEFINED, PJLINK_ERRORS, PJLINK_ERST_DATA, \58 E_PARAMETER, E_PROJECTOR, E_SOCKET_TIMEOUT, E_UNAVAILABLE, E_UNDEFINED, PJLINK_ERRORS, PJLINK_ERST_DATA, \
59 PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PORT, PJLINK_POWR_STATUS, PJLINK_VALID_CMD, \59 PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PORT, PJLINK_POWR_STATUS, PJLINK_VALID_CMD, \
60 STATUS_STRING, S_CONNECTED, S_CONNECTING, S_NETWORK_RECEIVED, S_NETWORK_SENDING, \60 STATUS_STRING, S_CONNECTED, S_CONNECTING, S_INFO, S_NETWORK_RECEIVED, S_NETWORK_SENDING, \
61 S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_STATUS61 S_NOT_CONNECTED, S_OFF, S_OK, S_ON, S_STATUS
6262
63# Shortcuts63# Shortcuts
@@ -159,7 +159,7 @@
159 # A command returned successfully, no further processing needed159 # A command returned successfully, no further processing needed
160 return160 return
161 elif _cmd not in self.pjlink_functions:161 elif _cmd not in self.pjlink_functions:
162 log.warn("({ip}) Unable to process command='{cmd}' (Future option)".format(ip=self.ip, cmd=cmd))162 log.warning("({ip}) Unable to process command='{cmd}' (Future option)".format(ip=self.ip, cmd=cmd))
163 return163 return
164 elif _data in PJLINK_ERRORS:164 elif _data in PJLINK_ERRORS:
165 # Oops - projector error165 # Oops - projector error
@@ -231,7 +231,7 @@
231 # : Received: '%1CLSS=Class 1' (Optoma)231 # : Received: '%1CLSS=Class 1' (Optoma)
232 # : Received: '%1CLSS=Version1' (BenQ)232 # : Received: '%1CLSS=Version1' (BenQ)
233 if len(data) > 1:233 if len(data) > 1:
234 log.warn("({ip}) Non-standard CLSS reply: '{data}'".format(ip=self.ip, data=data))234 log.warning("({ip}) Non-standard CLSS reply: '{data}'".format(ip=self.ip, data=data))
235 # Due to stupid projectors not following standards (Optoma, BenQ comes to mind),235 # Due to stupid projectors not following standards (Optoma, BenQ comes to mind),
236 # AND the different responses that can be received, the semi-permanent way to236 # AND the different responses that can be received, the semi-permanent way to
237 # fix the class reply is to just remove all non-digit characters.237 # fix the class reply is to just remove all non-digit characters.
@@ -261,15 +261,15 @@
261 """261 """
262 if len(data) != PJLINK_ERST_DATA['DATA_LENGTH']:262 if len(data) != PJLINK_ERST_DATA['DATA_LENGTH']:
263 count = PJLINK_ERST_DATA['DATA_LENGTH']263 count = PJLINK_ERST_DATA['DATA_LENGTH']
264 log.warn("{ip}) Invalid error status response '{data}': length != {count}".format(ip=self.ip,264 log.warning("{ip}) Invalid error status response '{data}': length != {count}".format(ip=self.ip,
265 data=data,265 data=data,
266 count=count))266 count=count))
267 return267 return
268 try:268 try:
269 datacheck = int(data)269 datacheck = int(data)
270 except ValueError:270 except ValueError:
271 # Bad data - ignore271 # Bad data - ignore
272 log.warn("({ip}) Invalid error status response '{data}'".format(ip=self.ip, data=data))272 log.warning("({ip}) Invalid error status response '{data}'".format(ip=self.ip, data=data))
273 return273 return
274 if datacheck == 0:274 if datacheck == 0:
275 self.projector_errors = None275 self.projector_errors = None
@@ -429,9 +429,9 @@
429 if self.model_filter is None:429 if self.model_filter is None:
430 self.model_filter = data430 self.model_filter = data
431 else:431 else:
432 log.warn("({ip}) Filter model already set".format(ip=self.ip))432 log.warning("({ip}) Filter model already set".format(ip=self.ip))
433 log.warn("({ip}) Saved model: '{old}'".format(ip=self.ip, old=self.model_filter))433 log.warning("({ip}) Saved model: '{old}'".format(ip=self.ip, old=self.model_filter))
434 log.warn("({ip}) New model: '{new}'".format(ip=self.ip, new=data))434 log.warning("({ip}) New model: '{new}'".format(ip=self.ip, new=data))
435435
436 def process_rlmp(self, data):436 def process_rlmp(self, data):
437 """437 """
@@ -440,9 +440,9 @@
440 if self.model_lamp is None:440 if self.model_lamp is None:
441 self.model_lamp = data441 self.model_lamp = data
442 else:442 else:
443 log.warn("({ip}) Lamp model already set".format(ip=self.ip))443 log.warning("({ip}) Lamp model already set".format(ip=self.ip))
444 log.warn("({ip}) Saved lamp: '{old}'".format(ip=self.ip, old=self.model_lamp))444 log.warning("({ip}) Saved lamp: '{old}'".format(ip=self.ip, old=self.model_lamp))
445 log.warn("({ip}) New lamp: '{new}'".format(ip=self.ip, new=data))445 log.warning("({ip}) New lamp: '{new}'".format(ip=self.ip, new=data))
446446
447 def process_snum(self, data):447 def process_snum(self, data):
448 """448 """
@@ -457,27 +457,32 @@
457 else:457 else:
458 # Compare serial numbers and see if we got the same projector458 # Compare serial numbers and see if we got the same projector
459 if self.serial_no != data:459 if self.serial_no != data:
460 log.warn("({ip}) Projector serial number does not match saved serial number".format(ip=self.ip))460 log.warning("({ip}) Projector serial number does not match saved serial number".format(ip=self.ip))
461 log.warn("({ip}) Saved: '{old}'".format(ip=self.ip, old=self.serial_no))461 log.warning("({ip}) Saved: '{old}'".format(ip=self.ip, old=self.serial_no))
462 log.warn("({ip}) Received: '{new}'".format(ip=self.ip, new=data))462 log.warning("({ip}) Received: '{new}'".format(ip=self.ip, new=data))
463 log.warn("({ip}) NOT saving serial number".format(ip=self.ip))463 log.warning("({ip}) NOT saving serial number".format(ip=self.ip))
464 self.serial_no_received = data464 self.serial_no_received = data
465465
466 def process_sver(self, data):466 def process_sver(self, data):
467 """467 """
468 Software version of projector468 Software version of projector
469 """469 """
470 if self.sw_version is None:470 if len(data) > 32:
471 # Defined in specs max version is 32 characters
472 log.warning("Invalid software version - too long")
473 return
474 elif self.sw_version is None:
471 log.debug("({ip}) Setting projector software version to '{data}'".format(ip=self.ip, data=data))475 log.debug("({ip}) Setting projector software version to '{data}'".format(ip=self.ip, data=data))
472 self.sw_version = data476 self.sw_version = data
473 self.db_update = True477 self.db_update = True
474 else:478 else:
475 # Compare software version and see if we got the same projector479 # Compare software version and see if we got the same projector
476 if self.serial_no != data:480 if self.serial_no != data:
477 log.warn("({ip}) Projector software version does not match saved software version".format(ip=self.ip))481 log.warning("({ip}) Projector software version does not match saved "
478 log.warn("({ip}) Saved: '{old}'".format(ip=self.ip, old=self.sw_version))482 "software version".format(ip=self.ip))
479 log.warn("({ip}) Received: '{new}'".format(ip=self.ip, new=data))483 log.warning("({ip}) Saved: '{old}'".format(ip=self.ip, old=self.sw_version))
480 log.warn("({ip}) NOT saving serial number".format(ip=self.ip))484 log.warning("({ip}) Received: '{new}'".format(ip=self.ip, new=data))
485 log.warning("({ip}) Saving new serial number as sw_version_received".format(ip=self.ip))
481 self.sw_version_received = data486 self.sw_version_received = data
482487
483488
@@ -605,7 +610,7 @@
605 Normally called by timer().610 Normally called by timer().
606 """611 """
607 if self.state() != self.ConnectedState:612 if self.state() != self.ConnectedState:
608 log.warn("({ip}) poll_loop(): Not connected - returning".format(ip=self.ip))613 log.warning("({ip}) poll_loop(): Not connected - returning".format(ip=self.ip))
609 return614 return
610 log.debug('({ip}) Updating projector status'.format(ip=self.ip))615 log.debug('({ip}) Updating projector status'.format(ip=self.ip))
611 # Reset timer in case we were called from a set command616 # Reset timer in case we were called from a set command
@@ -649,7 +654,9 @@
649 :param status: Status/Error code654 :param status: Status/Error code
650 :returns: (Status/Error code, String)655 :returns: (Status/Error code, String)
651 """656 """
652 if status in ERROR_STRING:657 if not isinstance(status, int):
658 return -1, 'Invalid status code'
659 elif status in ERROR_STRING:
653 return ERROR_STRING[status], ERROR_MSG[status]660 return ERROR_STRING[status], ERROR_MSG[status]
654 elif status in STATUS_STRING:661 elif status in STATUS_STRING:
655 return STATUS_STRING[status], ERROR_MSG[status]662 return STATUS_STRING[status], ERROR_MSG[status]
@@ -674,7 +681,7 @@
674 elif status >= S_NOT_CONNECTED and status < S_STATUS:681 elif status >= S_NOT_CONNECTED and status < S_STATUS:
675 self.status_connect = status682 self.status_connect = status
676 self.projector_status = S_NOT_CONNECTED683 self.projector_status = S_NOT_CONNECTED
677 elif status < S_NETWORK_SENDING:684 elif status <= S_INFO:
678 self.status_connect = S_CONNECTED685 self.status_connect = S_CONNECTED
679 self.projector_status = status686 self.projector_status = status
680 (status_code, status_message) = self._get_status(self.status_connect)687 (status_code, status_message) = self._get_status(self.status_connect)
@@ -803,7 +810,8 @@
803 log.debug('({ip}) get_data(): Not connected - returning'.format(ip=self.ip))810 log.debug('({ip}) get_data(): Not connected - returning'.format(ip=self.ip))
804 self.send_busy = False811 self.send_busy = False
805 return812 return
806 read = self.readLine(self.max_size)813 # Although we have a packet length limit, go ahead and use a larger buffer
814 read = self.readLine(1024)
807 log.debug("({ip}) get_data(): '{buff}'".format(ip=self.ip, buff=read))815 log.debug("({ip}) get_data(): '{buff}'".format(ip=self.ip, buff=read))
808 if read == -1:816 if read == -1:
809 # No data available817 # No data available
@@ -816,6 +824,8 @@
816 data = data_in.strip()824 data = data_in.strip()
817 if (len(data) < 7) or (not data.startswith(PJLINK_PREFIX)):825 if (len(data) < 7) or (not data.startswith(PJLINK_PREFIX)):
818 return self._trash_buffer(msg='get_data(): Invalid packet - length or prefix')826 return self._trash_buffer(msg='get_data(): Invalid packet - length or prefix')
827 elif len(data) > self.max_size:
828 return self._trash_buffer(msg='get_data(): Invalid packet - too long')
819 elif '=' not in data:829 elif '=' not in data:
820 return self._trash_buffer(msg='get_data(): Invalid packet does not have equal')830 return self._trash_buffer(msg='get_data(): Invalid packet does not have equal')
821 log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.ip, data=data))831 log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.ip, data=data))
@@ -830,8 +840,8 @@
830 log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))840 log.warning('({ip}) get_data(): Invalid packet - unknown command "{data}"'.format(ip=self.ip, data=cmd))
831 return self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd))841 return self._trash_buffer(msg='get_data(): Unknown command "{data}"'.format(data=cmd))
832 if int(self.pjlink_class) < int(version):842 if int(self.pjlink_class) < int(version):
833 log.warn('({ip}) get_data(): Projector returned class reply higher '843 log.warning('({ip}) get_data(): Projector returned class reply higher '
834 'than projector stated class'.format(ip=self.ip))844 'than projector stated class'.format(ip=self.ip))
835 return self.process_command(cmd, data)845 return self.process_command(cmd, data)
836846
837 @QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError)847 @QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError)
@@ -993,6 +1003,13 @@
993 self.reset_information()1003 self.reset_information()
994 self.projectorUpdateIcons.emit()1004 self.projectorUpdateIcons.emit()
9951005
1006 def get_av_mute_status(self):
1007 """
1008 Send command to retrieve shutter status.
1009 """
1010 log.debug('({ip}) Sending AVMT command'.format(ip=self.ip))
1011 return self.send_command(cmd='AVMT')
1012
996 def get_available_inputs(self):1013 def get_available_inputs(self):
997 """1014 """
998 Send command to retrieve available source inputs.1015 Send command to retrieve available source inputs.
@@ -1056,13 +1073,6 @@
1056 log.debug('({ip}) Sending POWR command'.format(ip=self.ip))1073 log.debug('({ip}) Sending POWR command'.format(ip=self.ip))
1057 return self.send_command(cmd='POWR')1074 return self.send_command(cmd='POWR')
10581075
1059 def get_shutter_status(self):
1060 """
1061 Send command to retrieve shutter status.
1062 """
1063 log.debug('({ip}) Sending AVMT command'.format(ip=self.ip))
1064 return self.send_command(cmd='AVMT')
1065
1066 def set_input_source(self, src=None):1076 def set_input_source(self, src=None):
1067 """1077 """
1068 Verify input source available as listed in 'INST' command,1078 Verify input source available as listed in 'INST' command,
10691079
=== modified file 'tests/functional/openlp_core_lib/test_projector_pjlink_cmd_routing.py'
--- tests/functional/openlp_core_lib/test_projector_pjlink_cmd_routing.py 2017-08-11 11:04:33 +0000
+++ tests/functional/openlp_core_lib/test_projector_pjlink_cmd_routing.py 2017-08-12 21:17:39 +0000
@@ -179,7 +179,7 @@
179179
180 # THEN: Error should be logged and no command called180 # THEN: Error should be logged and no command called
181 self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')181 self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
182 mock_log.warn.assert_called_once_with(log_text)182 mock_log.warning.assert_called_once_with(log_text)
183183
184 @patch.object(pjlink_test, 'pjlink_functions')184 @patch.object(pjlink_test, 'pjlink_functions')
185 @patch.object(openlp.core.lib.projector.pjlink, 'log')185 @patch.object(openlp.core.lib.projector.pjlink, 'log')
186186
=== modified file 'tests/functional/openlp_core_lib/test_projector_pjlink_commands.py'
--- tests/functional/openlp_core_lib/test_projector_pjlink_commands.py 2017-08-11 11:04:33 +0000
+++ tests/functional/openlp_core_lib/test_projector_pjlink_commands.py 2017-08-12 21:17:39 +0000
@@ -23,12 +23,14 @@
23Package to test the openlp.core.lib.projector.pjlink commands package.23Package to test the openlp.core.lib.projector.pjlink commands package.
24"""24"""
25from unittest import TestCase25from unittest import TestCase
26from unittest.mock import patch, MagicMock26from unittest.mock import patch
2727
28import openlp.core.lib.projector.pjlink28import openlp.core.lib.projector.pjlink
29from openlp.core.lib.projector.pjlink import PJLink29from openlp.core.lib.projector.pjlink import PJLink
30from openlp.core.lib.projector.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \30from openlp.core.lib.projector.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
31 PJLINK_POWR_STATUS, E_WARN, E_ERROR, S_OFF, S_STANDBY, S_ON31 PJLINK_POWR_STATUS, \
32 E_ERROR, E_NOT_CONNECTED, E_SOCKET_ADDRESS_NOT_AVAILABLE, E_UNKNOWN_SOCKET_ERROR, E_WARN, \
33 S_CONNECTED, S_OFF, S_ON, S_NOT_CONNECTED, S_CONNECTING, S_STANDBY
3234
33from tests.resources.projector.data import TEST_PIN35from tests.resources.projector.data import TEST_PIN
3436
@@ -45,48 +47,408 @@
45 """47 """
46 Tests for the PJLink module48 Tests for the PJLink module
47 """49 """
48 def test_projector_reset_information(self):50 @patch.object(pjlink_test, 'changeStatus')
49 """51 @patch.object(openlp.core.lib.projector.pjlink, 'log')
50 Test reset_information() resets all information and stops timers52 def test_projector_change_status_connection_error(self, mock_log, mock_change_status):
51 """53 """
52 # GIVEN: Test object and test data54 Test change_status with connection error
53 pjlink = pjlink_test55 """
54 pjlink.power = S_ON56 # GIVEN: Test object
55 pjlink.pjlink_name = 'OPENLPTEST'57 pjlink = pjlink_test
56 pjlink.manufacturer = 'PJLINK'58 pjlink.projector_status = 0
57 pjlink.model = '1'59 pjlink.status_connect = 0
58 pjlink.shutter = True60 test_code = E_UNKNOWN_SOCKET_ERROR
59 pjlink.mute = True61 mock_change_status.reset_mock()
60 pjlink.lamp = True62 mock_log.reset_mock()
61 pjlink.fan = True63
62 pjlink.source_available = True64 # WHEN: change_status called with unknown socket error
63 pjlink.other_info = 'ANOTHER TEST'65 pjlink.change_status(status=test_code, msg=None)
64 pjlink.send_queue = True66
65 pjlink.send_busy = True67 # THEN: Proper settings should change and signals sent
66 pjlink.timer = MagicMock()68 self.assertEqual(pjlink.projector_status, E_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')
67 pjlink.socket_timer = MagicMock()69 self.assertEqual(pjlink.status_connect, E_NOT_CONNECTED, 'Status connect should be NOT CONNECTED')
6870 mock_change_status.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR,
69 # WHEN: reset_information() is called71 'An unidentified error occurred')
70 with patch.object(pjlink.timer, 'stop') as mock_timer:72 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
71 with patch.object(pjlink.socket_timer, 'stop') as mock_socket_timer:73
72 pjlink.reset_information()74 @patch.object(pjlink_test, 'changeStatus')
7375 @patch.object(openlp.core.lib.projector.pjlink, 'log')
74 # THEN: All information should be reset and timers stopped76 def test_projector_change_status_connection_status_connecting(self, mock_log, mock_change_status):
75 self.assertEqual(pjlink.power, S_OFF, 'Projector power should be OFF')77 """
76 self.assertIsNone(pjlink.pjlink_name, 'Projector pjlink_name should be None')78 Test change_status with connection status
77 self.assertIsNone(pjlink.manufacturer, 'Projector manufacturer should be None')79 """
78 self.assertIsNone(pjlink.model, 'Projector model should be None')80 # GIVEN: Test object
79 self.assertIsNone(pjlink.shutter, 'Projector shutter should be None')81 pjlink = pjlink_test
80 self.assertIsNone(pjlink.mute, 'Projector shuttter should be None')82 pjlink.projector_status = 0
81 self.assertIsNone(pjlink.lamp, 'Projector lamp should be None')83 pjlink.status_connect = 0
82 self.assertIsNone(pjlink.fan, 'Projector fan should be None')84 test_code = S_CONNECTING
83 self.assertIsNone(pjlink.source_available, 'Projector source_available should be None')85 mock_change_status.reset_mock()
84 self.assertIsNone(pjlink.source, 'Projector source should be None')86 mock_log.reset_mock()
85 self.assertIsNone(pjlink.other_info, 'Projector other_info should be None')87
86 self.assertEqual(pjlink.send_queue, [], 'Projector send_queue should be an empty list')88 # WHEN: change_status called with unknown socket error
87 self.assertFalse(pjlink.send_busy, 'Projector send_busy should be False')89 pjlink.change_status(status=test_code, msg=None)
88 self.assertTrue(mock_timer.called, 'Projector timer.stop() should have been called')90
89 self.assertTrue(mock_socket_timer.called, 'Projector socket_timer.stop() should have been called')91 # THEN: Proper settings should change and signals sent
92 self.assertEqual(pjlink.projector_status, S_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')
93 self.assertEqual(pjlink.status_connect, S_CONNECTING, 'Status connect should be CONNECTING')
94 mock_change_status.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, 'Connecting')
95 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
96
97 @patch.object(pjlink_test, 'changeStatus')
98 @patch.object(openlp.core.lib.projector.pjlink, 'log')
99 def test_projector_change_status_connection_status_connected(self, mock_log, mock_change_status):
100 """
101 Test change_status with connection status
102 """
103 # GIVEN: Test object
104 pjlink = pjlink_test
105 pjlink.projector_status = 0
106 pjlink.status_connect = 0
107 test_code = S_ON
108 mock_change_status.reset_mock()
109 mock_log.reset_mock()
110
111 # WHEN: change_status called with unknown socket error
112 pjlink.change_status(status=test_code, msg=None)
113
114 # THEN: Proper settings should change and signals sent
115 self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
116 self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
117 mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, 'Power is on')
118 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
119
120 @patch.object(pjlink_test, 'changeStatus')
121 @patch.object(openlp.core.lib.projector.pjlink, 'log')
122 def test_projector_change_status_connection_status_with_message(self, mock_log, mock_change_status):
123 """
124 Test change_status with connection status
125 """
126 # GIVEN: Test object
127 pjlink = pjlink_test
128 pjlink.projector_status = 0
129 pjlink.status_connect = 0
130 test_message = 'Different Status Message than default'
131 test_code = S_ON
132 mock_change_status.reset_mock()
133 mock_log.reset_mock()
134
135 # WHEN: change_status called with unknown socket error
136 pjlink.change_status(status=test_code, msg=test_message)
137
138 # THEN: Proper settings should change and signals sent
139 self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
140 self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
141 mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, test_message)
142 self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
143
144 @patch.object(pjlink_test, 'send_command')
145 @patch.object(openlp.core.lib.projector.pjlink, 'log')
146 def test_projector_get_av_mute_status(self, mock_log, mock_send_command):
147 """
148 Test sending command to retrieve shutter/audio state
149 """
150 # GIVEN: Test object
151 pjlink = pjlink_test
152 mock_log.reset_mock()
153 mock_send_command.reset_mock()
154 test_data = 'AVMT'
155 test_log = '(127.0.0.1) Sending AVMT command'
156
157 # WHEN: get_av_mute_status is called
158 pjlink.get_av_mute_status()
159
160 # THEN: log data and send_command should have been called
161 mock_log.debug.assert_called_once_with(test_log)
162 mock_send_command.assert_called_once_with(cmd=test_data)
163
164 @patch.object(pjlink_test, 'send_command')
165 @patch.object(openlp.core.lib.projector.pjlink, 'log')
166 def test_projector_get_available_inputs(self, mock_log, mock_send_command):
167 """
168 Test sending command to retrieve avaliable inputs
169 """
170 # GIVEN: Test object
171 pjlink = pjlink_test
172 mock_log.reset_mock()
173 mock_send_command.reset_mock()
174 test_data = 'INST'
175 test_log = '(127.0.0.1) Sending INST command'
176
177 # WHEN: get_available_inputs is called
178 pjlink.get_available_inputs()
179
180 # THEN: log data and send_command should have been called
181 mock_log.debug.assert_called_once_with(test_log)
182 mock_send_command.assert_called_once_with(cmd=test_data)
183
184 @patch.object(pjlink_test, 'send_command')
185 @patch.object(openlp.core.lib.projector.pjlink, 'log')
186 def test_projector_get_error_status(self, mock_log, mock_send_command):
187 """
188 Test sending command to retrieve projector error status
189 """
190 # GIVEN: Test object
191 pjlink = pjlink_test
192 mock_log.reset_mock()
193 mock_send_command.reset_mock()
194 test_data = 'ERST'
195 test_log = '(127.0.0.1) Sending ERST command'
196
197 # WHEN: get_error_status is called
198 pjlink.get_error_status()
199
200 # THEN: log data and send_command should have been called
201 mock_log.debug.assert_called_once_with(test_log)
202 mock_send_command.assert_called_once_with(cmd=test_data)
203
204 @patch.object(pjlink_test, 'send_command')
205 @patch.object(openlp.core.lib.projector.pjlink, 'log')
206 def test_projector_get_input_source(self, mock_log, mock_send_command):
207 """
208 Test sending command to retrieve current input
209 """
210 # GIVEN: Test object
211 pjlink = pjlink_test
212 mock_log.reset_mock()
213 mock_send_command.reset_mock()
214 test_data = 'INPT'
215 test_log = '(127.0.0.1) Sending INPT command'
216
217 # WHEN: get_input_source is called
218 pjlink.get_input_source()
219
220 # THEN: log data and send_command should have been called
221 mock_log.debug.assert_called_once_with(test_log)
222 mock_send_command.assert_called_once_with(cmd=test_data)
223
224 @patch.object(pjlink_test, 'send_command')
225 @patch.object(openlp.core.lib.projector.pjlink, 'log')
226 def test_projector_get_lamp_status(self, mock_log, mock_send_command):
227 """
228 Test sending command to retrieve lamp(s) status
229 """
230 # GIVEN: Test object
231 pjlink = pjlink_test
232 mock_log.reset_mock()
233 mock_send_command.reset_mock()
234 test_data = 'LAMP'
235 test_log = '(127.0.0.1) Sending LAMP command'
236
237 # WHEN: get_lamp_status is called
238 pjlink.get_lamp_status()
239
240 # THEN: log data and send_command should have been called
241 mock_log.debug.assert_called_once_with(test_log)
242 mock_send_command.assert_called_once_with(cmd=test_data)
243
244 @patch.object(pjlink_test, 'send_command')
245 @patch.object(openlp.core.lib.projector.pjlink, 'log')
246 def test_projector_get_manufacturer(self, mock_log, mock_send_command):
247 """
248 Test sending command to retrieve manufacturer name
249 """
250 # GIVEN: Test object
251 pjlink = pjlink_test
252 mock_log.reset_mock()
253 mock_send_command.reset_mock()
254 test_data = 'INF1'
255 test_log = '(127.0.0.1) Sending INF1 command'
256
257 # WHEN: get_manufacturer is called
258 pjlink.get_manufacturer()
259
260 # THEN: log data and send_command should have been called
261 mock_log.debug.assert_called_once_with(test_log)
262 mock_send_command.assert_called_once_with(cmd=test_data)
263
264 @patch.object(pjlink_test, 'send_command')
265 @patch.object(openlp.core.lib.projector.pjlink, 'log')
266 def test_projector_get_model(self, mock_log, mock_send_command):
267 """
268 Test sending command to get model information
269 """
270 # GIVEN: Test object
271 pjlink = pjlink_test
272 mock_log.reset_mock()
273 mock_send_command.reset_mock()
274 test_data = 'INF2'
275 test_log = '(127.0.0.1) Sending INF2 command'
276
277 # WHEN: get_model is called
278 pjlink.get_model()
279
280 # THEN: log data and send_command should have been called
281 mock_log.debug.assert_called_once_with(test_log)
282 mock_send_command.assert_called_once_with(cmd=test_data)
283
284 @patch.object(pjlink_test, 'send_command')
285 @patch.object(openlp.core.lib.projector.pjlink, 'log')
286 def test_projector_get_name(self, mock_log, mock_send_command):
287 """
288 Test sending command to get user-assigned name
289 """
290 # GIVEN: Test object
291 pjlink = pjlink_test
292 mock_log.reset_mock()
293 mock_send_command.reset_mock()
294 test_data = 'NAME'
295 test_log = '(127.0.0.1) Sending NAME command'
296
297 # WHEN: get_name is called
298 pjlink.get_name()
299
300 # THEN: log data and send_command should have been called
301 mock_log.debug.assert_called_once_with(test_log)
302 mock_send_command.assert_called_once_with(cmd=test_data)
303
304 @patch.object(pjlink_test, 'send_command')
305 @patch.object(openlp.core.lib.projector.pjlink, 'log')
306 def test_projector_get_other_info(self, mock_log, mock_send_command):
307 """
308 Test sending command to retrieve other information
309 """
310 # GIVEN: Test object
311 pjlink = pjlink_test
312 mock_log.reset_mock()
313 mock_send_command.reset_mock()
314 test_data = 'INFO'
315 test_log = '(127.0.0.1) Sending INFO command'
316
317 # WHEN: get_other_info is called
318 pjlink.get_other_info()
319
320 # THEN: log data and send_command should have been called
321 mock_log.debug.assert_called_once_with(test_log)
322 mock_send_command.assert_called_once_with(cmd=test_data)
323
324 @patch.object(pjlink_test, 'send_command')
325 @patch.object(openlp.core.lib.projector.pjlink, 'log')
326 def test_projector_get_power_status(self, mock_log, mock_send_command):
327 """
328 Test sending command to retrieve current power state
329 """
330 # GIVEN: Test object
331 pjlink = pjlink_test
332 mock_log.reset_mock()
333 mock_send_command.reset_mock()
334 test_data = 'POWR'
335 test_log = '(127.0.0.1) Sending POWR command'
336
337 # WHEN: get_power_status called
338 pjlink.get_power_status()
339
340 # THEN: log data and send_command should have been called
341 mock_log.debug.assert_called_once_with(test_log)
342 mock_send_command.assert_called_once_with(cmd=test_data)
343
344 def test_projector_get_status_error(self):
345 """
346 Test to check returned information for error code
347 """
348 # GIVEN: Test object
349 pjlink = pjlink_test
350 test_string = 'E_SOCKET_ADDRESS_NOT_AVAILABLE'
351 test_message = 'The address specified to socket.bind() does not belong to the host'
352
353 # WHEN: get_status called
354 string, message = pjlink._get_status(status=E_SOCKET_ADDRESS_NOT_AVAILABLE)
355
356 # THEN: Proper strings should have been returned
357 self.assertEqual(string, test_string, 'Code as string should have been returned')
358 self.assertEqual(message, test_message, 'Description of code should have been returned')
359
360 def test_projector_get_status_invalid(self):
361 """
362 Test to check returned information for error code
363 """
364 # GIVEN: Test object
365 pjlink = pjlink_test
366 test_string = 'Test string since get_status will only work with int'
367 test_message = 'Invalid status code'
368
369 # WHEN: get_status called
370 string, message = pjlink._get_status(status=test_string)
371
372 # THEN: Proper strings should have been returned
373 self.assertEqual(string, -1, 'Should have returned -1 as a bad status check')
374 self.assertEqual(message, test_message, 'Error message should have been returned')
375
376 def test_projector_get_status_status(self):
377 """
378 Test to check returned information for status codes
379 """
380 # GIVEN: Test object
381 pjlink = pjlink_test
382 test_string = 'S_NOT_CONNECTED'
383 test_message = 'Not connected'
384
385 # WHEN: get_status called
386 string, message = pjlink._get_status(status=S_NOT_CONNECTED)
387
388 # THEN: Proper strings should have been returned
389 self.assertEqual(string, test_string, 'Code as string should have been returned')
390 self.assertEqual(message, test_message, 'Description of code should have been returned')
391
392 def test_projector_get_status_unknown(self):
393 """
394 Test to check returned information for unknown code
395 """
396 # GIVEN: Test object
397 pjlink = pjlink_test
398 test_string = 999999
399 test_message = 'Unknown status'
400
401 # WHEN: get_status called
402 string, message = pjlink._get_status(status=test_string)
403
404 # THEN: Proper strings should have been returned
405 self.assertEqual(string, test_string, 'Received code should have been returned')
406 self.assertEqual(message, test_message, 'Unknown status string should have been returned')
407
408 def test_projector_process_inf1(self):
409 """
410 Test saving INF1 data (manufacturer)
411 """
412 # GIVEN: Test object
413 pjlink = pjlink_test
414 pjlink.manufacturer = None
415 test_data = 'TEst INformation MultiCase'
416
417 # WHEN: process_inf called with test data
418 pjlink.process_inf1(data=test_data)
419
420 # THEN: Data should be saved
421 self.assertEqual(pjlink.manufacturer, test_data, 'Test data should have been saved')
422
423 def test_projector_process_inf2(self):
424 """
425 Test saving INF2 data (model)
426 """
427 # GIVEN: Test object
428 pjlink = pjlink_test
429 pjlink.model = None
430 test_data = 'TEst moDEl MultiCase'
431
432 # WHEN: process_inf called with test data
433 pjlink.process_inf2(data=test_data)
434
435 # THEN: Data should be saved
436 self.assertEqual(pjlink.model, test_data, 'Test data should have been saved')
437
438 def test_projector_process_info(self):
439 """
440 Test saving INFO data (other information)
441 """
442 # GIVEN: Test object
443 pjlink = pjlink_test
444 pjlink.other_info = None
445 test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
446
447 # WHEN: process_inf called with test data
448 pjlink.process_info(data=test_data)
449
450 # THEN: Data should be saved
451 self.assertEqual(pjlink.other_info, test_data, 'Test data should have been saved')
90452
91 @patch.object(pjlink_test, 'projectorUpdateIcons')453 @patch.object(pjlink_test, 'projectorUpdateIcons')
92 def test_projector_process_avmt_bad_data(self, mock_UpdateIcons):454 def test_projector_process_avmt_bad_data(self, mock_UpdateIcons):
@@ -245,12 +607,12 @@
245607
246 # WHEN: Process invalid reply608 # WHEN: Process invalid reply
247 pjlink.process_clss('Z')609 pjlink.process_clss('Z')
248 log_warn_text = "(127.0.0.1) NAN clss version reply 'Z' - defaulting to class '1'"610 log_text = "(127.0.0.1) NAN clss version reply 'Z' - defaulting to class '1'"
249611
250 # THEN: Projector class should be set with default value612 # THEN: Projector class should be set with default value
251 self.assertEqual(pjlink.pjlink_class, '1',613 self.assertEqual(pjlink.pjlink_class, '1',
252 'Non-standard class reply should have set class=1')614 'Non-standard class reply should have set class=1')
253 mock_log.error.assert_called_once_with(log_warn_text)615 mock_log.error.assert_called_once_with(log_text)
254616
255 @patch.object(openlp.core.lib.projector.pjlink, 'log')617 @patch.object(openlp.core.lib.projector.pjlink, 'log')
256 def test_projector_process_clss_invalid_no_version(self, mock_log):618 def test_projector_process_clss_invalid_no_version(self, mock_log):
@@ -262,12 +624,12 @@
262624
263 # WHEN: Process invalid reply625 # WHEN: Process invalid reply
264 pjlink.process_clss('Invalid')626 pjlink.process_clss('Invalid')
265 log_warn_text = "(127.0.0.1) No numbers found in class version reply 'Invalid' - defaulting to class '1'"627 log_text = "(127.0.0.1) No numbers found in class version reply 'Invalid' - defaulting to class '1'"
266628
267 # THEN: Projector class should be set with default value629 # THEN: Projector class should be set with default value
268 self.assertEqual(pjlink.pjlink_class, '1',630 self.assertEqual(pjlink.pjlink_class, '1',
269 'Non-standard class reply should have set class=1')631 'Non-standard class reply should have set class=1')
270 mock_log.error.assert_called_once_with(log_warn_text)632 mock_log.error.assert_called_once_with(log_text)
271633
272 def test_projector_process_erst_all_ok(self):634 def test_projector_process_erst_all_ok(self):
273 """635 """
@@ -292,15 +654,15 @@
292 # GIVEN: Test object654 # GIVEN: Test object
293 pjlink = pjlink_test655 pjlink = pjlink_test
294 pjlink.projector_errors = None656 pjlink.projector_errors = None
295 log_warn_text = "127.0.0.1) Invalid error status response '11111111': length != 6"657 log_text = "127.0.0.1) Invalid error status response '11111111': length != 6"
296658
297 # WHEN: process_erst called with invalid data (too many values659 # WHEN: process_erst called with invalid data (too many values
298 pjlink.process_erst('11111111')660 pjlink.process_erst('11111111')
299661
300 # THEN: pjlink.projector_errors should be empty and warning logged662 # THEN: pjlink.projector_errors should be empty and warning logged
301 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')663 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
302 self.assertTrue(mock_log.warn.called, 'Warning should have been logged')664 self.assertTrue(mock_log.warning.called, 'Warning should have been logged')
303 mock_log.warn.assert_called_once_with(log_warn_text)665 mock_log.warning.assert_called_once_with(log_text)
304666
305 @patch.object(openlp.core.lib.projector.pjlink, 'log')667 @patch.object(openlp.core.lib.projector.pjlink, 'log')
306 def test_projector_process_erst_data_invalid_nan(self, mock_log):668 def test_projector_process_erst_data_invalid_nan(self, mock_log):
@@ -310,15 +672,15 @@
310 # GIVEN: Test object672 # GIVEN: Test object
311 pjlink = pjlink_test673 pjlink = pjlink_test
312 pjlink.projector_errors = None674 pjlink.projector_errors = None
313 log_warn_text = "(127.0.0.1) Invalid error status response '1111Z1'"675 log_text = "(127.0.0.1) Invalid error status response '1111Z1'"
314676
315 # WHEN: process_erst called with invalid data (too many values677 # WHEN: process_erst called with invalid data (too many values
316 pjlink.process_erst('1111Z1')678 pjlink.process_erst('1111Z1')
317679
318 # THEN: pjlink.projector_errors should be empty and warning logged680 # THEN: pjlink.projector_errors should be empty and warning logged
319 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')681 self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
320 self.assertTrue(mock_log.warn.called, 'Warning should have been logged')682 self.assertTrue(mock_log.warning.called, 'Warning should have been logged')
321 mock_log.warn.assert_called_once_with(log_warn_text)683 mock_log.warning.assert_called_once_with(log_text)
322684
323 def test_projector_process_erst_all_warn(self):685 def test_projector_process_erst_all_warn(self):
324 """686 """
@@ -399,33 +761,67 @@
399 # THEN: Input selected should reflect current input761 # THEN: Input selected should reflect current input
400 self.assertEqual(pjlink.source, '1', 'Input source should be set to "1"')762 self.assertEqual(pjlink.source, '1', 'Input source should be set to "1"')
401763
402 @patch.object(pjlink_test, 'projectorReceivedData')764 @patch.object(pjlink_test, 'projectorUpdateIcons')
403 def test_projector_process_lamp_single(self, mock_projectorReceivedData):765 @patch.object(openlp.core.lib.projector.pjlink, 'log')
404 """766 def test_projector_process_inst(self, mock_log, mock_UpdateIcons):
405 Test status lamp on/off and hours767 """
406 """768 Test saving video source available information
407 # GIVEN: Test object769 """
408 pjlink = pjlink_test770 # GIVEN: Test object
409771 pjlink = pjlink_test
410 # WHEN: Call process_command with lamp data772 pjlink.source_available = []
411 pjlink.process_command('LAMP', '22222 1')773 test_data = '21 10 30 31 11 20'
412774 test_saved = ['10', '11', '20', '21', '30', '31']
413 # THEN: Lamp should have been set with status=ON and hours=22222775 log_data = '(127.0.0.1) Setting projector sources_available to ' \
776 '"[\'10\', \'11\', \'20\', \'21\', \'30\', \'31\']"'
777 mock_UpdateIcons.reset_mock()
778 mock_log.reset_mock()
779
780 # WHEN: process_inst called with test data
781 pjlink.process_inst(data=test_data)
782
783 # THEN: Data should have been sorted and saved properly
784 self.assertEqual(pjlink.source_available, test_saved, "Sources should have been sorted and saved")
785 mock_log.debug.assert_called_once_with(log_data)
786 self.assertTrue(mock_UpdateIcons.emit.called, 'Update Icons should have been called')
787
788 @patch.object(openlp.core.lib.projector.pjlink, 'log')
789 def test_projector_process_lamp_invalid(self, mock_log):
790 """
791 Test status multiple lamp on/off and hours
792 """
793 # GIVEN: Test object
794 pjlink = pjlink_test
795 pjlink.lamp = [{'Hours': 00000, 'On': True},
796 {'Hours': 11111, 'On': False}]
797 log_data = '(127.0.0.1) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"'
798
799 # WHEN: Call process_command with invalid lamp data
800 pjlink.process_lamp('11111 1 22222 0 333A3 1')
801
802 # THEN: lamps should not have changed
803 self.assertEqual(len(pjlink.lamp), 2,
804 'Projector should have kept 2 lamps specified')
414 self.assertEqual(pjlink.lamp[0]['On'], True,805 self.assertEqual(pjlink.lamp[0]['On'], True,
415 'Lamp power status should have been set to TRUE')806 'Lamp 1 power status should have been set to TRUE')
416 self.assertEqual(pjlink.lamp[0]['Hours'], 22222,807 self.assertEqual(pjlink.lamp[0]['Hours'], 00000,
417 'Lamp hours should have been set to 22222')808 'Lamp 1 hours should have been left at 00000')
809 self.assertEqual(pjlink.lamp[1]['On'], False,
810 'Lamp 2 power status should have been set to FALSE')
811 self.assertEqual(pjlink.lamp[1]['Hours'], 11111,
812 'Lamp 2 hours should have been left at 11111')
813 mock_log.warning.assert_called_once_with(log_data)
418814
419 @patch.object(pjlink_test, 'projectorReceivedData')815 def test_projector_process_lamp_multiple(self):
420 def test_projector_process_lamp_multiple(self, mock_projectorReceivedData):
421 """816 """
422 Test status multiple lamp on/off and hours817 Test status multiple lamp on/off and hours
423 """818 """
424 # GIVEN: Test object819 # GIVEN: Test object
425 pjlink = pjlink_test820 pjlink = pjlink_test
821 pjlink.lamps = []
426822
427 # WHEN: Call process_command with lamp data823 # WHEN: Call process_command with lamp data
428 pjlink.process_command('LAMP', '11111 1 22222 0 33333 1')824 pjlink.process_lamp('11111 1 22222 0 33333 1')
429825
430 # THEN: Lamp should have been set with proper lamp status826 # THEN: Lamp should have been set with proper lamp status
431 self.assertEqual(len(pjlink.lamp), 3,827 self.assertEqual(len(pjlink.lamp), 3,
@@ -443,53 +839,112 @@
443 self.assertEqual(pjlink.lamp[2]['Hours'], 33333,839 self.assertEqual(pjlink.lamp[2]['Hours'], 33333,
444 'Lamp 3 hours should have been set to 33333')840 'Lamp 3 hours should have been set to 33333')
445841
446 @patch.object(pjlink_test, 'projectorReceivedData')842 def test_projector_process_lamp_single(self):
843 """
844 Test status lamp on/off and hours
845 """
846 # GIVEN: Test object
847 pjlink = pjlink_test
848 pjlink.lamps = []
849
850 # WHEN: Call process_command with lamp data
851 pjlink.process_lamp('22222 1')
852
853 # THEN: Lamp should have been set with status=ON and hours=22222
854 self.assertEqual(pjlink.lamp[0]['On'], True,
855 'Lamp power status should have been set to TRUE')
856 self.assertEqual(pjlink.lamp[0]['Hours'], 22222,
857 'Lamp hours should have been set to 22222')
858
859 @patch.object(openlp.core.lib.projector.pjlink, 'log')
860 def test_projector_process_name(self, mock_log):
861 """
862 Test saving NAME data from projector
863 """
864 # GIVEN: Test data
865 pjlink = pjlink_test
866 test_data = "Some Name the End-User Set IN Projector"
867 test_log = '(127.0.0.1) Setting projector PJLink name to "Some Name the End-User Set IN Projector"'
868 mock_log.reset_mock()
869
870 # WHEN: process_name called with test data
871 pjlink.process_name(data=test_data)
872
873 # THEN: name should be set and logged
874 self.assertEqual(pjlink.pjlink_name, test_data, 'Name test data should have been saved')
875 mock_log.debug.assert_called_once_with(test_log)
876
447 @patch.object(pjlink_test, 'projectorUpdateIcons')877 @patch.object(pjlink_test, 'projectorUpdateIcons')
448 @patch.object(pjlink_test, 'send_command')878 @patch.object(pjlink_test, 'send_command')
449 @patch.object(pjlink_test, 'change_status')879 @patch.object(pjlink_test, 'change_status')
450 def test_projector_process_powr_on(self,880 def test_projector_process_powr_on(self,
451 mock_change_status,881 mock_change_status,
452 mock_send_command,882 mock_send_command,
453 mock_UpdateIcons,883 mock_UpdateIcons):
454 mock_ReceivedData):
455 """884 """
456 Test status power to ON885 Test status power to ON
457 """886 """
458 # GIVEN: Test object and preset887 # GIVEN: Test object and preset
459 pjlink = pjlink_test888 pjlink = pjlink_test
460 pjlink.power = S_STANDBY889 pjlink.power = S_STANDBY
890 test_data = PJLINK_POWR_STATUS[S_ON]
461891
462 # WHEN: Call process_command with turn power on command892 # WHEN: Call process_command with turn power on command
463 pjlink.process_command('POWR', PJLINK_POWR_STATUS[S_ON])893 pjlink.process_command(cmd='POWR', data=test_data)
464894
465 # THEN: Power should be set to ON895 # THEN: Power should be set to ON
466 self.assertEqual(pjlink.power, S_ON, 'Power should have been set to ON')896 self.assertEqual(pjlink.power, S_ON, 'Power should have been set to ON')
467 mock_send_command.assert_called_once_with('INST')897 mock_send_command.assert_called_once_with('INST')
898 mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])
468 self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')899 self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')
469900
470 @patch.object(pjlink_test, 'projectorReceivedData')901 @patch.object(pjlink_test, 'projectorUpdateIcons')
902 @patch.object(pjlink_test, 'send_command')
903 @patch.object(pjlink_test, 'change_status')
904 def test_projector_process_powr_invalid(self,
905 mock_change_status,
906 mock_send_command,
907 mock_UpdateIcons):
908 """
909 Test process_powr invalid call
910 """
911 # GIVEN: Test object and preset
912 pjlink = pjlink_test
913 pjlink.power = S_STANDBY
914 test_data = '99'
915
916 # WHEN: Call process_command with turn power on command
917 pjlink.process_command(cmd='POWR', data=test_data)
918
919 # THEN: Power should be set to ON
920 self.assertEqual(pjlink.power, S_STANDBY, 'Power should not have changed')
921 self.assertFalse(mock_change_status.called, 'Change status should not have been called')
922 self.assertFalse(mock_send_command.called, 'send_command("INST") should not have been called')
923 self.assertFalse(mock_UpdateIcons.emit.called, 'projectorUpdateIcons should not have been called')
924
471 @patch.object(pjlink_test, 'projectorUpdateIcons')925 @patch.object(pjlink_test, 'projectorUpdateIcons')
472 @patch.object(pjlink_test, 'send_command')926 @patch.object(pjlink_test, 'send_command')
473 @patch.object(pjlink_test, 'change_status')927 @patch.object(pjlink_test, 'change_status')
474 def test_projector_process_powr_off(self,928 def test_projector_process_powr_off(self,
475 mock_change_status,929 mock_change_status,
476 mock_send_command,930 mock_send_command,
477 mock_UpdateIcons,931 mock_UpdateIcons):
478 mock_ReceivedData):
479 """932 """
480 Test status power to STANDBY933 Test status power to STANDBY
481 """934 """
482 # GIVEN: Test object and preset935 # GIVEN: Test object and preset
483 pjlink = pjlink_test936 pjlink = pjlink_test
484 pjlink.power = S_ON937 pjlink.power = S_ON
938 test_data = PJLINK_POWR_STATUS[S_STANDBY]
485939
486 # WHEN: Call process_command with turn power on command940 # WHEN: Call process_command with turn power on command
487 pjlink.process_command('POWR', PJLINK_POWR_STATUS[S_STANDBY])941 pjlink.process_command(cmd='POWR', data=test_data)
488942
489 # THEN: Power should be set to STANDBY943 # THEN: Power should be set to STANDBY
490 self.assertEqual(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY')944 self.assertEqual(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY')
491 self.assertEqual(mock_send_command.called, False, 'send_command should not have been called')
492 self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')945 self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')
946 mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])
947 self.assertFalse(mock_send_command.called, "send_command['INST'] should not have been called")
493948
494 def test_projector_process_rfil_save(self):949 def test_projector_process_rfil_save(self):
495 """950 """
@@ -582,3 +1037,111 @@
582 # THEN: Serial number should be set1037 # THEN: Serial number should be set
583 self.assertNotEquals(pjlink.serial_no, test_number,1038 self.assertNotEquals(pjlink.serial_no, test_number,
584 'Projector serial number should NOT have been set')1039 'Projector serial number should NOT have been set')
1040
1041 @patch.object(openlp.core.lib.projector.pjlink, 'log')
1042 def test_projector_process_sver(self, mock_log):
1043 """
1044 Test invalid software version information - too long
1045 """
1046 # GIVEN: Test object
1047 pjlink = pjlink_test
1048 pjlink.sw_version = None
1049 pjlink.sw_version_received = None
1050 test_data = 'Test 1 Subtest 1'
1051 test_log = "(127.0.0.1) Setting projector software version to 'Test 1 Subtest 1'"
1052 mock_log.reset_mock()
1053
1054 # WHEN: process_sver called with invalid data
1055 pjlink.process_sver(data=test_data)
1056
1057 # THEN: Version information should not change
1058 self.assertEqual(pjlink.sw_version, test_data, 'Software version should have been updated')
1059 self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')
1060 mock_log.debug.assert_called_once_with(test_log)
1061
1062 @patch.object(openlp.core.lib.projector.pjlink, 'log')
1063 def test_projector_process_sver_changed(self, mock_log):
1064 """
1065 Test invalid software version information - Received different than saved
1066 """
1067 # GIVEN: Test object
1068 pjlink = pjlink_test
1069 test_data_new = 'Test 1 Subtest 2'
1070 test_data_old = 'Test 1 Subtest 1'
1071 pjlink.sw_version = test_data_old
1072 pjlink.sw_version_received = None
1073 test_log = '(127.0.0.1) Saving new serial number as sw_version_received'
1074 mock_log.reset_mock()
1075
1076 # WHEN: process_sver called with invalid data
1077 pjlink.process_sver(data=test_data_new)
1078
1079 # THEN: Version information should not change
1080 self.assertEqual(pjlink.sw_version, test_data_old, 'Software version should not have been updated')
1081 self.assertEqual(pjlink.sw_version_received, test_data_new,
1082 'Received software version should have been changed')
1083 self.assertEqual(mock_log.warning.call_count, 4, 'log.warn should have been called 4 times')
1084 # There was 4 calls, but only the last one is checked with this method
1085 mock_log.warning.assert_called_with(test_log)
1086
1087 @patch.object(openlp.core.lib.projector.pjlink, 'log')
1088 def test_projector_process_sver_invalid(self, mock_log):
1089 """
1090 Test invalid software version information - too long
1091 """
1092 # GIVEN: Test object
1093 pjlink = pjlink_test
1094 pjlink.sw_version = None
1095 pjlink.sw_version_received = None
1096 test_data = 'This is a test software version line that is too long based on PJLink version 2 specs'
1097 test_log = "Invalid software version - too long"
1098 mock_log.reset_mock()
1099
1100 # WHEN: process_sver called with invalid data
1101 pjlink.process_sver(data=test_data)
1102
1103 # THEN: Version information should not change
1104 self.assertIsNone(pjlink.sw_version, 'Software version should not have changed')
1105 self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')
1106 mock_log.warning.assert_called_once_with(test_log)
1107
1108 def test_projector_reset_information(self):
1109 """
1110 Test reset_information() resets all information and stops timers
1111 """
1112 # GIVEN: Test object and test data
1113 pjlink = pjlink_test
1114 pjlink.power = S_ON
1115 pjlink.pjlink_name = 'OPENLPTEST'
1116 pjlink.manufacturer = 'PJLINK'
1117 pjlink.model = '1'
1118 pjlink.shutter = True
1119 pjlink.mute = True
1120 pjlink.lamp = True
1121 pjlink.fan = True
1122 pjlink.source_available = True
1123 pjlink.other_info = 'ANOTHER TEST'
1124 pjlink.send_queue = True
1125 pjlink.send_busy = True
1126
1127 # WHEN: reset_information() is called
1128 with patch.object(pjlink, 'timer') as mock_timer:
1129 with patch.object(pjlink, 'socket_timer') as mock_socket_timer:
1130 pjlink.reset_information()
1131
1132 # THEN: All information should be reset and timers stopped
1133 self.assertEqual(pjlink.power, S_OFF, 'Projector power should be OFF')
1134 self.assertIsNone(pjlink.pjlink_name, 'Projector pjlink_name should be None')
1135 self.assertIsNone(pjlink.manufacturer, 'Projector manufacturer should be None')
1136 self.assertIsNone(pjlink.model, 'Projector model should be None')
1137 self.assertIsNone(pjlink.shutter, 'Projector shutter should be None')
1138 self.assertIsNone(pjlink.mute, 'Projector shuttter should be None')
1139 self.assertIsNone(pjlink.lamp, 'Projector lamp should be None')
1140 self.assertIsNone(pjlink.fan, 'Projector fan should be None')
1141 self.assertIsNone(pjlink.source_available, 'Projector source_available should be None')
1142 self.assertIsNone(pjlink.source, 'Projector source should be None')
1143 self.assertIsNone(pjlink.other_info, 'Projector other_info should be None')
1144 self.assertEqual(pjlink.send_queue, [], 'Projector send_queue should be an empty list')
1145 self.assertFalse(pjlink.send_busy, 'Projector send_busy should be False')
1146 self.assertTrue(mock_timer.stop.called, 'Projector timer.stop() should have been called')
1147 self.assertTrue(mock_socket_timer.stop.called, 'Projector socket_timer.stop() should have been called')