Blame tests/test_fprintd_utils.py

Packit Service 8ebd8e
#!/usr/bin/python3
Packit Service 8ebd8e
Packit Service 8ebd8e
# This program is free software; you can redistribute it and/or modify it under
Packit Service 8ebd8e
# the terms of the GNU Lesser General Public License as published by the Free
Packit Service 8ebd8e
# Software Foundation; either version 3 of the License, or (at your option) any
Packit Service 8ebd8e
# later version.  See http://www.gnu.org/copyleft/lgpl.html for the full text
Packit Service 8ebd8e
# of the license.
Packit Service 8ebd8e
Packit Service 8ebd8e
__author__ = 'Bastien Nocera'
Packit Service 8ebd8e
__email__ = 'hadess@hadess.net'
Packit Service 8ebd8e
__copyright__ = '(c) 2020 Red Hat Inc.'
Packit Service 8ebd8e
__license__ = 'LGPL 3+'
Packit Service 8ebd8e
Packit Service 8ebd8e
import tempfile
Packit Service 8ebd8e
import unittest
Packit Service 8ebd8e
import sys
Packit Service 8ebd8e
import subprocess
Packit Service 8ebd8e
import dbus
Packit Service 8ebd8e
import dbus.mainloop.glib
Packit Service 8ebd8e
import dbusmock
Packit Service 8ebd8e
import os
Packit Service 8ebd8e
import time
Packit Service 8ebd8e
from output_checker import OutputChecker
Packit Service 8ebd8e
Packit Service 8ebd8e
Packit Service 8ebd8e
VALID_FINGER_NAMES = [
Packit Service 8ebd8e
    'left-thumb',
Packit Service 8ebd8e
    'left-index-finger',
Packit Service 8ebd8e
    'left-middle-finger',
Packit Service 8ebd8e
    'left-ring-finger',
Packit Service 8ebd8e
    'left-little-finger',
Packit Service 8ebd8e
    'right-thumb',
Packit Service 8ebd8e
    'right-index-finger',
Packit Service 8ebd8e
    'right-middle-finger',
Packit Service 8ebd8e
    'right-ring-finger',
Packit Service 8ebd8e
    'right-little-finger'
Packit Service 8ebd8e
]
Packit Service 8ebd8e
Packit Service 8ebd8e
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
Packit Service 8ebd8e
Packit Service 8ebd8e
class TestFprintdUtilsBase(dbusmock.DBusTestCase):
Packit Service 8ebd8e
    '''Test fprintd utilities'''
Packit Service 8ebd8e
Packit Service 8ebd8e
    @classmethod
Packit Service 8ebd8e
    def setUpClass(klass):
Packit Service 8ebd8e
        klass.start_system_bus()
Packit Service 8ebd8e
        klass.dbus_con = klass.get_dbus(True)
Packit Service 8ebd8e
        klass.sleep_time = 0.5
Packit Service 8ebd8e
Packit Service 8ebd8e
        template_path = './'
Packit Service 8ebd8e
        if 'TOPSRCDIR' in os.environ:
Packit Service 8ebd8e
            template_path = os.environ['TOPSRCDIR'] + '/tests/'
Packit Service 8ebd8e
        klass.template_name = template_path + 'dbusmock/fprintd.py'
Packit Service 8ebd8e
        print ('Using template from %s' % klass.template_name)
Packit Service 8ebd8e
Packit Service 8ebd8e
        klass.tools_prefix = ''
Packit Service 8ebd8e
        if 'FPRINT_BUILD_DIR' in os.environ:
Packit Service 8ebd8e
            klass.tools_prefix = os.environ['FPRINT_BUILD_DIR'] + '/../utils/'
Packit Service 8ebd8e
            print ('Using tools from %s' % klass.tools_prefix)
Packit Service 8ebd8e
        else:
Packit Service 8ebd8e
            print ('Using tools from $PATH')
Packit Service 8ebd8e
Packit Service 8ebd8e
        klass.wrapper_args = []
Packit Service 8ebd8e
        klass.valgrind = False
Packit Service 8ebd8e
        if 'VALGRIND' in os.environ:
Packit Service 8ebd8e
            valgrind = os.environ['VALGRIND']
Packit Service 8ebd8e
            if valgrind is not None:
Packit Service 8ebd8e
                klass.valgrind = True
Packit Service 8ebd8e
                klass.sleep_time *= 4
Packit Service 8ebd8e
                klass.wrapper_args = ['valgrind', '--leak-check=full']
Packit Service 8ebd8e
                if os.path.exists(valgrind):
Packit Service 8ebd8e
                    klass.wrapper_args += ['--suppressions={}'.format(valgrind)]
Packit Service 8ebd8e
Packit Service 8ebd8e
        if 'ADDRESS_SANITIZER' in os.environ:
