tests/virtual-device: Do not preserve context on unplug tests

The unplug tests assume that the device is removed from the context once
they run, however we may have left the device around in a removed state
causing other tests to fail.

So isolate them in a new class where we create context and device
instances every time we run a test case.
This commit is contained in:
Marco Trevisan (Treviño)
2023-06-22 00:26:08 -04:00
parent 0819df6988
commit c27d72e3a1

View File

@@ -60,6 +60,15 @@ class GLibErrorMessage:
class VirtualDeviceBase(unittest.TestCase): class VirtualDeviceBase(unittest.TestCase):
DEFAULT_ENROLL_STEPS = 5 DEFAULT_ENROLL_STEPS = 5
USE_CLASS_DEVICE = True
@classmethod
def get_device(cls, ctx):
for dev in ctx.get_devices():
# We might have a USB device in the test system that needs skipping
if dev.get_driver() == cls._driver_name:
return dev
return None
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
@@ -75,26 +84,28 @@ class VirtualDeviceBase(unittest.TestCase):
cls.sockaddr = os.path.join(cls.tmpdir, '{}.socket'.format(sock_name)) cls.sockaddr = os.path.join(cls.tmpdir, '{}.socket'.format(sock_name))
os.environ['FP_{}'.format(driver_name.upper())] = cls.sockaddr os.environ['FP_{}'.format(driver_name.upper())] = cls.sockaddr
cls.ctx = FPrint.Context() cls._driver_name = driver_name
cls.dev = None if cls.USE_CLASS_DEVICE:
for dev in cls.ctx.get_devices(): cls.ctx = FPrint.Context()
# We might have a USB device in the test system that needs skipping cls.dev = cls.get_device(cls.ctx)
if dev.get_driver() == driver_name: assert cls.dev is not None, "You need to compile with {} for testing".format(
cls.dev = dev driver_name)
break
assert cls.dev is not None, "You need to compile with {} for testing".format(driver_name)
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
shutil.rmtree(cls.tmpdir) shutil.rmtree(cls.tmpdir)
del cls.dev if cls.USE_CLASS_DEVICE:
del cls.ctx del cls.dev
del cls.ctx
unittest.TestCase.tearDownClass() unittest.TestCase.tearDownClass()
def setUp(self): def setUp(self):
super().setUp() super().setUp()
if not self.USE_CLASS_DEVICE:
self.ctx = FPrint.Context()
self.dev = self.get_device(self.ctx)
self.assertIsNotNone(self.dev)
self._close_on_teardown = True self._close_on_teardown = True
self.assertFalse(self.dev.is_open()) self.assertFalse(self.dev.is_open())
self.dev.open_sync() self.dev.open_sync()
@@ -107,6 +118,9 @@ class VirtualDeviceBase(unittest.TestCase):
self.send_command('SET_ENROLL_STAGES', self.DEFAULT_ENROLL_STEPS) self.send_command('SET_ENROLL_STAGES', self.DEFAULT_ENROLL_STEPS)
self.dev.close_sync() self.dev.close_sync()
self.assertFalse(self.dev.is_open()) self.assertFalse(self.dev.is_open())
if not self.USE_CLASS_DEVICE:
del self.dev
del self.ctx
super().tearDown() super().tearDown()
def wait_timeout(self, interval): def wait_timeout(self, interval):
@@ -335,6 +349,79 @@ class VirtualDeviceBase(unittest.TestCase):
self.assertEqual(self._verify_fp.props.fpi_data.get_string(), scan_nick) self.assertEqual(self._verify_fp.props.fpi_data.get_string(), scan_nick)
class VirtualDeviceUnplugging(VirtualDeviceBase):
driver_name = 'virtual_device'
USE_CLASS_DEVICE = False
def test_device_unplug(self):
self._close_on_teardown = False
notified_spec = None
def on_removed_notify(dev, spec):
nonlocal notified_spec
notified_spec = spec
removed = False
def on_removed(dev):
nonlocal removed
removed = dev.props.removed
self.assertFalse(self.dev.props.removed)
self.dev.connect('notify::removed', on_removed_notify)
self.dev.connect('removed', on_removed)
self.send_command('UNPLUG')
self.assertEqual(notified_spec.name, 'removed')
self.assertTrue(self.dev.props.removed)
self.assertIn(self.dev, self.ctx.get_devices())
self.assertTrue(removed)
with self.assertRaises(GLib.GError) as error:
self.dev.close_sync()
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.REMOVED))
def test_device_unplug_during_verify(self):
self._close_on_teardown = False
self._destroy_on_teardown = True
notified_spec = None
def on_removed_notify(dev, spec):
nonlocal notified_spec
notified_spec = spec
removed = False
def on_removed(dev):
nonlocal removed
removed = dev.props.removed
self.assertFalse(self.dev.props.removed)
self.dev.connect('notify::removed', on_removed_notify)
self.dev.connect('removed', on_removed)
self.start_verify(FPrint.Print.new(self.dev),
identify=self.dev.supports_identify())
self.send_command('UNPLUG')
self.assertEqual(notified_spec.name, 'removed')
self.assertTrue(self.dev.props.removed)
self.assertIn(self.dev, self.ctx.get_devices())
self.assertFalse(removed)
with self.assertRaises(GLib.GError) as error:
self.complete_verify()
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.REMOVED))
self.assertTrue(removed)
self.assertIn(self.dev, self.ctx.get_devices())
with self.assertRaises(GLib.GError) as error:
self.dev.close_sync()
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.REMOVED))
class VirtualDevice(VirtualDeviceBase): class VirtualDevice(VirtualDeviceBase):
def test_device_properties(self): def test_device_properties(self):
@@ -705,69 +792,6 @@ class VirtualDevice(VirtualDeviceBase):
self.assertEqual(self.dev.get_scan_type(), FPrint.ScanType.SWIPE) self.assertEqual(self.dev.get_scan_type(), FPrint.ScanType.SWIPE)
self.assertIsNone(notified_spec) self.assertIsNone(notified_spec)
def test_device_unplug(self):
self._close_on_teardown = False
notified_spec = None
def on_removed_notify(dev, spec):
nonlocal notified_spec
notified_spec = spec
removed = False
def on_removed(dev):
nonlocal removed
removed = True
self.assertFalse(self.dev.props.removed)
self.dev.connect('notify::removed', on_removed_notify)
self.dev.connect('removed', on_removed)
self.send_command('UNPLUG')
self.assertEqual(notified_spec.name, 'removed')
self.assertTrue(self.dev.props.removed)
self.assertTrue(removed)
with self.assertRaises(GLib.GError) as error:
self.dev.close_sync()
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.REMOVED))
def test_device_unplug_during_verify(self):
self._close_on_teardown = False
notified_spec = None
def on_removed_notify(dev, spec):
nonlocal notified_spec
notified_spec = spec
removed = False
def on_removed(dev):
nonlocal removed
removed = True
self.assertFalse(self.dev.props.removed)
self.dev.connect('notify::removed', on_removed_notify)
self.dev.connect('removed', on_removed)
self.start_verify(FPrint.Print.new(self.dev),
identify=self.dev.supports_identify())
self.send_command('UNPLUG')
self.assertEqual(notified_spec.name, 'removed')
self.assertTrue(self.dev.props.removed)
self.assertFalse(removed)
with self.assertRaises(GLib.GError) as error:
self.complete_verify()
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.REMOVED))
self.assertTrue(removed)
with self.assertRaises(GLib.GError) as error:
self.dev.close_sync()
self.assertTrue(error.exception.matches(FPrint.DeviceError.quark(),
FPrint.DeviceError.REMOVED))
def test_device_sleep(self): def test_device_sleep(self):
self.send_sleep(1500) self.send_sleep(1500)