Blame tests/fprintd.py

Packit Service f1aff6
#! /usr/bin/env python3
Packit Service f1aff6
# Copyright © 2017, 2019 Red Hat, Inc
Packit Service f1aff6
#
Packit Service f1aff6
# This program is free software; you can redistribute it and/or
Packit Service f1aff6
# modify it under the terms of the GNU Lesser General Public
Packit Service f1aff6
# License as published by the Free Software Foundation; either
Packit Service f1aff6
# version 2.1 of the License, or (at your option) any later version.
Packit Service f1aff6
#
Packit Service f1aff6
# This program is distributed in the hope that it will be useful,
Packit Service f1aff6
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service f1aff6
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service f1aff6
# Lesser General Public License for more details.
Packit Service f1aff6
#
Packit Service f1aff6
# You should have received a copy of the GNU Lesser General Public
Packit Service f1aff6
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
Packit Service f1aff6
# Authors:
Packit Service f1aff6
#       Christian J. Kellner <christian@kellner.me>
Packit Service f1aff6
#       Benjamin Berg <bberg@redhat.com>
Packit Service f1aff6
Packit Service f1aff6
import unittest
Packit Service f1aff6
import time
Packit Service f1aff6
import subprocess
Packit Service f1aff6
import os
Packit Service f1aff6
import os.path
Packit Service f1aff6
import sys
Packit Service f1aff6
import tempfile
Packit Service f1aff6
import glob
Packit Service f1aff6
import shutil
Packit Service f1aff6
import socket
Packit Service f1aff6
import struct
Packit Service f1aff6
import dbusmock
Packit Service f1aff6
import gi
Packit Service f1aff6
from gi.repository import GLib, Gio
Packit Service f1aff6
import cairo
Packit Service f1aff6
Packit Service f1aff6
try:
Packit Service f1aff6
    from subprocess import DEVNULL
Packit Service f1aff6
except ImportError:
Packit Service f1aff6
    DEVNULL = open(os.devnull, 'wb')
Packit Service f1aff6
Packit Service f1aff6
SERVICE_FILE = '/usr/share/dbus-1/system-services/net.reactivated.Fprint.service'
Packit Service f1aff6
Packit Service f1aff6
def get_timeout(topic='default'):
Packit Service f1aff6
    vals = {
Packit Service f1aff6
        'valgrind': {
Packit Service f1aff6
            'test': 300,
Packit Service f1aff6
            'default': 20,
Packit Service f1aff6
            'daemon_start': 60
Packit Service f1aff6
        },
Packit Service f1aff6
        'default': {
Packit Service f1aff6
            'test': 60,
Packit Service f1aff6
            'default': 3,
Packit Service f1aff6
            'daemon_start': 5
Packit Service f1aff6
        }
Packit Service f1aff6
    }
Packit Service f1aff6
Packit Service f1aff6
    valgrind = os.getenv('VALGRIND')
Packit Service f1aff6
    lut = vals['valgrind' if valgrind is not None else 'default']
Packit Service f1aff6
    if topic not in lut:
Packit Service f1aff6
        raise ValueError('invalid topic')
Packit Service f1aff6
    return lut[topic]
Packit Service f1aff6
Packit Service f1aff6
Packit Service f1aff6
# Copied from libfprint tests
Packit Service f1aff6
class Connection:
Packit Service f1aff6
Packit Service f1aff6
    def __init__(self, addr):
Packit Service f1aff6
        self.addr = addr
Packit Service f1aff6
Packit Service f1aff6
    def __enter__(self):
Packit Service f1aff6
        self.con = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
Packit Service f1aff6
        self.con.connect(self.addr)
Packit Service f1aff6
        return self.con
Packit Service f1aff6
Packit Service f1aff6
    def __exit__(self, exc_type, exc_val, exc_tb):
Packit Service f1aff6
        self.con.close()
Packit Service f1aff6
        del self.con
Packit Service f1aff6
Packit Service f1aff6
def load_image(img):
Packit Service f1aff6
    png = cairo.ImageSurface.create_from_png(img)
Packit Service f1aff6
Packit Service f1aff6
    # Cairo wants 4 byte aligned rows, so just add a few pixel if necessary
Packit Service f1aff6
    w = png.get_width()
Packit Service f1aff6
    h = png.get_height()
Packit Service f1aff6
    w = (w + 3) // 4 * 4
Packit Service f1aff6
    h = (h + 3) // 4 * 4
