1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import hashlib
import unittest
from pypjlink.projector import Projector, POWER_STATES
from .utils import MockProjSocket
NO_AUTH_RESPONSE = 'PJLINK 0\r'
class AuthenticationTC(unittest.TestCase):
def test_no_auth(self):
"""test detection of no auth projector"""
power_response = '%1POWR=1\r'
with MockProjSocket(NO_AUTH_RESPONSE + power_response) as mock_stream:
proj = Projector.from_address('projhost')
self.assertFalse(proj.authenticate(lambda: ''))
# since projector said no auth required, I shouldn't have written
# anything to it
self.assertFalse(mock_stream.write.called)
def test_auth(self):
"""test authentication"""
auth_response = 'PJLINK 1 00112233\r'
power_response = '%1POWR=1\r'
with MockProjSocket(auth_response + power_response) as mock_stream:
proj = Projector.from_address('projhost')
self.assertTrue(proj.authenticate(lambda: 'p'))
# test write of authentication
self.assertEqual(
mock_stream.written,
self._md5_auth_code('00112233', 'p') + '%1POWR ?\r')
def test_wrong_auth(self):
"""test failed authentication"""
response = (
'PJLINK 1 00112233\r'
'PJLINK ERRA\r'
)
with MockProjSocket(response) as mock_stream:
proj = Projector.from_address('projhost')
self.assertFalse(proj.authenticate(lambda: 'p'))
self.assertEqual(
mock_stream.written,
self._md5_auth_code('00112233', 'p') + '%1POWR ?\r')
def test_string_password(self):
"""since 1.1.1, password can be a string in authenticate() method"""
auth_response = 'PJLINK 1 00112244\r'
power_response = '%1POWR=1\r'
with MockProjSocket(auth_response + power_response) as mock_stream:
proj = Projector.from_address('projhost')
self.assertTrue(proj.authenticate('ps'))
# test write of authentication
self.assertEqual(
mock_stream.written,
self._md5_auth_code('00112244', 'ps') + '%1POWR ?\r')
def test_no_password_no_auth(self):
"""since 1.1.1, password can be omitted from authenticate() method
if projector doesn't need a password"""
power_response = '%1POWR=1\r'
with MockProjSocket(NO_AUTH_RESPONSE + power_response) as mock_stream:
proj = Projector.from_address('projhost')
self.assertFalse(proj.authenticate())
self.assertFalse(mock_stream.write.called)
def test_no_password_auth_required(self):
"""if projector needs a password but is missing in authenticate() there
should be an error"""
auth_response = 'PJLINK 1 00112255\r'
power_response = '%1POWR=1\r'
with MockProjSocket(auth_response + power_response) as mock_stream:
proj = Projector.from_address('projhost')
with self.assertRaises(RuntimeError):
proj.authenticate()
self.assertFalse(mock_stream.write.called)
def _md5_auth_code(self, salt, password):
return hashlib.md5((salt + password).encode('utf-8')).hexdigest()
class NameTC(unittest.TestCase):
def test_unicode(self):
"""test utf-8 chars in projector name"""
response = NO_AUTH_RESPONSE + '%1NAME=à€\r'
with MockProjSocket(response) as mock_stream:
proj = Projector.from_address('projhost')
proj.authenticate(lambda: '')
name = proj.get_name()
self.assertEqual(name, 'à€')
class PowerTC(unittest.TestCase):
def test_get(self):
response = NO_AUTH_RESPONSE + '%1POWR={}\r'.format(
POWER_STATES['cooling'])
with MockProjSocket(response) as mock_stream:
proj = Projector.from_address('projhost')
proj.authenticate(lambda: '')
self.assertEqual(proj.get_power(), 'cooling')
def test_set(self):
response = NO_AUTH_RESPONSE + '%1POWR=OK\r'
with MockProjSocket(response) as mock_stream:
proj = Projector.from_address('projhost')
proj.authenticate(lambda: '')
proj.set_power('off')
self.assertEqual(
mock_stream.written, '%1POWR {}\r'.format(POWER_STATES['off']))
|