2019-10-07 15:14:21 +02:00
|
|
|
#! /usr/bin/env python3
|
|
|
|
|
# Copyright © 2017, 2019 Red Hat, Inc
|
2020-02-07 17:44:46 +01:00
|
|
|
# Copyright © 2020 Canonical Ltd
|
2019-10-07 15:14:21 +02:00
|
|
|
#
|
|
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
# License as published by the Free Software Foundation; either
|
|
|
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
# Lesser General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
# Authors:
|
|
|
|
|
# Christian J. Kellner <christian@kellner.me>
|
|
|
|
|
# Benjamin Berg <bberg@redhat.com>
|
2020-01-30 18:32:30 +01:00
|
|
|
# Marco Trevisan <marco.trevisan@canonical.com>
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
import unittest
|
|
|
|
|
import time
|
|
|
|
|
import subprocess
|
|
|
|
|
import os
|
|
|
|
|
import os.path
|
|
|
|
|
import sys
|
|
|
|
|
import tempfile
|
|
|
|
|
import glob
|
2020-02-11 00:33:14 +01:00
|
|
|
import pwd
|
2019-10-07 15:14:21 +02:00
|
|
|
import shutil
|
|
|
|
|
import socket
|
|
|
|
|
import struct
|
|
|
|
|
import dbusmock
|
|
|
|
|
import gi
|
2020-02-07 21:19:32 +01:00
|
|
|
gi.require_version('FPrint', '2.0')
|
|
|
|
|
from gi.repository import GLib, Gio, FPrint
|
2019-10-07 15:14:21 +02:00
|
|
|
import cairo
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
from subprocess import DEVNULL
|
|
|
|
|
except ImportError:
|
|
|
|
|
DEVNULL = open(os.devnull, 'wb')
|
|
|
|
|
|
|
|
|
|
SERVICE_FILE = '/usr/share/dbus-1/system-services/net.reactivated.Fprint.service'
|
|
|
|
|
|
|
|
|
|
def get_timeout(topic='default'):
|
|
|
|
|
vals = {
|
|
|
|
|
'valgrind': {
|
|
|
|
|
'test': 300,
|
|
|
|
|
'default': 20,
|
|
|
|
|
'daemon_start': 60
|
|
|
|
|
},
|
2020-02-14 18:31:40 +01:00
|
|
|
'asan': {
|
|
|
|
|
'test': 120,
|
|
|
|
|
'default': 6,
|
|
|
|
|
'daemon_start': 10
|
|
|
|
|
},
|
2019-10-07 15:14:21 +02:00
|
|
|
'default': {
|
|
|
|
|
'test': 60,
|
|
|
|
|
'default': 3,
|
|
|
|
|
'daemon_start': 5
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-14 18:31:40 +01:00
|
|
|
if os.getenv('VALGRIND') is not None:
|
|
|
|
|
lut = vals['valgrind']
|
|
|
|
|
elif os.getenv('ADDRESS_SANITIZER') is not None:
|
|
|
|
|
lut = vals['asan']
|
|
|
|
|
else:
|
|
|
|
|
lut = vals['default']
|
|
|
|
|
|
2019-10-07 15:14:21 +02:00
|
|
|
if topic not in lut:
|
|
|
|
|
raise ValueError('invalid topic')
|
|
|
|
|
return lut[topic]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Copied from libfprint tests
|
|
|
|
|
class Connection:
|
|
|
|
|
|
|
|
|
|
def __init__(self, addr):
|
|
|
|
|
self.addr = addr
|
|
|
|
|
|
|
|
|
|
def __enter__(self):
|
|
|
|
|
self.con = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
|
|
|
self.con.connect(self.addr)
|
|
|
|
|
return self.con
|
|
|
|
|
|
|
|
|
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
|
|
|
self.con.close()
|
|
|
|
|
del self.con
|
|
|
|
|
|
|
|
|
|
def load_image(img):
|
|
|
|
|
png = cairo.ImageSurface.create_from_png(img)
|
|
|
|
|
|
|
|
|
|
# Cairo wants 4 byte aligned rows, so just add a few pixel if necessary
|
|
|
|
|
w = png.get_width()
|
|
|
|
|
h = png.get_height()
|
|
|
|
|
w = (w + 3) // 4 * 4
|
|
|
|
|
h = (h + 3) // 4 * 4
|
|
|
|
|
img = cairo.ImageSurface(cairo.Format.A8, w, h)
|
|
|
|
|
cr = cairo.Context(img)
|
|
|
|
|
|
|
|
|
|
cr.set_source_rgba(1, 1, 1, 1)
|
|
|
|
|
cr.paint()
|
|
|
|
|
|
|
|
|
|
cr.set_source_rgba(0, 0, 0, 0)
|
|
|
|
|
cr.set_operator(cairo.OPERATOR_SOURCE)
|
|
|
|
|
|
|
|
|
|
cr.set_source_surface(png)
|
|
|
|
|
cr.paint()
|
|
|
|
|
|
|
|
|
|
return img
|
|
|
|
|
|
|
|
|
|
if hasattr(os.environ, 'TOPSRCDIR'):
|
|
|
|
|
root = os.environ['TOPSRCDIR']
|
|
|
|
|
else:
|
|
|
|
|
root = os.path.join(os.path.dirname(__file__), '..')
|
|
|
|
|
|
|
|
|
|
imgdir = os.path.join(root, 'tests', 'prints')
|
|
|
|
|
|
|
|
|
|
ctx = GLib.main_context_default()
|
|
|
|
|
|
|
|
|
|
class FPrintdTest(dbusmock.DBusTestCase):
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def path_from_service_file(sf):
|
|
|
|
|
with open(SERVICE_FILE) as f:
|
|
|
|
|
for line in f:
|
|
|
|
|
if not line.startswith('Exec='):
|
|
|
|
|
continue
|
|
|
|
|
return line.split('=', 1)[1].strip()
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def setUpClass(cls):
|
2020-02-07 17:33:37 +01:00
|
|
|
super().setUpClass()
|
2019-10-07 15:14:21 +02:00
|
|
|
fprintd = None
|
|
|
|
|
|
|
|
|
|
if 'FPRINT_BUILD_DIR' in os.environ:
|
|
|
|
|
print('Testing local build')
|
|
|
|
|
build_dir = os.environ['FPRINT_BUILD_DIR']
|
|
|
|
|
fprintd = os.path.join(build_dir, 'fprintd')
|
|
|
|
|
elif 'UNDER_JHBUILD' in os.environ:
|
|
|
|
|
print('Testing JHBuild version')
|
|
|
|
|
jhbuild_prefix = os.environ['JHBUILD_PREFIX']
|
|
|
|
|
fprintd = os.path.join(jhbuild_prefix, 'libexec', 'fprintd')
|
|
|
|
|
else:
|
|
|
|
|
print('Testing installed system binaries')
|
|
|
|
|
fprintd = cls.path_from_service_file(SERVICE_FILE)
|
|
|
|
|
|
|
|
|
|
assert fprintd is not None, 'failed to find daemon'
|
|
|
|
|
cls.paths = {'daemon': fprintd }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cls.tmpdir = tempfile.mkdtemp(prefix='libfprint-')
|
|
|
|
|
|
|
|
|
|
cls.sockaddr = os.path.join(cls.tmpdir, 'virtual-image.socket')
|
|
|
|
|
os.environ['FP_VIRTUAL_IMAGE'] = cls.sockaddr
|
|
|
|
|
|
|
|
|
|
cls.prints = {}
|
|
|
|
|
for f in glob.glob(os.path.join(imgdir, '*.png')):
|
|
|
|
|
n = os.path.basename(f)[:-4]
|
|
|
|
|
cls.prints[n] = load_image(f)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cls.test_bus = Gio.TestDBus.new(Gio.TestDBusFlags.NONE)
|
|
|
|
|
cls.test_bus.up()
|
2020-02-07 17:46:26 +01:00
|
|
|
cls.test_bus.unset()
|
2020-02-07 17:44:46 +01:00
|
|
|
addr = cls.test_bus.get_bus_address()
|
|
|
|
|
os.environ['DBUS_SYSTEM_BUS_ADDRESS'] = addr
|
|
|
|
|
cls.dbus = Gio.DBusConnection.new_for_address_sync(addr,
|
|
|
|
|
Gio.DBusConnectionFlags.MESSAGE_BUS_CONNECTION |
|
|
|
|
|
Gio.DBusConnectionFlags.AUTHENTICATION_CLIENT, None, None)
|
|
|
|
|
assert cls.dbus.is_closed() == False
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def tearDownClass(cls):
|
2020-02-07 17:44:46 +01:00
|
|
|
cls.dbus.close()
|
2019-10-07 15:14:21 +02:00
|
|
|
cls.test_bus.down()
|
2020-02-07 17:44:46 +01:00
|
|
|
del cls.dbus
|
|
|
|
|
del cls.test_bus
|
2019-10-07 15:14:21 +02:00
|
|
|
shutil.rmtree(cls.tmpdir)
|
|
|
|
|
dbusmock.DBusTestCase.tearDownClass()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def daemon_start(self):
|
|
|
|
|
timeout = get_timeout('daemon_start') # seconds
|
|
|
|
|
env = os.environ.copy()
|
|
|
|
|
env['G_DEBUG'] = 'fatal-criticals'
|
2020-03-17 15:24:46 +01:00
|
|
|
env['STATE_DIRECTORY'] = (self.state_dir + ':' + '/hopefully/a/state_dir_path/that/shouldnt/be/writable')
|
2019-10-07 15:14:21 +02:00
|
|
|
env['RUNTIME_DIRECTORY'] = self.run_dir
|
|
|
|
|
|
|
|
|
|
argv = [self.paths['daemon'], '-t']
|
|
|
|
|
valgrind = os.getenv('VALGRIND')
|
|
|
|
|
if valgrind is not None:
|
|
|
|
|
argv.insert(0, 'valgrind')
|
|
|
|
|
argv.insert(1, '--leak-check=full')
|
|
|
|
|
if os.path.exists(valgrind):
|
|
|
|
|
argv.insert(2, '--suppressions=%s' % valgrind)
|
|
|
|
|
self.valgrind = True
|
|
|
|
|
self.daemon = subprocess.Popen(argv,
|
|
|
|
|
env=env,
|
|
|
|
|
stdout=None,
|
|
|
|
|
stderr=subprocess.STDOUT)
|
2020-02-14 19:34:45 +01:00
|
|
|
self.addCleanup(self.daemon_stop)
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
timeout_count = timeout * 10
|
|
|
|
|
timeout_sleep = 0.1
|
|
|
|
|
while timeout_count > 0:
|
|
|
|
|
time.sleep(timeout_sleep)
|
|
|
|
|
timeout_count -= 1
|
|
|
|
|
try:
|
|
|
|
|
self.manager = Gio.DBusProxy.new_sync(self.dbus,
|
|
|
|
|
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
|
|
|
|
None,
|
|
|
|
|
'net.reactivated.Fprint',
|
|
|
|
|
'/net/reactivated/Fprint/Manager',
|
|
|
|
|
'net.reactivated.Fprint.Manager',
|
|
|
|
|
None)
|
|
|
|
|
|
|
|
|
|
devices = self.manager.GetDevices()
|
|
|
|
|
# Find the virtual device, just in case it is a local run
|
|
|
|
|
# and there is another usable sensor available locally
|
|
|
|
|
for path in devices:
|
|
|
|
|
dev = Gio.DBusProxy.new_sync(self.dbus,
|
|
|
|
|
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
|
|
|
|
|
None,
|
|
|
|
|
'net.reactivated.Fprint',
|
|
|
|
|
path,
|
|
|
|
|
'net.reactivated.Fprint.Device',
|
|
|
|
|
None)
|
|
|
|
|
|
|
|
|
|
if 'Virtual image device' in str(dev.get_cached_property('name')):
|
|
|
|
|
self.device = dev
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
print('Did not find virtual device! Probably libfprint was build without the corresponding driver!')
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
except GLib.GError:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
timeout_time = timeout * 10 * timeout_sleep
|
|
|
|
|
self.fail('daemon did not start in %d seconds' % timeout_time)
|
|
|
|
|
|
|
|
|
|
def daemon_stop(self):
|
|
|
|
|
|
|
|
|
|
if self.daemon:
|
|
|
|
|
try:
|
|
|
|
|
self.daemon.terminate()
|
|
|
|
|
except OSError:
|
|
|
|
|
pass
|
2020-02-13 19:19:01 +01:00
|
|
|
self.assertLess(self.daemon.wait(timeout=2), 128)
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
self.daemon = None
|
|
|
|
|
|
|
|
|
|
def polkitd_start(self):
|
|
|
|
|
self._polkitd, self._polkitd_obj = self.spawn_server_template(
|
|
|
|
|
'polkitd', {}, stdout=DEVNULL)
|
2020-02-14 19:34:45 +01:00
|
|
|
self.addCleanup(self.polkitd_stop)
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
def polkitd_stop(self):
|
|
|
|
|
if self._polkitd is None:
|
|
|
|
|
return
|
|
|
|
|
self._polkitd.terminate()
|
|
|
|
|
self._polkitd.wait()
|
|
|
|
|
|
2020-02-11 00:33:14 +01:00
|
|
|
def get_current_user(self):
|
|
|
|
|
return pwd.getpwuid(os.getuid()).pw_name
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.test_dir = tempfile.mkdtemp()
|
2020-02-08 18:00:15 +01:00
|
|
|
self.addCleanup(shutil.rmtree, self.test_dir)
|
2019-10-07 15:14:21 +02:00
|
|
|
self.state_dir = os.path.join(self.test_dir, 'state')
|
|
|
|
|
self.run_dir = os.path.join(self.test_dir, 'run')
|
2020-02-08 09:37:08 +01:00
|
|
|
os.environ['FP_DRIVERS_WHITELIST'] = 'virtual_image'
|
2019-10-07 15:14:21 +02:00
|
|
|
|
2020-02-08 10:20:18 +01:00
|
|
|
def assertFprintError(self, fprint_error):
|
|
|
|
|
return self.assertRaisesRegex(GLib.Error,
|
|
|
|
|
'.*net\.reactivated\.Fprint\.Error\.{}.*'.format(fprint_error))
|
|
|
|
|
|
2019-10-07 15:14:21 +02:00
|
|
|
# From libfprint tests
|
2020-02-07 21:19:32 +01:00
|
|
|
def send_retry(self, retry_error=FPrint.DeviceRetry.TOO_SHORT):
|
2019-10-07 15:14:21 +02:00
|
|
|
with Connection(self.sockaddr) as con:
|
|
|
|
|
con.sendall(struct.pack('ii', -1, retry_error))
|
|
|
|
|
|
2020-02-08 14:51:28 +01:00
|
|
|
# From libfprint tests
|
|
|
|
|
def send_error(self, error=FPrint.DeviceError.GENERAL):
|
|
|
|
|
with Connection(self.sockaddr) as con:
|
|
|
|
|
con.sendall(struct.pack('ii', -2, error))
|
|
|
|
|
|
2019-10-07 15:14:21 +02:00
|
|
|
# From libfprint tests
|
|
|
|
|
def send_image(self, image):
|
|
|
|
|
img = self.prints[image]
|
|
|
|
|
with Connection(self.sockaddr) as con:
|
|
|
|
|
mem = img.get_data()
|
|
|
|
|
mem = mem.tobytes()
|
2020-01-30 19:25:12 +01:00
|
|
|
self.assertEqual(len(mem), img.get_width() * img.get_height())
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
encoded_img = struct.pack('ii', img.get_width(), img.get_height())
|
|
|
|
|
encoded_img += mem
|
|
|
|
|
|
|
|
|
|
con.sendall(encoded_img)
|
|
|
|
|
|
2020-02-11 05:07:33 +01:00
|
|
|
def call_device_method_from_other_client(self, method, args=[]):
|
|
|
|
|
try:
|
|
|
|
|
return subprocess.check_output([
|
|
|
|
|
'gdbus',
|
|
|
|
|
'call',
|
|
|
|
|
'--system',
|
|
|
|
|
'--dest',
|
|
|
|
|
self.device.get_name(),
|
|
|
|
|
'--object-path',
|
|
|
|
|
self.device.get_object_path(),
|
|
|
|
|
'--method',
|
|
|
|
|
'{}.{}'.format(self.device.get_interface_name(), method),
|
|
|
|
|
] + args, stderr=subprocess.STDOUT, timeout=5)
|
|
|
|
|
except subprocess.CalledProcessError as e:
|
|
|
|
|
raise GLib.GError(e.output)
|
|
|
|
|
|
2020-01-30 18:32:30 +01:00
|
|
|
|
2020-03-17 17:01:50 +01:00
|
|
|
class FPrintdVirtualDeviceBaseTest(FPrintdTest):
|
|
|
|
|
|
2020-01-30 18:32:30 +01:00
|
|
|
def setUp(self):
|
|
|
|
|
super().setUp()
|
|
|
|
|
|
tests/fprintd: Allow tests to run even when virtual device is not available
The test file calls self.daemon_start() in order to start fprintd and
locate the virtual image device that's needed for the test to run.
However, since the virtual image driver is not available on all
libfprint installations, the test should be skipped if the driver is not
available.
The skipping mechanism used to work, by checking if self.device is None.
This is based on the assumption that self.device would be set to None in
cases where the driver is not available. However, even in the past
self.device is only set to None in the tearDown method and not in setUp,
so presumably in edge cases it didn't entirely work.
However, since 0fb4f3b0217ac0fe2ac7a65a5ff2abed68d74a53 which
consistently removes the self.device attribute rather than setting it to
None, the "self.device is None" check no longer works. In particular,
the following error message is shown:
test_manager_get_default_device (__main__.FPrintdManagerTests) ...
Did not find virtual device! Probably libfprint was build without
the corresponding driver!
ERROR
After this patch, the following is shown:
test_manager_get_default_device (__main__.FPrintdManagerTests) ...
Did not find virtual device! Probably libfprint was build without
the corresponding driver!
skipped 'Need virtual_image device to run the test'
We fix this bug by consistently setting self.device to None, in both the
setUp method before daemon_start gets called, and in tearDown. We also
make the same change to self.manager for consistency.
The issue was not caught on CI, as the CI configuration always installs
a libfprint version that has the virtual_image device explicitly enabled
in the preparation phase.
2020-03-19 23:27:15 -04:00
|
|
|
self.manager = None
|
|
|
|
|
self.device = None
|
2019-10-07 15:14:21 +02:00
|
|
|
self.polkitd_start()
|
|
|
|
|
self.daemon_start()
|
|
|
|
|
|
|
|
|
|
if self.device is None:
|
|
|
|
|
self.skipTest("Need virtual_image device to run the test")
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername',
|
|
|
|
|
'net.reactivated.fprint.device.enroll',
|
|
|
|
|
'net.reactivated.fprint.device.verify'])
|
|
|
|
|
|
|
|
|
|
def signal_cb(proxy, sender, signal, params):
|
|
|
|
|
print(signal, params)
|
|
|
|
|
if signal == 'EnrollStatus':
|
|
|
|
|
self._abort = params[1]
|
|
|
|
|
self._last_result = params[0]
|
|
|
|
|
|
2020-02-07 21:18:57 +01:00
|
|
|
if not self._abort and self._last_result.startswith('enroll-'):
|
|
|
|
|
# Exit wait loop, onto next enroll state (if any)
|
|
|
|
|
self._abort = True
|
2019-10-07 15:14:21 +02:00
|
|
|
elif self._abort:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
self._abort = True
|
|
|
|
|
self._last_result = 'Unexpected signal values'
|
|
|
|
|
print('Unexpected signal values')
|
|
|
|
|
elif signal == 'VerifyFingerSelected':
|
|
|
|
|
pass
|
|
|
|
|
elif signal == 'VerifyStatus':
|
|
|
|
|
self._abort = True
|
|
|
|
|
self._last_result = params[0]
|
|
|
|
|
self._verify_stopped = params[1]
|
|
|
|
|
else:
|
|
|
|
|
self._abort = True
|
|
|
|
|
self._last_result = 'Unexpected signal'
|
|
|
|
|
|
2020-01-30 18:32:30 +01:00
|
|
|
self.g_signal_id = self.device.connect('g-signal', signal_cb)
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.device.disconnect(self.g_signal_id)
|
tests/fprintd: Allow tests to run even when virtual device is not available
The test file calls self.daemon_start() in order to start fprintd and
locate the virtual image device that's needed for the test to run.
However, since the virtual image driver is not available on all
libfprint installations, the test should be skipped if the driver is not
available.
The skipping mechanism used to work, by checking if self.device is None.
This is based on the assumption that self.device would be set to None in
cases where the driver is not available. However, even in the past
self.device is only set to None in the tearDown method and not in setUp,
so presumably in edge cases it didn't entirely work.
However, since 0fb4f3b0217ac0fe2ac7a65a5ff2abed68d74a53 which
consistently removes the self.device attribute rather than setting it to
None, the "self.device is None" check no longer works. In particular,
the following error message is shown:
test_manager_get_default_device (__main__.FPrintdManagerTests) ...
Did not find virtual device! Probably libfprint was build without
the corresponding driver!
ERROR
After this patch, the following is shown:
test_manager_get_default_device (__main__.FPrintdManagerTests) ...
Did not find virtual device! Probably libfprint was build without
the corresponding driver!
skipped 'Need virtual_image device to run the test'
We fix this bug by consistently setting self.device to None, in both the
setUp method before daemon_start gets called, and in tearDown. We also
make the same change to self.manager for consistency.
The issue was not caught on CI, as the CI configuration always installs
a libfprint version that has the virtual_image device explicitly enabled
in the preparation phase.
2020-03-19 23:27:15 -04:00
|
|
|
self.device = None
|
|
|
|
|
self.manager = None
|
2020-02-07 17:49:16 +01:00
|
|
|
|
2020-02-06 19:46:09 +01:00
|
|
|
super().tearDown()
|
|
|
|
|
|
2020-02-06 21:16:31 +01:00
|
|
|
def wait_for_result(self, expected=None):
|
|
|
|
|
self._abort = False
|
|
|
|
|
while not self._abort:
|
|
|
|
|
ctx.iteration(True)
|
|
|
|
|
|
|
|
|
|
self.assertTrue(self._abort)
|
|
|
|
|
self._abort = False
|
|
|
|
|
|
|
|
|
|
if expected is not None:
|
|
|
|
|
self.assertEqual(self._last_result, expected)
|
|
|
|
|
|
2020-02-10 18:34:33 +01:00
|
|
|
def enroll_image(self, img, finger='right-index-finger', expected_result='enroll-completed'):
|
2020-03-17 15:54:14 +01:00
|
|
|
self.device.EnrollStart('(s)', finger)
|
|
|
|
|
|
2020-02-07 21:18:57 +01:00
|
|
|
stages = self.device.get_cached_property('num-enroll-stages').unpack()
|
|
|
|
|
for stage in range(stages):
|
|
|
|
|
self.send_image(img)
|
|
|
|
|
if stage < stages - 1:
|
|
|
|
|
self.wait_for_result('enroll-stage-passed')
|
|
|
|
|
else:
|
2020-03-27 16:26:28 +01:00
|
|
|
self.wait_for_result(expected_result)
|
2020-03-17 15:54:14 +01:00
|
|
|
|
|
|
|
|
self.device.EnrollStop()
|
2020-02-10 18:34:33 +01:00
|
|
|
self.assertEqual(self._last_result, expected_result)
|
2020-03-17 15:54:14 +01:00
|
|
|
|
2020-03-17 17:01:50 +01:00
|
|
|
|
2020-02-08 09:51:40 +01:00
|
|
|
class FPrintdManagerTests(FPrintdVirtualDeviceBaseTest):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
super().setUp()
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
|
|
|
|
|
def test_manager_get_devices(self):
|
|
|
|
|
self.assertListEqual(self.manager.GetDevices(),
|
|
|
|
|
[ self.device.get_object_path() ])
|
|
|
|
|
|
|
|
|
|
def test_manager_get_default_device(self):
|
|
|
|
|
self.assertEqual(self.manager.GetDefaultDevice(),
|
|
|
|
|
self.device.get_object_path())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class FPrintdManagerPreStartTests(FPrintdTest):
|
|
|
|
|
|
|
|
|
|
def test_manager_get_no_devices(self):
|
|
|
|
|
os.environ['FP_DRIVERS_WHITELIST'] = 'hopefully_no_existing_driver'
|
|
|
|
|
self.daemon_start()
|
|
|
|
|
self.assertListEqual(self.manager.GetDevices(), [])
|
|
|
|
|
|
|
|
|
|
def test_manager_get_no_default_device(self):
|
|
|
|
|
os.environ['FP_DRIVERS_WHITELIST'] = 'hopefully_no_existing_driver'
|
|
|
|
|
self.daemon_start()
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('NoSuchDevice'):
|
|
|
|
|
self.manager.GetDefaultDevice()
|
|
|
|
|
|
2020-02-08 10:50:26 +01:00
|
|
|
def test_manager_get_devices_on_name_appeared(self):
|
|
|
|
|
self._appeared = False
|
|
|
|
|
|
|
|
|
|
def on_name_appeared(connection, name, name_owner):
|
|
|
|
|
self._appeared = True
|
|
|
|
|
dev_path = connection.call_sync('net.reactivated.Fprint',
|
|
|
|
|
'/net/reactivated/Fprint/Manager',
|
|
|
|
|
'net.reactivated.Fprint.Manager',
|
|
|
|
|
'GetDefaultDevice', None, None,
|
|
|
|
|
Gio.DBusCallFlags.NO_AUTO_START, 500, None)
|
|
|
|
|
self.assertIsNotNone(dev_path)
|
|
|
|
|
self.assertTrue(dev_path.startswith('/net/reactivated/Fprint/Device/'))
|
|
|
|
|
|
|
|
|
|
id = Gio.bus_watch_name_on_connection(self.dbus,
|
|
|
|
|
'net.reactivated.Fprint', Gio.BusNameWatcherFlags.NONE,
|
|
|
|
|
on_name_appeared, None)
|
|
|
|
|
|
|
|
|
|
self.daemon_start()
|
|
|
|
|
while not self._appeared:
|
|
|
|
|
ctx.iteration(True)
|
|
|
|
|
|
|
|
|
|
self.assertTrue(self._appeared)
|
|
|
|
|
Gio.bus_unwatch_name(id)
|
|
|
|
|
|
2020-02-08 09:51:40 +01:00
|
|
|
|
2020-03-17 17:01:50 +01:00
|
|
|
class FPrintdVirtualDeviceTest(FPrintdVirtualDeviceBaseTest):
|
|
|
|
|
|
2020-01-30 18:58:28 +01:00
|
|
|
def test_allowed_claim(self):
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername',
|
|
|
|
|
'net.reactivated.fprint.device.enroll'])
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
2020-02-11 00:33:14 +01:00
|
|
|
def test_allowed_claim_current_user(self):
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
|
|
|
self.device.Claim('(s)', '')
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
|
|
|
|
self.device.Claim('(s)', self.get_current_user())
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
|
|
|
|
def test_allowed_list_enrolled_fingers_empty_user(self):
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
|
|
|
self.device.Claim('(s)', '')
|
|
|
|
|
self.enroll_image('whorl', finger='left-thumb')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.verify'])
|
|
|
|
|
|
|
|
|
|
self.assertEqual(self.device.ListEnrolledFingers('(s)', ''), ['left-thumb'])
|
|
|
|
|
self.assertEqual(self.device.ListEnrolledFingers('(s)', self.get_current_user()), ['left-thumb'])
|
|
|
|
|
|
|
|
|
|
def test_allowed_list_enrolled_fingers_current_user(self):
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
|
|
|
self.device.Claim('(s)', self.get_current_user())
|
|
|
|
|
self.enroll_image('whorl', finger='right-thumb')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.verify'])
|
|
|
|
|
|
|
|
|
|
self.assertEqual(self.device.ListEnrolledFingers('(s)', ''), ['right-thumb'])
|
|
|
|
|
self.assertEqual(self.device.ListEnrolledFingers('(s)', self.get_current_user()), ['right-thumb'])
|
|
|
|
|
|
2020-01-30 18:58:28 +01:00
|
|
|
def test_unallowed_claim(self):
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername'])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
|
2020-02-11 00:33:14 +01:00
|
|
|
def test_unallowed_claim_current_user(self):
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.Claim('(s)', '')
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.Claim('(s)', self.get_current_user())
|
|
|
|
|
|
2020-01-30 18:58:28 +01:00
|
|
|
def test_multiple_claims(self):
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
|
|
|
|
def test_unallowed_release(self):
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername'])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
|
|
|
|
def test_unclaimed_release(self):
|
|
|
|
|
with self.assertFprintError('ClaimDevice'):
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
|
|
|
|
def test_unclaimed_verify_start(self):
|
|
|
|
|
with self.assertFprintError('ClaimDevice'):
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
|
|
|
|
|
def test_unclaimed_verify_stop(self):
|
|
|
|
|
with self.assertFprintError('ClaimDevice'):
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
|
|
|
|
def test_unclaimed_enroll_start(self):
|
|
|
|
|
with self.assertFprintError('ClaimDevice'):
|
|
|
|
|
self.device.EnrollStart('(s)', 'left-index-finger')
|
|
|
|
|
|
|
|
|
|
def test_unclaimed_enroll_stop(self):
|
|
|
|
|
with self.assertFprintError('ClaimDevice'):
|
|
|
|
|
self.device.EnrollStop()
|
|
|
|
|
|
|
|
|
|
def test_unclaimed_delete_enrolled_fingers(self):
|
|
|
|
|
self.device.DeleteEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
def test_unclaimed_delete_enrolled_fingers2(self):
|
|
|
|
|
with self.assertFprintError('ClaimDevice'):
|
|
|
|
|
self.device.DeleteEnrolledFingers2()
|
|
|
|
|
|
|
|
|
|
def test_unclaimed_list_enrolled_fingers(self):
|
|
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
2020-02-10 18:56:49 +01:00
|
|
|
def test_claim_device_open_fail(self):
|
|
|
|
|
os.rename(self.tmpdir, self.tmpdir + '-moved')
|
|
|
|
|
self.addCleanup(os.rename, self.tmpdir + '-moved', self.tmpdir)
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('Internal'):
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
|
2020-02-11 05:07:33 +01:00
|
|
|
def test_claim_from_other_client_is_released_when_vanished(self):
|
|
|
|
|
self.call_device_method_from_other_client('Claim', ['testuser'])
|
2020-03-27 16:57:16 +01:00
|
|
|
time.sleep(1)
|
2020-02-11 05:07:33 +01:00
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
2020-03-17 17:01:50 +01:00
|
|
|
|
|
|
|
|
class FPrintdVirtualDeviceClaimedTest(FPrintdVirtualDeviceBaseTest):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
super().setUp()
|
2020-02-06 19:52:15 +01:00
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
|
2020-03-17 17:01:50 +01:00
|
|
|
def tearDown(self):
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
|
|
|
try:
|
|
|
|
|
self.device.Release()
|
|
|
|
|
except GLib.GError as e:
|
|
|
|
|
if not 'net.reactivated.Fprint.Error.ClaimDevice' in e.message:
|
|
|
|
|
raise(e)
|
|
|
|
|
super().tearDown()
|
|
|
|
|
|
|
|
|
|
def test_wrong_finger_enroll_start(self):
|
2020-02-06 19:52:15 +01:00
|
|
|
with self.assertFprintError('InvalidFingername'):
|
|
|
|
|
self.device.EnrollStart('(s)', 'any')
|
|
|
|
|
|
2020-02-08 15:11:57 +01:00
|
|
|
def test_verify_with_no_enrolled_prints(self):
|
|
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
|
2020-01-30 18:32:30 +01:00
|
|
|
def test_enroll_verify_list_delete(self):
|
2020-01-30 18:35:28 +01:00
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', 'nottestuser')
|
|
|
|
|
|
2020-03-17 15:54:14 +01:00
|
|
|
self.enroll_image('whorl')
|
2019-10-07 15:14:21 +02:00
|
|
|
|
2020-01-30 19:25:12 +01:00
|
|
|
self.assertTrue(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
|
2019-10-07 15:14:21 +02:00
|
|
|
|
2020-01-30 18:35:28 +01:00
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', 'nottestuser')
|
|
|
|
|
|
|
|
|
|
self.assertEqual(self.device.ListEnrolledFingers('(s)', 'testuser'), ['right-index-finger'])
|
|
|
|
|
|
2019-10-07 15:14:21 +02:00
|
|
|
# Finger is enrolled, try to verify it
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
|
|
|
|
|
# Try a wrong print; will stop verification
|
|
|
|
|
self.send_image('tented_arch')
|
2020-02-06 21:16:31 +01:00
|
|
|
self.wait_for_result()
|
2020-01-30 19:25:12 +01:00
|
|
|
self.assertTrue(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, 'verify-no-match')
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
|
|
|
|
|
# Send a retry error (swipe too short); will not stop verification
|
|
|
|
|
self.send_retry()
|
2020-02-06 21:16:31 +01:00
|
|
|
self.wait_for_result()
|
2020-01-30 19:25:12 +01:00
|
|
|
self.assertFalse(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, 'verify-swipe-too-short')
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
# Try the correct print; will stop verification
|
|
|
|
|
self.send_image('whorl')
|
2020-02-06 21:16:31 +01:00
|
|
|
self.wait_for_result()
|
2020-01-30 19:25:12 +01:00
|
|
|
self.assertTrue(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, 'verify-match')
|
2019-10-07 15:14:21 +02:00
|
|
|
|
2020-01-30 18:35:28 +01:00
|
|
|
self.assertEqual(self.device.ListEnrolledFingers('(s)', 'testuser'), ['right-index-finger'])
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
# And delete the print(s) again
|
|
|
|
|
self.device.DeleteEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
2020-01-30 19:25:12 +01:00
|
|
|
self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
|
2019-10-07 15:14:21 +02:00
|
|
|
|
2020-01-30 18:35:28 +01:00
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
2019-10-07 15:14:21 +02:00
|
|
|
def test_enroll_delete2(self):
|
2020-03-17 15:54:14 +01:00
|
|
|
self.enroll_image('whorl')
|
2019-10-07 15:14:21 +02:00
|
|
|
|
2020-01-30 19:25:12 +01:00
|
|
|
self.assertTrue(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
|
2019-10-07 15:14:21 +02:00
|
|
|
|
|
|
|
|
# And delete the print(s) again using the new API
|
|
|
|
|
self.device.DeleteEnrolledFingers2()
|
|
|
|
|
|
2020-01-30 19:25:12 +01:00
|
|
|
self.assertFalse(os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7')))
|
2019-10-07 15:14:21 +02:00
|
|
|
|
2020-02-10 18:34:33 +01:00
|
|
|
def test_enroll_invalid_storage_dir(self):
|
2020-02-11 05:29:43 +01:00
|
|
|
if 'CI_PROJECT_NAME' in os.environ:
|
|
|
|
|
self.skipTest('Permissions aren\'t respected in CI environment')
|
2020-02-10 18:34:33 +01:00
|
|
|
os.makedirs(self.state_dir, mode=0o500)
|
|
|
|
|
self.addCleanup(os.chmod, self.state_dir, mode=0o700)
|
|
|
|
|
self.enroll_image('whorl', expected_result='enroll-failed')
|
|
|
|
|
|
2020-02-11 01:28:22 +01:00
|
|
|
def test_verify_invalid_storage_dir(self):
|
2020-02-11 05:29:43 +01:00
|
|
|
if 'CI_PROJECT_NAME' in os.environ:
|
|
|
|
|
self.skipTest('Permissions aren\'t respected in CI environment')
|
2020-02-11 01:28:22 +01:00
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
os.chmod(self.state_dir, mode=0o000)
|
|
|
|
|
self.addCleanup(os.chmod, self.state_dir, mode=0o700)
|
|
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
|
2020-02-10 17:22:50 +01:00
|
|
|
def test_enroll_stop_cancels(self):
|
|
|
|
|
self.device.EnrollStart('(s)', 'left-index-finger')
|
|
|
|
|
self.device.EnrollStop()
|
|
|
|
|
self.wait_for_result(expected='enroll-failed')
|
|
|
|
|
|
2020-02-10 17:23:19 +01:00
|
|
|
def test_verify_stop_cancels(self):
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
self.wait_for_result(expected='verify-no-match')
|
|
|
|
|
|
|
|
|
|
def test_verify_finger_stop_cancels(self):
|
|
|
|
|
self.enroll_image('whorl', finger='left-thumb')
|
|
|
|
|
self.device.VerifyStart('(s)', 'left-thumb')
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
2020-02-06 21:20:27 +01:00
|
|
|
def test_busy_device_release_on_enroll(self):
|
|
|
|
|
self.device.EnrollStart('(s)', 'left-index-finger')
|
|
|
|
|
|
|
|
|
|
self.device.Release()
|
|
|
|
|
self.wait_for_result(expected='enroll-failed')
|
|
|
|
|
|
|
|
|
|
def test_busy_device_release_on_verify(self):
|
|
|
|
|
self.enroll_image('whorl', finger='left-index-finger')
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
|
|
|
|
|
self.device.Release()
|
|
|
|
|
self.wait_for_result(expected='verify-no-match')
|
|
|
|
|
|
|
|
|
|
def test_busy_device_release_on_verify_finger(self):
|
|
|
|
|
self.enroll_image('whorl', finger='left-middle-finger')
|
|
|
|
|
self.device.VerifyStart('(s)', 'left-middle-finger')
|
|
|
|
|
|
|
|
|
|
self.device.Release()
|
|
|
|
|
self.wait_for_result(expected='verify-no-match')
|
|
|
|
|
|
2020-02-11 02:12:35 +01:00
|
|
|
def test_enroll_stop_not_started(self):
|
|
|
|
|
with self.assertFprintError('NoActionInProgress'):
|
|
|
|
|
self.device.EnrollStop()
|
|
|
|
|
|
|
|
|
|
def test_verify_stop_not_started(self):
|
|
|
|
|
with self.assertFprintError('NoActionInProgress'):
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
2020-02-11 02:29:45 +01:00
|
|
|
def test_verify_finger_match(self):
|
|
|
|
|
self.enroll_image('whorl', finger='left-thumb')
|
|
|
|
|
self.device.VerifyStart('(s)', 'left-thumb')
|
|
|
|
|
self.send_image('whorl')
|
|
|
|
|
self.wait_for_result()
|
|
|
|
|
self.assertTrue(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, 'verify-match')
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
|
|
|
|
def test_verify_finger_no_match(self):
|
|
|
|
|
self.enroll_image('whorl', finger='left-thumb')
|
|
|
|
|
self.device.VerifyStart('(s)', 'left-thumb')
|
|
|
|
|
self.send_image('tented_arch')
|
|
|
|
|
self.wait_for_result()
|
|
|
|
|
self.assertTrue(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, 'verify-no-match')
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
2020-10-01 14:14:02 +02:00
|
|
|
def test_verify_finger_no_match_restart(self):
|
|
|
|
|
self.enroll_image('whorl', finger='left-thumb')
|
|
|
|
|
self.device.VerifyStart('(s)', 'left-thumb')
|
|
|
|
|
self.send_image('tented_arch')
|
|
|
|
|
self.wait_for_result()
|
|
|
|
|
self.assertTrue(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, 'verify-no-match')
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
|
|
|
|
# Immediately starting again after a no-match must work
|
|
|
|
|
self.device.VerifyStart('(s)', 'left-thumb')
|
|
|
|
|
self.send_image('whorl')
|
|
|
|
|
self.wait_for_result()
|
|
|
|
|
self.assertTrue(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, 'verify-match')
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
2020-02-11 02:29:45 +01:00
|
|
|
def test_verify_wrong_finger_match(self):
|
|
|
|
|
self.enroll_image('whorl', finger='left-thumb')
|
|
|
|
|
self.device.VerifyStart('(s)', 'left-toe')
|
|
|
|
|
self.send_image('whorl')
|
|
|
|
|
self.wait_for_result()
|
|
|
|
|
self.assertTrue(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, 'verify-match')
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
|
|
|
|
def test_verify_wrong_finger_no_match(self):
|
|
|
|
|
self.enroll_image('whorl', finger='right-thumb')
|
|
|
|
|
self.device.VerifyStart('(s)', 'right-toe')
|
|
|
|
|
self.send_image('tented_arch')
|
|
|
|
|
self.wait_for_result()
|
|
|
|
|
self.assertTrue(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, 'verify-no-match')
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
|
|
|
|
def test_verify_finger_not_enrolled(self):
|
|
|
|
|
self.enroll_image('whorl', finger='left-thumb')
|
|
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.VerifyStart('(s)', 'right-thumb')
|
|
|
|
|
|
2020-02-07 19:03:24 +01:00
|
|
|
def test_unallowed_enroll_start(self):
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.EnrollStart('(s)', 'right-index-finger')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
|
|
|
|
|
def test_unallowed_enroll_stop(self):
|
|
|
|
|
self.device.EnrollStart('(s)', 'right-index-finger')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.EnrollStop()
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.enroll'])
|
|
|
|
|
self.device.EnrollStop()
|
|
|
|
|
|
|
|
|
|
def test_unallowed_verify_start(self):
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
|
|
|
|
|
def test_unallowed_verify_stop(self):
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.verify'])
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
2020-02-11 00:33:14 +01:00
|
|
|
def test_list_enrolled_fingers_current_user(self):
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.verify'])
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', '')
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('NoEnrolledPrints'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', self.get_current_user())
|
|
|
|
|
|
2020-02-07 19:03:24 +01:00
|
|
|
def test_unallowed_list_enrolled_fingers(self):
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername'])
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
2020-02-11 00:33:14 +01:00
|
|
|
def test_unallowed_list_enrolled_fingers_current_user(self):
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', '')
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', self.get_current_user())
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername'])
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', '')
|
|
|
|
|
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.ListEnrolledFingers('(s)', self.get_current_user())
|
|
|
|
|
|
2020-02-07 19:03:24 +01:00
|
|
|
def test_unallowed_delete_enrolled_fingers(self):
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.DeleteEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername'])
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.DeleteEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
def test_unallowed_delete_enrolled_fingers2(self):
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
|
|
|
|
|
self._polkitd_obj.SetAllowed([''])
|
|
|
|
|
with self.assertFprintError('PermissionDenied'):
|
|
|
|
|
self.device.DeleteEnrolledFingers2()
|
2020-02-10 17:22:50 +01:00
|
|
|
|
2020-02-11 05:07:33 +01:00
|
|
|
def test_delete_enrolled_fingers_from_other_client(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.call_device_method_from_other_client('DeleteEnrolledFingers', ['testuser'])
|
|
|
|
|
|
|
|
|
|
def test_release_from_other_client(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.call_device_method_from_other_client('Release')
|
|
|
|
|
|
|
|
|
|
def test_enroll_start_from_other_client(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.call_device_method_from_other_client('EnrollStart', ['left-index-finger'])
|
|
|
|
|
|
|
|
|
|
def test_verify_start_from_other_client(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.call_device_method_from_other_client('VerifyStart', ['any'])
|
|
|
|
|
|
|
|
|
|
def test_verify_start_finger_from_other_client(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.call_device_method_from_other_client('VerifyStart', ['left-thumb'])
|
|
|
|
|
|
2020-02-07 21:19:32 +01:00
|
|
|
|
|
|
|
|
class FPrintdVirtualDeviceEnrollTests(FPrintdVirtualDeviceBaseTest):
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
super().setUp()
|
|
|
|
|
self._abort = False
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
self.device.EnrollStart('(s)', 'left-middle-finger')
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.device.EnrollStop()
|
|
|
|
|
self.device.Release()
|
|
|
|
|
super().tearDown()
|
|
|
|
|
|
|
|
|
|
def assertEnrollRetry(self, device_error, expected_error):
|
|
|
|
|
self.send_retry(retry_error=device_error)
|
|
|
|
|
self.wait_for_result(expected=expected_error)
|
|
|
|
|
|
2020-02-08 14:51:28 +01:00
|
|
|
def assertEnrollError(self, device_error, expected_error):
|
|
|
|
|
self.send_error(error=device_error)
|
|
|
|
|
self.wait_for_result(expected=expected_error)
|
|
|
|
|
|
2020-02-07 21:19:32 +01:00
|
|
|
def test_enroll_retry_general(self):
|
|
|
|
|
self.assertEnrollRetry(FPrint.DeviceRetry.GENERAL, 'enroll-retry-scan')
|
|
|
|
|
|
|
|
|
|
def test_enroll_retry_too_short(self):
|
|
|
|
|
self.assertEnrollRetry(FPrint.DeviceRetry.TOO_SHORT, 'enroll-swipe-too-short')
|
|
|
|
|
|
|
|
|
|
def test_enroll_retry_remove_finger(self):
|
|
|
|
|
self.assertEnrollRetry(FPrint.DeviceRetry.REMOVE_FINGER, 'enroll-remove-and-retry')
|
|
|
|
|
|
|
|
|
|
def test_enroll_retry_center_finger(self):
|
|
|
|
|
self.assertEnrollRetry(FPrint.DeviceRetry.CENTER_FINGER, 'enroll-finger-not-centered')
|
|
|
|
|
|
2020-02-08 14:51:28 +01:00
|
|
|
def test_enroll_error_general(self):
|
|
|
|
|
self.assertEnrollError(FPrint.DeviceError.GENERAL, 'enroll-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_enroll_error_not_supported(self):
|
|
|
|
|
self.assertEnrollError(FPrint.DeviceError.NOT_SUPPORTED, 'enroll-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_enroll_error_not_open(self):
|
|
|
|
|
self.assertEnrollError(FPrint.DeviceError.NOT_OPEN, 'enroll-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_enroll_error_already_open(self):
|
|
|
|
|
self.assertEnrollError(FPrint.DeviceError.ALREADY_OPEN, 'enroll-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_enroll_error_busy(self):
|
|
|
|
|
self.assertEnrollError(FPrint.DeviceError.BUSY, 'enroll-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_enroll_error_proto(self):
|
|
|
|
|
self.assertEnrollError(FPrint.DeviceError.PROTO, 'enroll-disconnected')
|
|
|
|
|
|
|
|
|
|
def test_enroll_error_data_invalid(self):
|
|
|
|
|
self.assertEnrollError(FPrint.DeviceError.DATA_INVALID, 'enroll-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_enroll_error_data_not_found(self):
|
|
|
|
|
self.assertEnrollError(FPrint.DeviceError.DATA_NOT_FOUND, 'enroll-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_enroll_error_data_full(self):
|
|
|
|
|
self.assertEnrollError(FPrint.DeviceError.DATA_FULL, 'enroll-data-full')
|
|
|
|
|
|
2020-02-11 02:13:10 +01:00
|
|
|
def test_enroll_start_during_enroll(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.device.EnrollStart('(s)', 'left-thumb')
|
|
|
|
|
|
|
|
|
|
def test_verify_start_during_enroll(self):
|
|
|
|
|
self.device.EnrollStop()
|
|
|
|
|
self.wait_for_result()
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
self.device.EnrollStart('(s)', 'right-thumb')
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.device.VerifyStart('(s)', 'any')
|
|
|
|
|
|
|
|
|
|
def test_verify_stop_during_enroll(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
|
2020-02-11 05:07:33 +01:00
|
|
|
def test_enroll_stop_from_other_client(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.call_device_method_from_other_client('EnrollStop')
|
|
|
|
|
|
2020-02-07 21:19:32 +01:00
|
|
|
|
2020-02-07 20:15:54 +01:00
|
|
|
class FPrintdVirtualDeviceVerificationTests(FPrintdVirtualDeviceBaseTest):
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def setUpClass(cls):
|
|
|
|
|
super().setUpClass()
|
|
|
|
|
cls.enroll_finger = 'left-middle-finger'
|
|
|
|
|
cls.verify_finger = cls.enroll_finger
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
super().setUp()
|
|
|
|
|
self.device.Claim('(s)', 'testuser')
|
|
|
|
|
self.enroll_image('whorl', finger=self.enroll_finger)
|
|
|
|
|
self.device.VerifyStart('(s)', self.verify_finger)
|
|
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
|
self.device.VerifyStop()
|
|
|
|
|
self.device.Release()
|
|
|
|
|
super().tearDown()
|
|
|
|
|
|
|
|
|
|
def assertVerifyRetry(self, device_error, expected_error):
|
|
|
|
|
self.send_retry(retry_error=device_error)
|
|
|
|
|
self.wait_for_result()
|
|
|
|
|
self.assertFalse(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, expected_error)
|
|
|
|
|
|
2020-02-08 14:51:28 +01:00
|
|
|
def assertVerifyError(self, device_error, expected_error):
|
|
|
|
|
self.send_error(error=device_error)
|
|
|
|
|
self.wait_for_result()
|
|
|
|
|
self.assertTrue(self._verify_stopped)
|
|
|
|
|
self.assertEqual(self._last_result, expected_error)
|
|
|
|
|
|
2020-02-07 20:15:54 +01:00
|
|
|
def test_verify_retry_general(self):
|
|
|
|
|
self.assertVerifyRetry(FPrint.DeviceRetry.GENERAL, 'verify-retry-scan')
|
|
|
|
|
|
|
|
|
|
def test_verify_retry_too_short(self):
|
|
|
|
|
self.assertVerifyRetry(FPrint.DeviceRetry.TOO_SHORT, 'verify-swipe-too-short')
|
|
|
|
|
|
|
|
|
|
def test_verify_retry_remove_finger(self):
|
|
|
|
|
self.assertVerifyRetry(FPrint.DeviceRetry.REMOVE_FINGER, 'verify-remove-and-retry')
|
|
|
|
|
|
|
|
|
|
def test_verify_retry_center_finger(self):
|
|
|
|
|
self.assertVerifyRetry(FPrint.DeviceRetry.CENTER_FINGER, 'verify-finger-not-centered')
|
|
|
|
|
|
2020-02-08 14:51:28 +01:00
|
|
|
def test_verify_error_general(self):
|
|
|
|
|
self.assertVerifyError(FPrint.DeviceError.GENERAL, 'verify-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_verify_error_not_supported(self):
|
|
|
|
|
self.assertVerifyError(FPrint.DeviceError.NOT_SUPPORTED, 'verify-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_verify_error_not_open(self):
|
|
|
|
|
self.assertVerifyError(FPrint.DeviceError.NOT_OPEN, 'verify-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_verify_error_already_open(self):
|
|
|
|
|
self.assertVerifyError(FPrint.DeviceError.ALREADY_OPEN, 'verify-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_verify_error_busy(self):
|
|
|
|
|
self.assertVerifyError(FPrint.DeviceError.BUSY, 'verify-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_verify_error_proto(self):
|
|
|
|
|
self.assertVerifyError(FPrint.DeviceError.PROTO, 'verify-disconnected')
|
|
|
|
|
|
|
|
|
|
def test_verify_error_data_invalid(self):
|
|
|
|
|
self.assertVerifyError(FPrint.DeviceError.DATA_INVALID, 'verify-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_verify_error_data_not_found(self):
|
|
|
|
|
self.assertVerifyError(FPrint.DeviceError.DATA_NOT_FOUND, 'verify-unknown-error')
|
|
|
|
|
|
|
|
|
|
def test_verify_error_data_full(self):
|
|
|
|
|
self.assertVerifyError(FPrint.DeviceError.DATA_FULL, 'verify-unknown-error')
|
|
|
|
|
|
2020-02-11 02:13:10 +01:00
|
|
|
def test_verify_start_during_verify(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.device.VerifyStart('(s)', self.verify_finger)
|
|
|
|
|
|
|
|
|
|
def test_enroll_start_during_verify(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.device.EnrollStart('(s)', 'right-thumb')
|
|
|
|
|
|
|
|
|
|
def test_enroll_stop_during_verify(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.device.EnrollStop()
|
|
|
|
|
|
2020-02-11 05:07:33 +01:00
|
|
|
def test_verify_stop_from_other_client(self):
|
|
|
|
|
with self.assertFprintError('AlreadyInUse'):
|
|
|
|
|
self.call_device_method_from_other_client('VerifyStop')
|
|
|
|
|
|
2020-02-07 20:15:54 +01:00
|
|
|
|
|
|
|
|
class FPrintdVirtualDeviceIdentificationTests(FPrintdVirtualDeviceVerificationTests):
|
|
|
|
|
'''This class will just repeat the tests of FPrintdVirtualDeviceVerificationTests
|
|
|
|
|
but with 'any' finger parameter (leading to an identification, when possible
|
|
|
|
|
under the hood).
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def setUpClass(cls):
|
|
|
|
|
super().setUpClass()
|
|
|
|
|
cls.verify_finger = 'any'
|
|
|
|
|
|
|
|
|
|
|
2020-02-11 05:12:46 +01:00
|
|
|
class FPrintdUtilsTest(FPrintdVirtualDeviceBaseTest):
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def setUpClass(cls):
|
|
|
|
|
super().setUpClass()
|
|
|
|
|
utils = {
|
|
|
|
|
'delete': None,
|
|
|
|
|
'enroll': None,
|
|
|
|
|
'list': None,
|
|
|
|
|
'verify': None,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for util in utils:
|
|
|
|
|
util_bin = 'fprintd-{}'.format(util)
|
|
|
|
|
if 'FPRINT_BUILD_DIR' in os.environ:
|
|
|
|
|
print('Testing local build')
|
|
|
|
|
build_dir = os.environ['FPRINT_BUILD_DIR']
|
|
|
|
|
path = os.path.join(build_dir, '../utils', util_bin)
|
|
|
|
|
elif 'UNDER_JHBUILD' in os.environ:
|
|
|
|
|
print('Testing JHBuild version')
|
|
|
|
|
jhbuild_prefix = os.environ['JHBUILD_PREFIX']
|
|
|
|
|
path = os.path.join(jhbuild_prefix, 'bin', util_bin)
|
|
|
|
|
|
|
|
|
|
assert os.path.exists(path), 'failed to find {} in {}'.format(util, path)
|
|
|
|
|
utils[util] = path
|
|
|
|
|
|
|
|
|
|
cls.utils = utils
|
|
|
|
|
cls.utils_proc = {}
|
|
|
|
|
|
|
|
|
|
def util_start(self, name, args=[]):
|
|
|
|
|
env = os.environ.copy()
|
|
|
|
|
env['G_DEBUG'] = 'fatal-criticals'
|
|
|
|
|
env['STATE_DIRECTORY'] = self.state_dir
|
|
|
|
|
env['RUNTIME_DIRECTORY'] = self.run_dir
|
|
|
|
|
|
|
|
|
|
argv = [self.utils[name]] + args
|
|
|
|
|
valgrind = os.getenv('VALGRIND')
|
|
|
|
|
if valgrind is not None:
|
|
|
|
|
argv.insert(0, 'valgrind')
|
|
|
|
|
argv.insert(1, '--leak-check=full')
|
|
|
|
|
if os.path.exists(valgrind):
|
|
|
|
|
argv.insert(2, '--suppressions=%s' % valgrind)
|
|
|
|
|
self.valgrind = True
|
|
|
|
|
self.utils_proc[name] = subprocess.Popen(argv,
|
|
|
|
|
env=env,
|
|
|
|
|
stdout=None,
|
|
|
|
|
stderr=subprocess.STDOUT)
|
|
|
|
|
self.addCleanup(self.utils_proc[name].terminate)
|
|
|
|
|
self.addCleanup(self.utils_proc[name].wait)
|
|
|
|
|
return self.utils_proc[name]
|
|
|
|
|
|
|
|
|
|
def test_vanished_client_operation_is_cancelled(self):
|
|
|
|
|
self.device.Claim('(s)', self.get_current_user())
|
|
|
|
|
self.enroll_image('whorl')
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
|
|
|
|
verify = self.util_start('verify')
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
verify.terminate()
|
|
|
|
|
self.assertLess(verify.wait(), 128)
|
|
|
|
|
time.sleep(1)
|
|
|
|
|
|
|
|
|
|
self.device.Claim('(s)', self.get_current_user())
|
|
|
|
|
self.device.Release()
|
|
|
|
|
|
2020-02-06 20:02:16 +01:00
|
|
|
def test_already_claimed_same_user_delete_enrolled_fingers(self):
|
|
|
|
|
self.device.DeleteEnrolledFingers('(s)', 'testuser')
|
|
|
|
|
|
|
|
|
|
def test_already_claimed_other_user_delete_enrolled_fingers(self):
|
|
|
|
|
self.device.DeleteEnrolledFingers('(s)', 'nottestuser')
|
|
|
|
|
|
2020-02-11 05:12:46 +01:00
|
|
|
|
2020-02-06 18:35:43 +01:00
|
|
|
|
|
|
|
|
def list_tests():
|
|
|
|
|
import unittest_inspector
|
|
|
|
|
return unittest_inspector.list_tests(sys.modules[__name__])
|
|
|
|
|
|
2019-10-07 15:14:21 +02:00
|
|
|
if __name__ == '__main__':
|
|
|
|
|
if len(sys.argv) == 2 and sys.argv[1] == "list-tests":
|
|
|
|
|
for machine, human in list_tests():
|
|
|
|
|
print("%s %s" % (machine, human), end="\n")
|
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
|
|
unittest.main(verbosity=2)
|