Packit Service f1aff6
    img = cairo.ImageSurface(cairo.Format.A8, w, h)
Packit Service f1aff6
    cr = cairo.Context(img)
Packit Service f1aff6
Packit Service f1aff6
    cr.set_source_rgba(1, 1, 1, 1)
Packit Service f1aff6
    cr.paint()
Packit Service f1aff6
Packit Service f1aff6
    cr.set_source_rgba(0, 0, 0, 0)
Packit Service f1aff6
    cr.set_operator(cairo.OPERATOR_SOURCE)
Packit Service f1aff6
Packit Service f1aff6
    cr.set_source_surface(png)
Packit Service f1aff6
    cr.paint()
Packit Service f1aff6
Packit Service f1aff6
    return img
Packit Service f1aff6
Packit Service f1aff6
if hasattr(os.environ, 'TOPSRCDIR'):
Packit Service f1aff6
    root = os.environ['TOPSRCDIR']
Packit Service f1aff6
else:
Packit Service f1aff6
    root = os.path.join(os.path.dirname(__file__), '..')
Packit Service f1aff6
Packit Service f1aff6
imgdir = os.path.join(root, 'tests', 'prints')
Packit Service f1aff6
Packit Service f1aff6
ctx = GLib.main_context_default()
Packit Service f1aff6
Packit Service f1aff6
class FPrintdTest(dbusmock.DBusTestCase):
Packit Service f1aff6
Packit Service f1aff6
    @staticmethod
Packit Service f1aff6
    def path_from_service_file(sf):
Packit Service f1aff6
        with open(SERVICE_FILE) as f:
Packit Service f1aff6
                for line in f:
Packit Service f1aff6
                    if not line.startswith('Exec='):
Packit Service f1aff6
                        continue
Packit Service f1aff6
                    return line.split('=', 1)[1].strip()
Packit Service f1aff6
        return None
Packit Service f1aff6
Packit Service f1aff6
    @classmethod
Packit Service f1aff6
    def setUpClass(cls):
Packit Service f1aff6
        fprintd = None
Packit Service f1aff6
Packit Service f1aff6
        if 'FPRINT_BUILD_DIR' in os.environ:
Packit Service f1aff6
            print('Testing local build')
Packit Service f1aff6
            build_dir = os.environ['FPRINT_BUILD_DIR']
Packit Service f1aff6
            fprintd = os.path.join(build_dir, 'fprintd')
Packit Service f1aff6
        elif 'UNDER_JHBUILD' in os.environ:
Packit Service f1aff6
            print('Testing JHBuild version')
Packit Service f1aff6
            jhbuild_prefix = os.environ['JHBUILD_PREFIX']
Packit Service f1aff6
            fprintd = os.path.join(jhbuild_prefix, 'libexec', 'fprintd')
Packit Service f1aff6
        else:
Packit Service f1aff6
            print('Testing installed system binaries')
Packit Service f1aff6
            fprintd = cls.path_from_service_file(SERVICE_FILE)
Packit Service f1aff6
Packit Service f1aff6
        assert fprintd is not None, 'failed to find daemon'
Packit Service f1aff6
        cls.paths = {'daemon': fprintd }
Packit Service f1aff6
Packit Service f1aff6
Packit Service f1aff6
        cls.tmpdir = tempfile.mkdtemp(prefix='libfprint-')
Packit Service f1aff6
Packit Service f1aff6
        cls.sockaddr = os.path.join(cls.tmpdir, 'virtual-image.socket')
Packit Service f1aff6
        os.environ['FP_VIRTUAL_IMAGE'] = cls.sockaddr
Packit Service f1aff6
Packit Service f1aff6
        cls.prints = {}
Packit Service f1aff6
        for f in glob.glob(os.path.join(imgdir, '*.png')):
Packit Service f1aff6
            n = os.path.basename(f)[:-4]
Packit Service f1aff6
            cls.prints[n] = load_image(f)
Packit Service f1aff6
Packit Service f1aff6
Packit Service f1aff6
        cls.test_bus = Gio.TestDBus.new(Gio.TestDBusFlags.NONE)
Packit Service f1aff6
        cls.test_bus.up()
Packit Service f1aff6
        try:
Packit Service f1aff6
            del os.environ['DBUS_SESSION_BUS_ADDRESS']
Packit Service f1aff6
        except KeyError:
Packit Service f1aff6
            pass
