From: Yu Watanabe Date: Wed, 3 Oct 2018 18:42:29 +0000 (+0900) Subject: test: add tests for destroy callback of asynchronous netlink call X-Git-Tag: v240~571^2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d0f02cd15fcb7fed2d2b1089fe64641f8b71134;p=thirdparty%2Fsystemd.git test: add tests for destroy callback of asynchronous netlink call --- diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c index b0686873c1f..710ed0d089c 100644 --- a/src/libsystemd/sd-netlink/test-netlink.c +++ b/src/libsystemd/sd-netlink/test-netlink.c @@ -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,40 +214,135 @@ 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; +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; + uint32_t serial; + char *ifname; - (*counter)--; + ifname = strdup("lo"); + assert_se(ifname); - r = sd_netlink_message_get_errno(m); + assert_se(sd_netlink_open(&rtnl) >= 0); - log_info_errno(r, "%d left in pipe. got reply: %m", *counter); + assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); - assert_se(r >= 0); + assert_se(sd_netlink_call_async(rtnl, m, link_handler, NULL, ifname, 0, &serial) >= 0); + + assert_se(sd_netlink_wait(rtnl, 0) >= 0); + assert_se(sd_netlink_process(rtnl, &r) >= 0); + + 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(int ifindex) { +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; - ifname = strdup("lo"); - assert_se(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(sd_netlink_call_async(rtnl, m, link_handler, NULL, ifname, 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) >= 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) { @@ -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);