Packit Service 8ebd8e
            klass.sleep_time *= 2
Packit Service 8ebd8e
Packit Service 8ebd8e
    def setUp(self):
Packit Service 8ebd8e
        super().setUp()
Packit Service 8ebd8e
        (self.p_mock, self.obj_fprintd_manager) = self.spawn_server_template(
Packit Service 8ebd8e
            self.template_name, {})
Packit Service 8ebd8e
        # set log to nonblocking
Packit Service 8ebd8e
        self.obj_fprintd_mock = dbus.Interface(self.obj_fprintd_manager, 'net.reactivated.Fprint.Manager.Mock')
Packit Service 8ebd8e
Packit Service 8ebd8e
    def tearDown(self):
Packit Service 8ebd8e
        self.p_mock.terminate()
Packit Service 8ebd8e
        self.p_mock.wait()
Packit Service 8ebd8e
        super().tearDown()
Packit Service 8ebd8e
Packit Service 8ebd8e
    def setup_device(self):
Packit Service 8ebd8e
        self.device_path = self.obj_fprintd_mock.AddDevice(
Packit Service 8ebd8e
            'FDO Trigger Finger Laser Reader', 3, 'swipe')
Packit Service 8ebd8e
        self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint',
Packit Service 8ebd8e
            self.device_path)
Packit Service 8ebd8e
        self.set_enrolled_fingers(['left-little-finger', 'right-little-finger'])
Packit Service 8ebd8e
Packit Service 8ebd8e
    def set_enrolled_fingers(self, fingers, user='toto'):
Packit Service 8ebd8e
        self.enrolled_fingers = fingers
Packit Service 8ebd8e
        self.device_mock.SetEnrolledFingers('toto', self.enrolled_fingers,
Packit Service 8ebd8e
            signature='sas')
Packit Service 8ebd8e
Packit Service 8ebd8e
    def start_utility_process(self, utility_name, args=[], sleep=True):
Packit Service 8ebd8e
        utility = [ os.path.join(self.tools_prefix, 'fprintd-{}'.format(utility_name)) ]
Packit Service 8ebd8e
        output = OutputChecker()
Packit Service 8ebd8e
        process = subprocess.Popen(self.wrapper_args + utility + args,
Packit Service 8ebd8e
                                   stdout=output.fd,
Packit Service 8ebd8e
                                   stderr=subprocess.STDOUT)
Packit Service 8ebd8e
        output.writer_attached()
Packit Service 8ebd8e
Packit Service 8ebd8e
        self.addCleanup(output.assert_closed)
Packit Service 8ebd8e
        self.addCleanup(self.try_stop_utility_process, process)
Packit Service 8ebd8e
Packit Service 8ebd8e
        if sleep:
Packit Service 8ebd8e
            time.sleep(self.sleep_time)
Packit Service 8ebd8e
Packit Service 8ebd8e
        return process, output
Packit Service 8ebd8e
Packit Service 8ebd8e
    def stop_utility_process(self, process):
Packit Service 8ebd8e
        process.terminate()
Packit Service 8ebd8e
        process.wait()
Packit Service 8ebd8e
Packit Service 8ebd8e
    def try_stop_utility_process(self, process):
Packit Service 8ebd8e
        try:
Packit Service 8ebd8e
            self.stop_utility_process(process)
Packit Service 8ebd8e
        except:
Packit Service 8ebd8e
            pass
Packit Service 8ebd8e
Packit Service 8ebd8e
    def run_utility_process(self, utility_name, args=[], sleep=True, timeout=None):
Packit Service 8ebd8e
        proc, output = self.start_utility_process(utility_name, args=args, sleep=sleep)
Packit Service 8ebd8e
        ret = proc.wait(timeout=timeout if timeout is not None else self.sleep_time * 4)
Packit Service 8ebd8e
        self.assertLessEqual(ret, 128)
Packit Service 8ebd8e
Packit Service 8ebd8e
        return b''.join(output.clear()), ret
Packit Service 8ebd8e
Packit Service 8ebd8e
Packit Service 8ebd8e
class TestFprintdUtils(TestFprintdUtilsBase):
Packit Service 8ebd8e
    def setUp(self):
Packit Service 8ebd8e
        super().setUp()
Packit Service 8ebd8e
        self.setup_device()
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_enroll(self):
Packit Service 8ebd8e
        process, out = self.start_utility_process('enroll', ['-f', 'right-index-finger', 'toto'])
Packit Service 8ebd8e
Packit Service 8ebd8e
        out.check_line(rb'right-index-finger', 0)
Packit Service 8ebd8e
Packit Service 8ebd8e
        self.device_mock.EmitEnrollStatus('enroll-completed', True)
Packit Service 8ebd8e
Packit Service 8ebd8e
        out.check_line(rb'Enroll result: enroll-completed', self.sleep_time)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_list(self):