Packit Service f1aff6
        os.environ['DBUS_SYSTEM_BUS_ADDRESS'] = cls.test_bus.get_bus_address()
Packit Service f1aff6
        cls.dbus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
Packit Service f1aff6
Packit Service f1aff6
    @classmethod
Packit Service f1aff6
    def tearDownClass(cls):
Packit Service f1aff6
        cls.test_bus.down()
Packit Service f1aff6
        shutil.rmtree(cls.tmpdir)
Packit Service f1aff6
        dbusmock.DBusTestCase.tearDownClass()
Packit Service f1aff6
Packit Service f1aff6
Packit Service f1aff6
    def daemon_start(self):
Packit Service f1aff6
        timeout = get_timeout('daemon_start')  # seconds
Packit Service f1aff6
        env = os.environ.copy()
Packit Service f1aff6
        env['G_DEBUG'] = 'fatal-criticals'
Packit Service f1aff6
        env['STATE_DIRECTORY'] = self.state_dir
Packit Service f1aff6
        env['RUNTIME_DIRECTORY'] = self.run_dir
Packit Service f1aff6
Packit Service f1aff6
        argv = [self.paths['daemon'], '-t']
Packit Service f1aff6
        valgrind = os.getenv('VALGRIND')
Packit Service f1aff6
        if valgrind is not None:
Packit Service f1aff6
            argv.insert(0, 'valgrind')
Packit Service f1aff6
            argv.insert(1, '--leak-check=full')
Packit Service f1aff6
            if os.path.exists(valgrind):
Packit Service f1aff6
                argv.insert(2, '--suppressions=%s' % valgrind)
Packit Service f1aff6
            self.valgrind = True
Packit Service f1aff6
        self.daemon = subprocess.Popen(argv,
Packit Service f1aff6
                                       env=env,
Packit Service f1aff6
                                       stdout=None,
Packit Service f1aff6
                                       stderr=subprocess.STDOUT)
Packit Service f1aff6
        self.device = None
Packit Service f1aff6
Packit Service f1aff6
        timeout_count = timeout * 10
Packit Service f1aff6
        timeout_sleep = 0.1
Packit Service f1aff6
        while timeout_count > 0:
Packit Service f1aff6
            time.sleep(timeout_sleep)
Packit Service f1aff6
            timeout_count -= 1
Packit Service f1aff6
            try:
Packit Service f1aff6
                self.manager = Gio.DBusProxy.new_sync(self.dbus,
Packit Service f1aff6
                                                      Gio.DBusProxyFlags.DO_NOT_AUTO_START,
Packit Service f1aff6
                                                      None,
Packit Service f1aff6
                                                      'net.reactivated.Fprint',
Packit Service f1aff6
                                                      '/net/reactivated/Fprint/Manager',
Packit Service f1aff6
                                                      'net.reactivated.Fprint.Manager',
Packit Service f1aff6
                                                      None)
Packit Service f1aff6
Packit Service f1aff6
                devices = self.manager.GetDevices()
Packit Service f1aff6
                # Find the virtual device, just in case it is a local run
Packit Service f1aff6
                # and there is another usable sensor available locally
Packit Service f1aff6
                for path in devices:
Packit Service f1aff6
                    dev = Gio.DBusProxy.new_sync(self.dbus,
Packit Service f1aff6
                                                 Gio.DBusProxyFlags.DO_NOT_AUTO_START,
Packit Service f1aff6
                                                 None,
Packit Service f1aff6
                                                 'net.reactivated.Fprint',
Packit Service f1aff6
                                                 path,
Packit Service f1aff6
                                                 'net.reactivated.Fprint.Device',
Packit Service f1aff6
                                                 None)
Packit Service f1aff6
Packit Service f1aff6
                    if 'Virtual image device' in str(dev.get_cached_property('name')):
Packit Service f1aff6
                        self.device = dev
Packit Service f1aff6
                        break
Packit Service f1aff6
                else:
Packit Service f1aff6
                    print('Did not find virtual device! Probably libfprint was build without the corresponding driver!')
Packit Service f1aff6
Packit Service f1aff6
                break
Packit Service f1aff6
            except GLib.GError:
Packit Service f1aff6
                pass
Packit Service f1aff6
        else:
Packit Service f1aff6
            timeout_time = timeout * 10 * timeout_sleep
Packit Service f1aff6
            self.fail('daemon did not start in %d seconds' % timeout_time)
