diff --git a/tests/dbusmock/fprintd.py b/tests/dbusmock/fprintd.py index 0fcbe582a3cfb99cc6f7db9a6724c4706f9ef9ba..d7530fe10fd6786564f1f0046de430e1ac7ac847 100644 --- a/tests/dbusmock/fprintd.py +++ b/tests/dbusmock/fprintd.py @@ -93,8 +93,9 @@ def GetDefaultDevice(self): return devices[0] @dbus.service.method(MANAGER_MOCK_IFACE, - in_signature='sis', out_signature='s') -def AddDevice(self, device_name, num_enroll_stages, scan_type): + in_signature='sisb', out_signature='s') +def AddDevice(self, device_name, num_enroll_stages, scan_type, + has_identification=False): '''Convenience method to add a fingerprint reader device You have to specify a device name, the number of enrollment @@ -139,12 +140,27 @@ def AddDevice(self, device_name, num_enroll_stages, scan_type): device = mockobject.objects[path] device.fingers = {} + device.has_identification = has_identification device.claimed_user = None device.action = None + device.selected_finger = None device.verify_script = [] return path +@dbus.service.method(MANAGER_MOCK_IFACE, + in_signature='o') +def RemoveDevice(self, path): + # This isn't compatible with hotplugging devices, which fprintd doesn't + # support yet, but it's meant to remove devices added to the mock for + # testing purposes. + if not path: + raise dbus.exceptions.DBusException( + 'Invalid empty path.', + name='org.freedesktop.DBus.Error.InvalidArgs') + + self.RemoveObject(path) + @dbus.service.method(DEVICE_IFACE, in_signature='s', out_signature='as') def ListEnrolledFingers(device, user): @@ -186,6 +202,8 @@ def Release(device): 'Device was not claimed before use', name='net.reactivated.Fprint.Error.ClaimDevice') device.claimed_user = None + device.action = None + device.selected_finger = None def can_verify_finger(device, finger_name): # We should already have checked that there are enrolled fingers @@ -228,8 +246,9 @@ def VerifyStart(device, finger_name): name='net.reactivated.Fprint.Error.AlreadyInUse') device.action = 'verify' - if finger_name == 'any': + if finger_name == 'any' and not device.has_identification: finger_name = device.fingers[device.claimed_user][0] + device.selected_finger = finger_name device.EmitSignal(DEVICE_IFACE, 'VerifyFingerSelected', 's', [ finger_name ]) @@ -262,6 +281,7 @@ def VerifyStop(device): 'No verification to stop', name='net.reactivated.Fprint.Error.NoActionInProgress') device.action = None + device.selected_finger = None @dbus.service.method(DEVICE_IFACE, in_signature='s', out_signature='') @@ -317,11 +337,6 @@ def SetEnrolledFingers(device, user, fingers): Returns nothing. ''' - if len(fingers) < 1: - raise dbus.exceptions.DBusException( - 'Fingers array must not be empty', - name='org.freedesktop.DBus.Error.InvalidArgs') - for k in fingers: if k not in VALID_FINGER_NAMES: raise dbus.exceptions.DBusException( @@ -330,6 +345,30 @@ def SetEnrolledFingers(device, user, fingers): device.fingers[user] = fingers +@dbus.service.method(DEVICE_MOCK_IFACE, + in_signature='', out_signature='s') +def GetSelectedFinger(device): + '''Convenience method to get the finger under verification + + Returns the finger name that the user has selected for verifying + ''' + if not device.selected_finger: + raise dbus.exceptions.DBusException( + 'Device is not verifying', + name='net.reactivated.Fprint.Error.NoActionInProgress') + + return device.selected_finger + +@dbus.service.method(DEVICE_MOCK_IFACE, + in_signature='', out_signature='b') +def HasIdentification(device): + '''Convenience method to get if a device supports identification + + Returns whether identification is supported. + ''' + + return device.has_identification + @dbus.service.method(DEVICE_MOCK_IFACE, in_signature='a(sbi)', out_signature='') def SetVerifyScript(device, script): diff --git a/tests/fprintd.py b/tests/fprintd.py index 0bd9ac361dcb0a1bdde513e08ff932f2b3af62af..7351980e84bd90e12e3919ecffc908443433b903 100755 --- a/tests/fprintd.py +++ b/tests/fprintd.py @@ -1123,8 +1123,8 @@ class FPrintdUtilsTest(FPrintdVirtualDeviceBaseTest): env=env, stdout=None, stderr=subprocess.STDOUT) - self.addCleanup(self.utils_proc[name].terminate) self.addCleanup(self.utils_proc[name].wait) + self.addCleanup(self.utils_proc[name].terminate) return self.utils_proc[name] def test_vanished_client_operation_is_cancelled(self): diff --git a/tests/meson.build b/tests/meson.build index 289958aa270f752e789f363d6c1d4724b64449c1..495acbcf3156be7a60275a228bbe5135058fb5d8 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -38,7 +38,7 @@ foreach t: tests fprintd, fprintd_utils, ], - 'suite': ['daemon'], + 'suite': [t == 'fprintd' ? 'daemon' : ''], } ] endforeach diff --git a/tests/test_fprintd_utils.py b/tests/test_fprintd_utils.py index e1ff4f92c0cf87be165b7d3d7e069e4cd288845d..afcea53ed6b16a9cf82150aae5421b32eb397dd8 100755 --- a/tests/test_fprintd_utils.py +++ b/tests/test_fprintd_utils.py @@ -22,9 +22,23 @@ import fcntl import os import time + +VALID_FINGER_NAMES = [ + 'left-thumb', + 'left-index-finger', + 'left-middle-finger', + 'left-ring-finger', + 'left-little-finger', + 'right-thumb', + 'right-index-finger', + 'right-middle-finger', + 'right-ring-finger', + 'right-little-finger' +] + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) -class TestFprintd(dbusmock.DBusTestCase): +class TestFprintdUtilsBase(dbusmock.DBusTestCase): '''Test fprintd utilities''' @classmethod @@ -61,6 +75,7 @@ class TestFprintd(dbusmock.DBusTestCase): klass.sleep_time *= 2 def setUp(self): + super().setUp() (self.p_mock, self.obj_fprintd_manager) = self.spawn_server_template( self.template_name, {}, stdout=subprocess.PIPE) # set log to nonblocking @@ -71,11 +86,19 @@ class TestFprintd(dbusmock.DBusTestCase): def tearDown(self): self.p_mock.terminate() self.p_mock.wait() + super().tearDown() def setup_device(self): - device_path = self.obj_fprintd_mock.AddDevice('FDO Trigger Finger Laser Reader', 3, 'swipe') - self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint', device_path) - self.device_mock.SetEnrolledFingers('toto', ['left-little-finger', 'right-little-finger']) + self.device_path = self.obj_fprintd_mock.AddDevice( + 'FDO Trigger Finger Laser Reader', 3, 'swipe') + self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint', + self.device_path) + self.set_enrolled_fingers(['left-little-finger', 'right-little-finger']) + + def set_enrolled_fingers(self, fingers, user='toto'): + self.enrolled_fingers = fingers + self.device_mock.SetEnrolledFingers('toto', self.enrolled_fingers, + signature='sas') def start_utility_process(self, utility_name, args=[], sleep=True): utility = [ os.path.join(self.tools_prefix, 'fprintd-{}'.format(utility_name)) ] @@ -86,15 +109,24 @@ class TestFprintd(dbusmock.DBusTestCase): flags = fcntl.fcntl(process.stdout, fcntl.F_GETFL) fcntl.fcntl(process.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) - self.addCleanup(lambda: print(process.stdout.read())) - self.addCleanup(process.terminate) - self.addCleanup(process.wait) + self.addCleanup(self.try_stop_utility_process, process) if sleep: time.sleep(self.sleep_time) return process + def stop_utility_process(self, process): + print(process.stdout.read()) + process.terminate() + process.wait() + + def try_stop_utility_process(self, process): + try: + self.stop_utility_process(process) + except: + pass + def get_process_output(self, process): out = process.stdout.read() self.addCleanup(print, out) @@ -105,11 +137,15 @@ class TestFprintd(dbusmock.DBusTestCase): ret = proc.wait(timeout=timeout if timeout is not None else self.sleep_time * 4) self.assertLessEqual(ret, 128) - return self.get_process_output(proc) + return self.get_process_output(proc), ret - def test_fprintd_enroll(self): + +class TestFprintdUtils(TestFprintdUtilsBase): + def setUp(self): + super().setUp() self.setup_device() + def test_fprintd_enroll(self): process = self.start_utility_process('enroll', ['-f', 'right-index-finger', 'toto']) out = self.get_process_output(process) @@ -121,65 +157,158 @@ class TestFprintd(dbusmock.DBusTestCase): out = self.get_process_output(process) self.assertRegex(out, 'Enroll result: enroll-completed') + def test_fprintd_list(self): + # Rick has no fingerprints enrolled + out, ret = self.run_utility_process('list', ['rick']) + self.assertRegex(out, r'has no fingers enrolled for') + self.assertEqual(ret, 0) + + # Toto does + out, ret = self.run_utility_process('list', ['toto']) + self.assertRegex(out, r'right-little-finger') + self.assertEqual(ret, 0) + + def test_fprintd_delete(self): + # Has fingerprints enrolled + out, ret = self.run_utility_process('list', ['toto']) + self.assertRegex(out, r'left-little-finger') + self.assertEqual(ret, 0) + self.assertRegex(out, r'right-little-finger') + + # Delete fingerprints + out, ret = self.run_utility_process('delete', ['toto']) + self.assertRegex(out, r'Fingerprints deleted') + self.assertEqual(ret, 0) + + # Doesn't have fingerprints + out, ret = self.run_utility_process('list', ['toto']) + self.assertRegex(out, r'has no fingers enrolled for') + self.assertEqual(ret, 0) + + +class TestFprintdUtilsNoDeviceTests(TestFprintdUtilsBase): + def test_fprintd_enroll(self): + out, ret = self.run_utility_process('enroll', ['toto']) + self.assertIn('No devices available', out) + self.assertEqual(ret, 1) + + def test_fprintd_list(self): + out, ret = self.run_utility_process('list', ['toto']) + self.assertIn('No devices available', out) + self.assertEqual(ret, 1) + + def test_fprintd_delete(self): + out, ret = self.run_utility_process('delete', ['toto']) + self.assertIn('No devices available', out) + self.assertEqual(ret, 1) + def test_fprintd_verify(self): + out, ret = self.run_utility_process('verify', ['toto']) + self.assertIn('No devices available', out) + self.assertEqual(ret, 1) + + +class TestFprintdUtilsVerify(TestFprintdUtilsBase): + def setUp(self): + super().setUp() self.setup_device() - process = self.start_utility_process('verify', ['toto']) + def start_verify_process(self, user='toto', finger=None, checkEnrolled=True): + args = [user] + if finger: + args += ['-f', finger] - out = self.get_process_output(process) - self.assertRegex(out, r'left-little-finger') - self.assertNotRegex(out, 'Verify result: verify-match \(done\)') + self.process = self.start_utility_process('verify', args) + out = self.get_process_output(self.process) + + self.assertNotRegex(out, r'Device already in use by [A-z]+') + self.assertNotIn('Verify result:', out) + + if checkEnrolled and finger: + self.assertNotIn('''Finger '{}' not enrolled for user {}'''.format( + finger, user), out) + + if checkEnrolled: + for f in self.enrolled_fingers: + self.assertIn(f, out) + + if finger: + expected_finger = finger + if finger == 'any' and not self.device_mock.HasIdentification(): + expected_finger = self.enrolled_fingers[0] + self.assertEqual(self.device_mock.GetSelectedFinger(), expected_finger) + + def assertVerifyMatch(self, match): + self.assertIn('Verify result: {} (done)'.format( + 'verify-match' if match else 'verify-no-match'), + self.get_process_output(self.process)) + + def test_fprintd_verify(self): + self.start_verify_process() self.device_mock.EmitVerifyStatus('verify-match', True) time.sleep(self.sleep_time) + self.assertVerifyMatch(True) - out = self.get_process_output(process) - self.assertRegex(out, 'Verify result: verify-match \(done\)') + def test_fprintd_verify_enrolled_fingers(self): + for finger in self.enrolled_fingers: + self.start_verify_process(finger=finger) - def test_fprintd_verify_script(self): - self.setup_device() - script = [ - ( 'verify-match', True, 2 ) - ] - self.device_mock.SetVerifyScript(script) + self.device_mock.EmitVerifyStatus('verify-match', True) + time.sleep(self.sleep_time) + self.assertVerifyMatch(True) - process = self.start_utility_process('verify', ['toto']) + def test_fprintd_verify_any_finger_no_identification(self): + self.start_verify_process(finger='any') - out = self.get_process_output(process) - self.assertRegex(out, r'left-little-finger') - self.assertNotRegex(out, 'Verify result: verify-match \(done\)') + self.device_mock.EmitVerifyStatus('verify-match', True) + time.sleep(self.sleep_time) + self.assertVerifyMatch(True) - time.sleep(self.sleep_time * 4) + def test_fprintd_verify_any_finger_identification(self): + self.obj_fprintd_mock.RemoveDevice(self.device_path) + self.device_path = self.obj_fprintd_mock.AddDevice('Full powered device', + 3, 'press', True) + self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint', + self.device_path) + self.set_enrolled_fingers(VALID_FINGER_NAMES) + self.start_verify_process(finger='any') - out = self.get_process_output(process) - self.assertRegex(out, 'Verify result: verify-match \(done\)') + self.device_mock.EmitVerifyStatus('verify-match', True) + time.sleep(self.sleep_time) + self.assertVerifyMatch(True) - def test_fprintd_list(self): - self.setup_device() + def test_fprintd_verify_not_enrolled_fingers(self): + for finger in [f for f in VALID_FINGER_NAMES if f not in self.enrolled_fingers]: + regex = r'Finger \'{}\' not enrolled'.format(finger) + with self.assertRaisesRegex(AssertionError, regex): + self.start_verify_process(finger=finger) + self.device_mock.Release() - # Rick has no fingerprints enrolled - out = self.run_utility_process('list', ['rick']) - self.assertRegex(out, r'has no fingers enrolled for') + def test_fprintd_verify_no_enrolled_fingers(self): + self.set_enrolled_fingers([]) + self.start_verify_process() + self.assertEqual(self.process.poll(), 1) - # Toto does - out = self.run_utility_process('list', ['toto']) - self.assertRegex(out, r'right-little-finger') + def test_fprintd_list_all_fingers(self): + self.set_enrolled_fingers(VALID_FINGER_NAMES) + self.start_verify_process() - def test_fprintd_delete(self): - self.setup_device() + def test_fprintd_verify_script(self): + script = [ + ( 'verify-match', True, 2 ) + ] + self.device_mock.SetVerifyScript(script) - # Has fingerprints enrolled - out = self.run_utility_process('list', ['toto']) - self.assertRegex(out, r'left-little-finger') - self.assertRegex(out, r'right-little-finger') + self.start_verify_process() + time.sleep(self.sleep_time * 4) + self.assertVerifyMatch(True) - # Delete fingerprints - out = self.run_utility_process('delete', ['toto']) - self.assertRegex(out, r'Fingerprints deleted') + def test_fprintd_multiple_verify_fails(self): + self.start_verify_process() - # Doesn't have fingerprints - out = self.run_utility_process('list', ['toto']) - self.assertRegex(out, r'has no fingers enrolled for') + with self.assertRaisesRegex(AssertionError, r'Device already in use'): + self.start_verify_process() if __name__ == '__main__': # avoid writing to stderr diff --git a/utils/delete.c b/utils/delete.c index cf27ebf5215cdc3d09949921f437904d9dbce1a9..0c25b7bbb1c2de7cf02342ec195be57e9dae3d1f 100644 --- a/utils/delete.c +++ b/utils/delete.c @@ -89,12 +89,12 @@ static void process_devices(char **argv) guint i; if (!net_reactivated_Fprint_Manager_get_devices(manager, &devices, &error)) { - g_print("list_devices failed: %s\n", error->message); + g_print("Impossible to get devices: %s\n", error->message); exit (1); } if (devices->len == 0) { - g_print("No devices found\n"); + g_print("No devices available\n"); exit(1); } diff --git a/utils/enroll.c b/utils/enroll.c index 4dd33594f92df34d5a67fc5569931177e644720e..8bd55e973079321f6c5cb401170d08ec3c958947 100644 --- a/utils/enroll.c +++ b/utils/enroll.c @@ -57,14 +57,9 @@ static DBusGProxy *open_device(const char *username) DBusGProxy *dev; if (!net_reactivated_Fprint_Manager_get_default_device(manager, &path, &error)) { - g_print("list_devices failed: %s\n", error->message); + g_print("Impossible to enroll: %s\n", error->message); exit (1); } - - if (path == NULL) { - g_print("No devices found\n"); - exit(1); - } g_print("Using device %s\n", path); diff --git a/utils/list.c b/utils/list.c index 8098c0c4418e40bb7582cd0bf00ff92b026404d0..54bc34ba59f707a7fa5710b8650e260eca463ed9 100644 --- a/utils/list.c +++ b/utils/list.c @@ -94,12 +94,12 @@ static void process_devices(char **argv) guint i; if (!net_reactivated_Fprint_Manager_get_devices(manager, &devices, &error)) { - g_print("list_devices failed: %s\n", error->message); + g_print("Impossible to get devices: %s\n", error->message); exit (1); } if (devices->len == 0) { - g_print("No devices found\n"); + g_print("No devices available\n"); exit(1); } diff --git a/utils/verify.c b/utils/verify.c index 2989a49436db2add53231ac4729c70c1f6a5e64b..caac88e3ee6e78cd7d16528dbe979c571473a8d5 100644 --- a/utils/verify.c +++ b/utils/verify.c @@ -54,14 +54,9 @@ static DBusGProxy *open_device(const char *username) DBusGProxy *dev; if (!net_reactivated_Fprint_Manager_get_default_device(manager, &path, &error)) { - g_print("list_devices failed: %s\n", error->message); + g_print("Impossible to verify: %s\n", error->message); exit (1); } - - if (path == NULL) { - g_print("No devices found\n"); - exit(1); - } g_print("Using device %s\n", path); @@ -100,8 +95,15 @@ static void find_finger(DBusGProxy *dev, const char *username) g_print(" - #%d: %s\n", i, fingers[i]); } - if (finger_name == NULL || strcmp (finger_name, "any") == 0) { + if (finger_name && !g_str_equal (finger_name, "any") && + !g_strv_contains ((const char **) fingers, finger_name)) { + g_print("Finger '%s' not enrolled for user %s.\n", finger_name, + username); g_free (finger_name); + exit(1); + } + + if (finger_name == NULL) { finger_name = g_strdup (fingers[0]); }