Packit Service 8ebd8e
        # Rick has no fingerprints enrolled
Packit Service 8ebd8e
        out, ret = self.run_utility_process('list', ['rick'])
Packit Service 8ebd8e
        self.assertRegex(out, rb'has no fingers enrolled for')
Packit Service 8ebd8e
        self.assertEqual(ret, 0)
Packit Service 8ebd8e
Packit Service 8ebd8e
        # Toto does
Packit Service 8ebd8e
        out, ret = self.run_utility_process('list', ['toto'])
Packit Service 8ebd8e
        self.assertRegex(out, rb'right-little-finger')
Packit Service 8ebd8e
        self.assertEqual(ret, 0)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_delete(self):
Packit Service 8ebd8e
        # Has fingerprints enrolled
Packit Service 8ebd8e
        out, ret = self.run_utility_process('list', ['toto'])
Packit Service 8ebd8e
        self.assertRegex(out, rb'left-little-finger')
Packit Service 8ebd8e
        self.assertEqual(ret, 0)
Packit Service 8ebd8e
        self.assertRegex(out, rb'right-little-finger')
Packit Service 8ebd8e
Packit Service 8ebd8e
        # Delete fingerprints
Packit Service 8ebd8e
        out, ret = self.run_utility_process('delete', ['toto'])
Packit Service 8ebd8e
        self.assertRegex(out, rb'Fingerprints deleted')
Packit Service 8ebd8e
        self.assertEqual(ret, 0)
Packit Service 8ebd8e
Packit Service 8ebd8e
        # Doesn't have fingerprints
Packit Service 8ebd8e
        out, ret = self.run_utility_process('list', ['toto'])
Packit Service 8ebd8e
        self.assertRegex(out, rb'has no fingers enrolled for')
Packit Service 8ebd8e
        self.assertEqual(ret, 0)
Packit Service 8ebd8e
Packit Service 8ebd8e
Packit Service 8ebd8e
class TestFprintdUtilsNoDeviceTests(TestFprintdUtilsBase):
Packit Service 8ebd8e
    def test_fprintd_enroll(self):
Packit Service 8ebd8e
        out, ret = self.run_utility_process('enroll', ['toto'])
Packit Service 8ebd8e
        self.assertIn(b'No devices available', out)
Packit Service 8ebd8e
        self.assertEqual(ret, 1)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_list(self):
Packit Service 8ebd8e
        out, ret = self.run_utility_process('list', ['toto'])
Packit Service 8ebd8e
        self.assertIn(b'No devices available', out)
Packit Service 8ebd8e
        self.assertEqual(ret, 1)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_delete(self):
Packit Service 8ebd8e
        out, ret = self.run_utility_process('delete', ['toto'])
Packit Service 8ebd8e
        self.assertIn(b'No devices available', out)
Packit Service 8ebd8e
        self.assertEqual(ret, 1)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_verify(self):
Packit Service 8ebd8e
        out, ret = self.run_utility_process('verify', ['toto'])
Packit Service 8ebd8e
        self.assertIn(b'No devices available', out)
Packit Service 8ebd8e
        self.assertEqual(ret, 1)
Packit Service 8ebd8e
Packit Service 8ebd8e
Packit Service 8ebd8e
class TestFprintdUtilsVerify(TestFprintdUtilsBase):
Packit Service 8ebd8e
    def setUp(self):
Packit Service 8ebd8e
        super().setUp()
Packit Service 8ebd8e
        self.setup_device()
Packit Service 8ebd8e
Packit Service 8ebd8e
    def start_verify_process(self, user='toto', finger=None, nowait=False):
Packit Service 8ebd8e
        args = [user]
Packit Service 8ebd8e
        if finger:
Packit Service 8ebd8e
            args += ['-f', finger]
Packit Service 8ebd8e
Packit Service 8ebd8e
        self.process, self.output = self.start_utility_process('verify', args)
Packit Service 8ebd8e
        if nowait:
Packit Service 8ebd8e
            return
Packit Service 8ebd8e
Packit Service 8ebd8e
        preamble = self.output.check_line(b'Verify started!')
Packit Service 8ebd8e
Packit Service 8ebd8e
        out = b''.join(preamble)
Packit Service 8ebd8e
Packit Service 8ebd8e
        self.assertNotIn(b'Verify result:', out)
Packit Service 8ebd8e
Packit Service 8ebd8e
        if finger:
Packit Service 8ebd8e
            expected_finger = finger
Packit Service 8ebd8e
            if finger == 'any' and not self.device_mock.HasIdentification():
Packit Service 8ebd8e
                expected_finger = self.enrolled_fingers[0]
Packit Service 8ebd8e
            self.assertEqual(self.device_mock.GetSelectedFinger(), expected_finger)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def assertVerifyMatch(self, match):
