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

Proposed by Ken Roberts
Status: Merged
Merged at revision: 2789
Proposed branch: lp:~alisonken1/openlp/pjlink2-l
Merge into: lp:openlp
Diff against target: 4652 lines (+2155/-2158)
27 files modified
openlp/core/lib/__init__.py (+0/-3)
openlp/core/projectors/__init__.py (+4/-2)
openlp/core/projectors/db.py (+2/-2)
openlp/core/projectors/editform.py (+2/-2)
openlp/core/projectors/manager.py (+7/-8)
openlp/core/projectors/pjlink.py (+1/-5)
openlp/core/projectors/sourceselectform.py (+2/-2)
openlp/core/projectors/tab.py (+1/-1)
openlp/core/ui/__init__.py (+4/-3)
openlp/core/ui/firsttimewizard.py (+2/-2)
openlp/core/ui/mainwindow.py (+3/-3)
openlp/core/ui/projector/__init__.py (+0/-24)
openlp/core/ui/settingsform.py (+1/-1)
tests/functional/openlp_core/lib/test_projector_constants.py (+0/-43)
tests/functional/openlp_core/lib/test_projector_db.py (+0/-462)
tests/functional/openlp_core/lib/test_projector_pjlink_base.py (+0/-209)
tests/functional/openlp_core/lib/test_projector_pjlink_cmd_routing.py (+0/-224)
tests/functional/openlp_core/lib/test_projector_pjlink_commands.py (+0/-1149)
tests/functional/openlp_core/projectors/__init__.py (+24/-0)
tests/functional/openlp_core/projectors/test_projector_constants.py (+43/-0)
tests/functional/openlp_core/projectors/test_projector_db.py (+462/-0)
tests/functional/openlp_core/projectors/test_projector_pjlink_base.py (+209/-0)
tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py (+224/-0)
tests/functional/openlp_core/projectors/test_projector_pjlink_commands.py (+1149/-0)
tests/interfaces/openlp_core/ui/test_projectoreditform.py (+7/-6)
tests/interfaces/openlp_core/ui/test_projectormanager.py (+4/-3)
tests/interfaces/openlp_core/ui/test_projectorsourceform.py (+4/-4)
To merge this branch: bzr merge lp:~alisonken1/openlp/pjlink2-l
Reviewer Review Type Date Requested Status
Phill Approve
Raoul Snyman Approve
Review via email: mp+333860@code.launchpad.net

This proposal supersedes a proposal from 2017-11-16.

Commit message

PJLink2-L updates

Description of the change

- Move openlp.core.lib.projector to openlp.core.projectors
- Move openlp.core.ui.projector to openlp.core.projectors
- Move tests.functional.openlp_core/lib/test_projector* to tests.functional.openlp.core.projectors
- Fix imports for new projector location
- Convert projector imports to fully-qualified import
- Fix delete projector item in ui.manager
- Fix projector tests
- Merge trunk (fix tests)
- Rename "Projector" dock to "Projector Controller"
--------------------------------------------------------------------------------
lp:~alisonken1/openlp/pjlink2-l (revision 2785)
https://ci.openlp.io/job/Branch-01-Pull/2303/ [SUCCESS]
https://ci.openlp.io/job/Branch-02-Functional-Tests/2204/ [SUCCESS]
https://ci.openlp.io/job/Branch-03-Interface-Tests/2082/ [SUCCESS]
https://ci.openlp.io/job/Branch-04a-Code_Analysis/1408/ [SUCCESS]
https://ci.openlp.io/job/Branch-04b-Test_Coverage/1232/ [SUCCESS]
https://ci.openlp.io/job/Branch-04c-Code_Analysis2/362/ [SUCCESS]
https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/193/ [FAILURE]

To post a comment you must log in.
Revision history for this message
Ken Roberts (alisonken1) wrote : Posted in a previous version of this proposal

This merge was originally branched from trunk as of 0100 2017-11-10.

Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Looks good, just 2 things:

1. Merge from trunk, it'll fix the tests
2. I have some comments on your import statements in-line, please fix them up.

review: Needs Fixing
Revision history for this message
Raoul Snyman (raoul-snyman) wrote : Posted in a previous version of this proposal

Just one last tweak.

review: Needs Fixing
Revision history for this message
Raoul Snyman (raoul-snyman) :
review: Approve
Revision history for this message
Phill (phill-ridout) wrote :

You've got a load of test files that appear to have been removed, and the re-added in another place. e.g.:

=== removed file 'tests/functional/openlp_core/lib/test_projector_db.py'
=== added file 'tests/functional/openlp_core/projectors/test_projector_db.py'

Have you moved these through the OS, rather than using bzr mv? It would keep the revision history intact and produce a cleaner diff.

review: Needs Information
Revision history for this message
Ken Roberts (alisonken1) wrote :

Yes - some of the files were OS mv'ed before I remembered the bzr mv.
Sorry about that. It would probably have to wait until monday if you
want me to back out the changes and try to redo them with the proper
bzr move.
Let me know if that is what you want me to try.

On Fri, Nov 17, 2017 at 8:02 AM, Phill <email address hidden> wrote:
> Review: Needs Information
>
> You've got a load of test files that appear to have been removed, and the re-added in another place. e.g.:
>
> === removed file 'tests/functional/openlp_core/lib/test_projector_db.py'
> === added file 'tests/functional/openlp_core/projectors/test_projector_db.py'
>
> Have you moved these through the OS, rather than using bzr mv? It would keep the revision history intact and produce a cleaner diff.
> --
> https://code.launchpad.net/~alisonken1/openlp/pjlink2-l/+merge/333860
> You are the owner of lp:~alisonken1/openlp/pjlink2-l.

