1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-28 11:55:44 +03:00

test: add tests for destroy callback of asynchronous netlink call

This commit is contained in:
Yu Watanabe 2018-10-04 03:42:29 +09:00
parent 545bab1f0a
commit 0d0f02cd15

View File

@ -5,6 +5,7 @@
#include "sd-netlink.h"
#include "alloc-util.h"
#include "ether-addr-util.h"
#include "macro.h"
#include "missing.h"
@ -177,8 +178,9 @@ static int link_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata)
assert_se(rtnl);
assert_se(m);
assert_se(userdata);
log_info("got link info about %s", ifname);
log_info("%s: got link info about %s", __func__, ifname);
free(ifname);
assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
@ -212,21 +214,6 @@ static void test_event_loop(int ifindex) {
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
}
static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
int *counter = userdata;
int r;
(*counter)--;
r = sd_netlink_message_get_errno(m);
log_info_errno(r, "%d left in pipe. got reply: %m", *counter);
assert_se(r >= 0);
return 1;
}
static void test_async(int ifindex) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
@ -248,6 +235,116 @@ static void test_async(int ifindex) {
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
}
struct test_async_object {
unsigned n_ref;
char *ifname;
};
static struct test_async_object *test_async_object_free(struct test_async_object *t) {
assert(t);
free(t->ifname);
return mfree(t);
}
DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(struct test_async_object, test_async_object, test_async_object_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct test_async_object *, test_async_object_unref);
static int link_handler2(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
struct test_async_object *t = userdata;
const char *data;
assert_se(rtnl);
assert_se(m);
assert_se(userdata);
log_info("%s: got link info about %s", __func__, t->ifname);
assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &data) >= 0);
assert_se(streq(data, "lo"));
return 1;
}
static void test_async_object_destroy(void *userdata) {
struct test_async_object *t = userdata;
assert(userdata);
log_info("%s: n_ref=%u", __func__, t->n_ref);
test_async_object_unref(t);
}
static void test_async_destroy_callback(int ifindex) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL;
_cleanup_(test_async_object_unrefp) struct test_async_object *t = NULL;
uint32_t serial;
char *ifname;
assert_se(t = new(struct test_async_object, 1));
assert_se(ifname = strdup("lo"));
*t = (struct test_async_object) {
.n_ref = 1,
.ifname = ifname,
};
assert_se(sd_netlink_open(&rtnl) >= 0);
/* destroy callback is called after processing message */
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_netlink_call_async(rtnl, m, link_handler2, test_async_object_destroy, t, 0, &serial) >= 0);
assert_se(t->n_ref == 1);
assert_se(test_async_object_ref(t));
assert_se(t->n_ref == 2);
assert_se(sd_netlink_wait(rtnl, 0) >= 0);
assert_se(sd_netlink_process(rtnl, &r) == 1);
assert_se(t->n_ref == 1);
assert_se(!sd_netlink_message_unref(m));
/* destroy callback is called when asynchronous call is cancelled */
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_netlink_call_async(rtnl, m, link_handler2, test_async_object_destroy, t, 0, &serial) >= 0);
assert_se(t->n_ref == 1);
assert_se(test_async_object_ref(t));
assert_se(t->n_ref == 2);
assert_se(sd_netlink_call_async_cancel(rtnl, serial) >= 0);
assert_se(t->n_ref == 1);
assert_se(!sd_netlink_message_unref(m));
/* destroy callback is also called by sd_netlink_unref() */
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
assert_se(sd_netlink_call_async(rtnl, m, link_handler2, test_async_object_destroy, t, 0, &serial) >= 0);
assert_se(t->n_ref == 1);
assert_se(test_async_object_ref(t));
assert_se(t->n_ref == 2);
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
assert_se(t->n_ref == 1);
}
static int pipe_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
int *counter = userdata;
int r;
(*counter)--;
r = sd_netlink_message_get_errno(m);
log_info_errno(r, "%d left in pipe. got reply: %m", *counter);
assert_se(r >= 0);
return 1;
}
static void test_pipe(int ifindex) {
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
@ -366,31 +463,25 @@ int main(void) {
uint16_t type;
test_match();
test_multiple();
assert_se(sd_netlink_open(&rtnl) >= 0);
assert_se(rtnl);
test_route(rtnl);
test_message(rtnl);
test_container(rtnl);
if_loopback = (int) if_nametoindex("lo");
assert_se(if_loopback > 0);
test_async(if_loopback);
test_async_destroy_callback(if_loopback);
test_pipe(if_loopback);
test_event_loop(if_loopback);
test_link_configure(rtnl, if_loopback);
test_get_addresses(rtnl);
test_message_link_bridge(rtnl);
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0);