Packit Service f1aff6
Packit Service f1aff6
    def daemon_stop(self):
Packit Service f1aff6
Packit Service f1aff6
        if self.daemon:
Packit Service f1aff6
            try:
Packit Service f1aff6
                self.daemon.terminate()
Packit Service f1aff6
            except OSError:
Packit Service f1aff6
                pass
Packit Service f1aff6
            self.daemon.wait()
Packit Service f1aff6
Packit Service f1aff6
        self.daemon = None
Packit Service f1aff6
        self.client = None
Packit Service f1aff6
Packit Service f1aff6
    def polkitd_start(self):
Packit Service f1aff6
        self._polkitd, self._polkitd_obj = self.spawn_server_template(
Packit Service f1aff6
            'polkitd', {}, stdout=DEVNULL)
Packit Service f1aff6
Packit Service f1aff6
    def polkitd_stop(self):
Packit Service f1aff6
        if self._polkitd is None:
Packit Service f1aff6
            return
Packit Service f1aff6
        self._polkitd.terminate()
Packit Service f1aff6
        self._polkitd.wait()
Packit Service f1aff6
Packit Service f1aff6
Packit Service f1aff6
Packit Service f1aff6
    def setUp(self):
Packit Service f1aff6
        self.test_dir = tempfile.mkdtemp()
Packit Service f1aff6
        self.state_dir = os.path.join(self.test_dir, 'state')
Packit Service f1aff6
        self.run_dir = os.path.join(self.test_dir, 'run')
Packit Service f1aff6
Packit Service f1aff6
    def tearDown(self):
Packit Service f1aff6
        shutil.rmtree(self.test_dir)
Packit Service f1aff6
Packit Service f1aff6
    # From libfprint tests
Packit Service f1aff6
    def send_retry(self, retry_error=1):
Packit Service f1aff6
        # The default (1) is too-short
Packit Service f1aff6
        with Connection(self.sockaddr) as con:
Packit Service f1aff6
            con.sendall(struct.pack('ii', -1, retry_error))
Packit Service f1aff6
Packit Service f1aff6
    # From libfprint tests
Packit Service f1aff6
    def send_image(self, image):
Packit Service f1aff6
        img = self.prints[image]
Packit Service f1aff6
        with Connection(self.sockaddr) as con:
Packit Service f1aff6
            mem = img.get_data()
Packit Service f1aff6
            mem = mem.tobytes()
Packit Service f1aff6
            assert len(mem) == img.get_width() * img.get_height()
Packit Service f1aff6
Packit Service f1aff6
            encoded_img = struct.pack('ii', img.get_width(), img.get_height())
Packit Service f1aff6
            encoded_img += mem
Packit Service f1aff6
Packit Service f1aff6
            con.sendall(encoded_img)
Packit Service f1aff6
Packit Service f1aff6
    def test_enroll_verify_delete(self):
Packit Service f1aff6
        self.polkitd_start()
Packit Service f1aff6
        self.daemon_start()
Packit Service f1aff6
Packit Service f1aff6
        if self.device is None:
Packit Service f1aff6
            self.daemon_stop()
Packit Service f1aff6
            self.polkitd_stop()
Packit Service f1aff6
            self.skipTest("Need virtual_image device to run the test")
Packit Service f1aff6
Packit Service f1aff6
        def timeout_cb(*args):
Packit Service f1aff6
            # Note: With meson we could just rely on it to kill us
Packit Service f1aff6
            print("Test timed out, hard exiting")
Packit Service f1aff6
            sys.exit(1)
Packit Service f1aff6
Packit Service f1aff6
        timeout = GLib.timeout_add(get_timeout('test') * 1000, timeout_cb)
Packit Service f1aff6
Packit Service f1aff6
        self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername',
Packit Service f1aff6
                                      'net.reactivated.fprint.device.enroll',
Packit Service f1aff6
                                      'net.reactivated.fprint.device.verify'])
Packit Service f1aff6
Packit Service f1aff6
        def signal_cb(proxy, sender, signal, params):
Packit Service f1aff6
            print(signal, params)
Packit Service f1aff6
            if signal == 'EnrollStatus':
Packit Service f1aff6
                self._abort = params[1]
Packit Service f1aff6
                self._last_result = params[0]
Packit Service f1aff6
Packit Service f1aff6
                if not self._abort and self._last_result == 'enroll-stage-passed':
