Merge lp:~alisonken1/openlp/bug-1734275 into lp:openlp

Proposed by Ken Roberts
Status: Merged
Merged at revision: 2791
Proposed branch: lp:~alisonken1/openlp/bug-1734275
Merge into: lp:openlp
Diff against target: 312 lines (+156/-98)
5 files modified
openlp/core/projectors/manager.py (+7/-5)
openlp/core/projectors/pjlink.py (+14/-11)
tests/functional/openlp_core/projectors/test_projector_bugfixes_01.py (+134/-0)
tests/functional/openlp_core/projectors/test_projector_pjlink_base.py (+1/-53)
tests/functional/openlp_core/projectors/test_projector_pjlink_commands.py (+0/-29)
To merge this branch: bzr merge lp:~alisonken1/openlp/bug-1734275
Reviewer Review Type Date Requested Status
Tim Bentley Pending
Phill Pending
Review via email: mp+334265@code.launchpad.net

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

Commit message

Bugfix 1734275 - PJLink non-standard response to LAMP command

Description of the change

- Fix non-standard LAMP response (bug 1734275)
- Moved bugfix tests to separate file
- Added test for non-standard LAMP response
- Refactor mocks
- Cleanups

--------------------------------------------------------------------------------
lp:~alisonken1/openlp/bug-1734275 (revision 2792)
https://ci.openlp.io/job/Branch-01-Pull/2312/ [SUCCESS]
https://ci.openlp.io/job/Branch-02-Functional-Tests/2213/ [SUCCESS]
https://ci.openlp.io/job/Branch-03-Interface-Tests/2089/ [SUCCESS]
https://ci.openlp.io/job/Branch-04a-Code_Analysis/1415/ [SUCCESS]
https://ci.openlp.io/job/Branch-04b-Test_Coverage/1237/ [SUCCESS]
https://ci.openlp.io/job/Branch-04c-Code_Analysis2/367/ [SUCCESS]
https://ci.openlp.io/job/Branch-05-AppVeyor-Tests/198/ [FAILURE]

To post a comment you must log in.
Revision history for this message
Phill (phill-ridout) wrote : Posted in a previous version of this proposal

A few inline comments, nothing major Sorry if it seems like I be tripping on my new status! :-p

review: Needs Fixing
Revision history for this message
Tim Bentley (trb143) : Posted in a previous version of this proposal
review: Approve
Revision history for this message
Phill (phill-ridout) wrote : Posted in a previous version of this proposal

You've just missed removing the pjlink instance in the test file. (see inline)

