Simulating modems in unit tests

Aleksander Morgado aleksander at lanedo.com
Mon Nov 25 10:30:29 PST 2013


Hey,

There is a new branch in upstream git:

  aleksander/ports-refactor-and-tests

This branch includes the port refactoring commits I did for the huawei
NDISDUP in /dev/cdc-wdm thing; except for the specific commits enabling
that feature.

In addition to the code refactor commits; I've also added now kind of a
'modem simulator' test setup. A bit more about this...

The new testing setup allows to run an independent ModemManager instance
in its own DBus (session) bus. Several --test options were added to the
ModemManager daemon to allow this testing. The private DBus bus is
obtained with the GTestDBus infrastructure available in GIO 2.34 (which
btw, will need to #ifdef GLIB_CHECK_VERSION; will do that soon).

Anyway, an example test can be seen here:

http://cgit.freedesktop.org/ModemManager/ModemManager/tree/plugins/generic/tests/test-service-generic.c?h=aleksander/ports-refactor-and-tests

Starting the private DBus bus and ModemManager inside it is done in the
test 'fixture' setup. In the same way, stopping ModemManager and
destroying the bus is done in the 'fixture' teardown. See this for more
detailed info:

http://cgit.freedesktop.org/ModemManager/ModemManager/tree/plugins/tests/test-fixture.c?h=aleksander/ports-refactor-and-tests

The first thing done in each test is to create an AT interpreter port (a
TestPortContext). This interpreter starts its own thread and opens a
unix (abstract) port to listen for requests from other processes. See:

http://cgit.freedesktop.org/ModemManager/ModemManager/tree/plugins/tests/test-port-context.c?h=aleksander/ports-refactor-and-tests

The interpreter can load the replies to send back from (one or more)
external files. For now, I just prepared a standard set of responses for
an AT port in a GSM modem:

http://cgit.freedesktop.org/ModemManager/ModemManager/tree/plugins/tests/gsm-port.conf?h=aleksander/ports-refactor-and-tests

Of course, if you want to test another kind of modem, you can load first
this set of generic responses, and afterwards another file with the
modem-specific responses.

Once the interpreter for a port is created, we 'set a test profile' in
ModemManager. We do this running "SetProfile()" in the new "Test"
interface that the ModemManager daemon will export (only if it was
launched with --tests-enable). The purpose of this call is to tell
ModemManager that new ports are available (the one we created) and which
plugin it should use. ModemManager will gather info about these new
ports (as if they were notified by udev) and create a 'virtual'
MMPortSerialAt for a new 'UNIX' subsystem. These ports are to be managed
like standard real serial ports, but they will skip all the unneeded
things (like flashing) and also they will use a GSocket instead of a
GIOChannel internally, so that they can send data to the remote port
(which we were running in another thread in our test app). Note that no
port probing is done; we just assume it's a list of AT ports that we
need to use, and we will use the plugin that we were told to use. This
of course breaks some possible test cases, like e.g. HSO, as in this
case we gather the purpose of each port directly from sysfs, or any
other case where we rely on udev tags.

Once we have set the profile in MM, the example test will wait for the
modem to be exposed by ModemManager, and once it finds it, it will
enable it, and then directly disable it. It's just the first example
test I came up with, I'm sure we can simulate and test lots of other things.


Anyway, I find this quite a pleasant way to quickly test MM behaviour,
and I believe we can setup a great unit test suite from here.


Thoughts?


TL;DR; Grab the "aleksander/ports-refactor-and-tests" branch and run
"make check" or just "./plugins/test-service-generic"

-- 
Aleksander


More information about the ModemManager-devel mailing list