diff options
| author | Michael Biebl <biebl@debian.org> | 2017-11-07 00:14:39 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2017-11-07 00:14:39 +0100 |
| commit | 90e8691111889a7b5f3c812f5a41f15a8a058913 (patch) | |
| tree | f101a879eca27c34a9bfa5f3da52266b22539a36 /src/platform/tests | |
| parent | bdb6eeb0670658255c2a4c3c501c0a27fa8cfe55 (diff) | |
New upstream version 1.9.90 upstream/1.9.90
Diffstat (limited to 'src/platform/tests')
| -rw-r--r-- | src/platform/tests/monitor.c | 2 | ||||
| -rw-r--r-- | src/platform/tests/test-address.c | 87 | ||||
| -rw-r--r-- | src/platform/tests/test-cleanup.c | 32 | ||||
| -rw-r--r-- | src/platform/tests/test-common.c | 445 | ||||
| -rw-r--r-- | src/platform/tests/test-common.h | 174 | ||||
| -rw-r--r-- | src/platform/tests/test-general.c | 2 | ||||
| -rw-r--r-- | src/platform/tests/test-link.c | 31 | ||||
| -rw-r--r-- | src/platform/tests/test-nmp-object.c | 494 | ||||
| -rw-r--r-- | src/platform/tests/test-route.c | 541 |
9 files changed, 1248 insertions, 560 deletions
diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c index d0c58aeb..e1220052 100644 --- a/src/platform/tests/monitor.c +++ b/src/platform/tests/monitor.c @@ -78,6 +78,8 @@ main (int argc, char **argv) nm_linux_platform_setup (); + nm_platform_check_kernel_support (NM_PLATFORM_GET, ~((NMPlatformKernelSupportFlags) 0)); + if (global_opt.persist) g_main_loop_run (loop); diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index 4c139ef0..93851ff7 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -22,7 +22,6 @@ #include "test-common.h" -#define DEVICE_NAME "nm-test-device" #define IP4_ADDRESS "192.0.2.1" #define IP4_ADDRESS_PEER "192.0.2.2" #define IP4_ADDRESS_PEER2 "192.0.3.1" @@ -30,8 +29,8 @@ #define IP6_ADDRESS "2001:db8:a:b:1:2:3:4" #define IP6_PLEN 64 -static int DEVICE_IFINDEX = -1; -static int EX = -1; +#define DEVICE_IFINDEX NMTSTP_ENV1_IFINDEX +#define EX NMTSTP_ENV1_EX /*****************************************************************************/ @@ -103,7 +102,7 @@ test_ip4_address_general (void) accept_signals (address_changed, 0, 1); /* Test address listing */ - addresses = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); + addresses = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); g_assert (addresses); g_assert_cmpint (addresses->len, ==, 1); address = &g_array_index (addresses, NMPlatformIP4Address, 0); @@ -143,9 +142,9 @@ test_ip6_address_general (void) inet_pton (AF_INET6, IP6_ADDRESS, &addr); /* Add address */ - g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags); - g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); accept_signal (address_added); /* Add address again (aka update) */ @@ -153,7 +152,7 @@ test_ip6_address_general (void) accept_signals (address_changed, 0, 1); /* Test address listing */ - addresses = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); + addresses = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); g_assert (addresses); g_assert_cmpint (addresses->len, ==, 1); address = &g_array_index (addresses, NMPlatformIP6Address, 0); @@ -164,7 +163,7 @@ test_ip6_address_general (void) /* Remove address */ nmtstp_ip6_address_del (NULL, EX, ifindex, addr, IP6_PLEN); - g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); accept_signal (address_removed); /* Remove address again */ @@ -229,20 +228,20 @@ test_ip6_address_general_2 (void) /* Add/delete notification */ nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0); accept_signal (address_added); - g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); nmtstp_ip6_address_del (NULL, EX, ifindex, addr, IP6_PLEN); accept_signal (address_removed); - g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (!nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); /* Add/delete conflict */ nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, 0); accept_signal (address_added); - g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); nmtstp_ip6_address_add (NULL, EX, ifindex, addr, IP6_PLEN, in6addr_any, lifetime, preferred, flags); ensure_no_signal (address_added); - g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr, IP6_PLEN)); + g_assert (nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, addr)); free_signal (address_added); free_signal (address_removed); @@ -330,7 +329,7 @@ test_ip4_address_peer_zero (void) nmtstp_ip4_address_add (NULL, EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, 0, label); - addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); + addrs = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); g_assert (addrs); g_assert_cmpint (addrs->len, ==, i + 1); g_array_unref (addrs); @@ -345,7 +344,7 @@ test_ip4_address_peer_zero (void) nmtstp_ip4_address_del (NULL, EX, ifindex, addr, plen, r_peers[i]); - addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); + addrs = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); g_assert (addrs); g_assert_cmpint (addrs->len, ==, G_N_ELEMENTS (peers) - i - 1); g_array_unref (addrs); @@ -366,62 +365,16 @@ _nmtstp_init_tests (int *argc, char ***argv) * SETUP TESTS *****************************************************************************/ -typedef struct { - const char *testpath; - GTestFunc test_func; -} TestSetup; - -static void -_g_test_run (gconstpointer user_data) -{ - const TestSetup *s = user_data; - int ifindex; - - _LOGT ("TEST: start %s", s->testpath); - - nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)); - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME)); - g_assert_cmpint (nm_platform_link_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL), ==, NM_PLATFORM_ERROR_SUCCESS); - - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - g_assert_cmpint (ifindex, >, 0); - g_assert_cmpint (DEVICE_IFINDEX, ==, -1); - - DEVICE_IFINDEX = ifindex; - EX = nmtstp_run_command_check_external_global (); - - s->test_func (); - - g_assert_cmpint (DEVICE_IFINDEX, ==, ifindex); - DEVICE_IFINDEX = -1; - - g_assert_cmpint (ifindex, ==, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)); - g_assert (nm_platform_link_delete (NM_PLATFORM_GET, ifindex)); - _LOGT ("TEST: finished %s", s->testpath); -} - -static void -_g_test_add_func (const char *testpath, - GTestFunc test_func) -{ - TestSetup *s; - - s = g_new0 (TestSetup, 1); - s->testpath = testpath; - s->test_func = test_func; - - g_test_add_data_func_full (testpath, s, _g_test_run, g_free); -} - void _nmtstp_setup_tests (void) { - _g_test_add_func ("/address/ipv4/general", test_ip4_address_general); - _g_test_add_func ("/address/ipv6/general", test_ip6_address_general); +#define add_test_func(testpath, test_func) nmtstp_env1_add_test_func(testpath, test_func, FALSE) + add_test_func ("/address/ipv4/general", test_ip4_address_general); + add_test_func ("/address/ipv6/general", test_ip6_address_general); - _g_test_add_func ("/address/ipv4/general-2", test_ip4_address_general_2); - _g_test_add_func ("/address/ipv6/general-2", test_ip6_address_general_2); + add_test_func ("/address/ipv4/general-2", test_ip4_address_general_2); + add_test_func ("/address/ipv6/general-2", test_ip6_address_general_2); - _g_test_add_func ("/address/ipv4/peer", test_ip4_address_peer); - _g_test_add_func ("/address/ipv4/peer/zero", test_ip4_address_peer_zero); + add_test_func ("/address/ipv4/peer", test_ip4_address_peer); + add_test_func ("/address/ipv4/peer/zero", test_ip4_address_peer_zero); } diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index 71a92cbf..937cd12c 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -22,8 +22,6 @@ #include "test-common.h" -#define DEVICE_NAME "nm-test-device" - static void test_cleanup_internal (void) { @@ -31,8 +29,8 @@ test_cleanup_internal (void) int ifindex; GArray *addresses4; GArray *addresses6; - GArray *routes4; - GArray *routes6; + GPtrArray *routes4; + GPtrArray *routes6; in_addr_t addr4; in_addr_t network4; int plen4 = 24; @@ -72,10 +70,10 @@ test_cleanup_internal (void) nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network6, plen6, gateway6, in6addr_any, metric, mss); nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway6, in6addr_any, metric, mss); - addresses4 = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); - addresses6 = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); - routes4 = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); - routes6 = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); + addresses4 = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); + addresses6 = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); + routes4 = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex); + routes6 = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, ifindex); g_assert_cmpint (addresses4->len, ==, 1); g_assert_cmpint (addresses6->len, ==, 2); /* also has a IPv6 LL address. */ @@ -84,26 +82,24 @@ test_cleanup_internal (void) g_array_unref (addresses4); g_array_unref (addresses6); - g_array_unref (routes4); - g_array_unref (routes6); + g_ptr_array_unref (routes4); + g_ptr_array_unref (routes6); /* Delete interface with all addresses and routes */ g_assert (nm_platform_link_delete (NM_PLATFORM_GET, ifindex)); - addresses4 = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); - addresses6 = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); - routes4 = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); - routes6 = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); + addresses4 = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex); + addresses6 = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex); + routes4 = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex); + routes6 = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, ifindex); g_assert_cmpint (addresses4->len, ==, 0); g_assert_cmpint (addresses6->len, ==, 0); - g_assert_cmpint (routes4->len, ==, 0); - g_assert_cmpint (routes6->len, ==, 0); + g_assert (!routes4); + g_assert (!routes6); g_array_unref (addresses4); g_array_unref (addresses6); - g_array_unref (routes4); - g_array_unref (routes6); } NMTstpSetupFunc const _nmtstp_setup_platform_func = SETUP; diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index a9d0694d..18076712 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -30,6 +30,9 @@ #define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)" #define SIGNAL_DATA_ARG(data) (data)->name, nm_platform_signal_change_type_to_string ((data)->change_type), (data)->ifindex, (data)->ifname ? " ifname '" : "", (data)->ifname ? (data)->ifname : "", (data)->ifname ? "'" : "", (data)->received_count +int NMTSTP_ENV1_IFINDEX = -1; +int NMTSTP_ENV1_EX = -1; + /*****************************************************************************/ void @@ -67,6 +70,90 @@ _init_platform (NMPlatform **platform, gboolean external_command) /*****************************************************************************/ +static GArray * +_ipx_address_get_all (NMPlatform *self, int ifindex, NMPObjectType obj_type) +{ + NMPLookup lookup; + + g_assert (NM_IS_PLATFORM (self)); + g_assert (ifindex > 0); + g_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)); + nmp_lookup_init_addrroute (&lookup, + obj_type, + ifindex); + return nmp_cache_lookup_to_array (nm_platform_lookup (self, &lookup), + obj_type, + FALSE /*addresses are always visible. */); +} + +GArray * +nmtstp_platform_ip4_address_get_all (NMPlatform *self, int ifindex) +{ + return _ipx_address_get_all (self, ifindex, NMP_OBJECT_TYPE_IP4_ADDRESS); +} + +GArray * +nmtstp_platform_ip6_address_get_all (NMPlatform *self, int ifindex) +{ + return _ipx_address_get_all (self, ifindex, NMP_OBJECT_TYPE_IP6_ADDRESS); +} + +/*****************************************************************************/ + +gboolean +nmtstp_platform_ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric) +{ + NMDedupMultiIter iter; + + nm_platform_process_events (platform); + + nm_dedup_multi_iter_for_each (&iter, + nm_platform_lookup_addrroute (platform, + NMP_OBJECT_TYPE_IP4_ROUTE, + ifindex)) { + const NMPlatformIP4Route *r = NMP_OBJECT_CAST_IP4_ROUTE (iter.current->obj); + + if ( r->ifindex != ifindex + || r->network != network + || r->plen != plen + || r->metric != metric) { + continue; + } + + return nm_platform_ip_route_delete (platform, NMP_OBJECT_UP_CAST (r)); + } + + return TRUE; +} + +gboolean +nmtstp_platform_ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric) +{ + NMDedupMultiIter iter; + + nm_platform_process_events (platform); + + nm_dedup_multi_iter_for_each (&iter, + nm_platform_lookup_addrroute (platform, + NMP_OBJECT_TYPE_IP6_ROUTE, + ifindex)) { + const NMPlatformIP6Route *r = NMP_OBJECT_CAST_IP6_ROUTE (iter.current->obj); + + if ( r->ifindex != ifindex + || !IN6_ARE_ADDR_EQUAL (&r->network, &network) + || r->plen != plen + || r->metric != metric) { + continue; + } + + return nm_platform_ip_route_delete (platform, NMP_OBJECT_UP_CAST (r)); + } + + return TRUE; +} + +/*****************************************************************************/ + SignalData * add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname) { @@ -153,9 +240,9 @@ link_callback (NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink { const NMPObjectType obj_type = obj_type_i; const NMPlatformSignalChangeType change_type = change_type_i; - GArray *links; - NMPlatformLink *cached; - int i; + NMPLookup lookup; + NMDedupMultiIter iter; + const NMPlatformLink *cached; g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_LINK); g_assert (received); @@ -185,19 +272,21 @@ link_callback (NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink /* Check the data */ g_assert (received->ifindex > 0); - links = nm_platform_link_get_all (NM_PLATFORM_GET, TRUE); - for (i = 0; i < links->len; i++) { - cached = &g_array_index (links, NMPlatformLink, i); + + nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_LINK); + nmp_cache_iter_for_each_link (&iter, + nm_platform_lookup (platform, &lookup), + &cached) { + if (!nmp_object_is_visible (NMP_OBJECT_UP_CAST (cached))) + continue; if (cached->ifindex == received->ifindex) { g_assert_cmpint (nm_platform_link_cmp (cached, received), ==, 0); g_assert (!memcmp (cached, received, sizeof (*cached))); if (data->change_type == NM_PLATFORM_SIGNAL_REMOVED) g_error ("Deleted link still found in the local cache."); - g_array_unref (links); return; } } - g_array_unref (links); if (data->change_type != NM_PLATFORM_SIGNAL_REMOVED) g_error ("Added/changed link not found in the local cache."); @@ -205,113 +294,219 @@ link_callback (NMPlatform *platform, int obj_type_i, int ifindex, NMPlatformLink /*****************************************************************************/ -gboolean -nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric) +static const NMPlatformIP4Route * +_ip4_route_get (NMPlatform *platform, + int ifindex, + guint32 network, + int plen, + guint32 metric, + guint8 tos, + guint *out_c_exists) { - gs_free char *arg_network = NULL; - const char *argv[] = { - NULL, - "route", - "list", - "dev", - ifname, - "exact", - NULL, - NULL, - }; - int exit_status; - gs_free char *std_out = NULL, *std_err = NULL; - char *out; - gboolean success; - gs_free_error GError *error = NULL; - gs_free char *metric_pattern = NULL; + NMDedupMultiIter iter; + NMPLookup lookup; + const NMPObject *o = NULL; + guint c; + const NMPlatformIP4Route *r = NULL; - g_assert (ifname && nm_utils_is_valid_iface_name (ifname, NULL)); - g_assert (!strstr (ifname, " metric ")); - g_assert (plen >= 0 && plen <= 32); + _init_platform (&platform, FALSE); - if (!nmtstp_is_root_test ()) { - /* If we don't test against linux-platform, we don't actually configure any - * routes in the system. */ - return -1; + nmp_lookup_init_ip4_route_by_weak_id (&lookup, + network, + plen, + metric, + tos); + + c = 0; + nmp_cache_iter_for_each (&iter, + nm_platform_lookup (platform, &lookup), + &o) { + if ( NMP_OBJECT_CAST_IP4_ROUTE (o)->ifindex != ifindex + && ifindex > 0) + continue; + if (!r) + r = NMP_OBJECT_CAST_IP4_ROUTE (o); + c++; } - argv[0] = nm_utils_file_search_in_paths ("ip", NULL, - (const char *[]) { "/sbin", "/usr/sbin", NULL }, - G_FILE_TEST_IS_EXECUTABLE, NULL, NULL, NULL); - argv[6] = arg_network = g_strdup_printf ("%s/%d", nm_utils_inet4_ntop (network, NULL), plen); + NM_SET_OUT (out_c_exists, c); + return r; +} - if (!argv[0]) { - /* Hm. There is no 'ip' binary. Return *unknown* */ - return -1; +const NMPlatformIP4Route * +_nmtstp_assert_ip4_route_exists (const char *file, + guint line, + const char *func, + NMPlatform *platform, + int c_exists, + const char *ifname, + guint32 network, + int plen, + guint32 metric, + guint8 tos) +{ + int ifindex; + guint c; + const NMPlatformIP4Route *r = NULL; + + _init_platform (&platform, FALSE); + + ifindex = -1; + if (ifname) { + ifindex = nm_platform_link_get_ifindex (platform, ifname); + g_assert (ifindex > 0); } - success = g_spawn_sync (NULL, - (char **) argv, - (char *[]) { NULL }, - 0, - NULL, - NULL, - &std_out, - &std_err, - &exit_status, - &error); - g_assert_no_error (error); - g_assert (success); - g_assert_cmpstr (std_err, ==, ""); - g_assert (std_out); - - metric_pattern = g_strdup_printf (" metric %u", metric); - out = std_out; - while (out) { - char *eol = strchr (out, '\n'); - gs_free char *line = eol ? g_strndup (out, eol - out) : g_strdup (out); - const char *p; - - out = eol ? &eol[1] : NULL; - if (!line[0]) - continue; + r = _ip4_route_get (platform, + ifindex, + network, + plen, + metric, + tos, + &c); - if (metric == 0) { - if (!strstr (line, " metric ")) - return TRUE; - } - p = strstr (line, metric_pattern); - if (p && NM_IN_SET (p[strlen (metric_pattern)], ' ', '\0')) - return TRUE; + if (c != c_exists && c_exists != -1) { + g_error ("[%s:%u] %s(): The ip4 route %s/%d metric %u tos %u shall exist %u times, but platform has it %u times", + file, line, func, + nm_utils_inet4_ntop (network, NULL), plen, + metric, + tos, + c_exists, + c); } - return FALSE; + + return r; } -void -_nmtstp_assert_ip4_route_exists (const char *file, guint line, const char *func, NMPlatform *platform, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric) +const NMPlatformIP4Route * +nmtstp_ip4_route_get (NMPlatform *platform, + int ifindex, + guint32 network, + int plen, + guint32 metric, + guint8 tos) +{ + return _ip4_route_get (platform, + ifindex, + network, + plen, + metric, + tos, + NULL); +} + +/*****************************************************************************/ + +static const NMPlatformIP6Route * +_ip6_route_get (NMPlatform *platform, + int ifindex, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen, + guint *out_c_exists) +{ + NMDedupMultiIter iter; + NMPLookup lookup; + const NMPObject *o = NULL; + guint c; + const NMPlatformIP6Route *r = NULL; + + _init_platform (&platform, FALSE); + + nmp_lookup_init_ip6_route_by_weak_id (&lookup, + network, + plen, + metric, + src, + src_plen); + + c = 0; + nmp_cache_iter_for_each (&iter, + nm_platform_lookup (platform, &lookup), + &o) { + if ( NMP_OBJECT_CAST_IP6_ROUTE (o)->ifindex != ifindex + && ifindex > 0) + continue; + if (!r) + r = NMP_OBJECT_CAST_IP6_ROUTE (o); + c++; + } + + NM_SET_OUT (out_c_exists, c); + return r; +} + +const NMPlatformIP6Route * +_nmtstp_assert_ip6_route_exists (const char *file, + guint line, + const char *func, + NMPlatform *platform, + int c_exists, + const char *ifname, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen) { int ifindex; - gboolean exists_checked; + guint c; + const NMPlatformIP6Route *r = NULL; _init_platform (&platform, FALSE); - /* Check for existance of the route by spawning iproute2. Do this because platform - * code might be entirely borked, but we expect ip-route to give a correct result. - * If the ip command cannot be found, we accept this as success. */ - exists_checked = nmtstp_ip4_route_exists (ifname, network, plen, metric); - if (exists_checked != -1 && !exists_checked != !exists) { - g_error ("[%s:%u] %s(): We expect the ip4 route %s/%d metric %u %s, but it %s", - file, line, func, - nm_utils_inet4_ntop (network, NULL), plen, metric, - exists ? "to exist" : "not to exist", - exists ? "doesn't" : "does"); + ifindex = -1; + if (ifname) { + ifindex = nm_platform_link_get_ifindex (platform, ifname); + g_assert (ifindex > 0); } - ifindex = nm_platform_link_get_ifindex (platform, ifname); - g_assert (ifindex > 0); - if (!nm_platform_ip4_route_get (platform, ifindex, network, plen, metric) != !exists) { - g_error ("[%s:%u] %s(): The ip4 route %s/%d metric %u %s, but platform thinks %s", + r = _ip6_route_get (platform, + ifindex, + network, + plen, + metric, + src, + src_plen, + &c); + + if (c != c_exists && c_exists != -1) { + char s_src[NM_UTILS_INET_ADDRSTRLEN]; + char s_network[NM_UTILS_INET_ADDRSTRLEN]; + + g_error ("[%s:%u] %s(): The ip6 route %s/%d metric %u src %s/%d shall exist %u times, but platform has it %u times", file, line, func, - nm_utils_inet4_ntop (network, NULL), plen, metric, - exists ? "exists" : "does not exist", - exists ? "it doesn't" : "it does"); + nm_utils_inet6_ntop (network, s_network), + plen, + metric, + nm_utils_inet6_ntop (src, s_src), + src_plen, + c_exists, + c); } + + return r; +} + +const NMPlatformIP6Route * +nmtstp_ip6_route_get (NMPlatform *platform, + int ifindex, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen) +{ + return _ip6_route_get (platform, + ifindex, + network, + plen, + metric, + src, + src_plen, + NULL); } /*****************************************************************************/ @@ -369,7 +564,7 @@ _wait_for_signal_timeout (gpointer user_data) } guint -nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms) +nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_ms) { WaitForSignalData data = { 0 }; gulong id_link, id_ip4_address, id_ip6_address, id_ip4_route, id_ip6_route; @@ -384,8 +579,18 @@ nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms) id_ip4_route = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); id_ip6_route = g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (_wait_for_signal_cb), &data); - if (timeout_ms != 0) - data.id = g_timeout_add (timeout_ms, _wait_for_signal_timeout, &data); + /* if timeout_ms is negative, it means the wait-time already expired. + * Maybe, we should do nothing and return right away, without even + * processing events from platform. However, that inconsistency (of not + * processing events from mainloop) is inconvenient. + * + * It's better that on the return of nmtstp_wait_for_signal(), we always + * have no events pending. So, a negative timeout is treated the same as + * a zero timeout: we check whether there are any events pending in platform, + * and quite the mainloop immediately afterwards. But we always check. */ + + data.id = g_timeout_add (CLAMP (timeout_ms, 0, G_MAXUINT32), + _wait_for_signal_timeout, &data); g_main_loop_run (data.loop); @@ -414,14 +619,14 @@ nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms) if (until_ms < now) return 0; - signal_counts = nmtstp_wait_for_signal (platform, MAX (1, until_ms - now)); + signal_counts = nmtstp_wait_for_signal (platform, until_ms - now); if (signal_counts) return signal_counts; } } const NMPlatformLink * -nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms) +nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 timeout_ms) { return nmtstp_wait_for_link_until (platform, ifname, expected_link_type, nm_utils_get_monotonic_timestamp_ms () + timeout_ms); } @@ -445,7 +650,7 @@ nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType if (until_ms < now) return NULL; - nmtstp_wait_for_signal (platform, MAX (1, until_ms - now)); + nmtstp_wait_for_signal (platform, until_ms - now); } } @@ -717,7 +922,7 @@ _ip_address_add (NMPlatform *platform, g_assert (label == NULL); g_assert (flags == 0); - a = nm_platform_ip6_address_get (platform, ifindex, address->addr6, plen); + a = nm_platform_ip6_address_get (platform, ifindex, address->addr6); if ( a && !memcmp (nm_platform_ip6_address_get_peer (a), (IN6_IS_ADDR_UNSPECIFIED (&peer_address->addr6) || IN6_ARE_ADDR_EQUAL (&address->addr6, &peer_address->addr6)) @@ -804,7 +1009,7 @@ void nmtstp_ip4_route_add (NMPlatform *platform, route.metric = metric; route.mss = mss; - g_assert (nm_platform_ip4_route_add (platform, &route)); + g_assert_cmpint (nm_platform_ip4_route_add (platform, NMP_NLM_FLAG_REPLACE, &route), ==, NM_PLATFORM_ERROR_SUCCESS); } void nmtstp_ip6_route_add (NMPlatform *platform, @@ -828,7 +1033,7 @@ void nmtstp_ip6_route_add (NMPlatform *platform, route.metric = metric; route.mss = mss; - g_assert (nm_platform_ip6_route_add (platform, &route)); + g_assert_cmpint (nm_platform_ip6_route_add (platform, NMP_NLM_FLAG_REPLACE, &route), ==, NM_PLATFORM_ERROR_SUCCESS); } /*****************************************************************************/ @@ -861,7 +1066,7 @@ _ip_address_del (NMPlatform *platform, if (is_v4) had_address = !!nm_platform_ip4_address_get (platform, ifindex, address->addr4, plen, peer_address->addr4); else - had_address = !!nm_platform_ip6_address_get (platform, ifindex, address->addr6, plen); + had_address = !!nm_platform_ip6_address_get (platform, ifindex, address->addr6); if (is_v4) { success = nmtstp_run_command ("ip address delete %s%s%s/%d dev %s", @@ -913,7 +1118,7 @@ _ip_address_del (NMPlatform *platform, } else { const NMPlatformIP6Address *a; - a = nm_platform_ip6_address_get (platform, ifindex, address->addr6, plen); + a = nm_platform_ip6_address_get (platform, ifindex, address->addr6); if (!a) break; } @@ -974,6 +1179,36 @@ nmtstp_ip6_address_del (NMPlatform *platform, } G_STMT_END const NMPlatformLink * +nmtstp_link_veth_add (NMPlatform *platform, + gboolean external_command, + const char *name, + const char *peer) +{ + const NMPlatformLink *pllink = NULL; + gboolean success; + + g_assert (nm_utils_is_valid_iface_name (name, NULL)); + + external_command = nmtstp_run_command_check_external (external_command); + + _init_platform (&platform, external_command); + + if (external_command) { + success = !nmtstp_run_command ("ip link add dev %s type veth peer name %s", + name, peer); + if (success) { + pllink = nmtstp_assert_wait_for_link (platform, name, NM_LINK_TYPE_VETH, 100); + nmtstp_assert_wait_for_link (platform, peer, NM_LINK_TYPE_VETH, 10); + } + } else + success = nm_platform_link_veth_add (platform, name, peer, &pllink) == NM_PLATFORM_ERROR_SUCCESS; + + g_assert (success); + _assert_pllink (platform, success, pllink, name, NM_LINK_TYPE_VETH); + return pllink; +} + +const NMPlatformLink * nmtstp_link_dummy_add (NMPlatform *platform, gboolean external_command, const char *name) diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h index a52a5db5..4010aa2f 100644 --- a/src/platform/tests/test-common.h +++ b/src/platform/tests/test-common.h @@ -5,6 +5,7 @@ #include <arpa/inet.h> #include "platform/nm-platform.h" +#include "platform/nmp-object.h" #include "platform/nm-fake-platform.h" #include "platform/nm-linux-platform.h" @@ -93,9 +94,9 @@ int nmtstp_run_command (const char *format, ...) _nm_printf (1, 2); /*****************************************************************************/ -guint nmtstp_wait_for_signal (NMPlatform *platform, guint timeout_ms); +guint nmtstp_wait_for_signal (NMPlatform *platform, gint64 timeout_ms); guint nmtstp_wait_for_signal_until (NMPlatform *platform, gint64 until_ms); -const NMPlatformLink *nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, guint timeout_ms); +const NMPlatformLink *nmtstp_wait_for_link (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 timeout_ms); const NMPlatformLink *nmtstp_wait_for_link_until (NMPlatform *platform, const char *ifname, NMLinkType expected_link_type, gint64 until_ms); #define nmtstp_assert_wait_for_signal(platform, timeout_ms) \ @@ -120,10 +121,45 @@ gboolean nmtstp_run_command_check_external (int external_command); /*****************************************************************************/ -gboolean nmtstp_ip4_route_exists (const char *ifname, guint32 network, int plen, guint32 metric); - -void _nmtstp_assert_ip4_route_exists (const char *file, guint line, const char *func, NMPlatform *platform, gboolean exists, const char *ifname, guint32 network, int plen, guint32 metric); -#define nmtstp_assert_ip4_route_exists(platform, exists, ifname, network, plen, metric) _nmtstp_assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, platform, exists, ifname, network, plen, metric) +const NMPlatformIP4Route *_nmtstp_assert_ip4_route_exists (const char *file, + guint line, + const char *func, + NMPlatform *platform, + int c_exists, + const char *ifname, + guint32 network, + int plen, + guint32 metric, + guint8 tos); +#define nmtstp_assert_ip4_route_exists(platform, c_exists, ifname, network, plen, metric, tos) _nmtstp_assert_ip4_route_exists (__FILE__, __LINE__, G_STRFUNC, platform, c_exists, ifname, network, plen, metric, tos) + +const NMPlatformIP4Route *nmtstp_ip4_route_get (NMPlatform *platform, + int ifindex, + guint32 network, + int plen, + guint32 metric, + guint8 tos); + +const NMPlatformIP6Route *_nmtstp_assert_ip6_route_exists (const char *file, + guint line, + const char *func, + NMPlatform *platform, + int c_exists, + const char *ifname, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen); +#define nmtstp_assert_ip6_route_exists(platform, c_exists, ifname, network, plen, metric, src, src_plen) _nmtstp_assert_ip6_route_exists (__FILE__, __LINE__, G_STRFUNC, platform, c_exists, ifname, network, plen, metric, src, src_plen) + +const NMPlatformIP6Route *nmtstp_ip6_route_get (NMPlatform *platform, + int ifindex, + const struct in6_addr *network, + guint plen, + guint32 metric, + const struct in6_addr *src, + guint8 src_plen); /*****************************************************************************/ @@ -187,8 +223,36 @@ void nmtstp_ip6_route_add (NMPlatform *platform, guint32 metric, guint32 mss); +static inline GPtrArray * +nmtstp_ip4_route_get_all (NMPlatform *platform, + int ifindex) +{ + return nm_platform_lookup_addrroute_clone (platform, + NMP_OBJECT_TYPE_IP4_ROUTE, + ifindex, + nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel, + NULL); +} + +static inline GPtrArray * +nmtstp_ip6_route_get_all (NMPlatform *platform, + int ifindex) +{ + return nm_platform_lookup_addrroute_clone (platform, + NMP_OBJECT_TYPE_IP6_ROUTE, + ifindex, + nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel, + NULL); +} + /*****************************************************************************/ +GArray *nmtstp_platform_ip4_address_get_all (NMPlatform *self, int ifindex); +GArray *nmtstp_platform_ip6_address_get_all (NMPlatform *self, int ifindex); + +gboolean nmtstp_platform_ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric); +gboolean nmtstp_platform_ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric); + const NMPlatformLink *nmtstp_link_get_typed (NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type); const NMPlatformLink *nmtstp_link_get (NMPlatform *platform, int ifindex, const char *name); @@ -197,6 +261,10 @@ void nmtstp_link_set_updown (NMPlatform *platform, int ifindex, gboolean up); +const NMPlatformLink *nmtstp_link_veth_add (NMPlatform *platform, + gboolean external_command, + const char *name, + const char *peer); const NMPlatformLink *nmtstp_link_dummy_add (NMPlatform *platform, gboolean external_command, const char *name); @@ -231,6 +299,100 @@ void nmtstp_link_del (NMPlatform *platform, int ifindex, const char *name); +/*****************************************************************************/ + +extern int NMTSTP_ENV1_IFINDEX; +extern int NMTSTP_ENV1_EX; + +static inline void +_nmtstp_env1_wrapper_setup (const NmtstTestData *test_data) +{ + int *p_ifindex; + gpointer p_ifup; + + nmtst_test_data_unpack (test_data, &p_ifindex, NULL, NULL, NULL, &p_ifup); + + g_assert (p_ifindex && *p_ifindex == -1); + + _LOGT ("TEST[%s]: setup", test_data->testpath); + + nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)); + g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME)); + g_assert_cmpint (nm_platform_link_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL), ==, NM_PLATFORM_ERROR_SUCCESS); + + *p_ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); + g_assert_cmpint (*p_ifindex, >, 0); + g_assert_cmpint (NMTSTP_ENV1_IFINDEX, ==, -1); + + if (GPOINTER_TO_INT (p_ifup)) + g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, *p_ifindex, NULL)); + + nm_platform_process_events (NM_PLATFORM_GET); + + NMTSTP_ENV1_IFINDEX = *p_ifindex; + NMTSTP_ENV1_EX = nmtstp_run_command_check_external_global (); +} + +static inline void +_nmtstp_env1_wrapper_run (gconstpointer user_data) +{ + const NmtstTestData *test_data = user_data; + GTestDataFunc test_func_data; + GTestFunc test_func; + gconstpointer d; + + nmtst_test_data_unpack (test_data, NULL, &test_func, &test_func_data, &d, NULL); + + _LOGT ("TEST[%s]: run", test_data->testpath); + if (test_func) + test_func (); + else + test_func_data (d); +} + +static inline void +_nmtstp_env1_wrapper_teardown (const NmtstTestData *test_data) +{ + int *p_ifindex; + + nmtst_test_data_unpack (test_data, &p_ifindex, NULL, NULL, NULL, NULL); + + g_assert_cmpint (NMTSTP_ENV1_IFINDEX, ==, *p_ifindex); + NMTSTP_ENV1_IFINDEX = -1; + + _LOGT ("TEST[%s]: teardown", test_data->testpath); + + g_assert_cmpint (*p_ifindex, ==, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)); + g_assert (nm_platform_link_delete (NM_PLATFORM_GET, *p_ifindex)); + + nm_platform_process_events (NM_PLATFORM_GET); + + _LOGT ("TEST[%s]: finished", test_data->testpath); + + *p_ifindex = -1; +} + +/* add test function, that set's up a particular environment, consisting + * of a dummy device with ifindex NMTSTP_ENV1_IFINDEX. */ +#define _nmtstp_env1_add_test_func_full(testpath, test_func, test_data_func, arg, ifup) \ + nmtst_add_test_func_full (testpath, \ + _nmtstp_env1_wrapper_run, \ + _nmtstp_env1_wrapper_setup, \ + _nmtstp_env1_wrapper_teardown, \ + ({ static int _ifindex = -1; &_ifindex; }), \ + ({ GTestFunc _test_func = (test_func); _test_func; }), \ + ({ GTestDataFunc _test_func = (test_data_func); _test_func; }), \ + (arg), \ + ({ gboolean _ifup = (ifup); GINT_TO_POINTER (_ifup);})) + +#define nmtstp_env1_add_test_func_data(testpath, test_func, arg, ifup) \ + _nmtstp_env1_add_test_func_full(testpath, NULL, test_func, arg, ifup) + +#define nmtstp_env1_add_test_func(testpath, test_func, ifup) \ + _nmtstp_env1_add_test_func_full(testpath, test_func, NULL, NULL, ifup) + +/*****************************************************************************/ + typedef void (*NMTstpSetupFunc) (void); extern NMTstpSetupFunc const _nmtstp_setup_platform_func; diff --git a/src/platform/tests/test-general.c b/src/platform/tests/test-general.c index e772662c..342aa0d6 100644 --- a/src/platform/tests/test-general.c +++ b/src/platform/tests/test-general.c @@ -44,7 +44,7 @@ static void test_link_get_all (void) { gs_unref_object NMPlatform *platform = NULL; - gs_unref_array GArray *links = NULL; + gs_unref_ptrarray GPtrArray *links = NULL; platform = nm_linux_platform_new (TRUE, NM_PLATFORM_NETNS_SUPPORT_DEFAULT); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index ed435567..9c72371c 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -76,7 +76,7 @@ test_bogus(void) g_assert (!addrlen); g_assert (!nm_platform_link_get_address (NM_PLATFORM_GET, BOGUS_IFINDEX, NULL)); - g_assert (!nm_platform_link_set_mtu (NM_PLATFORM_GET, BOGUS_IFINDEX, MTU)); + g_assert (nm_platform_link_set_mtu (NM_PLATFORM_GET, BOGUS_IFINDEX, MTU) != NM_PLATFORM_ERROR_SUCCESS); g_assert (!nm_platform_link_get_mtu (NM_PLATFORM_GET, BOGUS_IFINDEX)); @@ -264,7 +264,8 @@ test_slave (int master, int type, SignalData *master_changed) } g_assert (!nm_platform_link_is_up (NM_PLATFORM_GET, ifindex)); g_assert (!nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); - if (nm_platform_link_is_connected (NM_PLATFORM_GET, master)) { + if ( nmtstp_is_root_test () + && nm_platform_link_is_connected (NM_PLATFORM_GET, master)) { if (nm_platform_link_get_type (NM_PLATFORM_GET, master) == NM_LINK_TYPE_TEAM) { /* Older team versions (e.g. Fedora 17) have a bug that team master stays * IFF_LOWER_UP even if its slave is down. Double check it with iproute2 and if @@ -285,7 +286,7 @@ test_slave (int master, int type, SignalData *master_changed) g_assert (nm_platform_link_is_connected (NM_PLATFORM_GET, master)); accept_signals (link_changed, 1, 3); /* NM running, can cause additional change of addrgenmode */ - accept_signals (master_changed, 1, 2); + accept_signals (master_changed, 0, 2); /* Enslave again * @@ -294,7 +295,7 @@ test_slave (int master, int type, SignalData *master_changed) ensure_no_signal (link_changed); g_assert (nm_platform_link_enslave (NM_PLATFORM_GET, master, ifindex)); accept_signals (link_changed, 0, 2); - ensure_no_signal (master_changed); + accept_signals (master_changed, 0, 2); /* Set slave option */ switch (type) { @@ -327,7 +328,7 @@ test_slave (int master, int type, SignalData *master_changed) ensure_no_signal (link_changed); accept_signal (link_removed); } - accept_signals (master_changed, 1, 2); + accept_signals (master_changed, 0, 2); ensure_no_signal (master_changed); @@ -511,7 +512,8 @@ test_bridge_addr (void) plink = nm_platform_link_get (NM_PLATFORM_GET, link.ifindex); g_assert (plink); - if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET)) { + if (nm_platform_check_kernel_support (NM_PLATFORM_GET, + NM_PLATFORM_KERNEL_SUPPORT_USER_IPV6LL)) { g_assert (!nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, link.ifindex)); g_assert_cmpint (_nm_platform_uint8_inv (plink->inet6_addr_gen_mode_inv), ==, NM_IN6_ADDR_GEN_MODE_EUI64); @@ -601,7 +603,7 @@ test_internal (void) accept_signal (link_changed); /* Set MTU */ - g_assert (nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, MTU)); + g_assert (nm_platform_link_set_mtu (NM_PLATFORM_GET, ifindex, MTU) == NM_PLATFORM_ERROR_SUCCESS); g_assert_cmpint (nm_platform_link_get_mtu (NM_PLATFORM_GET, ifindex), ==, MTU); accept_signal (link_changed); @@ -790,7 +792,7 @@ test_software_detect (gconstpointer user_data) * namespaced, the creation can fail if a macvtap in another namespace * has the same index. Try to detect this situation and skip already * used indexes. - * http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=17af2bce88d31e65ed73d638bb752d2e13c66ced + * The fix (17af2bce) is included kernel 4.7, dated 24 July, 2016. */ for (i = ifindex_parent + 1; i < ifindex_parent + 100; i++) { snprintf (buf, sizeof (buf), "/sys/class/macvtap/tap%d", i); @@ -1713,9 +1715,8 @@ test_nl_bugs_veth (void) NMTstpNamespaceHandle *ns_handle = NULL; /* create veth pair. */ - nmtstp_run_command_check ("ip link add dev %s type veth peer name %s", IFACE_VETH0, IFACE_VETH1); - ifindex_veth0 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_VETH0, NM_LINK_TYPE_VETH, 100)->ifindex; - ifindex_veth1 = nmtstp_assert_wait_for_link (NM_PLATFORM_GET, IFACE_VETH1, NM_LINK_TYPE_VETH, 100)->ifindex; + ifindex_veth0 = nmtstp_link_veth_add (NM_PLATFORM_GET, -1, IFACE_VETH0, IFACE_VETH1)->ifindex; + ifindex_veth1 = nmtstp_link_get_typed (NM_PLATFORM_GET, -1, IFACE_VETH1, NM_LINK_TYPE_VETH)->ifindex; /* assert that nm_platform_link_veth_get_properties() returns the expected peer ifindexes. */ g_assert (nm_platform_link_veth_get_properties (NM_PLATFORM_GET, ifindex_veth0, &i)); @@ -1728,8 +1729,8 @@ test_nl_bugs_veth (void) pllink_veth0 = nm_platform_link_get (NM_PLATFORM_GET, ifindex_veth0); g_assert (pllink_veth0); if (pllink_veth0->parent == 0) { - /* pre-4.1 kernels don't support exposing the veth peer as IFA_LINK. skip the remainder - * of the test. */ + /* Kernels prior to 4.1 dated 21 June, 2015 don't support exposing the veth peer + * as IFA_LINK. skip the remainder of the test. */ goto out; } g_assert_cmpint (pllink_veth0->parent, ==, ifindex_veth1); @@ -2023,8 +2024,8 @@ test_netns_general (gpointer fixture, gconstpointer test_data) _sysctl_assert_eq (platform_1, "/proc/sys/net/ipv6/conf/dummy2b/disable_ipv6", NULL); _sysctl_assert_eq (platform_2, "/proc/sys/net/ipv6/conf/dummy2a/disable_ipv6", NULL); - /* older kernels (Ubuntu 12.04) don't support ethtool -i for dummy devices. Work around that and - * skip asserts that are known to fail. */ + /* Kernels prior to 3.19 dated 8 February, 2015 don't support ethtool -i for dummy devices. + * Work around that and skip asserts that are known to fail. */ ethtool_support = nmtstp_run_command ("ethtool -i dummy1_ > /dev/null") == 0; if (ethtool_support) { g_assert (nmp_utils_ethtool_get_driver_info (nmtstp_link_get_typed (platform_1, 0, "dummy1_", NM_LINK_TYPE_DUMMY)->ifindex, &driver_info)); diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c index 42dfc572..a02388d2 100644 --- a/src/platform/tests/test-nmp-object.c +++ b/src/platform/tests/test-nmp-object.c @@ -33,6 +33,60 @@ struct { /*****************************************************************************/ +static void +test_obj_base (void) +{ + static const union { + GObject g; + NMPObject k; + } x = { }; + static const union { + GTypeClass k; + NMPClass c; + } l = { }; + static const GObject *g = &x.g; + static const GTypeClass *k = &l.k; + static const NMPObject *o = &x.k; + static const NMPClass *c = &l.c; + + NMObjBaseInst *obj; + gs_unref_object GCancellable *obj_cancellable = g_cancellable_new (); + nm_auto_nmpobj NMPObject *obj_link = nmp_object_new_link (10); + +#define STATIC_ASSERT(cond) \ + G_STMT_START { \ + G_STATIC_ASSERT (cond); \ + G_STATIC_ASSERT_EXPR (cond); \ + g_assert (cond); \ + } G_STMT_END + + STATIC_ASSERT (&g->g_type_instance == (void *) &o->_class); + STATIC_ASSERT (&g->g_type_instance.g_class == (void *) &o->_class); + + STATIC_ASSERT (sizeof (o->parent.parent) == sizeof (GTypeInstance)); + + STATIC_ASSERT (&c->parent == (void *) c); + STATIC_ASSERT (&c->parent.parent.g_type_class == (void *) c); + STATIC_ASSERT (&c->parent.parent.g_type == (void *) c); + STATIC_ASSERT (&c->parent.parent.g_type == &k->g_type); + + STATIC_ASSERT (sizeof (c->parent.parent) == sizeof (GTypeClass)); + + STATIC_ASSERT (&o->parent == (void *) o); + STATIC_ASSERT (&o->parent.klass == (void *) &o->_class); + + obj = (NMObjBaseInst *) obj_cancellable; + g_assert (!NMP_CLASS_IS_VALID ((NMPClass *) obj->klass)); + g_assert (G_TYPE_CHECK_INSTANCE_TYPE (obj, G_TYPE_CANCELLABLE)); + + obj = (NMObjBaseInst *) obj_link; + g_assert (NMP_CLASS_IS_VALID ((NMPClass *) obj->klass)); + g_assert (!G_TYPE_CHECK_INSTANCE_TYPE (obj, G_TYPE_CANCELLABLE)); + +} + +/*****************************************************************************/ + static gboolean _nmp_object_id_equal (const NMPObject *a, const NMPObject *b) { @@ -56,150 +110,144 @@ _nmp_object_equal (const NMPObject *a, const NMPObject *b) /*****************************************************************************/ static void -_assert_cache_multi_lookup_contains (const NMPCache *cache, const NMPCacheId *cache_id, const NMPObject *obj, gboolean contains) +_assert_cache_multi_lookup_contains (const NMPCache *cache, const NMDedupMultiHeadEntry *head_entry, const NMPObject *obj, gboolean visible_only, gboolean contains) { - const NMPlatformObject *const *objects; - guint i, len; + NMDedupMultiIter iter; gboolean found; + guint i, len; + const NMPObject *o; - g_assert (cache_id); g_assert (NMP_OBJECT_IS_VALID (obj)); g_assert (nmp_cache_lookup_obj (cache, obj) == obj); + g_assert (!head_entry || (head_entry->len > 0 && c_list_length (&head_entry->lst_entries_head) == head_entry->len)); - objects = nmp_cache_lookup_multi (cache, cache_id, &len); - - g_assert ((len == 0 && !objects) || (len > 0 && objects && !objects[len])); + len = head_entry ? head_entry->len : 0; found = FALSE; - for (i = 0; i < len; i++) { - NMPObject *o; - - g_assert (objects[i]); - o = NMP_OBJECT_UP_CAST (objects[i]); + i = 0; + nmp_cache_iter_for_each (&iter, + head_entry, + &o) { g_assert (NMP_OBJECT_IS_VALID (o)); - if (obj == o) { - g_assert (!found); - found = TRUE; + if ( !visible_only + || nmp_object_is_visible (o)) { + g_assert (!found); + found = TRUE; + } } + i++; } + g_assert (len == i); g_assert (!!contains == found); } -/*****************************************************************************/ +static void +_assert_cache_multi_lookup_contains_link (const NMPCache *cache, + gboolean visible_only, + const NMPObject *obj, + gboolean contains) +{ + const NMDedupMultiHeadEntry *head_entry; + NMPLookup lookup; -typedef struct { - NMPCache *cache; - NMPCacheOpsType expected_ops_type; - const NMPObject *obj_clone; - NMPObject *new_clone; - gboolean was_visible; - gboolean called; -} _NMPCacheUpdateData; + g_assert (cache); + + nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_LINK); + head_entry = nmp_cache_lookup (cache, &lookup); + _assert_cache_multi_lookup_contains (cache, head_entry, obj, visible_only, contains); +} + +/*****************************************************************************/ static void -_nmp_cache_update_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data) +ops_post_check (NMPCache *cache, + NMPCacheOpsType ops_type, + const NMPObject *obj_old, + const NMPObject *obj_new, + const NMPObject *obj_new_expected, + NMPCacheOpsType expected_ops_type) { - _NMPCacheUpdateData *data = user_data; - - g_assert (data); - g_assert (!data->called); - g_assert (data->cache == cache); + g_assert (cache); - g_assert_cmpint (data->expected_ops_type, ==, ops_type); + g_assert_cmpint (expected_ops_type, ==, ops_type); switch (ops_type) { case NMP_CACHE_OPS_ADDED: - g_assert (!old); - g_assert (NMP_OBJECT_IS_VALID (new)); - g_assert (nmp_object_is_alive (new)); - g_assert (nmp_object_id_equal (data->obj_clone, new)); - g_assert (nmp_object_equal (data->obj_clone, new)); + g_assert (!obj_old); + g_assert (NMP_OBJECT_IS_VALID (obj_new)); + g_assert (nmp_object_is_alive (obj_new)); + g_assert (nmp_object_id_equal (obj_new_expected, obj_new)); + g_assert (nmp_object_equal (obj_new_expected, obj_new)); break; case NMP_CACHE_OPS_UPDATED: - g_assert (NMP_OBJECT_IS_VALID (old)); - g_assert (NMP_OBJECT_IS_VALID (new)); - g_assert (nmp_object_is_alive (old)); - g_assert (nmp_object_is_alive (new)); - g_assert (nmp_object_id_equal (data->obj_clone, new)); - g_assert (nmp_object_id_equal (data->obj_clone, old)); - g_assert (nmp_object_id_equal (old, new)); - g_assert (nmp_object_equal (data->obj_clone, new)); - g_assert (!nmp_object_equal (data->obj_clone, old)); - g_assert (!nmp_object_equal (old, new)); + g_assert (obj_old != obj_new); + g_assert (NMP_OBJECT_IS_VALID (obj_old)); + g_assert (NMP_OBJECT_IS_VALID (obj_new)); + g_assert (nmp_object_is_alive (obj_old)); + g_assert (nmp_object_is_alive (obj_new)); + g_assert (nmp_object_id_equal (obj_new_expected, obj_new)); + g_assert (nmp_object_id_equal (obj_new_expected, obj_old)); + g_assert (nmp_object_id_equal (obj_old, obj_new)); + g_assert (nmp_object_equal (obj_new_expected, obj_new)); + g_assert (!nmp_object_equal (obj_new_expected, obj_old)); + g_assert (!nmp_object_equal (obj_old, obj_new)); break; case NMP_CACHE_OPS_REMOVED: - g_assert (!new); - g_assert (NMP_OBJECT_IS_VALID (old)); - g_assert (nmp_object_is_alive (old)); - g_assert (nmp_object_id_equal (data->obj_clone, old)); + g_assert (!obj_new); + g_assert (NMP_OBJECT_IS_VALID (obj_old)); + g_assert (nmp_object_is_alive (obj_old)); + if (obj_new_expected) + g_assert (nmp_object_id_equal (obj_new_expected, obj_old)); + break; + case NMP_CACHE_OPS_UNCHANGED: + g_assert (obj_old == obj_new); + if (obj_old) { + g_assert (NMP_OBJECT_IS_VALID (obj_old)); + g_assert (nmp_object_is_alive (obj_old)); + g_assert (nmp_object_equal (obj_old, obj_new)); + g_assert (nmp_object_id_equal (obj_new_expected, obj_new)); + } else + g_assert (!obj_new_expected); break; default: g_assert_not_reached (); } - - data->was_visible = old ? nmp_object_is_visible (old) : FALSE; - data->new_clone = new ? nmp_object_clone (new, FALSE) : NULL; - data->called = TRUE; } static void -_nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj, gboolean *out_was_visible, NMPCacheOpsType expected_ops_type) +_nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, const NMPObject **out_obj_old, const NMPObject **out_obj_new, NMPCacheOpsType expected_ops_type) { NMPCacheOpsType ops_type; - NMPObject *obj2; - gboolean was_visible; - nm_auto_nmpobj NMPObject *obj_clone = nmp_object_clone (obj, FALSE); - nm_auto_nmpobj NMPObject *new_clone = NULL; + const NMPObject *obj_prev; const NMPObject *obj_old; - _NMPCacheUpdateData data = { - .cache = cache, - .expected_ops_type = expected_ops_type, - .obj_clone = obj_clone, - }; - - obj_old = nmp_cache_lookup_link (cache, obj->object.ifindex); - if (obj_old && obj_old->_link.udev.device) - obj_clone->_link.udev.device = udev_device_ref (obj_old->_link.udev.device); - _nmp_object_fixup_link_udev_fields (obj_clone, nmp_cache_use_udev_get (cache)); + const NMPObject *obj_new; + nm_auto_nmpobj NMPObject *obj_new_expected = NULL; g_assert (cache); g_assert (NMP_OBJECT_IS_VALID (obj)); - ops_type = nmp_cache_update_netlink (cache, obj, &obj2, &was_visible, _nmp_cache_update_hook, &data); - - new_clone = data.new_clone; - - g_assert_cmpint (ops_type, ==, expected_ops_type); + obj_prev = nmp_cache_lookup_link (cache, obj->object.ifindex); + obj_new_expected = nmp_object_clone (obj, FALSE); + if (obj_prev && obj_prev->_link.udev.device) + obj_new_expected->_link.udev.device = udev_device_ref (obj_prev->_link.udev.device); + _nmp_object_fixup_link_udev_fields (&obj_new_expected, NULL, nmp_cache_use_udev_get (cache)); - if (ops_type != NMP_CACHE_OPS_UNCHANGED) { - g_assert (NMP_OBJECT_IS_VALID (obj2)); - g_assert (data.called); - g_assert_cmpint (data.was_visible, ==, was_visible); + ops_type = nmp_cache_update_netlink (cache, obj, FALSE, &obj_old, &obj_new); + ops_post_check (cache, ops_type, obj_old, obj_new, + nmp_object_is_alive (obj_new_expected) ? obj_new_expected : NULL, + expected_ops_type); - if (ops_type == NMP_CACHE_OPS_REMOVED) - g_assert (!data.new_clone); - else { - g_assert (data.new_clone); - g_assert (nmp_object_equal (obj2, data.new_clone)); - } - } else { - g_assert (!data.called); - g_assert (!obj2 || was_visible == nmp_object_is_visible (obj2)); - } - - g_assert (!obj2 || nmp_object_id_equal (obj, obj2)); - if (ops_type != NMP_CACHE_OPS_REMOVED && obj2) - g_assert (nmp_object_equal (obj, obj2)); - - if (out_obj) - *out_obj = obj2; + if (out_obj_new) + *out_obj_new = obj_new; else - nmp_object_unref (obj2); - if (out_was_visible) - *out_was_visible = was_visible; + nmp_object_unref (obj_new); + if (out_obj_old) + *out_obj_old = obj_old; + else + nmp_object_unref (obj_old); } static const NMPlatformLink pl_link_2 = { @@ -218,168 +266,189 @@ static void test_cache_link (void) { NMPCache *cache; - NMPObject *obj1, *obj2; + NMPObject *objm1; + const NMPObject *obj_old, *obj_new; NMPObject objs1; - gboolean was_visible; - NMPCacheId cache_id_storage; struct udev_device *udev_device_2 = g_list_nth_data (global.udev_devices, 0); struct udev_device *udev_device_3 = g_list_nth_data (global.udev_devices, 0); NMPCacheOpsType ops_type; + nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = NULL; + + multi_idx = nm_dedup_multi_index_new (); - cache = nmp_cache_new (nmtst_get_rand_int () % 2); + cache = nmp_cache_new (multi_idx, nmtst_get_rand_int () % 2); /* if we have a link, and don't set is_in_netlink, adding it has no effect. */ - obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - g_assert (NMP_OBJECT_UP_CAST (&obj1->object) == obj1); - g_assert (!nmp_object_is_alive (obj1)); - _nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_UNCHANGED); + objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + g_assert (NMP_OBJECT_UP_CAST (&objm1->object) == objm1); + g_assert (!nmp_object_is_alive (objm1)); + _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED); ASSERT_nmp_cache_is_consistent (cache); - g_assert (!obj2); - g_assert (!was_visible); - g_assert (!nmp_cache_lookup_obj (cache, obj1)); + g_assert (!obj_old); + g_assert (!obj_new); + g_assert (!nmp_cache_lookup_obj (cache, objm1)); g_assert (!nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex))); - nmp_object_unref (obj1); + nmp_object_unref (objm1); /* Only when setting @is_in_netlink the link is added. */ - obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - obj1->_link.netlink.is_in_netlink = TRUE; - g_assert (nmp_object_is_alive (obj1)); - _nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_ADDED); + objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + objm1->_link.netlink.is_in_netlink = TRUE; + g_assert (nmp_object_is_alive (objm1)); + _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_ADDED); ASSERT_nmp_cache_is_consistent (cache); - g_assert (nmp_object_equal (obj1, obj2)); - g_assert (!was_visible); - g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2); - g_assert (nmp_object_is_visible (obj2)); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, TRUE); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE); - nmp_object_unref (obj1); - nmp_object_unref (obj2); + g_assert (!obj_old); + g_assert (obj_new); + g_assert (objm1 == obj_new); + g_assert (nmp_object_equal (objm1, obj_new)); + g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); + g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); + g_assert (nmp_object_is_visible (obj_new)); + _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); + _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE); + nmp_object_unref (objm1); + nmp_object_unref (obj_new); /* updating the same link with identical value, has no effect. */ - obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - obj1->_link.netlink.is_in_netlink = TRUE; - g_assert (nmp_object_is_alive (obj1)); - _nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_UNCHANGED); + objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + objm1->_link.netlink.is_in_netlink = TRUE; + g_assert (nmp_object_is_alive (objm1)); + _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED); ASSERT_nmp_cache_is_consistent (cache); - g_assert (obj2 != obj1); - g_assert (nmp_object_equal (obj1, obj2)); - g_assert (was_visible); - g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2); - nmp_object_unref (obj1); - nmp_object_unref (obj2); + g_assert (obj_old); + g_assert (obj_new); + g_assert (obj_new != objm1); + g_assert (nmp_object_equal (objm1, obj_new)); + g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); + g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); + nmp_object_unref (objm1); + nmp_object_unref (obj_new); + nmp_object_unref (obj_new); /* remove the link from netlink */ - obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - g_assert (!nmp_object_is_alive (obj1)); - _nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_REMOVED); + objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + g_assert (!nmp_object_is_alive (objm1)); + _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_REMOVED); ASSERT_nmp_cache_is_consistent (cache); - g_assert (obj2 != obj1); - g_assert (was_visible); - g_assert (!nmp_cache_lookup_obj (cache, obj1)); + g_assert (obj_old); + g_assert (!obj_new); + g_assert (!nmp_cache_lookup_obj (cache, objm1)); g_assert (!nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex))); - nmp_object_unref (obj1); - nmp_object_unref (obj2); + nmp_object_unref (objm1); + nmp_object_unref (obj_old); + nmp_object_unref (obj_new); if (udev_device_2) { /* now add the link only with aspect UDEV. */ - ops_type = nmp_cache_update_link_udev (cache, pl_link_2.ifindex, udev_device_2, &obj2, &was_visible, NULL, NULL); + ops_type = nmp_cache_update_link_udev (cache, pl_link_2.ifindex, udev_device_2, &obj_old, &obj_new); ASSERT_nmp_cache_is_consistent (cache); g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_ADDED); - g_assert (!was_visible); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2); - g_assert (!nmp_object_is_visible (obj2)); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, FALSE); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE); - nmp_object_unref (obj2); + g_assert (!obj_old); + g_assert (obj_new); + g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); + g_assert (!nmp_object_is_visible (obj_new)); + _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, FALSE); + _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); + nmp_object_unref (obj_new); } /* add it in netlink too. */ - obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - obj1->_link.netlink.is_in_netlink = TRUE; - g_assert (nmp_object_is_alive (obj1)); - _nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_ADDED); + objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + objm1->_link.netlink.is_in_netlink = TRUE; + g_assert (nmp_object_is_alive (objm1)); + _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_ADDED); ASSERT_nmp_cache_is_consistent (cache); - g_assert (nmp_object_equal (obj1, obj2)); - g_assert (!was_visible); - g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2); - g_assert (nmp_object_is_visible (obj2)); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, TRUE); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE); - nmp_object_unref (obj1); - nmp_object_unref (obj2); + if (udev_device_2) { + g_assert (obj_old); + g_assert (!nmp_object_is_visible (obj_old)); + } else + g_assert (!obj_old); + g_assert (nmp_object_equal (objm1, obj_new)); + g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); + g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); + g_assert (nmp_object_is_visible (obj_new)); + _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE); + _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); + nmp_object_unref (objm1); + nmp_object_unref (obj_old); + nmp_object_unref (obj_new); /* remove again from netlink. */ - obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); - obj1->_link.netlink.is_in_netlink = FALSE; - g_assert (!nmp_object_is_alive (obj1)); - _nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_REMOVED); + objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2); + objm1->_link.netlink.is_in_netlink = FALSE; + g_assert (!nmp_object_is_alive (objm1)); + _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_REMOVED); ASSERT_nmp_cache_is_consistent (cache); - g_assert (obj2 != obj1); - g_assert (was_visible); + if (udev_device_2) + g_assert (obj_new == objm1); + else + g_assert (!obj_new); + g_assert (obj_old); + g_assert (nmp_object_is_alive (obj_old)); if (udev_device_2) { - g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2); - g_assert (!nmp_object_is_visible (obj2)); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, FALSE); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE); + g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); + g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new); + g_assert (!nmp_object_is_visible (obj_new)); + _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, FALSE); + _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); } else { - g_assert (nmp_cache_lookup_obj (cache, obj1) == NULL); + g_assert (nmp_cache_lookup_obj (cache, objm1) == NULL); g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == NULL); - g_assert (nmp_object_is_visible (obj2)); + g_assert (nmp_object_is_visible (obj_new)); } - nmp_object_unref (obj1); - nmp_object_unref (obj2); + nmp_object_unref (objm1); + nmp_object_unref (obj_old); + nmp_object_unref (obj_new); /* now another link only with aspect UDEV. */ if (udev_device_3) { /* now add the link only with aspect UDEV. */ - ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, udev_device_3, &obj2, &was_visible, NULL, NULL); + ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, udev_device_3, &obj_old, &obj_new); g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_ADDED); ASSERT_nmp_cache_is_consistent (cache); - g_assert (NMP_OBJECT_IS_VALID (obj2)); - g_assert (!was_visible); - g_assert (!nmp_object_is_visible (obj2)); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj2); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, FALSE); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE); - g_assert_cmpint (obj2->_link.netlink.is_in_netlink, ==, FALSE); - g_assert_cmpint (obj2->link.initialized, ==, FALSE); - nmp_object_unref (obj2); + g_assert (NMP_OBJECT_IS_VALID (obj_new)); + g_assert (!obj_old); + g_assert (!nmp_object_is_visible (obj_new)); + g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj_new); + _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, FALSE); + _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); + g_assert_cmpint (obj_new->_link.netlink.is_in_netlink, ==, FALSE); + g_assert_cmpint (obj_new->link.initialized, ==, FALSE); + nmp_object_unref (obj_new); /* add it in netlink too. */ - obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_3); - obj1->_link.netlink.is_in_netlink = TRUE; - g_assert (nmp_object_is_alive (obj1)); - _nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_UPDATED); + objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_3); + objm1->_link.netlink.is_in_netlink = TRUE; + g_assert (nmp_object_is_alive (objm1)); + _nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UPDATED); ASSERT_nmp_cache_is_consistent (cache); - g_assert (obj2 != obj1); - g_assert (nmp_object_equal (obj1, obj2)); - g_assert (!was_visible); - g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj2); - g_assert (nmp_object_is_visible (obj2)); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, TRUE); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE); - g_assert_cmpint (obj2->_link.netlink.is_in_netlink, ==, TRUE); - g_assert_cmpint (obj2->link.initialized, ==, TRUE); - nmp_object_unref (obj1); - nmp_object_unref (obj2); + g_assert (obj_old); + g_assert (obj_new == objm1); + g_assert (nmp_object_equal (objm1, obj_new)); + g_assert (!obj_old || !nmp_object_is_visible (obj_old)); + g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new); + g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj_new); + g_assert (nmp_object_is_visible (obj_new)); + _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE); + _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); + g_assert_cmpint (obj_new->_link.netlink.is_in_netlink, ==, TRUE); + g_assert_cmpint (obj_new->link.initialized, ==, TRUE); + nmp_object_unref (objm1); + nmp_object_unref (obj_old); + nmp_object_unref (obj_new); /* remove UDEV. */ - ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, NULL, &obj2, &was_visible, NULL, NULL); + ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, NULL, &obj_old, &obj_new); g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_UPDATED); ASSERT_nmp_cache_is_consistent (cache); - g_assert (was_visible); - g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj2); - g_assert (nmp_object_is_visible (obj2)); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, TRUE); - _assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE); - g_assert_cmpint (obj2->_link.netlink.is_in_netlink, ==, TRUE); - g_assert_cmpint (obj2->link.initialized, ==, !nmp_cache_use_udev_get (cache)); - nmp_object_unref (obj2); + g_assert (obj_old && nmp_object_is_visible (obj_old)); + g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj_new); + g_assert (nmp_object_is_visible (obj_new)); + _assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE); + _assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE); + g_assert_cmpint (obj_new->_link.netlink.is_in_netlink, ==, TRUE); + g_assert_cmpint (obj_new->link.initialized, ==, !nmp_cache_use_udev_get (cache)); + nmp_object_unref (obj_new); + nmp_object_unref (obj_old); } nmp_cache_free (cache); @@ -429,6 +498,7 @@ main (int argc, char **argv) udev_enumerate_unref (enumerator); } + g_test_add_func ("/nmp-object/obj-base", test_obj_base); g_test_add_func ("/nmp-object/cache_link", test_cache_link); result = g_test_run (); diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index 9960d867..2c00fada 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -27,13 +27,50 @@ #include "test-common.h" -#define DEVICE_NAME "nm-test-device" +#define DEVICE_IFINDEX NMTSTP_ENV1_IFINDEX +#define EX NMTSTP_ENV1_EX + +static void +_wait_for_ipv6_addr_non_tentative (NMPlatform *platform, + gint64 timeout_ms, + int ifindex, + guint addr_n, + const struct in6_addr *addrs) +{ + guint i; + + /* Wait that the addresses become non-tentative. Dummy interfaces are NOARP + * and thus don't do DAD, but the kernel sets the address as tentative for a + * small amount of time, which prevents the immediate addition of the route + * with RTA_PREFSRC */ + + NMTST_WAIT_ASSERT (400, { + gboolean should_wait = FALSE; + const NMPlatformIP6Address *plt_addr; + + for (i = 0; i < addr_n; i++) { + plt_addr = nm_platform_ip6_address_get (platform, ifindex, addrs[i]); + if ( !plt_addr + || NM_FLAGS_HAS (plt_addr->n_ifa_flags, IFA_F_TENTATIVE)) { + should_wait = TRUE; + break; + } + } + if (!should_wait) + return; + nmtstp_assert_wait_for_signal (platform, + (nmtst_wait_end_us - g_get_monotonic_time ()) / 1000); + }); +} + static void ip4_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMPlatformIP4Route *received, int change_type_i, SignalData *data) { const NMPObjectType obj_type = obj_type_i; const NMPlatformSignalChangeType change_type = change_type_i; + NMPObject o_id; + nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new (NMP_OBJECT_TYPE_IP4_ROUTE, NULL); g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_IP4_ROUTE); g_assert (received); @@ -41,6 +78,11 @@ ip4_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMP g_assert (data && data->name); g_assert_cmpstr (data->name, ==, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED); + /* run code for initializing the ID only */ + nmp_object_stackinit_id (&o_id, NMP_OBJECT_UP_CAST (received)); + nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), TRUE); + nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), FALSE); + if (data->ifindex && data->ifindex != received->ifindex) return; if (data->change_type != change_type) @@ -58,6 +100,8 @@ ip6_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMP { const NMPObjectType obj_type = obj_type_i; const NMPlatformSignalChangeType change_type = change_type_i; + NMPObject o_id; + nm_auto_nmpobj NMPObject *o_id_p = nmp_object_new (NMP_OBJECT_TYPE_IP6_ROUTE, NULL); g_assert_cmpint (obj_type, ==, NMP_OBJECT_TYPE_IP6_ROUTE); g_assert (received); @@ -65,6 +109,11 @@ ip6_route_callback (NMPlatform *platform, int obj_type_i, int ifindex, const NMP g_assert (data && data->name); g_assert_cmpstr (data->name, ==, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED); + /* run code for initializing the ID only */ + nmp_object_stackinit_id (&o_id, NMP_OBJECT_UP_CAST (received)); + nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), TRUE); + nmp_object_copy (o_id_p, NMP_OBJECT_UP_CAST (received), FALSE); + if (data->ifindex && data->ifindex != received->ifindex) return; if (data->change_type != change_type) @@ -90,50 +139,50 @@ test_ip4_route_metric0 (void) int mss = 1000; /* No routes initially */ - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0); - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, metric, 0); /* add the first route */ nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, metric, mss); accept_signal (route_added); - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0); - nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); /* Deleting route with metric 0 does nothing */ - g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0)); + g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0)); ensure_no_signal (route_removed); - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0); - nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); /* add the second route */ nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, INADDR_ANY, 0, 0, mss); accept_signal (route_added); - nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, 0); - nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric); + nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); /* Delete route with metric 0 */ - g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0)); + g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0)); accept_signal (route_removed); - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0); - nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); /* Delete route with metric 0 again (we expect nothing to happen) */ - g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0)); + g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, 0)); ensure_no_signal (route_removed); - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0); - nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); /* Delete the other route */ - g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); accept_signal (route_removed); - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, 0); - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, 0, 0); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, metric, 0); free_signal (route_added); free_signal (route_changed); @@ -147,7 +196,7 @@ test_ip4_route (void) SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip4_route_callback); SignalData *route_changed = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip4_route_callback); SignalData *route_removed = add_signal (NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip4_route_callback); - GArray *routes; + GPtrArray *routes; NMPlatformIP4Route rts[3]; in_addr_t network; guint8 plen = 24; @@ -164,9 +213,9 @@ test_ip4_route (void) accept_signal (route_added); /* Add route */ - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, metric, 0); nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, 0, metric, mss); - nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, network, plen, metric); + nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, network, plen, metric, 0); accept_signal (route_added); /* Add route again */ @@ -174,9 +223,9 @@ test_ip4_route (void) accept_signals (route_changed, 0, 1); /* Add default route */ - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, 0, 0, metric); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, 0, 0, metric, 0); nmtstp_ip4_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, 0, 0, gateway, 0, metric, mss); - nmtstp_assert_ip4_route_exists (NULL, TRUE, DEVICE_NAME, 0, 0, metric); + nmtstp_assert_ip4_route_exists (NULL, 1, DEVICE_NAME, 0, 0, metric, 0); accept_signal (route_added); /* Add default route again */ @@ -184,7 +233,7 @@ test_ip4_route (void) accept_signals (route_changed, 0, 1); /* Test route listing */ - routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); + routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex); memset (rts, 0, sizeof (rts)); rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); rts[0].network = gateway; @@ -211,23 +260,23 @@ test_ip4_route (void) rts[2].mss = mss; rts[2].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE); g_assert_cmpint (routes->len, ==, 3); - nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, rts, routes->len, TRUE); - g_array_unref (routes); + nmtst_platform_ip4_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts, routes->len, TRUE); + g_ptr_array_unref (routes); /* Remove route */ - g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); - nmtstp_assert_ip4_route_exists (NULL, FALSE, DEVICE_NAME, network, plen, metric); + g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); + nmtstp_assert_ip4_route_exists (NULL, 0, DEVICE_NAME, network, plen, metric, 0); accept_signal (route_removed); /* Remove route again */ - g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); /* Remove default route */ - g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, 0, 0, metric)); + g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, 0, 0, metric)); accept_signal (route_removed); /* Remove route to gateway */ - g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, gateway, 32, metric)); + g_assert (nmtstp_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, gateway, 32, metric)); accept_signal (route_removed); free_signal (route_added); @@ -242,7 +291,7 @@ test_ip6_route (void) SignalData *route_added = add_signal (NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_ADDED, ip6_route_callback); SignalData *route_changed = add_signal (NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, ip6_route_callback); SignalData *route_removed = add_signal (NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, ip6_route_callback); - GArray *routes; + GPtrArray *routes; NMPlatformIP6Route rts[3]; struct in6_addr network; guint8 plen = 64; @@ -259,28 +308,16 @@ test_ip6_route (void) NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0)); accept_signals (route_added, 0, 1); - /* Wait that the address becomes non-tentative. Dummy interfaces are NOARP - * and thus don't do DAD, but the kernel sets the address as tentative for a - * small amount of time, which prevents the immediate addition of the route - * with RTA_PREFSRC */ - NMTST_WAIT_ASSERT (200, { - const NMPlatformIP6Address *plt_addr; - - nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); - nm_platform_process_events (NM_PLATFORM_GET); - plt_addr = nm_platform_ip6_address_get (NM_PLATFORM_GET, ifindex, pref_src, 128); - if (plt_addr && !NM_FLAGS_HAS (plt_addr->n_ifa_flags, IFA_F_TENTATIVE)) - break; - }); + _wait_for_ipv6_addr_non_tentative (NM_PLATFORM_GET, 200, ifindex, 1, &pref_src); /* Add route to gateway */ nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, gateway, 128, in6addr_any, in6addr_any, metric, mss); accept_signal (route_added); /* Add route */ - g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (!nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network, plen, gateway, pref_src, metric, mss); - g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); accept_signal (route_added); /* Add route again */ @@ -288,9 +325,9 @@ test_ip6_route (void) accept_signals (route_changed, 0, 1); /* Add default route */ - g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); + g_assert (!nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &in6addr_any, 0, metric, NULL, 0)); nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway, in6addr_any, metric, mss); - g_assert (nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); + g_assert (nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &in6addr_any, 0, metric, NULL, 0)); accept_signal (route_added); /* Add default route again */ @@ -298,7 +335,7 @@ test_ip6_route (void) accept_signals (route_changed, 0, 1); /* Test route listing */ - routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); + routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, ifindex); memset (rts, 0, sizeof (rts)); rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); rts[0].network = gateway; @@ -325,23 +362,23 @@ test_ip6_route (void) rts[2].metric = nm_utils_ip6_route_metric_normalize (metric); rts[2].mss = mss; g_assert_cmpint (routes->len, ==, 3); - nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, rts, routes->len, TRUE); - g_array_unref (routes); + nmtst_platform_ip6_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts, routes->len, TRUE); + g_ptr_array_unref (routes); /* Remove route */ - g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); - g_assert (!nm_platform_ip6_route_get (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (!nmtstp_ip6_route_get (NM_PLATFORM_GET, ifindex, &network, plen, metric, NULL, 0)); accept_signal (route_removed); /* Remove route again */ - g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); + g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, plen, metric)); /* Remove default route */ - g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); + g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, in6addr_any, 0, metric)); accept_signal (route_removed); /* Remove route to gateway */ - g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, gateway, 128, metric)); + g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, gateway, 128, metric)); accept_signal (route_removed); free_signal (route_added); @@ -352,6 +389,45 @@ test_ip6_route (void) /*****************************************************************************/ static void +test_ip_route_get (void) +{ + int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); + in_addr_t a; + NMPlatformError result; + nm_auto_nmpobj NMPObject *route = NULL; + const NMPlatformIP4Route *r; + + nmtstp_run_command_check ("ip route add 1.2.3.0/24 dev %s", DEVICE_NAME); + + NMTST_WAIT_ASSERT (100, { + nmtstp_wait_for_signal (NM_PLATFORM_GET, 10); + if (nmtstp_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.0"), 24, 0, 0)) + break; + }); + + a = nmtst_inet4_from_string ("1.2.3.1"); + result = nm_platform_ip_route_get (NM_PLATFORM_GET, + AF_INET, + &a, + nmtst_get_rand_int () % 2 ? 0 : ifindex, + &route); + + g_assert (result == NM_PLATFORM_ERROR_SUCCESS); + g_assert (NMP_OBJECT_GET_TYPE (route) == NMP_OBJECT_TYPE_IP4_ROUTE); + g_assert (!NMP_OBJECT_IS_STACKINIT (route)); + g_assert (route->parent._ref_count == 1); + r = NMP_OBJECT_CAST_IP4_ROUTE (route); + g_assert (r->rt_cloned); + g_assert (r->ifindex == ifindex); + g_assert (r->network == a); + g_assert (r->plen == 32); + + nmtstp_run_command_check ("ip route flush dev %s", DEVICE_NAME); + + nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); +} + +static void test_ip4_zero_gateway (void) { int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); @@ -361,15 +437,14 @@ test_ip4_zero_gateway (void) NMTST_WAIT_ASSERT (100, { nmtstp_wait_for_signal (NM_PLATFORM_GET, 10); - if ( nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.1"), 32, 0) - && nm_platform_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.2"), 32, 0)) + if ( nmtstp_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.1"), 32, 0, 0) + && nmtstp_ip4_route_get (NM_PLATFORM_GET, ifindex, nmtst_inet4_from_string ("1.2.3.2"), 32, 0, 0)) break; }); nmtstp_run_command_check ("ip route flush dev %s", DEVICE_NAME); nmtstp_wait_for_signal (NM_PLATFORM_GET, 50); - nm_platform_process_events (NM_PLATFORM_GET); } static void @@ -378,7 +453,7 @@ test_ip4_route_options (void) int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); NMPlatformIP4Route route = { }; in_addr_t network; - GArray *routes; + GPtrArray *routes; NMPlatformIP4Route rts[1]; inet_pton (AF_INET, "172.16.1.0", &network); @@ -396,12 +471,10 @@ test_ip4_route_options (void) route.mtu = 1350; route.lock_cwnd = TRUE; - g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, &route)); + g_assert (nm_platform_ip4_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &route) == NM_PLATFORM_ERROR_SUCCESS); /* Test route listing */ - routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, - NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | - NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); + routes = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex); memset (rts, 0, sizeof (rts)); rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); rts[0].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK); @@ -416,69 +489,268 @@ test_ip4_route_options (void) rts[0].initrwnd = 50; rts[0].mtu = 1350; rts[0].lock_cwnd = TRUE; - g_assert_cmpint (routes->len, ==, 1); - nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, rts, routes->len, TRUE); + nmtst_platform_ip4_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts, routes->len, TRUE); /* Remove route */ - /* FIXME. Due to a bug, we cannot delete routes with non-zero TOS. See bgo#785004. */ - //g_assert (nm_platform_ip4_route_delete (NM_PLATFORM_GET, ifindex, network, 24, 20)); + g_assert (nm_platform_ip_route_delete (NM_PLATFORM_GET, routes->pdata[0])); - g_array_unref (routes); + g_ptr_array_unref (routes); } static void -test_ip6_route_options (void) +test_ip6_route_options (gconstpointer test_data) { - int ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); - NMPlatformIP6Route route = { }; - struct in6_addr network; - GArray *routes; - NMPlatformIP6Route rts[3]; - - inet_pton (AF_INET6, "2001:db8:a:b:0:0:0:0", &network); - - route.ifindex = ifindex; - route.rt_source = NM_IP_CONFIG_SOURCE_USER; - route.network = network; - route.plen = 64; - route.gateway = in6addr_any; - route.metric = 1024; - route.window = 20000; - route.cwnd = 8; - route.initcwnd = 22; - route.initrwnd = 33; - route.mtu = 1300; - route.lock_mtu = TRUE; - - g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, &route)); - - /* Test route listing */ - routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, - NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | - NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT); - memset (rts, 0, sizeof (rts)); - rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); - rts[0].network = network; - rts[0].plen = 64; - rts[0].ifindex = ifindex; - rts[0].gateway = in6addr_any; - rts[0].metric = 1024; - rts[0].window = 20000; - rts[0].cwnd = 8; - rts[0].initcwnd = 22; - rts[0].initrwnd = 33; - rts[0].mtu = 1300; - rts[0].lock_mtu = TRUE; - - g_assert_cmpint (routes->len, ==, 1); - nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, rts, routes->len, TRUE); + const int TEST_IDX = GPOINTER_TO_INT (test_data); + const int IFINDEX = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); + GPtrArray *routes; +#define RTS_MAX 3 + NMPlatformIP6Route rts_add[RTS_MAX] = { }; + NMPlatformIP6Route rts_cmp[RTS_MAX] = { }; + NMPlatformIP6Address addr[1] = { }; + struct in6_addr addr_in6[G_N_ELEMENTS (addr)] = { }; + guint rts_n = 0; + guint addr_n = 0; + guint i; + + switch (TEST_IDX) { + case 1: + rts_add[rts_n++] = ((NMPlatformIP6Route) { + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = *nmtst_inet6_from_string ("2001:db8:a:b:0:0:0:0"), + .plen = 64, + .gateway = in6addr_any, + .metric = 1024, + .window = 20000, + .cwnd = 8, + .initcwnd = 22, + .initrwnd = 33, + .mtu = 1300, + .lock_mtu = TRUE, + }); + break; + case 2: + addr[addr_n++] = ((NMPlatformIP6Address) { + .ifindex = IFINDEX, + .address = *nmtst_inet6_from_string ("2000::2"), + .plen = 128, + .peer_address = in6addr_any, + .lifetime = NM_PLATFORM_LIFETIME_PERMANENT, + .preferred = NM_PLATFORM_LIFETIME_PERMANENT, + .n_ifa_flags = 0, + }); + rts_add[rts_n++] = ((NMPlatformIP6Route) { + .ifindex = IFINDEX, + .rt_source = NM_IP_CONFIG_SOURCE_USER, + .network = *nmtst_inet6_from_string ("1010::1"), + .plen = 128, + .gateway = in6addr_any, + .metric = 256, + .pref_src = *nmtst_inet6_from_string ("2000::2"), + }); + break; + case 3: + addr[addr_n++] = ((NMPlatformIP6Address) { + .ifindex = IFINDEX, + .address = *nmtst_inet6_from_string ("2001:db8:8086::5"), + .plen = 128, + .peer_address = in6addr_any, + .lifetime = NM_PLATFORM_LIFETIME_PERMANENT, + .preferred = NM_PLATFORM_LIFETIME_PERMANENT, + .n_ifa_flags = 0, + }); + rts_add[rts_n++] = ((NMPlatformIP6Route) { + .ifindex = IFINDEX, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), + .network = *nmtst_inet6_from_string ("2001:db8:8086::"), + .plen = 110, + .metric = 10021, + .mss = 0, + }); + rts_add[rts_n++] = ((NMPlatformIP6Route) { + .ifindex = IFINDEX, + .rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER), + .network = *nmtst_inet6_from_string ("2001:db8:abad:c0de::"), + .plen = 64, + .gateway = *nmtst_inet6_from_string ("2001:db8:8086::1"), + .metric = 21, + .mss = 0, + }); + break; + default: + g_assert_not_reached (); + } + + for (i = 0; i < addr_n; i++) { + g_assert (addr[i].ifindex == IFINDEX); + addr_in6[i] = addr[i].address; + g_assert (nm_platform_ip6_address_add (NM_PLATFORM_GET, + IFINDEX, + addr[i].address, + addr[i].plen, + addr[i].peer_address, + addr[i].lifetime, + addr[i].preferred, + addr[i].n_ifa_flags)); + } + + _wait_for_ipv6_addr_non_tentative (NM_PLATFORM_GET, 400, IFINDEX, addr_n, addr_in6); + + for (i = 0; i < rts_n; i++) + g_assert (nm_platform_ip6_route_add (NM_PLATFORM_GET, NMP_NLM_FLAG_REPLACE, &rts_add[i]) == NM_PLATFORM_ERROR_SUCCESS); + + routes = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, IFINDEX); + switch (TEST_IDX) { + case 1: + case 2: + case 3: + for (i = 0; i < rts_n; i++) { + rts_cmp[i] = rts_add[i]; + rts_cmp[i].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER); + } + break; + default: + g_assert_not_reached (); + } + g_assert_cmpint (routes->len, ==, rts_n); + nmtst_platform_ip6_routes_equal_aptr ((const NMPObject *const*) routes->pdata, rts_cmp, routes->len, TRUE); + g_ptr_array_unref (routes); + + for (i = 0; i < rts_n; i++) { + g_assert (nmtstp_platform_ip6_route_delete (NM_PLATFORM_GET, IFINDEX, + rts_add[i].network, rts_add[i].plen, + rts_add[i].metric)); + } + + for (i = 0; i < addr_n; i++) { + nmtstp_ip6_address_del (NM_PLATFORM_GET, + EX, + IFINDEX, + rts_add[i].network, + rts_add[i].plen); + } +} - /* Remove route */ - g_assert (nm_platform_ip6_route_delete (NM_PLATFORM_GET, ifindex, network, 64, 1024)); +/*****************************************************************************/ - g_array_unref (routes); +static void +test_ip (gconstpointer test_data) +{ + const int TEST_IDX = GPOINTER_TO_INT (test_data); + const int IFINDEX = nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME); + guint i, j, k; + const NMPlatformLink *l; + char ifname[IFNAMSIZ]; + char ifname2[IFNAMSIZ]; + char s1[NM_UTILS_INET_ADDRSTRLEN]; + NMPlatform *platform = NM_PLATFORM_GET; + const int EX_ = -1; + struct { + int ifindex; + } iface_data[10] = { 0 }; + int order_idx[G_N_ELEMENTS (iface_data)] = { 0 }; + guint order_len; + guint try; + + for (i = 0; i < G_N_ELEMENTS (iface_data); i++) { + nm_sprintf_buf (ifname, "v%02u", i); + nm_sprintf_buf (ifname2, "w%02u", i); + + g_assert (!nm_platform_link_get_by_ifname (platform, ifname)); + g_assert (!nm_platform_link_get_by_ifname (platform, ifname2)); + l = nmtstp_link_veth_add (platform, EX_, ifname, ifname2); + iface_data[i].ifindex = l->ifindex; + + nmtstp_link_set_updown (platform, EX_, iface_data[i].ifindex, TRUE); + nmtstp_link_set_updown (platform, EX_, nmtstp_link_get (platform, -1, ifname2)->ifindex, TRUE); + + nm_sprintf_buf (s1, "192.168.7.%d", 100 + i); + nmtstp_ip4_address_add (platform, + EX_, + iface_data[i].ifindex, + nmtst_inet4_from_string (s1), + 24, + nmtst_inet4_from_string (s1), + 3600, + 3600, + 0, + NULL); + } + + order_len = 0; + for (try = 0; try < 5 * G_N_ELEMENTS (order_idx); try++) { + NMPObject o; + NMPlatformIP4Route *r; + guint idx; + const NMDedupMultiHeadEntry *head_entry; + NMPLookup lookup; + + nmp_object_stackinit (&o, NMP_OBJECT_TYPE_IP4_ROUTE, NULL); + r = NMP_OBJECT_CAST_IP4_ROUTE (&o); + r->network = nmtst_inet4_from_string ("192.168.9.0"); + r->plen = 24; + r->metric = 109; + + if ( order_len == 0 + || ( order_len < G_N_ELEMENTS (order_idx) + && nmtst_get_rand_int () % 2)) { +again_find_idx: + idx = nmtst_get_rand_int () % G_N_ELEMENTS (iface_data); + for (i = 0; i < order_len; i++) { + if (order_idx[i] == idx) + goto again_find_idx; + } + order_idx[order_len++] = idx; + + r->ifindex = iface_data[idx].ifindex; + g_assert (nm_platform_ip4_route_add (platform, NMP_NLM_FLAG_APPEND, r) == NM_PLATFORM_ERROR_SUCCESS); + } else { + i = nmtst_get_rand_int () % order_len; + idx = order_idx[i]; + for (i++; i < order_len; i++) + order_idx[i - 1] = order_idx[i]; + order_len--; + + r->ifindex = iface_data[idx].ifindex; + g_assert (nm_platform_ip_route_delete (platform, &o)); + } + + head_entry = nm_platform_lookup (platform, + nmp_lookup_init_obj_type (&lookup, NMP_OBJECT_TYPE_IP4_ROUTE)); + for (j = 0; j < G_N_ELEMENTS (iface_data); j++) { + gboolean has; + NMDedupMultiIter iter; + const NMPObject *o_cached; + + has = FALSE; + for (k = 0; k < order_len; k++) { + if (order_idx[k] == j) { + g_assert (!has); + has = TRUE; + } + } + + nmp_cache_iter_for_each (&iter, head_entry, &o_cached) { + const NMPlatformIP4Route *r_cached = NMP_OBJECT_CAST_IP4_ROUTE (o_cached); + + if ( r_cached->ifindex != iface_data[j].ifindex + || r_cached->metric != 109) + continue; + + g_assert (has); + has = FALSE; + } + g_assert (!has); + } + } + + for (i = 0; i < G_N_ELEMENTS (iface_data); i++) + g_assert (nm_platform_link_delete (platform, iface_data[i].ifindex)); + + (void) TEST_IDX; + (void) IFINDEX; } /*****************************************************************************/ @@ -494,22 +766,19 @@ _nmtstp_init_tests (int *argc, char ***argv) void _nmtstp_setup_tests (void) { - SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME); - - nm_platform_link_delete (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME)); - g_assert (!nm_platform_link_get_by_ifname (NM_PLATFORM_GET, DEVICE_NAME)); - g_assert (nm_platform_link_dummy_add (NM_PLATFORM_GET, DEVICE_NAME, NULL) == NM_PLATFORM_ERROR_SUCCESS); - accept_signal (link_added); - free_signal (link_added); - - g_assert (nm_platform_link_set_up (NM_PLATFORM_GET, nm_platform_link_get_ifindex (NM_PLATFORM_GET, DEVICE_NAME), NULL)); - - g_test_add_func ("/route/ip4", test_ip4_route); - g_test_add_func ("/route/ip6", test_ip6_route); - g_test_add_func ("/route/ip4_metric0", test_ip4_route_metric0); - g_test_add_func ("/route/ip4_options", test_ip4_route_options); - g_test_add_func ("/route/ip6_options", test_ip6_route_options); - - if (nmtstp_is_root_test ()) - g_test_add_func ("/route/ip4_zero_gateway", test_ip4_zero_gateway); +#define add_test_func(testpath, test_func) nmtstp_env1_add_test_func(testpath, test_func, TRUE) +#define add_test_func_data(testpath, test_func, arg) nmtstp_env1_add_test_func_data(testpath, test_func, arg, TRUE) + add_test_func ("/route/ip4", test_ip4_route); + add_test_func ("/route/ip6", test_ip6_route); + add_test_func ("/route/ip4_metric0", test_ip4_route_metric0); + add_test_func ("/route/ip4_options", test_ip4_route_options); + add_test_func_data ("/route/ip6_options/1", test_ip6_route_options, GINT_TO_POINTER (1)); + add_test_func_data ("/route/ip6_options/2", test_ip6_route_options, GINT_TO_POINTER (2)); + add_test_func_data ("/route/ip6_options/3", test_ip6_route_options, GINT_TO_POINTER (3)); + + if (nmtstp_is_root_test ()) { + add_test_func_data ("/route/ip/1", test_ip, GINT_TO_POINTER (1)); + add_test_func ("/route/ip_route_get", test_ip_route_get); + add_test_func ("/route/ip4_zero_gateway", test_ip4_zero_gateway); + } } |