-
Notifications
You must be signed in to change notification settings - Fork 2k
Writing tests for gnrc_netapi modules
gnrc_nettest
provides functionality to test gnrc_netapi
(see netapi) based modules. For every gnrc_netapi
message call there are functions to test this message:
-
GNRC_NETAPI_MSG_TYPE_SND
:-
gnrc_nettest_send()
: to test inner-stack modules (modules that get all their communication partners throughgnrc_netreg
) -
gnrc_nettest_send_iface()
: to test modules communicating with at least onegnrc_netif
interface.
-
-
GNRC_NETAPI_MSG_TYPE_RCV
:gnrc_nettest_receive()
-
GNRC_NETAPI_MSG_TYPE_GET
:gnrc_nettest_get()
-
GNRC_NETAPI_MSG_TYPE_SET
:gnrc_nettest_set()
There are also functions to manipulate the behavior of gnrc_nettest
itself, so that you can set option behavior the module the module you like to test expects from its neighboring modules:
-
gnrc_nettest_register_get()
: set a getter for an option. -
gnrc_nettest_register_set()
: set a setter for an option.
In general the functions are implemented to be used with any unittest framework. For RIOT we use a modified version of embUnit, but it is not restricted to that. Furthermore, gnrc_nettest
requires the main thread to have a packet queue so you have to initialize one. This means that your main.c
has to look at minimum like this:
#include <stdio.h>
#include "net/gnrc/nettest.h"
#include "embUnit.h"
#include "msg.h"
#define MAIN_MSG_QUEUE_SIZE (4) /* As long as this value stays an exponential of 2
* this can be adapted for your tests */
static msg_t msg_queue[MAIN_MSG_QUEUE_SIZE];
int main(void)
{
if (gnrc_nettest_init() < 0) {
puts("Error initializing nettest thread");
return 1;
}
msg_init_queue(msg_queue, MAIN_MSG_QUEUE_SIZE);
TESTS_START();
/* TESTS_RUN(some_test_generator()); */
TESTS_END();
return 0;
}
Note that your tests have to generate some Test *
objects (through some_test_generator()
in this example) to have the tests actually run. Please refer to "Testing RIOT" for details on how to set up unittests.
The tests for GNRC_NETAPI_MSG_TYPE_SND
and GNRC_NETAPI_MSG_TYPE_RCV
are based on the principle that a gnrc_netapi
module gets some kind of input which triggers some kind of output. For gnrc_nettest
both input and output must be handled through gnrc_netapi
, other kinds of output or input (e.g. for interfaces) are out of scope of gnrc_nettest
. Each of the test functions for this modules have four parameters that are relevant for this:
-
gnrc_pktsnip_t *in
: the input that triggers the output -
unsigned int exp_pkts
: the numbers of packets expected in output (may be 0) -
const kernel_pid_t *exp_senders
: the expected senders of the output (may beNULL
ifexp_pkts
is 0) -
const gnrc_pktsnip_t **exp_out
: the expected output packets (may beNULL
ifexp_pkts
is 0)
If the module you test needs to set or get some kind of option from the layer it is supposed to output to (e.g. hardware address from the interface) you can use gnrc_nettest_register_get()
and gnrc_nettest_register_set()
to set getters/setters for these options for the neighboring layers.
If exp_pkts
is 0, the tested module's priority MUST be equal or higher to the testing threads priority to ensure that the in
packets are handled by the tested module.
You can test getting and setting options with gnrc_nettest_get()
and gnrc_nettest_set()
by just using the parameters as documented.
If the module you test needs to set or get some kind of option to set or get its own options you can use gnrc_nettest_register_get()
and gnrc_nettest_register_set()
to set getters/setters for these options for the neighboring layers.
Have look at tests/udp/
(currently PR'd at #3248) for an example.