Packit Service 8ebd8e
        self.output.check_line(r'Verify result: {} (done)'.format(
Packit Service 8ebd8e
            'verify-match' if match else 'verify-no-match'))
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_verify(self):
Packit Service 8ebd8e
        self.start_verify_process()
Packit Service 8ebd8e
Packit Service 8ebd8e
        self.device_mock.EmitVerifyStatus('verify-match', True)
Packit Service 8ebd8e
        time.sleep(self.sleep_time)
Packit Service 8ebd8e
        self.assertVerifyMatch(True)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_verify_enrolled_fingers(self):
Packit Service 8ebd8e
        for finger in self.enrolled_fingers:
Packit Service 8ebd8e
            self.start_verify_process(finger=finger)
Packit Service 8ebd8e
Packit Service 8ebd8e
            self.device_mock.EmitVerifyStatus('verify-match', True)
Packit Service 8ebd8e
            time.sleep(self.sleep_time)
Packit Service 8ebd8e
            self.assertVerifyMatch(True)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_verify_any_finger_no_identification(self):
Packit Service 8ebd8e
        self.start_verify_process(finger='any')
Packit Service 8ebd8e
Packit Service 8ebd8e
        self.device_mock.EmitVerifyStatus('verify-match', True)
Packit Service 8ebd8e
        time.sleep(self.sleep_time)
Packit Service 8ebd8e
        self.assertVerifyMatch(True)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_verify_any_finger_identification(self):
Packit Service 8ebd8e
        self.obj_fprintd_mock.RemoveDevice(self.device_path)
Packit Service 8ebd8e
        self.device_path = self.obj_fprintd_mock.AddDevice('Full powered device',
Packit Service 8ebd8e
            3, 'press', True)
Packit Service 8ebd8e
        self.device_mock = self.dbus_con.get_object('net.reactivated.Fprint',
Packit Service 8ebd8e
            self.device_path)
Packit Service 8ebd8e
        self.set_enrolled_fingers(VALID_FINGER_NAMES)
Packit Service 8ebd8e
        self.start_verify_process(finger='any')
Packit Service 8ebd8e
Packit Service 8ebd8e
        self.device_mock.EmitVerifyStatus('verify-match', True)
Packit Service 8ebd8e
        time.sleep(self.sleep_time)
Packit Service 8ebd8e
        self.assertVerifyMatch(True)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_verify_not_enrolled_fingers(self):
Packit Service 8ebd8e
        for finger in [f for f in VALID_FINGER_NAMES if f not in self.enrolled_fingers]:
Packit Service 8ebd8e
            self.start_verify_process(finger=finger, nowait=True)
Packit Service 8ebd8e
            regex = r'Finger \'{}\' not enrolled'.format(finger)
Packit Service 8ebd8e
            self.output.check_line_re(regex, timeout=self.sleep_time)
Packit Service 8ebd8e
Packit Service 8ebd8e
            self.device_mock.Release()
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_verify_no_enrolled_fingers(self):
Packit Service 8ebd8e
        self.set_enrolled_fingers([])
Packit Service 8ebd8e
        self.start_verify_process(nowait=True)
Packit Service 8ebd8e
        self.output.check_line(b'No fingers enrolled for this device.', timeout=self.sleep_time)
Packit Service 8ebd8e
        self.assertEqual(self.process.poll(), 1)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_list_all_fingers(self):
Packit Service 8ebd8e
        self.set_enrolled_fingers(VALID_FINGER_NAMES)
Packit Service 8ebd8e
        self.start_verify_process()
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_verify_script(self):
Packit Service 8ebd8e
        script = [
Packit Service 8ebd8e
            ( 'verify-match', True, 2 )
Packit Service 8ebd8e
        ]
Packit Service 8ebd8e
        self.device_mock.SetVerifyScript(script)
Packit Service 8ebd8e
        time.sleep(2)
Packit Service 8ebd8e
Packit Service 8ebd8e
        self.start_verify_process()
Packit Service 8ebd8e
        time.sleep(2 + self.sleep_time)
Packit Service 8ebd8e
        self.assertVerifyMatch(True)
Packit Service 8ebd8e
Packit Service 8ebd8e
    def test_fprintd_multiple_verify_fails(self):
Packit Service 8ebd8e
        self.start_verify_process()
Packit Service 8ebd8e
Packit Service 8ebd8e
        self.start_verify_process(nowait=True)
Packit Service 8ebd8e
        self.output.check_line_re(rb'Device already in use by [A-z]+', timeout=self.sleep_time)
Packit Service 8ebd8e
Packit Service 8ebd8e
if __name__ == '__main__':
Packit Service 8ebd8e
    # avoid writing to stderr
Packit Service 8ebd8e
    unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2))