From 15f3b0fccabf46384a223897165fde8ffb3f460c Mon Sep 17 00:00:00 2001 From: Phill Date: Sat, 4 May 2019 10:13:29 +0100 Subject: [PATCH 1/7] Seperate some fixes out of annother branch --- openlp/core/app.py | 18 +++++------ openlp/core/common/__init__.py | 4 +-- openlp/core/display/window.py | 2 +- openlp/core/lib/theme.py | 2 +- openlp/core/server.py | 3 +- openlp/core/ui/firsttimewizard.py | 2 +- openlp/core/ui/mainwindow.py | 19 ++++++----- openlp/core/ui/servicemanager.py | 32 ++++++++++++------- openlp/core/ui/slidecontroller.py | 2 +- openlp/core/widgets/dialogs.py | 2 +- openlp/core/widgets/layouts.py | 2 +- openlp/core/widgets/views.py | 6 ++-- .../plugins/bibles/lib/importers/csvbible.py | 2 +- openlp/plugins/images/lib/mediaitem.py | 3 +- .../lib/importers/presentationmanager.py | 2 +- .../plugins/songs/lib/importers/songbeamer.py | 2 +- .../songs/lib/importers/worshipassistant.py | 2 +- .../openlp_core/common/test_init.py | 6 ++-- .../openlp_core/ui/test_mainwindow.py | 1 - 19 files changed, 58 insertions(+), 54 deletions(-) diff --git a/openlp/core/app.py b/openlp/core/app.py index dfb413caa..ab738e1a2 100644 --- a/openlp/core/app.py +++ b/openlp/core/app.py @@ -287,12 +287,12 @@ class OpenLP(QtWidgets.QApplication): return QtWidgets.QApplication.event(self, event) -def parse_options(args=None): +def parse_options(): """ Parse the command line arguments - :param args: list of command line arguments - :return: a tuple of parsed options of type optparse.Value and a list of remaining argsZ + :return: An :object:`argparse.Namespace` insatnce containing the parsed args. + :rtype: argparse.Namespace """ # Set up command line options. parser = argparse.ArgumentParser(prog='openlp') @@ -307,9 +307,9 @@ def parse_options(args=None): dir_name=os.path.join('', '..', '..'))) parser.add_argument('-w', '--no-web-server', dest='no_web_server', action='store_true', help='Turn off the Web and Socket Server ') - parser.add_argument('rargs', nargs='?', default=[]) - # Parse command line options and deal with them. Use args supplied pragmatically if possible. - return parser.parse_args(args) if args else parser.parse_args() + parser.add_argument('rargs', nargs='*', default=[]) + # Parse command line options and deal with them. + return parser.parse_args() def set_up_logging(log_path): @@ -328,13 +328,11 @@ def set_up_logging(log_path): print('Logging to: {name}'.format(name=file_path)) -def main(args=None): +def main(): """ The main function which parses command line options and then runs - - :param args: Some args """ - args = parse_options(args) + args = parse_options() qt_args = ['--disable-web-security'] # qt_args = [] if args and args.loglevel.lower() in ['d', 'debug']: diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index dfed903c7..fd251be14 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -134,8 +134,8 @@ def extension_loader(glob_pattern, excluded_files=[]): importlib.import_module(module_name) except (ImportError, OSError): # On some platforms importing vlc.py might cause OSError exceptions. (e.g. Mac OS X) - log.warning('Failed to import {module_name} on path {extension_path}' - .format(module_name=module_name, extension_path=extension_path)) + log.exception('Failed to import {module_name} on path {extension_path}' + .format(module_name=module_name, extension_path=extension_path)) def path_to_module(path): diff --git a/openlp/core/display/window.py b/openlp/core/display/window.py index 6b2e9af1b..161b49981 100644 --- a/openlp/core/display/window.py +++ b/openlp/core/display/window.py @@ -180,7 +180,7 @@ class DisplayWindow(QtWidgets.QWidget): """ Set the URL of the webview - :param str url: The URL to set + :param QtCore.QUrl | str url: The URL to set """ if not isinstance(url, QtCore.QUrl): url = QtCore.QUrl(url) diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index 4bc145c72..f770b7487 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -333,7 +333,7 @@ class Theme(object): else: # make string value unicode if not isinstance(value, str): - value = str(str(value), 'utf-8') + value = str(value, 'utf-8') # None means an empty string so lets have one. if value == 'None': value = '' diff --git a/openlp/core/server.py b/openlp/core/server.py index 7c7842853..33c024254 100644 --- a/openlp/core/server.py +++ b/openlp/core/server.py @@ -22,6 +22,7 @@ from PyQt5 import QtCore, QtNetwork from openlp.core.common.mixins import LogMixin +from openlp.core.common.path import Path from openlp.core.common.registry import Registry @@ -97,7 +98,7 @@ class Server(QtCore.QObject, LogMixin): msg = self.in_stream.readLine() if msg: self.log_debug("socket msg = " + msg) - Registry().get('service_manager').on_load_service_clicked(msg) + Registry().get('service_manager').load_service(Path(msg)) def close_server(self): """ diff --git a/openlp/core/ui/firsttimewizard.py b/openlp/core/ui/firsttimewizard.py index 87b044ac0..8cb967a54 100644 --- a/openlp/core/ui/firsttimewizard.py +++ b/openlp/core/ui/firsttimewizard.py @@ -78,7 +78,7 @@ class ThemeListWidget(QtWidgets.QListWidget): """ nominal_width = 141 # Icon width of 133 + 4 each side max_items_per_row = self.viewport().width() // nominal_width or 1 # or 1 to avoid divide by 0 errors - col_size = (self.viewport().width() - 1) / max_items_per_row + col_size = (self.viewport().width() - 1) // max_items_per_row self.setGridSize(QtCore.QSize(col_size, 140)) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 3443185ae..703bdc943 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -22,7 +22,7 @@ """ This is the main window, where all the action happens. """ -import sys +import os from datetime import datetime from distutils import dir_util from distutils.errors import DistutilsFileError @@ -475,7 +475,6 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert super(MainWindow, self).__init__() Registry().register('main_window', self) self.clipboard = self.application.clipboard() - self.arguments = ''.join(self.application.args) # Set up settings sections for the main application (not for use by plugins). self.ui_settings_section = 'user interface' self.general_settings_section = 'core' @@ -632,8 +631,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert # if self.live_controller.display.isVisible(): # self.live_controller.display.setFocus() self.activateWindow() - if self.arguments: - self.open_cmd_line_files(self.arguments) + if self.application.args: + self.open_cmd_line_files(self.application.args) elif Settings().value(self.general_settings_section + '/auto open'): self.service_manager_contents.load_last_file() # This will store currently used layout preset so it remains enabled on next startup. @@ -1339,7 +1338,7 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert self.application.set_normal_cursor() self.log_exception('Data copy failed {err}'.format(err=str(why))) err_text = translate('OpenLP.MainWindow', - 'OpenLP Data directory copy failed\n\n{err}').format(err=str(why)), + 'OpenLP Data directory copy failed\n\n{err}').format(err=str(why)) QtWidgets.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'New Data Directory Error'), err_text, QtWidgets.QMessageBox.StandardButtons(QtWidgets.QMessageBox.Ok)) @@ -1354,11 +1353,11 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert settings.remove('advanced/data path') self.application.set_normal_cursor() - def open_cmd_line_files(self, filename): + def open_cmd_line_files(self, args): """ Open files passed in through command line arguments """ - if not isinstance(filename, str): - filename = str(filename, sys.getfilesystemencoding()) - if filename.endswith(('.osz', '.oszl')): - self.service_manager_contents.load_file(Path(filename)) + for arg in args: + file_name = os.path.expanduser(arg) + if os.path.isfile(file_name): + self.service_manager_contents.load_file(Path(file_name)) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 9303dae35..3858e1f48 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -430,11 +430,20 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi return False self.new_file() - def on_load_service_clicked(self, load_file=None): + def on_load_service_clicked(self, checked): + """ + Handle the `fileOpenItem` action + + :param bool checked: Not used. + :rtype: None + """ + self.load_service() + + def load_service(self, file_path=None): """ Loads the service file and saves the existing one it there is one unchanged. - :param load_file: The service file to the loaded. Will be None is from menu so selection will be required. + :param openlp.core.common.path.Path | None file_path: The service file to the loaded. """ if self.is_modified(): result = self.save_modified_service() @@ -442,7 +451,7 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi return False elif result == QtWidgets.QMessageBox.Save: self.decide_save_method() - if not load_file: + if not file_path: file_path, filter_used = FileDialog.getOpenFileName( self.main_window, translate('OpenLP.ServiceManager', 'Open File'), @@ -450,8 +459,6 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz *.oszl)')) if not file_path: return False - else: - file_path = str_to_path(load_file) Settings().setValue(self.main_window.service_manager_settings_section + '/last directory', file_path.parent) self.load_file(file_path) @@ -670,8 +677,9 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi def load_file(self, file_path): """ - Load an existing service file - :param file_path: + Load an existing service file. + + :param openlp.core.common.path.Path file_path: The service file to load. """ if not file_path.exists(): return False @@ -1520,12 +1528,12 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi event.setDropAction(QtCore.Qt.CopyAction) event.accept() for url in link.urls(): - file_name = url.toLocalFile() - if file_name.endswith('.osz'): - self.on_load_service_clicked(file_name) - elif file_name.endswith('.oszl'): + file_path = Path(url.toLocalFile()) + if file_path.suffix == '.osz': + self.load_service(file_path) + elif file_path.suffix == '.oszl': # todo correct - self.on_load_service_clicked(file_name) + self.load_service(file_path) elif link.hasText(): plugin = link.text() item = self.service_manager_list.itemAt(event.pos()) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index b5855d3d3..437dbf88c 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -112,7 +112,7 @@ class MediaSlider(QtWidgets.QSlider): class InfoLabel(QtWidgets.QLabel): """ - InfoLabel is a subclassed QLabel. Created to provide the ablilty to add a ellipsis if the text is cut off. Original + InfoLabel is a subclassed QLabel. Created to provide the ability to add a ellipsis if the text is cut off. Original source: https://stackoverflow.com/questions/11446478/pyside-pyqt-truncate-text-in-qlabel-based-on-minimumsize """ diff --git a/openlp/core/widgets/dialogs.py b/openlp/core/widgets/dialogs.py index 7668dcab8..11083f393 100755 --- a/openlp/core/widgets/dialogs.py +++ b/openlp/core/widgets/dialogs.py @@ -35,7 +35,7 @@ class FileDialog(QtWidgets.QFileDialog): :type caption: str :type directory: openlp.core.common.path.Path :type options: QtWidgets.QFileDialog.Options - :rtype: tuple[openlp.core.common.path.Path, str] + :rtype: openlp.core.common.path.Path """ args, kwargs = replace_params(args, kwargs, ((2, 'directory', path_to_str),)) diff --git a/openlp/core/widgets/layouts.py b/openlp/core/widgets/layouts.py index 65c61e266..0b46bf3f6 100644 --- a/openlp/core/widgets/layouts.py +++ b/openlp/core/widgets/layouts.py @@ -37,7 +37,7 @@ class AspectRatioLayout(QtWidgets.QLayout): """ Create a layout. - :param PyQt5.QtWidgets.QWidget parent: The parent widget, can be None. + :param QtWidgets.QWidget | None parent: The parent widget :param float aspect_ratio: The aspect ratio as a float (e.g. 16.0/9.0) """ super().__init__(parent) diff --git a/openlp/core/widgets/views.py b/openlp/core/widgets/views.py index 68422e1b4..dbe7c2be6 100644 --- a/openlp/core/widgets/views.py +++ b/openlp/core/widgets/views.py @@ -39,7 +39,7 @@ def handle_mime_data_urls(mime_data): """ Process the data from a drag and drop operation. - :param PyQt5.QtCore.QMimeData mime_data: The mime data from the drag and drop opperation. + :param QtCore.QMimeData mime_data: The mime data from the drag and drop opperation. :return: A list of file paths that were dropped :rtype: list[openlp.core.common.path.Path] """ @@ -297,7 +297,7 @@ class ListWidgetWithDnD(QtWidgets.QListWidget): """ self.setAcceptDrops(True) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) - Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().load_file) + Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().handle_mime_data) def clear(self, search_while_typing=False): """ @@ -412,7 +412,7 @@ class TreeWidgetWithDnD(QtWidgets.QTreeWidget): """ self.setAcceptDrops(True) self.setDragDropMode(QtWidgets.QAbstractItemView.DragDrop) - Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().load_file) + Registry().register_function(('%s_dnd' % self.mime_data_text), self.parent().handle_mime_data) Registry().register_function(('%s_dnd_internal' % self.mime_data_text), self.parent().dnd_move_internal) def mouseMoveEvent(self, event): diff --git a/openlp/plugins/bibles/lib/importers/csvbible.py b/openlp/plugins/bibles/lib/importers/csvbible.py index 694784f80..0f273de8b 100644 --- a/openlp/plugins/bibles/lib/importers/csvbible.py +++ b/openlp/plugins/bibles/lib/importers/csvbible.py @@ -102,7 +102,7 @@ class CSVBible(BibleImport): :rtype: list[namedtuple] """ try: - encoding = get_file_encoding(file_path)['encoding'] + encoding = get_file_encoding(file_path) with file_path.open('r', encoding=encoding, newline='') as csv_file: csv_reader = csv.reader(csv_file, delimiter=',', quotechar='"') return [results_tuple(*line) for line in csv_reader] diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 14bef3f0e..9909198cf 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -401,10 +401,9 @@ class ImageMediaItem(MediaManagerItem): Process a list for files either from the File Dialog or from Drag and Drop. This method is overloaded from MediaManagerItem. - :param files: A List of strings containing the filenames of the files to be loaded + :param list[openlp.core.common.path.Path] file_paths: A List of paths to be loaded :param target_group: The QTreeWidgetItem of the group that will be the parent of the added files """ - file_paths = [Path(file) for file in file_paths] self.application.set_normal_cursor() self.load_list(file_paths, target_group) last_dir = file_paths[0].parent diff --git a/openlp/plugins/songs/lib/importers/presentationmanager.py b/openlp/plugins/songs/lib/importers/presentationmanager.py index ae673dcab..6647222cb 100644 --- a/openlp/plugins/songs/lib/importers/presentationmanager.py +++ b/openlp/plugins/songs/lib/importers/presentationmanager.py @@ -48,7 +48,7 @@ class PresentationManagerImport(SongImport): tree = etree.parse(str(file_path), parser=etree.XMLParser(recover=True)) except etree.XMLSyntaxError: # Try to detect encoding and use it - encoding = get_file_encoding(file_path)['encoding'] + encoding = get_file_encoding(file_path) # Open file with detected encoding and remove encoding declaration text = file_path.read_text(encoding=encoding) text = re.sub(r'.+\?>\n', '', text) diff --git a/openlp/plugins/songs/lib/importers/songbeamer.py b/openlp/plugins/songs/lib/importers/songbeamer.py index d5ba82bd0..0fe42c541 100644 --- a/openlp/plugins/songs/lib/importers/songbeamer.py +++ b/openlp/plugins/songs/lib/importers/songbeamer.py @@ -124,7 +124,7 @@ class SongBeamerImport(SongImport): self.chord_table = None if file_path.is_file(): # Detect the encoding - self.input_file_encoding = get_file_encoding(file_path)['encoding'] + self.input_file_encoding = get_file_encoding(file_path) # The encoding should only be ANSI (cp1252), UTF-8, Unicode, Big-Endian-Unicode. # So if it doesn't start with 'u' we default to cp1252. See: # https://forum.songbeamer.com/viewtopic.php?p=419&sid=ca4814924e37c11e4438b7272a98b6f2 diff --git a/openlp/plugins/songs/lib/importers/worshipassistant.py b/openlp/plugins/songs/lib/importers/worshipassistant.py index 15f14122f..4cc374f8f 100644 --- a/openlp/plugins/songs/lib/importers/worshipassistant.py +++ b/openlp/plugins/songs/lib/importers/worshipassistant.py @@ -82,7 +82,7 @@ class WorshipAssistantImport(SongImport): Receive a CSV file to import. """ # Get encoding - encoding = get_file_encoding(self.import_source)['encoding'] + encoding = get_file_encoding(self.import_source) with self.import_source.open('r', encoding=encoding) as songs_file: songs_reader = csv.DictReader(songs_file, escapechar='\\') try: diff --git a/tests/functional/openlp_core/common/test_init.py b/tests/functional/openlp_core/common/test_init.py index e968cce1f..d7320114e 100644 --- a/tests/functional/openlp_core/common/test_init.py +++ b/tests/functional/openlp_core/common/test_init.py @@ -322,7 +322,7 @@ class TestInit(TestCase, TestMixin): mocked_open.assert_called_once_with('rb') assert mocked_universal_detector_inst.feed.mock_calls == [call(b'data' * 256)] mocked_universal_detector_inst.close.assert_called_once_with() - assert result == encoding_result + assert result == 'UTF-8' def test_get_file_encoding_eof(self): """ @@ -344,7 +344,7 @@ class TestInit(TestCase, TestMixin): mocked_open.assert_called_once_with('rb') assert mocked_universal_detector_inst.feed.mock_calls == [call(b'data' * 256), call(b'data' * 4)] mocked_universal_detector_inst.close.assert_called_once_with() - assert result == encoding_result + assert result == 'UTF-8' def test_get_file_encoding_oserror(self): """ @@ -367,4 +367,4 @@ class TestInit(TestCase, TestMixin): mocked_log.exception.assert_called_once_with('Error detecting file encoding') mocked_universal_detector_inst.feed.assert_not_called() mocked_universal_detector_inst.close.assert_called_once_with() - assert result == encoding_result + assert result == 'UTF-8' diff --git a/tests/functional/openlp_core/ui/test_mainwindow.py b/tests/functional/openlp_core/ui/test_mainwindow.py index 6a7e02430..1d1929286 100644 --- a/tests/functional/openlp_core/ui/test_mainwindow.py +++ b/tests/functional/openlp_core/ui/test_mainwindow.py @@ -108,7 +108,6 @@ class TestMainWindow(TestCase, TestMixin): """ # GIVEN a non service file as an argument to openlp service = 'run_openlp.py' - self.main_window.arguments = service # WHEN the argument is processed self.main_window.open_cmd_line_files(service) From a503c61a51b6b33065559d07eb325529a1b3557d Mon Sep 17 00:00:00 2001 From: Ken Roberts Date: Sat, 4 May 2019 03:21:48 -0700 Subject: [PATCH 2/7] PJLink2 update v05 --- openlp/core/projectors/pjlink.py | 20 +- openlp/core/projectors/pjlinkcommands.py | 12 +- .../test_projector_command_routing.py | 107 +++- .../projectors/test_projector_commands_01.py | 549 ++++++++++++++++++ ...ds_01.py => test_projector_commands_02.py} | 397 +------------ .../test_projector_pjlink_cmd_routing.py | 121 +--- 6 files changed, 689 insertions(+), 517 deletions(-) create mode 100644 tests/openlp_core/projectors/test_projector_commands_01.py rename tests/openlp_core/projectors/{test_projector_pjlink_commands_01.py => test_projector_commands_02.py} (54%) diff --git a/openlp/core/projectors/pjlink.py b/openlp/core/projectors/pjlink.py index 1383b27d8..5aa6f2b20 100644 --- a/openlp/core/projectors/pjlink.py +++ b/openlp/core/projectors/pjlink.py @@ -861,6 +861,24 @@ class PJLink(QtNetwork.QTcpSocket): log.debug('({ip}) Sending POWR command'.format(ip=self.entry.name)) return self.send_command(cmd='POWR', priority=priority) + def set_audio_mute(self, priority=False): + """ + Send command to set audio to muted + """ + log.debug('({ip}) Setting AVMT to 21 (audio mute)'.format(ip=self.entry.name)) + self.send_command(cmd='AVMT', opts='21', priority=True) + self.status_timer_add(cmd='AVMT', callback=self.get_av_mute_status) + self.poll_loop() + + def set_audio_normal(self, priority=False): + """ + Send command to set audio to normal + """ + log.debug('({ip}) Setting AVMT to 20 (audio normal)'.format(ip=self.entry.name)) + self.send_command(cmd='AVMT', opts='20', priority=True) + self.status_timer_add(cmd='AVMT', callback=self.get_av_mute_status) + self.poll_loop() + def set_input_source(self, src=None): """ Verify input source available as listed in 'INST' command, @@ -924,9 +942,9 @@ class PJLink(QtNetwork.QTcpSocket): log.warning('({ip}) "{cmd}" already in checks - returning'.format(ip=self.entry.name, cmd=cmd)) return log.debug('({ip}) Adding "{cmd}" callback for status timer'.format(ip=self.entry.name, cmd=cmd)) + self.status_timer_checks[cmd] = callback if not self.status_timer.isActive(): self.status_timer.start() - self.status_timer_checks[cmd] = callback def status_timer_delete(self, cmd): """ diff --git a/openlp/core/projectors/pjlinkcommands.py b/openlp/core/projectors/pjlinkcommands.py index 1834acc03..6df155db1 100644 --- a/openlp/core/projectors/pjlinkcommands.py +++ b/openlp/core/projectors/pjlinkcommands.py @@ -113,15 +113,21 @@ def process_avmt(projector, data): '31': {'shutter': True, 'mute': True} } if data not in settings: - log.warning('({ip}) Invalid shutter response: {data}'.format(ip=projector.entry.name, data=data)) + log.warning('({ip}) Invalid av mute response: {data}'.format(ip=projector.entry.name, data=data)) return shutter = settings[data]['shutter'] mute = settings[data]['mute'] # Check if we need to update the icons update_icons = (shutter != projector.shutter) or (mute != projector.mute) - projector.shutter = shutter - projector.mute = mute if update_icons: + if projector.shutter != shutter: + projector.shutter = shutter + log.debug('({ip}) Setting shutter to {chk}'.format(ip=projector.entry.name, + chk='closed' if shutter else 'open')) + if projector.mute != mute: + projector.mute = mute + log.debug('({ip}) Setting speaker to {chk}'.format(ip=projector.entry.name, + chk='muted' if shutter else 'normal')) if 'AVMT' in projector.status_timer_checks: projector.status_timer_delete('AVMT') projector.projectorUpdateIcons.emit() diff --git a/tests/openlp_core/projectors/test_projector_command_routing.py b/tests/openlp_core/projectors/test_projector_command_routing.py index 38721eb24..866ee3132 100644 --- a/tests/openlp_core/projectors/test_projector_command_routing.py +++ b/tests/openlp_core/projectors/test_projector_command_routing.py @@ -28,7 +28,8 @@ from unittest.mock import call, patch import openlp.core.projectors.pjlink from openlp.core.projectors.pjlinkcommands import process_command -from openlp.core.projectors.constants import E_UNDEFINED, S_DATA_OK +from openlp.core.projectors.constants import E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED, \ + S_DATA_OK, PJLINK_ERRORS, STATUS_MSG from openlp.core.projectors.db import Projector from openlp.core.projectors.pjlink import PJLink from tests.resources.projector.data import TEST1_DATA @@ -114,19 +115,111 @@ class TestPJLinkRouting(TestCase): assert (chk == S_DATA_OK), 'Should have returned S_DATA_OK' @patch.object(openlp.core.projectors.pjlinkcommands, 'log') - def test_routing_pjink_errors(self, mock_log): + def test_routing_pjink_err1(self, mock_log): """ - Test rouing when PJLink error received (err1, err2, err3, err4, erra) + Test rouing when PJLink ERR1 received """ # GIVEN: Test setup - log_error_text = [call('({ip}) CLSS: PJLink returned "ERR1: Undefined Command"'.format(ip=self.pjlink.name))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR1"'.format(ip=self.pjlink.name))] err_code = E_UNDEFINED + err_msg = STATUS_MSG[err_code] + err_str = PJLINK_ERRORS[err_code] + + log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name, + err=err_str))] # WHEN: routing called - chk = process_command(projector=self.pjlink, cmd='CLSS', data='ERR1') + chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str) # THEN: Appropriate log entries should have been made and methods called/not called mock_log.error.assert_has_calls(log_error_text) mock_log.debug.assert_has_calls(log_debug_text) - assert (chk == err_code), 'Should have returned E_UNDEFINED' + assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code]) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_routing_pjink_err2(self, mock_log): + """ + Test rouing when PJLink ERR2 received + """ + # GIVEN: Test setup + err_code = E_PARAMETER + err_msg = STATUS_MSG[err_code] + err_str = PJLINK_ERRORS[err_code] + + log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name, + err=err_str))] + + # WHEN: routing called + chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str) + + # THEN: Appropriate log entries should have been made and methods called/not called + mock_log.error.assert_has_calls(log_error_text) + mock_log.debug.assert_has_calls(log_debug_text) + assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code]) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_routing_pjink_err3(self, mock_log): + """ + Test rouing when PJLink ERR3 received + """ + # GIVEN: Test setup + err_code = E_UNAVAILABLE + err_msg = STATUS_MSG[err_code] + err_str = PJLINK_ERRORS[err_code] + + log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name, + err=err_str))] + + # WHEN: routing called + chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str) + + # THEN: Appropriate log entries should have been made and methods called/not called + mock_log.error.assert_has_calls(log_error_text) + mock_log.debug.assert_has_calls(log_debug_text) + assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code]) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_routing_pjink_err4(self, mock_log): + """ + Test rouing when PJLink ERR4 received + """ + # GIVEN: Test setup + err_code = E_PROJECTOR + err_msg = STATUS_MSG[err_code] + err_str = PJLINK_ERRORS[err_code] + + log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name, + err=err_str))] + + # WHEN: routing called + chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str) + + # THEN: Appropriate log entries should have been made and methods called/not called + mock_log.error.assert_has_calls(log_error_text) + mock_log.debug.assert_has_calls(log_debug_text) + assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code]) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_routing_pjink_errA(self, mock_log): + """ + Test rouing when PJLink ERRA received + """ + # GIVEN: Test setup + err_code = E_AUTHENTICATION + err_msg = STATUS_MSG[err_code] + err_str = PJLINK_ERRORS[err_code] + + log_error_text = [call('({ip}) CLSS: {err}'.format(ip=self.pjlink.name, err=err_msg))] + log_debug_text = [call('({ip}) Processing command "CLSS" with data "{err}"'.format(ip=self.pjlink.name, + err=err_str))] + + # WHEN: routing called + chk = process_command(projector=self.pjlink, cmd='CLSS', data=err_str) + + # THEN: Appropriate log entries should have been made and methods called/not called + mock_log.error.assert_has_calls(log_error_text) + mock_log.debug.assert_has_calls(log_debug_text) + assert (chk == err_code), 'Should have returned {err}'.format(err=PJLINK_ERRORS[err_code]) diff --git a/tests/openlp_core/projectors/test_projector_commands_01.py b/tests/openlp_core/projectors/test_projector_commands_01.py new file mode 100644 index 000000000..64fa4c1fc --- /dev/null +++ b/tests/openlp_core/projectors/test_projector_commands_01.py @@ -0,0 +1,549 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 + +########################################################################## +# OpenLP - Open Source Lyrics Projection # +# ---------------------------------------------------------------------- # +# Copyright (c) 2008-2019 OpenLP Developers # +# ---------------------------------------------------------------------- # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +########################################################################## +""" +Package to test the openlp.core.projectors.pjlink commands package. +""" +from unittest import TestCase +from unittest.mock import call, patch + +import openlp.core.projectors.pjlink +from openlp.core.projectors.pjlinkcommands import process_command +from openlp.core.projectors.constants import E_ERROR, E_WARN, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, S_OK +from openlp.core.projectors.db import Projector +from openlp.core.projectors.pjlink import PJLink +from tests.resources.projector.data import TEST1_DATA + + +class TestPJLinkCommands(TestCase): + """ + Tests PJLink get status commands part 1 + """ + def setUp(self): + """ + Initial test setup + """ + self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) + + def tearDown(self): + """ + Test reset + """ + del(self.pjlink) + + @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_avmt_audio_muted(self, mock_log, mock_UpdateIcons): + """ + Test avmt status shutter unchanged and mute on + """ + # GIVEN: Test setup + log_warning_text = [] + log_debug_text = [call('({ip}) Processing command "AVMT" with data "21"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), + call('({ip}) Setting speaker to muted'.format(ip=self.pjlink.name))] + self.pjlink.shutter = True + self.pjlink.mute = False + + # WHEN: Called with setting shutter closed and mute on + process_command(projector=self.pjlink, cmd='AVMT', data='21') + + # THEN: Shutter should be closed and mute should be True + assert self.pjlink.shutter, 'Shutter should not have changed' + assert self.pjlink.mute, 'Audio should be off' + assert mock_UpdateIcons.emit.called, 'Update icons should have been called' + mock_log.warning.assert_has_calls(log_warning_text) + mock_log.debug.assert_has_calls(log_debug_text) + + @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_avmt_bad_data(self, mock_log, mock_UpdateIcons): + """ + Test avmt bad data fail + """ + # GIVEN: Test object + log_warning_text = [call('({ip}) Invalid av mute response: 36'.format(ip=self.pjlink.name))] + log_debug_text = [call('({ip}) Processing command "AVMT" with data "36"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name))] + self.pjlink.shutter = True + self.pjlink.mute = True + + # WHEN: Called with an invalid setting + process_command(projector=self.pjlink, cmd='AVMT', data='36') + + # THEN: Shutter should be closed and mute should be True + assert self.pjlink.shutter, 'Shutter should changed' + assert self.pjlink.mute, 'Audio should not have changed' + assert (not mock_UpdateIcons.emit.called), 'Update icons should NOT have been called' + mock_log.warning.assert_has_calls(log_warning_text) + mock_log.debug.assert_has_calls(log_debug_text) + + @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_avmt_closed_muted(self, mock_log, mock_UpdateIcons): + """ + Test avmt status shutter closed and mute off + """ + # GIVEN: Test object + log_warning_text = [] + log_debug_text = [call('({ip}) Processing command "AVMT" with data "31"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), + call('({ip}) Setting shutter to closed'.format(ip=self.pjlink.name)), + call('({ip}) Setting speaker to muted'.format(ip=self.pjlink.name))] + self.pjlink.shutter = False + self.pjlink.mute = False + + # WHEN: Called with setting shutter to closed and mute on + process_command(projector=self.pjlink, cmd='AVMT', data='31') + + # THEN: Shutter should be closed and mute should be True + assert self.pjlink.shutter, 'Shutter should have been set to closed' + assert self.pjlink.mute, 'Audio should be muted' + assert mock_UpdateIcons.emit.called, 'Update icons should have been called' + mock_log.warning.assert_has_calls(log_warning_text) + mock_log.debug.assert_has_calls(log_debug_text) + + @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_avmt_open_unmuted(self, mock_log, mock_UpdateIcons): + """ + Test avmt status shutter open and mute off + """ + # GIVEN: Test object + log_warning_text = [] + log_debug_text = [call('({ip}) Processing command "AVMT" with data "30"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), + call('({ip}) Setting shutter to open'.format(ip=self.pjlink.name)), + call('({ip}) Setting speaker to normal'.format(ip=self.pjlink.name))] + self.pjlink.shutter = True + self.pjlink.mute = True + + # WHEN: Called with setting shutter to closed and mute on + process_command(projector=self.pjlink, cmd='AVMT', data='30') + + # THEN: Shutter should be closed and mute should be True + assert (not self.pjlink.shutter), 'Shutter should have been set to off' + assert (not self.pjlink.mute), 'Audio should be on' + assert mock_UpdateIcons.emit.called, 'Update icons should have been called' + mock_log.warning.assert_has_calls(log_warning_text) + mock_log.debug.assert_has_calls(log_debug_text) + + @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_avmt_shutter_closed(self, mock_log, mock_UpdateIcons): + """ + Test avmt status shutter closed and audio unchanged + """ + # GIVEN: Test object + log_warning_text = [] + log_debug_text = [call('({ip}) Processing command "AVMT" with data "11"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), + call('({ip}) Setting shutter to closed'.format(ip=self.pjlink.name))] + self.pjlink.shutter = False + self.pjlink.mute = True + + # WHEN: Called with setting shutter closed and mute off + process_command(projector=self.pjlink, cmd='AVMT', data='11') + + # THEN: Shutter should be True and mute should be False + assert self.pjlink.shutter, 'Shutter should have been set to closed' + assert self.pjlink.mute, 'Audio should not have changed' + assert mock_UpdateIcons.emit.called, 'Update icons should have been called' + mock_log.warning.assert_has_calls(log_warning_text) + mock_log.debug.assert_has_calls(log_debug_text) + + @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_avmt_status_timer_check_delete(self, mock_log, mock_UpdateIcons): + """ + Test avmt deletes callback in projector.status_timer_check + """ + # GIVEN: Test object + log_warning_text = [] + log_debug_text = [call('({ip}) Processing command "AVMT" with data "11"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for AVMT'.format(ip=self.pjlink.name)), + call('({ip}) Setting shutter to closed'.format(ip=self.pjlink.name))] + self.pjlink.shutter = False + self.pjlink.mute = True + self.pjlink.status_timer_checks = {'AVMT': self.pjlink.get_av_mute_status} + + # WHEN: Called with setting shutter closed and mute off + with patch.object(self.pjlink, 'status_timer') as mock_status_timer: + process_command(projector=self.pjlink, cmd='AVMT', data='11') + + # THEN: Shutter should be True and mute should be False + assert self.pjlink.shutter, 'Shutter should have been set to closed' + assert self.pjlink.mute, 'Audio should not have changed' + assert mock_UpdateIcons.emit.called, 'Update icons should have been called' + assert ('AVMT' not in self.pjlink.status_timer_checks), 'Status timer list should not have AVMT callback' + assert mock_status_timer.stop.called, 'Projector status_timer.stop() should have been called' + mock_log.warning.assert_has_calls(log_warning_text) + mock_log.debug.assert_has_calls(log_debug_text) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_clss_1(self, mock_log): + """ + Test CLSS request returns non-standard reply 1 + """ + # GIVEN: Test object + log_error_calls = [] + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "CLSS" with data "1"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), + call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] + + # WHEN: Process non-standard reply + process_command(projector=self.pjlink, cmd='CLSS', data='1') + + # THEN: Projector class should be set with proper value + assert ('1' == self.pjlink.pjlink_class), 'Should have set class=1' + 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) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_clss_2(self, mock_log): + """ + Test CLSS request returns non-standard reply 1 + """ + # GIVEN: Test object + log_error_calls = [] + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "CLSS" with data "2"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), + call('({ip}) Setting pjlink_class for this projector to "2"'.format(ip=self.pjlink.name))] + + # WHEN: Process non-standard reply + process_command(projector=self.pjlink, cmd='CLSS', data='2') + + # THEN: Projector class should be set with proper value + assert ('2' == self.pjlink.pjlink_class), 'Should have set class=2' + 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) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_clss_invalid_nan(self, mock_log): + """ + Test CLSS reply has no class number + """ + # GIVEN: Test setup + log_error_calls = [call('({ip}) NAN CLSS version reply "Z" - ' + 'defaulting to class "1"'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Z"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), + call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] + + # WHEN: Process invalid reply + process_command(projector=self.pjlink, cmd='CLSS', data='Z') + + # THEN: Projector class should be set with default value + assert (self.pjlink.pjlink_class == '1'), 'Invalid NaN class reply should have set class=1' + mock_log.error.assert_has_calls(log_error_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_clss_invalid_no_version(self, mock_log): + """ + Test CLSS reply has no class number + """ + # GIVEN: Test object + log_error_calls = [call('({ip}) No numbers found in class version reply "Invalid" ' + '- defaulting to class "1"'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Invalid"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), + call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] + + # WHEN: Process invalid reply + process_command(projector=self.pjlink, cmd='CLSS', data='Invalid') + + # THEN: Projector class should be set with default value + assert (self.pjlink.pjlink_class == '1'), 'Invalid class reply should have set class=1' + mock_log.error.assert_has_calls(log_error_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_clss_nonstandard_reply_1(self, mock_log): + """ + Test CLSS request returns non-standard reply 1 + """ + # GIVEN: Test object + log_error_calls = [] + log_warning_calls = [call('({ip}) Non-standard CLSS reply: "Class 1"'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Class 1"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), + call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] + + # WHEN: Process non-standard reply + process_command(projector=self.pjlink, cmd='CLSS', data='Class 1') + + # THEN: Projector class should be set with proper value + assert ('1' == self.pjlink.pjlink_class), 'Non-standard class reply should have set class=1' + 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) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_clss_nonstandard_reply_2(self, mock_log): + """ + Test CLSS request returns non-standard reply 1 + """ + # GIVEN: Test object + log_warning_calls = [call('({ip}) Non-standard CLSS reply: "Version2"'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Version2"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), + call('({ip}) Setting pjlink_class for this projector to "2"'.format(ip=self.pjlink.name))] + + # WHEN: Process non-standard reply + process_command(projector=self.pjlink, cmd='CLSS', data='Version2') + + # THEN: Projector class should be set with proper value + assert ('2' == self.pjlink.pjlink_class), 'Non-standard class reply should have set class=1' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_erst_all_error(self, mock_log): + """ + Test test_projector_process_erst_all_error + """ + # GIVEN: Test object + chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_ERROR], + lamp=PJLINK_ERST_STATUS[E_ERROR], + temp=PJLINK_ERST_STATUS[E_ERROR], + cover=PJLINK_ERST_STATUS[E_ERROR], + filt=PJLINK_ERST_STATUS[E_ERROR], + other=PJLINK_ERST_STATUS[E_ERROR]) + chk_test = {'Fan': E_ERROR, + 'Lamp': E_ERROR, + 'Temperature': E_ERROR, + 'Cover': E_ERROR, + 'Filter': E_ERROR, + 'Other': E_ERROR} + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "ERST" with data "{chk}"'.format(ip=self.pjlink.name, + chk=chk_data)), + call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] + self.pjlink.projector_errors = None + + # WHEN: process_erst with status set to WARN + process_command(projector=self.pjlink, cmd='ERST', data=chk_data) + + # THEN: PJLink instance errors should match chk_value + assert (self.pjlink.projector_errors == chk_test), 'Projector errors should be all E_ERROR' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_erst_all_ok(self, mock_log): + """ + Test to verify pjlink.projector_errors is set to None when no errors + """ + # GIVEN: Test object + chk_data = '0' * PJLINK_ERST_DATA['DATA_LENGTH'] + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "ERST" with data "{chk}"'.format(ip=self.pjlink.name, + chk=chk_data)), + call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] + + # WHEN: process_erst with no errors + process_command(projector=self.pjlink, cmd='ERST', data=chk_data) + + # THEN: PJLink instance errors should be None + assert (self.pjlink.projector_errors is None), 'projector_errors should have been set to None' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_erst_all_warn(self, mock_log): + """ + Test test_projector_process_erst_all_error + """ + # GIVEN: Test object + chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_WARN], + lamp=PJLINK_ERST_STATUS[E_WARN], + temp=PJLINK_ERST_STATUS[E_WARN], + cover=PJLINK_ERST_STATUS[E_WARN], + filt=PJLINK_ERST_STATUS[E_WARN], + other=PJLINK_ERST_STATUS[E_WARN]) + chk_test = {'Fan': E_WARN, + 'Lamp': E_WARN, + 'Temperature': E_WARN, + 'Cover': E_WARN, + 'Filter': E_WARN, + 'Other': E_WARN} + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "ERST" with data "{chk}"'.format(ip=self.pjlink.name, + chk=chk_data)), + call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] + self.pjlink.projector_errors = None + + # WHEN: process_erst with status set to WARN + process_command(projector=self.pjlink, cmd='ERST', data=chk_data) + + # THEN: PJLink instance errors should match chk_value + assert (self.pjlink.projector_errors == chk_test), 'Projector errors should be all E_WARN' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_erst_data_invalid_length(self, mock_log): + """ + Test test_projector_process_erst_data_invalid_length + """ + # GIVEN: Test object + chk_data = '0' * (PJLINK_ERST_DATA['DATA_LENGTH'] + 1) + log_warn_calls = [call('({ip}) Invalid error status response "{data}": ' + 'length != {chk}'.format(ip=self.pjlink.name, + data=chk_data, chk=PJLINK_ERST_DATA['DATA_LENGTH']))] + log_debug_calls = [call('({ip}) Processing command "ERST" with data "{data}"'.format(ip=self.pjlink.name, + data=chk_data)), + call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] + self.pjlink.projector_errors = None + + # WHEN: process_erst called with invalid data (too many values + process_command(self.pjlink, cmd='ERST', data=chk_data) + + # THEN: pjlink.projector_errors should be empty and warning logged + assert (not self.pjlink.projector_errors), 'There should be no errors' + mock_log.warning.assert_has_calls(log_warn_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_erst_data_invalid_nan(self, mock_log): + """ + Test ERST called with invalid data + """ + # GIVEN: Test object + chk_data = 'Z' + ('0' * (PJLINK_ERST_DATA['DATA_LENGTH'] - 1)) + log_warn_calls = [call('({ip}) Invalid error status response "{data}"'.format(ip=self.pjlink.name, + data=chk_data))] + log_debug_calls = [call('({ip}) Processing command "ERST" with data "{data}"'.format(ip=self.pjlink.name, + data=chk_data)), + call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] + self.pjlink.projector_errors = None + + # WHEN: process_erst called with invalid data (too many values + process_command(self.pjlink, cmd='ERST', data=chk_data) + + # THEN: pjlink.projector_errors should be empty and warning logged + assert (not self.pjlink.projector_errors), 'There should be no errors' + mock_log.warning.assert_has_calls(log_warn_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_erst_warn_cover_only(self, mock_log): + """ + Test test_projector_process_erst_warn_cover_only + """ + # GIVEN: Test object + chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[S_OK], + lamp=PJLINK_ERST_STATUS[S_OK], + temp=PJLINK_ERST_STATUS[S_OK], + cover=PJLINK_ERST_STATUS[E_WARN], + filt=PJLINK_ERST_STATUS[S_OK], + other=PJLINK_ERST_STATUS[S_OK]) + chk_test = {'Cover': E_WARN} + log_warn_calls = [] + log_debug_calls = [call('({ip}) Processing command "ERST" with data "{data}"'.format(ip=self.pjlink.name, + data=chk_data)), + call('({ip}) Calling function for ERST'.format(ip=self.pjlink.name))] + self.pjlink.projector_errors = None + + # WHEN: process_erst with status set to WARN + process_command(projector=self.pjlink, cmd='ERST', data=chk_data) + + # THEN: PJLink instance errors should match only cover warning + assert (1 == len(self.pjlink.projector_errors)), 'There should only be 1 error listed in projector_errors' + assert ('Cover' in self.pjlink.projector_errors), '"Cover" should be the only error listed' + assert (self.pjlink.projector_errors['Cover'] == E_WARN), '"Cover" should have E_WARN listed as error' + assert (chk_test == self.pjlink.projector_errors), 'projector_errors should match test errors' + mock_log.warning.assert_has_calls(log_warn_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_inf1(self, mock_log): + """ + Test saving INF1 data (manufacturer) + """ + # GIVEN: Test object + chk_data = 'TEst INformation MultiCase' + log_warn_calls = [] + log_debug_calls = [call('({ip}) Processing command "INF1" with data "{data}"'.format(ip=self.pjlink.name, + data=chk_data)), + call('({ip}) Calling function for INF1'.format(ip=self.pjlink.name)), + call('({ip}) Setting projector manufacturer data to ' + '"{data}"'.format(ip=self.pjlink.name, data=chk_data))] + self.pjlink.manufacturer = None + + # WHEN: process_inf called with test data + process_command(projector=self.pjlink, cmd='INF1', data=chk_data) + + # THEN: Data should be saved + assert (self.pjlink.manufacturer == chk_data), 'Test data should have been saved' + mock_log.warning.assert_has_calls(log_warn_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_inf2(self, mock_log): + """ + Test saving INF2 data (model) + """ + # GIVEN: Test object + chk_data = 'TEst moDEl MultiCase' + log_warn_calls = [] + log_debug_calls = [call('({ip}) Processing command "INF2" with data "{data}"'.format(ip=self.pjlink.name, + data=chk_data)), + call('({ip}) Calling function for INF2'.format(ip=self.pjlink.name)), + call('({ip}) Setting projector model to "{data}"'.format(ip=self.pjlink.name, + data=chk_data))] + self.pjlink.model = None + + # WHEN: process_inf called with test data + process_command(projector=self.pjlink, cmd='INF2', data=chk_data) + + # THEN: Data should be saved + assert (self.pjlink.model == chk_data), 'Test data should have been saved' + mock_log.warning.assert_has_calls(log_warn_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_info(self, mock_log): + """ + Test saving INF2 data (model) + """ + # GIVEN: Test object + chk_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set' + log_warn_calls = [] + log_debug_calls = [call('({ip}) Processing command "INFO" with data "{data}"'.format(ip=self.pjlink.name, + data=chk_data)), + call('({ip}) Calling function for INFO'.format(ip=self.pjlink.name)), + call('({ip}) Setting projector other_info to "{data}"'.format(ip=self.pjlink.name, + data=chk_data))] + self.pjlink.other_info = None + + # WHEN: process_inf called with test data + process_command(projector=self.pjlink, cmd='INFO', data=chk_data) + + # THEN: Data should be saved + assert (self.pjlink.other_info == chk_data), 'Test data should have been saved' + mock_log.warning.assert_has_calls(log_warn_calls) + mock_log.debug.assert_has_calls(log_debug_calls) diff --git a/tests/openlp_core/projectors/test_projector_pjlink_commands_01.py b/tests/openlp_core/projectors/test_projector_commands_02.py similarity index 54% rename from tests/openlp_core/projectors/test_projector_pjlink_commands_01.py rename to tests/openlp_core/projectors/test_projector_commands_02.py index 48e479660..f483269a8 100644 --- a/tests/openlp_core/projectors/test_projector_pjlink_commands_01.py +++ b/tests/openlp_core/projectors/test_projector_commands_02.py @@ -26,8 +26,8 @@ from unittest import TestCase, skip from unittest.mock import call, patch import openlp.core.projectors.pjlink -from openlp.core.projectors.constants import E_ERROR, E_WARN, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \ - PJLINK_POWR_STATUS, S_NOT_CONNECTED, S_OK, S_ON, S_STANDBY, STATUS_CODE +from openlp.core.projectors.pjlinkcommands import process_command +from openlp.core.projectors.constants import PJLINK_POWR_STATUS, S_ON, S_STANDBY from openlp.core.projectors.db import Projector from openlp.core.projectors.pjlink import PJLink from tests.resources.projector.data import TEST1_DATA @@ -35,396 +35,19 @@ from tests.resources.projector.data import TEST1_DATA class TestPJLinkCommands(TestCase): """ - Tests for the PJLinkCommands class part 1 + Tests PJLink get status commands part 2 """ - @skip('Needs update to new setup') - def test_projector_process_inf1(self): + def setUp(self): """ - Test saving INF1 data (manufacturer) + Initial test setup """ - test_data = 'TEst INformation MultiCase' + self.pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.manufacturer = None - - # WHEN: process_inf called with test data - pjlink.process_inf1(data=test_data) - - # THEN: Data should be saved - assert pjlink.manufacturer == test_data, 'Test data should have been saved' - - @skip('Needs update to new setup') - def test_projector_process_inf2(self): + def tearDown(self): """ - Test saving INF2 data (model) + Test reset """ - test_data = 'TEst moDEl MultiCase' - - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.model = None - - # WHEN: process_inf called with test data - pjlink.process_inf2(data=test_data) - - # THEN: Data should be saved - assert pjlink.model == test_data, 'Test data should have been saved' - - @skip('Needs update to new setup') - def test_projector_process_info(self): - """ - Test saving INFO data (other information) - """ - test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set' - - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.other_info = None - - # WHEN: process_inf called with test data - pjlink.process_info(data=test_data) - - # THEN: Data should be saved - assert pjlink.other_info == test_data, 'Test data should have been saved' - - @skip('Needs update to new setup') - def test_projector_process_avmt_bad_data(self): - """ - Test avmt bad data fail - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.shutter = True - pjlink.mute = True - - # WHEN: Called with an invalid setting - pjlink.process_avmt('36') - - # THEN: Shutter should be closed and mute should be True - assert pjlink.shutter is True, 'Shutter should changed' - assert pjlink.mute is True, 'Audio should not have changed' - assert mock_UpdateIcons.emit.called is False, 'Update icons should NOT have been called' - - @skip('Needs update to new setup') - def test_projector_process_avmt_closed_muted(self): - """ - Test avmt status shutter closed and mute off - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.shutter = False - pjlink.mute = False - - # WHEN: Called with setting shutter to closed and mute on - pjlink.process_avmt('31') - - # THEN: Shutter should be closed and mute should be True - assert pjlink.shutter is True, 'Shutter should have been set to closed' - assert pjlink.mute is True, 'Audio should be muted' - assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called' - - @skip('Needs update to new setup') - def test_projector_process_avmt_shutter_closed(self): - """ - Test avmt status shutter closed and audio unchanged - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.shutter = False - pjlink.mute = True - - # WHEN: Called with setting shutter closed and mute off - pjlink.process_avmt('11') - - # THEN: Shutter should be True and mute should be False - assert pjlink.shutter is True, 'Shutter should have been set to closed' - assert pjlink.mute is True, 'Audio should not have changed' - assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called' - - @skip('Needs update to new setup') - def test_projector_process_avmt_audio_muted(self): - """ - Test avmt status shutter unchanged and mute on - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.shutter = True - pjlink.mute = False - - # WHEN: Called with setting shutter closed and mute on - pjlink.process_avmt('21') - - # THEN: Shutter should be closed and mute should be True - assert pjlink.shutter is True, 'Shutter should not have changed' - assert pjlink.mute is True, 'Audio should be off' - assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called' - - @skip('Needs update to new setup') - def test_projector_process_avmt_open_unmuted(self): - """ - Test avmt status shutter open and mute off - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.shutter = True - pjlink.mute = True - - # WHEN: Called with setting shutter to closed and mute on - pjlink.process_avmt('30') - - # THEN: Shutter should be closed and mute should be True - assert pjlink.shutter is False, 'Shutter should have been set to open' - assert pjlink.mute is False, 'Audio should be on' - assert mock_UpdateIcons.emit.called is True, 'Update icons should have been called' - - @skip('Needs update to new setup') - def test_projector_process_clss_one(self): - """ - Test class 1 sent from projector - """ - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - - # WHEN: Process class response - pjlink.process_clss('1') - - # THEN: Projector class should be set to 1 - assert pjlink.pjlink_class == '1', 'Projector should have set class=1' - - @skip('Needs update to new setup') - def test_projector_process_clss_two(self): - """ - Test class 2 sent from projector - """ - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - - # WHEN: Process class response - pjlink.process_clss('2') - - # THEN: Projector class should be set to 1 - assert pjlink.pjlink_class == '2', 'Projector should have set class=2' - - @skip('Needs update to new setup') - def test_projector_process_clss_invalid_nan(self): - """ - Test CLSS reply has no class number - """ - # 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}) reset_information() connect status is ' - '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), - call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=pjlink.name))] - log_error_calls = [call('({ip}) NAN CLSS version reply "Z" - ' - 'defaulting to class "1"'.format(ip=pjlink.name))] - - # WHEN: Process invalid reply - pjlink.process_clss('Z') - - # THEN: Projector class should be set with default value - assert pjlink.pjlink_class == '1', 'Invalid NaN class reply should have set class=1' - mock_log.error.assert_has_calls(log_error_calls) - mock_log.debug.assert_has_calls(log_debug_calls) - - @skip('Needs update to new setup') - def test_projector_process_clss_invalid_no_version(self): - """ - Test CLSS reply has no class number - """ - # 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}) reset_information() connect status is ' - '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED])), - call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=pjlink.name))] - log_error_calls = [call('({ip}) No numbers found in class version reply "Invalid" ' - '- defaulting to class "1"'.format(ip=pjlink.name))] - - # WHEN: Process invalid reply - pjlink.process_clss('Invalid') - - # THEN: Projector class should be set with default value - assert pjlink.pjlink_class == '1', 'Invalid class reply should have set class=1' - mock_log.error.assert_has_calls(log_error_calls) - mock_log.debug.assert_has_calls(log_debug_calls) - - @skip('Needs update to new setup') - def test_projector_process_clss_nonstandard_reply_1(self): - """ - Test CLSS request returns non-standard reply 1 - """ - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - - # WHEN: Process non-standard reply - pjlink.process_clss('Class 1') - - # THEN: Projector class should be set with proper value - assert '1' == pjlink.pjlink_class, 'Non-standard class reply should have set class=1' - - @skip('Needs update to new setup') - def test_projector_process_clss_nonstandard_reply_2(self): - """ - Test CLSS request returns non-standard reply 2 - """ - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - - # WHEN: Process non-standard reply - pjlink.process_clss('Version2') - - # THEN: Projector class should be set with proper value - assert '2' == pjlink.pjlink_class, 'Non-standard class reply should have set class=2' - - @skip('Needs update to new setup') - def test_projector_process_erst_all_ok(self): - """ - Test to verify pjlink.projector_errors is set to None when no errors - """ - chk_data = '0' * PJLINK_ERST_DATA['DATA_LENGTH'] - - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - - # WHEN: process_erst with no errors - pjlink.process_erst(chk_data) - - # THEN: PJLink instance errors should be None - assert pjlink.projector_errors is None, 'projector_errors should have been set to None' - - @skip('Needs update to new setup') - def test_projector_process_erst_data_invalid_length(self): - """ - Test test_projector_process_erst_data_invalid_length - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.projector_errors = None - chk_data = '0' * (PJLINK_ERST_DATA['DATA_LENGTH'] + 1) - log_debug_calls = [call('({ip}) reset_information() connect status is ' - '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED]))] - log_warn_calls = [call('({ip}) Invalid error status response "0000000": ' - 'length != {chk}'.format(ip=pjlink.name, chk=PJLINK_ERST_DATA['DATA_LENGTH']))] - - # WHEN: process_erst called with invalid data (too many values - pjlink.process_erst(chk_data) - - # THEN: pjlink.projector_errors should be empty and warning logged - assert pjlink.projector_errors is None, 'There should be no errors' - mock_log.debug.assert_has_calls(log_debug_calls) - mock_log.warning.assert_has_calls(log_warn_calls) - - @skip('Needs update to new setup') - def test_projector_process_erst_data_invalid_nan(self): - """ - Test test_projector_process_erst_data_invalid_nan - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.projector_errors = None - chk_data = 'Z' + ('0' * (PJLINK_ERST_DATA['DATA_LENGTH'] - 1)) - log_debug_calls = [call('({ip}) reset_information() connect status is ' - '{state}'.format(ip=pjlink.name, state=STATUS_CODE[S_NOT_CONNECTED]))] - log_warn_calls = [call('({ip}) Invalid error status response "Z00000"'.format(ip=pjlink.name))] - - # WHEN: process_erst called with invalid data (too many values - pjlink.process_erst(chk_data) - - # THEN: pjlink.projector_errors should be empty and warning logged - assert pjlink.projector_errors is None, 'There should be no errors' - mock_log.debug.assert_has_calls(log_debug_calls) - mock_log.warning.assert_has_calls(log_warn_calls) - - @skip('Needs update to new setup') - def test_projector_process_erst_all_warn(self): - """ - Test test_projector_process_erst_all_warn - """ - chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_WARN], - lamp=PJLINK_ERST_STATUS[E_WARN], - temp=PJLINK_ERST_STATUS[E_WARN], - cover=PJLINK_ERST_STATUS[E_WARN], - filt=PJLINK_ERST_STATUS[E_WARN], - other=PJLINK_ERST_STATUS[E_WARN]) - chk_test = {'Fan': E_WARN, - 'Lamp': E_WARN, - 'Temperature': E_WARN, - 'Cover': E_WARN, - 'Filter': E_WARN, - 'Other': E_WARN} - - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.projector_errors = None - - # WHEN: process_erst with status set to WARN - pjlink.process_erst(chk_data) - - # THEN: PJLink instance errors should match chk_value - assert pjlink.projector_errors == chk_test, 'Projector errors should be all E_WARN' - - @skip('Needs update to new setup') - def test_projector_process_erst_all_error(self): - """ - Test test_projector_process_erst_all_error - """ - chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[E_ERROR], - lamp=PJLINK_ERST_STATUS[E_ERROR], - temp=PJLINK_ERST_STATUS[E_ERROR], - cover=PJLINK_ERST_STATUS[E_ERROR], - filt=PJLINK_ERST_STATUS[E_ERROR], - other=PJLINK_ERST_STATUS[E_ERROR]) - chk_test = {'Fan': E_ERROR, - 'Lamp': E_ERROR, - 'Temperature': E_ERROR, - 'Cover': E_ERROR, - 'Filter': E_ERROR, - 'Other': E_ERROR} - - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.projector_errors = None - - # WHEN: process_erst with status set to WARN - pjlink.process_erst(chk_data) - - # THEN: PJLink instance errors should match chk_value - assert pjlink.projector_errors == chk_test, 'Projector errors should be all E_ERROR' - - @skip('Needs update to new setup') - def test_projector_process_erst_warn_cover_only(self): - """ - Test test_projector_process_erst_warn_cover_only - """ - chk_data = '{fan}{lamp}{temp}{cover}{filt}{other}'.format(fan=PJLINK_ERST_STATUS[S_OK], - lamp=PJLINK_ERST_STATUS[S_OK], - temp=PJLINK_ERST_STATUS[S_OK], - cover=PJLINK_ERST_STATUS[E_WARN], - filt=PJLINK_ERST_STATUS[S_OK], - other=PJLINK_ERST_STATUS[S_OK]) - chk_test = {'Cover': E_WARN} - - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.projector_errors = None - - # WHEN: process_erst with status set to WARN - pjlink.process_erst(chk_data) - - # THEN: PJLink instance errors should match only cover warning - assert 1 == len(pjlink.projector_errors), 'There should only be 1 error listed in projector_errors' - assert 'Cover' in pjlink.projector_errors, '"Cover" should be the only error listed' - assert pjlink.projector_errors['Cover'] == E_WARN, '"Cover" should have E_WARN listed as error' - assert chk_test == pjlink.projector_errors, 'projector_errors should match test errors' + del(self.pjlink) @skip('Needs update to new setup') def test_projector_process_inpt_valid(self): @@ -441,7 +64,7 @@ class TestPJLinkCommands(TestCase): pjlink.source_available = chk_source_available # WHEN: Called with input source - pjlink.process_inpt('21') + process_command(projector=self.pjlink, cmd='INPT', data='21') # THEN: Input selected should reflect current input assert pjlink.source == '21', 'Input source should be set to "21"' diff --git a/tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py b/tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py index a5225fd69..669f0a10a 100644 --- a/tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py +++ b/tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py @@ -23,12 +23,11 @@ Package to test the openlp.core.projectors.pjlink command routing. """ -from unittest import TestCase, skip +from unittest import TestCase from unittest.mock import call, patch import openlp.core.projectors.pjlink -from openlp.core.projectors.constants import E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED, \ - PJLINK_ERRORS, PJLINK_PREFIX, STATUS_MSG +from openlp.core.projectors.constants import PJLINK_PREFIX from openlp.core.projectors.db import Projector from openlp.core.projectors.pjlink import PJLink from tests.resources.projector.data import TEST1_DATA @@ -134,119 +133,3 @@ class TestPJLinkRouting(TestCase): 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' - - @skip('Needs update to new setup') - def test_routing_err1(self): - """ - Test ERR1 - Undefined projector function - """ - # 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=self.pjlink.name, msg=STATUS_MSG[E_UNDEFINED]))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR1"'.format(ip=self.pjlink.name)), - call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name))] - - # WHEN: process_command called with ERR1 - pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED]) - - # 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_UNDEFINED]) - - @skip('Needs update to new setup') - def test_routing_err2(self): - """ - Test ERR2 - Parameter 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=self.pjlink.name, msg=STATUS_MSG[E_PARAMETER]))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR2"'.format(ip=self.pjlink.name)), - call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name))] - - # WHEN: process_command called with ERR2 - pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER]) - - # THEN: Appropriate log entries should have been made and methods called/not called - mock_log.error.assert_has_calls(log_error_text) - mock_log.debug.assert_has_calls(log_debug_text) - mock_process_clss.assert_called_once_with(data=PJLINK_ERRORS[E_PARAMETER]) - - @skip('Needs update to new setup') - def test_routing_err3(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=self.pjlink.name, msg=STATUS_MSG[E_UNAVAILABLE]))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR3"'.format(ip=self.pjlink.name)), - call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name))] - - # WHEN: process_command called with ERR3 - pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE]) - - # 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_UNAVAILABLE]) - - @skip('Needs update to new setup') - def test_routing_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=self.pjlink.name, msg=STATUS_MSG[E_PROJECTOR]))] - log_debug_text = [call('({ip}) Processing command "CLSS" with data "ERR4"'.format(ip=self.pjlink.name)), - call('({ip}) Calling function for CLSS'.format(ip=self.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]) - - @skip('Needs update to new setup') - def test_routing_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=self.pjlink.name, - msg=STATUS_MSG[E_AUTHENTICATION]))] - log_debug_calls = [call('({ip}) Processing command "PJLINK" with data "ERRA"'.format(ip=self.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() From 7aa7e5c6351d80d8623c639d8a8a6af51f6cee06 Mon Sep 17 00:00:00 2001 From: Phill Date: Sat, 4 May 2019 12:49:20 +0100 Subject: [PATCH 3/7] Move some changes out of annother branch --- openlp/core/common/__init__.py | 6 +++--- openlp/core/lib/mediamanageritem.py | 10 +++++----- openlp/plugins/presentations/lib/mediaitem.py | 18 ++++++++---------- .../openlp_core/ui/test_thememanager.py | 4 ++-- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/openlp/core/common/__init__.py b/openlp/core/common/__init__.py index fd251be14..c7bc25b29 100644 --- a/openlp/core/common/__init__.py +++ b/openlp/core/common/__init__.py @@ -463,8 +463,8 @@ def get_file_encoding(file_path): Utility function to incrementally detect the file encoding. :param openlp.core.common.path.Path file_path: Filename for the file to determine the encoding for. - :return: A dict with the keys 'encoding' and 'confidence' - :rtype: dict[str, float] + :return: The name of the encoding detected + :rtype: str """ detector = UniversalDetector() try: @@ -477,7 +477,7 @@ def get_file_encoding(file_path): except OSError: log.exception('Error detecting file encoding') finally: - return detector.close() + return detector.close()['encoding'] def normalize_str(irregular_string): diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 50f8497ab..0511eeb16 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -333,7 +333,7 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): self.validate_and_load(file_paths) self.application.set_normal_cursor() - def load_file(self, data): + def handle_mime_data(self, data): """ Turn file from Drag and Drop into an array so the Validate code can run it. @@ -379,11 +379,11 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): duplicates_found = False files_added = False for file_path in file_paths: - if path_to_str(file_path) in full_list: + if file_path in full_list: duplicates_found = True else: files_added = True - full_list.append(path_to_str(file_path)) + full_list.append(file_path) if full_list and files_added: if target_group is None: self.list_view.clear() @@ -416,8 +416,8 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties): file_paths = [] for index in range(self.list_view.count()): list_item = self.list_view.item(index) - filename = list_item.data(QtCore.Qt.UserRole) - file_paths.append(str_to_path(filename)) + file_path = list_item.data(QtCore.Qt.UserRole) + file_paths.append(file_path) return file_paths def load_list(self, load_list, target_group): diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index b11140489..dda2a485c 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -24,7 +24,7 @@ import logging from PyQt5 import QtCore, QtWidgets from openlp.core.common.i18n import UiStrings, get_natural_key, translate -from openlp.core.common.path import path_to_str, str_to_path +from openlp.core.common.path import path_to_str from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.core.lib import ServiceItemContext, build_icon, check_item_selected, create_thumb, validate_thumb @@ -127,7 +127,7 @@ class PresentationMediaItem(MediaManagerItem): """ self.list_view.setIconSize(QtCore.QSize(88, 50)) file_paths = Settings().value(self.settings_section + '/presentations files') - self.load_list([path_to_str(path) for path in file_paths], initial_load=True) + self.load_list(file_paths, initial_load=True) self.populate_display_types() def populate_display_types(self): @@ -158,7 +158,6 @@ class PresentationMediaItem(MediaManagerItem): :param list[openlp.core.common.path.Path] file_paths: List of file paths to add to the media manager. """ - file_paths = [str_to_path(filename) for filename in file_paths] current_paths = self.get_file_list() titles = [file_path.name for file_path in current_paths] self.application.set_busy_cursor() @@ -175,7 +174,7 @@ class PresentationMediaItem(MediaManagerItem): if not file_path.exists(): item_name = QtWidgets.QListWidgetItem(file_name) item_name.setIcon(UiIcons().delete) - item_name.setData(QtCore.Qt.UserRole, path_to_str(file_path)) + item_name.setData(QtCore.Qt.UserRole, file_path) item_name.setToolTip(str(file_path)) self.list_view.addItem(item_name) else: @@ -211,7 +210,7 @@ class PresentationMediaItem(MediaManagerItem): 'This type of presentation is not supported.')) continue item_name = QtWidgets.QListWidgetItem(file_name) - item_name.setData(QtCore.Qt.UserRole, path_to_str(file_path)) + item_name.setData(QtCore.Qt.UserRole, file_path) item_name.setIcon(icon) item_name.setToolTip(str(file_path)) self.list_view.addItem(item_name) @@ -230,8 +229,7 @@ class PresentationMediaItem(MediaManagerItem): self.application.set_busy_cursor() self.main_window.display_progress_bar(len(row_list)) for item in items: - file_path = str_to_path(item.data(QtCore.Qt.UserRole)) - self.clean_up_thumbnails(file_path) + self.clean_up_thumbnails(item.data(QtCore.Qt.UserRole)) self.main_window.increment_progress_bar() self.main_window.finished_progress_bar() for row in row_list: @@ -278,7 +276,7 @@ class PresentationMediaItem(MediaManagerItem): if len(items) > 1: return False if file_path is None: - file_path = str_to_path(items[0].data(QtCore.Qt.UserRole)) + file_path = items[0].data(QtCore.Qt.UserRole) file_type = file_path.suffix.lower()[1:] if not self.display_type_combo_box.currentText(): return False @@ -293,7 +291,7 @@ class PresentationMediaItem(MediaManagerItem): service_item.theme = -1 for bitem in items: if file_path is None: - file_path = str_to_path(bitem.data(QtCore.Qt.UserRole)) + file_path = bitem.data(QtCore.Qt.UserRole) path, file_name = file_path.parent, file_path.name service_item.title = file_name if file_path.exists(): @@ -329,7 +327,7 @@ class PresentationMediaItem(MediaManagerItem): service_item.processor = self.display_type_combo_box.currentText() service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay) for bitem in items: - file_path = str_to_path(bitem.data(QtCore.Qt.UserRole)) + file_path = bitem.data(QtCore.Qt.UserRole) path, file_name = file_path.parent, file_path.name service_item.title = file_name if file_path.exists(): diff --git a/tests/functional/openlp_core/ui/test_thememanager.py b/tests/functional/openlp_core/ui/test_thememanager.py index 757ff3faf..e4a2e7988 100644 --- a/tests/functional/openlp_core/ui/test_thememanager.py +++ b/tests/functional/openlp_core/ui/test_thememanager.py @@ -143,7 +143,7 @@ class TestThemeManager(TestCase): mocked_theme.export_theme.return_value = "{}" # WHEN: Calling _write_theme with a theme with a name with special characters in it - theme_manager._write_theme(mocked_theme, None, None) + theme_manager._write_theme(mocked_theme) # THEN: It should have been created assert os.path.exists(os.path.join(self.temp_folder, 'theme æ„› name', 'theme æ„› name.json')) is True, \ @@ -224,7 +224,7 @@ class TestThemeManager(TestCase): theme_manager = ThemeManager(None) # WHEN: unzip_theme is called - theme_manager.unzip_theme('theme.file', 'folder') + theme_manager.unzip_theme(Path('theme.file'), Path('folder')) # THEN: The critical_error_message_box should have been called assert mocked_critical_error_message_box.call_count == 1, 'Should have been called once' From 1d736a58f5ccff7534d0af3078c2266946a184fa Mon Sep 17 00:00:00 2001 From: Phill Date: Sat, 4 May 2019 13:05:53 +0100 Subject: [PATCH 4/7] Fix up tests --- openlp/core/ui/mainwindow.py | 2 ++ tests/functional/openlp_core/common/test_common.py | 4 ++-- tests/functional/openlp_core/test_app.py | 4 ++-- tests/functional/openlp_core/ui/test_mainwindow.py | 2 +- tests/functional/openlp_plugins/bibles/test_csvimport.py | 3 +-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 703bdc943..7c26ea9a4 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -1356,6 +1356,8 @@ class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow, LogMixin, RegistryPropert def open_cmd_line_files(self, args): """ Open files passed in through command line arguments + + :param list[str] args: List of remaining positionall arguments """ for arg in args: file_name = os.path.expanduser(arg) diff --git a/tests/functional/openlp_core/common/test_common.py b/tests/functional/openlp_core/common/test_common.py index 349ad6326..715e66ff6 100644 --- a/tests/functional/openlp_core/common/test_common.py +++ b/tests/functional/openlp_core/common/test_common.py @@ -88,7 +88,7 @@ class TestCommonFunctions(TestCase): extension_loader('glob') # THEN: The `ImportError` should be caught and logged - assert mocked_logger.warning.called + assert mocked_logger.exception.called def test_extension_loader_os_error(self): """ @@ -106,7 +106,7 @@ class TestCommonFunctions(TestCase): extension_loader('glob') # THEN: The `OSError` should be caught and logged - assert mocked_logger.warning.called + assert mocked_logger.exception.called def test_de_hump_conversion(self): """ diff --git a/tests/functional/openlp_core/test_app.py b/tests/functional/openlp_core/test_app.py index 744e98a47..37d7e1647 100644 --- a/tests/functional/openlp_core/test_app.py +++ b/tests/functional/openlp_core/test_app.py @@ -138,7 +138,7 @@ def test_parse_options_file(): assert args.loglevel == 'warning', 'The log level should be set to warning' assert args.no_error_form is False, 'The no_error_form should be set to False' assert args.portable is False, 'The portable flag should be set to false' - assert args.rargs == 'dummy_temp', 'The service file should not be blank' + assert args.rargs == ['dummy_temp'], 'The service file should not be blank' def test_parse_options_file_and_debug(): @@ -155,7 +155,7 @@ def test_parse_options_file_and_debug(): assert args.loglevel == ' debug', 'The log level should be set to debug' assert args.no_error_form is False, 'The no_error_form should be set to False' assert args.portable is False, 'The portable flag should be set to false' - assert args.rargs == 'dummy_temp', 'The service file should not be blank' + assert args.rargs == ['dummy_temp'], 'The service file should not be blank' @skip('Figure out why this is causing a segfault') diff --git a/tests/functional/openlp_core/ui/test_mainwindow.py b/tests/functional/openlp_core/ui/test_mainwindow.py index 1d1929286..817e2272e 100644 --- a/tests/functional/openlp_core/ui/test_mainwindow.py +++ b/tests/functional/openlp_core/ui/test_mainwindow.py @@ -96,7 +96,7 @@ class TestMainWindow(TestCase, TestMixin): # WHEN the argument is processed with patch.object(self.main_window.service_manager, 'load_file') as mocked_load_file: - self.main_window.open_cmd_line_files(service) + self.main_window.open_cmd_line_files([service]) # THEN the service from the arguments is loaded mocked_load_file.assert_called_with(Path(service)) diff --git a/tests/functional/openlp_plugins/bibles/test_csvimport.py b/tests/functional/openlp_plugins/bibles/test_csvimport.py index ca3b933ba..0110db597 100644 --- a/tests/functional/openlp_plugins/bibles/test_csvimport.py +++ b/tests/functional/openlp_plugins/bibles/test_csvimport.py @@ -136,8 +136,7 @@ class TestCSVImport(TestCase): mocked_enter_file = MagicMock() mocked_csv_file.open.return_value.__enter__.return_value = mocked_enter_file - with patch('openlp.plugins.bibles.lib.importers.csvbible.get_file_encoding', - return_value={'encoding': 'utf-8', 'confidence': 0.99}), \ + with patch('openlp.plugins.bibles.lib.importers.csvbible.get_file_encoding', return_value='utf-8'), \ patch('openlp.plugins.bibles.lib.importers.csvbible.csv.reader', return_value=iter(test_data)) as mocked_reader: From 5cb0d2a772d679cec4ae7be6994a60cd1917bb6e Mon Sep 17 00:00:00 2001 From: Phill Date: Sat, 4 May 2019 19:13:57 +0100 Subject: [PATCH 5/7] test fix --- tests/functional/openlp_core/test_server.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/functional/openlp_core/test_server.py b/tests/functional/openlp_core/test_server.py index 2f72e7480..96cf55005 100644 --- a/tests/functional/openlp_core/test_server.py +++ b/tests/functional/openlp_core/test_server.py @@ -22,6 +22,7 @@ from unittest import TestCase from unittest.mock import MagicMock, patch +from openlp.core.common.path import Path from openlp.core.common.registry import Registry from openlp.core.server import Server from tests.helpers.testmixin import TestMixin @@ -83,8 +84,8 @@ class TestServer(TestCase, TestMixin): self.server._on_ready_read() # THEN: the service will be loaded - assert service_manager.on_load_service_clicked.call_count == 1 - service_manager.on_load_service_clicked.assert_called_once_with(file_name) + assert service_manager.load_service.call_count == 1 + service_manager.load_service.assert_called_once_with(Path(file_name)) @patch("PyQt5.QtCore.QTextStream") def test_post_to_server(self, mocked_stream): From 3ee9df96aeee18617e79c064c715a7aa3668eb8c Mon Sep 17 00:00:00 2001 From: Phill Date: Sat, 4 May 2019 19:25:59 +0100 Subject: [PATCH 6/7] PEP8 --- openlp/core/lib/mediamanageritem.py | 1 - openlp/core/ui/servicemanager.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 0511eeb16..876b70da2 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -29,7 +29,6 @@ from PyQt5 import QtCore, QtWidgets from openlp.core.common.i18n import UiStrings, translate from openlp.core.common.mixins import RegistryProperties -from openlp.core.common.path import path_to_str, str_to_path from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings from openlp.core.lib import ServiceItemContext diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 3858e1f48..b18f2f9d8 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -38,7 +38,7 @@ from openlp.core.common.applocation import AppLocation from openlp.core.common.i18n import UiStrings, format_time, translate from openlp.core.common.json import OpenLPJsonDecoder, OpenLPJsonEncoder from openlp.core.common.mixins import LogMixin, RegistryProperties -from openlp.core.common.path import Path, str_to_path +from openlp.core.common.path import Path from openlp.core.common.registry import Registry, RegistryBase from openlp.core.common.settings import Settings from openlp.core.lib import build_icon @@ -433,8 +433,8 @@ class ServiceManager(QtWidgets.QWidget, RegistryBase, Ui_ServiceManager, LogMixi def on_load_service_clicked(self, checked): """ Handle the `fileOpenItem` action - - :param bool checked: Not used. + + :param bool checked: Not used. :rtype: None """ self.load_service() From 855828939f27bdc1a20e0636d365258a768ed409 Mon Sep 17 00:00:00 2001 From: Ken Roberts Date: Sat, 4 May 2019 21:08:32 -0700 Subject: [PATCH 7/7] PJLink2 update v06 --- openlp/core/projectors/pjlink.py | 54 +- openlp/core/projectors/pjlinkcommands.py | 46 +- .../projectors/test_projector_commands_01.py | 12 +- .../projectors/test_projector_commands_02.py | 708 ++++++++++-------- ...ds_02.py => test_projector_commands_03.py} | 0 .../test_projector_pjlink_base_02.py | 31 - .../test_projector_pjlink_cmd_routing.py | 20 +- 7 files changed, 465 insertions(+), 406 deletions(-) rename tests/openlp_core/projectors/{test_projector_pjlink_commands_02.py => test_projector_commands_03.py} (100%) diff --git a/openlp/core/projectors/pjlink.py b/openlp/core/projectors/pjlink.py index 5aa6f2b20..9859b2825 100644 --- a/openlp/core/projectors/pjlink.py +++ b/openlp/core/projectors/pjlink.py @@ -520,14 +520,23 @@ class PJLink(QtNetwork.QTcpSocket): self.send_busy = False return # Although we have a packet length limit, go ahead and use a larger buffer - read = self.readLine(1024) - log.debug('({ip}) get_socket(): "{buff}"'.format(ip=self.entry.name, buff=read)) - if read == -1: + self.socket_timer.start() + while self.bytesAvailable() >= 1: + data = self.readLine(1024) + data = data.strip() + if not data: + log.warning('({ip}) get_socket(): Ignoring empty packet'.format(ip=self.entry.name)) + if self.bytesAvailable() < 1: + break + + self.socket_timer.stop() + if data: + log.debug('({ip}) get_socket(): "{buff}"'.format(ip=self.entry.name, buff=data)) + if data == -1: # No data available log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.entry.name)) - return self.receive_data_signal() - self.socket_timer.stop() - return self.get_data(buff=read) + return + return self.get_data(buff=data) def get_data(self, buff, *args, **kwargs): """ @@ -540,21 +549,22 @@ class PJLink(QtNetwork.QTcpSocket): # NOTE: Class2 has changed to some values being UTF-8 data_in = decode(buff, 'utf-8') if isinstance(buff, bytes) else buff data = data_in.strip() + self.receive_data_signal() # Initial packet checks if (len(data) < 7): self._trash_buffer(msg='get_data(): Invalid packet - length') - return self.receive_data_signal() + return elif len(data) > self.max_size: self._trash_buffer(msg='get_data(): Invalid packet - too long ({length} bytes)'.format(length=len(data))) - return self.receive_data_signal() + return elif not data.startswith(PJLINK_PREFIX): self._trash_buffer(msg='get_data(): Invalid packet - PJLink prefix missing') - return self.receive_data_signal() + return elif data[6] != '=' and data[8] != '=': # data[6] = standard command packet # data[8] = initial PJLink connection (after mangling) self._trash_buffer(msg='get_data(): Invalid reply - Does not have "="') - return self.receive_data_signal() + return log.debug('({ip}) get_data(): Checking new data "{data}"'.format(ip=self.entry.name, data=data)) header, data = data.split('=') log.debug('({ip}) get_data() header="{header}" data="{data}"'.format(ip=self.entry.name, @@ -572,20 +582,20 @@ class PJLink(QtNetwork.QTcpSocket): data=data)) if cmd not in PJLINK_VALID_CMD: self._trash_buffer('get_data(): Invalid packet - unknown command "{data}"'.format(data=cmd)) - return self.receive_data_signal() + return elif version not in PJLINK_VALID_CMD[cmd]['version']: self._trash_buffer(msg='get_data() Command reply version does not match a valid command version') - return self.receive_data_signal() + return elif int(self.pjlink_class) < int(version): if not ignore_class: log.warning('({ip}) get_data(): Projector returned class reply higher ' 'than projector stated class'.format(ip=self.entry.name)) - return self.receive_data_signal() + return chk = process_command(self, cmd, data) if chk is None: # Command processed normally and not initial connection, so skip other checks - return self.receive_data_signal() + return # PJLink initial connection checks elif chk == S_DATA_OK: # Previous command returned OK @@ -612,7 +622,7 @@ class PJLink(QtNetwork.QTcpSocket): self.projectorAuthentication.emit(self.entry.name) self.change_status(status=E_AUTHENTICATION) - return self.receive_data_signal() + return @QtCore.pyqtSlot(QtNetwork.QAbstractSocket.SocketError) def get_error(self, err): @@ -728,17 +738,17 @@ class PJLink(QtNetwork.QTcpSocket): log.debug('({ip}) _send_command(): Normal queue = {data}'.format(ip=self.entry.name, data=self.send_queue)) return - if len(self.priority_queue) != 0: - out = self.priority_queue.pop(0) - log.debug('({ip}) _send_command(): Getting priority queued packet'.format(ip=self.entry.name)) - elif len(self.send_queue) != 0: - out = self.send_queue.pop(0) - log.debug('({ip}) _send_command(): Getting normal queued packet'.format(ip=self.entry.name)) - else: + if not self.priority_queue and not self.send_queue: # No data to send log.warning('({ip}) _send_command(): No data to send'.format(ip=self.entry.name)) self.send_busy = False return + elif self.priority_queue: + out = self.priority_queue.pop(0) + log.debug('({ip}) _send_command(): Getting priority queued packet'.format(ip=self.entry.name)) + elif self.send_queue: + out = self.send_queue.pop(0) + log.debug('({ip}) _send_command(): Getting normal queued packet'.format(ip=self.entry.name)) self.send_busy = True log.debug('({ip}) _send_command(): Sending "{data}"'.format(ip=self.entry.name, data=out.strip())) self.socket_timer.start() diff --git a/openlp/core/projectors/pjlinkcommands.py b/openlp/core/projectors/pjlinkcommands.py index 6df155db1..1a3b416d7 100644 --- a/openlp/core/projectors/pjlinkcommands.py +++ b/openlp/core/projectors/pjlinkcommands.py @@ -153,14 +153,14 @@ def process_clss(projector, data): # fix the class reply is to just remove all non-digit characters. chk = re.findall(r'\d', data) if len(chk) < 1: - log.error('({ip}) No numbers found in class version reply "{data}" - ' - 'defaulting to class "1"'.format(ip=projector.entry.name, data=data)) + log.warning('({ip}) No numbers found in class version reply "{data}" - ' + 'defaulting to class "1"'.format(ip=projector.entry.name, data=data)) clss = '1' else: clss = chk[0] # Should only be the first match elif not data.isdigit(): - log.error('({ip}) NAN CLSS version reply "{data}" - ' - 'defaulting to class "1"'.format(ip=projector.entry.name, data=data)) + log.warning('({ip}) NAN CLSS version reply "{data}" - ' + 'defaulting to class "1"'.format(ip=projector.entry.name, data=data)) clss = '1' else: clss = data @@ -282,12 +282,13 @@ def process_inpt(projector, data): if projector.source_available is not None: # We have available inputs, so verify it's in the list if data not in projector.source_available: - log.warn('({ip}) Input source not listed in available sources - ignoring'.format(ip=projector.entry.name)) + log.warning('({ip}) Input source not listed in available sources - ' + 'ignoring'.format(ip=projector.entry.name)) return elif data not in PJLINK_DEFAULT_CODES: # Hmm - no sources available yet, so check with PJLink defaults - log.warn('({ip}) Input source not listed as a PJLink available source ' - '- ignoring'.format(ip=projector.entry.name)) + log.warning('({ip}) Input source not listed as a PJLink valid source ' + '- ignoring'.format(ip=projector.entry.name)) return projector.source = data log.debug('({ip}) Setting current source to "{data}"'.format(ip=projector.entry.name, data=projector.source)) @@ -326,7 +327,10 @@ def process_lamp(projector, data): lamps = [] lamp_list = data.split() if len(lamp_list) < 2: - lamps.append({'Hours': int(lamp_list[0]), 'On': None}) + # Invalid data - not enough information + log.warning('({ip}) process_lamp(): Invalid data "{data}" - ' + 'Missing data'.format(ip=projector.entry.name, data=data)) + return else: while lamp_list: if not lamp_list[0].isnumeric() or not lamp_list[1].isnumeric(): @@ -411,20 +415,22 @@ def process_powr(projector, data): :param projector: Projector instance :param data: Power status """ - log.debug('({ip}: Processing POWR command'.format(ip=projector.entry.name)) - if data in PJLINK_POWR_STATUS: - power = PJLINK_POWR_STATUS[data] - update_icons = projector.power != power - projector.power = power - projector.change_status(PJLINK_POWR_STATUS[data]) - if update_icons: - projector.projectorUpdateIcons.emit() - # Update the input sources available - if power == S_ON: - projector.send_command('INST') - else: + log.debug('({ip}) Processing POWR command'.format(ip=projector.entry.name)) + if data not in PJLINK_POWR_STATUS: # Log unknown status response log.warning('({ip}) Unknown power response: "{data}"'.format(ip=projector.entry.name, data=data)) + return + + power = PJLINK_POWR_STATUS[data] + update_icons = projector.power != power + if update_icons: + projector.power = power + projector.change_status(PJLINK_POWR_STATUS[data]) + projector.projectorUpdateIcons.emit() + if power == S_ON: + # Input sources list should only be available after power on, so update here + projector.send_command('INST') + if projector.power in [S_ON, S_STANDBY, S_OFF] and 'POWR' in projector.status_timer_checks: projector.status_timer_delete(cmd='POWR') return diff --git a/tests/openlp_core/projectors/test_projector_commands_01.py b/tests/openlp_core/projectors/test_projector_commands_01.py index 64fa4c1fc..07e283031 100644 --- a/tests/openlp_core/projectors/test_projector_commands_01.py +++ b/tests/openlp_core/projectors/test_projector_commands_01.py @@ -246,8 +246,8 @@ class TestPJLinkCommands(TestCase): Test CLSS reply has no class number """ # GIVEN: Test setup - log_error_calls = [call('({ip}) NAN CLSS version reply "Z" - ' - 'defaulting to class "1"'.format(ip=self.pjlink.name))] + log_warning_calls = [call('({ip}) NAN CLSS version reply "Z" - ' + 'defaulting to class "1"'.format(ip=self.pjlink.name))] log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Z"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] @@ -257,7 +257,7 @@ class TestPJLinkCommands(TestCase): # THEN: Projector class should be set with default value assert (self.pjlink.pjlink_class == '1'), 'Invalid NaN class reply should have set class=1' - 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) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') @@ -266,8 +266,8 @@ class TestPJLinkCommands(TestCase): Test CLSS reply has no class number """ # GIVEN: Test object - log_error_calls = [call('({ip}) No numbers found in class version reply "Invalid" ' - '- defaulting to class "1"'.format(ip=self.pjlink.name))] + log_warning_calls = [call('({ip}) No numbers found in class version reply "Invalid" ' + '- defaulting to class "1"'.format(ip=self.pjlink.name))] log_debug_calls = [call('({ip}) Processing command "CLSS" with data "Invalid"'.format(ip=self.pjlink.name)), call('({ip}) Calling function for CLSS'.format(ip=self.pjlink.name)), call('({ip}) Setting pjlink_class for this projector to "1"'.format(ip=self.pjlink.name))] @@ -277,7 +277,7 @@ class TestPJLinkCommands(TestCase): # THEN: Projector class should be set with default value assert (self.pjlink.pjlink_class == '1'), 'Invalid class reply should have set class=1' - 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) @patch.object(openlp.core.projectors.pjlinkcommands, 'log') diff --git a/tests/openlp_core/projectors/test_projector_commands_02.py b/tests/openlp_core/projectors/test_projector_commands_02.py index f483269a8..e112c27c9 100644 --- a/tests/openlp_core/projectors/test_projector_commands_02.py +++ b/tests/openlp_core/projectors/test_projector_commands_02.py @@ -22,7 +22,7 @@ """ Package to test the openlp.core.projectors.pjlink commands package. """ -from unittest import TestCase, skip +from unittest import TestCase from unittest.mock import call, patch import openlp.core.projectors.pjlink @@ -49,428 +49,502 @@ class TestPJLinkCommands(TestCase): """ del(self.pjlink) - @skip('Needs update to new setup') - def test_projector_process_inpt_valid(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_inpt_good(self, mock_log): """ Test input source status shows current input """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.source = '11' - log_debug_calls = [call('({ip}) reset_information() connect status is ' - 'S_NOT_CONNECTED'.format(ip=pjlink.name))] - chk_source_available = ['11', '12', '21', '22', '31', '32'] - pjlink.source_available = chk_source_available + self.pjlink.source = '11' + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "INPT" with data "21"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for INPT'.format(ip=self.pjlink.name)), + call('({ip}) Setting current source to "21"'.format(ip=self.pjlink.name))] + chk_source_available = ['11', '12', '21', '22', '31', '32'] + self.pjlink.source_available = chk_source_available - # WHEN: Called with input source - process_command(projector=self.pjlink, cmd='INPT', data='21') + # WHEN: Called with input source + process_command(projector=self.pjlink, cmd='INPT', data='21') - # THEN: Input selected should reflect current input - assert pjlink.source == '21', 'Input source should be set to "21"' - mock_log.debug.assert_has_calls(log_debug_calls) + # THEN: Input selected should reflect current input + assert ('21' == self.pjlink.source), 'Input source should be set to "21"' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) - @skip('Needs update to new setup') - def test_projector_process_input_not_in_list(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_inpt_invalid(self, mock_log): """ - Test setting input outside of available inputs - - TODO: Future test + Test input source returned not valid according to standard """ - pass + # GIVEN: Test object + log_warning_calls = [call('({ip}) Input source not listed as a PJLink valid source - ' + 'ignoring'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "INPT" with data "91"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for INPT'.format(ip=self.pjlink.name))] + self.pjlink.source = None + self.pjlink.source_available = None - @skip('Needs update to new setup') - def test_projector_process_input_not_in_default(self): - """ - Test setting input with no sources available - TODO: Future test - """ - pass + # WHEN: Called with input source + process_command(projector=self.pjlink, cmd='INPT', data='91') - @skip('Needs update to new setup') - def test_projector_process_input_invalid(self): - """ - Test setting input with an invalid value + # THEN: Input selected should reflect current input + assert (not self.pjlink.source), 'Input source should not have changed' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) - TODO: Future test + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_inpt_not_in_list(self, mock_log): """ + Test input source not listed in available sources + """ + # GIVEN: Test object + log_warning_calls = [call('({ip}) Input source not listed in available sources - ' + 'ignoring'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "INPT" with data "25"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for INPT'.format(ip=self.pjlink.name))] + self.pjlink.source = '11' + chk_source_available = ['11', '12', '21', '22', '31', '32'] + self.pjlink.source_available = chk_source_available - @skip('Needs update to new setup') - def test_projector_process_inst_class_1(self): + # WHEN: Called with input source + process_command(projector=self.pjlink, cmd='INPT', data='25') + + # THEN: Input selected should reflect current input + assert ('11' == self.pjlink.source), 'Input source should not have changed' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_inst_class_1(self, mock_log): """ Test saving video source available information """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.source_available = [] - log_debug_calls = [call('({ip}) reset_information() connect status is ' - 'S_NOT_CONNECTED'.format(ip=pjlink.name)), - call('({ip}) Setting projector source_available to ' - '"[\'11\', \'12\', \'21\', \'22\', \'31\', \'32\']"'.format(ip=pjlink.name))] + self.pjlink.source_available = [] + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "INST" with data ' + '"21 12 11 22 32 31"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for INST'.format(ip=self.pjlink.name)), + call('({ip}) Setting projector source_available to ' + '"[\'11\', \'12\', \'21\', \'22\', \'31\', \'32\']"'.format(ip=self.pjlink.name))] - chk_data = '21 12 11 22 32 31' # Although they should already be sorted, use unsorted to verify method - chk_test = ['11', '12', '21', '22', '31', '32'] + chk_data = '21 12 11 22 32 31' # Although they should already be sorted, use unsorted to check method + chk_test = ['11', '12', '21', '22', '31', '32'] - # WHEN: process_inst called with test data - pjlink.process_inst(data=chk_data) + # WHEN: process_inst called with test data + process_command(projector=self.pjlink, cmd='INST', data=chk_data) - # THEN: Data should have been sorted and saved properly - assert pjlink.source_available == chk_test, "Sources should have been sorted and saved" - mock_log.debug.assert_has_calls(log_debug_calls) + # THEN: Data should have been sorted and saved properly + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (self.pjlink.source_available == chk_test), "Sources should have been sorted and saved" - @skip('Needs update to new setup') - def test_projector_process_lamp_invalid(self): - """ - Test status multiple lamp on/off and hours - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.lamp = [{'Hours': 00000, 'On': True}, - {'Hours': 11111, 'On': False}] - log_data = [call('({ip}) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"'.format(ip=pjlink.name))] - - # WHEN: Call process_command with invalid lamp data - pjlink.process_lamp('11111 1 22222 0 333A3 1') - - # THEN: lamps should not have changed - assert 2 == len(pjlink.lamp), 'Projector should have kept 2 lamps specified' - assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have stayed TRUE' - assert 00000 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been left at 00000' - assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have stayed FALSE' - assert 11111 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been left at 11111' - mock_log.warning.assert_has_calls(log_data) - - @skip('Needs update to new setup') - def test_projector_process_lamp_multiple(self): - """ - Test status multiple lamp on/off and hours - """ - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.lamp = [] - - # WHEN: Call process_command with invalid lamp data - pjlink.process_lamp('11111 1 22222 0 33333 1') - - # THEN: Lamp should have been set with proper lamp status - assert 3 == len(pjlink.lamp), 'Projector should have 3 lamps specified' - assert pjlink.lamp[0]['On'] is True, 'Lamp 1 power status should have been set to TRUE' - assert 11111 == pjlink.lamp[0]['Hours'], 'Lamp 1 hours should have been set to 11111' - assert pjlink.lamp[1]['On'] is False, 'Lamp 2 power status should have been set to FALSE' - assert 22222 == pjlink.lamp[1]['Hours'], 'Lamp 2 hours should have been set to 22222' - assert pjlink.lamp[2]['On'] is True, 'Lamp 3 power status should have been set to TRUE' - assert 33333 == pjlink.lamp[2]['Hours'], 'Lamp 3 hours should have been set to 33333' - - @skip('Needs update to new setup') - def test_projector_process_lamp_single(self): - """ - Test status lamp on/off and hours - """ - - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.lamp = [] - - # WHEN: Call process_command with invalid lamp data - pjlink.process_lamp('22222 1') - - # THEN: Lamp should have been set with status=ON and hours=22222 - assert 1 == len(pjlink.lamp), 'Projector should have only 1 lamp' - assert pjlink.lamp[0]['On'] is True, 'Lamp power status should have been set to TRUE' - assert 22222 == pjlink.lamp[0]['Hours'], 'Lamp hours should have been set to 22222' - - @skip('Needs update to new setup') - def test_projector_process_lamp_single_hours_only(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_lamp_invalid_missing_data(self, mock_log): """ Test process lamp with 1 lamp reply hours only and no on/off status """ # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.lamp = [] + log_warning_calls = [call('({ip}) process_lamp(): Invalid data "45" - ' + 'Missing data'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "LAMP" with data "45"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for LAMP'.format(ip=self.pjlink.name))] + self.pjlink.lamp = None - # WHEN: Process lamp command called with only hours and no lamp power state - pjlink.process_lamp("45") + # WHEN: Call process_command with 3 lamps + process_command(projector=self.pjlink, cmd='LAMP', data='45') - # THEN: Lamp should show hours as 45 and lamp power as Unavailable - assert 1 == len(pjlink.lamp), 'There should only be 1 lamp available' - assert 45 == pjlink.lamp[0]['Hours'], 'Lamp hours should have equalled 45' - assert pjlink.lamp[0]['On'] is None, 'Lamp power should be "None"' + # THEN: Lamp should have been set with proper lamp status + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (not self.pjlink.lamp), 'Projector lamp info should not have changed' - @skip('Needs update to new setup') - def test_projector_process_name(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_lamp_invalid_nan(self, mock_log): + """ + Test status multiple lamp on/off and hours + """ + # GIVEN: Test object + self.pjlink.lamp = [{'Hours': 00000, 'On': True}, + {'Hours': 11111, 'On': False}] + log_warning_calls = [call('({ip}) process_lamp(): Invalid data "11111 1 22222 0 ' + '333A3 1"'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "LAMP" with data "11111 1 22222 0 ' + '333A3 1"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for LAMP'.format(ip=self.pjlink.name))] + + # WHEN: Call process_command with invalid lamp data + process_command(projector=self.pjlink, cmd='LAMP', data='11111 1 22222 0 333A3 1') + + # THEN: lamps should not have changed + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (2 == len(self.pjlink.lamp)), 'Projector lamp list should not have changed' + assert self.pjlink.lamp[0]['On'], 'Lamp 1 power status should not have changed' + assert (0 == self.pjlink.lamp[0]['Hours']), 'Lamp 1 hours should not have changed' + assert (not self.pjlink.lamp[1]['On']), 'Lamp 2 power status should not have changed' + assert (11111 == self.pjlink.lamp[1]['Hours']), 'Lamp 2 hours should not have changed' + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_lamp_multiple(self, mock_log): + """ + Test status multiple lamp on/off and hours + """ + # GIVEN: Test object + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "LAMP" with data "11111 1 22222 0 ' + '33333 1"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for LAMP'.format(ip=self.pjlink.name))] + self.pjlink.lamp = None + + # WHEN: Call process_command with 3 lamps + process_command(projector=self.pjlink, cmd='LAMP', data='11111 1 22222 0 33333 1') + + # THEN: Lamp should have been set with proper lamp status + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (3 == len(self.pjlink.lamp)), 'Projector should have 3 lamps specified' + assert self.pjlink.lamp[0]['On'], 'Lamp 1 power status should have been set to TRUE' + assert (11111 == self.pjlink.lamp[0]['Hours']), 'Lamp 1 hours should have been set to 11111' + assert (not self.pjlink.lamp[1]['On']), 'Lamp 2 power status should have been set to FALSE' + assert (22222 == self.pjlink.lamp[1]['Hours']), 'Lamp 2 hours should have been set to 22222' + assert self.pjlink.lamp[2]['On'], 'Lamp 3 power status should have been set to TRUE' + assert (33333 == self.pjlink.lamp[2]['Hours']), 'Lamp 3 hours should have been set to 33333' + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_lamp_single(self, mock_log): + """ + Test status lamp on/off and hours + """ + # GIVEN: Test object + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "LAMP" with data "11111 1"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for LAMP'.format(ip=self.pjlink.name))] + self.pjlink.lamp = None + + # WHEN: Call process_command with 3 lamps + process_command(projector=self.pjlink, cmd='LAMP', data='11111 1') + + # THEN: Lamp should have been set with proper lamp status + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (1 == len(self.pjlink.lamp)), 'Projector should have 1 lamp specified' + assert self.pjlink.lamp[0]['On'], 'Lamp 1 power status should have been set to TRUE' + assert (11111 == self.pjlink.lamp[0]['Hours']), 'Lamp 1 hours should have been set to 11111' + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_name(self, mock_log): """ Test saving NAME data from projector """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - chk_data = "Some Name the End-User Set IN Projector" - log_debug_calls = [call('({ip}) Setting projector PJLink name to ' - '"Some Name the End-User Set IN Projector"'.format(ip=pjlink.name))] + chk_data = "Some Name the End-User Set IN Projector" + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "NAME" with data ' + '"Some Name the End-User Set IN Projector"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for NAME'.format(ip=self.pjlink.name)), + call('({ip}) Setting projector PJLink name to ' + '"Some Name the End-User Set IN Projector"'.format(ip=self.pjlink.name))] - # WHEN: process_name called with test data - pjlink.process_name(data=chk_data) + # WHEN: process_name called with test data + process_command(projector=self.pjlink, cmd='NAME', data=chk_data) - # THEN: name should be set and logged - assert pjlink.pjlink_name == chk_data, 'Name test data should have been saved' - mock_log.debug.assert_has_calls(log_debug_calls) + # THEN: name should be set and logged + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (self.pjlink.pjlink_name == chk_data), 'Name test data should have been saved' - @skip('Needs update to new setup') - def test_projector_process_powr_on(self): - """ - Test status power to ON - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \ - patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \ - patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: - - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.power = S_STANDBY - - # WHEN: process_name called with test data - pjlink.process_powr(data=PJLINK_POWR_STATUS[S_ON]) - - # THEN: Power should be set to ON - assert pjlink.power == S_ON, 'Power should have been set to ON' - assert mock_UpdateIcons.emit.called is True, 'projectorUpdateIcons should have been called' - mock_send_command.assert_called_once_with('INST') - mock_change_status.assert_called_once_with(S_ON) - - @skip('Needs update to new setup') - def test_projector_process_powr_invalid(self): + @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') + @patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') + @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_powr_invalid(self, mock_log, mock_UpdateIcons, mock_change_status, mock_send_command): """ Test process_powr invalid call """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log, \ - patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \ - patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \ - patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: + self.pjlink.power = S_STANDBY + log_warning_calls = [call('({ip}) Unknown power response: "99"'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "POWR" with data "99"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for POWR'.format(ip=self.pjlink.name)), + call('({ip}) Processing POWR command'.format(ip=self.pjlink.name))] - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.power = S_STANDBY - log_warn_calls = [call('({ip}) Unknown power response: "99"'.format(ip=pjlink.name))] + # WHEN: process_command called with test data + process_command(projector=self.pjlink, cmd='POWR', data='99') - # WHEN: process_name called with test data - pjlink.process_powr(data='99') + # THEN: Projector power should not have changed + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (S_STANDBY == self.pjlink.power), 'Power should not have changed' + mock_UpdateIcons.emit.assert_not_called() + mock_change_status.assert_not_called() + mock_send_command.assert_not_called() - # THEN: Power should be set to ON - assert pjlink.power == S_STANDBY, 'Power should not have changed' - mock_UpdateIcons.emit.assert_not_called() - mock_change_status.assert_not_called() - mock_send_command.assert_not_called() - mock_log.warning.assert_has_calls(log_warn_calls) - - @skip('Needs update to new setup') - def test_projector_process_powr_off(self): + @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') + @patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') + @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_powr_off(self, mock_log, mock_UpdateIcons, mock_change_status, mock_send_command): """ - Test status power to STANDBY + Test status power to OFF """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') as mock_send_command, \ - patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') as mock_change_status, \ - patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') as mock_UpdateIcons: + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "POWR" with data "0"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for POWR'.format(ip=self.pjlink.name)), + call('({ip}) Processing POWR command'.format(ip=self.pjlink.name))] + self.pjlink.power = S_ON - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.power = S_ON + # WHEN: process_name called with test data + process_command(projector=self.pjlink, cmd='POWR', data=PJLINK_POWR_STATUS[S_STANDBY]) - # WHEN: process_name called with test data - pjlink.process_powr(data=PJLINK_POWR_STATUS[S_STANDBY]) + # THEN: Power should be set to ON + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (S_STANDBY == self.pjlink.power), 'Power should have been set to OFF' + assert mock_UpdateIcons.emit.called, 'projectorUpdateIcons should have been called' + assert (not mock_send_command.called), 'send_command should not have been called' + mock_change_status.assert_called_once_with(S_STANDBY) - # THEN: Power should be set to ON - assert pjlink.power == S_STANDBY, 'Power should have changed to S_STANDBY' - mock_UpdateIcons.emit.assert_called_with() - mock_change_status.assert_called_with(313) - mock_send_command.assert_not_called() + @patch.object(openlp.core.projectors.pjlink.PJLink, 'send_command') + @patch.object(openlp.core.projectors.pjlink.PJLink, 'change_status') + @patch.object(openlp.core.projectors.pjlink.PJLink, 'projectorUpdateIcons') + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_powr_on(self, mock_log, mock_UpdateIcons, mock_change_status, mock_send_command): + """ + Test status power to ON + """ + # GIVEN: Test object + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "POWR" with data "1"'.format(ip=self.pjlink.name)), + call('({ip}) Calling function for POWR'.format(ip=self.pjlink.name)), + call('({ip}) Processing POWR command'.format(ip=self.pjlink.name))] + self.pjlink.power = S_STANDBY - @skip('Needs update to new setup') - def test_projector_process_rfil_save(self): + # WHEN: process_name called with test data + process_command(projector=self.pjlink, cmd='POWR', data=PJLINK_POWR_STATUS[S_ON]) + + # THEN: Power should be set to ON + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (S_ON == self.pjlink.power), 'Power should have been set to ON' + assert mock_UpdateIcons.emit.called, 'projectorUpdateIcons should have been called' + mock_send_command.assert_called_once_with('INST') + mock_change_status.assert_called_once_with(S_ON) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_rfil_save(self, mock_log): """ Test saving filter type """ - filter_model = 'Filter Type Test' - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.model_filter = None + new_data = 'Filter Type Test' + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "RFIL" with data ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data)), + call('({ip}) Calling function for RFIL'.format(ip=self.pjlink.name))] + self.pjlink.model_filter = None # WHEN: Filter model is received - pjlink.process_rfil(data=filter_model) + process_command(projector=self.pjlink, cmd='RFIL', data=new_data) # THEN: Filter model number should be saved - assert pjlink.model_filter == filter_model, 'Filter type should have been saved' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (self.pjlink.model_filter == new_data), 'Filter model should have been saved' - @skip('Needs update to new setup') - def test_projector_process_rfil_nosave(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_rfil_nosave(self, mock_log): """ Test saving filter type previously saved """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + old_data = 'Old filter type' + new_data = 'Filter Type Test' + log_warning_calls = [call('({ip}) Filter model already set'.format(ip=self.pjlink.name)), + call('({ip}) Saved model: "{data}"'.format(ip=self.pjlink.name, data=old_data)), + call('({ip}) New model: "{data}"'.format(ip=self.pjlink.name, data=new_data))] + log_debug_calls = [call('({ip}) Processing command "RFIL" with data ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data)), + call('({ip}) Calling function for RFIL'.format(ip=self.pjlink.name))] + self.pjlink.model_filter = old_data - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.model_filter = 'Old filter type' - filter_model = 'Filter Type Test' - log_warn_calls = [call('({ip}) Filter model already set'.format(ip=pjlink.name)), - call('({ip}) Saved model: "Old filter type"'.format(ip=pjlink.name)), - call('({ip}) New model: "Filter Type Test"'.format(ip=pjlink.name))] + # WHEN: Filter model is received + process_command(projector=self.pjlink, cmd='RFIL', data=new_data) - # WHEN: Filter model is received - pjlink.process_rfil(data=filter_model) + # THEN: Filter model number should be saved + assert (self.pjlink.model_filter != new_data), 'Filter model should NOT have been saved' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) - # THEN: Filter model number should be saved - assert pjlink.model_filter != filter_model, 'Filter type should NOT have been saved' - mock_log.warning.assert_has_calls(log_warn_calls) - - @skip('Needs update to new setup') - def test_projector_process_rlmp_save(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_rlmp_save(self, mock_log): """ Test saving lamp type """ # GIVEN: Test object - # GIVEN: Test object - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.model_lamp = None - lamp_model = 'Lamp Type Test' + new_data = 'Lamp Type Test' + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "RLMP" with data ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data)), + call('({ip}) Calling function for RLMP'.format(ip=self.pjlink.name))] + self.pjlink.model_lamp = None # WHEN: Filter model is received - pjlink.process_rlmp(data=lamp_model) + process_command(projector=self.pjlink, cmd='RLMP', data=new_data) # THEN: Filter model number should be saved - assert pjlink.model_lamp == lamp_model, 'Lamp type should have been saved' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + assert (self.pjlink.model_lamp == new_data), 'Lamp model should have been saved' - @skip('Needs update to new setup') - def test_projector_process_rlmp_nosave(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_rlmp_nosave(self, mock_log): """ Test saving lamp type previously saved """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: + old_data = 'Old filter type' + new_data = 'Filter Type Test' + log_warning_calls = [call('({ip}) Lamp model already set'.format(ip=self.pjlink.name)), + call('({ip}) Saved lamp: "{data}"'.format(ip=self.pjlink.name, data=old_data)), + call('({ip}) New lamp: "{data}"'.format(ip=self.pjlink.name, data=new_data))] + log_debug_calls = [call('({ip}) Processing command "RLMP" with data ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data)), + call('({ip}) Calling function for RLMP'.format(ip=self.pjlink.name))] + self.pjlink.model_lamp = old_data - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.model_lamp = 'Old lamp type' - lamp_model = 'Lamp Type Test' - log_warn_calls = [call('({ip}) Lamp model already set'.format(ip=pjlink.name)), - call('({ip}) Saved lamp: "Old lamp type"'.format(ip=pjlink.name)), - call('({ip}) New lamp: "Lamp Type Test"'.format(ip=pjlink.name))] + # WHEN: Filter model is received + process_command(projector=self.pjlink, cmd='RLMP', data=new_data) - # WHEN: Filter model is received - pjlink.process_rlmp(data=lamp_model) + # THEN: Filter model number should be saved + assert (self.pjlink.model_lamp != new_data), 'Lamp model should NOT have been saved' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) - # THEN: Filter model number should be saved - assert pjlink.model_lamp != lamp_model, 'Lamp type should NOT have been saved' - mock_log.warning.assert_has_calls(log_warn_calls) - - @skip('Needs update to new setup') - def test_projector_process_snum_set(self): - """ - Test saving serial number from projector - """ - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.serial_no = None - log_debug_calls = [call('({ip}) Setting projector serial number to ' - '"Test Serial Number"'.format(ip=pjlink.name))] - test_number = 'Test Serial Number' - - # WHEN: No serial number is set and we receive serial number command - pjlink.process_snum(data=test_number) - - # THEN: Serial number should be set - assert pjlink.serial_no == test_number, 'Projector serial number should have been set' - mock_log.debug.assert_has_calls(log_debug_calls) - - @skip('Needs update to new setup') - def test_projector_process_snum_different(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_snum_different(self, mock_log): """ Test projector serial number different than saved serial number """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.serial_no = 'Previous serial number' - log_warn_calls = [call('({ip}) Projector serial number does not match ' - 'saved serial number'.format(ip=pjlink.name)), - call('({ip}) Saved: "Previous serial number"'.format(ip=pjlink.name)), - call('({ip}) Received: "Test Serial Number"'.format(ip=pjlink.name)), - call('({ip}) NOT saving serial number'.format(ip=pjlink.name))] - test_number = 'Test Serial Number' + new_data = 'Test Serial Number' + old_data = 'Previous serial number' + log_warning_calls = [call('({ip}) Projector serial number does not match ' + 'saved serial number'.format(ip=self.pjlink.name)), + call('({ip}) Saved: "{data}"'.format(ip=self.pjlink.name, data=old_data)), + call('({ip}) Received: "{data}"'.format(ip=self.pjlink.name, data=new_data)), + call('({ip}) NOT saving serial number'.format(ip=self.pjlink.name))] - # WHEN: No serial number is set and we receive serial number command - pjlink.process_snum(data=test_number) + log_debug_calls = [call('({ip}) Processing command "SNUM" with data ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data)), + call('({ip}) Calling function for SNUM'.format(ip=self.pjlink.name))] + self.pjlink.serial_no = old_data - # THEN: Serial number should be set - assert pjlink.serial_no != test_number, 'Projector serial number should NOT have been set' - mock_log.warning.assert_has_calls(log_warn_calls) + # WHEN: No serial number is set and we receive serial number command + process_command(projector=self.pjlink, cmd='SNUM', data=new_data) - @skip('Needs update to new setup') - def test_projector_process_sver(self): + # THEN: Serial number should be set + assert (self.pjlink.serial_no != new_data), 'Projector serial number should NOT have been set' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_snum_set(self, mock_log): """ - Test invalid software version information - too long + Test saving serial number from projector """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.sw_version = None - pjlink.sw_version_received = None - test_data = 'Test 1 Subtest 1' - log_debug_calls = [call('({ip}) Setting projector software version to ' - '"Test 1 Subtest 1"'.format(ip=pjlink.name))] + new_data = 'Test Serial Number' + self.pjlink.serial_no = None + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "SNUM" with data "{data}"'.format(ip=self.pjlink.name, + data=new_data)), + call('({ip}) Calling function for SNUM'.format(ip=self.pjlink.name)), + call('({ip}) Setting projector serial number to ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data))] - # WHEN: process_sver called with invalid data - pjlink.process_sver(data=test_data) + # WHEN: No serial number is set and we receive serial number command + process_command(projector=self.pjlink, cmd='SNUM', data=new_data) - # THEN: Version information should not change - assert pjlink.sw_version == test_data, 'Software version should have been updated' - mock_log.debug.assert_has_calls(log_debug_calls) + # THEN: Serial number should be set + assert (self.pjlink.serial_no == new_data), 'Projector serial number should have been set' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) - @skip('Needs update to new setup') - def test_projector_process_sver_changed(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_sver_changed(self, mock_log): """ Test invalid software version information - Received different than saved """ # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - test_data_old = 'Test 1 Subtest 1' - test_data_new = 'Test 1 Subtest 2' - log_warn_calls = [call('({ip}) Projector software version does not match ' - 'saved software version'.format(ip=pjlink.name)), - call('({ip}) Saved: "Test 1 Subtest 1"'.format(ip=pjlink.name)), - call('({ip}) Received: "Test 1 Subtest 2"'.format(ip=pjlink.name)), - call('({ip}) Updating software version'.format(ip=pjlink.name))] - pjlink.sw_version = test_data_old + old_data = 'Test 1 Subtest 1' + new_data = 'Test 1 Subtest 2' + log_warning_calls = [call('({ip}) Projector software version does not match ' + 'saved software version'.format(ip=self.pjlink.name)), + call('({ip}) Saved: "{data}"'.format(ip=self.pjlink.name, data=old_data)), + call('({ip}) Received: "{data}"'.format(ip=self.pjlink.name, data=new_data)), + call('({ip}) Updating software version'.format(ip=self.pjlink.name))] + log_debug_calls = [call('({ip}) Processing command "SVER" with data ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data)), + call('({ip}) Calling function for SVER'.format(ip=self.pjlink.name)), + call('({ip}) Setting projector software version to ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data))] + self.pjlink.sw_version = old_data - # WHEN: process_sver called with invalid data - pjlink.process_sver(data=test_data_new) + # WHEN: process_sver called with invalid data + process_command(self.pjlink, cmd='SVER', data=new_data) - # THEN: Version information should not change - assert pjlink.sw_version == test_data_new, 'Software version should have changed' - mock_log.warning.assert_has_calls(log_warn_calls) + # THEN: Version information should change + assert (self.pjlink.sw_version == new_data), 'Software version should have changed' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) - @skip('Needs update to new setup') - def test_projector_process_sver_invalid(self): + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_sver_invalid(self, mock_log): """ Test invalid software version information - too long """ - test_data = 'This is a test software version line that is too long based on PJLink version 2 specs' - log_warn_calls = [call('Invalid software version - too long')] - # GIVEN: Test object - with patch.object(openlp.core.projectors.pjlink, 'log') as mock_log: - pjlink = PJLink(Projector(**TEST1_DATA), no_poll=True) - pjlink.sw_version = None + new_data = 'This is a test software version line that is too long based on PJLink version 2 specs' + log_warning_calls = [call('Invalid software version - too long')] + log_debug_calls = [call('({ip}) Processing command "SVER" with data "{data}"'.format(ip=self.pjlink.name, + data=new_data)), + call('({ip}) Calling function for SVER'.format(ip=self.pjlink.name))] + self.pjlink.sw_version = None + self.pjlink.sw_version_received = None - # WHEN: process_sver called with invalid data - pjlink.process_sver(data=test_data) + # WHEN: process_sver called with invalid data + process_command(projector=self.pjlink, cmd='SVER', data=new_data) - # THEN: Version information should not change - assert pjlink.sw_version is None, 'Software version should not have changed' - assert pjlink.sw_version_received is None, 'Received software version should not have changed' - mock_log.warning.assert_has_calls(log_warn_calls) + # THEN: Version information should not change + assert (not self.pjlink.sw_version), 'Software version should not have changed' + assert (not self.pjlink.sw_version_received), 'Received software version should not have changed' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) + + @patch.object(openlp.core.projectors.pjlinkcommands, 'log') + def test_projector_sver_save(self, mock_log): + """ + Test invalid software version information - too long + """ + # GIVEN: Test object + new_data = 'Test 1 Subtest 1' + log_warning_calls = [] + log_debug_calls = [call('({ip}) Processing command "SVER" with data ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data)), + call('({ip}) Calling function for SVER'.format(ip=self.pjlink.name)), + call('({ip}) Setting projector software version to ' + '"{data}"'.format(ip=self.pjlink.name, data=new_data))] + self.pjlink.sw_version = None + self.pjlink.sw_version_received = None + + # WHEN: process_sver called with invalid data + process_command(projector=self.pjlink, cmd='SVER', data=new_data) + + # THEN: Version information should not change + assert (self.pjlink.sw_version == new_data), 'Software version should have been updated' + assert (not self.pjlink.sw_version_received), 'Received version field should not have changed' + mock_log.warning.assert_has_calls(log_warning_calls) + mock_log.debug.assert_has_calls(log_debug_calls) diff --git a/tests/openlp_core/projectors/test_projector_pjlink_commands_02.py b/tests/openlp_core/projectors/test_projector_commands_03.py similarity index 100% rename from tests/openlp_core/projectors/test_projector_pjlink_commands_02.py rename to tests/openlp_core/projectors/test_projector_commands_03.py diff --git a/tests/openlp_core/projectors/test_projector_pjlink_base_02.py b/tests/openlp_core/projectors/test_projector_pjlink_base_02.py index 78d1e0b80..c45f230a2 100644 --- a/tests/openlp_core/projectors/test_projector_pjlink_base_02.py +++ b/tests/openlp_core/projectors/test_projector_pjlink_base_02.py @@ -132,37 +132,6 @@ class TestPJLinkBase(TestCase): 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, 'state') - @patch.object(openlp.core.projectors.pjlink.PJLink, 'reset_information') - @patch.object(openlp.core.projectors.pjlink, 'log') - def test_local_send_command_no_data_queue_check(self, mock_log, mock_reset, mock_state): - """ - Test _underscore_send_command last queue length check - """ - # GIVEN: Test object - log_error_calls = [] - log_warning_calls = [call('({ip}) _send_command(): No data to send'.format(ip=self.pjlink.name))] - log_debug_calls = [] - mock_state.return_value = QSOCKET_STATE[S_CONNECTED] - 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, 'send_queue') as mock_queue: - # Unlikely case of send_queue not really empty, but len(send_queue) returns 0 - mock_queue.return_value = ['test'] - mock_queue.__len__.return_value = 0 - self.pjlink._send_command(data=None) - - # 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.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') diff --git a/tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py b/tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py index 669f0a10a..137a7c4d0 100644 --- a/tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py +++ b/tests/openlp_core/projectors/test_projector_pjlink_cmd_routing.py @@ -56,9 +56,9 @@ class TestPJLinkRouting(TestCase): Test projector received valid command invalid version """ # GIVEN: Test object - log_warning_text = [call('({ip}) get_data() Command reply version does not match ' - 'a valid command version'.format(ip=self.pjlink.name)), - call('({ip}) _send_command(): Nothing to send - returning'.format(ip=self.pjlink.name))] + 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)), @@ -83,10 +83,10 @@ class TestPJLinkRouting(TestCase): Test projector receiving invalid command """ # GIVEN: Test object - log_warning_text = [call('({ip}) get_data(): Invalid packet - ' - 'unknown command "UNKN"'.format(ip=self.pjlink.name)), - call('({ip}) _send_command(): Nothing to send - ' - 'returning'.format(ip=self.pjlink.name))] + 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, @@ -113,9 +113,9 @@ class TestPJLinkRouting(TestCase): Test projector received valid command with command version higher than projector """ # GIVEN: Test object - log_warning_text = [call('({ip}) get_data(): Projector returned class reply higher than projector ' - 'stated class'.format(ip=self.pjlink.name)), - call('({ip}) _send_command(): Nothing to send - returning'.format(ip=self.pjlink.name))] + 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)),