2019-08-12 12:34:37 +00:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import os.path
|
2021-06-21 19:26:59 +00:00
|
|
|
import glob
|
2019-08-12 12:34:37 +00:00
|
|
|
import shutil
|
|
|
|
import tempfile
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
if len(sys.argv) != 2:
|
|
|
|
print("You need to specify exactly one argument, the directory with test data")
|
|
|
|
|
2019-11-18 20:09:50 +00:00
|
|
|
# Check that umockdev is available
|
|
|
|
try:
|
|
|
|
umockdev_version = subprocess.check_output(['umockdev-run', '--version'])
|
|
|
|
version = tuple(int(_) for _ in umockdev_version.split(b'.'))
|
|
|
|
if version < (0, 13, 2):
|
|
|
|
print('umockdev is too old for test to be reliable, expect random failures!')
|
|
|
|
print('Please update umockdev to at least 0.13.2.')
|
2021-06-25 08:02:09 +00:00
|
|
|
pcap_supported = version >= (0, 16) or os.getenv('CI_PROJECT_NAME') == "libfprint"
|
|
|
|
spi_supported = version >= (0, 16) or os.getenv('CI_PROJECT_NAME') == "libfprint"
|
2021-06-16 08:53:34 +00:00
|
|
|
|
2019-11-18 20:09:50 +00:00
|
|
|
except FileNotFoundError:
|
|
|
|
print('umockdev-run not found, skipping test!')
|
|
|
|
print('Please install umockdev.')
|
|
|
|
sys.exit(77)
|
|
|
|
|
2019-08-12 12:34:37 +00:00
|
|
|
edir = os.path.dirname(sys.argv[0])
|
|
|
|
ddir = sys.argv[1]
|
|
|
|
|
|
|
|
tmpdir = tempfile.mkdtemp(prefix='libfprint-umockdev-test-')
|
|
|
|
|
|
|
|
assert os.path.isdir(ddir)
|
|
|
|
|
|
|
|
def cmp_pngs(png_a, png_b):
|
|
|
|
print("Comparing PNGs %s and %s" % (png_a, png_b))
|
|
|
|
import cairo
|
|
|
|
img_a = cairo.ImageSurface.create_from_png(png_a)
|
|
|
|
img_b = cairo.ImageSurface.create_from_png(png_b)
|
|
|
|
|
|
|
|
assert img_a.get_format() == cairo.FORMAT_RGB24
|
|
|
|
assert img_b.get_format() == cairo.FORMAT_RGB24
|
|
|
|
assert img_a.get_width() == img_b.get_width()
|
|
|
|
assert img_a.get_height() == img_b.get_height()
|
|
|
|
assert img_a.get_stride () == img_b.get_stride()
|
|
|
|
|
|
|
|
data_a = img_a.get_data()
|
|
|
|
data_b = img_b.get_data()
|
|
|
|
stride = img_a.get_stride()
|
|
|
|
|
|
|
|
for x in range(img_a.get_width()):
|
|
|
|
for y in range(img_a.get_height()):
|
2019-11-28 10:37:33 +00:00
|
|
|
# RGB24 format is endian dependent, using +1 means we test either
|
|
|
|
# the G or B component, which works on any endian for the greyscale
|
|
|
|
# test.
|
|
|
|
assert(data_a[y * stride + x * 4 + 1] == data_b[y * stride + x * 4 + 1])
|
2019-08-12 12:34:37 +00:00
|
|
|
|
2019-11-26 17:39:09 +00:00
|
|
|
def get_umockdev_runner(ioctl_basename):
|
|
|
|
ioctl = os.path.join(ddir, "{}.ioctl".format(ioctl_basename))
|
2021-06-16 08:53:34 +00:00
|
|
|
pcap = os.path.join(ddir, "{}.pcapng".format(ioctl_basename))
|
|
|
|
|
2021-06-21 19:26:59 +00:00
|
|
|
devices = glob.glob(os.path.join(ddir, "device")) + glob.glob(os.path.join(ddir, "device-*[!~]"))
|
|
|
|
device_args = []
|
|
|
|
for device in devices:
|
2021-06-16 08:53:34 +00:00
|
|
|
p = open(device).readline().strip()
|
|
|
|
assert p.startswith('P: ')
|
2021-06-21 19:26:59 +00:00
|
|
|
device_args.extend(("-d", device))
|
|
|
|
|
|
|
|
if os.path.exists(pcap):
|
2021-06-16 08:53:34 +00:00
|
|
|
syspath = '/sys' + p[3:]
|
|
|
|
|
2021-06-21 19:26:59 +00:00
|
|
|
umockdev = ['umockdev-run', *device_args,
|
2021-06-16 08:53:34 +00:00
|
|
|
'-p', "%s=%s" % (syspath, pcap),
|
|
|
|
'--']
|
|
|
|
|
|
|
|
# Skip test if we detect too old umockdev for pcap replay
|
|
|
|
if not pcap_supported:
|
|
|
|
sys.exit(77)
|
|
|
|
|
|
|
|
else:
|
|
|
|
dev = open(ioctl).readline().strip()
|
|
|
|
assert dev.startswith('@DEV ')
|
|
|
|
dev = dev[5:]
|
2021-06-22 15:24:10 +00:00
|
|
|
if dev.endswith(" (SPI)"):
|
|
|
|
dev = dev[:dev.rindex(" ")]
|
|
|
|
|
|
|
|
# Skip test if we detect too old umockdev for spi replay
|
|
|
|
if not spi_supported:
|
|
|
|
sys.exit(77)
|
2021-06-16 08:53:34 +00:00
|
|
|
|
2021-06-21 19:26:59 +00:00
|
|
|
umockdev = ['umockdev-run', *device_args,
|
2021-06-16 08:53:34 +00:00
|
|
|
'-i', "%s=%s" % (dev, ioctl),
|
|
|
|
'--']
|
2021-06-22 15:24:10 +00:00
|
|
|
|
2019-11-26 17:39:09 +00:00
|
|
|
wrapper = os.getenv('LIBFPRINT_TEST_WRAPPER')
|
|
|
|
return umockdev + (wrapper.split(' ') if wrapper else []) + [sys.executable]
|
|
|
|
|
|
|
|
def capture():
|
|
|
|
subprocess.check_call(get_umockdev_runner("capture") +
|
|
|
|
['%s' % os.path.join(edir, "capture.py"),
|
|
|
|
'%s' % os.path.join(tmpdir, "capture.png")])
|
2019-08-12 12:34:37 +00:00
|
|
|
|
|
|
|
assert os.path.isfile(os.path.join(tmpdir, "capture.png"))
|
|
|
|
if os.path.isfile(os.path.join(ddir, "capture.png")):
|
|
|
|
# Compare the images, they need to be identical
|
|
|
|
cmp_pngs(os.path.join(tmpdir, "capture.png"), os.path.join(ddir, "capture.png"))
|
|
|
|
|
2019-08-12 14:30:40 +00:00
|
|
|
def custom():
|
2019-11-26 17:39:09 +00:00
|
|
|
subprocess.check_call(get_umockdev_runner("custom") +
|
|
|
|
['%s' % os.path.join(ddir, "custom.py")])
|
2019-08-12 14:30:40 +00:00
|
|
|
|
2019-08-12 12:34:37 +00:00
|
|
|
try:
|
|
|
|
if os.path.exists(os.path.join(ddir, "capture.ioctl")):
|
|
|
|
capture()
|
|
|
|
|
2019-08-12 14:30:40 +00:00
|
|
|
if os.path.exists(os.path.join(ddir, "custom.ioctl")):
|
|
|
|
custom()
|
|
|
|
|
2020-12-09 00:20:10 +00:00
|
|
|
except Exception as e:
|
2020-11-05 14:52:54 +00:00
|
|
|
# Store created output files for inspection (in the build directory)
|
|
|
|
outdir = os.path.join('errors', os.path.basename(ddir))
|
2020-12-09 00:21:49 +00:00
|
|
|
shutil.copytree(tmpdir, outdir, dirs_exist_ok=True)
|
2020-12-09 00:20:10 +00:00
|
|
|
raise e
|
2020-11-05 14:52:54 +00:00
|
|
|
|
2019-08-12 12:34:37 +00:00
|
|
|
finally:
|
|
|
|
shutil.rmtree(tmpdir)
|
|
|
|
|