tests: Add umockdev based testing
Initially only the vfs5011 driver is tested. Please note that these tests will be unreliable before umockdev 0.13.2. See also https://github.com/martinpitt/umockdev/pull/92
This commit is contained in:
parent
e372311afe
commit
538038867b
8 changed files with 329 additions and 2 deletions
|
@ -7,7 +7,7 @@ stages:
|
||||||
variables:
|
variables:
|
||||||
DEPENDENCIES: libgusb-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
|
DEPENDENCIES: libgusb-devel glib2-devel nss-devel pixman-devel systemd meson gtk-doc
|
||||||
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
|
gcc gcc-c++ glibc-devel libX11-devel libXv-devel gtk3-devel flatpak-builder
|
||||||
gobject-introspection-devel python3-cairo python3-gobject
|
gobject-introspection-devel python3-cairo python3-gobject umockdev
|
||||||
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
BUNDLE: "org.freedesktop.libfprint.Demo.flatpak"
|
||||||
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
LAST_ABI_BREAK: "056ea541ddc97f5806cffbd99a12dc87e4da3546"
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ test:
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
- dnf update -y --nogpgcheck && dnf install -y --nogpgcheck $DEPENDENCIES
|
||||||
- meson -Ddrivers=virtual_image . _build
|
- meson -Ddrivers=all . _build
|
||||||
- ninja -C _build
|
- ninja -C _build
|
||||||
- meson test -C _build --verbose --no-stdsplit
|
- meson test -C _build --verbose --no-stdsplit
|
||||||
|
|
||||||
|
|
21
tests/README-umockdev
Normal file
21
tests/README-umockdev
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
To create a new umockdev test, you should:
|
||||||
|
|
||||||
|
1. Decide on what to test, the easiest case is just using the existing
|
||||||
|
capture test case.
|
||||||
|
2. Find the USB device you are testing with lsusb, e.g.:
|
||||||
|
Bus 001 Device 005: ID 138a:0090 Validity Sensors, Inc. VFS7500 Touch Fingerprint Sensor
|
||||||
|
This means we need to record USB device /dev/bus/usb/001/005
|
||||||
|
3. Run "umockdev-record /dev/bus/usb/001/005 >device"
|
||||||
|
This records the information about device, it should be placed into test/DRIVER/device
|
||||||
|
4. Run the test, for a capture test this would be:
|
||||||
|
umockdev-record -i /dev/bus/usb/001/005=capture.ioctl -- ./capture.py capture.png
|
||||||
|
This will create a capture.ioctl and capture.png file.
|
||||||
|
5. Place all files into the driver subdirectory test/DRIVER,
|
||||||
|
i.e. device, capture.ioctl, capture.png
|
||||||
|
6. Add glue to meson.build
|
||||||
|
7. Test whether everything works as expected
|
||||||
|
|
||||||
|
Please note, there is no need to use a real finger print in this case. If
|
||||||
|
you would like to avoid submitting your own fingerprint then please just
|
||||||
|
use e.g. the side of your finger, arm, or anything else that will produce
|
||||||
|
an image with the device.
|
46
tests/capture.py
Executable file
46
tests/capture.py
Executable file
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import gi
|
||||||
|
gi.require_version('FPrint', '2.0')
|
||||||
|
from gi.repository import FPrint, GLib
|
||||||
|
import cairo
|
||||||
|
import sys
|
||||||
|
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("Please specify exactly one argument, the output location for the capture image")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
ctx = GLib.main_context_default()
|
||||||
|
|
||||||
|
c = FPrint.Context()
|
||||||
|
c.enumerate()
|
||||||
|
devices = c.get_devices()
|
||||||
|
|
||||||
|
d = devices[0]
|
||||||
|
|
||||||
|
d.open_sync()
|
||||||
|
|
||||||
|
img = d.capture_sync(True)
|
||||||
|
|
||||||
|
d.close_sync()
|
||||||
|
|
||||||
|
width = img.get_width()
|
||||||
|
height = img.get_height()
|
||||||
|
|
||||||
|
c_img = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height)
|
||||||
|
|
||||||
|
c_rowstride = c_img.get_stride()
|
||||||
|
|
||||||
|
buf = img.get_data()
|
||||||
|
c_buf = c_img.get_data()
|
||||||
|
|
||||||
|
for x in range(width):
|
||||||
|
for y in range(height):
|
||||||
|
c_buf[y * c_rowstride + x * 4 + 0] = buf[y * width + x]
|
||||||
|
c_buf[y * c_rowstride + x * 4 + 1] = buf[y * width + x]
|
||||||
|
c_buf[y * c_rowstride + x * 4 + 2] = buf[y * width + x]
|
||||||
|
# Byte 4 is don't care
|
||||||
|
|
||||||
|
c_img.mark_dirty()
|
||||||
|
c_img.write_to_png(sys.argv[1])
|
||||||
|
|
|
@ -15,3 +15,11 @@ if 'virtual_image' in drivers
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if 'vfs5011' in drivers
|
||||||
|
test(
|
||||||
|
'vfs5011',
|
||||||
|
find_program('umockdev-test.py'),
|
||||||
|
args: join_paths(meson.current_source_dir(), 'vfs5011'),
|
||||||
|
env: envs,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
65
tests/umockdev-test.py
Executable file
65
tests/umockdev-test.py
Executable file
|
@ -0,0 +1,65 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("You need to specify exactly one argument, the directory with test data")
|
||||||
|
|
||||||
|
edir = os.path.dirname(sys.argv[0])
|
||||||
|
ddir = sys.argv[1]
|
||||||
|
|
||||||
|
tmpdir = tempfile.mkdtemp(prefix='libfprint-umockdev-test-')
|
||||||
|
|
||||||
|
assert os.path.isdir(ddir)
|
||||||
|
assert os.path.isfile(os.path.join(ddir, "device"))
|
||||||
|
|
||||||
|
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()):
|
||||||
|
assert(data_a[y * stride + x * 4] == data_b[y * stride + x * 4])
|
||||||
|
|
||||||
|
def capture():
|
||||||
|
ioctl = os.path.join(ddir, "capture.ioctl")
|
||||||
|
device = os.path.join(ddir, "device")
|
||||||
|
dev = open(ioctl).readline().strip()
|
||||||
|
assert dev.startswith('@DEV ')
|
||||||
|
dev = dev[5:]
|
||||||
|
|
||||||
|
subprocess.check_call(['umockdev-run', '-d', device,
|
||||||
|
'-i', "%s=%s" % (dev, ioctl),
|
||||||
|
'--',
|
||||||
|
'%s' % os.path.join(edir, "capture.py"),
|
||||||
|
'%s' % os.path.join(tmpdir, "capture.png")])
|
||||||
|
|
||||||
|
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"))
|
||||||
|
|
||||||
|
try:
|
||||||
|
if os.path.exists(os.path.join(ddir, "capture.ioctl")):
|
||||||
|
capture()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmpdir)
|
||||||
|
|
107
tests/vfs5011/capture.ioctl
Normal file
107
tests/vfs5011/capture.ioctl
Normal file
File diff suppressed because one or more lines are too long
BIN
tests/vfs5011/capture.png
Normal file
BIN
tests/vfs5011/capture.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
80
tests/vfs5011/device
Normal file
80
tests/vfs5011/device
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
P: /devices/pci0000:00/0000:00:14.0/usb2/2-6
|
||||||
|
N: bus/usb/002/017=12011001FF11FF088A13170078000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004
|
||||||
|
E: DEVNAME=/dev/bus/usb/002/017
|
||||||
|
E: DEVTYPE=usb_device
|
||||||
|
E: DRIVER=usb
|
||||||
|
E: PRODUCT=138a/17/78
|
||||||
|
E: TYPE=255/17/255
|
||||||
|
E: BUSNUM=002
|
||||||
|
E: DEVNUM=017
|
||||||
|
E: MAJOR=189
|
||||||
|
E: MINOR=144
|
||||||
|
E: SUBSYSTEM=usb
|
||||||
|
E: ID_VENDOR=138a
|
||||||
|
E: ID_VENDOR_ENC=138a
|
||||||
|
E: ID_VENDOR_ID=138a
|
||||||
|
E: ID_MODEL=0017
|
||||||
|
E: ID_MODEL_ENC=0017
|
||||||
|
E: ID_MODEL_ID=0017
|
||||||
|
E: ID_REVISION=0078
|
||||||
|
E: ID_SERIAL=138a_0017_6c3b5712a6c0
|
||||||
|
E: ID_SERIAL_SHORT=6c3b5712a6c0
|
||||||
|
E: ID_BUS=usb
|
||||||
|
E: ID_USB_INTERFACES=:ff0000:
|
||||||
|
E: ID_VENDOR_FROM_DATABASE=Validity Sensors, Inc.
|
||||||
|
E: ID_MODEL_FROM_DATABASE=VFS 5011 fingerprint sensor
|
||||||
|
A: authorized=1
|
||||||
|
A: avoid_reset_quirk=0
|
||||||
|
A: bConfigurationValue=1
|
||||||
|
A: bDeviceClass=ff
|
||||||
|
A: bDeviceProtocol=ff
|
||||||
|
A: bDeviceSubClass=11
|
||||||
|
A: bMaxPacketSize0=8
|
||||||
|
A: bMaxPower=100mA
|
||||||
|
A: bNumConfigurations=1
|
||||||
|
A: bNumInterfaces= 1
|
||||||
|
A: bcdDevice=0078
|
||||||
|
A: bmAttributes=a0
|
||||||
|
A: busnum=2
|
||||||
|
A: configuration=
|
||||||
|
H: descriptors=12011001FF11FF088A13170078000000010109022E00010100A0320904000004FF00000007050102400000070581024000000705820240000007058303080004
|
||||||
|
A: dev=189:144
|
||||||
|
A: devnum=17
|
||||||
|
A: devpath=6
|
||||||
|
L: driver=../../../../../bus/usb/drivers/usb
|
||||||
|
A: idProduct=0017
|
||||||
|
A: idVendor=138a
|
||||||
|
A: ltm_capable=no
|
||||||
|
A: maxchild=0
|
||||||
|
L: port=../2-0:1.0/usb2-port6
|
||||||
|
A: power/active_duration=624952
|
||||||
|
A: power/async=enabled
|
||||||
|
A: power/autosuspend=2
|
||||||
|
A: power/autosuspend_delay_ms=2000
|
||||||
|
A: power/connected_duration=624952
|
||||||
|
A: power/control=on
|
||||||
|
A: power/level=on
|
||||||
|
A: power/persist=1
|
||||||
|
A: power/runtime_active_kids=0
|
||||||
|
A: power/runtime_active_time=624676
|
||||||
|
A: power/runtime_enabled=forbidden
|
||||||
|
A: power/runtime_status=active
|
||||||
|
A: power/runtime_suspended_time=0
|
||||||
|
A: power/runtime_usage=1
|
||||||
|
A: power/wakeup=disabled
|
||||||
|
A: power/wakeup_abort_count=
|
||||||
|
A: power/wakeup_active=
|
||||||
|
A: power/wakeup_active_count=
|
||||||
|
A: power/wakeup_count=
|
||||||
|
A: power/wakeup_expire_count=
|
||||||
|
A: power/wakeup_last_time_ms=
|
||||||
|
A: power/wakeup_max_time_ms=
|
||||||
|
A: power/wakeup_total_time_ms=
|
||||||
|
A: quirks=0x0
|
||||||
|
A: removable=fixed
|
||||||
|
A: rx_lanes=1
|
||||||
|
A: serial=6c3b5712a6c0
|
||||||
|
A: speed=12
|
||||||
|
A: tx_lanes=1
|
||||||
|
A: urbnum=7
|
||||||
|
A: version= 1.10
|
Loading…
Reference in a new issue