--
- Ken
Registered Linux user 296561
Slackin' since 1993
Slackware Linux (http://www.slackware.com)
OpenLP - Church Projection Software
Empower Your Church http://openlp.org

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

It's not a big issue to me, I can see the files moved.

Revision history for this message
Phill (phill-ridout) wrote :

I've looked again, as it's only the tests and superfly is happy with it I'll approve.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/lib/__init__.py'
2--- openlp/core/lib/__init__.py 2017-11-09 20:39:17 +0000
3+++ openlp/core/lib/__init__.py 2017-11-17 06:06:50 +0000
4@@ -620,6 +620,3 @@
5 from .htmlbuilder import build_html, build_lyrics_format_css, build_lyrics_outline_css, build_chords_css
6 from .imagemanager import ImageManager
7 from .mediamanageritem import MediaManagerItem
8-from .projector.db import ProjectorDB, Projector
9-from .projector.pjlink import PJLink
10-from .projector.constants import PJLINK_PORT, ERROR_MSG, ERROR_STRING
11
12=== removed directory 'openlp/core/lib/projector'
13=== added directory 'openlp/core/projectors'
14=== renamed file 'openlp/core/lib/projector/__init__.py' => 'openlp/core/projectors/__init__.py'
15--- openlp/core/lib/projector/__init__.py 2016-12-31 11:01:36 +0000
16+++ openlp/core/projectors/__init__.py 2017-11-17 06:06:50 +0000
17@@ -20,11 +20,13 @@
18 # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
19 ###############################################################################
20 """
21- :mod:`openlp.core.ui.projector`
22+ :mod:`openlp.core.projectors`
23
24- Initialization for the openlp.core.ui.projector modules.
25+ Initialization for the openlp.core.projectors modules.
26 """
27
28+from openlp.core.projectors.constants import PJLINK_PORT, ERROR_MSG, ERROR_STRING
29+
30
31 class DialogSourceStyle(object):
32 """
33
34=== renamed file 'openlp/core/lib/projector/constants.py' => 'openlp/core/projectors/constants.py'
35=== renamed file 'openlp/core/lib/projector/db.py' => 'openlp/core/projectors/db.py'
36--- openlp/core/lib/projector/db.py 2017-10-23 22:09:57 +0000
37+++ openlp/core/projectors/db.py 2017-11-17 06:06:50 +0000
38@@ -43,8 +43,8 @@
39 from sqlalchemy.orm import relationship
40
41 from openlp.core.lib.db import Manager, init_db, init_url
42-from openlp.core.lib.projector.constants import PJLINK_DEFAULT_CODES
43-from openlp.core.lib.projector import upgrade
44+from openlp.core.projectors.constants import PJLINK_DEFAULT_CODES
45+from openlp.core.projectors import upgrade
46
47 Base = declarative_base(MetaData())
48
49
50=== renamed file 'openlp/core/ui/projector/editform.py' => 'openlp/core/projectors/editform.py'
51--- openlp/core/ui/projector/editform.py 2017-10-07 07:05:07 +0000
52+++ openlp/core/projectors/editform.py 2017-11-17 06:06:50 +0000
53@@ -30,8 +30,8 @@
54 from openlp.core.common import verify_ip_address
55 from openlp.core.common.i18n import translate
56 from openlp.core.lib import build_icon
57-from openlp.core.lib.projector.db import Projector
58-from openlp.core.lib.projector.constants import PJLINK_PORT
59+from openlp.core.projectors.db import Projector
60+from openlp.core.projectors.constants import PJLINK_PORT
61
62 log = logging.getLogger(__name__)
63 log.debug('editform loaded')
64
65=== renamed file 'openlp/core/ui/projector/manager.py' => 'openlp/core/projectors/manager.py'
66--- openlp/core/ui/projector/manager.py 2017-10-23 22:09:57 +0000
67+++ openlp/core/projectors/manager.py 2017-11-17 06:06:50 +0000
68@@ -34,14 +34,14 @@
69 from openlp.core.common.registry import RegistryBase
70 from openlp.core.common.settings import Settings
71 from openlp.core.lib.ui import create_widget_action
72-from openlp.core.lib.projector import DialogSourceStyle
73-from openlp.core.lib.projector.constants import ERROR_MSG, ERROR_STRING, E_AUTHENTICATION, E_ERROR, \
74+from openlp.core.projectors import DialogSourceStyle
75+from openlp.core.projectors.constants import ERROR_MSG, ERROR_STRING, E_AUTHENTICATION, E_ERROR, \
76 E_NETWORK, E_NOT_CONNECTED, E_UNKNOWN_SOCKET_ERROR, STATUS_STRING, S_CONNECTED, S_CONNECTING, S_COOLDOWN, \
77 S_INITIALIZE, S_NOT_CONNECTED, S_OFF, S_ON, S_STANDBY, S_WARMUP
78-from openlp.core.lib.projector.db import ProjectorDB
79-from openlp.core.lib.projector.pjlink import PJLink, PJLinkUDP
80-from openlp.core.ui.projector.editform import ProjectorEditForm
81-from openlp.core.ui.projector.sourceselectform import SourceSelectTabs, SourceSelectSingle
82+from openlp.core.projectors.db import ProjectorDB
83+from openlp.core.projectors.pjlink import PJLink, PJLinkUDP
84+from openlp.core.projectors.editform import ProjectorEditForm
85+from openlp.core.projectors.sourceselectform import SourceSelectTabs, SourceSelectSingle
86 from openlp.core.widgets.toolbar import OpenLPToolbar
87
88 log = logging.getLogger(__name__)
89@@ -518,7 +518,7 @@
90 projector.thread.quit()
91 new_list = []
92 for item in self.projector_list:
93- if item.link.dbid == projector.link.dbid:
94+ if item.link.db_item.id == projector.link.db_item.id:
95 continue
96 new_list.append(item)
97 self.projector_list = new_list
98@@ -730,7 +730,6 @@
99 thread.started.connect(item.link.thread_started)
100 thread.finished.connect(item.link.thread_stopped)
101 thread.finished.connect(thread.deleteLater)
102- item.link.projectorNetwork.connect(self.update_status)
103 item.link.changeStatus.connect(self.update_status)
104 item.link.projectorAuthentication.connect(self.authentication_error)
105 item.link.projectorNoAuthentication.connect(self.no_authentication_error)
106
107=== renamed file 'openlp/core/lib/projector/pjlink.py' => 'openlp/core/projectors/pjlink.py'
108--- openlp/core/lib/projector/pjlink.py 2017-10-23 22:09:57 +0000
109+++ openlp/core/projectors/pjlink.py 2017-11-17 06:06:50 +0000
110@@ -54,7 +54,7 @@
111
112 from openlp.core.common import qmd5_hash
113 from openlp.core.common.i18n import translate
114-from openlp.core.lib.projector.constants import CONNECTION_ERRORS, CR, ERROR_MSG, ERROR_STRING, \
115+from openlp.core.projectors.constants import CONNECTION_ERRORS, CR, ERROR_MSG, ERROR_STRING, \
116 E_AUTHENTICATION, E_CONNECTION_REFUSED, E_GENERAL, E_INVALID_DATA, E_NETWORK, E_NOT_CONNECTED, E_OK, \
117 E_PARAMETER, E_PROJECTOR, E_SOCKET_TIMEOUT, E_UNAVAILABLE, E_UNDEFINED, PJLINK_ERRORS, PJLINK_ERST_DATA, \
118 PJLINK_ERST_STATUS, PJLINK_MAX_PACKET, PJLINK_PORT, PJLINK_POWR_STATUS, PJLINK_VALID_CMD, \
119@@ -520,7 +520,6 @@
120 """
121 # Signals sent by this module
122 changeStatus = QtCore.pyqtSignal(str, int, str)
123- projectorNetwork = QtCore.pyqtSignal(int) # Projector network activity
124 projectorStatus = QtCore.pyqtSignal(int) # Status update
125 projectorAuthentication = QtCore.pyqtSignal(str) # Authentication error
126 projectorNoAuthentication = QtCore.pyqtSignal(str) # PIN set and no authentication needed
127@@ -846,7 +845,6 @@
128 log.debug('({ip}) get_socket(): No data available (-1)'.format(ip=self.ip))
129 return self.receive_data_signal()
130 self.socket_timer.stop()
131- self.projectorNetwork.emit(S_NETWORK_RECEIVED)
132 return self.get_data(buff=read, ip=self.ip)
133
134 def get_data(self, buff, ip):
135@@ -925,7 +923,6 @@
136 if cmd not in PJLINK_VALID_CMD:
137 log.error('({ip}) send_command(): Invalid command requested - ignoring.'.format(ip=self.ip))
138 return
139- self.projectorNetwork.emit(S_NETWORK_SENDING)
140 log.debug('({ip}) send_command(): Building cmd="{command}" opts="{data}"{salt}'.format(ip=self.ip,
141 command=cmd,
142 data=opts,
143@@ -996,7 +993,6 @@
144 log.debug('({ip}) _send_string(): Sending "{data}"'.format(ip=self.ip, data=out.strip()))
145 log.debug('({ip}) _send_string(): Queue = {data}'.format(ip=self.ip, data=self.send_queue))
146 self.socket_timer.start()
147- self.projectorNetwork.emit(S_NETWORK_SENDING)
148 sent = self.write(out.encode('{string_encoding}'.format(string_encoding='utf-8' if utf8 else 'ascii')))
149 self.waitForBytesWritten(2000) # 2 seconds should be enough
150 if sent == -1:
151
152=== renamed file 'openlp/core/ui/projector/sourceselectform.py' => 'openlp/core/projectors/sourceselectform.py'
153--- openlp/core/ui/projector/sourceselectform.py 2017-10-07 07:05:07 +0000
154+++ openlp/core/projectors/sourceselectform.py 2017-11-17 06:06:50 +0000
155@@ -31,8 +31,8 @@
156 from openlp.core.common import is_macosx
157 from openlp.core.common.i18n import translate
158 from openlp.core.lib import build_icon
159-from openlp.core.lib.projector.db import ProjectorSource
160-from openlp.core.lib.projector.constants import PJLINK_DEFAULT_SOURCES, PJLINK_DEFAULT_CODES
161+from openlp.core.projectors.db import ProjectorSource
162+from openlp.core.projectors.constants import PJLINK_DEFAULT_SOURCES, PJLINK_DEFAULT_CODES
163
164 log = logging.getLogger(__name__)
165
166
167=== renamed file 'openlp/core/ui/projector/tab.py' => 'openlp/core/projectors/tab.py'
168--- openlp/core/ui/projector/tab.py 2017-10-07 07:05:07 +0000
169+++ openlp/core/projectors/tab.py 2017-11-17 06:06:50 +0000
170@@ -29,7 +29,7 @@
171 from openlp.core.common.i18n import UiStrings, translate
172 from openlp.core.common.settings import Settings
173 from openlp.core.lib import SettingsTab
174-from openlp.core.lib.projector import DialogSourceStyle
175+from openlp.core.projectors import DialogSourceStyle
176
177 log = logging.getLogger(__name__)
178 log.debug('projectortab module loaded')
179
180=== renamed file 'openlp/core/lib/projector/upgrade.py' => 'openlp/core/projectors/upgrade.py'
181=== modified file 'openlp/core/ui/__init__.py'
182--- openlp/core/ui/__init__.py 2017-06-05 18:22:14 +0000
183+++ openlp/core/ui/__init__.py 2017-11-17 06:06:50 +0000
184@@ -115,9 +115,10 @@
185 from .shortcutlistform import ShortcutListForm
186 from .servicemanager import ServiceManager
187 from .thememanager import ThemeManager
188-from .projector.manager import ProjectorManager
189-from .projector.tab import ProjectorTab
190-from .projector.editform import ProjectorEditForm
191+
192+from openlp.core.projectors.editform import ProjectorEditForm
193+from openlp.core.projectors.manager import ProjectorManager
194+from openlp.core.projectors.tab import ProjectorTab
195
196 __all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeForm',
197 'ThemeManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm', 'Display', 'AudioPlayer',
198
199=== modified file 'openlp/core/ui/firsttimewizard.py'
200--- openlp/core/ui/firsttimewizard.py 2017-10-07 07:05:07 +0000
201+++ openlp/core/ui/firsttimewizard.py 2017-11-17 06:06:50 +0000
202@@ -261,8 +261,8 @@
203 self.alert_check_box.setText(translate('OpenLP.FirstTimeWizard',
204 'Alerts – Display informative messages while showing other slides'))
205 self.projectors_check_box.setText(translate('OpenLP.FirstTimeWizard',
206- 'Projectors – Control PJLink compatible projects on your network'
207- ' from OpenLP'))
208+ 'Projector Controller – Control PJLink compatible projects on your'
209+ ' network from OpenLP'))
210 self.no_internet_page.setTitle(translate('OpenLP.FirstTimeWizard', 'No Internet Connection'))
211 self.no_internet_page.setSubTitle(
212 translate('OpenLP.FirstTimeWizard', 'Unable to detect an Internet connection.'))
213
214=== modified file 'openlp/core/ui/mainwindow.py'
215--- openlp/core/ui/mainwindow.py 2017-11-03 20:55:41 +0000
216+++ openlp/core/ui/mainwindow.py 2017-11-17 06:06:50 +0000
217@@ -48,6 +48,7 @@
218 from openlp.core.display.renderer import Renderer
219 from openlp.core.lib import PluginManager, ImageManager, PluginStatus, build_icon
220 from openlp.core.lib.ui import create_action
221+from openlp.core.projectors.manager import ProjectorManager
222 from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, LiveController, PluginForm, \
223 ShortcutListForm, FormattingTagForm, PreviewController
224 from openlp.core.ui.firsttimeform import FirstTimeForm
225@@ -55,7 +56,6 @@
226 from openlp.core.widgets.docks import OpenLPDockWidget, MediaDockManager
227 from openlp.core.ui.media import MediaController
228 from openlp.core.ui.printserviceform import PrintServiceForm
229-from openlp.core.ui.projector.manager import ProjectorManager
230 from openlp.core.ui.style import PROGRESSBAR_STYLE, get_library_stylesheet
231 from openlp.core.version import get_version
232
233@@ -375,7 +375,7 @@
234 self.media_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Library'))
235 self.service_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Service'))
236 self.theme_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Themes'))
237- self.projector_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Projectors'))
238+ self.projector_manager_dock.setWindowTitle(translate('OpenLP.MainWindow', 'Projector Controller'))
239 self.file_new_item.setText(translate('OpenLP.MainWindow', '&New Service'))
240 self.file_new_item.setToolTip(UiStrings().NewService)
241 self.file_new_item.setStatusTip(UiStrings().CreateService)
242@@ -407,7 +407,7 @@
243 translate('OpenLP.MainWindow', 'Import settings from a *.config file previously exported from '
244 'this or another machine.'))
245 self.settings_import_item.setText(translate('OpenLP.MainWindow', 'Settings'))
246- self.view_projector_manager_item.setText(translate('OpenLP.MainWindow', '&Projectors'))
247+ self.view_projector_manager_item.setText(translate('OpenLP.MainWindow', '&Projector Controller'))
248 self.view_projector_manager_item.setToolTip(translate('OpenLP.MainWindow', 'Hide or show Projectors.'))
249 self.view_projector_manager_item.setStatusTip(translate('OpenLP.MainWindow',
250 'Toggle visibility of the Projectors.'))
251
252=== removed directory 'openlp/core/ui/projector'
253=== removed file 'openlp/core/ui/projector/__init__.py'
254--- openlp/core/ui/projector/__init__.py 2016-12-31 11:01:36 +0000
255+++ openlp/core/ui/projector/__init__.py 1970-01-01 00:00:00 +0000
256@@ -1,24 +0,0 @@
257-# -*- coding: utf-8 -*-
258-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
259-
260-###############################################################################
261-# OpenLP - Open Source Lyrics Projection #
262-# --------------------------------------------------------------------------- #
263-# Copyright (c) 2008-2017 OpenLP Developers #
264-# --------------------------------------------------------------------------- #
265-# This program is free software; you can redistribute it and/or modify it #
266-# under the terms of the GNU General Public License as published by the Free #
267-# Software Foundation; version 2 of the License. #
268-# #
269-# This program is distributed in the hope that it will be useful, but WITHOUT #
270-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
271-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
272-# more details. #
273-# #
274-# You should have received a copy of the GNU General Public License along #
275-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
276-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
277-###############################################################################
278-"""
279-The Projector driver module.
280-"""
281
282=== modified file 'openlp/core/ui/settingsform.py'
283--- openlp/core/ui/settingsform.py 2017-10-23 22:09:57 +0000
284+++ openlp/core/ui/settingsform.py 2017-11-17 06:06:50 +0000
285@@ -30,9 +30,9 @@
286 from openlp.core.common.mixins import RegistryProperties
287 from openlp.core.common.registry import Registry
288 from openlp.core.lib import build_icon
289+from openlp.core.projectors.tab import ProjectorTab
290 from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
291 from openlp.core.ui.media import PlayerTab
292-from openlp.core.ui.projector.tab import ProjectorTab
293 from openlp.core.ui.settingsdialog import Ui_SettingsDialog
294
295 log = logging.getLogger(__name__)
296
297=== removed file 'tests/functional/openlp_core/lib/test_projector_constants.py'
298--- tests/functional/openlp_core/lib/test_projector_constants.py 2017-08-06 07:23:26 +0000
299+++ tests/functional/openlp_core/lib/test_projector_constants.py 1970-01-01 00:00:00 +0000
300@@ -1,43 +0,0 @@
301-# -*- coding: utf-8 -*-
302-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
303-
304-###############################################################################
305-# OpenLP - Open Source Lyrics Projection #
306-# --------------------------------------------------------------------------- #
307-# Copyright (c) 2008-2015 OpenLP Developers #
308-# --------------------------------------------------------------------------- #
309-# This program is free software; you can redistribute it and/or modify it #
310-# under the terms of the GNU General Public License as published by the Free #
311-# Software Foundation; version 2 of the License. #
312-# #
313-# This program is distributed in the hope that it will be useful, but WITHOUT #
314-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
315-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
316-# more details. #
317-# #
318-# You should have received a copy of the GNU General Public License along #
319-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
320-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
321-###############################################################################
322-"""
323-Package to test the openlp.core.lib.projector.constants package.
324-"""
325-from unittest import TestCase
326-
327-
328-class TestProjectorConstants(TestCase):
329- """
330- Test specific functions in the projector constants module.
331- """
332- def test_build_pjlink_video_label(self):
333- """
334- Test building PJLINK_DEFAULT_CODES dictionary
335- """
336- # GIVEN: Test data
337- from tests.resources.projector.data import TEST_VIDEO_CODES
338-
339- # WHEN: Import projector PJLINK_DEFAULT_CODES
340- from openlp.core.lib.projector.constants import PJLINK_DEFAULT_CODES
341-
342- # THEN: Verify dictionary was build correctly
343- self.assertEqual(PJLINK_DEFAULT_CODES, TEST_VIDEO_CODES, 'PJLink video strings should match')
344
345=== removed file 'tests/functional/openlp_core/lib/test_projector_db.py'
346--- tests/functional/openlp_core/lib/test_projector_db.py 2017-09-22 12:03:28 +0000
347+++ tests/functional/openlp_core/lib/test_projector_db.py 1970-01-01 00:00:00 +0000
348@@ -1,462 +0,0 @@
349-# -*- coding: utf-8 -*-
350-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
351-
352-###############################################################################
353-# OpenLP - Open Source Lyrics Projection #
354-# --------------------------------------------------------------------------- #
355-# Copyright (c) 2008-2017 OpenLP Developers #
356-# --------------------------------------------------------------------------- #
357-# This program is free software; you can redistribute it and/or modify it #
358-# under the terms of the GNU General Public License as published by the Free #
359-# Software Foundation; version 2 of the License. #
360-# #
361-# This program is distributed in the hope that it will be useful, but WITHOUT #
362-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
363-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
364-# more details. #
365-# #
366-# You should have received a copy of the GNU General Public License along #
367-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
368-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
369-###############################################################################
370-"""
371-Package to test the openlp.core.ui.projectordb find, edit, delete
372-record functions.
373-
374-PREREQUISITE: add_record() and get_all() functions validated.
375-"""
376-import os
377-import shutil
378-from tempfile import mkdtemp
379-
380-from unittest import TestCase
381-from unittest.mock import patch
382-
383-from openlp.core.lib.projector import upgrade
384-from openlp.core.lib.db import upgrade_db
385-from openlp.core.lib.projector.constants import PJLINK_PORT
386-from openlp.core.lib.projector.db import Manufacturer, Model, Projector, ProjectorDB, ProjectorSource, Source
387-
388-from tests.resources.projector.data import TEST_DB_PJLINK1, TEST_DB, TEST1_DATA, TEST2_DATA, TEST3_DATA
389-from tests.utils.constants import TEST_RESOURCES_PATH
390-
391-
392-def compare_data(one, two):
393- """
394- Verify two Projector() instances contain the same data
395- """
396- return one is not None and \
397- two is not None and \
398- one.ip == two.ip and \
399- one.port == two.port and \
400- one.name == two.name and \
401- one.location == two.location and \
402- one.notes == two.notes and \
403- one.sw_version == two.sw_version and \
404- one.serial_no == two.serial_no and \
405- one.model_filter == two.model_filter and \
406- one.model_lamp == two.model_lamp
407-
408-
409-def compare_source(one, two):
410- """
411- Verify two ProjectorSource instances contain the same data
412- """
413- return one is not None and \
414- two is not None and \
415- one.projector_id == two.projector_id and \
416- one.code == two.code and \
417- one.text == two.text
418-
419-
420-def add_records(projector_db, test):
421- """
422- Add record if not in database
423- """
424- record_list = projector_db.get_projector_all()
425- if len(record_list) < 1:
426- added = False
427- for record in test:
428- added = projector_db.add_projector(record) or added
429- return added
430-
431- for new_record in test:
432- added = None
433- for record in record_list:
434- if compare_data(record, new_record):
435- break
436- added = projector_db.add_projector(new_record)
437- return added
438-
439-
440-class TestProjectorDBUpdate(TestCase):
441- """
442- Test case for upgrading Projector DB.
443- NOTE: Separate class so I don't have to look for upgrade tests.
444- """
445- def setUp(self):
446- """
447- Setup for tests
448- """
449- self.tmp_folder = mkdtemp(prefix='openlp_')
450-
451- def tearDown(self):
452- """
453- Clean up after tests
454- """
455- # Ignore errors since windows can have problems with locked files
456- shutil.rmtree(self.tmp_folder, ignore_errors=True)
457-
458- def test_upgrade_old_projector_db(self):
459- """
460- Test that we can upgrade an old song db to the current schema
461- """
462- # GIVEN: An old prjector db
463- old_db = os.path.join(TEST_RESOURCES_PATH, "projector", TEST_DB_PJLINK1)
464- tmp_db = os.path.join(self.tmp_folder, TEST_DB)
465- shutil.copyfile(old_db, tmp_db)
466- db_url = 'sqlite:///{db}'.format(db=tmp_db)
467-
468- # WHEN: upgrading the db
469- updated_to_version, latest_version = upgrade_db(db_url, upgrade)
470-
471- # THEN: the song db should have been upgraded to the latest version
472- self.assertEqual(updated_to_version, latest_version,
473- 'The projector DB should have been upgrade to the latest version')
474-
475-
476-class TestProjectorDB(TestCase):
477- """
478- Test case for ProjectorDB
479- """
480- @patch('openlp.core.lib.projector.db.init_url')
481- def setUp(self, mocked_init_url):
482- """
483- Set up anything necessary for all tests
484- """
485- self.tmp_folder = mkdtemp(prefix='openlp_')
486- tmpdb_url = 'sqlite:///{db}'.format(db=os.path.join(self.tmp_folder, TEST_DB))
487- mocked_init_url.return_value = tmpdb_url
488- self.projector = ProjectorDB()
489-
490- def tearDown(self):
491- """
492- Clean up
493- """
494- self.projector.session.close()
495- self.projector = None
496- # Ignore errors since windows can have problems with locked files
497- shutil.rmtree(self.tmp_folder, ignore_errors=True)
498-
499- def test_find_record_by_ip(self):
500- """
501- Test find record by IP
502- """
503- # GIVEN: Record entries in database
504- add_records(self.projector, [Projector(**TEST1_DATA), Projector(**TEST2_DATA)])
505-
506- # WHEN: Search for record using IP
507- record = self.projector.get_projector_by_ip(TEST2_DATA['ip'])
508-
509- # THEN: Verify proper record returned
510- self.assertTrue(compare_data(Projector(**TEST2_DATA), record),
511- 'Record found should have been test_2 data')
512-
513- def test_find_record_by_name(self):
514- """
515- Test find record by name
516- """
517- # GIVEN: Record entries in database
518- add_records(self.projector, [Projector(**TEST1_DATA), Projector(**TEST2_DATA)])
519-
520- # WHEN: Search for record using name
521- record = self.projector.get_projector_by_name(TEST2_DATA['name'])
522-
523- # THEN: Verify proper record returned
524- self.assertTrue(compare_data(Projector(**TEST2_DATA), record),
525- 'Record found should have been test_2 data')
526-
527- def test_record_delete(self):
528- """
529- Test record can be deleted
530- """
531- # GIVEN: Record in database
532- add_records(self.projector, [Projector(**TEST3_DATA), ])
533- record = self.projector.get_projector_by_ip(TEST3_DATA['ip'])
534-
535- # WHEN: Record deleted
536- self.projector.delete_projector(record)
537-
538- # THEN: Verify record not retrievable
539- found = self.projector.get_projector_by_ip(TEST3_DATA['ip'])
540- self.assertFalse(found, 'test_3 record should have been deleted')
541-
542- def test_record_edit(self):
543- """
544- Test edited record returns the same record ID with different data
545- """
546- # GIVEN: Record entries in database
547- add_records(self.projector, [Projector(**TEST1_DATA), Projector(**TEST2_DATA)])
548-
549- # WHEN: We retrieve a specific record
550- record = self.projector.get_projector_by_ip(TEST1_DATA['ip'])
551- record_id = record.id
552-
553- # WHEN: Data is changed
554- record.ip = TEST3_DATA['ip']
555- record.port = TEST3_DATA['port']
556- record.pin = TEST3_DATA['pin']
557- record.name = TEST3_DATA['name']
558- record.location = TEST3_DATA['location']
559- record.notes = TEST3_DATA['notes']
560- record.sw_version = TEST3_DATA['sw_version']
561- record.serial_no = TEST3_DATA['serial_no']
562- record.model_filter = TEST3_DATA['model_filter']
563- record.model_lamp = TEST3_DATA['model_lamp']
564- updated = self.projector.update_projector(record)
565- self.assertTrue(updated, 'Save updated record should have returned True')
566- record = self.projector.get_projector_by_ip(TEST3_DATA['ip'])
567-
568- # THEN: Record ID should remain the same, but data should be changed
569- self.assertEqual(record_id, record.id, 'Edited record should have the same ID')
570- self.assertTrue(compare_data(Projector(**TEST3_DATA), record), 'Edited record should have new data')
571-
572- def test_source_add(self):
573- """
574- Test source entry for projector item
575- """
576- # GIVEN: Record entries in database
577- projector1 = Projector(**TEST1_DATA)
578- self.projector.add_projector(projector1)
579- item = self.projector.get_projector_by_id(projector1.id)
580- item_id = item.id
581-
582- # WHEN: A source entry is saved for item
583- source = ProjectorSource(projector_id=item_id, code='11', text='First RGB source')
584- self.projector.add_source(source)
585-
586- # THEN: Projector should have the same source entry
587- item = self.projector.get_projector_by_id(item_id)
588- self.assertTrue(compare_source(item.source_list[0], source))
589-
590- def test_manufacturer_repr(self):
591- """
592- Test Manufacturer.__repr__() text
593- """
594- # GIVEN: Test object
595- manufacturer = Manufacturer()
596-
597- # WHEN: Name is set
598- manufacturer.name = 'OpenLP Test'
599-
600- # THEN: __repr__ should return a proper string
601- self.assertEqual(str(manufacturer), '<Manufacturer(name="OpenLP Test")>',
602- 'Manufacturer.__repr__() should have returned a proper representation string')
603-
604- def test_model_repr(self):
605- """
606- Test Model.__repr__() text
607- """
608- # GIVEN: Test object
609- model = Model()
610-
611- # WHEN: Name is set
612- model.name = 'OpenLP Test'
613-
614- # THEN: __repr__ should return a proper string
615- self.assertEqual(str(model), '<Model(name='"OpenLP Test"')>',
616- 'Model.__repr__() should have returned a proper representation string')
617-
618- def test_source_repr(self):
619- """
620- Test Source.__repr__() text
621- """
622- # GIVEN: Test object
623- source = Source()
624-
625- # WHEN: Source() information is set
626- source.pjlink_name = 'Test object'
627- source.pjlink_code = '11'
628- source.text = 'Input text'
629-
630- # THEN: __repr__ should return a proper string
631- self.assertEqual(str(source), '<Source(pjlink_name="Test object", pjlink_code="11", text="Input text")>',
632- 'Source.__repr__() should have returned a proper representation string')
633-
634- def test_projector_repr(self):
635- """
636- Test Projector.__repr__() text
637- """
638- # GIVEN: Test object
639- projector = Projector()
640-
641- # WHEN: projector() is populated
642- # NOTE: projector.[pin, other, sources, sw_version, serial_no, sw_version, model_lamp, model_filter]
643- # should all return None.
644- # projector.source_list should return an empty list
645- projector.id = 0
646- projector.ip = '127.0.0.1'
647- projector.port = PJLINK_PORT
648- projector.name = 'Test One'
649- projector.location = 'Somewhere over the rainbow'
650- projector.notes = 'Not again'
651- projector.pjlink_name = 'TEST'
652- projector.manufacturer = 'IN YOUR DREAMS'
653- projector.model = 'OpenLP'
654-
655- # THEN: __repr__ should return a proper string
656- self.assertEqual(str(projector),
657- '< Projector(id="0", ip="127.0.0.1", port="4352", mac_adx="None", pin="None", '
658- 'name="Test One", location="Somewhere over the rainbow", notes="Not again", '
659- 'pjlink_name="TEST", manufacturer="IN YOUR DREAMS", model="OpenLP", serial_no="None", '
660- 'other="None", sources="None", source_list="[]", model_filter="None", model_lamp="None", '
661- 'sw_version="None") >',
662- 'Projector.__repr__() should have returned a proper representation string')
663-
664- def test_projectorsource_repr(self):
665- """
666- Test ProjectorSource.__repr__() text
667- """
668- # GIVEN: test setup
669- projector1 = Projector(**TEST1_DATA)
670- self.projector.add_projector(projector1)
671- item = self.projector.get_projector_by_id(projector1.id)
672- item_id = item.id
673-
674- # WHEN: A source entry is saved for item
675- source = ProjectorSource(projector_id=item_id, code='11', text='First RGB source')
676- self.projector.add_source(source)
677-
678- # THEN: __repr__ should return a proper string
679- self.assertEqual(str(source),
680- '<ProjectorSource(id="1", code="11", text="First RGB source", projector_id="1")>',
681- 'ProjectorSource.__repr__)_ should have returned a proper representation string')
682-
683- def test_get_projector_by_id_none(self):
684- """
685- Test get_projector_by_id() returns None if no db entry
686- """
687- # GIVEN: Test object and data
688- projector = self.projector
689-
690- # WHEN: DB search for entry not saved
691- results = projector.get_projector_by_id(dbid=123134556409824506)
692-
693- # THEN: Verify return was None
694- self.assertEqual(results, None, 'Returned results should have equaled None')
695-
696- def test_get_projector_all_none(self):
697- """
698- Test get_projector_all() with no projectors in db
699- """
700- # GIVEN: Test object with no data
701- projector = self.projector
702-
703- # WHEN: We retrieve the database entries
704- results = projector.get_projector_all()
705-
706- # THEN: Verify results is None
707- self.assertEqual(results, [], 'Returned results should have returned an empty list')
708-
709- def test_get_projector_all_one(self):
710- """
711- Test get_projector_all() with one entry in db
712- """
713- # GIVEN: One entry in database
714- projector = Projector(**TEST1_DATA)
715- self.projector.add_projector(projector)
716-
717- # WHEN: We retrieve the database entries
718- results = self.projector.get_projector_all()
719-
720- # THEN: We should have a list with one entry
721- self.assertEqual(len(results), 1, 'Returned results should have returned a list with one entry')
722- self.assertTrue((projector in results), 'Result should have been equal to TEST1_DATA')
723-
724- def test_get_projector_all_many(self):
725- """
726- Test get_projector_all() with multiple entries in db
727- """
728- # GIVEN: multiple entries in database
729- projector_list = []
730- projector_list.append(Projector(**TEST1_DATA))
731- projector_list.append(Projector(**TEST2_DATA))
732- projector_list.append(Projector(**TEST3_DATA))
733- for projector in projector_list:
734- self.projector.add_projector(projector)
735-
736- # WHEN: We retrieve the database entries
737- results = self.projector.get_projector_all()
738-
739- # THEN: We should have a list with three entries
740- self.assertEqual(len(results), len(projector_list),
741- 'Returned results should have returned a list with three entries')
742- for projector in results:
743- self.assertTrue((projector in projector_list),
744- 'Projector DB entry should have been in expected list')
745-
746- def test_get_projector_by_name_fail(self):
747- """
748- Test get_projector_by_name() fail
749- """
750- # GIVEN: Test entry in database
751- self.projector.add_projector(Projector(**TEST1_DATA))
752-
753- # WHEN: We attempt to get a projector that's not in database
754- results = self.projector.get_projector_by_name(name=TEST2_DATA['name'])
755-
756- # THEN: We should have None
757- self.assertEqual(results, None, 'projector.get_projector_by_name() should have returned None')
758-
759- def test_add_projector_fail(self):
760- """
761- Test add_projector() fail
762- """
763- # GIVEN: Test entry in the database
764- self.projector.add_projector(Projector(**TEST1_DATA))
765-
766- # WHEN: Attempt to add same projector entry
767- results = self.projector.add_projector(Projector(**TEST1_DATA))
768-
769- # THEN: We should have failed to add new entry
770- self.assertFalse(results, 'add_projector() should have failed')
771-
772- def test_update_projector_default_fail(self):
773- """
774- Test update_projector() with no options fails
775- """
776- # GIVEN: projector instance
777- projector = self.projector
778-
779- # WHEN: attempt to update a projector entry with no options
780- results = projector.update_projector()
781-
782- # THEN: We should have failed
783- self.assertFalse(results, 'update_projector(projector=None) should have returned False')
784-
785- def test_update_projector_not_in_db_fail(self):
786- """
787- Test update_projector() when entry not in database
788- """
789- # GIVEN: Projector entry in database
790- self.projector.add_projector(Projector(**TEST1_DATA))
791- projector = Projector(**TEST2_DATA)
792-
793- # WHEN: Attempt to update data with a different ID
794- results = self.projector.update_projector(projector)
795-
796- # THEN: Results should be False
797- self.assertFalse(results, 'update_projector(projector=projector) should have returned False')
798-
799- def test_delete_projector_fail(self):
800- """
801- Test delete_projector(projector) fails to delete record
802- """
803- # GIVEN: Test entry in db
804- self.projector.add_projector(Projector(**TEST1_DATA))
805-
806- # wHEN: Attempting to delete an entry not in the databae
807- results = self.projector.delete_projector(Projector(**TEST2_DATA))
808-
809- # THEN: Results should be False
810- self.assertFalse(results, 'delete_projector() should have returned False')
811
812=== removed file 'tests/functional/openlp_core/lib/test_projector_pjlink_base.py'
813--- tests/functional/openlp_core/lib/test_projector_pjlink_base.py 2017-09-22 12:03:28 +0000
814+++ tests/functional/openlp_core/lib/test_projector_pjlink_base.py 1970-01-01 00:00:00 +0000
815@@ -1,209 +0,0 @@
816-# -*- coding: utf-8 -*-
817-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
818-
819-###############################################################################
820-# OpenLP - Open Source Lyrics Projection #
821-# --------------------------------------------------------------------------- #
822-# Copyright (c) 2008-2015 OpenLP Developers #
823-# --------------------------------------------------------------------------- #
824-# This program is free software; you can redistribute it and/or modify it #
825-# under the terms of the GNU General Public License as published by the Free #
826-# Software Foundation; version 2 of the License. #
827-# #
828-# This program is distributed in the hope that it will be useful, but WITHOUT #
829-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
830-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
831-# more details. #
832-# #
833-# You should have received a copy of the GNU General Public License along #
834-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
835-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
836-###############################################################################
837-"""
838-Package to test the openlp.core.lib.projector.pjlink base package.
839-"""
840-from unittest import TestCase
841-from unittest.mock import call, patch, MagicMock
842-
843-from openlp.core.lib.projector.db import Projector
844-from openlp.core.lib.projector.pjlink import PJLink
845-from openlp.core.lib.projector.constants import E_PARAMETER, ERROR_STRING, S_ON, S_CONNECTED
846-
847-from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE, TEST_HASH, TEST1_DATA
848-
849-pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True)
850-
851-
852-class TestPJLinkBase(TestCase):
853- """
854- Tests for the PJLink module
855- """
856- @patch.object(pjlink_test, 'readyRead')
857- @patch.object(pjlink_test, 'send_command')
858- @patch.object(pjlink_test, 'waitForReadyRead')
859- @patch('openlp.core.common.qmd5_hash')
860- def test_authenticated_connection_call(self,
861- mock_qmd5_hash,
862- mock_waitForReadyRead,
863- mock_send_command,
864- mock_readyRead):
865- """
866- Ticket 92187: Fix for projector connect with PJLink authentication exception.
867- """
868- # GIVEN: Test object
869- pjlink = pjlink_test
870-
871- # WHEN: Calling check_login with authentication request:
872- pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
873-
874- # THEN: Should have called qmd5_hash
875- self.assertTrue(mock_qmd5_hash.called_with(TEST_SALT,
876- "Connection request should have been called with TEST_SALT"))
877- self.assertTrue(mock_qmd5_hash.called_with(TEST_PIN,
878- "Connection request should have been called with TEST_PIN"))
879-
880- @patch.object(pjlink_test, 'change_status')
881- def test_status_change(self, mock_change_status):
882- """
883- Test process_command call with ERR2 (Parameter) status
884- """
885- # GIVEN: Test object
886- pjlink = pjlink_test
887-
888- # WHEN: process_command is called with "ERR2" status from projector
889- pjlink.process_command('POWR', 'ERR2')
890-
891- # THEN: change_status should have called change_status with E_UNDEFINED
892- # as first parameter
893- mock_change_status.called_with(E_PARAMETER,
894- 'change_status should have been called with "{}"'.format(
895- ERROR_STRING[E_PARAMETER]))
896-
897- @patch.object(pjlink_test, 'send_command')
898- @patch.object(pjlink_test, 'waitForReadyRead')
899- @patch.object(pjlink_test, 'projectorAuthentication')
900- @patch.object(pjlink_test, 'timer')
901- @patch.object(pjlink_test, 'socket_timer')
902- def test_bug_1593882_no_pin_authenticated_connection(self,
903- mock_socket_timer,
904- mock_timer,
905- mock_authentication,
906- mock_ready_read,
907- mock_send_command):
908- """
909- Test bug 1593882 no pin and authenticated request exception
910- """
911- # GIVEN: Test object and mocks
912- pjlink = pjlink_test
913- pjlink.pin = None
914- mock_ready_read.return_value = True
915-
916- # WHEN: call with authentication request and pin not set
917- pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
918-
919- # THEN: 'No Authentication' signal should have been sent
920- mock_authentication.emit.assert_called_with(pjlink.ip)
921-
922- @patch.object(pjlink_test, 'waitForReadyRead')
923- @patch.object(pjlink_test, 'state')
924- @patch.object(pjlink_test, '_send_command')
925- @patch.object(pjlink_test, 'timer')
926- @patch.object(pjlink_test, 'socket_timer')
927- def test_bug_1593883_pjlink_authentication(self,
928- mock_socket_timer,
929- mock_timer,
930- mock_send_command,
931- mock_state,
932- mock_waitForReadyRead):
933- """
934- Test bugfix 1593883 pjlink authentication
935- """
936- # GIVEN: Test object and data
937- pjlink = pjlink_test
938- pjlink.pin = TEST_PIN
939- mock_state.return_value = pjlink.ConnectedState
940- mock_waitForReadyRead.return_value = True
941-
942- # WHEN: Athenticated connection is called
943- pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
944-
945- # THEN: send_command should have the proper authentication
946- self.assertEqual("{test}".format(test=mock_send_command.call_args),
947- "call(data='{hash}%1CLSS ?\\r')".format(hash=TEST_HASH))
948-
949- @patch.object(pjlink_test, 'disconnect_from_host')
950- def test_socket_abort(self, mock_disconnect):
951- """
952- Test PJLink.socket_abort calls disconnect_from_host
953- """
954- # GIVEN: Test object
955- pjlink = pjlink_test
956-
957- # WHEN: Calling socket_abort
958- pjlink.socket_abort()
959-
960- # THEN: disconnect_from_host should be called
961- self.assertTrue(mock_disconnect.called, 'Should have called disconnect_from_host')
962-
963- def test_poll_loop_not_connected(self):
964- """
965- Test PJLink.poll_loop not connected return
966- """
967- # GIVEN: Test object and mocks
968- pjlink = pjlink_test
969- pjlink.state = MagicMock()
970- pjlink.timer = MagicMock()
971- pjlink.state.return_value = False
972- pjlink.ConnectedState = True
973-
974- # WHEN: PJLink.poll_loop called
975- pjlink.poll_loop()
976-
977- # THEN: poll_loop should exit without calling any other method
978- self.assertFalse(pjlink.timer.called, 'Should have returned without calling any other method')
979-
980- @patch.object(pjlink_test, 'send_command')
981- def test_poll_loop_start(self, mock_send_command):
982- """
983- Test PJLink.poll_loop makes correct calls
984- """
985- # GIVEN: test object and test data
986- pjlink = pjlink_test
987- pjlink.state = MagicMock()
988- pjlink.timer = MagicMock()
989- pjlink.timer.interval = MagicMock()
990- pjlink.timer.setInterval = MagicMock()
991- pjlink.timer.start = MagicMock()
992- pjlink.poll_time = 20
993- pjlink.power = S_ON
994- pjlink.source_available = None
995- pjlink.other_info = None
996- pjlink.manufacturer = None
997- pjlink.model = None
998- pjlink.pjlink_name = None
999- pjlink.ConnectedState = S_CONNECTED
1000- pjlink.timer.interval.return_value = 10
1001- pjlink.state.return_value = S_CONNECTED
1002- call_list = [
1003- call('POWR', queue=True),
1004- call('ERST', queue=True),
1005- call('LAMP', queue=True),
1006- call('AVMT', queue=True),
1007- call('INPT', queue=True),
1008- call('INST', queue=True),
1009- call('INFO', queue=True),
1010- call('INF1', queue=True),
1011- call('INF2', queue=True),
1012- call('NAME', queue=True),
1013- ]
1014-
1015- # WHEN: PJLink.poll_loop is called
1016- pjlink.poll_loop()
1017-
1018- # THEN: proper calls were made to retrieve projector data
1019- # First, call to update the timer with the next interval
1020- self.assertTrue(pjlink.timer.setInterval.called, 'Should have updated the timer')
1021- # Next, should have called the timer to start
1022- self.assertTrue(pjlink.timer.start.called, 'Should have started the timer')
1023- # Finally, should have called send_command with a list of projetctor status checks
1024- mock_send_command.assert_has_calls(call_list, 'Should have queued projector queries')
1025
1026=== removed file 'tests/functional/openlp_core/lib/test_projector_pjlink_cmd_routing.py'
1027--- tests/functional/openlp_core/lib/test_projector_pjlink_cmd_routing.py 2017-09-22 12:03:28 +0000
1028+++ tests/functional/openlp_core/lib/test_projector_pjlink_cmd_routing.py 1970-01-01 00:00:00 +0000
1029@@ -1,224 +0,0 @@
1030-# -*- coding: utf-8 -*-
1031-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
1032-
1033-###############################################################################
1034-# OpenLP - Open Source Lyrics Projection #
1035-# --------------------------------------------------------------------------- #
1036-# Copyright (c) 2008-2015 OpenLP Developers #
1037-# --------------------------------------------------------------------------- #
1038-# This program is free software; you can redistribute it and/or modify it #
1039-# under the terms of the GNU General Public License as published by the Free #
1040-# Software Foundation; version 2 of the License. #
1041-# #
1042-# This program is distributed in the hope that it will be useful, but WITHOUT #
1043-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
1044-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
1045-# more details. #
1046-# #
1047-# You should have received a copy of the GNU General Public License along #
1048-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
1049-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
1050-###############################################################################
1051-"""
1052-Package to test the openlp.core.lib.projector.pjlink class command routing.
1053-"""
1054-
1055-from unittest import TestCase
1056-from unittest.mock import patch, MagicMock
1057-
1058-import openlp.core.lib.projector.pjlink
1059-from openlp.core.lib.projector.db import Projector
1060-from openlp.core.lib.projector.pjlink import PJLink
1061-from openlp.core.lib.projector.constants import PJLINK_ERRORS, \
1062- E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED
1063-
1064-'''
1065-from openlp.core.lib.projector.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
1066- PJLINK_POWR_STATUS, PJLINK_VALID_CMD, E_WARN, E_ERROR, S_OFF, S_STANDBY, S_ON
1067-'''
1068-from tests.resources.projector.data import TEST_PIN, TEST1_DATA
1069-
1070-pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
1071-pjlink_test.ip = '127.0.0.1'
1072-
1073-
1074-class TestPJLinkRouting(TestCase):
1075- """
1076- Tests for the PJLink module command routing
1077- """
1078- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1079- def test_process_command_call_clss(self, mock_log):
1080- """
1081- Test process_command calls proper function
1082- """
1083- # GIVEN: Test object
1084- pjlink = pjlink_test
1085- log_text = '(127.0.0.1) Calling function for CLSS'
1086- mock_log.reset_mock()
1087- mock_process_clss = MagicMock()
1088- pjlink.pjlink_functions['CLSS'] = mock_process_clss
1089-
1090- # WHEN: process_command is called with valid function and data
1091- pjlink.process_command(cmd='CLSS', data='1')
1092-
1093- # THEN: Process method should have been called properly
1094- mock_log.debug.assert_called_with(log_text)
1095- mock_process_clss.assert_called_with('1')
1096-
1097- @patch.object(pjlink_test, 'change_status')
1098- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1099- def test_process_command_err1(self, mock_log, mock_change_status):
1100- """
1101- Test ERR1 - Undefined projector function
1102- """
1103- # GIVEN: Test object
1104- pjlink = pjlink_test
1105- log_text = '(127.0.0.1) Projector returned error "ERR1"'
1106- mock_change_status.reset_mock()
1107- mock_log.reset_mock()
1108-
1109- # WHEN: process_command called with ERR1
1110- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED])
1111-
1112- # THEN: Error should be logged and status_change should be called
1113- mock_change_status.assert_called_once_with(E_UNDEFINED, 'Undefined Command: "CLSS"')
1114- mock_log.error.assert_called_with(log_text)
1115-
1116- @patch.object(pjlink_test, 'change_status')
1117- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1118- def test_process_command_err2(self, mock_log, mock_change_status):
1119- """
1120- Test ERR2 - Parameter Error
1121- """
1122- # GIVEN: Test object
1123- pjlink = pjlink_test
1124- log_text = '(127.0.0.1) Projector returned error "ERR2"'
1125- mock_change_status.reset_mock()
1126- mock_log.reset_mock()
1127-
1128- # WHEN: process_command called with ERR2
1129- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER])
1130-
1131- # THEN: Error should be logged and status_change should be called
1132- mock_change_status.assert_called_once_with(E_PARAMETER)
1133- mock_log.error.assert_called_with(log_text)
1134-
1135- @patch.object(pjlink_test, 'change_status')
1136- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1137- def test_process_command_err3(self, mock_log, mock_change_status):
1138- """
1139- Test ERR3 - Unavailable error
1140- """
1141- # GIVEN: Test object
1142- pjlink = pjlink_test
1143- log_text = '(127.0.0.1) Projector returned error "ERR3"'
1144- mock_change_status.reset_mock()
1145- mock_log.reset_mock()
1146-
1147- # WHEN: process_command called with ERR3
1148- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE])
1149-
1150- # THEN: Error should be logged and status_change should be called
1151- mock_change_status.assert_called_once_with(E_UNAVAILABLE)
1152- mock_log.error.assert_called_with(log_text)
1153-
1154- @patch.object(pjlink_test, 'change_status')
1155- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1156- def test_process_command_err4(self, mock_log, mock_change_status):
1157- """
1158- Test ERR3 - Unavailable error
1159- """
1160- # GIVEN: Test object
1161- pjlink = pjlink_test
1162- log_text = '(127.0.0.1) Projector returned error "ERR4"'
1163- mock_change_status.reset_mock()
1164- mock_log.reset_mock()
1165-
1166- # WHEN: process_command called with ERR3
1167- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])
1168-
1169- # THEN: Error should be logged and status_change should be called
1170- mock_change_status.assert_called_once_with(E_PROJECTOR)
1171- mock_log.error.assert_called_with(log_text)
1172-
1173- @patch.object(pjlink_test, 'projectorAuthentication')
1174- @patch.object(pjlink_test, 'change_status')
1175- @patch.object(pjlink_test, 'disconnect_from_host')
1176- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1177- def test_process_command_erra(self, mock_log, mock_disconnect, mock_change_status, mock_err_authenticate):
1178- """
1179- Test ERRA - Authentication Error
1180- """
1181- # GIVEN: Test object
1182- pjlink = pjlink_test
1183- log_text = '(127.0.0.1) Projector returned error "ERRA"'
1184- mock_change_status.reset_mock()
1185- mock_log.reset_mock()
1186-
1187- # WHEN: process_command called with ERRA
1188- pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_AUTHENTICATION])
1189-
1190- # THEN: Error should be logged and several methods should be called
1191- self.assertTrue(mock_disconnect.called, 'disconnect_from_host should have been called')
1192- mock_change_status.assert_called_once_with(E_AUTHENTICATION)
1193- mock_log.error.assert_called_with(log_text)
1194-
1195- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1196- def test_process_command_future(self, mock_log):
1197- """
1198- Test command valid but no method to process yet
1199- """
1200- # GIVEN: Test object
1201- pjlink = pjlink_test
1202- log_text = "(127.0.0.1) Unable to process command='CLSS' (Future option)"
1203- mock_log.reset_mock()
1204- # Remove a valid command so we can test valid command but not available yet
1205- pjlink.pjlink_functions.pop('CLSS')
1206-
1207- # WHEN: process_command called with an unknown command
1208- with patch.object(pjlink, 'pjlink_functions') as mock_functions:
1209- pjlink.process_command(cmd='CLSS', data='DONT CARE')
1210-
1211- # THEN: Error should be logged and no command called
1212- self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
1213- mock_log.warning.assert_called_once_with(log_text)
1214-
1215- @patch.object(pjlink_test, 'pjlink_functions')
1216- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1217- def test_process_command_invalid(self, mock_log, mock_functions):
1218- """
1219- Test not a valid command
1220- """
1221- # GIVEN: Test object
1222- pjlink = pjlink_test
1223- mock_functions.reset_mock()
1224- mock_log.reset_mock()
1225-
1226- # WHEN: process_command called with an unknown command
1227- pjlink.process_command(cmd='Unknown', data='Dont Care')
1228- log_text = "(127.0.0.1) Ignoring command='Unknown' (Invalid/Unknown)"
1229-
1230- # THEN: Error should be logged and no command called
1231- self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
1232- mock_log.error.assert_called_once_with(log_text)
1233-
1234- @patch.object(pjlink_test, 'pjlink_functions')
1235- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1236- def test_process_command_ok(self, mock_log, mock_functions):
1237- """
1238- Test command returned success
1239- """
1240- # GIVEN: Test object
1241- pjlink = pjlink_test
1242- mock_functions.reset_mock()
1243- mock_log.reset_mock()
1244-
1245- # WHEN: process_command called with an unknown command
1246- pjlink.process_command(cmd='CLSS', data='OK')
1247- log_text = '(127.0.0.1) Command "CLSS" returned OK'
1248-
1249- # THEN: Error should be logged and no command called
1250- self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
1251- self.assertEqual(mock_log.debug.call_count, 2, 'log.debug() should have been called twice')
1252- # Although we called it twice, only the last log entry is saved
1253- mock_log.debug.assert_called_with(log_text)
1254
1255=== removed file 'tests/functional/openlp_core/lib/test_projector_pjlink_commands.py'
1256--- tests/functional/openlp_core/lib/test_projector_pjlink_commands.py 2017-09-22 12:03:28 +0000
1257+++ tests/functional/openlp_core/lib/test_projector_pjlink_commands.py 1970-01-01 00:00:00 +0000
1258@@ -1,1149 +0,0 @@
1259-# -*- coding: utf-8 -*-
1260-# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
1261-
1262-###############################################################################
1263-# OpenLP - Open Source Lyrics Projection #
1264-# --------------------------------------------------------------------------- #
1265-# Copyright (c) 2008-2015 OpenLP Developers #
1266-# --------------------------------------------------------------------------- #
1267-# This program is free software; you can redistribute it and/or modify it #
1268-# under the terms of the GNU General Public License as published by the Free #
1269-# Software Foundation; version 2 of the License. #
1270-# #
1271-# This program is distributed in the hope that it will be useful, but WITHOUT #
1272-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
1273-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
1274-# more details. #
1275-# #
1276-# You should have received a copy of the GNU General Public License along #
1277-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
1278-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
1279-###############################################################################
1280-"""
1281-Package to test the openlp.core.lib.projector.pjlink commands package.
1282-"""
1283-from unittest import TestCase
1284-from unittest.mock import patch
1285-
1286-import openlp.core.lib.projector.pjlink
1287-from openlp.core.lib.projector.db import Projector
1288-from openlp.core.lib.projector.pjlink import PJLink
1289-from openlp.core.lib.projector.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
1290- PJLINK_POWR_STATUS, \
1291- E_ERROR, E_NOT_CONNECTED, E_SOCKET_ADDRESS_NOT_AVAILABLE, E_UNKNOWN_SOCKET_ERROR, E_WARN, \
1292- S_CONNECTED, S_OFF, S_ON, S_NOT_CONNECTED, S_CONNECTING, S_STANDBY
1293-
1294-from tests.resources.projector.data import TEST_PIN, TEST1_DATA
1295-
1296-pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
1297-pjlink_test.ip = '127.0.0.1'
1298-
1299-# Create a list of ERST positional data so we don't have to redo the same buildup multiple times
1300-PJLINK_ERST_POSITIONS = []
1301-for pos in range(0, len(PJLINK_ERST_DATA)):
1302- if pos in PJLINK_ERST_DATA:
1303- PJLINK_ERST_POSITIONS.append(PJLINK_ERST_DATA[pos])
1304-
1305-
1306-class TestPJLinkCommands(TestCase):
1307- """
1308- Tests for the PJLink module
1309- """
1310- @patch.object(pjlink_test, 'changeStatus')
1311- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1312- def test_projector_change_status_connection_error(self, mock_log, mock_change_status):
1313- """
1314- Test change_status with connection error
1315- """
1316- # GIVEN: Test object
1317- pjlink = pjlink_test
1318- pjlink.projector_status = 0
1319- pjlink.status_connect = 0
1320- test_code = E_UNKNOWN_SOCKET_ERROR
1321- mock_change_status.reset_mock()
1322- mock_log.reset_mock()
1323-
1324- # WHEN: change_status called with unknown socket error
1325- pjlink.change_status(status=test_code, msg=None)
1326-
1327- # THEN: Proper settings should change and signals sent
1328- self.assertEqual(pjlink.projector_status, E_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')
1329- self.assertEqual(pjlink.status_connect, E_NOT_CONNECTED, 'Status connect should be NOT CONNECTED')
1330- mock_change_status.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR,
1331- 'An unidentified error occurred')
1332- self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
1333-
1334- @patch.object(pjlink_test, 'changeStatus')
1335- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1336- def test_projector_change_status_connection_status_connecting(self, mock_log, mock_change_status):
1337- """
1338- Test change_status with connection status
1339- """
1340- # GIVEN: Test object
1341- pjlink = pjlink_test
1342- pjlink.projector_status = 0
1343- pjlink.status_connect = 0
1344- test_code = S_CONNECTING
1345- mock_change_status.reset_mock()
1346- mock_log.reset_mock()
1347-
1348- # WHEN: change_status called with unknown socket error
1349- pjlink.change_status(status=test_code, msg=None)
1350-
1351- # THEN: Proper settings should change and signals sent
1352- self.assertEqual(pjlink.projector_status, S_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')
1353- self.assertEqual(pjlink.status_connect, S_CONNECTING, 'Status connect should be CONNECTING')
1354- mock_change_status.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, 'Connecting')
1355- self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
1356-
1357- @patch.object(pjlink_test, 'changeStatus')
1358- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1359- def test_projector_change_status_connection_status_connected(self, mock_log, mock_change_status):
1360- """
1361- Test change_status with connection status
1362- """
1363- # GIVEN: Test object
1364- pjlink = pjlink_test
1365- pjlink.projector_status = 0
1366- pjlink.status_connect = 0
1367- test_code = S_ON
1368- mock_change_status.reset_mock()
1369- mock_log.reset_mock()
1370-
1371- # WHEN: change_status called with unknown socket error
1372- pjlink.change_status(status=test_code, msg=None)
1373-
1374- # THEN: Proper settings should change and signals sent
1375- self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
1376- self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
1377- mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, 'Power is on')
1378- self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
1379-
1380- @patch.object(pjlink_test, 'changeStatus')
1381- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1382- def test_projector_change_status_connection_status_with_message(self, mock_log, mock_change_status):
1383- """
1384- Test change_status with connection status
1385- """
1386- # GIVEN: Test object
1387- pjlink = pjlink_test
1388- pjlink.projector_status = 0
1389- pjlink.status_connect = 0
1390- test_message = 'Different Status Message than default'
1391- test_code = S_ON
1392- mock_change_status.reset_mock()
1393- mock_log.reset_mock()
1394-
1395- # WHEN: change_status called with unknown socket error
1396- pjlink.change_status(status=test_code, msg=test_message)
1397-
1398- # THEN: Proper settings should change and signals sent
1399- self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
1400- self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
1401- mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, test_message)
1402- self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
1403-
1404- @patch.object(pjlink_test, 'send_command')
1405- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1406- def test_projector_get_av_mute_status(self, mock_log, mock_send_command):
1407- """
1408- Test sending command to retrieve shutter/audio state
1409- """
1410- # GIVEN: Test object
1411- pjlink = pjlink_test
1412- mock_log.reset_mock()
1413- mock_send_command.reset_mock()
1414- test_data = 'AVMT'
1415- test_log = '(127.0.0.1) Sending AVMT command'
1416-
1417- # WHEN: get_av_mute_status is called
1418- pjlink.get_av_mute_status()
1419-
1420- # THEN: log data and send_command should have been called
1421- mock_log.debug.assert_called_once_with(test_log)
1422- mock_send_command.assert_called_once_with(cmd=test_data)
1423-
1424- @patch.object(pjlink_test, 'send_command')
1425- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1426- def test_projector_get_available_inputs(self, mock_log, mock_send_command):
1427- """
1428- Test sending command to retrieve avaliable inputs
1429- """
1430- # GIVEN: Test object
1431- pjlink = pjlink_test
1432- mock_log.reset_mock()
1433- mock_send_command.reset_mock()
1434- test_data = 'INST'
1435- test_log = '(127.0.0.1) Sending INST command'
1436-
1437- # WHEN: get_available_inputs is called
1438- pjlink.get_available_inputs()
1439-
1440- # THEN: log data and send_command should have been called
1441- mock_log.debug.assert_called_once_with(test_log)
1442- mock_send_command.assert_called_once_with(cmd=test_data)
1443-
1444- @patch.object(pjlink_test, 'send_command')
1445- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1446- def test_projector_get_error_status(self, mock_log, mock_send_command):
1447- """
1448- Test sending command to retrieve projector error status
1449- """
1450- # GIVEN: Test object
1451- pjlink = pjlink_test
1452- mock_log.reset_mock()
1453- mock_send_command.reset_mock()
1454- test_data = 'ERST'
1455- test_log = '(127.0.0.1) Sending ERST command'
1456-
1457- # WHEN: get_error_status is called
1458- pjlink.get_error_status()
1459-
1460- # THEN: log data and send_command should have been called
1461- mock_log.debug.assert_called_once_with(test_log)
1462- mock_send_command.assert_called_once_with(cmd=test_data)
1463-
1464- @patch.object(pjlink_test, 'send_command')
1465- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1466- def test_projector_get_input_source(self, mock_log, mock_send_command):
1467- """
1468- Test sending command to retrieve current input
1469- """
1470- # GIVEN: Test object
1471- pjlink = pjlink_test
1472- mock_log.reset_mock()
1473- mock_send_command.reset_mock()
1474- test_data = 'INPT'
1475- test_log = '(127.0.0.1) Sending INPT command'
1476-
1477- # WHEN: get_input_source is called
1478- pjlink.get_input_source()
1479-
1480- # THEN: log data and send_command should have been called
1481- mock_log.debug.assert_called_once_with(test_log)
1482- mock_send_command.assert_called_once_with(cmd=test_data)
1483-
1484- @patch.object(pjlink_test, 'send_command')
1485- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1486- def test_projector_get_lamp_status(self, mock_log, mock_send_command):
1487- """
1488- Test sending command to retrieve lamp(s) status
1489- """
1490- # GIVEN: Test object
1491- pjlink = pjlink_test
1492- mock_log.reset_mock()
1493- mock_send_command.reset_mock()
1494- test_data = 'LAMP'
1495- test_log = '(127.0.0.1) Sending LAMP command'
1496-
1497- # WHEN: get_lamp_status is called
1498- pjlink.get_lamp_status()
1499-
1500- # THEN: log data and send_command should have been called
1501- mock_log.debug.assert_called_once_with(test_log)
1502- mock_send_command.assert_called_once_with(cmd=test_data)
1503-
1504- @patch.object(pjlink_test, 'send_command')
1505- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1506- def test_projector_get_manufacturer(self, mock_log, mock_send_command):
1507- """
1508- Test sending command to retrieve manufacturer name
1509- """
1510- # GIVEN: Test object
1511- pjlink = pjlink_test
1512- mock_log.reset_mock()
1513- mock_send_command.reset_mock()
1514- test_data = 'INF1'
1515- test_log = '(127.0.0.1) Sending INF1 command'
1516-
1517- # WHEN: get_manufacturer is called
1518- pjlink.get_manufacturer()
1519-
1520- # THEN: log data and send_command should have been called
1521- mock_log.debug.assert_called_once_with(test_log)
1522- mock_send_command.assert_called_once_with(cmd=test_data)
1523-
1524- @patch.object(pjlink_test, 'send_command')
1525- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1526- def test_projector_get_model(self, mock_log, mock_send_command):
1527- """
1528- Test sending command to get model information
1529- """
1530- # GIVEN: Test object
1531- pjlink = pjlink_test
1532- mock_log.reset_mock()
1533- mock_send_command.reset_mock()
1534- test_data = 'INF2'
1535- test_log = '(127.0.0.1) Sending INF2 command'
1536-
1537- # WHEN: get_model is called
1538- pjlink.get_model()
1539-
1540- # THEN: log data and send_command should have been called
1541- mock_log.debug.assert_called_once_with(test_log)
1542- mock_send_command.assert_called_once_with(cmd=test_data)
1543-
1544- @patch.object(pjlink_test, 'send_command')
1545- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1546- def test_projector_get_name(self, mock_log, mock_send_command):
1547- """
1548- Test sending command to get user-assigned name
1549- """
1550- # GIVEN: Test object
1551- pjlink = pjlink_test
1552- mock_log.reset_mock()
1553- mock_send_command.reset_mock()
1554- test_data = 'NAME'
1555- test_log = '(127.0.0.1) Sending NAME command'
1556-
1557- # WHEN: get_name is called
1558- pjlink.get_name()
1559-
1560- # THEN: log data and send_command should have been called
1561- mock_log.debug.assert_called_once_with(test_log)
1562- mock_send_command.assert_called_once_with(cmd=test_data)
1563-
1564- @patch.object(pjlink_test, 'send_command')
1565- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1566- def test_projector_get_other_info(self, mock_log, mock_send_command):
1567- """
1568- Test sending command to retrieve other information
1569- """
1570- # GIVEN: Test object
1571- pjlink = pjlink_test
1572- mock_log.reset_mock()
1573- mock_send_command.reset_mock()
1574- test_data = 'INFO'
1575- test_log = '(127.0.0.1) Sending INFO command'
1576-
1577- # WHEN: get_other_info is called
1578- pjlink.get_other_info()
1579-
1580- # THEN: log data and send_command should have been called
1581- mock_log.debug.assert_called_once_with(test_log)
1582- mock_send_command.assert_called_once_with(cmd=test_data)
1583-
1584- @patch.object(pjlink_test, 'send_command')
1585- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1586- def test_projector_get_power_status(self, mock_log, mock_send_command):
1587- """
1588- Test sending command to retrieve current power state
1589- """
1590- # GIVEN: Test object
1591- pjlink = pjlink_test
1592- mock_log.reset_mock()
1593- mock_send_command.reset_mock()
1594- test_data = 'POWR'
1595- test_log = '(127.0.0.1) Sending POWR command'
1596-
1597- # WHEN: get_power_status called
1598- pjlink.get_power_status()
1599-
1600- # THEN: log data and send_command should have been called
1601- mock_log.debug.assert_called_once_with(test_log)
1602- mock_send_command.assert_called_once_with(cmd=test_data)
1603-
1604- def test_projector_get_status_error(self):
1605- """
1606- Test to check returned information for error code
1607- """
1608- # GIVEN: Test object
1609- pjlink = pjlink_test
1610- test_string = 'E_SOCKET_ADDRESS_NOT_AVAILABLE'
1611- test_message = 'The address specified to socket.bind() does not belong to the host'
1612-
1613- # WHEN: get_status called
1614- string, message = pjlink._get_status(status=E_SOCKET_ADDRESS_NOT_AVAILABLE)
1615-
1616- # THEN: Proper strings should have been returned
1617- self.assertEqual(string, test_string, 'Code as string should have been returned')
1618- self.assertEqual(message, test_message, 'Description of code should have been returned')
1619-
1620- def test_projector_get_status_invalid(self):
1621- """
1622- Test to check returned information for error code
1623- """
1624- # GIVEN: Test object
1625- pjlink = pjlink_test
1626- test_string = 'Test string since get_status will only work with int'
1627- test_message = 'Invalid status code'
1628-
1629- # WHEN: get_status called
1630- string, message = pjlink._get_status(status=test_string)
1631-
1632- # THEN: Proper strings should have been returned
1633- self.assertEqual(string, -1, 'Should have returned -1 as a bad status check')
1634- self.assertEqual(message, test_message, 'Error message should have been returned')
1635-
1636- def test_projector_get_status_status(self):
1637- """
1638- Test to check returned information for status codes
1639- """
1640- # GIVEN: Test object
1641- pjlink = pjlink_test
1642- test_string = 'S_NOT_CONNECTED'
1643- test_message = 'Not connected'
1644-
1645- # WHEN: get_status called
1646- string, message = pjlink._get_status(status=S_NOT_CONNECTED)
1647-
1648- # THEN: Proper strings should have been returned
1649- self.assertEqual(string, test_string, 'Code as string should have been returned')
1650- self.assertEqual(message, test_message, 'Description of code should have been returned')
1651-
1652- def test_projector_get_status_unknown(self):
1653- """
1654- Test to check returned information for unknown code
1655- """
1656- # GIVEN: Test object
1657- pjlink = pjlink_test
1658- test_string = 999999
1659- test_message = 'Unknown status'
1660-
1661- # WHEN: get_status called
1662- string, message = pjlink._get_status(status=test_string)
1663-
1664- # THEN: Proper strings should have been returned
1665- self.assertEqual(string, test_string, 'Received code should have been returned')
1666- self.assertEqual(message, test_message, 'Unknown status string should have been returned')
1667-
1668- def test_projector_process_inf1(self):
1669- """
1670- Test saving INF1 data (manufacturer)
1671- """
1672- # GIVEN: Test object
1673- pjlink = pjlink_test
1674- pjlink.manufacturer = None
1675- test_data = 'TEst INformation MultiCase'
1676-
1677- # WHEN: process_inf called with test data
1678- pjlink.process_inf1(data=test_data)
1679-
1680- # THEN: Data should be saved
1681- self.assertEqual(pjlink.manufacturer, test_data, 'Test data should have been saved')
1682-
1683- def test_projector_process_inf2(self):
1684- """
1685- Test saving INF2 data (model)
1686- """
1687- # GIVEN: Test object
1688- pjlink = pjlink_test
1689- pjlink.model = None
1690- test_data = 'TEst moDEl MultiCase'
1691-
1692- # WHEN: process_inf called with test data
1693- pjlink.process_inf2(data=test_data)
1694-
1695- # THEN: Data should be saved
1696- self.assertEqual(pjlink.model, test_data, 'Test data should have been saved')
1697-
1698- def test_projector_process_info(self):
1699- """
1700- Test saving INFO data (other information)
1701- """
1702- # GIVEN: Test object
1703- pjlink = pjlink_test
1704- pjlink.other_info = None
1705- test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
1706-
1707- # WHEN: process_inf called with test data
1708- pjlink.process_info(data=test_data)
1709-
1710- # THEN: Data should be saved
1711- self.assertEqual(pjlink.other_info, test_data, 'Test data should have been saved')
1712-
1713- @patch.object(pjlink_test, 'projectorUpdateIcons')
1714- def test_projector_process_avmt_bad_data(self, mock_UpdateIcons):
1715- """
1716- Test avmt bad data fail
1717- """
1718- # GIVEN: Test object
1719- pjlink = pjlink_test
1720- pjlink.shutter = True
1721- pjlink.mute = True
1722-
1723- # WHEN: Called with an invalid setting
1724- pjlink.process_avmt('36')
1725-
1726- # THEN: Shutter should be closed and mute should be True
1727- self.assertTrue(pjlink.shutter, 'Shutter should changed')
1728- self.assertTrue(pjlink.mute, 'Audio should not have changed')
1729- self.assertFalse(mock_UpdateIcons.emit.called, 'Update icons should NOT have been called')
1730-
1731- @patch.object(pjlink_test, 'projectorUpdateIcons')
1732- def test_projector_process_avmt_closed_muted(self, mock_UpdateIcons):
1733- """
1734- Test avmt status shutter closed and mute off
1735- """
1736- # GIVEN: Test object
1737- pjlink = pjlink_test
1738- pjlink.shutter = False
1739- pjlink.mute = False
1740-
1741- # WHEN: Called with setting shutter to closed and mute on
1742- pjlink.process_avmt('31')
1743-
1744- # THEN: Shutter should be closed and mute should be True
1745- self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
1746- self.assertTrue(pjlink.mute, 'Audio should be muted')
1747- self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
1748-
1749- @patch.object(pjlink_test, 'projectorUpdateIcons')
1750- def test_projector_process_avmt_shutter_closed(self, mock_UpdateIcons):
1751- """
1752- Test avmt status shutter closed and audio unchanged
1753- """
1754- # GIVEN: Test object
1755- pjlink = pjlink_test
1756- pjlink.shutter = False
1757- pjlink.mute = True
1758-
1759- # WHEN: Called with setting shutter closed and mute off
1760- pjlink.process_avmt('11')
1761-
1762- # THEN: Shutter should be True and mute should be False
1763- self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
1764- self.assertTrue(pjlink.mute, 'Audio should not have changed')
1765- self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
1766-
1767- @patch.object(pjlink_test, 'projectorUpdateIcons')
1768- def test_projector_process_avmt_audio_muted(self, mock_UpdateIcons):
1769- """
1770- Test avmt status shutter unchanged and mute on
1771- """
1772- # GIVEN: Test object
1773- pjlink = pjlink_test
1774- pjlink.shutter = True
1775- pjlink.mute = False
1776-
1777- # WHEN: Called with setting shutter closed and mute on
1778- pjlink.process_avmt('21')
1779-
1780- # THEN: Shutter should be closed and mute should be True
1781- self.assertTrue(pjlink.shutter, 'Shutter should not have changed')
1782- self.assertTrue(pjlink.mute, 'Audio should be off')
1783- self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
1784-
1785- @patch.object(pjlink_test, 'projectorUpdateIcons')
1786- def test_projector_process_avmt_open_unmuted(self, mock_UpdateIcons):
1787- """
1788- Test avmt status shutter open and mute off
1789- """
1790- # GIVEN: Test object
1791- pjlink = pjlink_test
1792- pjlink.shutter = True
1793- pjlink.mute = True
1794-
1795- # WHEN: Called with setting shutter to closed and mute on
1796- pjlink.process_avmt('30')
1797-
1798- # THEN: Shutter should be closed and mute should be True
1799- self.assertFalse(pjlink.shutter, 'Shutter should have been set to open')
1800- self.assertFalse(pjlink.mute, 'Audio should be on')
1801- self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
1802-
1803- def test_projector_process_clss_one(self):
1804- """
1805- Test class 1 sent from projector
1806- """
1807- # GIVEN: Test object
1808- pjlink = pjlink_test
1809-
1810- # WHEN: Process class response
1811- pjlink.process_clss('1')
1812-
1813- # THEN: Projector class should be set to 1
1814- self.assertEqual(pjlink.pjlink_class, '1',
1815- 'Projector should have set class=1')
1816-
1817- def test_projector_process_clss_two(self):
1818- """
1819- Test class 2 sent from projector
1820- """
1821- # GIVEN: Test object
1822- pjlink = pjlink_test
1823-
1824- # WHEN: Process class response
1825- pjlink.process_clss('2')
1826-
1827- # THEN: Projector class should be set to 1
1828- self.assertEqual(pjlink.pjlink_class, '2',
1829- 'Projector should have set class=2')
1830-
1831- def test_projector_process_clss_nonstandard_reply_optoma(self):
1832- """
1833- Bugfix 1550891: CLSS request returns non-standard reply with Optoma projector
1834- """
1835- # GIVEN: Test object
1836- pjlink = pjlink_test
1837-
1838- # WHEN: Process non-standard reply
1839- pjlink.process_clss('Class 1')
1840-
1841- # THEN: Projector class should be set with proper value
1842- self.assertEqual(pjlink.pjlink_class, '1',
1843- 'Non-standard class reply should have set class=1')
1844-
1845- def test_projector_process_clss_nonstandard_reply_benq(self):
1846- """
1847- Bugfix 1550891: CLSS request returns non-standard reply with BenQ projector
1848- """
1849- # GIVEN: Test object
1850- pjlink = pjlink_test
1851-
1852- # WHEN: Process non-standard reply
1853- pjlink.process_clss('Version2')
1854-
1855- # THEN: Projector class should be set with proper value
1856- # NOTE: At this time BenQ is Class 1, but we're trying a different value to verify
1857- self.assertEqual(pjlink.pjlink_class, '2',
1858- 'Non-standard class reply should have set class=2')
1859-
1860- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1861- def test_projector_process_clss_invalid_nan(self, mock_log):
1862- """
1863- Test CLSS reply has no class number
1864- """
1865- # GIVEN: Test object
1866- pjlink = pjlink_test
1867-
1868- # WHEN: Process invalid reply
1869- pjlink.process_clss('Z')
1870- log_text = "(127.0.0.1) NAN clss version reply 'Z' - defaulting to class '1'"
1871-
1872- # THEN: Projector class should be set with default value
1873- self.assertEqual(pjlink.pjlink_class, '1',
1874- 'Non-standard class reply should have set class=1')
1875- mock_log.error.assert_called_once_with(log_text)
1876-
1877- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1878- def test_projector_process_clss_invalid_no_version(self, mock_log):
1879- """
1880- Test CLSS reply has no class number
1881- """
1882- # GIVEN: Test object
1883- pjlink = pjlink_test
1884-
1885- # WHEN: Process invalid reply
1886- pjlink.process_clss('Invalid')
1887- log_text = "(127.0.0.1) No numbers found in class version reply 'Invalid' - defaulting to class '1'"
1888-
1889- # THEN: Projector class should be set with default value
1890- self.assertEqual(pjlink.pjlink_class, '1',
1891- 'Non-standard class reply should have set class=1')
1892- mock_log.error.assert_called_once_with(log_text)
1893-
1894- def test_projector_process_erst_all_ok(self):
1895- """
1896- Test test_projector_process_erst_all_ok
1897- """
1898- # GIVEN: Test object
1899- pjlink = pjlink_test
1900- chk_test = PJLINK_ERST_STATUS['OK']
1901- chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
1902-
1903- # WHEN: process_erst with no errors
1904- pjlink.process_erst(chk_param)
1905-
1906- # THEN: PJLink instance errors should be None
1907- self.assertIsNone(pjlink.projector_errors, 'projector_errors should have been set to None')
1908-
1909- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1910- def test_projector_process_erst_data_invalid_length(self, mock_log):
1911- """
1912- Test test_projector_process_erst_data_invalid_length
1913- """
1914- # GIVEN: Test object
1915- pjlink = pjlink_test
1916- pjlink.projector_errors = None
1917- log_text = "127.0.0.1) Invalid error status response '11111111': length != 6"
1918-
1919- # WHEN: process_erst called with invalid data (too many values
1920- pjlink.process_erst('11111111')
1921-
1922- # THEN: pjlink.projector_errors should be empty and warning logged
1923- self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
1924- self.assertTrue(mock_log.warning.called, 'Warning should have been logged')
1925- mock_log.warning.assert_called_once_with(log_text)
1926-
1927- @patch.object(openlp.core.lib.projector.pjlink, 'log')
1928- def test_projector_process_erst_data_invalid_nan(self, mock_log):
1929- """
1930- Test test_projector_process_erst_data_invalid_nan
1931- """
1932- # GIVEN: Test object
1933- pjlink = pjlink_test
1934- pjlink.projector_errors = None
1935- log_text = "(127.0.0.1) Invalid error status response '1111Z1'"
1936-
1937- # WHEN: process_erst called with invalid data (too many values
1938- pjlink.process_erst('1111Z1')
1939-
1940- # THEN: pjlink.projector_errors should be empty and warning logged
1941- self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
1942- self.assertTrue(mock_log.warning.called, 'Warning should have been logged')
1943- mock_log.warning.assert_called_once_with(log_text)
1944-
1945- def test_projector_process_erst_all_warn(self):
1946- """
1947- Test test_projector_process_erst_all_warn
1948- """
1949- # GIVEN: Test object
1950- pjlink = pjlink_test
1951- chk_test = PJLINK_ERST_STATUS[E_WARN]
1952- chk_string = ERROR_STRING[E_WARN]
1953- chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
1954-
1955- # WHEN: process_erst with status set to WARN
1956- pjlink.process_erst(chk_param)
1957-
1958- # THEN: PJLink instance errors should match chk_value
1959- for chk in pjlink.projector_errors:
1960- self.assertEqual(pjlink.projector_errors[chk], chk_string,
1961- "projector_errors['{chk}'] should have been set to {err}".format(chk=chk,
1962- err=chk_string))
1963-
1964- def test_projector_process_erst_all_error(self):
1965- """
1966- Test test_projector_process_erst_all_error
1967- """
1968- # GIVEN: Test object
1969- pjlink = pjlink_test
1970- chk_test = PJLINK_ERST_STATUS[E_ERROR]
1971- chk_string = ERROR_STRING[E_ERROR]
1972- chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
1973-
1974- # WHEN: process_erst with status set to WARN
1975- pjlink.process_erst(chk_param)
1976-
1977- # THEN: PJLink instance errors should match chk_value
1978- for chk in pjlink.projector_errors:
1979- self.assertEqual(pjlink.projector_errors[chk], chk_string,
1980- "projector_errors['{chk}'] should have been set to {err}".format(chk=chk,
1981- err=chk_string))
1982-
1983- def test_projector_process_erst_warn_cover_only(self):
1984- """
1985- Test test_projector_process_erst_warn_cover_only
1986- """
1987- # GIVEN: Test object
1988- pjlink = pjlink_test
1989- chk_test = PJLINK_ERST_STATUS[E_WARN]
1990- chk_string = ERROR_STRING[E_WARN]
1991- pos = PJLINK_ERST_DATA['COVER']
1992- build_chk = []
1993- for check in range(0, len(PJLINK_ERST_POSITIONS)):
1994- if check == pos:
1995- build_chk.append(chk_test)
1996- else:
1997- build_chk.append(PJLINK_ERST_STATUS['OK'])
1998- chk_param = ''.join(build_chk)
1999-
2000- # WHEN: process_erst with cover only set to WARN and all others set to OK
2001- pjlink.process_erst(chk_param)
2002-
2003- # THEN: Only COVER should have an error
2004- self.assertEqual(len(pjlink.projector_errors), 1, 'projector_errors should only have 1 error')
2005- self.assertTrue(('Cover' in pjlink.projector_errors), 'projector_errors should have an error for "Cover"')
2006- self.assertEqual(pjlink.projector_errors['Cover'],
2007- chk_string,
2008- 'projector_errors["Cover"] should have error "{err}"'.format(err=chk_string))
2009-
2010- def test_projector_process_inpt(self):
2011- """
2012- Test input source status shows current input
2013- """
2014- # GIVEN: Test object
2015- pjlink = pjlink_test
2016- pjlink.source = '0'
2017-
2018- # WHEN: Called with input source
2019- pjlink.process_inpt('1')
2020-
2021- # THEN: Input selected should reflect current input
2022- self.assertEqual(pjlink.source, '1', 'Input source should be set to "1"')
2023-
2024- @patch.object(pjlink_test, 'projectorUpdateIcons')
2025- @patch.object(openlp.core.lib.projector.pjlink, 'log')
2026- def test_projector_process_inst(self, mock_log, mock_UpdateIcons):
2027- """
2028- Test saving video source available information
2029- """
2030- # GIVEN: Test object
2031- pjlink = pjlink_test
2032- pjlink.source_available = []
2033- test_data = '21 10 30 31 11 20'
2034- test_saved = ['10', '11', '20', '21', '30', '31']
2035- log_data = '(127.0.0.1) Setting projector sources_available to ' \
2036- '"[\'10\', \'11\', \'20\', \'21\', \'30\', \'31\']"'
2037- mock_UpdateIcons.reset_mock()
2038- mock_log.reset_mock()
2039-
2040- # WHEN: process_inst called with test data
2041- pjlink.process_inst(data=test_data)
2042-
2043- # THEN: Data should have been sorted and saved properly
2044- self.assertEqual(pjlink.source_available, test_saved, "Sources should have been sorted and saved")
2045- mock_log.debug.assert_called_once_with(log_data)
2046- self.assertTrue(mock_UpdateIcons.emit.called, 'Update Icons should have been called')
2047-
2048- @patch.object(openlp.core.lib.projector.pjlink, 'log')
2049- def test_projector_process_lamp_invalid(self, mock_log):
2050- """
2051- Test status multiple lamp on/off and hours
2052- """
2053- # GIVEN: Test object
2054- pjlink = pjlink_test
2055- pjlink.lamp = [{'Hours': 00000, 'On': True},
2056- {'Hours': 11111, 'On': False}]
2057- log_data = '(127.0.0.1) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"'
2058-
2059- # WHEN: Call process_command with invalid lamp data
2060- pjlink.process_lamp('11111 1 22222 0 333A3 1')
2061-
2062- # THEN: lamps should not have changed
2063- self.assertEqual(len(pjlink.lamp), 2,
2064- 'Projector should have kept 2 lamps specified')
2065- self.assertEqual(pjlink.lamp[0]['On'], True,
2066- 'Lamp 1 power status should have been set to TRUE')
2067- self.assertEqual(pjlink.lamp[0]['Hours'], 00000,
2068- 'Lamp 1 hours should have been left at 00000')
2069- self.assertEqual(pjlink.lamp[1]['On'], False,
2070- 'Lamp 2 power status should have been set to FALSE')
2071- self.assertEqual(pjlink.lamp[1]['Hours'], 11111,
2072- 'Lamp 2 hours should have been left at 11111')
2073- mock_log.warning.assert_called_once_with(log_data)
2074-
2075- def test_projector_process_lamp_multiple(self):
2076- """
2077- Test status multiple lamp on/off and hours
2078- """
2079- # GIVEN: Test object
2080- pjlink = pjlink_test
2081- pjlink.lamps = []
2082-
2083- # WHEN: Call process_command with lamp data
2084- pjlink.process_lamp('11111 1 22222 0 33333 1')
2085-
2086- # THEN: Lamp should have been set with proper lamp status
2087- self.assertEqual(len(pjlink.lamp), 3,
2088- 'Projector should have 3 lamps specified')
2089- self.assertEqual(pjlink.lamp[0]['On'], True,
2090- 'Lamp 1 power status should have been set to TRUE')
2091- self.assertEqual(pjlink.lamp[0]['Hours'], 11111,
2092- 'Lamp 1 hours should have been set to 11111')
2093- self.assertEqual(pjlink.lamp[1]['On'], False,
2094- 'Lamp 2 power status should have been set to FALSE')
2095- self.assertEqual(pjlink.lamp[1]['Hours'], 22222,
2096- 'Lamp 2 hours should have been set to 22222')
2097- self.assertEqual(pjlink.lamp[2]['On'], True,
2098- 'Lamp 3 power status should have been set to TRUE')
2099- self.assertEqual(pjlink.lamp[2]['Hours'], 33333,
2100- 'Lamp 3 hours should have been set to 33333')
2101-
2102- def test_projector_process_lamp_single(self):
2103- """
2104- Test status lamp on/off and hours
2105- """
2106- # GIVEN: Test object
2107- pjlink = pjlink_test
2108- pjlink.lamps = []
2109-
2110- # WHEN: Call process_command with lamp data
2111- pjlink.process_lamp('22222 1')
2112-
2113- # THEN: Lamp should have been set with status=ON and hours=22222
2114- self.assertEqual(pjlink.lamp[0]['On'], True,
2115- 'Lamp power status should have been set to TRUE')
2116- self.assertEqual(pjlink.lamp[0]['Hours'], 22222,
2117- 'Lamp hours should have been set to 22222')
2118-
2119- @patch.object(openlp.core.lib.projector.pjlink, 'log')
2120- def test_projector_process_name(self, mock_log):
2121- """
2122- Test saving NAME data from projector
2123- """
2124- # GIVEN: Test data
2125- pjlink = pjlink_test
2126- test_data = "Some Name the End-User Set IN Projector"
2127- test_log = '(127.0.0.1) Setting projector PJLink name to "Some Name the End-User Set IN Projector"'
2128- mock_log.reset_mock()
2129-
2130- # WHEN: process_name called with test data
2131- pjlink.process_name(data=test_data)
2132-
2133- # THEN: name should be set and logged
2134- self.assertEqual(pjlink.pjlink_name, test_data, 'Name test data should have been saved')
2135- mock_log.debug.assert_called_once_with(test_log)
2136-
2137- @patch.object(pjlink_test, 'projectorUpdateIcons')
2138- @patch.object(pjlink_test, 'send_command')
2139- @patch.object(pjlink_test, 'change_status')
2140- def test_projector_process_powr_on(self,
2141- mock_change_status,
2142- mock_send_command,
2143- mock_UpdateIcons):
2144- """
2145- Test status power to ON
2146- """
2147- # GIVEN: Test object and preset
2148- pjlink = pjlink_test
2149- pjlink.power = S_STANDBY
2150- test_data = PJLINK_POWR_STATUS[S_ON]
2151-
2152- # WHEN: Call process_command with turn power on command
2153- pjlink.process_command(cmd='POWR', data=test_data)
2154-
2155- # THEN: Power should be set to ON
2156- self.assertEqual(pjlink.power, S_ON, 'Power should have been set to ON')
2157- mock_send_command.assert_called_once_with('INST')
2158- mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])
2159- self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')
2160-
2161- @patch.object(pjlink_test, 'projectorUpdateIcons')
2162- @patch.object(pjlink_test, 'send_command')
2163- @patch.object(pjlink_test, 'change_status')
2164- def test_projector_process_powr_invalid(self,
2165- mock_change_status,
2166- mock_send_command,
2167- mock_UpdateIcons):
2168- """
2169- Test process_powr invalid call
2170- """
2171- # GIVEN: Test object and preset
2172- pjlink = pjlink_test
2173- pjlink.power = S_STANDBY
2174- test_data = '99'
2175-
2176- # WHEN: Call process_command with turn power on command
2177- pjlink.process_command(cmd='POWR', data=test_data)
2178-
2179- # THEN: Power should be set to ON
2180- self.assertEqual(pjlink.power, S_STANDBY, 'Power should not have changed')
2181- self.assertFalse(mock_change_status.called, 'Change status should not have been called')
2182- self.assertFalse(mock_send_command.called, 'send_command("INST") should not have been called')
2183- self.assertFalse(mock_UpdateIcons.emit.called, 'projectorUpdateIcons should not have been called')
2184-
2185- @patch.object(pjlink_test, 'projectorUpdateIcons')
2186- @patch.object(pjlink_test, 'send_command')
2187- @patch.object(pjlink_test, 'change_status')
2188- def test_projector_process_powr_off(self,
2189- mock_change_status,
2190- mock_send_command,
2191- mock_UpdateIcons):
2192- """
2193- Test status power to STANDBY
2194- """
2195- # GIVEN: Test object and preset
2196- pjlink = pjlink_test
2197- pjlink.power = S_ON
2198- test_data = PJLINK_POWR_STATUS[S_STANDBY]
2199-
2200- # WHEN: Call process_command with turn power on command
2201- pjlink.process_command(cmd='POWR', data=test_data)
2202-
2203- # THEN: Power should be set to STANDBY
2204- self.assertEqual(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY')
2205- self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')
2206- mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])
2207- self.assertFalse(mock_send_command.called, "send_command['INST'] should not have been called")
2208-
2209- def test_projector_process_rfil_save(self):
2210- """
2211- Test saving filter type
2212- """
2213- # GIVEN: Test object
2214- pjlink = pjlink_test
2215- pjlink.model_filter = None
2216- filter_model = 'Filter Type Test'
2217-
2218- # WHEN: Filter model is received
2219- pjlink.process_rfil(data=filter_model)
2220-
2221- # THEN: Filter model number should be saved
2222- self.assertEqual(pjlink.model_filter, filter_model, 'Filter type should have been saved')
2223-
2224- def test_projector_process_rfil_nosave(self):
2225- """
2226- Test saving filter type previously saved
2227- """
2228- # GIVEN: Test object
2229- pjlink = pjlink_test
2230- pjlink.model_filter = 'Old filter type'
2231- filter_model = 'Filter Type Test'
2232-
2233- # WHEN: Filter model is received
2234- pjlink.process_rfil(data=filter_model)
2235-
2236- # THEN: Filter model number should be saved
2237- self.assertNotEquals(pjlink.model_filter, filter_model, 'Filter type should NOT have been saved')
2238-
2239- def test_projector_process_rlmp_save(self):
2240- """
2241- Test saving lamp type
2242- """
2243- # GIVEN: Test object
2244- pjlink = pjlink_test
2245- pjlink.model_lamp = None
2246- lamp_model = 'Lamp Type Test'
2247-
2248- # WHEN: Filter model is received
2249- pjlink.process_rlmp(data=lamp_model)
2250-
2251- # THEN: Filter model number should be saved
2252- self.assertEqual(pjlink.model_lamp, lamp_model, 'Lamp type should have been saved')
2253-
2254- def test_projector_process_rlmp_nosave(self):
2255- """
2256- Test saving lamp type previously saved
2257- """
2258- # GIVEN: Test object
2259- pjlink = pjlink_test
2260- pjlink.model_lamp = 'Old lamp type'
2261- lamp_model = 'Filter Type Test'
2262-
2263- # WHEN: Filter model is received
2264- pjlink.process_rlmp(data=lamp_model)
2265-
2266- # THEN: Filter model number should be saved
2267- self.assertNotEquals(pjlink.model_lamp, lamp_model, 'Lamp type should NOT have been saved')
2268-
2269- def test_projector_process_snum_set(self):
2270- """
2271- Test saving serial number from projector
2272- """
2273- # GIVEN: Test object
2274- pjlink = pjlink_test
2275- pjlink.serial_no = None
2276- test_number = 'Test Serial Number'
2277-
2278- # WHEN: No serial number is set and we receive serial number command
2279- pjlink.process_snum(data=test_number)
2280-
2281- # THEN: Serial number should be set
2282- self.assertEqual(pjlink.serial_no, test_number,
2283- 'Projector serial number should have been set')
2284-
2285- def test_projector_process_snum_different(self):
2286- """
2287- Test projector serial number different than saved serial number
2288- """
2289- # GIVEN: Test object
2290- pjlink = pjlink_test
2291- pjlink.serial_no = 'Previous serial number'
2292- test_number = 'Test Serial Number'
2293-
2294- # WHEN: No serial number is set and we receive serial number command
2295- pjlink.process_snum(data=test_number)
2296-
2297- # THEN: Serial number should be set
2298- self.assertNotEquals(pjlink.serial_no, test_number,
2299- 'Projector serial number should NOT have been set')
2300-
2301- @patch.object(openlp.core.lib.projector.pjlink, 'log')
2302- def test_projector_process_sver(self, mock_log):
2303- """
2304- Test invalid software version information - too long
2305- """
2306- # GIVEN: Test object
2307- pjlink = pjlink_test
2308- pjlink.sw_version = None
2309- pjlink.sw_version_received = None
2310- test_data = 'Test 1 Subtest 1'
2311- test_log = "(127.0.0.1) Setting projector software version to 'Test 1 Subtest 1'"
2312- mock_log.reset_mock()
2313-
2314- # WHEN: process_sver called with invalid data
2315- pjlink.process_sver(data=test_data)
2316-
2317- # THEN: Version information should not change
2318- self.assertEqual(pjlink.sw_version, test_data, 'Software version should have been updated')
2319- self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')
2320- mock_log.debug.assert_called_once_with(test_log)
2321-
2322- @patch.object(openlp.core.lib.projector.pjlink, 'log')
2323- def test_projector_process_sver_changed(self, mock_log):
2324- """
2325- Test invalid software version information - Received different than saved
2326- """
2327- # GIVEN: Test object
2328- pjlink = pjlink_test
2329- test_data_new = 'Test 1 Subtest 2'
2330- test_data_old = 'Test 1 Subtest 1'
2331- pjlink.sw_version = test_data_old
2332- pjlink.sw_version_received = None
2333- test_log = '(127.0.0.1) Saving new serial number as sw_version_received'
2334- mock_log.reset_mock()
2335-
2336- # WHEN: process_sver called with invalid data
2337- pjlink.process_sver(data=test_data_new)
2338-
2339- # THEN: Version information should not change
2340- self.assertEqual(pjlink.sw_version, test_data_old, 'Software version should not have been updated')
2341- self.assertEqual(pjlink.sw_version_received, test_data_new,
2342- 'Received software version should have been changed')
2343- self.assertEqual(mock_log.warning.call_count, 4, 'log.warn should have been called 4 times')
2344- # There was 4 calls, but only the last one is checked with this method
2345- mock_log.warning.assert_called_with(test_log)
2346-
2347- @patch.object(openlp.core.lib.projector.pjlink, 'log')
2348- def test_projector_process_sver_invalid(self, mock_log):
2349- """
2350- Test invalid software version information - too long
2351- """
2352- # GIVEN: Test object
2353- pjlink = pjlink_test
2354- pjlink.sw_version = None
2355- pjlink.sw_version_received = None
2356- test_data = 'This is a test software version line that is too long based on PJLink version 2 specs'
2357- test_log = "Invalid software version - too long"
2358- mock_log.reset_mock()
2359-
2360- # WHEN: process_sver called with invalid data
2361- pjlink.process_sver(data=test_data)
2362-
2363- # THEN: Version information should not change
2364- self.assertIsNone(pjlink.sw_version, 'Software version should not have changed')
2365- self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')
2366- mock_log.warning.assert_called_once_with(test_log)
2367-
2368- def test_projector_reset_information(self):
2369- """
2370- Test reset_information() resets all information and stops timers
2371- """
2372- # GIVEN: Test object and test data
2373- pjlink = pjlink_test
2374- pjlink.power = S_ON
2375- pjlink.pjlink_name = 'OPENLPTEST'
2376- pjlink.manufacturer = 'PJLINK'
2377- pjlink.model = '1'
2378- pjlink.shutter = True
2379- pjlink.mute = True
2380- pjlink.lamp = True
2381- pjlink.fan = True
2382- pjlink.source_available = True
2383- pjlink.other_info = 'ANOTHER TEST'
2384- pjlink.send_queue = True
2385- pjlink.send_busy = True
2386-
2387- # WHEN: reset_information() is called
2388- with patch.object(pjlink, 'timer') as mock_timer:
2389- with patch.object(pjlink, 'socket_timer') as mock_socket_timer:
2390- pjlink.reset_information()
2391-
2392- # THEN: All information should be reset and timers stopped
2393- self.assertEqual(pjlink.power, S_OFF, 'Projector power should be OFF')
2394- self.assertIsNone(pjlink.pjlink_name, 'Projector pjlink_name should be None')
2395- self.assertIsNone(pjlink.manufacturer, 'Projector manufacturer should be None')
2396- self.assertIsNone(pjlink.model, 'Projector model should be None')
2397- self.assertIsNone(pjlink.shutter, 'Projector shutter should be None')
2398- self.assertIsNone(pjlink.mute, 'Projector shuttter should be None')
2399- self.assertIsNone(pjlink.lamp, 'Projector lamp should be None')
2400- self.assertIsNone(pjlink.fan, 'Projector fan should be None')
2401- self.assertIsNone(pjlink.source_available, 'Projector source_available should be None')
2402- self.assertIsNone(pjlink.source, 'Projector source should be None')
2403- self.assertIsNone(pjlink.other_info, 'Projector other_info should be None')
2404- self.assertEqual(pjlink.send_queue, [], 'Projector send_queue should be an empty list')
2405- self.assertFalse(pjlink.send_busy, 'Projector send_busy should be False')
2406- self.assertTrue(mock_timer.stop.called, 'Projector timer.stop() should have been called')
2407- self.assertTrue(mock_socket_timer.stop.called, 'Projector socket_timer.stop() should have been called')
2408
2409=== added directory 'tests/functional/openlp_core/projectors'
2410=== added file 'tests/functional/openlp_core/projectors/__init__.py'
2411--- tests/functional/openlp_core/projectors/__init__.py 1970-01-01 00:00:00 +0000
2412+++ tests/functional/openlp_core/projectors/__init__.py 2017-11-17 06:06:50 +0000
2413@@ -0,0 +1,24 @@
2414+# -*- coding: utf-8 -*-
2415+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
2416+
2417+###############################################################################
2418+# OpenLP - Open Source Lyrics Projection #
2419+# --------------------------------------------------------------------------- #
2420+# Copyright (c) 2008-2017 OpenLP Developers #
2421+# --------------------------------------------------------------------------- #
2422+# This program is free software; you can redistribute it and/or modify it #
2423+# under the terms of the GNU General Public License as published by the Free #
2424+# Software Foundation; version 2 of the License. #
2425+# #
2426+# This program is distributed in the hope that it will be useful, but WITHOUT #
2427+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
2428+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
2429+# more details. #
2430+# #
2431+# You should have received a copy of the GNU General Public License along #
2432+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
2433+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
2434+###############################################################################
2435+"""
2436+Module-level functions for the functional test suite
2437+"""
2438
2439=== added file 'tests/functional/openlp_core/projectors/test_projector_constants.py'
2440--- tests/functional/openlp_core/projectors/test_projector_constants.py 1970-01-01 00:00:00 +0000
2441+++ tests/functional/openlp_core/projectors/test_projector_constants.py 2017-11-17 06:06:50 +0000
2442@@ -0,0 +1,43 @@
2443+# -*- coding: utf-8 -*-
2444+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
2445+
2446+###############################################################################
2447+# OpenLP - Open Source Lyrics Projection #
2448+# --------------------------------------------------------------------------- #
2449+# Copyright (c) 2008-2015 OpenLP Developers #
2450+# --------------------------------------------------------------------------- #
2451+# This program is free software; you can redistribute it and/or modify it #
2452+# under the terms of the GNU General Public License as published by the Free #
2453+# Software Foundation; version 2 of the License. #
2454+# #
2455+# This program is distributed in the hope that it will be useful, but WITHOUT #
2456+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
2457+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
2458+# more details. #
2459+# #
2460+# You should have received a copy of the GNU General Public License along #
2461+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
2462+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
2463+###############################################################################
2464+"""
2465+Package to test the openlp.core.projectors.constants module.
2466+"""
2467+from unittest import TestCase
2468+
2469+
2470+class TestProjectorConstants(TestCase):
2471+ """
2472+ Test specific functions in the projector constants module.
2473+ """
2474+ def test_build_pjlink_video_label(self):
2475+ """
2476+ Test building PJLINK_DEFAULT_CODES dictionary
2477+ """
2478+ # GIVEN: Test data
2479+ from tests.resources.projector.data import TEST_VIDEO_CODES
2480+
2481+ # WHEN: Import projector PJLINK_DEFAULT_CODES
2482+ from openlp.core.projectors.constants import PJLINK_DEFAULT_CODES
2483+
2484+ # THEN: Verify dictionary was build correctly
2485+ self.assertEqual(PJLINK_DEFAULT_CODES, TEST_VIDEO_CODES, 'PJLink video strings should match')
2486
2487=== added file 'tests/functional/openlp_core/projectors/test_projector_db.py'
2488--- tests/functional/openlp_core/projectors/test_projector_db.py 1970-01-01 00:00:00 +0000
2489+++ tests/functional/openlp_core/projectors/test_projector_db.py 2017-11-17 06:06:50 +0000
2490@@ -0,0 +1,462 @@
2491+# -*- coding: utf-8 -*-
2492+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
2493+
2494+###############################################################################
2495+# OpenLP - Open Source Lyrics Projection #
2496+# --------------------------------------------------------------------------- #
2497+# Copyright (c) 2008-2017 OpenLP Developers #
2498+# --------------------------------------------------------------------------- #
2499+# This program is free software; you can redistribute it and/or modify it #
2500+# under the terms of the GNU General Public License as published by the Free #
2501+# Software Foundation; version 2 of the License. #
2502+# #
2503+# This program is distributed in the hope that it will be useful, but WITHOUT #
2504+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
2505+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
2506+# more details. #
2507+# #
2508+# You should have received a copy of the GNU General Public License along #
2509+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
2510+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
2511+###############################################################################
2512+"""
2513+Package to test the openlp.core.projectors.db module.
2514+record functions.
2515+
2516+PREREQUISITE: add_record() and get_all() functions validated.
2517+"""
2518+import os
2519+import shutil
2520+from tempfile import mkdtemp
2521+
2522+from unittest import TestCase
2523+from unittest.mock import patch
2524+
2525+from openlp.core.lib.db import upgrade_db
2526+from openlp.core.projectors import upgrade
2527+from openlp.core.projectors.constants import PJLINK_PORT
2528+from openlp.core.projectors.db import Manufacturer, Model, Projector, ProjectorDB, ProjectorSource, Source
2529+
2530+from tests.resources.projector.data import TEST_DB_PJLINK1, TEST_DB, TEST1_DATA, TEST2_DATA, TEST3_DATA
2531+from tests.utils.constants import TEST_RESOURCES_PATH
2532+
2533+
2534+def compare_data(one, two):
2535+ """
2536+ Verify two Projector() instances contain the same data
2537+ """
2538+ return one is not None and \
2539+ two is not None and \
2540+ one.ip == two.ip and \
2541+ one.port == two.port and \
2542+ one.name == two.name and \
2543+ one.location == two.location and \
2544+ one.notes == two.notes and \
2545+ one.sw_version == two.sw_version and \
2546+ one.serial_no == two.serial_no and \
2547+ one.model_filter == two.model_filter and \
2548+ one.model_lamp == two.model_lamp
2549+
2550+
2551+def compare_source(one, two):
2552+ """
2553+ Verify two ProjectorSource instances contain the same data
2554+ """
2555+ return one is not None and \
2556+ two is not None and \
2557+ one.projector_id == two.projector_id and \
2558+ one.code == two.code and \
2559+ one.text == two.text
2560+
2561+
2562+def add_records(projector_db, test):
2563+ """
2564+ Add record if not in database
2565+ """
2566+ record_list = projector_db.get_projector_all()
2567+ if len(record_list) < 1:
2568+ added = False
2569+ for record in test:
2570+ added = projector_db.add_projector(record) or added
2571+ return added
2572+
2573+ for new_record in test:
2574+ added = None
2575+ for record in record_list:
2576+ if compare_data(record, new_record):
2577+ break
2578+ added = projector_db.add_projector(new_record)
2579+ return added
2580+
2581+
2582+class TestProjectorDBUpdate(TestCase):
2583+ """
2584+ Test case for upgrading Projector DB.
2585+ NOTE: Separate class so I don't have to look for upgrade tests.
2586+ """
2587+ def setUp(self):
2588+ """
2589+ Setup for tests
2590+ """
2591+ self.tmp_folder = mkdtemp(prefix='openlp_')
2592+
2593+ def tearDown(self):
2594+ """
2595+ Clean up after tests
2596+ """
2597+ # Ignore errors since windows can have problems with locked files
2598+ shutil.rmtree(self.tmp_folder, ignore_errors=True)
2599+
2600+ def test_upgrade_old_projector_db(self):
2601+ """
2602+ Test that we can upgrade an old song db to the current schema
2603+ """
2604+ # GIVEN: An old prjector db
2605+ old_db = os.path.join(TEST_RESOURCES_PATH, "projector", TEST_DB_PJLINK1)
2606+ tmp_db = os.path.join(self.tmp_folder, TEST_DB)
2607+ shutil.copyfile(old_db, tmp_db)
2608+ db_url = 'sqlite:///{db}'.format(db=tmp_db)
2609+
2610+ # WHEN: upgrading the db
2611+ updated_to_version, latest_version = upgrade_db(db_url, upgrade)
2612+
2613+ # THEN: the song db should have been upgraded to the latest version
2614+ self.assertEqual(updated_to_version, latest_version,
2615+ 'The projector DB should have been upgrade to the latest version')
2616+
2617+
2618+class TestProjectorDB(TestCase):
2619+ """
2620+ Test case for ProjectorDB
2621+ """
2622+ @patch('openlp.core.projectors.db.init_url')
2623+ def setUp(self, mocked_init_url):
2624+ """
2625+ Set up anything necessary for all tests
2626+ """
2627+ self.tmp_folder = mkdtemp(prefix='openlp_')
2628+ tmpdb_url = 'sqlite:///{db}'.format(db=os.path.join(self.tmp_folder, TEST_DB))
2629+ mocked_init_url.return_value = tmpdb_url
2630+ self.projector = ProjectorDB()
2631+
2632+ def tearDown(self):
2633+ """
2634+ Clean up
2635+ """
2636+ self.projector.session.close()
2637+ self.projector = None
2638+ # Ignore errors since windows can have problems with locked files
2639+ shutil.rmtree(self.tmp_folder, ignore_errors=True)
2640+
2641+ def test_find_record_by_ip(self):
2642+ """
2643+ Test find record by IP
2644+ """
2645+ # GIVEN: Record entries in database
2646+ add_records(self.projector, [Projector(**TEST1_DATA), Projector(**TEST2_DATA)])
2647+
2648+ # WHEN: Search for record using IP
2649+ record = self.projector.get_projector_by_ip(TEST2_DATA['ip'])
2650+
2651+ # THEN: Verify proper record returned
2652+ self.assertTrue(compare_data(Projector(**TEST2_DATA), record),
2653+ 'Record found should have been test_2 data')
2654+
2655+ def test_find_record_by_name(self):
2656+ """
2657+ Test find record by name
2658+ """
2659+ # GIVEN: Record entries in database
2660+ add_records(self.projector, [Projector(**TEST1_DATA), Projector(**TEST2_DATA)])
2661+
2662+ # WHEN: Search for record using name
2663+ record = self.projector.get_projector_by_name(TEST2_DATA['name'])
2664+
2665+ # THEN: Verify proper record returned
2666+ self.assertTrue(compare_data(Projector(**TEST2_DATA), record),
2667+ 'Record found should have been test_2 data')
2668+
2669+ def test_record_delete(self):
2670+ """
2671+ Test record can be deleted
2672+ """
2673+ # GIVEN: Record in database
2674+ add_records(self.projector, [Projector(**TEST3_DATA), ])
2675+ record = self.projector.get_projector_by_ip(TEST3_DATA['ip'])
2676+
2677+ # WHEN: Record deleted
2678+ self.projector.delete_projector(record)
2679+
2680+ # THEN: Verify record not retrievable
2681+ found = self.projector.get_projector_by_ip(TEST3_DATA['ip'])
2682+ self.assertFalse(found, 'test_3 record should have been deleted')
2683+
2684+ def test_record_edit(self):
2685+ """
2686+ Test edited record returns the same record ID with different data
2687+ """
2688+ # GIVEN: Record entries in database
2689+ add_records(self.projector, [Projector(**TEST1_DATA), Projector(**TEST2_DATA)])
2690+
2691+ # WHEN: We retrieve a specific record
2692+ record = self.projector.get_projector_by_ip(TEST1_DATA['ip'])
2693+ record_id = record.id
2694+
2695+ # WHEN: Data is changed
2696+ record.ip = TEST3_DATA['ip']
2697+ record.port = TEST3_DATA['port']
2698+ record.pin = TEST3_DATA['pin']
2699+ record.name = TEST3_DATA['name']
2700+ record.location = TEST3_DATA['location']
2701+ record.notes = TEST3_DATA['notes']
2702+ record.sw_version = TEST3_DATA['sw_version']
2703+ record.serial_no = TEST3_DATA['serial_no']
2704+ record.model_filter = TEST3_DATA['model_filter']
2705+ record.model_lamp = TEST3_DATA['model_lamp']
2706+ updated = self.projector.update_projector(record)
2707+ self.assertTrue(updated, 'Save updated record should have returned True')
2708+ record = self.projector.get_projector_by_ip(TEST3_DATA['ip'])
2709+
2710+ # THEN: Record ID should remain the same, but data should be changed
2711+ self.assertEqual(record_id, record.id, 'Edited record should have the same ID')
2712+ self.assertTrue(compare_data(Projector(**TEST3_DATA), record), 'Edited record should have new data')
2713+
2714+ def test_source_add(self):
2715+ """
2716+ Test source entry for projector item
2717+ """
2718+ # GIVEN: Record entries in database
2719+ projector1 = Projector(**TEST1_DATA)
2720+ self.projector.add_projector(projector1)
2721+ item = self.projector.get_projector_by_id(projector1.id)
2722+ item_id = item.id
2723+
2724+ # WHEN: A source entry is saved for item
2725+ source = ProjectorSource(projector_id=item_id, code='11', text='First RGB source')
2726+ self.projector.add_source(source)
2727+
2728+ # THEN: Projector should have the same source entry
2729+ item = self.projector.get_projector_by_id(item_id)
2730+ self.assertTrue(compare_source(item.source_list[0], source))
2731+
2732+ def test_manufacturer_repr(self):
2733+ """
2734+ Test Manufacturer.__repr__() text
2735+ """
2736+ # GIVEN: Test object
2737+ manufacturer = Manufacturer()
2738+
2739+ # WHEN: Name is set
2740+ manufacturer.name = 'OpenLP Test'
2741+
2742+ # THEN: __repr__ should return a proper string
2743+ self.assertEqual(str(manufacturer), '<Manufacturer(name="OpenLP Test")>',
2744+ 'Manufacturer.__repr__() should have returned a proper representation string')
2745+
2746+ def test_model_repr(self):
2747+ """
2748+ Test Model.__repr__() text
2749+ """
2750+ # GIVEN: Test object
2751+ model = Model()
2752+
2753+ # WHEN: Name is set
2754+ model.name = 'OpenLP Test'
2755+
2756+ # THEN: __repr__ should return a proper string
2757+ self.assertEqual(str(model), '<Model(name='"OpenLP Test"')>',
2758+ 'Model.__repr__() should have returned a proper representation string')
2759+
2760+ def test_source_repr(self):
2761+ """
2762+ Test Source.__repr__() text
2763+ """
2764+ # GIVEN: Test object
2765+ source = Source()
2766+
2767+ # WHEN: Source() information is set
2768+ source.pjlink_name = 'Test object'
2769+ source.pjlink_code = '11'
2770+ source.text = 'Input text'
2771+
2772+ # THEN: __repr__ should return a proper string
2773+ self.assertEqual(str(source), '<Source(pjlink_name="Test object", pjlink_code="11", text="Input text")>',
2774+ 'Source.__repr__() should have returned a proper representation string')
2775+
2776+ def test_projector_repr(self):
2777+ """
2778+ Test Projector.__repr__() text
2779+ """
2780+ # GIVEN: Test object
2781+ projector = Projector()
2782+
2783+ # WHEN: projector() is populated
2784+ # NOTE: projector.[pin, other, sources, sw_version, serial_no, sw_version, model_lamp, model_filter]
2785+ # should all return None.
2786+ # projector.source_list should return an empty list
2787+ projector.id = 0
2788+ projector.ip = '127.0.0.1'
2789+ projector.port = PJLINK_PORT
2790+ projector.name = 'Test One'
2791+ projector.location = 'Somewhere over the rainbow'
2792+ projector.notes = 'Not again'
2793+ projector.pjlink_name = 'TEST'
2794+ projector.manufacturer = 'IN YOUR DREAMS'
2795+ projector.model = 'OpenLP'
2796+
2797+ # THEN: __repr__ should return a proper string
2798+ self.assertEqual(str(projector),
2799+ '< Projector(id="0", ip="127.0.0.1", port="4352", mac_adx="None", pin="None", '
2800+ 'name="Test One", location="Somewhere over the rainbow", notes="Not again", '
2801+ 'pjlink_name="TEST", manufacturer="IN YOUR DREAMS", model="OpenLP", serial_no="None", '
2802+ 'other="None", sources="None", source_list="[]", model_filter="None", model_lamp="None", '
2803+ 'sw_version="None") >',
2804+ 'Projector.__repr__() should have returned a proper representation string')
2805+
2806+ def test_projectorsource_repr(self):
2807+ """
2808+ Test ProjectorSource.__repr__() text
2809+ """
2810+ # GIVEN: test setup
2811+ projector1 = Projector(**TEST1_DATA)
2812+ self.projector.add_projector(projector1)
2813+ item = self.projector.get_projector_by_id(projector1.id)
2814+ item_id = item.id
2815+
2816+ # WHEN: A source entry is saved for item
2817+ source = ProjectorSource(projector_id=item_id, code='11', text='First RGB source')
2818+ self.projector.add_source(source)
2819+
2820+ # THEN: __repr__ should return a proper string
2821+ self.assertEqual(str(source),
2822+ '<ProjectorSource(id="1", code="11", text="First RGB source", projector_id="1")>',
2823+ 'ProjectorSource.__repr__)_ should have returned a proper representation string')
2824+
2825+ def test_get_projector_by_id_none(self):
2826+ """
2827+ Test get_projector_by_id() returns None if no db entry
2828+ """
2829+ # GIVEN: Test object and data
2830+ projector = self.projector
2831+
2832+ # WHEN: DB search for entry not saved
2833+ results = projector.get_projector_by_id(dbid=123134556409824506)
2834+
2835+ # THEN: Verify return was None
2836+ self.assertEqual(results, None, 'Returned results should have equaled None')
2837+
2838+ def test_get_projector_all_none(self):
2839+ """
2840+ Test get_projector_all() with no projectors in db
2841+ """
2842+ # GIVEN: Test object with no data
2843+ projector = self.projector
2844+
2845+ # WHEN: We retrieve the database entries
2846+ results = projector.get_projector_all()
2847+
2848+ # THEN: Verify results is None
2849+ self.assertEqual(results, [], 'Returned results should have returned an empty list')
2850+
2851+ def test_get_projector_all_one(self):
2852+ """
2853+ Test get_projector_all() with one entry in db
2854+ """
2855+ # GIVEN: One entry in database
2856+ projector = Projector(**TEST1_DATA)
2857+ self.projector.add_projector(projector)
2858+
2859+ # WHEN: We retrieve the database entries
2860+ results = self.projector.get_projector_all()
2861+
2862+ # THEN: We should have a list with one entry
2863+ self.assertEqual(len(results), 1, 'Returned results should have returned a list with one entry')
2864+ self.assertTrue((projector in results), 'Result should have been equal to TEST1_DATA')
2865+
2866+ def test_get_projector_all_many(self):
2867+ """
2868+ Test get_projector_all() with multiple entries in db
2869+ """
2870+ # GIVEN: multiple entries in database
2871+ projector_list = []
2872+ projector_list.append(Projector(**TEST1_DATA))
2873+ projector_list.append(Projector(**TEST2_DATA))
2874+ projector_list.append(Projector(**TEST3_DATA))
2875+ for projector in projector_list:
2876+ self.projector.add_projector(projector)
2877+
2878+ # WHEN: We retrieve the database entries
2879+ results = self.projector.get_projector_all()
2880+
2881+ # THEN: We should have a list with three entries
2882+ self.assertEqual(len(results), len(projector_list),
2883+ 'Returned results should have returned a list with three entries')
2884+ for projector in results:
2885+ self.assertTrue((projector in projector_list),
2886+ 'Projector DB entry should have been in expected list')
2887+
2888+ def test_get_projector_by_name_fail(self):
2889+ """
2890+ Test get_projector_by_name() fail
2891+ """
2892+ # GIVEN: Test entry in database
2893+ self.projector.add_projector(Projector(**TEST1_DATA))
2894+
2895+ # WHEN: We attempt to get a projector that's not in database
2896+ results = self.projector.get_projector_by_name(name=TEST2_DATA['name'])
2897+
2898+ # THEN: We should have None
2899+ self.assertEqual(results, None, 'projector.get_projector_by_name() should have returned None')
2900+
2901+ def test_add_projector_fail(self):
2902+ """
2903+ Test add_projector() fail
2904+ """
2905+ # GIVEN: Test entry in the database
2906+ self.projector.add_projector(Projector(**TEST1_DATA))
2907+
2908+ # WHEN: Attempt to add same projector entry
2909+ results = self.projector.add_projector(Projector(**TEST1_DATA))
2910+
2911+ # THEN: We should have failed to add new entry
2912+ self.assertFalse(results, 'add_projector() should have failed')
2913+
2914+ def test_update_projector_default_fail(self):
2915+ """
2916+ Test update_projector() with no options fails
2917+ """
2918+ # GIVEN: projector instance
2919+ projector = self.projector
2920+
2921+ # WHEN: attempt to update a projector entry with no options
2922+ results = projector.update_projector()
2923+
2924+ # THEN: We should have failed
2925+ self.assertFalse(results, 'update_projector(projector=None) should have returned False')
2926+
2927+ def test_update_projector_not_in_db_fail(self):
2928+ """
2929+ Test update_projector() when entry not in database
2930+ """
2931+ # GIVEN: Projector entry in database
2932+ self.projector.add_projector(Projector(**TEST1_DATA))
2933+ projector = Projector(**TEST2_DATA)
2934+
2935+ # WHEN: Attempt to update data with a different ID
2936+ results = self.projector.update_projector(projector)
2937+
2938+ # THEN: Results should be False
2939+ self.assertFalse(results, 'update_projector(projector=projector) should have returned False')
2940+
2941+ def test_delete_projector_fail(self):
2942+ """
2943+ Test delete_projector(projector) fails to delete record
2944+ """
2945+ # GIVEN: Test entry in db
2946+ self.projector.add_projector(Projector(**TEST1_DATA))
2947+
2948+ # wHEN: Attempting to delete an entry not in the databae
2949+ results = self.projector.delete_projector(Projector(**TEST2_DATA))
2950+
2951+ # THEN: Results should be False
2952+ self.assertFalse(results, 'delete_projector() should have returned False')
2953
2954=== added file 'tests/functional/openlp_core/projectors/test_projector_pjlink_base.py'
2955--- tests/functional/openlp_core/projectors/test_projector_pjlink_base.py 1970-01-01 00:00:00 +0000
2956+++ tests/functional/openlp_core/projectors/test_projector_pjlink_base.py 2017-11-17 06:06:50 +0000
2957@@ -0,0 +1,209 @@
2958+# -*- coding: utf-8 -*-
2959+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
2960+
2961+###############################################################################
2962+# OpenLP - Open Source Lyrics Projection #
2963+# --------------------------------------------------------------------------- #
2964+# Copyright (c) 2008-2015 OpenLP Developers #
2965+# --------------------------------------------------------------------------- #
2966+# This program is free software; you can redistribute it and/or modify it #
2967+# under the terms of the GNU General Public License as published by the Free #
2968+# Software Foundation; version 2 of the License. #
2969+# #
2970+# This program is distributed in the hope that it will be useful, but WITHOUT #
2971+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
2972+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
2973+# more details. #
2974+# #
2975+# You should have received a copy of the GNU General Public License along #
2976+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
2977+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
2978+###############################################################################
2979+"""
2980+Package to test the openlp.core.projectors.pjlink base package.
2981+"""
2982+from unittest import TestCase
2983+from unittest.mock import call, patch, MagicMock
2984+
2985+from openlp.core.projectors.constants import E_PARAMETER, ERROR_STRING, S_ON, S_CONNECTED
2986+from openlp.core.projectors.db import Projector
2987+from openlp.core.projectors.pjlink import PJLink
2988+
2989+from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE, TEST_HASH, TEST1_DATA
2990+
2991+pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True)
2992+
2993+
2994+class TestPJLinkBase(TestCase):
2995+ """
2996+ Tests for the PJLink module
2997+ """
2998+ @patch.object(pjlink_test, 'readyRead')
2999+ @patch.object(pjlink_test, 'send_command')
3000+ @patch.object(pjlink_test, 'waitForReadyRead')
3001+ @patch('openlp.core.common.qmd5_hash')
3002+ def test_authenticated_connection_call(self,
3003+ mock_qmd5_hash,
3004+ mock_waitForReadyRead,
3005+ mock_send_command,
3006+ mock_readyRead):
3007+ """
3008+ Ticket 92187: Fix for projector connect with PJLink authentication exception.
3009+ """
3010+ # GIVEN: Test object
3011+ pjlink = pjlink_test
3012+
3013+ # WHEN: Calling check_login with authentication request:
3014+ pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
3015+
3016+ # THEN: Should have called qmd5_hash
3017+ self.assertTrue(mock_qmd5_hash.called_with(TEST_SALT,
3018+ "Connection request should have been called with TEST_SALT"))
3019+ self.assertTrue(mock_qmd5_hash.called_with(TEST_PIN,
3020+ "Connection request should have been called with TEST_PIN"))
3021+
3022+ @patch.object(pjlink_test, 'change_status')
3023+ def test_status_change(self, mock_change_status):
3024+ """
3025+ Test process_command call with ERR2 (Parameter) status
3026+ """
3027+ # GIVEN: Test object
3028+ pjlink = pjlink_test
3029+
3030+ # WHEN: process_command is called with "ERR2" status from projector
3031+ pjlink.process_command('POWR', 'ERR2')
3032+
3033+ # THEN: change_status should have called change_status with E_UNDEFINED
3034+ # as first parameter
3035+ mock_change_status.called_with(E_PARAMETER,
3036+ 'change_status should have been called with "{}"'.format(
3037+ ERROR_STRING[E_PARAMETER]))
3038+
3039+ @patch.object(pjlink_test, 'send_command')
3040+ @patch.object(pjlink_test, 'waitForReadyRead')
3041+ @patch.object(pjlink_test, 'projectorAuthentication')
3042+ @patch.object(pjlink_test, 'timer')
3043+ @patch.object(pjlink_test, 'socket_timer')
3044+ def test_bug_1593882_no_pin_authenticated_connection(self,
3045+ mock_socket_timer,
3046+ mock_timer,
3047+ mock_authentication,
3048+ mock_ready_read,
3049+ mock_send_command):
3050+ """
3051+ Test bug 1593882 no pin and authenticated request exception
3052+ """
3053+ # GIVEN: Test object and mocks
3054+ pjlink = pjlink_test
3055+ pjlink.pin = None
3056+ mock_ready_read.return_value = True
3057+
3058+ # WHEN: call with authentication request and pin not set
3059+ pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
3060+
3061+ # THEN: 'No Authentication' signal should have been sent
3062+ mock_authentication.emit.assert_called_with(pjlink.ip)
3063+
3064+ @patch.object(pjlink_test, 'waitForReadyRead')
3065+ @patch.object(pjlink_test, 'state')
3066+ @patch.object(pjlink_test, '_send_command')
3067+ @patch.object(pjlink_test, 'timer')
3068+ @patch.object(pjlink_test, 'socket_timer')
3069+ def test_bug_1593883_pjlink_authentication(self,
3070+ mock_socket_timer,
3071+ mock_timer,
3072+ mock_send_command,
3073+ mock_state,
3074+ mock_waitForReadyRead):
3075+ """
3076+ Test bugfix 1593883 pjlink authentication
3077+ """
3078+ # GIVEN: Test object and data
3079+ pjlink = pjlink_test
3080+ pjlink.pin = TEST_PIN
3081+ mock_state.return_value = pjlink.ConnectedState
3082+ mock_waitForReadyRead.return_value = True
3083+
3084+ # WHEN: Athenticated connection is called
3085+ pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
3086+
3087+ # THEN: send_command should have the proper authentication
3088+ self.assertEqual("{test}".format(test=mock_send_command.call_args),
3089+ "call(data='{hash}%1CLSS ?\\r')".format(hash=TEST_HASH))
3090+
3091+ @patch.object(pjlink_test, 'disconnect_from_host')
3092+ def test_socket_abort(self, mock_disconnect):
3093+ """
3094+ Test PJLink.socket_abort calls disconnect_from_host
3095+ """
3096+ # GIVEN: Test object
3097+ pjlink = pjlink_test
3098+
3099+ # WHEN: Calling socket_abort
3100+ pjlink.socket_abort()
3101+
3102+ # THEN: disconnect_from_host should be called
3103+ self.assertTrue(mock_disconnect.called, 'Should have called disconnect_from_host')
3104+
3105+ def test_poll_loop_not_connected(self):
3106+ """
3107+ Test PJLink.poll_loop not connected return
3108+ """
3109+ # GIVEN: Test object and mocks
3110+ pjlink = pjlink_test
3111+ pjlink.state = MagicMock()
3112+ pjlink.timer = MagicMock()
3113+ pjlink.state.return_value = False
3114+ pjlink.ConnectedState = True
3115+
3116+ # WHEN: PJLink.poll_loop called
3117+ pjlink.poll_loop()
3118+
3119+ # THEN: poll_loop should exit without calling any other method
3120+ self.assertFalse(pjlink.timer.called, 'Should have returned without calling any other method')
3121+
3122+ @patch.object(pjlink_test, 'send_command')
3123+ def test_poll_loop_start(self, mock_send_command):
3124+ """
3125+ Test PJLink.poll_loop makes correct calls
3126+ """
3127+ # GIVEN: test object and test data
3128+ pjlink = pjlink_test
3129+ pjlink.state = MagicMock()
3130+ pjlink.timer = MagicMock()
3131+ pjlink.timer.interval = MagicMock()
3132+ pjlink.timer.setInterval = MagicMock()
3133+ pjlink.timer.start = MagicMock()
3134+ pjlink.poll_time = 20
3135+ pjlink.power = S_ON
3136+ pjlink.source_available = None
3137+ pjlink.other_info = None
3138+ pjlink.manufacturer = None
3139+ pjlink.model = None
3140+ pjlink.pjlink_name = None
3141+ pjlink.ConnectedState = S_CONNECTED
3142+ pjlink.timer.interval.return_value = 10
3143+ pjlink.state.return_value = S_CONNECTED
3144+ call_list = [
3145+ call('POWR', queue=True),
3146+ call('ERST', queue=True),
3147+ call('LAMP', queue=True),
3148+ call('AVMT', queue=True),
3149+ call('INPT', queue=True),
3150+ call('INST', queue=True),
3151+ call('INFO', queue=True),
3152+ call('INF1', queue=True),
3153+ call('INF2', queue=True),
3154+ call('NAME', queue=True),
3155+ ]
3156+
3157+ # WHEN: PJLink.poll_loop is called
3158+ pjlink.poll_loop()
3159+
3160+ # THEN: proper calls were made to retrieve projector data
3161+ # First, call to update the timer with the next interval
3162+ self.assertTrue(pjlink.timer.setInterval.called, 'Should have updated the timer')
3163+ # Next, should have called the timer to start
3164+ self.assertTrue(pjlink.timer.start.called, 'Should have started the timer')
3165+ # Finally, should have called send_command with a list of projetctor status checks
3166+ mock_send_command.assert_has_calls(call_list, 'Should have queued projector queries')
3167
3168=== added file 'tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py'
3169--- tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py 1970-01-01 00:00:00 +0000
3170+++ tests/functional/openlp_core/projectors/test_projector_pjlink_cmd_routing.py 2017-11-17 06:06:50 +0000
3171@@ -0,0 +1,224 @@
3172+# -*- coding: utf-8 -*-
3173+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
3174+
3175+###############################################################################
3176+# OpenLP - Open Source Lyrics Projection #
3177+# --------------------------------------------------------------------------- #
3178+# Copyright (c) 2008-2015 OpenLP Developers #
3179+# --------------------------------------------------------------------------- #
3180+# This program is free software; you can redistribute it and/or modify it #
3181+# under the terms of the GNU General Public License as published by the Free #
3182+# Software Foundation; version 2 of the License. #
3183+# #
3184+# This program is distributed in the hope that it will be useful, but WITHOUT #
3185+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
3186+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
3187+# more details. #
3188+# #
3189+# You should have received a copy of the GNU General Public License along #
3190+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
3191+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
3192+###############################################################################
3193+"""
3194+Package to test the openlp.core.projectors.pjlink command routing.
3195+"""
3196+
3197+from unittest import TestCase
3198+from unittest.mock import patch, MagicMock
3199+
3200+import openlp.core.projectors.pjlink
3201+from openlp.core.projectors.constants import PJLINK_ERRORS, \
3202+ E_AUTHENTICATION, E_PARAMETER, E_PROJECTOR, E_UNAVAILABLE, E_UNDEFINED
3203+from openlp.core.projectors.db import Projector
3204+from openlp.core.projectors.pjlink import PJLink
3205+
3206+'''
3207+from openlp.core.projectors.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
3208+ PJLINK_POWR_STATUS, PJLINK_VALID_CMD, E_WARN, E_ERROR, S_OFF, S_STANDBY, S_ON
3209+'''
3210+from tests.resources.projector.data import TEST_PIN, TEST1_DATA
3211+
3212+pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
3213+pjlink_test.ip = '127.0.0.1'
3214+
3215+
3216+class TestPJLinkRouting(TestCase):
3217+ """
3218+ Tests for the PJLink module command routing
3219+ """
3220+ @patch.object(openlp.core.projectors.pjlink, 'log')
3221+ def test_process_command_call_clss(self, mock_log):
3222+ """
3223+ Test process_command calls proper function
3224+ """
3225+ # GIVEN: Test object
3226+ pjlink = pjlink_test
3227+ log_text = '(127.0.0.1) Calling function for CLSS'
3228+ mock_log.reset_mock()
3229+ mock_process_clss = MagicMock()
3230+ pjlink.pjlink_functions['CLSS'] = mock_process_clss
3231+
3232+ # WHEN: process_command is called with valid function and data
3233+ pjlink.process_command(cmd='CLSS', data='1')
3234+
3235+ # THEN: Process method should have been called properly
3236+ mock_log.debug.assert_called_with(log_text)
3237+ mock_process_clss.assert_called_with('1')
3238+
3239+ @patch.object(pjlink_test, 'change_status')
3240+ @patch.object(openlp.core.projectors.pjlink, 'log')
3241+ def test_process_command_err1(self, mock_log, mock_change_status):
3242+ """
3243+ Test ERR1 - Undefined projector function
3244+ """
3245+ # GIVEN: Test object
3246+ pjlink = pjlink_test
3247+ log_text = '(127.0.0.1) Projector returned error "ERR1"'
3248+ mock_change_status.reset_mock()
3249+ mock_log.reset_mock()
3250+
3251+ # WHEN: process_command called with ERR1
3252+ pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNDEFINED])
3253+
3254+ # THEN: Error should be logged and status_change should be called
3255+ mock_change_status.assert_called_once_with(E_UNDEFINED, 'Undefined Command: "CLSS"')
3256+ mock_log.error.assert_called_with(log_text)
3257+
3258+ @patch.object(pjlink_test, 'change_status')
3259+ @patch.object(openlp.core.projectors.pjlink, 'log')
3260+ def test_process_command_err2(self, mock_log, mock_change_status):
3261+ """
3262+ Test ERR2 - Parameter Error
3263+ """
3264+ # GIVEN: Test object
3265+ pjlink = pjlink_test
3266+ log_text = '(127.0.0.1) Projector returned error "ERR2"'
3267+ mock_change_status.reset_mock()
3268+ mock_log.reset_mock()
3269+
3270+ # WHEN: process_command called with ERR2
3271+ pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PARAMETER])
3272+
3273+ # THEN: Error should be logged and status_change should be called
3274+ mock_change_status.assert_called_once_with(E_PARAMETER)
3275+ mock_log.error.assert_called_with(log_text)
3276+
3277+ @patch.object(pjlink_test, 'change_status')
3278+ @patch.object(openlp.core.projectors.pjlink, 'log')
3279+ def test_process_command_err3(self, mock_log, mock_change_status):
3280+ """
3281+ Test ERR3 - Unavailable error
3282+ """
3283+ # GIVEN: Test object
3284+ pjlink = pjlink_test
3285+ log_text = '(127.0.0.1) Projector returned error "ERR3"'
3286+ mock_change_status.reset_mock()
3287+ mock_log.reset_mock()
3288+
3289+ # WHEN: process_command called with ERR3
3290+ pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_UNAVAILABLE])
3291+
3292+ # THEN: Error should be logged and status_change should be called
3293+ mock_change_status.assert_called_once_with(E_UNAVAILABLE)
3294+ mock_log.error.assert_called_with(log_text)
3295+
3296+ @patch.object(pjlink_test, 'change_status')
3297+ @patch.object(openlp.core.projectors.pjlink, 'log')
3298+ def test_process_command_err4(self, mock_log, mock_change_status):
3299+ """
3300+ Test ERR3 - Unavailable error
3301+ """
3302+ # GIVEN: Test object
3303+ pjlink = pjlink_test
3304+ log_text = '(127.0.0.1) Projector returned error "ERR4"'
3305+ mock_change_status.reset_mock()
3306+ mock_log.reset_mock()
3307+
3308+ # WHEN: process_command called with ERR3
3309+ pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_PROJECTOR])
3310+
3311+ # THEN: Error should be logged and status_change should be called
3312+ mock_change_status.assert_called_once_with(E_PROJECTOR)
3313+ mock_log.error.assert_called_with(log_text)
3314+
3315+ @patch.object(pjlink_test, 'projectorAuthentication')
3316+ @patch.object(pjlink_test, 'change_status')
3317+ @patch.object(pjlink_test, 'disconnect_from_host')
3318+ @patch.object(openlp.core.projectors.pjlink, 'log')
3319+ def test_process_command_erra(self, mock_log, mock_disconnect, mock_change_status, mock_err_authenticate):
3320+ """
3321+ Test ERRA - Authentication Error
3322+ """
3323+ # GIVEN: Test object
3324+ pjlink = pjlink_test
3325+ log_text = '(127.0.0.1) Projector returned error "ERRA"'
3326+ mock_change_status.reset_mock()
3327+ mock_log.reset_mock()
3328+
3329+ # WHEN: process_command called with ERRA
3330+ pjlink.process_command(cmd='CLSS', data=PJLINK_ERRORS[E_AUTHENTICATION])
3331+
3332+ # THEN: Error should be logged and several methods should be called
3333+ self.assertTrue(mock_disconnect.called, 'disconnect_from_host should have been called')
3334+ mock_change_status.assert_called_once_with(E_AUTHENTICATION)
3335+ mock_log.error.assert_called_with(log_text)
3336+
3337+ @patch.object(openlp.core.projectors.pjlink, 'log')
3338+ def test_process_command_future(self, mock_log):
3339+ """
3340+ Test command valid but no method to process yet
3341+ """
3342+ # GIVEN: Test object
3343+ pjlink = pjlink_test
3344+ log_text = "(127.0.0.1) Unable to process command='CLSS' (Future option)"
3345+ mock_log.reset_mock()
3346+ # Remove a valid command so we can test valid command but not available yet
3347+ pjlink.pjlink_functions.pop('CLSS')
3348+
3349+ # WHEN: process_command called with an unknown command
3350+ with patch.object(pjlink, 'pjlink_functions') as mock_functions:
3351+ pjlink.process_command(cmd='CLSS', data='DONT CARE')
3352+
3353+ # THEN: Error should be logged and no command called
3354+ self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
3355+ mock_log.warning.assert_called_once_with(log_text)
3356+
3357+ @patch.object(pjlink_test, 'pjlink_functions')
3358+ @patch.object(openlp.core.projectors.pjlink, 'log')
3359+ def test_process_command_invalid(self, mock_log, mock_functions):
3360+ """
3361+ Test not a valid command
3362+ """
3363+ # GIVEN: Test object
3364+ pjlink = pjlink_test
3365+ mock_functions.reset_mock()
3366+ mock_log.reset_mock()
3367+
3368+ # WHEN: process_command called with an unknown command
3369+ pjlink.process_command(cmd='Unknown', data='Dont Care')
3370+ log_text = "(127.0.0.1) Ignoring command='Unknown' (Invalid/Unknown)"
3371+
3372+ # THEN: Error should be logged and no command called
3373+ self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
3374+ mock_log.error.assert_called_once_with(log_text)
3375+
3376+ @patch.object(pjlink_test, 'pjlink_functions')
3377+ @patch.object(openlp.core.projectors.pjlink, 'log')
3378+ def test_process_command_ok(self, mock_log, mock_functions):
3379+ """
3380+ Test command returned success
3381+ """
3382+ # GIVEN: Test object
3383+ pjlink = pjlink_test
3384+ mock_functions.reset_mock()
3385+ mock_log.reset_mock()
3386+
3387+ # WHEN: process_command called with an unknown command
3388+ pjlink.process_command(cmd='CLSS', data='OK')
3389+ log_text = '(127.0.0.1) Command "CLSS" returned OK'
3390+
3391+ # THEN: Error should be logged and no command called
3392+ self.assertFalse(mock_functions.called, 'Should not have gotten to the end of the method')
3393+ self.assertEqual(mock_log.debug.call_count, 2, 'log.debug() should have been called twice')
3394+ # Although we called it twice, only the last log entry is saved
3395+ mock_log.debug.assert_called_with(log_text)
3396
3397=== added file 'tests/functional/openlp_core/projectors/test_projector_pjlink_commands.py'
3398--- tests/functional/openlp_core/projectors/test_projector_pjlink_commands.py 1970-01-01 00:00:00 +0000
3399+++ tests/functional/openlp_core/projectors/test_projector_pjlink_commands.py 2017-11-17 06:06:50 +0000
3400@@ -0,0 +1,1149 @@
3401+# -*- coding: utf-8 -*-
3402+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
3403+
3404+###############################################################################
3405+# OpenLP - Open Source Lyrics Projection #
3406+# --------------------------------------------------------------------------- #
3407+# Copyright (c) 2008-2015 OpenLP Developers #
3408+# --------------------------------------------------------------------------- #
3409+# This program is free software; you can redistribute it and/or modify it #
3410+# under the terms of the GNU General Public License as published by the Free #
3411+# Software Foundation; version 2 of the License. #
3412+# #
3413+# This program is distributed in the hope that it will be useful, but WITHOUT #
3414+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
3415+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
3416+# more details. #
3417+# #
3418+# You should have received a copy of the GNU General Public License along #
3419+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
3420+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
3421+###############################################################################
3422+"""
3423+Package to test the openlp.core.projectors.pjlink commands package.
3424+"""
3425+from unittest import TestCase
3426+from unittest.mock import patch
3427+
3428+import openlp.core.projectors.pjlink
3429+from openlp.core.projectors.constants import ERROR_STRING, PJLINK_ERST_DATA, PJLINK_ERST_STATUS, \
3430+ PJLINK_POWR_STATUS, \
3431+ E_ERROR, E_NOT_CONNECTED, E_SOCKET_ADDRESS_NOT_AVAILABLE, E_UNKNOWN_SOCKET_ERROR, E_WARN, \
3432+ S_CONNECTED, S_OFF, S_ON, S_NOT_CONNECTED, S_CONNECTING, S_STANDBY
3433+from openlp.core.projectors.db import Projector
3434+from openlp.core.projectors.pjlink import PJLink
3435+
3436+from tests.resources.projector.data import TEST_PIN, TEST1_DATA
3437+
3438+pjlink_test = PJLink(Projector(**TEST1_DATA), pin=TEST_PIN, no_poll=True)
3439+pjlink_test.ip = '127.0.0.1'
3440+
3441+# Create a list of ERST positional data so we don't have to redo the same buildup multiple times
3442+PJLINK_ERST_POSITIONS = []
3443+for pos in range(0, len(PJLINK_ERST_DATA)):
3444+ if pos in PJLINK_ERST_DATA:
3445+ PJLINK_ERST_POSITIONS.append(PJLINK_ERST_DATA[pos])
3446+
3447+
3448+class TestPJLinkCommands(TestCase):
3449+ """
3450+ Tests for the PJLink module
3451+ """
3452+ @patch.object(pjlink_test, 'changeStatus')
3453+ @patch.object(openlp.core.projectors.pjlink, 'log')
3454+ def test_projector_change_status_connection_error(self, mock_log, mock_change_status):
3455+ """
3456+ Test change_status with connection error
3457+ """
3458+ # GIVEN: Test object
3459+ pjlink = pjlink_test
3460+ pjlink.projector_status = 0
3461+ pjlink.status_connect = 0
3462+ test_code = E_UNKNOWN_SOCKET_ERROR
3463+ mock_change_status.reset_mock()
3464+ mock_log.reset_mock()
3465+
3466+ # WHEN: change_status called with unknown socket error
3467+ pjlink.change_status(status=test_code, msg=None)
3468+
3469+ # THEN: Proper settings should change and signals sent
3470+ self.assertEqual(pjlink.projector_status, E_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')
3471+ self.assertEqual(pjlink.status_connect, E_NOT_CONNECTED, 'Status connect should be NOT CONNECTED')
3472+ mock_change_status.emit.assert_called_once_with(pjlink.ip, E_UNKNOWN_SOCKET_ERROR,
3473+ 'An unidentified error occurred')
3474+ self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
3475+
3476+ @patch.object(pjlink_test, 'changeStatus')
3477+ @patch.object(openlp.core.projectors.pjlink, 'log')
3478+ def test_projector_change_status_connection_status_connecting(self, mock_log, mock_change_status):
3479+ """
3480+ Test change_status with connection status
3481+ """
3482+ # GIVEN: Test object
3483+ pjlink = pjlink_test
3484+ pjlink.projector_status = 0
3485+ pjlink.status_connect = 0
3486+ test_code = S_CONNECTING
3487+ mock_change_status.reset_mock()
3488+ mock_log.reset_mock()
3489+
3490+ # WHEN: change_status called with unknown socket error
3491+ pjlink.change_status(status=test_code, msg=None)
3492+
3493+ # THEN: Proper settings should change and signals sent
3494+ self.assertEqual(pjlink.projector_status, S_NOT_CONNECTED, 'Projector status should be NOT CONNECTED')
3495+ self.assertEqual(pjlink.status_connect, S_CONNECTING, 'Status connect should be CONNECTING')
3496+ mock_change_status.emit.assert_called_once_with(pjlink.ip, S_CONNECTING, 'Connecting')
3497+ self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
3498+
3499+ @patch.object(pjlink_test, 'changeStatus')
3500+ @patch.object(openlp.core.projectors.pjlink, 'log')
3501+ def test_projector_change_status_connection_status_connected(self, mock_log, mock_change_status):
3502+ """
3503+ Test change_status with connection status
3504+ """
3505+ # GIVEN: Test object
3506+ pjlink = pjlink_test
3507+ pjlink.projector_status = 0
3508+ pjlink.status_connect = 0
3509+ test_code = S_ON
3510+ mock_change_status.reset_mock()
3511+ mock_log.reset_mock()
3512+
3513+ # WHEN: change_status called with unknown socket error
3514+ pjlink.change_status(status=test_code, msg=None)
3515+
3516+ # THEN: Proper settings should change and signals sent
3517+ self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
3518+ self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
3519+ mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, 'Power is on')
3520+ self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
3521+
3522+ @patch.object(pjlink_test, 'changeStatus')
3523+ @patch.object(openlp.core.projectors.pjlink, 'log')
3524+ def test_projector_change_status_connection_status_with_message(self, mock_log, mock_change_status):
3525+ """
3526+ Test change_status with connection status
3527+ """
3528+ # GIVEN: Test object
3529+ pjlink = pjlink_test
3530+ pjlink.projector_status = 0
3531+ pjlink.status_connect = 0
3532+ test_message = 'Different Status Message than default'
3533+ test_code = S_ON
3534+ mock_change_status.reset_mock()
3535+ mock_log.reset_mock()
3536+
3537+ # WHEN: change_status called with unknown socket error
3538+ pjlink.change_status(status=test_code, msg=test_message)
3539+
3540+ # THEN: Proper settings should change and signals sent
3541+ self.assertEqual(pjlink.projector_status, S_ON, 'Projector status should be ON')
3542+ self.assertEqual(pjlink.status_connect, S_CONNECTED, 'Status connect should be CONNECTED')
3543+ mock_change_status.emit.assert_called_once_with(pjlink.ip, S_ON, test_message)
3544+ self.assertEqual(mock_log.debug.call_count, 3, 'Debug log should have been called 3 times')
3545+
3546+ @patch.object(pjlink_test, 'send_command')
3547+ @patch.object(openlp.core.projectors.pjlink, 'log')
3548+ def test_projector_get_av_mute_status(self, mock_log, mock_send_command):
3549+ """
3550+ Test sending command to retrieve shutter/audio state
3551+ """
3552+ # GIVEN: Test object
3553+ pjlink = pjlink_test
3554+ mock_log.reset_mock()
3555+ mock_send_command.reset_mock()
3556+ test_data = 'AVMT'
3557+ test_log = '(127.0.0.1) Sending AVMT command'
3558+
3559+ # WHEN: get_av_mute_status is called
3560+ pjlink.get_av_mute_status()
3561+
3562+ # THEN: log data and send_command should have been called
3563+ mock_log.debug.assert_called_once_with(test_log)
3564+ mock_send_command.assert_called_once_with(cmd=test_data)
3565+
3566+ @patch.object(pjlink_test, 'send_command')
3567+ @patch.object(openlp.core.projectors.pjlink, 'log')
3568+ def test_projector_get_available_inputs(self, mock_log, mock_send_command):
3569+ """
3570+ Test sending command to retrieve avaliable inputs
3571+ """
3572+ # GIVEN: Test object
3573+ pjlink = pjlink_test
3574+ mock_log.reset_mock()
3575+ mock_send_command.reset_mock()
3576+ test_data = 'INST'
3577+ test_log = '(127.0.0.1) Sending INST command'
3578+
3579+ # WHEN: get_available_inputs is called
3580+ pjlink.get_available_inputs()
3581+
3582+ # THEN: log data and send_command should have been called
3583+ mock_log.debug.assert_called_once_with(test_log)
3584+ mock_send_command.assert_called_once_with(cmd=test_data)
3585+
3586+ @patch.object(pjlink_test, 'send_command')
3587+ @patch.object(openlp.core.projectors.pjlink, 'log')
3588+ def test_projector_get_error_status(self, mock_log, mock_send_command):
3589+ """
3590+ Test sending command to retrieve projector error status
3591+ """
3592+ # GIVEN: Test object
3593+ pjlink = pjlink_test
3594+ mock_log.reset_mock()
3595+ mock_send_command.reset_mock()
3596+ test_data = 'ERST'
3597+ test_log = '(127.0.0.1) Sending ERST command'
3598+
3599+ # WHEN: get_error_status is called
3600+ pjlink.get_error_status()
3601+
3602+ # THEN: log data and send_command should have been called
3603+ mock_log.debug.assert_called_once_with(test_log)
3604+ mock_send_command.assert_called_once_with(cmd=test_data)
3605+
3606+ @patch.object(pjlink_test, 'send_command')
3607+ @patch.object(openlp.core.projectors.pjlink, 'log')
3608+ def test_projector_get_input_source(self, mock_log, mock_send_command):
3609+ """
3610+ Test sending command to retrieve current input
3611+ """
3612+ # GIVEN: Test object
3613+ pjlink = pjlink_test
3614+ mock_log.reset_mock()
3615+ mock_send_command.reset_mock()
3616+ test_data = 'INPT'
3617+ test_log = '(127.0.0.1) Sending INPT command'
3618+
3619+ # WHEN: get_input_source is called
3620+ pjlink.get_input_source()
3621+
3622+ # THEN: log data and send_command should have been called
3623+ mock_log.debug.assert_called_once_with(test_log)
3624+ mock_send_command.assert_called_once_with(cmd=test_data)
3625+
3626+ @patch.object(pjlink_test, 'send_command')
3627+ @patch.object(openlp.core.projectors.pjlink, 'log')
3628+ def test_projector_get_lamp_status(self, mock_log, mock_send_command):
3629+ """
3630+ Test sending command to retrieve lamp(s) status
3631+ """
3632+ # GIVEN: Test object
3633+ pjlink = pjlink_test
3634+ mock_log.reset_mock()
3635+ mock_send_command.reset_mock()
3636+ test_data = 'LAMP'
3637+ test_log = '(127.0.0.1) Sending LAMP command'
3638+
3639+ # WHEN: get_lamp_status is called
3640+ pjlink.get_lamp_status()
3641+
3642+ # THEN: log data and send_command should have been called
3643+ mock_log.debug.assert_called_once_with(test_log)
3644+ mock_send_command.assert_called_once_with(cmd=test_data)
3645+
3646+ @patch.object(pjlink_test, 'send_command')
3647+ @patch.object(openlp.core.projectors.pjlink, 'log')
3648+ def test_projector_get_manufacturer(self, mock_log, mock_send_command):
3649+ """
3650+ Test sending command to retrieve manufacturer name
3651+ """
3652+ # GIVEN: Test object
3653+ pjlink = pjlink_test
3654+ mock_log.reset_mock()
3655+ mock_send_command.reset_mock()
3656+ test_data = 'INF1'
3657+ test_log = '(127.0.0.1) Sending INF1 command'
3658+
3659+ # WHEN: get_manufacturer is called
3660+ pjlink.get_manufacturer()
3661+
3662+ # THEN: log data and send_command should have been called
3663+ mock_log.debug.assert_called_once_with(test_log)
3664+ mock_send_command.assert_called_once_with(cmd=test_data)
3665+
3666+ @patch.object(pjlink_test, 'send_command')
3667+ @patch.object(openlp.core.projectors.pjlink, 'log')
3668+ def test_projector_get_model(self, mock_log, mock_send_command):
3669+ """
3670+ Test sending command to get model information
3671+ """
3672+ # GIVEN: Test object
3673+ pjlink = pjlink_test
3674+ mock_log.reset_mock()
3675+ mock_send_command.reset_mock()
3676+ test_data = 'INF2'
3677+ test_log = '(127.0.0.1) Sending INF2 command'
3678+
3679+ # WHEN: get_model is called
3680+ pjlink.get_model()
3681+
3682+ # THEN: log data and send_command should have been called
3683+ mock_log.debug.assert_called_once_with(test_log)
3684+ mock_send_command.assert_called_once_with(cmd=test_data)
3685+
3686+ @patch.object(pjlink_test, 'send_command')
3687+ @patch.object(openlp.core.projectors.pjlink, 'log')
3688+ def test_projector_get_name(self, mock_log, mock_send_command):
3689+ """
3690+ Test sending command to get user-assigned name
3691+ """
3692+ # GIVEN: Test object
3693+ pjlink = pjlink_test
3694+ mock_log.reset_mock()
3695+ mock_send_command.reset_mock()
3696+ test_data = 'NAME'
3697+ test_log = '(127.0.0.1) Sending NAME command'
3698+
3699+ # WHEN: get_name is called
3700+ pjlink.get_name()
3701+
3702+ # THEN: log data and send_command should have been called
3703+ mock_log.debug.assert_called_once_with(test_log)
3704+ mock_send_command.assert_called_once_with(cmd=test_data)
3705+
3706+ @patch.object(pjlink_test, 'send_command')
3707+ @patch.object(openlp.core.projectors.pjlink, 'log')
3708+ def test_projector_get_other_info(self, mock_log, mock_send_command):
3709+ """
3710+ Test sending command to retrieve other information
3711+ """
3712+ # GIVEN: Test object
3713+ pjlink = pjlink_test
3714+ mock_log.reset_mock()
3715+ mock_send_command.reset_mock()
3716+ test_data = 'INFO'
3717+ test_log = '(127.0.0.1) Sending INFO command'
3718+
3719+ # WHEN: get_other_info is called
3720+ pjlink.get_other_info()
3721+
3722+ # THEN: log data and send_command should have been called
3723+ mock_log.debug.assert_called_once_with(test_log)
3724+ mock_send_command.assert_called_once_with(cmd=test_data)
3725+
3726+ @patch.object(pjlink_test, 'send_command')
3727+ @patch.object(openlp.core.projectors.pjlink, 'log')
3728+ def test_projector_get_power_status(self, mock_log, mock_send_command):
3729+ """
3730+ Test sending command to retrieve current power state
3731+ """
3732+ # GIVEN: Test object
3733+ pjlink = pjlink_test
3734+ mock_log.reset_mock()
3735+ mock_send_command.reset_mock()
3736+ test_data = 'POWR'
3737+ test_log = '(127.0.0.1) Sending POWR command'
3738+
3739+ # WHEN: get_power_status called
3740+ pjlink.get_power_status()
3741+
3742+ # THEN: log data and send_command should have been called
3743+ mock_log.debug.assert_called_once_with(test_log)
3744+ mock_send_command.assert_called_once_with(cmd=test_data)
3745+
3746+ def test_projector_get_status_error(self):
3747+ """
3748+ Test to check returned information for error code
3749+ """
3750+ # GIVEN: Test object
3751+ pjlink = pjlink_test
3752+ test_string = 'E_SOCKET_ADDRESS_NOT_AVAILABLE'
3753+ test_message = 'The address specified to socket.bind() does not belong to the host'
3754+
3755+ # WHEN: get_status called
3756+ string, message = pjlink._get_status(status=E_SOCKET_ADDRESS_NOT_AVAILABLE)
3757+
3758+ # THEN: Proper strings should have been returned
3759+ self.assertEqual(string, test_string, 'Code as string should have been returned')
3760+ self.assertEqual(message, test_message, 'Description of code should have been returned')
3761+
3762+ def test_projector_get_status_invalid(self):
3763+ """
3764+ Test to check returned information for error code
3765+ """
3766+ # GIVEN: Test object
3767+ pjlink = pjlink_test
3768+ test_string = 'Test string since get_status will only work with int'
3769+ test_message = 'Invalid status code'
3770+
3771+ # WHEN: get_status called
3772+ string, message = pjlink._get_status(status=test_string)
3773+
3774+ # THEN: Proper strings should have been returned
3775+ self.assertEqual(string, -1, 'Should have returned -1 as a bad status check')
3776+ self.assertEqual(message, test_message, 'Error message should have been returned')
3777+
3778+ def test_projector_get_status_status(self):
3779+ """
3780+ Test to check returned information for status codes
3781+ """
3782+ # GIVEN: Test object
3783+ pjlink = pjlink_test
3784+ test_string = 'S_NOT_CONNECTED'
3785+ test_message = 'Not connected'
3786+
3787+ # WHEN: get_status called
3788+ string, message = pjlink._get_status(status=S_NOT_CONNECTED)
3789+
3790+ # THEN: Proper strings should have been returned
3791+ self.assertEqual(string, test_string, 'Code as string should have been returned')
3792+ self.assertEqual(message, test_message, 'Description of code should have been returned')
3793+
3794+ def test_projector_get_status_unknown(self):
3795+ """
3796+ Test to check returned information for unknown code
3797+ """
3798+ # GIVEN: Test object
3799+ pjlink = pjlink_test
3800+ test_string = 999999
3801+ test_message = 'Unknown status'
3802+
3803+ # WHEN: get_status called
3804+ string, message = pjlink._get_status(status=test_string)
3805+
3806+ # THEN: Proper strings should have been returned
3807+ self.assertEqual(string, test_string, 'Received code should have been returned')
3808+ self.assertEqual(message, test_message, 'Unknown status string should have been returned')
3809+
3810+ def test_projector_process_inf1(self):
3811+ """
3812+ Test saving INF1 data (manufacturer)
3813+ """
3814+ # GIVEN: Test object
3815+ pjlink = pjlink_test
3816+ pjlink.manufacturer = None
3817+ test_data = 'TEst INformation MultiCase'
3818+
3819+ # WHEN: process_inf called with test data
3820+ pjlink.process_inf1(data=test_data)
3821+
3822+ # THEN: Data should be saved
3823+ self.assertEqual(pjlink.manufacturer, test_data, 'Test data should have been saved')
3824+
3825+ def test_projector_process_inf2(self):
3826+ """
3827+ Test saving INF2 data (model)
3828+ """
3829+ # GIVEN: Test object
3830+ pjlink = pjlink_test
3831+ pjlink.model = None
3832+ test_data = 'TEst moDEl MultiCase'
3833+
3834+ # WHEN: process_inf called with test data
3835+ pjlink.process_inf2(data=test_data)
3836+
3837+ # THEN: Data should be saved
3838+ self.assertEqual(pjlink.model, test_data, 'Test data should have been saved')
3839+
3840+ def test_projector_process_info(self):
3841+ """
3842+ Test saving INFO data (other information)
3843+ """
3844+ # GIVEN: Test object
3845+ pjlink = pjlink_test
3846+ pjlink.other_info = None
3847+ test_data = 'TEst ExtrANEous MultiCase INformatoin that MFGR might Set'
3848+
3849+ # WHEN: process_inf called with test data
3850+ pjlink.process_info(data=test_data)
3851+
3852+ # THEN: Data should be saved
3853+ self.assertEqual(pjlink.other_info, test_data, 'Test data should have been saved')
3854+
3855+ @patch.object(pjlink_test, 'projectorUpdateIcons')
3856+ def test_projector_process_avmt_bad_data(self, mock_UpdateIcons):
3857+ """
3858+ Test avmt bad data fail
3859+ """
3860+ # GIVEN: Test object
3861+ pjlink = pjlink_test
3862+ pjlink.shutter = True
3863+ pjlink.mute = True
3864+
3865+ # WHEN: Called with an invalid setting
3866+ pjlink.process_avmt('36')
3867+
3868+ # THEN: Shutter should be closed and mute should be True
3869+ self.assertTrue(pjlink.shutter, 'Shutter should changed')
3870+ self.assertTrue(pjlink.mute, 'Audio should not have changed')
3871+ self.assertFalse(mock_UpdateIcons.emit.called, 'Update icons should NOT have been called')
3872+
3873+ @patch.object(pjlink_test, 'projectorUpdateIcons')
3874+ def test_projector_process_avmt_closed_muted(self, mock_UpdateIcons):
3875+ """
3876+ Test avmt status shutter closed and mute off
3877+ """
3878+ # GIVEN: Test object
3879+ pjlink = pjlink_test
3880+ pjlink.shutter = False
3881+ pjlink.mute = False
3882+
3883+ # WHEN: Called with setting shutter to closed and mute on
3884+ pjlink.process_avmt('31')
3885+
3886+ # THEN: Shutter should be closed and mute should be True
3887+ self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
3888+ self.assertTrue(pjlink.mute, 'Audio should be muted')
3889+ self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
3890+
3891+ @patch.object(pjlink_test, 'projectorUpdateIcons')
3892+ def test_projector_process_avmt_shutter_closed(self, mock_UpdateIcons):
3893+ """
3894+ Test avmt status shutter closed and audio unchanged
3895+ """
3896+ # GIVEN: Test object
3897+ pjlink = pjlink_test
3898+ pjlink.shutter = False
3899+ pjlink.mute = True
3900+
3901+ # WHEN: Called with setting shutter closed and mute off
3902+ pjlink.process_avmt('11')
3903+
3904+ # THEN: Shutter should be True and mute should be False
3905+ self.assertTrue(pjlink.shutter, 'Shutter should have been set to closed')
3906+ self.assertTrue(pjlink.mute, 'Audio should not have changed')
3907+ self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
3908+
3909+ @patch.object(pjlink_test, 'projectorUpdateIcons')
3910+ def test_projector_process_avmt_audio_muted(self, mock_UpdateIcons):
3911+ """
3912+ Test avmt status shutter unchanged and mute on
3913+ """
3914+ # GIVEN: Test object
3915+ pjlink = pjlink_test
3916+ pjlink.shutter = True
3917+ pjlink.mute = False
3918+
3919+ # WHEN: Called with setting shutter closed and mute on
3920+ pjlink.process_avmt('21')
3921+
3922+ # THEN: Shutter should be closed and mute should be True
3923+ self.assertTrue(pjlink.shutter, 'Shutter should not have changed')
3924+ self.assertTrue(pjlink.mute, 'Audio should be off')
3925+ self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
3926+
3927+ @patch.object(pjlink_test, 'projectorUpdateIcons')
3928+ def test_projector_process_avmt_open_unmuted(self, mock_UpdateIcons):
3929+ """
3930+ Test avmt status shutter open and mute off
3931+ """
3932+ # GIVEN: Test object
3933+ pjlink = pjlink_test
3934+ pjlink.shutter = True
3935+ pjlink.mute = True
3936+
3937+ # WHEN: Called with setting shutter to closed and mute on
3938+ pjlink.process_avmt('30')
3939+
3940+ # THEN: Shutter should be closed and mute should be True
3941+ self.assertFalse(pjlink.shutter, 'Shutter should have been set to open')
3942+ self.assertFalse(pjlink.mute, 'Audio should be on')
3943+ self.assertTrue(mock_UpdateIcons.emit.called, 'Update icons should have been called')
3944+
3945+ def test_projector_process_clss_one(self):
3946+ """
3947+ Test class 1 sent from projector
3948+ """
3949+ # GIVEN: Test object
3950+ pjlink = pjlink_test
3951+
3952+ # WHEN: Process class response
3953+ pjlink.process_clss('1')
3954+
3955+ # THEN: Projector class should be set to 1
3956+ self.assertEqual(pjlink.pjlink_class, '1',
3957+ 'Projector should have set class=1')
3958+
3959+ def test_projector_process_clss_two(self):
3960+ """
3961+ Test class 2 sent from projector
3962+ """
3963+ # GIVEN: Test object
3964+ pjlink = pjlink_test
3965+
3966+ # WHEN: Process class response
3967+ pjlink.process_clss('2')
3968+
3969+ # THEN: Projector class should be set to 1
3970+ self.assertEqual(pjlink.pjlink_class, '2',
3971+ 'Projector should have set class=2')
3972+
3973+ def test_projector_process_clss_nonstandard_reply_optoma(self):
3974+ """
3975+ Bugfix 1550891: CLSS request returns non-standard reply with Optoma projector
3976+ """
3977+ # GIVEN: Test object
3978+ pjlink = pjlink_test
3979+
3980+ # WHEN: Process non-standard reply
3981+ pjlink.process_clss('Class 1')
3982+
3983+ # THEN: Projector class should be set with proper value
3984+ self.assertEqual(pjlink.pjlink_class, '1',
3985+ 'Non-standard class reply should have set class=1')
3986+
3987+ def test_projector_process_clss_nonstandard_reply_benq(self):
3988+ """
3989+ Bugfix 1550891: CLSS request returns non-standard reply with BenQ projector
3990+ """
3991+ # GIVEN: Test object
3992+ pjlink = pjlink_test
3993+
3994+ # WHEN: Process non-standard reply
3995+ pjlink.process_clss('Version2')
3996+
3997+ # THEN: Projector class should be set with proper value
3998+ # NOTE: At this time BenQ is Class 1, but we're trying a different value to verify
3999+ self.assertEqual(pjlink.pjlink_class, '2',
4000+ 'Non-standard class reply should have set class=2')
4001+
4002+ @patch.object(openlp.core.projectors.pjlink, 'log')
4003+ def test_projector_process_clss_invalid_nan(self, mock_log):
4004+ """
4005+ Test CLSS reply has no class number
4006+ """
4007+ # GIVEN: Test object
4008+ pjlink = pjlink_test
4009+
4010+ # WHEN: Process invalid reply
4011+ pjlink.process_clss('Z')
4012+ log_text = "(127.0.0.1) NAN clss version reply 'Z' - defaulting to class '1'"
4013+
4014+ # THEN: Projector class should be set with default value
4015+ self.assertEqual(pjlink.pjlink_class, '1',
4016+ 'Non-standard class reply should have set class=1')
4017+ mock_log.error.assert_called_once_with(log_text)
4018+
4019+ @patch.object(openlp.core.projectors.pjlink, 'log')
4020+ def test_projector_process_clss_invalid_no_version(self, mock_log):
4021+ """
4022+ Test CLSS reply has no class number
4023+ """
4024+ # GIVEN: Test object
4025+ pjlink = pjlink_test
4026+
4027+ # WHEN: Process invalid reply
4028+ pjlink.process_clss('Invalid')
4029+ log_text = "(127.0.0.1) No numbers found in class version reply 'Invalid' - defaulting to class '1'"
4030+
4031+ # THEN: Projector class should be set with default value
4032+ self.assertEqual(pjlink.pjlink_class, '1',
4033+ 'Non-standard class reply should have set class=1')
4034+ mock_log.error.assert_called_once_with(log_text)
4035+
4036+ def test_projector_process_erst_all_ok(self):
4037+ """
4038+ Test test_projector_process_erst_all_ok
4039+ """
4040+ # GIVEN: Test object
4041+ pjlink = pjlink_test
4042+ chk_test = PJLINK_ERST_STATUS['OK']
4043+ chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
4044+
4045+ # WHEN: process_erst with no errors
4046+ pjlink.process_erst(chk_param)
4047+
4048+ # THEN: PJLink instance errors should be None
4049+ self.assertIsNone(pjlink.projector_errors, 'projector_errors should have been set to None')
4050+
4051+ @patch.object(openlp.core.projectors.pjlink, 'log')
4052+ def test_projector_process_erst_data_invalid_length(self, mock_log):
4053+ """
4054+ Test test_projector_process_erst_data_invalid_length
4055+ """
4056+ # GIVEN: Test object
4057+ pjlink = pjlink_test
4058+ pjlink.projector_errors = None
4059+ log_text = "127.0.0.1) Invalid error status response '11111111': length != 6"
4060+
4061+ # WHEN: process_erst called with invalid data (too many values
4062+ pjlink.process_erst('11111111')
4063+
4064+ # THEN: pjlink.projector_errors should be empty and warning logged
4065+ self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
4066+ self.assertTrue(mock_log.warning.called, 'Warning should have been logged')
4067+ mock_log.warning.assert_called_once_with(log_text)
4068+
4069+ @patch.object(openlp.core.projectors.pjlink, 'log')
4070+ def test_projector_process_erst_data_invalid_nan(self, mock_log):
4071+ """
4072+ Test test_projector_process_erst_data_invalid_nan
4073+ """
4074+ # GIVEN: Test object
4075+ pjlink = pjlink_test
4076+ pjlink.projector_errors = None
4077+ log_text = "(127.0.0.1) Invalid error status response '1111Z1'"
4078+
4079+ # WHEN: process_erst called with invalid data (too many values
4080+ pjlink.process_erst('1111Z1')
4081+
4082+ # THEN: pjlink.projector_errors should be empty and warning logged
4083+ self.assertIsNone(pjlink.projector_errors, 'There should be no errors')
4084+ self.assertTrue(mock_log.warning.called, 'Warning should have been logged')
4085+ mock_log.warning.assert_called_once_with(log_text)
4086+
4087+ def test_projector_process_erst_all_warn(self):
4088+ """
4089+ Test test_projector_process_erst_all_warn
4090+ """
4091+ # GIVEN: Test object
4092+ pjlink = pjlink_test
4093+ chk_test = PJLINK_ERST_STATUS[E_WARN]
4094+ chk_string = ERROR_STRING[E_WARN]
4095+ chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
4096+
4097+ # WHEN: process_erst with status set to WARN
4098+ pjlink.process_erst(chk_param)
4099+
4100+ # THEN: PJLink instance errors should match chk_value
4101+ for chk in pjlink.projector_errors:
4102+ self.assertEqual(pjlink.projector_errors[chk], chk_string,
4103+ "projector_errors['{chk}'] should have been set to {err}".format(chk=chk,
4104+ err=chk_string))
4105+
4106+ def test_projector_process_erst_all_error(self):
4107+ """
4108+ Test test_projector_process_erst_all_error
4109+ """
4110+ # GIVEN: Test object
4111+ pjlink = pjlink_test
4112+ chk_test = PJLINK_ERST_STATUS[E_ERROR]
4113+ chk_string = ERROR_STRING[E_ERROR]
4114+ chk_param = chk_test * len(PJLINK_ERST_POSITIONS)
4115+
4116+ # WHEN: process_erst with status set to WARN
4117+ pjlink.process_erst(chk_param)
4118+
4119+ # THEN: PJLink instance errors should match chk_value
4120+ for chk in pjlink.projector_errors:
4121+ self.assertEqual(pjlink.projector_errors[chk], chk_string,
4122+ "projector_errors['{chk}'] should have been set to {err}".format(chk=chk,
4123+ err=chk_string))
4124+
4125+ def test_projector_process_erst_warn_cover_only(self):
4126+ """
4127+ Test test_projector_process_erst_warn_cover_only
4128+ """
4129+ # GIVEN: Test object
4130+ pjlink = pjlink_test
4131+ chk_test = PJLINK_ERST_STATUS[E_WARN]
4132+ chk_string = ERROR_STRING[E_WARN]
4133+ pos = PJLINK_ERST_DATA['COVER']
4134+ build_chk = []
4135+ for check in range(0, len(PJLINK_ERST_POSITIONS)):
4136+ if check == pos:
4137+ build_chk.append(chk_test)
4138+ else:
4139+ build_chk.append(PJLINK_ERST_STATUS['OK'])
4140+ chk_param = ''.join(build_chk)
4141+
4142+ # WHEN: process_erst with cover only set to WARN and all others set to OK
4143+ pjlink.process_erst(chk_param)
4144+
4145+ # THEN: Only COVER should have an error
4146+ self.assertEqual(len(pjlink.projector_errors), 1, 'projector_errors should only have 1 error')
4147+ self.assertTrue(('Cover' in pjlink.projector_errors), 'projector_errors should have an error for "Cover"')
4148+ self.assertEqual(pjlink.projector_errors['Cover'],
4149+ chk_string,
4150+ 'projector_errors["Cover"] should have error "{err}"'.format(err=chk_string))
4151+
4152+ def test_projector_process_inpt(self):
4153+ """
4154+ Test input source status shows current input
4155+ """
4156+ # GIVEN: Test object
4157+ pjlink = pjlink_test
4158+ pjlink.source = '0'
4159+
4160+ # WHEN: Called with input source
4161+ pjlink.process_inpt('1')
4162+
4163+ # THEN: Input selected should reflect current input
4164+ self.assertEqual(pjlink.source, '1', 'Input source should be set to "1"')
4165+
4166+ @patch.object(pjlink_test, 'projectorUpdateIcons')
4167+ @patch.object(openlp.core.projectors.pjlink, 'log')
4168+ def test_projector_process_inst(self, mock_log, mock_UpdateIcons):
4169+ """
4170+ Test saving video source available information
4171+ """
4172+ # GIVEN: Test object
4173+ pjlink = pjlink_test
4174+ pjlink.source_available = []
4175+ test_data = '21 10 30 31 11 20'
4176+ test_saved = ['10', '11', '20', '21', '30', '31']
4177+ log_data = '(127.0.0.1) Setting projector sources_available to ' \
4178+ '"[\'10\', \'11\', \'20\', \'21\', \'30\', \'31\']"'
4179+ mock_UpdateIcons.reset_mock()
4180+ mock_log.reset_mock()
4181+
4182+ # WHEN: process_inst called with test data
4183+ pjlink.process_inst(data=test_data)
4184+
4185+ # THEN: Data should have been sorted and saved properly
4186+ self.assertEqual(pjlink.source_available, test_saved, "Sources should have been sorted and saved")
4187+ mock_log.debug.assert_called_once_with(log_data)
4188+ self.assertTrue(mock_UpdateIcons.emit.called, 'Update Icons should have been called')
4189+
4190+ @patch.object(openlp.core.projectors.pjlink, 'log')
4191+ def test_projector_process_lamp_invalid(self, mock_log):
4192+ """
4193+ Test status multiple lamp on/off and hours
4194+ """
4195+ # GIVEN: Test object
4196+ pjlink = pjlink_test
4197+ pjlink.lamp = [{'Hours': 00000, 'On': True},
4198+ {'Hours': 11111, 'On': False}]
4199+ log_data = '(127.0.0.1) process_lamp(): Invalid data "11111 1 22222 0 333A3 1"'
4200+
4201+ # WHEN: Call process_command with invalid lamp data
4202+ pjlink.process_lamp('11111 1 22222 0 333A3 1')
4203+
4204+ # THEN: lamps should not have changed
4205+ self.assertEqual(len(pjlink.lamp), 2,
4206+ 'Projector should have kept 2 lamps specified')
4207+ self.assertEqual(pjlink.lamp[0]['On'], True,
4208+ 'Lamp 1 power status should have been set to TRUE')
4209+ self.assertEqual(pjlink.lamp[0]['Hours'], 00000,
4210+ 'Lamp 1 hours should have been left at 00000')
4211+ self.assertEqual(pjlink.lamp[1]['On'], False,
4212+ 'Lamp 2 power status should have been set to FALSE')
4213+ self.assertEqual(pjlink.lamp[1]['Hours'], 11111,
4214+ 'Lamp 2 hours should have been left at 11111')
4215+ mock_log.warning.assert_called_once_with(log_data)
4216+
4217+ def test_projector_process_lamp_multiple(self):
4218+ """
4219+ Test status multiple lamp on/off and hours
4220+ """
4221+ # GIVEN: Test object
4222+ pjlink = pjlink_test
4223+ pjlink.lamps = []
4224+
4225+ # WHEN: Call process_command with lamp data
4226+ pjlink.process_lamp('11111 1 22222 0 33333 1')
4227+
4228+ # THEN: Lamp should have been set with proper lamp status
4229+ self.assertEqual(len(pjlink.lamp), 3,
4230+ 'Projector should have 3 lamps specified')
4231+ self.assertEqual(pjlink.lamp[0]['On'], True,
4232+ 'Lamp 1 power status should have been set to TRUE')
4233+ self.assertEqual(pjlink.lamp[0]['Hours'], 11111,
4234+ 'Lamp 1 hours should have been set to 11111')
4235+ self.assertEqual(pjlink.lamp[1]['On'], False,
4236+ 'Lamp 2 power status should have been set to FALSE')
4237+ self.assertEqual(pjlink.lamp[1]['Hours'], 22222,
4238+ 'Lamp 2 hours should have been set to 22222')
4239+ self.assertEqual(pjlink.lamp[2]['On'], True,
4240+ 'Lamp 3 power status should have been set to TRUE')
4241+ self.assertEqual(pjlink.lamp[2]['Hours'], 33333,
4242+ 'Lamp 3 hours should have been set to 33333')
4243+
4244+ def test_projector_process_lamp_single(self):
4245+ """
4246+ Test status lamp on/off and hours
4247+ """
4248+ # GIVEN: Test object
4249+ pjlink = pjlink_test
4250+ pjlink.lamps = []
4251+
4252+ # WHEN: Call process_command with lamp data
4253+ pjlink.process_lamp('22222 1')
4254+
4255+ # THEN: Lamp should have been set with status=ON and hours=22222
4256+ self.assertEqual(pjlink.lamp[0]['On'], True,
4257+ 'Lamp power status should have been set to TRUE')
4258+ self.assertEqual(pjlink.lamp[0]['Hours'], 22222,
4259+ 'Lamp hours should have been set to 22222')
4260+
4261+ @patch.object(openlp.core.projectors.pjlink, 'log')
4262+ def test_projector_process_name(self, mock_log):
4263+ """
4264+ Test saving NAME data from projector
4265+ """
4266+ # GIVEN: Test data
4267+ pjlink = pjlink_test
4268+ test_data = "Some Name the End-User Set IN Projector"
4269+ test_log = '(127.0.0.1) Setting projector PJLink name to "Some Name the End-User Set IN Projector"'
4270+ mock_log.reset_mock()
4271+
4272+ # WHEN: process_name called with test data
4273+ pjlink.process_name(data=test_data)
4274+
4275+ # THEN: name should be set and logged
4276+ self.assertEqual(pjlink.pjlink_name, test_data, 'Name test data should have been saved')
4277+ mock_log.debug.assert_called_once_with(test_log)
4278+
4279+ @patch.object(pjlink_test, 'projectorUpdateIcons')
4280+ @patch.object(pjlink_test, 'send_command')
4281+ @patch.object(pjlink_test, 'change_status')
4282+ def test_projector_process_powr_on(self,
4283+ mock_change_status,
4284+ mock_send_command,
4285+ mock_UpdateIcons):
4286+ """
4287+ Test status power to ON
4288+ """
4289+ # GIVEN: Test object and preset
4290+ pjlink = pjlink_test
4291+ pjlink.power = S_STANDBY
4292+ test_data = PJLINK_POWR_STATUS[S_ON]
4293+
4294+ # WHEN: Call process_command with turn power on command
4295+ pjlink.process_command(cmd='POWR', data=test_data)
4296+
4297+ # THEN: Power should be set to ON
4298+ self.assertEqual(pjlink.power, S_ON, 'Power should have been set to ON')
4299+ mock_send_command.assert_called_once_with('INST')
4300+ mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])
4301+ self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')
4302+
4303+ @patch.object(pjlink_test, 'projectorUpdateIcons')
4304+ @patch.object(pjlink_test, 'send_command')
4305+ @patch.object(pjlink_test, 'change_status')
4306+ def test_projector_process_powr_invalid(self,
4307+ mock_change_status,
4308+ mock_send_command,
4309+ mock_UpdateIcons):
4310+ """
4311+ Test process_powr invalid call
4312+ """
4313+ # GIVEN: Test object and preset
4314+ pjlink = pjlink_test
4315+ pjlink.power = S_STANDBY
4316+ test_data = '99'
4317+
4318+ # WHEN: Call process_command with turn power on command
4319+ pjlink.process_command(cmd='POWR', data=test_data)
4320+
4321+ # THEN: Power should be set to ON
4322+ self.assertEqual(pjlink.power, S_STANDBY, 'Power should not have changed')
4323+ self.assertFalse(mock_change_status.called, 'Change status should not have been called')
4324+ self.assertFalse(mock_send_command.called, 'send_command("INST") should not have been called')
4325+ self.assertFalse(mock_UpdateIcons.emit.called, 'projectorUpdateIcons should not have been called')
4326+
4327+ @patch.object(pjlink_test, 'projectorUpdateIcons')
4328+ @patch.object(pjlink_test, 'send_command')
4329+ @patch.object(pjlink_test, 'change_status')
4330+ def test_projector_process_powr_off(self,
4331+ mock_change_status,
4332+ mock_send_command,
4333+ mock_UpdateIcons):
4334+ """
4335+ Test status power to STANDBY
4336+ """
4337+ # GIVEN: Test object and preset
4338+ pjlink = pjlink_test
4339+ pjlink.power = S_ON
4340+ test_data = PJLINK_POWR_STATUS[S_STANDBY]
4341+
4342+ # WHEN: Call process_command with turn power on command
4343+ pjlink.process_command(cmd='POWR', data=test_data)
4344+
4345+ # THEN: Power should be set to STANDBY
4346+ self.assertEqual(pjlink.power, S_STANDBY, 'Power should have been set to STANDBY')
4347+ self.assertEqual(mock_UpdateIcons.emit.called, True, 'projectorUpdateIcons should have been called')
4348+ mock_change_status.assert_called_once_with(PJLINK_POWR_STATUS[test_data])
4349+ self.assertFalse(mock_send_command.called, "send_command['INST'] should not have been called")
4350+
4351+ def test_projector_process_rfil_save(self):
4352+ """
4353+ Test saving filter type
4354+ """
4355+ # GIVEN: Test object
4356+ pjlink = pjlink_test
4357+ pjlink.model_filter = None
4358+ filter_model = 'Filter Type Test'
4359+
4360+ # WHEN: Filter model is received
4361+ pjlink.process_rfil(data=filter_model)
4362+
4363+ # THEN: Filter model number should be saved
4364+ self.assertEqual(pjlink.model_filter, filter_model, 'Filter type should have been saved')
4365+
4366+ def test_projector_process_rfil_nosave(self):
4367+ """
4368+ Test saving filter type previously saved
4369+ """
4370+ # GIVEN: Test object
4371+ pjlink = pjlink_test
4372+ pjlink.model_filter = 'Old filter type'
4373+ filter_model = 'Filter Type Test'
4374+
4375+ # WHEN: Filter model is received
4376+ pjlink.process_rfil(data=filter_model)
4377+
4378+ # THEN: Filter model number should be saved
4379+ self.assertNotEquals(pjlink.model_filter, filter_model, 'Filter type should NOT have been saved')
4380+
4381+ def test_projector_process_rlmp_save(self):
4382+ """
4383+ Test saving lamp type
4384+ """
4385+ # GIVEN: Test object
4386+ pjlink = pjlink_test
4387+ pjlink.model_lamp = None
4388+ lamp_model = 'Lamp Type Test'
4389+
4390+ # WHEN: Filter model is received
4391+ pjlink.process_rlmp(data=lamp_model)
4392+
4393+ # THEN: Filter model number should be saved
4394+ self.assertEqual(pjlink.model_lamp, lamp_model, 'Lamp type should have been saved')
4395+
4396+ def test_projector_process_rlmp_nosave(self):
4397+ """
4398+ Test saving lamp type previously saved
4399+ """
4400+ # GIVEN: Test object
4401+ pjlink = pjlink_test
4402+ pjlink.model_lamp = 'Old lamp type'
4403+ lamp_model = 'Filter Type Test'
4404+
4405+ # WHEN: Filter model is received
4406+ pjlink.process_rlmp(data=lamp_model)
4407+
4408+ # THEN: Filter model number should be saved
4409+ self.assertNotEquals(pjlink.model_lamp, lamp_model, 'Lamp type should NOT have been saved')
4410+
4411+ def test_projector_process_snum_set(self):
4412+ """
4413+ Test saving serial number from projector
4414+ """
4415+ # GIVEN: Test object
4416+ pjlink = pjlink_test
4417+ pjlink.serial_no = None
4418+ test_number = 'Test Serial Number'
4419+
4420+ # WHEN: No serial number is set and we receive serial number command
4421+ pjlink.process_snum(data=test_number)
4422+
4423+ # THEN: Serial number should be set
4424+ self.assertEqual(pjlink.serial_no, test_number,
4425+ 'Projector serial number should have been set')
4426+
4427+ def test_projector_process_snum_different(self):
4428+ """
4429+ Test projector serial number different than saved serial number
4430+ """
4431+ # GIVEN: Test object
4432+ pjlink = pjlink_test
4433+ pjlink.serial_no = 'Previous serial number'
4434+ test_number = 'Test Serial Number'
4435+
4436+ # WHEN: No serial number is set and we receive serial number command
4437+ pjlink.process_snum(data=test_number)
4438+
4439+ # THEN: Serial number should be set
4440+ self.assertNotEquals(pjlink.serial_no, test_number,
4441+ 'Projector serial number should NOT have been set')
4442+
4443+ @patch.object(openlp.core.projectors.pjlink, 'log')
4444+ def test_projector_process_sver(self, mock_log):
4445+ """
4446+ Test invalid software version information - too long
4447+ """
4448+ # GIVEN: Test object
4449+ pjlink = pjlink_test
4450+ pjlink.sw_version = None
4451+ pjlink.sw_version_received = None
4452+ test_data = 'Test 1 Subtest 1'
4453+ test_log = "(127.0.0.1) Setting projector software version to 'Test 1 Subtest 1'"
4454+ mock_log.reset_mock()
4455+
4456+ # WHEN: process_sver called with invalid data
4457+ pjlink.process_sver(data=test_data)
4458+
4459+ # THEN: Version information should not change
4460+ self.assertEqual(pjlink.sw_version, test_data, 'Software version should have been updated')
4461+ self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')
4462+ mock_log.debug.assert_called_once_with(test_log)
4463+
4464+ @patch.object(openlp.core.projectors.pjlink, 'log')
4465+ def test_projector_process_sver_changed(self, mock_log):
4466+ """
4467+ Test invalid software version information - Received different than saved
4468+ """
4469+ # GIVEN: Test object
4470+ pjlink = pjlink_test
4471+ test_data_new = 'Test 1 Subtest 2'
4472+ test_data_old = 'Test 1 Subtest 1'
4473+ pjlink.sw_version = test_data_old
4474+ pjlink.sw_version_received = None
4475+ test_log = '(127.0.0.1) Saving new serial number as sw_version_received'
4476+ mock_log.reset_mock()
4477+
4478+ # WHEN: process_sver called with invalid data
4479+ pjlink.process_sver(data=test_data_new)
4480+
4481+ # THEN: Version information should not change
4482+ self.assertEqual(pjlink.sw_version, test_data_old, 'Software version should not have been updated')
4483+ self.assertEqual(pjlink.sw_version_received, test_data_new,
4484+ 'Received software version should have been changed')
4485+ self.assertEqual(mock_log.warning.call_count, 4, 'log.warn should have been called 4 times')
4486+ # There was 4 calls, but only the last one is checked with this method
4487+ mock_log.warning.assert_called_with(test_log)
4488+
4489+ @patch.object(openlp.core.projectors.pjlink, 'log')
4490+ def test_projector_process_sver_invalid(self, mock_log):
4491+ """
4492+ Test invalid software version information - too long
4493+ """
4494+ # GIVEN: Test object
4495+ pjlink = pjlink_test
4496+ pjlink.sw_version = None
4497+ pjlink.sw_version_received = None
4498+ test_data = 'This is a test software version line that is too long based on PJLink version 2 specs'
4499+ test_log = "Invalid software version - too long"
4500+ mock_log.reset_mock()
4501+
4502+ # WHEN: process_sver called with invalid data
4503+ pjlink.process_sver(data=test_data)
4504+
4505+ # THEN: Version information should not change
4506+ self.assertIsNone(pjlink.sw_version, 'Software version should not have changed')
4507+ self.assertIsNone(pjlink.sw_version_received, 'Received software version should not have changed')
4508+ mock_log.warning.assert_called_once_with(test_log)
4509+
4510+ def test_projector_reset_information(self):
4511+ """
4512+ Test reset_information() resets all information and stops timers
4513+ """
4514+ # GIVEN: Test object and test data
4515+ pjlink = pjlink_test
4516+ pjlink.power = S_ON
4517+ pjlink.pjlink_name = 'OPENLPTEST'
4518+ pjlink.manufacturer = 'PJLINK'
4519+ pjlink.model = '1'
4520+ pjlink.shutter = True
4521+ pjlink.mute = True
4522+ pjlink.lamp = True
4523+ pjlink.fan = True
4524+ pjlink.source_available = True
4525+ pjlink.other_info = 'ANOTHER TEST'
4526+ pjlink.send_queue = True
4527+ pjlink.send_busy = True
4528+
4529+ # WHEN: reset_information() is called
4530+ with patch.object(pjlink, 'timer') as mock_timer:
4531+ with patch.object(pjlink, 'socket_timer') as mock_socket_timer:
4532+ pjlink.reset_information()
4533+
4534+ # THEN: All information should be reset and timers stopped
4535+ self.assertEqual(pjlink.power, S_OFF, 'Projector power should be OFF')
4536+ self.assertIsNone(pjlink.pjlink_name, 'Projector pjlink_name should be None')
4537+ self.assertIsNone(pjlink.manufacturer, 'Projector manufacturer should be None')
4538+ self.assertIsNone(pjlink.model, 'Projector model should be None')
4539+ self.assertIsNone(pjlink.shutter, 'Projector shutter should be None')
4540+ self.assertIsNone(pjlink.mute, 'Projector shuttter should be None')
4541+ self.assertIsNone(pjlink.lamp, 'Projector lamp should be None')
4542+ self.assertIsNone(pjlink.fan, 'Projector fan should be None')
4543+ self.assertIsNone(pjlink.source_available, 'Projector source_available should be None')
4544+ self.assertIsNone(pjlink.source, 'Projector source should be None')
4545+ self.assertIsNone(pjlink.other_info, 'Projector other_info should be None')
4546+ self.assertEqual(pjlink.send_queue, [], 'Projector send_queue should be an empty list')
4547+ self.assertFalse(pjlink.send_busy, 'Projector send_busy should be False')
4548+ self.assertTrue(mock_timer.stop.called, 'Projector timer.stop() should have been called')
4549+ self.assertTrue(mock_socket_timer.stop.called, 'Projector socket_timer.stop() should have been called')
4550
4551=== modified file 'tests/interfaces/openlp_core/ui/test_projectoreditform.py'
4552--- tests/interfaces/openlp_core/ui/test_projectoreditform.py 2017-10-07 07:05:07 +0000
4553+++ tests/interfaces/openlp_core/ui/test_projectoreditform.py 2017-11-17 06:06:50 +0000
4554@@ -20,7 +20,7 @@
4555 # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
4556 ###############################################################################
4557 """
4558-Interface tests to test the openlp.core.ui.projector.editform.ProjectorEditForm()
4559+Interface tests to test the openlp.core.projectors.editform.ProjectorEditForm()
4560 class and methods.
4561 """
4562 import os
4563@@ -28,8 +28,9 @@
4564 from unittest.mock import patch
4565
4566 from openlp.core.common.registry import Registry
4567-from openlp.core.lib.projector.db import Projector, ProjectorDB
4568-from openlp.core.ui import ProjectorEditForm
4569+from openlp.core.projectors.db import Projector, ProjectorDB
4570+from openlp.core.projectors.editform import ProjectorEditForm
4571+from openlp.core.projectors.manager import ProjectorManager
4572
4573 from tests.helpers.testmixin import TestMixin
4574 from tests.resources.projector.data import TEST_DB, TEST1_DATA, TEST2_DATA
4575@@ -48,7 +49,7 @@
4576 self.setup_application()
4577 self.build_settings()
4578 Registry.create()
4579- with patch('openlp.core.lib.projector.db.init_url') as mocked_init_url:
4580+ with patch('openlp.core.projectors.db.init_url') as mocked_init_url:
4581 if os.path.exists(TEST_DB):
4582 os.unlink(TEST_DB)
4583 mocked_init_url.return_value = 'sqlite:///' + TEST_DB
4584@@ -66,7 +67,7 @@
4585 del self.projector_form
4586 self.destroy_settings()
4587
4588- @patch('openlp.core.ui.projector.editform.QtWidgets.QDialog.exec')
4589+ @patch('openlp.core.projectors.editform.QtWidgets.QDialog.exec')
4590 def test_edit_form_add_projector(self, mocked_exec):
4591 """
4592 Test projector edit form with no parameters creates a new entry.
4593@@ -84,7 +85,7 @@
4594 self.assertTrue((item.ip is None and item.name is None),
4595 'Projector edit form should have a new Projector() instance to edit')
4596
4597- @patch('openlp.core.ui.projector.editform.QtWidgets.QDialog.exec')
4598+ @patch('openlp.core.projectors.editform.QtWidgets.QDialog.exec')
4599 def test_edit_form_edit_projector(self, mocked_exec):
4600 """
4601 Test projector edit form with existing projector entry
4602
4603=== modified file 'tests/interfaces/openlp_core/ui/test_projectormanager.py'
4604--- tests/interfaces/openlp_core/ui/test_projectormanager.py 2017-11-03 22:52:24 +0000
4605+++ tests/interfaces/openlp_core/ui/test_projectormanager.py 2017-11-17 06:06:50 +0000
4606@@ -27,8 +27,9 @@
4607 from unittest.mock import patch, MagicMock
4608
4609 from openlp.core.common.registry import Registry
4610-from openlp.core.ui import ProjectorManager, ProjectorEditForm
4611-from openlp.core.lib.projector.db import ProjectorDB
4612+from openlp.core.projectors.db import ProjectorDB
4613+from openlp.core.projectors.editform import ProjectorEditForm
4614+from openlp.core.projectors.manager import ProjectorManager
4615
4616 from tests.helpers.testmixin import TestMixin
4617 from tests.resources.projector.data import TEST_DB
4618@@ -45,7 +46,7 @@
4619 self.setup_application()
4620 self.build_settings()
4621 Registry.create()
4622- with patch('openlp.core.lib.projector.db.init_url') as mocked_init_url:
4623+ with patch('openlp.core.projectors.db.init_url') as mocked_init_url:
4624 if os.path.exists(TEST_DB):
4625 os.unlink(TEST_DB)
4626 mocked_init_url.return_value = 'sqlite:///%s' % TEST_DB
4627
4628=== modified file 'tests/interfaces/openlp_core/ui/test_projectorsourceform.py'
4629--- tests/interfaces/openlp_core/ui/test_projectorsourceform.py 2017-11-03 22:52:24 +0000
4630+++ tests/interfaces/openlp_core/ui/test_projectorsourceform.py 2017-11-17 06:06:50 +0000
4631@@ -32,9 +32,9 @@
4632 from PyQt5.QtWidgets import QDialog
4633
4634 from openlp.core.common.registry import Registry
4635-from openlp.core.lib.projector.db import ProjectorDB, Projector
4636-from openlp.core.lib.projector.constants import PJLINK_DEFAULT_CODES, PJLINK_DEFAULT_SOURCES
4637-from openlp.core.ui.projector.sourceselectform import source_group, SourceSelectSingle
4638+from openlp.core.projectors.db import ProjectorDB, Projector
4639+from openlp.core.projectors.constants import PJLINK_DEFAULT_CODES, PJLINK_DEFAULT_SOURCES
4640+from openlp.core.projectors.sourceselectform import source_group, SourceSelectSingle
4641
4642 from tests.helpers.testmixin import TestMixin
4643 from tests.resources.projector.data import TEST_DB, TEST1_DATA
4644@@ -58,7 +58,7 @@
4645 """
4646 Test class for the Projector Source Select form module
4647 """
4648- @patch('openlp.core.lib.projector.db.init_url')
4649+ @patch('openlp.core.projectors.db.init_url')
4650 def setUp(self, mocked_init_url):
4651 """
4652 Set up anything necessary for all tests