Packit Service f1aff6
                    self.send_image('whorl')
Packit Service f1aff6
                elif self._abort:
Packit Service f1aff6
                    pass
Packit Service f1aff6
                else:
Packit Service f1aff6
                    self._abort = True
Packit Service f1aff6
                    self._last_result = 'Unexpected signal values'
Packit Service f1aff6
                    print('Unexpected signal values')
Packit Service f1aff6
            elif signal == 'VerifyFingerSelected':
Packit Service f1aff6
                pass
Packit Service f1aff6
            elif signal == 'VerifyStatus':
Packit Service f1aff6
                self._abort = True
Packit Service f1aff6
                self._last_result = params[0]
Packit Service f1aff6
                self._verify_stopped = params[1]
Packit Service f1aff6
            else:
Packit Service f1aff6
                self._abort = True
Packit Service f1aff6
                self._last_result = 'Unexpected signal'
Packit Service f1aff6
Packit Service f1aff6
        signal_id = self.device.connect('g-signal', signal_cb)
Packit Service f1aff6
Packit Service f1aff6
        self.device.Claim('(s)', 'testuser')
Packit Service f1aff6
Packit Service f1aff6
        self.device.EnrollStart('(s)', 'right-index-finger')
Packit Service f1aff6
Packit Service f1aff6
        self.send_image('whorl')
Packit Service f1aff6
Packit Service f1aff6
        self._abort = False
Packit Service f1aff6
        while not self._abort:
Packit Service f1aff6
            ctx.iteration(True)
Packit Service f1aff6
Packit Service f1aff6
        assert self._last_result == 'enroll-completed'
Packit Service f1aff6
Packit Service f1aff6
        self.device.EnrollStop()
Packit Service f1aff6
Packit Service f1aff6
        assert os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7'))
Packit Service f1aff6
Packit Service f1aff6
        # Finger is enrolled, try to verify it
Packit Service f1aff6
        self.device.VerifyStart('(s)', 'any')
Packit Service f1aff6
Packit Service f1aff6
        # Try a wrong print; will stop verification
Packit Service f1aff6
        self.send_image('tented_arch')
Packit Service f1aff6
        self._abort = False
Packit Service f1aff6
        while not self._abort:
Packit Service f1aff6
            ctx.iteration(True)
Packit Service f1aff6
        assert self._verify_stopped == True
Packit Service f1aff6
        assert self._last_result == 'verify-no-match'
Packit Service f1aff6
Packit Service f1aff6
        self.device.VerifyStop()
Packit Service f1aff6
        self.device.VerifyStart('(s)', 'any')
Packit Service f1aff6
Packit Service f1aff6
        # Send a retry error (swipe too short); will not stop verification
Packit Service f1aff6
        self.send_retry()
Packit Service f1aff6
        self._abort = False
Packit Service f1aff6
        while not self._abort:
Packit Service f1aff6
            ctx.iteration(True)
Packit Service f1aff6
        assert self._verify_stopped == False
Packit Service f1aff6
        assert self._last_result == 'verify-swipe-too-short'
Packit Service f1aff6
Packit Service f1aff6
        # Try the correct print; will stop verification
Packit Service f1aff6
        self.send_image('whorl')
Packit Service f1aff6
        self._abort = False
Packit Service f1aff6
        while not self._abort:
Packit Service f1aff6
            ctx.iteration(True)
Packit Service f1aff6
        assert self._verify_stopped == True
Packit Service f1aff6
        assert self._last_result == 'verify-match'
Packit Service f1aff6
Packit Service f1aff6
Packit Service f1aff6
        # And delete the print(s) again
Packit Service f1aff6
        self.device.DeleteEnrolledFingers('(s)', 'testuser')
Packit Service f1aff6
Packit Service f1aff6
        assert not os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7'))
Packit Service f1aff6
Packit Service f1aff6
        GLib.source_remove(timeout)
Packit Service f1aff6
Packit Service f1aff6
        self.device.disconnect(signal_id)
Packit Service f1aff6
Packit Service f1aff6
        self.device.Release()
Packit Service f1aff6
        self.daemon_stop()
Packit Service f1aff6
        self.polkitd_stop()
Packit Service f1aff6
Packit Service f1aff6
    def test_enroll_delete2(self):
Packit Service f1aff6
        self.polkitd_start()
Packit Service f1aff6
        self.daemon_start()
Packit Service f1aff6
Packit Service f1aff6
        if self.device is None:
Packit Service f1aff6
            self.daemon_stop()
Packit Service f1aff6
            self.polkitd_stop()
Packit Service f1aff6
            self.skipTest("Need virtual_image device to run the test")
Packit Service f1aff6
Packit Service f1aff6
        def timeout_cb(*args):
Packit Service f1aff6
            # Note: With meson we could just rely on it to kill us
Packit Service f1aff6
            print("Test timed out, hard exiting")
Packit Service f1aff6
            sys.exit(1)
Packit Service f1aff6
Packit Service f1aff6
        timeout = GLib.timeout_add(get_timeout('test') * 1000, timeout_cb)
Packit Service f1aff6
Packit Service f1aff6
        self._polkitd_obj.SetAllowed(['net.reactivated.fprint.device.setusername',
Packit Service f1aff6
                                      'net.reactivated.fprint.device.enroll',
Packit Service f1aff6
                                      'net.reactivated.fprint.device.verify'])
Packit Service f1aff6
Packit Service f1aff6
        def signal_cb(proxy, sender, signal, params):
Packit Service f1aff6
            print(signal, params)
Packit Service f1aff6
            if signal == 'EnrollStatus':
Packit Service f1aff6
                self._abort = params[1]
Packit Service f1aff6
                self._last_result = params[0]
Packit Service f1aff6
Packit Service f1aff6
                if not self._abort and self._last_result == 'enroll-stage-passed':
Packit Service f1aff6
                    self.send_image('whorl')
Packit Service f1aff6
                elif self._abort:
Packit Service f1aff6
                    pass
Packit Service f1aff6
                else:
Packit Service f1aff6
                    self._abort = True
Packit Service f1aff6
                    self._last_result = 'Unexpected signal values'
Packit Service f1aff6
                    print('Unexpected signal values')
Packit Service f1aff6
            elif signal == 'VerifyFingerSelected':
Packit Service f1aff6
                pass
Packit Service f1aff6
            elif signal == 'VerifyStatus':
Packit Service f1aff6
                self._abort = True
Packit Service f1aff6
                self._last_result = params[0]
Packit Service f1aff6
                self._verify_stopped = params[1]
Packit Service f1aff6
            else:
Packit Service f1aff6
                self._abort = True
Packit Service f1aff6
                self._last_result = 'Unexpected signal'
Packit Service f1aff6
Packit Service f1aff6
        signal_id = self.device.connect('g-signal', signal_cb)
Packit Service f1aff6
Packit Service f1aff6
        self.device.Claim('(s)', 'testuser')
Packit Service f1aff6
Packit Service f1aff6
        self.device.EnrollStart('(s)', 'right-index-finger')
Packit Service f1aff6
Packit Service f1aff6
        self.send_image('whorl')
Packit Service f1aff6
Packit Service f1aff6
        self._abort = False
Packit Service f1aff6
        while not self._abort:
Packit Service f1aff6
            ctx.iteration(True)
Packit Service f1aff6
Packit Service f1aff6
        assert self._last_result == 'enroll-completed'
Packit Service f1aff6
Packit Service f1aff6
        self.device.EnrollStop()
Packit Service f1aff6
Packit Service f1aff6
        assert os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7'))
Packit Service f1aff6
Packit Service f1aff6
        # And delete the print(s) again using the new API
Packit Service f1aff6
        self.device.DeleteEnrolledFingers2()
Packit Service f1aff6
Packit Service f1aff6
        assert not os.path.exists(os.path.join(self.state_dir, 'testuser/virtual_image/0/7'))
Packit Service f1aff6
Packit Service f1aff6
        GLib.source_remove(timeout)
Packit Service f1aff6
Packit Service f1aff6
        self.device.disconnect(signal_id)
Packit Service f1aff6
Packit Service f1aff6
        self.device.Release()
Packit Service f1aff6
        self.daemon_stop()
Packit Service f1aff6
        self.polkitd_stop()
Packit Service f1aff6
Packit Service f1aff6
if __name__ == '__main__':
Packit Service f1aff6
    if len(sys.argv) == 2 and sys.argv[1] == "list-tests":
Packit Service f1aff6
        for machine, human in list_tests():
Packit Service f1aff6
            print("%s %s" % (machine, human), end="\n")
Packit Service f1aff6
        sys.exit(0)
Packit Service f1aff6
Packit Service f1aff6
    unittest.main(verbosity=2)