|
|
|
import sys
|
|
|
|
from unittest import TestCase
|
|
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
from io import StringIO
|
|
|
|
|
|
|
|
|
|
|
|
class USBError(BaseException):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class Test(TestCase):
|
|
|
|
def setUp(self):
|
|
|
|
print("Real platform: " + sys.platform)
|
|
|
|
|
|
|
|
@patch('sys.platform', new='linux')
|
|
|
|
def test_list(self):
|
|
|
|
method, output = self.call_find(True, True, True, 'list', 'auto')
|
|
|
|
self.assertIn("Available write methods:", output)
|
|
|
|
self.assertIn("'auto'", output)
|
|
|
|
self.assertIn("'hidapi'", output)
|
|
|
|
self.assertIn("'libusb'", output)
|
|
|
|
|
|
|
|
method, output = self.call_find(True, True, True, 'hidapi', 'list')
|
|
|
|
self.assertIn("Known device ids with method 'hidapi' are:", output)
|
|
|
|
self.assertIn("'3-4:5-6': HidApi Test", output)
|
|
|
|
|
|
|
|
method, output = self.call_find(True, True, True, 'libusb', 'list')
|
|
|
|
self.assertIn("Known device ids with method 'libusb' are:", output)
|
|
|
|
self.assertIn("'3:4:2': LibUsb Test", output)
|
|
|
|
|
|
|
|
@patch('sys.platform', new='linux')
|
|
|
|
def test_unknown(self):
|
|
|
|
method, output = self.call_find(True, True, True, 'hello', 'auto')
|
|
|
|
self.assertIn("Unknown write method 'hello'", output)
|
|
|
|
self.assertIn("Available write methods:", output)
|
|
|
|
|
|
|
|
@patch('sys.platform', new='linux')
|
|
|
|
def test_all_in_linux_positive(self):
|
|
|
|
method, output = self.call_find(True, True, True, 'auto', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(True, True, True, 'libusb', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(True, True, True, 'hidapi', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
@patch('sys.platform', new='linux')
|
|
|
|
def test_only_one_lib_linux_positive(self):
|
|
|
|
method, output = self.call_find(False, True, True, 'auto', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(False, True, True, 'hidapi', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(True, False, True, 'auto', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(True, False, True, 'libusb', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
@patch('sys.platform', new='windows')
|
|
|
|
def test_windows_positive(self):
|
|
|
|
method, output = self.call_find(True, False, True, 'auto', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(True, False, True, 'libusb', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
@patch('sys.platform', new='darwin')
|
|
|
|
def test_macos_positive(self):
|
|
|
|
method, output = self.call_find(False, True, True, 'auto', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(False, True, True, 'hidapi', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
@patch('sys.version_info', new=[2])
|
|
|
|
def test_python2_positive(self):
|
|
|
|
method, output = self.call_find(True, True, True, 'auto', 'auto')
|
|
|
|
self.assertIn('device initialized', output)
|
|
|
|
self.assertIn('Preferring method libusb', output)
|
|
|
|
self.assertIsNotNone(method)
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
@patch('sys.platform', new='linux')
|
|
|
|
def test_all_in_linux_negative(self):
|
|
|
|
method, output = self.call_find(True, True, False, 'auto', 'auto')
|
|
|
|
self.assertNotIn('device initialized', output)
|
|
|
|
self.assertIn('device is not available', output)
|
|
|
|
self.assertIsNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(True, True, False, 'libusb', 'auto')
|
|
|
|
self.assertNotIn('device initialized', output)
|
|
|
|
self.assertIn('device is not available', output)
|
|
|
|
self.assertIsNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(True, True, False, 'hidapi', 'auto')
|
|
|
|
self.assertNotIn('device initialized', output)
|
|
|
|
self.assertIn('device is not available', output)
|
|
|
|
self.assertIsNone(method)
|
|
|
|
|
|
|
|
@patch('sys.platform', new='linux')
|
|
|
|
def test_all_out_linux_negative(self):
|
|
|
|
method, output = self.call_find(False, False, False, 'auto', 'auto')
|
|
|
|
self.assertNotIn('device initialized', output)
|
|
|
|
self.assertIn('One of the python packages', output)
|
|
|
|
self.assertIsNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(False, False, False, 'libusb', 'auto')
|
|
|
|
self.assertNotIn('device initialized', output)
|
|
|
|
self.assertIn('is not possible to be used', output)
|
|
|
|
self.assertIsNone(method)
|
|
|
|
|
|
|
|
method, output = self.call_find(False, False, False, 'hidapi', 'auto')
|
|
|
|
self.assertNotIn('device initialized', output)
|
|
|
|
self.assertIn('is not possible to be used', output)
|
|
|
|
self.assertIsNone(method)
|
|
|
|
|
|
|
|
@patch('sys.platform', new='windows')
|
|
|
|
def test_windows_negative(self):
|
|
|
|
method, output = self.call_find(True, False, True, 'hidapi', 'auto')
|
|
|
|
self.assertNotIn('device initialized', output)
|
|
|
|
self.assertIn('please use method', output)
|
|
|
|
self.assertIsNone(method)
|
|
|
|
|
|
|
|
@patch('sys.platform', new='darwin')
|
|
|
|
def test_macos_negative(self):
|
|
|
|
method, output = self.call_find(False, True, True, 'libusb', 'auto')
|
|
|
|
self.assertNotIn('device initialized', output)
|
|
|
|
self.assertIn('please use method', output)
|
|
|
|
self.assertIsNone(method)
|
|
|
|
|
|
|
|
@patch('sys.version_info', new=[2])
|
|
|
|
def test_python2_negative(self):
|
|
|
|
method, output = self.call_find(True, True, True, 'hidapi', 'auto')
|
|
|
|
self.assertNotIn('device initialized', output)
|
|
|
|
self.assertIn('Please use method', output)
|
|
|
|
self.assertIsNone(method)
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def test_get_methods(self):
|
|
|
|
methods, output = self.call_info_methods()
|
|
|
|
self.assertDictEqual({
|
|
|
|
'hidapi': True,
|
|
|
|
'libusb': True}, methods)
|
|
|
|
|
|
|
|
def test_get_device_ids(self):
|
|
|
|
device_ids, output = self.call_info_ids('libusb')
|
|
|
|
self.assertDictEqual({
|
|
|
|
'3:4:2': 'LibUsb Test Manufacturer - LibUsb Test Product (bus=3 dev=4 endpoint=2)'},
|
|
|
|
device_ids)
|
|
|
|
|
|
|
|
device_ids, output = self.call_info_ids('hidapi')
|
|
|
|
self.assertDictEqual({
|
|
|
|
'3-4:5-6': 'HidApi Test Manufacturer - HidApi Test Product (if=0)'},
|
|
|
|
device_ids)
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
def call_find(self, pyusb_available, pyhidapi_available, device_available, method, device_id):
|
|
|
|
self.print_test_conditions(pyusb_available, pyhidapi_available, device_available, method, device_id)
|
|
|
|
method_obj, output = self.prepare_modules(pyusb_available, pyhidapi_available, device_available,
|
|
|
|
lambda m: m._find_write_method(method, device_id))
|
|
|
|
self.assertEqual(pyusb_available, 'usb.core detected' in output)
|
|
|
|
self.assertEqual(pyhidapi_available, 'pyhidapi detected' in output)
|
|
|
|
return method_obj, output
|
|
|
|
|
|
|
|
def call_info_methods(self):
|
|
|
|
self.print_test_conditions(True, True, True, '-', '-')
|
|
|
|
return self.prepare_modules(True, True, True,
|
|
|
|
lambda m: m.get_available_methods())
|
|
|
|
|
|
|
|
def call_info_ids(self, method):
|
|
|
|
self.print_test_conditions(True, True, True, '-', '-')
|
|
|
|
return self.prepare_modules(True, True, True,
|
|
|
|
lambda m: m.get_available_device_ids(method))
|
|
|
|
|
|
|
|
def prepare_modules(self, pyusb_available, pyhidapi_available, device_available, func):
|
|
|
|
result = None
|
|
|
|
output = None
|
|
|
|
with self.do_import_patch(pyusb_available, pyhidapi_available, device_available) as mock:
|
|
|
|
with patch('sys.stdout', new_callable=StringIO) as stdio_mock:
|
|
|
|
import lednamebadge
|
|
|
|
try:
|
|
|
|
result = func(lednamebadge.LedNameBadge)
|
|
|
|
except(SystemExit):
|
|
|
|
pass
|
|
|
|
output = stdio_mock.getvalue()
|
|
|
|
print(output)
|
|
|
|
return result, output
|
|
|
|
|
|
|
|
def print_test_conditions(self, pyusb_available, pyhidapi_available, device_available, method, device_id):
|
|
|
|
print("Test condition: os=%s pyusb=%s pyhidapi=%s device=%s method=%s device_id=%s" % (
|
|
|
|
sys.platform,
|
|
|
|
'yes' if pyusb_available else 'no',
|
|
|
|
'yes' if pyhidapi_available else 'no',
|
|
|
|
'yes' if device_available else 'no',
|
|
|
|
method,
|
|
|
|
device_id))
|
|
|
|
|
|
|
|
def do_import_patch(self, pyusb_available, pyhidapi_available, device_available):
|
|
|
|
patch_obj = patch.dict('sys.modules', {
|
|
|
|
'pyhidapi': self.create_hid_mock(device_available) if pyhidapi_available else None,
|
|
|
|
'usb': self.create_usb_mock(device_available) if pyusb_available else None,
|
|
|
|
'usb.core': MagicMock() if pyusb_available else None,
|
|
|
|
'usb.core.USBError': USBError if pyusb_available else None,
|
|
|
|
'usb.util': MagicMock() if pyusb_available else None})
|
|
|
|
# Assure fresh reimport of lednamebadge with current mocks
|
|
|
|
if 'lednamebadge' in sys.modules:
|
|
|
|
del sys.modules['lednamebadge']
|
|
|
|
return patch_obj
|
|
|
|
|
|
|
|
|
|
|
|
def create_hid_mock(self, device_available):
|
|
|
|
device = MagicMock()
|
|
|
|
device.path = b'3-4:5-6'
|
|
|
|
device.manufacturer_string = 'HidApi Test Manufacturer'
|
|
|
|
device.product_string = 'HidApi Test Product'
|
|
|
|
device.interface_number = 0
|
|
|
|
|
|
|
|
mock = MagicMock()
|
|
|
|
mock.hid_enumerate.return_value = [device] if device_available else []
|
|
|
|
mock.hid_open_path.return_value = 123456 if device_available else []
|
|
|
|
return mock
|
|
|
|
|
|
|
|
|
|
|
|
def create_usb_mock(self, device_available):
|
|
|
|
device = MagicMock()
|
|
|
|
device.manufacturer = 'LibUsb Test Manufacturer'
|
|
|
|
device.product = 'LibUsb Test Product'
|
|
|
|
device.bus = 3
|
|
|
|
device.address = 4
|
|
|
|
|
|
|
|
ep = MagicMock()
|
|
|
|
ep.bEndpointAddress = 2
|
|
|
|
|
|
|
|
mock = MagicMock()
|
|
|
|
mock.core = MagicMock()
|
|
|
|
mock.core.find.return_value = [device] if device_available else []
|
|
|
|
mock.core.USBError = USBError
|
|
|
|
mock.util.find_descriptor.return_value = [ep] if device_available else []
|
|
|
|
return mock
|