Revision history for this message
Phill (phill-ridout) : Posted in a previous version of this proposal
review: Needs Fixing
Revision history for this message
Phill (phill-ridout) : Posted in a previous version of this proposal
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/projectors/manager.py'
2--- openlp/core/projectors/manager.py 2017-11-10 11:59:38 +0000
3+++ openlp/core/projectors/manager.py 2017-11-24 19:16:10 +0000
4@@ -672,14 +672,16 @@
5 data=projector.model_filter)
6 count = 1
7 for item in projector.link.lamp:
8+ if item['On'] is None:
9+ status = translate('OpenLP.ProjectorManager', 'Unavailable')
10+ elif item['On']:
11+ status = translate('OpenLP.ProjectorManager', 'ON')
12+ else:
13+ status = translate('OpenLP.ProjectorManager', 'OFF')
14 message += '<b>{title} {count}</b> {status} '.format(title=translate('OpenLP.ProjectorManager',
15 'Lamp'),
16 count=count,
17- status=translate('OpenLP.ProjectorManager',
18- 'ON')
19- if item['On']
20- else translate('OpenLP.ProjectorManager',
21- 'OFF'))
22+ status=status)
23
24 message += '<b>{title}</b>: {hours}<br />'.format(title=translate('OpenLP.ProjectorManager', 'Hours'),
25 hours=item['Hours'])
26
27=== modified file 'openlp/core/projectors/pjlink.py'
28--- openlp/core/projectors/pjlink.py 2017-11-10 11:59:38 +0000
29+++ openlp/core/projectors/pjlink.py 2017-11-24 19:16:10 +0000
30@@ -402,17 +402,20 @@
31 :param data: Lamp(s) status.
32 """
33 lamps = []
34- data_dict = data.split()
35- while data_dict:
36- try:
37- fill = {'Hours': int(data_dict[0]), 'On': False if data_dict[1] == '0' else True}
38- except ValueError:
39- # In case of invalid entry
40- log.warning('({ip}) process_lamp(): Invalid data "{data}"'.format(ip=self.ip, data=data))
41- return
42- lamps.append(fill)
43- data_dict.pop(0) # Remove lamp hours
44- data_dict.pop(0) # Remove lamp on/off
45+ lamp_list = data.split()
46+ if len(lamp_list) < 2:
47+ lamps.append({'Hours': int(lamp_list[0]), 'On': None})
48+ else:
49+ while lamp_list:
50+ try:
51+ fill = {'Hours': int(lamp_list[0]), 'On': False if lamp_list[1] == '0' else True}
52+ except ValueError:
53+ # In case of invalid entry
54+ log.warning('({ip}) process_lamp(): Invalid data "{data}"'.format(ip=self.ip, data=data))
55+ return
56+ lamps.append(fill)
57+ lamp_list.pop(0) # Remove lamp hours
58+ lamp_list.pop(0) # Remove lamp on/off
59 self.lamp = lamps
60 return
61
62
63=== added file 'tests/functional/openlp_core/projectors/test_projector_bugfixes_01.py'
64--- tests/functional/openlp_core/projectors/test_projector_bugfixes_01.py 1970-01-01 00:00:00 +0000
65+++ tests/functional/openlp_core/projectors/test_projector_bugfixes_01.py 2017-11-24 19:16:10 +0000
66@@ -0,0 +1,134 @@
67+# -*- coding: utf-8 -*-
68+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
69+
70+###############################################################################
71+# OpenLP - Open Source Lyrics Projection #
72+# --------------------------------------------------------------------------- #
73+# Copyright (c) 2008-2015 OpenLP Developers #
74+# --------------------------------------------------------------------------- #
75+# This program is free software; you can redistribute it and/or modify it #
76+# under the terms of the GNU General Public License as published by the Free #
77+# Software Foundation; version 2 of the License. #
78+# #
79+# This program is distributed in the hope that it will be useful, but WITHOUT #
80+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
81+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
82+# more details. #
83+# #
84+# You should have received a copy of the GNU General Public License along #
85+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
86+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
87+###############################################################################
88+"""
89+Package to test the openlp.core.projectors.pjlink base package.
90+"""
91+from unittest import TestCase
92+from unittest.mock import patch
93+
94+from openlp.core.projectors.db import Projector
95+from openlp.core.projectors.pjlink import PJLink
96+
97+from tests.resources.projector.data import TEST_PIN, TEST_CONNECT_AUTHENTICATE, TEST_HASH, TEST1_DATA
98+
99+
100+class TestPJLinkBugs(TestCase):
101+ """
102+ Tests for the PJLink module bugfixes
103+ """
104+ def setUp(self):
105+ '''
106+ Initialization
107+ '''
108+ self.pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True)
109+
110+ def tearDown(self):
111+ '''
112+ Cleanups
113+ '''
114+ self.pjlink_test = None
115+
116+ def test_bug_1550891_process_clss_nonstandard_reply_1(self):
117+ """
118+ Bugfix 1550891: CLSS request returns non-standard reply with Optoma/Viewsonic projector
119+ """
120+ # GIVEN: Test object
121+ pjlink = self.pjlink_test
122+
123+ # WHEN: Process non-standard reply
124+ pjlink.process_clss('Class 1')
125+
126+ # THEN: Projector class should be set with proper value
127+ self.assertEqual(pjlink.pjlink_class, '1',
128+ 'Non-standard class reply should have set class=1')
129+
130+ def test_bug_1550891_process_clss_nonstandard_reply_2(self):
131+ """
132+ Bugfix 1550891: CLSS request returns non-standard reply with BenQ projector
133+ """
134+ # GIVEN: Test object
135+ pjlink = self.pjlink_test
136+
137+ # WHEN: Process non-standard reply
138+ pjlink.process_clss('Version2')
139+
140+ # THEN: Projector class should be set with proper value
141+ # NOTE: At this time BenQ is Class 1, but we're trying a different value to verify
142+ self.assertEqual(pjlink.pjlink_class, '2',
143+ 'Non-standard class reply should have set class=2')
144+
145+ def test_bug_1593882_no_pin_authenticated_connection(self):
146+ """
147+ Test bug 1593882 no pin and authenticated request exception
148+ """
149+ # GIVEN: Test object and mocks
150+ mock_socket_timer = patch.object(self.pjlink_test, 'socket_timer').start()
151+ mock_timer = patch.object(self.pjlink_test, 'timer').start()
152+ mock_authentication = patch.object(self.pjlink_test, 'projectorAuthentication').start()
153+ mock_ready_read = patch.object(self.pjlink_test, 'waitForReadyRead').start()
154+ mock_send_command = patch.object(self.pjlink_test, 'send_command').start()
155+ pjlink = self.pjlink_test
156+ pjlink.pin = None
157+ mock_ready_read.return_value = True
158+
159+ # WHEN: call with authentication request and pin not set
160+ pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
161+
162+ # THEN: 'No Authentication' signal should have been sent
163+ mock_authentication.emit.assert_called_with(pjlink.ip)
164+
165+ def test_bug_1593883_pjlink_authentication(self):
166+ """
167+ Test bugfix 1593883 pjlink authentication
168+ """
169+ # GIVEN: Test object and data
170+ mock_socket_timer = patch.object(self.pjlink_test, 'socket_timer').start()
171+ mock_timer = patch.object(self.pjlink_test, 'timer').start()
172+ mock_send_command = patch.object(self.pjlink_test, 'write').start()
173+ mock_state = patch.object(self.pjlink_test, 'state').start()
174+ mock_waitForReadyRead = patch.object(self.pjlink_test, 'waitForReadyRead').start()
175+ pjlink = self.pjlink_test
176+ pjlink.pin = TEST_PIN
177+ mock_state.return_value = pjlink.ConnectedState
178+ mock_waitForReadyRead.return_value = True
179+
180+ # WHEN: Athenticated connection is called
181+ pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
182+
183+ # THEN: send_command should have the proper authentication
184+ self.assertEqual("{test}".format(test=mock_send_command.call_args),
185+ "call(b'{hash}%1CLSS ?\\r')".format(hash=TEST_HASH))
186+
187+ def test_bug_1734275_process_lamp_nonstandard_reply(self):
188+ """
189+ Test bugfix 17342785 non-standard LAMP response
190+ """
191+ # GIVEN: Test object
192+ pjlink = self.pjlink_test
193+
194+ # WHEN: Process lamp command called with only hours and no lamp power state
195+ pjlink.process_lamp("45")
196+
197+ # THEN: Lamp should show hours as 45 and lamp power as Unavailable
198+ self.assertEqual(len(pjlink.lamp), 1, 'There should only be 1 lamp available')
199+ self.assertEqual(pjlink.lamp[0]['Hours'], 45, 'Lamp hours should have equalled 45')
200+ self.assertIsNone(pjlink.lamp[0]['On'], 'Lamp power should be "None"')
201
202=== modified file 'tests/functional/openlp_core/projectors/test_projector_pjlink_base.py'
203--- tests/functional/openlp_core/projectors/test_projector_pjlink_base.py 2017-11-16 23:53:53 +0000
204+++ tests/functional/openlp_core/projectors/test_projector_pjlink_base.py 2017-11-24 19:16:10 +0000
205@@ -29,7 +29,7 @@
206 from openlp.core.projectors.db import Projector
207 from openlp.core.projectors.pjlink import PJLink
208
209-from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE, TEST_HASH, TEST1_DATA
210+from tests.resources.projector.data import TEST_PIN, TEST_SALT, TEST_CONNECT_AUTHENTICATE, TEST1_DATA
211
212 pjlink_test = PJLink(Projector(**TEST1_DATA), no_poll=True)
213
214@@ -79,58 +79,6 @@
215 'change_status should have been called with "{}"'.format(
216 ERROR_STRING[E_PARAMETER]))
217
218- @patch.object(pjlink_test, 'send_command')
219- @patch.object(pjlink_test, 'waitForReadyRead')
220- @patch.object(pjlink_test, 'projectorAuthentication')
221- @patch.object(pjlink_test, 'timer')
222- @patch.object(pjlink_test, 'socket_timer')
223- def test_bug_1593882_no_pin_authenticated_connection(self,
224- mock_socket_timer,
225- mock_timer,
226- mock_authentication,
227- mock_ready_read,
228- mock_send_command):
229- """
230- Test bug 1593882 no pin and authenticated request exception
231- """
232- # GIVEN: Test object and mocks
233- pjlink = pjlink_test
234- pjlink.pin = None
235- mock_ready_read.return_value = True
236-
237- # WHEN: call with authentication request and pin not set
238- pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
239-
240- # THEN: 'No Authentication' signal should have been sent
241- mock_authentication.emit.assert_called_with(pjlink.ip)
242-
243- @patch.object(pjlink_test, 'waitForReadyRead')
244- @patch.object(pjlink_test, 'state')
245- @patch.object(pjlink_test, '_send_command')
246- @patch.object(pjlink_test, 'timer')
247- @patch.object(pjlink_test, 'socket_timer')
248- def test_bug_1593883_pjlink_authentication(self,
249- mock_socket_timer,
250- mock_timer,
251- mock_send_command,
252- mock_state,
253- mock_waitForReadyRead):
254- """
255- Test bugfix 1593883 pjlink authentication
256- """
257- # GIVEN: Test object and data
258- pjlink = pjlink_test
259- pjlink.pin = TEST_PIN
260- mock_state.return_value = pjlink.ConnectedState
261- mock_waitForReadyRead.return_value = True
262-
263- # WHEN: Athenticated connection is called
264- pjlink.check_login(data=TEST_CONNECT_AUTHENTICATE)
265-
266- # THEN: send_command should have the proper authentication
267- self.assertEqual("{test}".format(test=mock_send_command.call_args),
268- "call(data='{hash}%1CLSS ?\\r')".format(hash=TEST_HASH))
269-
270 @patch.object(pjlink_test, 'disconnect_from_host')
271 def test_socket_abort(self, mock_disconnect):
272 """
273
274=== modified file 'tests/functional/openlp_core/projectors/test_projector_pjlink_commands.py'
275--- tests/functional/openlp_core/projectors/test_projector_pjlink_commands.py 2017-11-16 23:53:53 +0000
276+++ tests/functional/openlp_core/projectors/test_projector_pjlink_commands.py 2017-11-24 19:16:10 +0000
277@@ -570,35 +570,6 @@
278 self.assertEqual(pjlink.pjlink_class, '2',
279 'Projector should have set class=2')
280
281- def test_projector_process_clss_nonstandard_reply_optoma(self):
282- """
283- Bugfix 1550891: CLSS request returns non-standard reply with Optoma projector
284- """
285- # GIVEN: Test object
286- pjlink = pjlink_test
287-
288- # WHEN: Process non-standard reply
289- pjlink.process_clss('Class 1')
290-
291- # THEN: Projector class should be set with proper value
292- self.assertEqual(pjlink.pjlink_class, '1',
293- 'Non-standard class reply should have set class=1')
294-
295- def test_projector_process_clss_nonstandard_reply_benq(self):
296- """
297- Bugfix 1550891: CLSS request returns non-standard reply with BenQ projector
298- """
299- # GIVEN: Test object
300- pjlink = pjlink_test
301-
302- # WHEN: Process non-standard reply
303- pjlink.process_clss('Version2')
304-
305- # THEN: Projector class should be set with proper value
306- # NOTE: At this time BenQ is Class 1, but we're trying a different value to verify
307- self.assertEqual(pjlink.pjlink_class, '2',
308- 'Non-standard class reply should have set class=2')
309-
310 @patch.object(openlp.core.projectors.pjlink, 'log')
311 def test_projector_process_clss_invalid_nan(self, mock_log):
312 """