Martin Pitt
2012-07-06 05:01:31 UTC
Hello friends of udev,
I would like to make it vastly easier, and for some aspects possible
at all, to write automatic tests for libudev/gudev client software.
For example, upower's test suite builds a temporary mock sysfs tree:
http://cgit.freedesktop.org/upower/tree/src/linux/integration-test
(line 106 ff.) so that we can test its logic with having various
combinations of empty or full batteries, UPSes, ACs, power supplies
that power the whole platform vs. only particular devices, and so on.
Often developers do not have that hardware, or it's not easy to set up
a situation to reproduce a bug (waiting a couple of hours for your
battery to drain, etc.), so it is much more convenient to reproduce
the sysfs attributes in a small test bed.
Another example is the test suite for Ubuntu's driver package
detection which implements the corresponding PackageKit API; it also
uses a "fake sys" module largely derived from upower's:
https://github.com/tseliot/ubuntu-drivers-common/blob/master/tests/fakesysfs.py
There are several problems with these approaches:
* Copy&paste code is obviously bad. It would be much better if the
convenience API to set up a libudev/gudev test bed would be
provided by libudev/gudev itself. Also, it should be in C and
available through introspection, so that you can use it from a
variety of languages; this means it should be in gudev.
I am currently working on a first patch for this, and will post it
for discussion here when I have something working.
* upower's test suite is not working any more with current
systemd/udev versions because the support for $SYSFS_PATH was
removed.
I have a patch attached to generalize this to use
$UDEV_TEST_PREFIX, replacing the current compile-time TEST_PREFIX
macro. This will also allow us in the future to create mock dev and
run/rules.d files without having to change the environment variable
and temporary directory structure again. Once that (or a variant of
it) is in, I'll adapt upower's test suite to also set
UDEV_TEST_PREFIX so that it works with both old and new libudev
versions.
With that patch you can now e. g. call
UDEV_TEST_PREFIX=test ./udevadm info --export-db
UDEV_TEST_PREFIX=test ./udevadm info --query=all --path=/devices/virtual/block/md0
in the built systemd tree and it will DTRT. I tested with
./test-libudev, which also works fine.
* You can currently only control the coldplug part. That's why
upower's test suite starts the daemon again in each test case. But
you cannot test the dynamic parts with that, such as updating the
properties correctly when changing power sources. What's missing is
to emulate corresponding uevents for the $UDEV_TEST_PREFIX tree.
My initial idea about this was to make udev_monitor_send_device()
public API and relax the uid/pid checks to allow non-root messages
when the corresponding sysfs dir is writable for the calling user
(or something like that). But as non-root users are not allowed to
send NETLINK_KOBJECT_UEVENT messages, this is moot anyway as we do
not want to require root privileges for tests, at least not in all
cases.
So my current idea about this to have gudev read events from a
simple GIO socket in $UDEV_TEST_PREFIX/uevent instead from
libudev_monitor_* if $UDEV_TEST_PREFIX is given, as in that case
the real uevents won't coincide with the sysfs anyway. The "uevent"
signal would then be raised on messages from that socket. Do you
think that's too crazy?
Thanks,
Martin
I would like to make it vastly easier, and for some aspects possible
at all, to write automatic tests for libudev/gudev client software.
For example, upower's test suite builds a temporary mock sysfs tree:
http://cgit.freedesktop.org/upower/tree/src/linux/integration-test
(line 106 ff.) so that we can test its logic with having various
combinations of empty or full batteries, UPSes, ACs, power supplies
that power the whole platform vs. only particular devices, and so on.
Often developers do not have that hardware, or it's not easy to set up
a situation to reproduce a bug (waiting a couple of hours for your
battery to drain, etc.), so it is much more convenient to reproduce
the sysfs attributes in a small test bed.
Another example is the test suite for Ubuntu's driver package
detection which implements the corresponding PackageKit API; it also
uses a "fake sys" module largely derived from upower's:
https://github.com/tseliot/ubuntu-drivers-common/blob/master/tests/fakesysfs.py
There are several problems with these approaches:
* Copy&paste code is obviously bad. It would be much better if the
convenience API to set up a libudev/gudev test bed would be
provided by libudev/gudev itself. Also, it should be in C and
available through introspection, so that you can use it from a
variety of languages; this means it should be in gudev.
I am currently working on a first patch for this, and will post it
for discussion here when I have something working.
* upower's test suite is not working any more with current
systemd/udev versions because the support for $SYSFS_PATH was
removed.
I have a patch attached to generalize this to use
$UDEV_TEST_PREFIX, replacing the current compile-time TEST_PREFIX
macro. This will also allow us in the future to create mock dev and
run/rules.d files without having to change the environment variable
and temporary directory structure again. Once that (or a variant of
it) is in, I'll adapt upower's test suite to also set
UDEV_TEST_PREFIX so that it works with both old and new libudev
versions.
With that patch you can now e. g. call
UDEV_TEST_PREFIX=test ./udevadm info --export-db
UDEV_TEST_PREFIX=test ./udevadm info --query=all --path=/devices/virtual/block/md0
in the built systemd tree and it will DTRT. I tested with
./test-libudev, which also works fine.
* You can currently only control the coldplug part. That's why
upower's test suite starts the daemon again in each test case. But
you cannot test the dynamic parts with that, such as updating the
properties correctly when changing power sources. What's missing is
to emulate corresponding uevents for the $UDEV_TEST_PREFIX tree.
My initial idea about this was to make udev_monitor_send_device()
public API and relax the uid/pid checks to allow non-root messages
when the corresponding sysfs dir is writable for the calling user
(or something like that). But as non-root users are not allowed to
send NETLINK_KOBJECT_UEVENT messages, this is moot anyway as we do
not want to require root privileges for tests, at least not in all
cases.
So my current idea about this to have gudev read events from a
simple GIO socket in $UDEV_TEST_PREFIX/uevent instead from
libudev_monitor_* if $UDEV_TEST_PREFIX is given, as in that case
the real uevents won't coincide with the sysfs anyway. The "uevent"
signal would then be raised on messages from that socket. Do you
think that's too crazy?
Thanks,
Martin
--
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
Martin Pitt | http://www.piware.de
Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)