From a895b58484a69178b2cc6efa9656b05852b49b79 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 3 Jun 2014 15:45:09 +0200 Subject: [PATCH 01/30] platform: don't log error for delete_object() if IPv6 address doesn't exist This causes root platform tests to fail on rhel-7 Signed-off-by: Thomas Haller --- src/platform/nm-linux-platform.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index aaf066af18..21dfee93fc 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1535,13 +1535,22 @@ delete_object (NMPlatform *platform, struct nl_object *obj, gboolean do_refresh_ debug("delete_object failed with \"%s\" (%d), meaning the object was already removed", nl_geterror (nle), nle); break; + case -NLE_FAILURE: + if (object_type == OBJECT_TYPE_IP6_ADDRESS) { + /* On RHEL7 kernel, deleting a non existing address fails with ENXIO (which libnl maps to NLE_FAILURE) */ + debug("delete_object for address failed with \"%s\" (%d), meaning the address was already removed", + nl_geterror (nle), nle); + break; + } + goto DEFAULT; case -NLE_NOADDR: if (object_type == OBJECT_TYPE_IP4_ADDRESS || object_type == OBJECT_TYPE_IP6_ADDRESS) { debug("delete_object for address failed with \"%s\" (%d), meaning the address was already removed", nl_geterror (nle), nle); break; } - /* fall-through to error, because we only expect this for addresses. */ + goto DEFAULT; + DEFAULT: default: error ("Netlink error deleting %s: %s", to_string_object (platform, obj), nl_geterror (nle)); return FALSE; From cb023c57a7210e59c8c4050766f8082b2575a91d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 3 Jun 2014 16:40:04 +0200 Subject: [PATCH 02/30] platform: improve logging on error in delete_object() Signed-off-by: Thomas Haller --- src/platform/nm-linux-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 21dfee93fc..54863425e3 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1552,7 +1552,7 @@ delete_object (NMPlatform *platform, struct nl_object *obj, gboolean do_refresh_ goto DEFAULT; DEFAULT: default: - error ("Netlink error deleting %s: %s", to_string_object (platform, obj), nl_geterror (nle)); + error ("Netlink error deleting %s: %s (%d)", to_string_object (platform, obj), nl_geterror (nle), nle); return FALSE; } From d2ac129d65c94697602552d9315adac6f21a3982 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 30 May 2014 18:14:48 +0200 Subject: [PATCH 03/30] nmtst: g_type_init() has been deprecated in GLib 2.35.0 Signed-off-by: Thomas Haller --- libnm-util/nm-test-utils.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libnm-util/nm-test-utils.h b/libnm-util/nm-test-utils.h index a3de61ad64..44aa255078 100644 --- a/libnm-util/nm-test-utils.h +++ b/libnm-util/nm-test-utils.h @@ -54,7 +54,9 @@ nmtst_init (int *argc, char ***argv) g_test_init (argc, argv, NULL); } +#if !GLIB_CHECK_VERSION (2, 35, 0) g_type_init (); +#endif __nmtst_internal.rand0 = g_rand_new_with_seed (0); } From a268b825d76f775f8328e50b187054f0fc0dfeeb Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 22 Apr 2014 11:36:01 +0200 Subject: [PATCH 04/30] nmtst: move header file to include/ directory https://bugzilla.gnome.org/show_bug.cgi?id=706293 Signed-off-by: Thomas Haller --- include/Makefile.am | 1 + {libnm-util => include}/nm-test-utils.h | 0 libnm-util/Makefile.am | 3 +-- 3 files changed, 2 insertions(+), 2 deletions(-) rename {libnm-util => include}/nm-test-utils.h (100%) diff --git a/include/Makefile.am b/include/Makefile.am index 10e4f04c08..9dc989ec1c 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -5,6 +5,7 @@ EXTRA_DIST = \ nm-glib-compat.h \ nm-gvaluearray-compat.h \ nm-test-helpers.h \ + nm-test-utils.h \ nm-version.h.in \ nm-settings-flags.h diff --git a/libnm-util/nm-test-utils.h b/include/nm-test-utils.h similarity index 100% rename from libnm-util/nm-test-utils.h rename to include/nm-test-utils.h diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am index ccc9ed22bd..d1911cf34f 100644 --- a/libnm-util/Makefile.am +++ b/libnm-util/Makefile.am @@ -59,8 +59,7 @@ libnm_util_la_private_headers = \ nm-param-spec-specialized.h \ nm-util-private.h \ nm-utils-private.h \ - nm-setting-private.h \ - nm-test-utils.h + nm-setting-private.h libnm_util_la_csources = \ crypto.c \ From 237ee0588778e3bd91617a98217e3f02a7b91524 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 17 Apr 2014 14:55:57 +0200 Subject: [PATCH 05/30] nmtst: make all test functions "inline static" 'inline' is needed to avoid compiler warnings about unused functions. Marking them only as 'inline' was simply wrong and leads to linker errors when including the header in different translation units. By making them "inline static" we also don't need to foward declare the function prototype to avoid another compiler warning. Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 51 +++++++++-------------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 44aa255078..518ab23068 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -39,9 +39,7 @@ extern struct __nmtst_internal __nmtst_internal; #define NMTST_DEFINE() \ struct __nmtst_internal __nmtst_internal = { 0 }; -inline void nmtst_init (int *argc, char ***argv); - -inline void +inline static void nmtst_init (int *argc, char ***argv) { g_assert (!__nmtst_internal.rand0); @@ -61,18 +59,14 @@ nmtst_init (int *argc, char ***argv) __nmtst_internal.rand0 = g_rand_new_with_seed (0); } -inline GRand *nmtst_get_rand0 (void); - -inline GRand * +inline static GRand * nmtst_get_rand0 () { g_assert (__nmtst_internal.rand0); return __nmtst_internal.rand0; } -inline GRand *nmtst_get_rand (void); - -inline GRand * +inline static GRand * nmtst_get_rand () { if (G_UNLIKELY (!__nmtst_internal.rand)) { @@ -109,8 +103,7 @@ nmtst_get_rand () memcpy(&x, __nmtst_swap_temp, sizeof(x)); \ } G_STMT_END -inline guint32 nmtst_inet4_from_string (const char *str); -inline guint32 +inline static guint32 nmtst_inet4_from_string (const char *str) { guint32 addr; @@ -126,8 +119,7 @@ nmtst_inet4_from_string (const char *str) return addr; } -inline struct in6_addr *nmtst_inet6_from_string (const char *str); -inline struct in6_addr * +inline static struct in6_addr * nmtst_inet6_from_string (const char *str) { static struct in6_addr addr; @@ -145,9 +137,7 @@ nmtst_inet6_from_string (const char *str) #ifdef NM_PLATFORM_H -inline NMPlatformIP6Address *nmtst_platform_ip6_address (const char *address, const char *peer_address, guint plen); - -inline NMPlatformIP6Address * +inline static NMPlatformIP6Address * nmtst_platform_ip6_address (const char *address, const char *peer_address, guint plen) { static NMPlatformIP6Address addr; @@ -160,13 +150,7 @@ nmtst_platform_ip6_address (const char *address, const char *peer_address, guint return &addr; } - -inline NMPlatformIP6Address * -nmtst_platform_ip6_address_full (const char *address, const char *peer_address, guint plen, - int ifindex, NMPlatformSource source, guint32 timestamp, - guint32 lifetime, guint32 preferred, guint flags); - -inline NMPlatformIP6Address * +inline static NMPlatformIP6Address * nmtst_platform_ip6_address_full (const char *address, const char *peer_address, guint plen, int ifindex, NMPlatformSource source, guint32 timestamp, guint32 lifetime, guint32 preferred, guint flags) @@ -183,10 +167,7 @@ nmtst_platform_ip6_address_full (const char *address, const char *peer_address, return addr; } - -inline NMPlatformIP6Route * nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway); - -inline NMPlatformIP6Route * +inline static NMPlatformIP6Route * nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway) { static NMPlatformIP6Route route; @@ -199,13 +180,7 @@ nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway) return &route; } - -inline NMPlatformIP6Route * -nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gateway, - int ifindex, NMPlatformSource source, - guint metric, guint mss); - -inline NMPlatformIP6Route * +inline static NMPlatformIP6Route * nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gateway, int ifindex, NMPlatformSource source, guint metric, guint mss) @@ -225,9 +200,7 @@ nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gate #ifdef NM_IP4_CONFIG_H -inline NMIP4Config *nmtst_ip4_config_clone (NMIP4Config *config); - -inline NMIP4Config * +inline static NMIP4Config * nmtst_ip4_config_clone (NMIP4Config *config) { NMIP4Config *copy = nm_ip4_config_new (); @@ -243,9 +216,7 @@ nmtst_ip4_config_clone (NMIP4Config *config) #ifdef NM_IP6_CONFIG_H -inline NMIP6Config *nmtst_ip6_config_clone (NMIP6Config *config); - -inline NMIP6Config * +inline static NMIP6Config * nmtst_ip6_config_clone (NMIP6Config *config) { NMIP6Config *copy = nm_ip6_config_new (); From d29cd00d2b9ca016baebc46100a79e0f835dc324 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 5 Jun 2014 10:11:00 +0200 Subject: [PATCH 06/30] nmtst: return const address from nmtst_inet6_from_string() Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 518ab23068..0f3fa6c4c0 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -119,7 +119,7 @@ nmtst_inet4_from_string (const char *str) return addr; } -inline static struct in6_addr * +inline static const struct in6_addr * nmtst_inet6_from_string (const char *str) { static struct in6_addr addr; From 17c300b816592008ee9fb0633c3f24e766150b14 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 22 Apr 2014 13:00:34 +0200 Subject: [PATCH 07/30] nmtst: include missing header file glib-object.h Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 0f3fa6c4c0..8de9d15861 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -25,6 +25,7 @@ #include #include +#include struct __nmtst_internal From 86693d237810d9380974bb7ca59ec5a420029020 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 14 Apr 2014 12:03:05 +0200 Subject: [PATCH 08/30] nmtst: add parameter to nmtst_init to setup nm-logging Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 10 +++++++++- src/logging/nm-logging.h | 4 ++++ src/tests/test-ip6-config.c | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 8de9d15861..20e867f0b8 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -41,7 +41,7 @@ extern struct __nmtst_internal __nmtst_internal; struct __nmtst_internal __nmtst_internal = { 0 }; inline static void -nmtst_init (int *argc, char ***argv) +nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_domains) { g_assert (!__nmtst_internal.rand0); @@ -58,6 +58,14 @@ nmtst_init (int *argc, char ***argv) #endif __nmtst_internal.rand0 = g_rand_new_with_seed (0); + + if (log_level || log_domains) { + gboolean success = FALSE; +#ifdef NM_LOGGING_H + success = nm_logging_setup (log_level, log_domains, NULL, NULL); +#endif + g_assert (success); + } } inline static GRand * diff --git a/src/logging/nm-logging.h b/src/logging/nm-logging.h index c3984483e6..a53f93a55a 100644 --- a/src/logging/nm-logging.h +++ b/src/logging/nm-logging.h @@ -22,6 +22,10 @@ #ifndef NM_LOGGING_H #define NM_LOGGING_H +#ifdef __NM_TEST_UTILS_H__ +#error nm-test-utils.h must be included as last header +#endif + #include #include diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c index 21fa9b0c7a..8d376aa3ac 100644 --- a/src/tests/test-ip6-config.c +++ b/src/tests/test-ip6-config.c @@ -324,7 +324,7 @@ NMTST_DEFINE(); int main (int argc, char **argv) { - nmtst_init (&argc, &argv); + nmtst_init (&argc, &argv, NULL, NULL); g_test_add_func ("/ip6-config/subtract", test_subtract); g_test_add_func ("/ip6-config/compare-with-source", test_compare_with_source); From 64d09e5afe45f981e8e61d7a138b5c8183fda9c4 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 17 Apr 2014 10:47:48 +0200 Subject: [PATCH 09/30] nmtst: add nmtst_initialized() Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 20e867f0b8..c55a467193 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -40,10 +40,18 @@ extern struct __nmtst_internal __nmtst_internal; #define NMTST_DEFINE() \ struct __nmtst_internal __nmtst_internal = { 0 }; + +inline static gboolean +nmtst_initialized (void) +{ + return !!__nmtst_internal.rand0; +} + + inline static void nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_domains) { - g_assert (!__nmtst_internal.rand0); + g_assert (!nmtst_initialized ()); g_assert (!((!!argc) ^ (!!argv))); if (argc) { @@ -71,13 +79,15 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma inline static GRand * nmtst_get_rand0 () { - g_assert (__nmtst_internal.rand0); + g_assert (nmtst_initialized ()); return __nmtst_internal.rand0; } inline static GRand * nmtst_get_rand () { + g_assert (nmtst_initialized ()); + if (G_UNLIKELY (!__nmtst_internal.rand)) { guint32 seed; const char *str; From 5a58afcec979c90e811d20afe60e20b9d0ebcc39 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 17 Apr 2014 10:49:01 +0200 Subject: [PATCH 10/30] nmtst: add nmtst_is_debug() and interpret environment NMTST_DEBUG Also enable "DEBUG" logging conditionally depending on is_debug(). Signed-off-by: Thomas Haller --- include/nm-glib-compat.h | 5 ++ include/nm-test-utils.h | 130 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/include/nm-glib-compat.h b/include/nm-glib-compat.h index 9004e241c0..2141b91958 100644 --- a/include/nm-glib-compat.h +++ b/include/nm-glib-compat.h @@ -91,4 +91,9 @@ g_type_ensure (GType type) #endif +/* g_test_initialized() is only available since glib 2.36. */ +#if !GLIB_CHECK_VERSION (2, 36, 0) +#define g_test_initialized() (g_test_config_vars->test_initialized) +#endif + #endif /* NM_GLIB_COMPAT_H */ diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index c55a467193..467e61ac54 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -26,6 +26,7 @@ #include #include #include +#include struct __nmtst_internal @@ -33,6 +34,7 @@ struct __nmtst_internal GRand *rand0; guint32 rand_seed; GRand *rand; + gboolean is_debug; }; extern struct __nmtst_internal __nmtst_internal; @@ -47,14 +49,68 @@ nmtst_initialized (void) return !!__nmtst_internal.rand0; } +/* split the string inplace at specific delimiters, allowing escaping with '\\'. + * Returns a zero terminated array of pointers into @str. + * + * The caller must g_free() the returned argv array. + **/ +inline static char ** +nmtst_str_split (char *str, const char *delimiters) +{ + const char *d; + GArray *result = g_array_sized_new (TRUE, FALSE, sizeof (char *), 3); + + g_assert (str); + g_assert (delimiters && !strchr (delimiters, '\\')); + + while (*str) { + gsize i = 0, j = 0; + + while (TRUE) { + char c = str[i]; + + if (c == '\0') { + str[j++] = 0; + break; + } else if (c == '\\') { + str[j++] = str[++i]; + if (!str[i]) + break; + } else { + for (d = delimiters; *d; d++) { + if (c == *d) { + str[j++] = 0; + i++; + goto BREAK_INNER_LOOPS; + } + } + str[j++] = c; + } + i++; + } + +BREAK_INNER_LOOPS: + g_array_append_val (result, str); + str = &str[i]; + } + + return (char **) g_array_free (result, FALSE); +} + inline static void nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_domains) { + const char *nmtst_debug; + gboolean is_debug = FALSE; + char *c_log_level = NULL, *c_log_domains = NULL; + GArray *debug_messages = g_array_new (TRUE, FALSE, sizeof (char *)); + int i; + g_assert (!nmtst_initialized ()); g_assert (!((!!argc) ^ (!!argv))); - if (argc) { + if (argc && !g_test_initialized ()) { /* g_test_init() is a variadic function, so we cannot pass it * (variadic) arguments. If you need to pass additional parameters, * call nmtst_init() with argc==NULL and call g_test_init() yourself. */ @@ -65,8 +121,65 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma g_type_init (); #endif + is_debug = g_test_verbose (); + + nmtst_debug = g_getenv ("NMTST_DEBUG"); + if (nmtst_debug) { + char **d_argv, **i_argv, *nmtst_debug_copy; + + /* By setting then NMTST_DEBUG variable, @is_debug is set automatically. + * This can be reverted with no-debug (on command line or environment variable). */ + is_debug = TRUE; + + nmtst_debug_copy = g_strdup (nmtst_debug); + d_argv = nmtst_str_split (nmtst_debug_copy, ",; \t\r\n"); + + for (i_argv = d_argv; *i_argv; i_argv++) { + const char *debug = *i_argv; + + if (!g_ascii_strcasecmp (debug, "debug")) + is_debug = TRUE; + else if (!g_ascii_strcasecmp (debug, "no-debug")) { + /* when specifying the NMTST_DEBUG variable, we set is_debug to true. Use this flag to disable this + * (e.g. for only setting the log-level, but not is_debug). */ + is_debug = FALSE; + } else if (!g_ascii_strncasecmp (debug, "log-level=", strlen ("log-level="))) { + g_free (c_log_level); + log_level = c_log_level = g_strdup (&debug[strlen ("log-level=")]); + } else if (!g_ascii_strncasecmp (debug, "log-domains=", strlen ("log-domains="))) { + g_free (c_log_domains); + log_domains = c_log_domains = g_strdup (&debug[strlen ("log-domains=")]); + } else { + char *msg = g_strdup_printf (">>> nmtst: ignore unrecognized NMTST_DEBUG option \"%s\"", debug); + + g_array_append_val (debug_messages, msg); + } + } + + g_free (d_argv); + g_free (nmtst_debug_copy); + } + + if (argv && *argv) { + char **a = *argv; + + for (; *a; a++) { + if (!g_ascii_strcasecmp (*a, "--debug")) + is_debug = TRUE; + else if (!g_ascii_strcasecmp (*a, "--no-debug")) + is_debug = FALSE; + } + } + + __nmtst_internal.is_debug = is_debug; __nmtst_internal.rand0 = g_rand_new_with_seed (0); + if (!log_level && log_domains) { + /* if the log level is not specified (but the domain is), we assume + * the caller wants to set it depending on is_debug */ + log_level = is_debug ? "DEBUG" : "WARN"; + } + if (log_level || log_domains) { gboolean success = FALSE; #ifdef NM_LOGGING_H @@ -74,6 +187,21 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma #endif g_assert (success); } + + /* Delay messages until we setup logging. */ + for (i = 0; i < debug_messages->len; i++) + g_message ("%s", g_array_index (debug_messages, const char *, i)); + + g_strfreev ((char **) g_array_free (debug_messages, FALSE)); + g_free (c_log_level); + g_free (c_log_domains); +} + +inline static gboolean +nmtst_is_debug (void) +{ + g_assert (nmtst_initialized ()); + return __nmtst_internal.is_debug; } inline static GRand * From be56b26c7d96058db00249c461eb9e97033d62bc Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 17 Apr 2014 16:27:43 +0200 Subject: [PATCH 11/30] nmtst: add functions nmtst_static_SIZE_NUM() to create a copy of a string returned from an internal buffer Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 467e61ac54..abc75993fd 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -242,6 +242,26 @@ nmtst_get_rand () return __nmtst_internal.rand; } + +#define __define_nmtst_static(NUM,SIZE) \ +inline static const char * \ +nmtst_static_##SIZE##_##NUM (const char *str) \ +{ \ + gsize l; \ + static char buf[SIZE]; \ +\ + if (!str) \ + return NULL; \ + l = g_strlcpy (buf, str, sizeof (buf)); \ + g_assert (l < sizeof (buf)); \ + return buf; \ +} +__define_nmtst_static(01, 1024) +__define_nmtst_static(02, 1024) +__define_nmtst_static(03, 1024) +#undef __define_nmtst_static + + #define NMTST_SWAP(x,y) \ G_STMT_START { \ char __nmtst_swap_temp[sizeof(x) == sizeof(y) ? (signed) sizeof(x) : -1]; \ From 0e9cd4f6fc44c617377c3bc6298e74dd86aaec01 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 17 Apr 2014 14:56:32 +0200 Subject: [PATCH 12/30] nmtst: add functions nmtst_platform_ip[46]_routes_equal Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index abc75993fd..f42c70d183 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -362,6 +362,48 @@ nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gate return route; } +inline static void +nmtst_platform_ip4_routes_equal (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gsize len) +{ + gsize i; + + g_assert (a); + g_assert (b); + + for (i = 0; i < len; i++) { + if (nm_platform_ip4_route_cmp (&a[i], &b[i]) != 0) { + g_error ("Error comparing IPv4 route[%lu]: %s vs %s", (long unsigned) i, + nmtst_static_1024_01 (nm_platform_ip4_route_to_string (&a[i])), + nmtst_static_1024_02 (nm_platform_ip4_route_to_string (&b[i]))); + g_assert_not_reached (); + } + + /* also check with memcmp, though this might fail for valid programs (due to field alignment) */ + g_assert_cmpint (memcmp (&a[i], &b[i], sizeof (a[i])), ==, 0); + } +} + +inline static void +nmtst_platform_ip6_routes_equal (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gsize len) +{ + gsize i; + + g_assert (a); + g_assert (b); + + for (i = 0; i < len; i++) { + if (nm_platform_ip6_route_cmp (&a[i], &b[i]) != 0) { + g_error ("Error comparing IPv6 route[%lu]: %s vs %s", (long unsigned) i, + nmtst_static_1024_01 (nm_platform_ip6_route_to_string (&a[i])), + nmtst_static_1024_02 (nm_platform_ip6_route_to_string (&b[i]))); + g_assert_not_reached (); + } + + /* also check with memcmp, though this might fail for valid programs (due to field alignment) */ + g_assert_cmpint (memcmp (&a[i], &b[i], sizeof (a[i])), ==, 0); + } +} + #endif From 8af001eae44caa65b714233f1870119a3129558e Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 22 Apr 2014 16:55:28 +0200 Subject: [PATCH 13/30] nmtst: combine files nm-test-helpers.h and nm-test-utils.h Move the content of nm-test-helpers.h to nm-test-utils.h which completly replaces the older file. Signed-off-by: Thomas Haller --- include/Makefile.am | 1 - include/nm-test-helpers.h | 49 ------------------- include/nm-test-utils.h | 23 +++++++++ libnm-util/tests/test-crypto.c | 3 +- libnm-util/tests/test-general.c | 3 +- libnm-util/tests/test-secrets.c | 2 +- libnm-util/tests/test-setting-8021x.c | 3 +- libnm-util/tests/test-settings-defaults.c | 2 +- .../ifcfg-rh/tests/test-ifcfg-rh-utils.c | 3 +- .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 3 +- src/settings/plugins/ifnet/tests/test_all.c | 3 +- .../plugins/ifupdown/tests/test-ifupdown.c | 4 +- .../plugins/keyfile/tests/test-keyfile.c | 3 +- .../tests/test-supplicant-config.c | 3 +- src/tests/test-dhcp-options.c | 3 +- 15 files changed, 44 insertions(+), 64 deletions(-) delete mode 100644 include/nm-test-helpers.h diff --git a/include/Makefile.am b/include/Makefile.am index 9dc989ec1c..087afe48f6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -4,7 +4,6 @@ EXTRA_DIST = \ nm-dbus-glib-types.h \ nm-glib-compat.h \ nm-gvaluearray-compat.h \ - nm-test-helpers.h \ nm-test-utils.h \ nm-version.h.in \ nm-settings-flags.h diff --git a/include/nm-test-helpers.h b/include/nm-test-helpers.h deleted file mode 100644 index cae099a848..0000000000 --- a/include/nm-test-helpers.h +++ /dev/null @@ -1,49 +0,0 @@ -/* NetworkManager -- Network link manager - * - * Dan Williams - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 Red Hat, Inc. - */ - -#ifndef NM_TEST_HELPERS_H -#define NM_TEST_HELPERS_H - -#include -#include -#include - -static void -FAIL(const char *test_name, const char *fmt, ...) -{ - va_list args; - char buf[500]; - - g_snprintf (buf, 500, "FAIL: (%s) %s\n", test_name, fmt); - - va_start (args, fmt); - vfprintf (stderr, buf, args); - va_end (args); - _exit (1); -} - -#define ASSERT(x, test_name, fmt, ...) \ - if (!(x)) { \ - FAIL (test_name, fmt, ## __VA_ARGS__); \ - } - -#endif /* NM_TEST_HELPERS_H */ - diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index f42c70d183..3d807153a0 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -24,6 +24,8 @@ #include +#include +#include #include #include #include @@ -302,6 +304,27 @@ nmtst_inet6_from_string (const char *str) return &addr; } +inline static void +FAIL(const char *test_name, const char *fmt, ...) +{ + va_list args; + char buf[500]; + + g_snprintf (buf, 500, "FAIL: (%s) %s\n", test_name, fmt); + + va_start (args, fmt); + vfprintf (stderr, buf, args); + va_end (args); + _exit (1); +} + +#define ASSERT(x, test_name, fmt, ...) \ + if (!(x)) { \ + FAIL (test_name, fmt, ## __VA_ARGS__); \ + } + +/*******************************************************************************/ + #ifdef NM_PLATFORM_H inline static NMPlatformIP6Address * diff --git a/libnm-util/tests/test-crypto.c b/libnm-util/tests/test-crypto.c index 223f407d94..c11b6392f0 100644 --- a/libnm-util/tests/test-crypto.c +++ b/libnm-util/tests/test-crypto.c @@ -28,10 +28,11 @@ #include #include -#include "nm-test-helpers.h" #include "crypto.h" #include "nm-utils.h" +#include "nm-test-utils.h" + #if 0 static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; static const char *pem_rsa_key_end = "-----END RSA PRIVATE KEY-----"; diff --git a/libnm-util/tests/test-general.c b/libnm-util/tests/test-general.c index c65bd6cad1..5922f1fb87 100644 --- a/libnm-util/tests/test-general.c +++ b/libnm-util/tests/test-general.c @@ -25,7 +25,6 @@ #include #include -#include "nm-test-helpers.h" #include #include "nm-setting-private.h" @@ -46,6 +45,8 @@ #include "nm-dbus-glib-types.h" #include "nm-glib-compat.h" +#include "nm-test-utils.h" + static void vpn_check_func (const char *key, const char *value, gpointer user_data) { diff --git a/libnm-util/tests/test-secrets.c b/libnm-util/tests/test-secrets.c index 19c41943dc..73fc9224b0 100644 --- a/libnm-util/tests/test-secrets.c +++ b/libnm-util/tests/test-secrets.c @@ -22,7 +22,6 @@ #include #include -#include "nm-test-helpers.h" #include #include "nm-setting-connection.h" @@ -37,6 +36,7 @@ #include "nm-setting-pppoe.h" #include "nm-setting-vpn.h" +#include "nm-test-utils.h" #define TEST_NEED_SECRETS_EAP_TLS_CA_CERT TEST_CERT_DIR "/test_ca_cert.pem" #define TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT TEST_CERT_DIR "/test_key_and_cert.pem" diff --git a/libnm-util/tests/test-setting-8021x.c b/libnm-util/tests/test-setting-8021x.c index a536a2069b..62889c61fc 100644 --- a/libnm-util/tests/test-setting-8021x.c +++ b/libnm-util/tests/test-setting-8021x.c @@ -22,12 +22,13 @@ #include #include -#include "nm-test-helpers.h" #include #include "nm-setting-connection.h" #include "nm-setting-8021x.h" +#include "nm-test-utils.h" + static void compare_blob_data (const char *test, const char *key_path, diff --git a/libnm-util/tests/test-settings-defaults.c b/libnm-util/tests/test-settings-defaults.c index 93468bcce3..15412fed55 100644 --- a/libnm-util/tests/test-settings-defaults.c +++ b/libnm-util/tests/test-settings-defaults.c @@ -22,7 +22,6 @@ #include #include -#include "nm-test-helpers.h" #include #include "nm-setting-8021x.h" @@ -39,6 +38,7 @@ #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" +#include "nm-test-utils.h" static void test_defaults (GType type, const char *name) diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c index e32ad78901..cdb1f1f274 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c @@ -23,11 +23,10 @@ #include #include -#include "nm-test-helpers.h" - #include "common.h" #include "utils.h" +#include "nm-test-utils.h" static void test_get_ifcfg_name (const char *desc, diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index cb57e04227..98706725e5 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -48,7 +48,6 @@ #include #include -#include "nm-test-helpers.h" #include "NetworkManagerUtils.h" #include "nm-glib-compat.h" @@ -57,6 +56,8 @@ #include "writer.h" #include "utils.h" +#include "nm-test-utils.h" + #if 0 static void connection_diff (NMConnection *a, NMConnection *b) diff --git a/src/settings/plugins/ifnet/tests/test_all.c b/src/settings/plugins/ifnet/tests/test_all.c index e2b1576ad9..dc93dcccd6 100644 --- a/src/settings/plugins/ifnet/tests/test_all.c +++ b/src/settings/plugins/ifnet/tests/test_all.c @@ -28,7 +28,6 @@ #include #include -#include "nm-test-helpers.h" #include "nm-linux-platform.h" #include "nm-logging.h" @@ -38,6 +37,8 @@ #include "connection_parser.h" #include "nm-config.h" +#include "nm-test-utils.h" + /* Fake NMConfig handling; the values it returns don't matter, so this * is easier than forcing it to read our own config file, etc. */ diff --git a/src/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/settings/plugins/ifupdown/tests/test-ifupdown.c index 652e4af219..8386428703 100644 --- a/src/settings/plugins/ifupdown/tests/test-ifupdown.c +++ b/src/settings/plugins/ifupdown/tests/test-ifupdown.c @@ -23,12 +23,12 @@ #include -#include "nm-test-helpers.h" #include "nm-logging.h" - #include "interface_parser.h" #include "parser.h" +#include "nm-test-utils.h" + typedef struct { char *key; char *data; diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c index a300163b71..5084a45bda 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile.c @@ -41,12 +41,13 @@ #include #include -#include "nm-test-helpers.h" #include "nm-glib-compat.h" #include "reader.h" #include "writer.h" +#include "nm-test-utils.h" + #define TEST_WIRED_FILE TEST_KEYFILES_DIR"/Test_Wired_Connection" #define TEST_WIRELESS_FILE TEST_KEYFILES_DIR"/Test_Wireless_Connection" diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c index d1d0562f2c..9b1038b618 100644 --- a/src/supplicant-manager/tests/test-supplicant-config.c +++ b/src/supplicant-manager/tests/test-supplicant-config.c @@ -39,12 +39,13 @@ #include #include -#include "nm-test-helpers.h" #include "nm-glib-compat.h" #include "nm-supplicant-config.h" #include "nm-supplicant-settings-verify.h" +#include "nm-test-utils.h" + static gboolean validate_opt (const char *detail, GHashTable *hash, diff --git a/src/tests/test-dhcp-options.c b/src/tests/test-dhcp-options.c index c9748cf775..96e9b5c822 100644 --- a/src/tests/test-dhcp-options.c +++ b/src/tests/test-dhcp-options.c @@ -25,12 +25,13 @@ #include #include -#include "nm-test-helpers.h" #include #include "nm-dhcp-manager.h" #include "nm-logging.h" +#include "nm-test-utils.h" + typedef struct { const char *name; const char *value; From 9df3a23d26e1c2da04a0db9e048d01d358862145 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 23 Apr 2014 17:12:45 +0200 Subject: [PATCH 14/30] nmtst: add nmtst_free() Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 3d807153a0..c50f041851 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -100,9 +101,25 @@ BREAK_INNER_LOOPS: } +/* free instances allocated by nmtst (especially nmtst_init()) on shutdown + * to release memory. After nmtst_free(), the test is uninitialized again. */ +inline static void +nmtst_free (void) +{ + if (!nmtst_initialized ()) + return; + + g_rand_free (__nmtst_internal.rand0); + if (__nmtst_internal.rand) + g_rand_free (__nmtst_internal.rand); + + memset (&__nmtst_internal, 0, sizeof (__nmtst_internal)); +} + inline static void nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_domains) { + static gsize atexit_registered = 0; const char *nmtst_debug; gboolean is_debug = FALSE; char *c_log_level = NULL, *c_log_domains = NULL; @@ -197,6 +214,11 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma g_strfreev ((char **) g_array_free (debug_messages, FALSE)); g_free (c_log_level); g_free (c_log_domains); + + if (g_once_init_enter (&atexit_registered)) { + atexit (nmtst_free); + g_once_init_leave (&atexit_registered, 1); + } } inline static gboolean From 7a7dd9203d23311931fef9dd499249e29d256bcc Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 23 Apr 2014 16:54:54 +0200 Subject: [PATCH 15/30] nmtst: add nmtst_reexec_sudo() function Interpret environment variable NMTST_DEBUG which allows to specify 'sudo-cmd=CMD'. If the test program calls nmtst_reexec_sudo(), it will `exec CMD "$0" "$@"`. Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 49 ++++++++++++++++++++++++++++++++++++++ tools/test-sudo-wrapper.sh | 29 ++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100755 tools/test-sudo-wrapper.sh diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index c50f041851..8b7b39806a 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -30,6 +30,7 @@ #include #include #include +#include struct __nmtst_internal @@ -38,6 +39,8 @@ struct __nmtst_internal guint32 rand_seed; GRand *rand; gboolean is_debug; + char *sudo_cmd; + char **orig_argv; }; extern struct __nmtst_internal __nmtst_internal; @@ -112,6 +115,8 @@ nmtst_free (void) g_rand_free (__nmtst_internal.rand0); if (__nmtst_internal.rand) g_rand_free (__nmtst_internal.rand); + g_free (__nmtst_internal.sudo_cmd); + g_strfreev (__nmtst_internal.orig_argv); memset (&__nmtst_internal, 0, sizeof (__nmtst_internal)); } @@ -123,12 +128,18 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma const char *nmtst_debug; gboolean is_debug = FALSE; char *c_log_level = NULL, *c_log_domains = NULL; + char *sudo_cmd = NULL; GArray *debug_messages = g_array_new (TRUE, FALSE, sizeof (char *)); int i; g_assert (!nmtst_initialized ()); g_assert (!((!!argc) ^ (!!argv))); + g_assert (!argc || (g_strv_length (*argv) == *argc)); + + if (argc) + __nmtst_internal.orig_argv = g_strdupv (*argv); + if (argc && !g_test_initialized ()) { /* g_test_init() is a variadic function, so we cannot pass it * (variadic) arguments. If you need to pass additional parameters, @@ -168,6 +179,9 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma } else if (!g_ascii_strncasecmp (debug, "log-domains=", strlen ("log-domains="))) { g_free (c_log_domains); log_domains = c_log_domains = g_strdup (&debug[strlen ("log-domains=")]); + } else if (!g_ascii_strncasecmp (debug, "sudo-cmd=", strlen ("sudo-cmd="))) { + g_free (sudo_cmd); + sudo_cmd = g_strdup (&debug[strlen ("sudo-cmd=")]); } else { char *msg = g_strdup_printf (">>> nmtst: ignore unrecognized NMTST_DEBUG option \"%s\"", debug); @@ -192,6 +206,7 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma __nmtst_internal.is_debug = is_debug; __nmtst_internal.rand0 = g_rand_new_with_seed (0); + __nmtst_internal.sudo_cmd = sudo_cmd; if (!log_level && log_domains) { /* if the log level is not specified (but the domain is), we assume @@ -266,6 +281,40 @@ nmtst_get_rand () return __nmtst_internal.rand; } +inline static const char * +nmtst_get_sudo_cmd (void) +{ + g_assert (nmtst_initialized ()); + return __nmtst_internal.sudo_cmd; +} + +inline static void +nmtst_reexec_sudo (void) +{ + char *str; + char **argv; + int i; + int errsv; + + g_assert (nmtst_initialized ()); + g_assert (__nmtst_internal.orig_argv); + + if (!__nmtst_internal.sudo_cmd) + return; + + str = g_strjoinv (" ", __nmtst_internal.orig_argv); + g_message (">> exec %s %s", __nmtst_internal.sudo_cmd, str); + + argv = g_new0 (char *, 1 + g_strv_length (__nmtst_internal.orig_argv) + 1); + argv[0] = __nmtst_internal.sudo_cmd; + for (i = 0; __nmtst_internal.orig_argv[i]; i++) + argv[i+1] = __nmtst_internal.orig_argv[i]; + + execvp (__nmtst_internal.sudo_cmd, argv); + + errsv = errno; + g_error (">> exec %s failed: %d - %s", __nmtst_internal.sudo_cmd, errsv, strerror (errsv)); +} #define __define_nmtst_static(NUM,SIZE) \ inline static const char * \ diff --git a/tools/test-sudo-wrapper.sh b/tools/test-sudo-wrapper.sh new file mode 100755 index 0000000000..b375368e53 --- /dev/null +++ b/tools/test-sudo-wrapper.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +CMD="$1" +shift; + +# convert the libtool internal path +resolve_cmd() { + local C="$1" + + local C2="$(echo "$C" | sed 's#^\(.*/\)\.libs/lt-\([^/]\+\)$#\1\2#')" + if [[ "$C2" != "$C" && ! -x "$C2" ]]; then + # such a file does not exist... back to $C + C2="$C" + fi + echo "$C2" +} + +if [[ $UID == 0 ]]; then + # we are already root. Execute directly. + exec "$(resolve_cmd "$CMD")" "$@" +elif [[ "$NMTST_SUDO_NO_CALL_SELF" != "" ]]; then + # when setting $NMTST_SUDO_NO_CALL_SELF, pass the (resolved) command + # directly to sudo. + exec sudo "$(resolve_cmd "$CMD")" "$@" +else + # by default, call self again with sudo. + exec sudo -E "$0" "$CMD" "$@" +fi + From 5d3bef5d3ff3dc9054a6c88d40f46718365cf235 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 5 Jun 2014 11:31:00 +0200 Subject: [PATCH 16/30] nmtst: add nmtst_spawn_sync() Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 8b7b39806a..def20bb4a3 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -394,6 +394,57 @@ FAIL(const char *test_name, const char *fmt, ...) FAIL (test_name, fmt, ## __VA_ARGS__); \ } + +#define nmtst_spawn_sync(working_directory, standard_out, standard_err, assert_exit_status, ...) \ + __nmtst_spawn_sync (working_directory, standard_out, standard_err, assert_exit_status, ##__VA_ARGS__, NULL) +inline static gint +__nmtst_spawn_sync (const char *working_directory, char **standard_out, char **standard_err, int assert_exit_status, ...) G_GNUC_NULL_TERMINATED; +inline static gint +__nmtst_spawn_sync (const char *working_directory, char **standard_out, char **standard_err, int assert_exit_status, ...) +{ + gint exit_status = 0; + GError *error = NULL; + char *arg; + va_list va_args; + GPtrArray *argv = g_ptr_array_new (); + gboolean success; + + va_start (va_args, assert_exit_status); + while ((arg = va_arg (va_args, char *))) + g_ptr_array_add (argv, arg); + va_end (va_args); + + g_assert (argv->len >= 1); + g_ptr_array_add (argv, NULL); + + success = g_spawn_sync (working_directory, + (char**) argv->pdata, + NULL, + 0 /*G_SPAWN_DEFAULT*/, + NULL, + NULL, + standard_out, + standard_err, + &exit_status, + &error); + if (!success) + g_error ("nmtst_spawn_sync(%s): %s", ((char **) argv->pdata)[0], error->message); + g_assert (!error); + + g_assert (!standard_out || *standard_out); + g_assert (!standard_err || *standard_err); + + if (assert_exit_status != -1) { + /* exit status is a guint8 on success. Set @assert_exit_status to -1 + * not to check for the exit status. */ + g_assert (WIFEXITED (exit_status)); + g_assert_cmpint (WEXITSTATUS (exit_status), ==, assert_exit_status); + } + + g_ptr_array_free (argv, TRUE); + return exit_status; +} + /*******************************************************************************/ #ifdef NM_PLATFORM_H From 284ef00d16a754d4fa5ee7b650df08938eedaea2 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 24 Apr 2014 20:18:46 +0200 Subject: [PATCH 17/30] nmtst: call nm_utils_init() in nmtst_init() Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index def20bb4a3..a4b2491533 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -32,6 +32,8 @@ #include #include +#include "nm-utils.h" + struct __nmtst_internal { @@ -125,6 +127,7 @@ inline static void nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_domains) { static gsize atexit_registered = 0; + GError *error = NULL; const char *nmtst_debug; gboolean is_debug = FALSE; char *c_log_level = NULL, *c_log_domains = NULL; @@ -222,6 +225,10 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma g_assert (success); } + if (!nm_utils_init (&error)) + g_error ("failed to initialize libnm-util: %s", error->message); + g_assert (!error); + /* Delay messages until we setup logging. */ for (i = 0; i < debug_messages->len; i++) g_message ("%s", g_array_index (debug_messages, const char *, i)); From ed868a388b40333ce63e9c56720f283ea655d31d Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 22 Apr 2014 17:05:41 +0200 Subject: [PATCH 18/30] core: add compatibility wrapper for g_test_skip() to nm-glib-compat.h Signed-off-by: Thomas Haller --- include/nm-glib-compat.h | 14 ++++++++++++++ include/nm-test-utils.h | 1 + libnm-util/tests/test-general.c | 1 - .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 1 - src/settings/plugins/keyfile/tests/test-keyfile.c | 2 -- .../tests/test-supplicant-config.c | 2 -- 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/nm-glib-compat.h b/include/nm-glib-compat.h index 2141b91958..cfaddb7d31 100644 --- a/include/nm-glib-compat.h +++ b/include/nm-glib-compat.h @@ -96,4 +96,18 @@ g_type_ensure (GType type) #define g_test_initialized() (g_test_config_vars->test_initialized) #endif +/* g_test_skip() is only available since glib 2.38. Add a compatibility wrapper. */ +inline static void +__nmtst_g_test_skip (const gchar *msg) +{ +#if GLIB_CHECK_VERSION (2, 38, 0) + G_GNUC_BEGIN_IGNORE_DEPRECATIONS + g_test_skip (msg); + G_GNUC_END_IGNORE_DEPRECATIONS +#else + g_debug ("%s", msg); +#endif +} +#define g_test_skip __nmtst_g_test_skip + #endif /* NM_GLIB_COMPAT_H */ diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index a4b2491533..97937a90bc 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -33,6 +33,7 @@ #include #include "nm-utils.h" +#include "nm-glib-compat.h" struct __nmtst_internal diff --git a/libnm-util/tests/test-general.c b/libnm-util/tests/test-general.c index 5922f1fb87..bc63251754 100644 --- a/libnm-util/tests/test-general.c +++ b/libnm-util/tests/test-general.c @@ -43,7 +43,6 @@ #include "nm-utils.h" #include "nm-util-private.h" #include "nm-dbus-glib-types.h" -#include "nm-glib-compat.h" #include "nm-test-utils.h" diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 98706725e5..5d91b2add3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -49,7 +49,6 @@ #include #include "NetworkManagerUtils.h" -#include "nm-glib-compat.h" #include "common.h" #include "reader.h" diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c index 5084a45bda..335167ba6c 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile.c @@ -41,8 +41,6 @@ #include #include -#include "nm-glib-compat.h" - #include "reader.h" #include "writer.h" diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c index 9b1038b618..2b917625a6 100644 --- a/src/supplicant-manager/tests/test-supplicant-config.c +++ b/src/supplicant-manager/tests/test-supplicant-config.c @@ -39,8 +39,6 @@ #include #include -#include "nm-glib-compat.h" - #include "nm-supplicant-config.h" #include "nm-supplicant-settings-verify.h" From 66e2e932b5e028ab27a9a709425455e4fa42030a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 22 Apr 2014 16:02:15 +0200 Subject: [PATCH 19/30] platform: add nm_platform_link_get() Signed-off-by: Thomas Haller --- src/platform/nm-fake-platform.c | 11 +++++++++++ src/platform/nm-linux-platform.c | 17 +++++++++++++++++ src/platform/nm-platform.c | 21 +++++++++++++++++++++ src/platform/nm-platform.h | 2 ++ 4 files changed, 51 insertions(+) diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index dce98d8a9b..115011c3b1 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -184,6 +184,16 @@ link_added_emit (gpointer user_data) return FALSE; } +static gboolean +_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link) +{ + NMFakePlatformLink *device = link_get (platform, ifindex); + + if (device) + *link = device->link; + return !!device; +} + static gboolean link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *address, size_t address_len) { @@ -1288,6 +1298,7 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass) platform_class->sysctl_set = sysctl_set; platform_class->sysctl_get = sysctl_get; + platform_class->link_get = _nm_platform_link_get; platform_class->link_get_all = link_get_all; platform_class->link_add = link_add; platform_class->link_delete = link_delete; diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 54863425e3..0d9872b57c 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1877,6 +1877,22 @@ link_get_all (NMPlatform *platform) return links; } +static gboolean +_nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link) +{ + NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + auto_nl_object struct rtnl_link *rtnllink; + + rtnllink = rtnl_link_get (priv->link_cache, ifindex); + if (rtnllink) { + if (link_is_announceable (platform, rtnllink)) { + if (init_link (platform, link, rtnllink)) + return TRUE; + } + } + return FALSE; +} + static struct nl_object * build_rtnl_link (int ifindex, const char *name, NMLinkType type) { @@ -3804,6 +3820,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass) platform_class->sysctl_set = sysctl_set; platform_class->sysctl_get = sysctl_get; + platform_class->link_get = _nm_platform_link_get; platform_class->link_get_all = link_get_all; platform_class->link_add = link_add; platform_class->link_delete = link_delete; diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index daa023ffdd..02e2905d1b 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -439,6 +439,27 @@ nm_platform_link_get_all (void) return result; } +/** + * nm_platform_link_get: + * @ifindex: ifindex of the link + * @link: (out): output NMPlatformLink structure. + * + * If a link with given @ifindex exists, fill the given NMPlatformLink + * structure. + * + * Returns: %TRUE, if such a link exists, %FALSE otherwise. + * If the link does not exist, the content of @link is undefined. + **/ +gboolean +nm_platform_link_get (int ifindex, NMPlatformLink *link) +{ + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (link, FALSE); + + g_return_val_if_fail (klass->link_get, FALSE); + return !!klass->link_get (platform, ifindex, link); +} + /** * nm_platform_link_add: * @name: Interface name diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h index 2353e6aab5..9a2487125c 100644 --- a/src/platform/nm-platform.h +++ b/src/platform/nm-platform.h @@ -346,6 +346,7 @@ typedef struct { gboolean (*sysctl_set) (NMPlatform *, const char *path, const char *value); char * (*sysctl_get) (NMPlatform *, const char *path); + gboolean (*link_get) (NMPlatform *platform, int ifindex, NMPlatformLink *link); GArray *(*link_get_all) (NMPlatform *); gboolean (*link_add) (NMPlatform *, const char *name, NMLinkType type, const void *address, size_t address_len); gboolean (*link_delete) (NMPlatform *, int ifindex); @@ -477,6 +478,7 @@ char *nm_platform_sysctl_get (const char *path); gint32 nm_platform_sysctl_get_int32 (const char *path, gint32 fallback); gint64 nm_platform_sysctl_get_int_checked (const char *path, guint base, gint64 min, gint64 max, gint64 fallback); +gboolean nm_platform_link_get (int ifindex, NMPlatformLink *link); GArray *nm_platform_link_get_all (void); gboolean nm_platform_dummy_add (const char *name); gboolean nm_platform_bridge_add (const char *name, const void *address, size_t address_len); From 79a99613c289074d7dc6cef8e56884e52a699238 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 17 Apr 2014 10:32:03 +0200 Subject: [PATCH 20/30] platform/test: use nm-test-utils.h in test-common Signed-off-by: Thomas Haller --- src/platform/tests/test-common.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 911bec9d71..3a495bb7e5 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -1,5 +1,6 @@ #include "test-common.h" -#include "nm-glib-compat.h" + +#include "nm-test-utils.h" SignalData * add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname) @@ -130,24 +131,14 @@ run_command (const char *format, ...) g_free (command); } +NMTST_DEFINE(); + int main (int argc, char **argv) { int result; - openlog (G_LOG_DOMAIN, LOG_CONS | LOG_PERROR, LOG_DAEMON); - -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - g_test_init (&argc, &argv, NULL); - /* Enable debug messages if called with --debug */ - for (; *argv; argv++) { - if (!g_strcmp0 (*argv, "--debug")) { - nm_logging_setup ("debug", NULL, NULL, NULL); - } - } + nmtst_init (&argc, &argv, NULL, "ALL"); SETUP (); From accd10b501c55e1c62a6021b803375b05e0cd342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20=C5=A0imerda?= Date: Thu, 17 Apr 2014 17:40:21 +0200 Subject: [PATCH 21/30] platform/test: disable bonding tests if no bonding module is available Co-Authored-By: Thomas Haller Signed-off-by: Thomas Haller --- src/platform/tests/test-link.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 1767d3c874..c0a92062bf 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -1,4 +1,5 @@ #include "test-common.h" +#include "nm-test-utils.h" #define LO_INDEX 1 #define LO_NAME "lo" @@ -348,6 +349,13 @@ test_bridge (void) static void test_bond (void) { + if (SETUP == nm_linux_platform_setup && + !g_file_test ("/proc/1/net/bonding", G_FILE_TEST_IS_DIR) && + system("modprobe --show bonding") != 0) { + g_test_skip ("Skipping test for bonding: bonding module not available"); + return; + } + test_software (NM_LINK_TYPE_BOND, "bond"); } From f008c9fbea6e548916cf91eb1f50ba4146ed824f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20=C5=A0imerda?= Date: Thu, 17 Apr 2014 14:57:55 +0200 Subject: [PATCH 22/30] platform/test: fix fake platform to emit signals synchronously (analog to Linux platform) When adding a link, the Linux platform implementation raises the link-changed signal synchronously. Fix the fake platform to behave identically and also fix all the tests. This also fixes the Linux platform tests for the most part because now the test functions (and fake platform) behave like the Linux system implementation. https://bugzilla.gnome.org/show_bug.cgi?id=706293 Co-Authored-By: Thomas Haller Signed-off-by: Thomas Haller --- src/platform/nm-fake-platform.c | 42 ++----------------------------- src/platform/nm-linux-platform.c | 2 +- src/platform/nm-platform.c | 6 ++--- src/platform/tests/test-address.c | 2 +- src/platform/tests/test-cleanup.c | 2 +- src/platform/tests/test-common.c | 8 ++++++ src/platform/tests/test-link.c | 8 +++--- src/platform/tests/test-route.c | 2 +- 8 files changed, 21 insertions(+), 51 deletions(-) diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 115011c3b1..0a4c6b2555 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -36,8 +36,6 @@ typedef struct { GArray *ip6_addresses; GArray *ip4_routes; GArray *ip6_routes; - - GSList *link_added_ids; } NMFakePlatformPrivate; typedef struct { @@ -163,27 +161,6 @@ link_get_all (NMPlatform *platform) return links; } -typedef struct { - NMPlatform *platform; - int ifindex; - guint id; -} LinkAddedInfo; - -static gboolean -link_added_emit (gpointer user_data) -{ - LinkAddedInfo *info = user_data; - NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (info->platform); - NMFakePlatformLink *device; - - priv->link_added_ids = g_slist_remove (priv->link_added_ids, GUINT_TO_POINTER (info->id)); - - device = link_get (info->platform, info->ifindex); - g_assert (device); - g_signal_emit_by_name (info->platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, info->ifindex, &device->link, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL); - return FALSE; -} - static gboolean _nm_platform_link_get (NMPlatform *platform, int ifindex, NMPlatformLink *link) { @@ -199,23 +176,13 @@ link_add (NMPlatform *platform, const char *name, NMLinkType type, const void *a { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); NMFakePlatformLink device; - LinkAddedInfo *info; link_init (&device, priv->links->len, type, name); g_array_append_val (priv->links, device); - if (device.link.ifindex) { - /* Platform requires LINK_ADDED signal emission from an idle handler */ - info = g_new0 (LinkAddedInfo, 1); - info->platform = platform; - info->ifindex = device.link.ifindex; - info->id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - link_added_emit, - info, - g_free); - priv->link_added_ids = g_slist_prepend (priv->link_added_ids, GUINT_TO_POINTER (info->id)); - } + if (device.link.ifindex) + g_signal_emit_by_name (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, device.link.ifindex, &device, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_INTERNAL); return TRUE; } @@ -1260,11 +1227,6 @@ nm_fake_platform_finalize (GObject *object) { NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (object); int i; - GSList *iter; - - for (iter = priv->link_added_ids; iter; iter = iter->next) - g_source_remove (GPOINTER_TO_UINT (iter->data)); - g_slist_free (priv->link_added_ids); g_hash_table_unref (priv->options); for (i = 0; i < priv->links->len; i++) { diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 0d9872b57c..a9e5eae4b9 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -1636,7 +1636,7 @@ event_notification (struct nl_msg *msg, gpointer user_data) return NL_OK; nl_cache_remove (cached_object); - /* Don't announced removed interfaces that are not recognized by + /* Don't announce removed interfaces that are not recognized by * udev. They were either not yet discovered or they have been * already removed and announced. */ diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 02e2905d1b..42b31453c3 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -314,7 +314,7 @@ nm_platform_sysctl_get_int_checked (const char *path, guint base, gint64 min, gi /** * nm_platform_query_devices: * - * Emit #NMPlatform:link-added signals for all currently-known links. + * Emit #NMPlatform:link-changed ADDED signals for all currently-known links. * Should only be called at startup. */ void @@ -468,8 +468,8 @@ nm_platform_link_get (int ifindex, NMPlatformLink *link) * @address_len: the length of the @address * * Add a software interface. Sets platform->error to NM_PLATFORM_ERROR_EXISTS - * if interface is already already exists. Any link-added signal will be - * emitted from an idle handler and not within this function. + * if interface is already already exists. Any link-changed ADDED signal will be + * emitted directly, before this function finishes. */ static gboolean nm_platform_link_add (const char *name, NMLinkType type, const void *address, size_t address_len) diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c index ed50157ab5..3fef537528 100644 --- a/src/platform/tests/test-address.c +++ b/src/platform/tests/test-address.c @@ -252,7 +252,7 @@ setup_tests (void) nm_platform_link_delete (nm_platform_link_get_ifindex (DEVICE_NAME)); g_assert (!nm_platform_link_exists (DEVICE_NAME)); g_assert (nm_platform_dummy_add (DEVICE_NAME)); - wait_signal (link_added); + accept_signal (link_added); free_signal (link_added); g_test_add_func ("/address/internal/ip4", test_ip4_address); diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c index c35dafb21d..5d6036ca44 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/platform/tests/test-cleanup.c @@ -34,7 +34,7 @@ test_cleanup_internal () /* Create and set up device */ g_assert (nm_platform_dummy_add (DEVICE_NAME)); - wait_signal (link_added); + accept_signal (link_added); free_signal (link_added); g_assert (nm_platform_link_set_up (nm_platform_link_get_ifindex (DEVICE_NAME))); ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 3a495bb7e5..686536f857 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -48,6 +48,9 @@ accept_signal (SignalData *data) void wait_signal (SignalData *data) { + if (data->received) + g_error ("Signal '%s' received before waiting for it.", data->name); + data->loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (data->loop); g_clear_pointer (&data->loop, g_main_loop_unref); @@ -96,6 +99,11 @@ link_callback (NMPlatform *platform, int ifindex, NMPlatformLink *received, NMPl debug ("Received signal '%s-%s' ifindex %d ifname '%s'.", data->name, _change_type_to_string (data->change_type), ifindex, received->name); data->received = TRUE; + if (change_type == NM_PLATFORM_SIGNAL_REMOVED) + g_assert (!nm_platform_link_get_name (ifindex)); + else + g_assert (nm_platform_link_get_name (ifindex)); + /* Check the data */ g_assert (received->ifindex > 0); links = nm_platform_link_get_all (); diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index c0a92062bf..b7c14aad9b 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -113,7 +113,7 @@ software_add (NMLinkType link_type, const char *name) /* Don't call link_callback for the bridge interface */ parent_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, PARENT_NAME); if (nm_platform_bridge_add (PARENT_NAME, NULL, 0)) - wait_signal (parent_added); + accept_signal (parent_added); free_signal (parent_added); { @@ -145,7 +145,7 @@ test_slave (int master, int type, SignalData *master_changed) g_assert (ifindex > 0); link_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, link_callback, ifindex); link_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, ifindex); - wait_signal (link_added); + accept_signal (link_added); /* Set the slave up to see whether master's IFF_LOWER_UP is set correctly. * @@ -247,7 +247,7 @@ test_software (NMLinkType link_type, const char *link_typename) link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME); g_assert (software_add (link_type, DEVICE_NAME)); no_error (); - wait_signal (link_added); + accept_signal (link_added); g_assert (nm_platform_link_exists (DEVICE_NAME)); ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); g_assert (ifindex >= 0); @@ -389,7 +389,7 @@ test_internal (void) /* Add device */ g_assert (nm_platform_dummy_add (DEVICE_NAME)); no_error (); - wait_signal (link_added); + accept_signal (link_added); /* Try to add again */ g_assert (!nm_platform_dummy_add (DEVICE_NAME)); diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index a332474265..eea2c657dd 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -220,7 +220,7 @@ setup_tests (void) nm_platform_link_delete (nm_platform_link_get_ifindex (DEVICE_NAME)); g_assert (!nm_platform_link_exists (DEVICE_NAME)); g_assert (nm_platform_dummy_add (DEVICE_NAME)); - wait_signal (link_added); + accept_signal (link_added); free_signal (link_added); g_assert (nm_platform_link_set_up (nm_platform_link_get_ifindex (DEVICE_NAME))); From fd41c989d5934d1319fd386ec4a020e6485b6617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20=C5=A0imerda?= Date: Thu, 17 Apr 2014 14:57:55 +0200 Subject: [PATCH 23/30] platform: fix software device handling when announcing links The handling for announcing links was broken resulting in duplicate link-added signals from platform. Co-Authored-By: Thomas Haller Signed-off-by: Thomas Haller --- src/platform/nm-linux-platform.c | 54 ++++++++++++++++++-------------- src/platform/tests/test-link.c | 9 ++++++ 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index a9e5eae4b9..6aa8b650e2 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -3594,38 +3594,40 @@ udev_device_added (NMPlatform *platform, auto_nl_object struct rtnl_link *rtnllink = NULL; const char *ifname; int ifindex; - gboolean is_changed; + gboolean was_announceable = FALSE; ifname = g_udev_device_get_name (udev_device); if (!ifname) { - debug ("failed to get device's interface"); + debug ("udev-add: failed to get device's interface"); return; } if (g_udev_device_get_property (udev_device, "IFINDEX")) ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); else { - warning ("(%s): failed to get device's ifindex", ifname); + warning ("(%s): udev-add: failed to get device's ifindex", ifname); + return; + } + if (ifindex <= 0) { + warning ("(%s): udev-add: retrieved invalid IFINDEX=%d", ifname, ifindex); return; } if (!g_udev_device_get_sysfs_path (udev_device)) { - debug ("(%s): couldn't determine device path; ignoring...", ifname); + debug ("(%s): udev-add: couldn't determine device path; ignoring...", ifname); return; } - is_changed = g_hash_table_lookup_extended (priv->udev_devices, GINT_TO_POINTER (ifindex), NULL, NULL); + rtnllink = rtnl_link_get (priv->link_cache, ifindex); + if (rtnllink) + was_announceable = link_is_announceable (platform, rtnllink); + g_hash_table_insert (priv->udev_devices, GINT_TO_POINTER (ifindex), g_object_ref (udev_device)); - /* Don't announce devices that have not yet been discovered via Netlink. */ - rtnllink = rtnl_link_get (priv->link_cache, ifindex); - if (!rtnllink) { - debug ("%s: not found in link cache, ignoring...", ifname); - return; - } - - announce_object (platform, (struct nl_object *) rtnllink, is_changed ? NM_PLATFORM_SIGNAL_CHANGED : NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_EXTERNAL); + /* Announce devices only if they also have been discovered via Netlink. */ + if (rtnllink && link_is_announceable (platform, rtnllink)) + announce_object (platform, (struct nl_object *) rtnllink, was_announceable ? NM_PLATFORM_SIGNAL_CHANGED : NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_REASON_EXTERNAL); } static void @@ -3633,12 +3635,13 @@ udev_device_removed (NMPlatform *platform, GUdevDevice *udev_device) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); + auto_nl_object struct rtnl_link *rtnllink = NULL; int ifindex = 0; + gboolean was_announceable = FALSE; - if (g_udev_device_get_property (udev_device, "IFINDEX")) { + if (g_udev_device_get_property (udev_device, "IFINDEX")) ifindex = g_udev_device_get_property_as_int (udev_device, "IFINDEX"); - g_hash_table_remove (priv->udev_devices, GINT_TO_POINTER (ifindex)); - } else { + else { GHashTableIter iter; gpointer key, value; @@ -3650,19 +3653,24 @@ udev_device_removed (NMPlatform *platform, while (g_hash_table_iter_next (&iter, &key, &value)) { if ((GUdevDevice *)value == udev_device) { ifindex = GPOINTER_TO_INT (key); - g_hash_table_iter_remove (&iter); break; } } } - /* Announce device removal if it's still in the Netlink cache. */ - if (ifindex) { - auto_nl_object struct rtnl_link *device = rtnl_link_get (priv->link_cache, ifindex); + debug ("udev-remove: IFINDEX=%d", ifindex); + if (ifindex <= 0) + return; - if (device) - announce_object (platform, (struct nl_object *) device, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_EXTERNAL); - } + rtnllink = rtnl_link_get (priv->link_cache, ifindex); + if (rtnllink) + was_announceable = link_is_announceable (platform, rtnllink); + + g_hash_table_remove (priv->udev_devices, GINT_TO_POINTER (ifindex)); + + /* Announce device removal if it is no longer announceable. */ + if (was_announceable && !link_is_announceable (platform, rtnllink)) + announce_object (platform, (struct nl_object *) rtnllink, NM_PLATFORM_SIGNAL_REMOVED, NM_PLATFORM_REASON_EXTERNAL); } static void diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index b7c14aad9b..73c260c4ca 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -461,9 +461,11 @@ test_internal (void) static void test_external (void) { + NMPlatformLink link; SignalData *link_added = add_signal_ifname (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_ADDED, link_callback, DEVICE_NAME); SignalData *link_changed, *link_removed; int ifindex; + gboolean success; run_command ("ip link add %s type %s", DEVICE_NAME, "dummy"); wait_signal (link_added); @@ -476,6 +478,13 @@ test_external (void) link_changed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_CHANGED, link_callback, ifindex); link_removed = add_signal_ifindex (NM_PLATFORM_SIGNAL_LINK_CHANGED, NM_PLATFORM_SIGNAL_REMOVED, link_callback, ifindex); + success = nm_platform_link_get (ifindex, &link); + g_assert (success); + if (!link.driver) { + /* we still lack the notification via UDEV. Expect another link changed signal. */ + wait_signal (link_changed); + } + /* Up/connected/arp */ g_assert (!nm_platform_link_is_up (ifindex)); g_assert (!nm_platform_link_is_connected (ifindex)); From 1ff6e1b65e10c0eb68ee70ffbd215498f27a56b0 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 17 Apr 2014 17:39:42 +0200 Subject: [PATCH 24/30] platform/test: fix expecting NM_PLATFORM_SOURCE_KERNEL in platform tests In this case, the fake platform implementation was wrong in that it did not set the source property of the route/address objects like linux platform does. Fix the test and the fake platform. https://bugzilla.gnome.org/show_bug.cgi?id=706293 Signed-off-by: Thomas Haller --- src/platform/nm-fake-platform.c | 4 ++++ src/platform/tests/test-route.c | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c index 0a4c6b2555..4f8f5b28aa 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/platform/nm-fake-platform.c @@ -827,6 +827,7 @@ ip4_address_add (NMPlatform *platform, int ifindex, int i; memset (&address, 0, sizeof (address)); + address.source = NM_PLATFORM_SOURCE_KERNEL; address.ifindex = ifindex; address.address = addr; address.peer_address = peer_addr; @@ -868,6 +869,7 @@ ip6_address_add (NMPlatform *platform, int ifindex, int i; memset (&address, 0, sizeof (address)); + address.source = NM_PLATFORM_SOURCE_KERNEL; address.ifindex = ifindex; address.address = addr; address.peer_address = peer_addr; @@ -1045,6 +1047,7 @@ ip4_route_add (NMPlatform *platform, int ifindex, in_addr_t network, int plen, guint i; memset (&route, 0, sizeof (route)); + route.source = NM_PLATFORM_SOURCE_KERNEL; route.ifindex = ifindex; route.network = network; route.plen = plen; @@ -1082,6 +1085,7 @@ ip6_route_add (NMPlatform *platform, int ifindex, struct in6_addr network, int p guint i; memset (&route, 0, sizeof (route)); + route.source = NM_PLATFORM_SOURCE_KERNEL; route.ifindex = ifindex; route.network = network; route.plen = plen; diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c index eea2c657dd..d07749d494 100644 --- a/src/platform/tests/test-route.c +++ b/src/platform/tests/test-route.c @@ -1,4 +1,5 @@ #include "test-common.h" +#include "nm-test-utils.h" #define DEVICE_NAME "nm-test-device" @@ -93,18 +94,21 @@ test_ip4_route () /* Test route listing */ routes = nm_platform_ip4_route_get_all (ifindex, TRUE); memset (rts, 0, sizeof (rts)); + rts[0].source = NM_PLATFORM_SOURCE_KERNEL; rts[0].network = gateway; rts[0].plen = 32; rts[0].ifindex = ifindex; rts[0].gateway = INADDR_ANY; rts[0].metric = metric; rts[0].mss = mss; + rts[1].source = NM_PLATFORM_SOURCE_KERNEL; rts[1].network = network; rts[1].plen = plen; rts[1].ifindex = ifindex; rts[1].gateway = gateway; rts[1].metric = metric; rts[1].mss = mss; + rts[2].source = NM_PLATFORM_SOURCE_KERNEL; rts[2].network = 0; rts[2].plen = 0; rts[2].ifindex = ifindex; @@ -113,6 +117,7 @@ test_ip4_route () rts[2].mss = mss; g_assert_cmpint (routes->len, ==, 3); g_assert (!memcmp (routes->data, rts, sizeof (rts))); + nmtst_platform_ip4_routes_equal ((NMPlatformIP4Route *) routes->data, rts, routes->len); g_array_unref (routes); /* Remove route */ @@ -176,18 +181,21 @@ test_ip6_route () /* Test route listing */ routes = nm_platform_ip6_route_get_all (ifindex, TRUE); memset (rts, 0, sizeof (rts)); + rts[0].source = NM_PLATFORM_SOURCE_KERNEL; rts[0].network = gateway; rts[0].plen = 128; rts[0].ifindex = ifindex; rts[0].gateway = in6addr_any; rts[0].metric = metric; rts[0].mss = mss; + rts[1].source = NM_PLATFORM_SOURCE_KERNEL; rts[1].network = network; rts[1].plen = plen; rts[1].ifindex = ifindex; rts[1].gateway = gateway; rts[1].metric = metric; rts[1].mss = mss; + rts[2].source = NM_PLATFORM_SOURCE_KERNEL; rts[2].network = in6addr_any; rts[2].plen = 0; rts[2].ifindex = ifindex; @@ -196,6 +204,7 @@ test_ip6_route () rts[2].mss = mss; g_assert_cmpint (routes->len, ==, 3); g_assert (!memcmp (routes->data, rts, sizeof (rts))); + nmtst_platform_ip6_routes_equal ((NMPlatformIP6Route *) routes->data, rts, routes->len); g_array_unref (routes); /* Remove route */ From 0fde65a14eaa1dad72838f5e23fa45dbf90506aa Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 5 Jun 2014 11:59:50 +0200 Subject: [PATCH 25/30] platform/test: workaround team bug in older kernel version In older versions of team (e.g. Fedora 17), the master team device stays up, even if no slaves are IFF_LOWER_UP. Workaround this bug. Signed-off-by: Thomas Haller --- src/platform/tests/test-link.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c index 73c260c4ca..a3f757c2e7 100644 --- a/src/platform/tests/test-link.c +++ b/src/platform/tests/test-link.c @@ -183,7 +183,20 @@ test_slave (int master, int type, SignalData *master_changed) } g_assert (!nm_platform_link_is_up (ifindex)); g_assert (!nm_platform_link_is_connected (ifindex)); - g_assert (!nm_platform_link_is_connected (master)); + if (nm_platform_link_is_connected (master)) { + if (nm_platform_link_get_type (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 + * `ip link` also claims master to be up, accept it. */ + char *stdout = NULL; + + nmtst_spawn_sync (NULL, &stdout, NULL, 0, "/sbin/ip", "link", "show", "dev", nm_platform_link_get_name (master)); + + g_assert (strstr (stdout, "LOWER_UP")); + g_free (stdout); + } else + g_assert_not_reached (); + } /* Set slave up and see if master gets up too */ g_assert (nm_platform_link_set_up (ifindex)); no_error (); From e3784fa618dff2816a0a793b257d908ef2e99daa Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 22 Apr 2014 14:22:11 +0200 Subject: [PATCH 26/30] platform/test: always run linux platform tests (will be skipped as non-root) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always run the linux platform tests, even if called as non-root user. In such a case, print a message and return 77 (signalizing that the test was skipped). Only if we configured with --enable-test=root, we enforce that the user executes the tests as root. Co-Authored-By: Pavel Šimerda Signed-off-by: Thomas Haller --- configure.ac | 2 +- src/platform/tests/Makefile.am | 21 ++++++--------------- src/platform/tests/test-common.c | 11 +++++++++++ 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 066c9d54f8..1cbe601da9 100644 --- a/configure.ac +++ b/configure.ac @@ -756,7 +756,7 @@ AS_IF([test "$with_valgrind" == "yes"], [AC_PATH_PROGS(with_valgrind, valgrind, no)]) # Add conditionals and substitutions AM_CONDITIONAL(ENABLE_TESTS, test "$enable_tests" != "no") -AM_CONDITIONAL(RUN_ROOT_TESTS, test "$enable_tests" == "root") +AM_CONDITIONAL(REQUIRE_ROOT_TESTS, test "$enable_tests" == "root") AS_IF([test "$with_valgrind" != "no"], AC_SUBST(VALGRIND_RULES, 'TESTS_ENVIRONMENT = "$(top_srcdir)/tools/run-test-valgrind.sh" "$(LIBTOOL)" "$(with_valgrind)" "$(top_srcdir)/valgrind.suppressions"'), AC_SUBST(VALGRIND_RULES, [])) diff --git a/src/platform/tests/Makefile.am b/src/platform/tests/Makefile.am index 9bdb4452bc..9b10ea7b2a 100644 --- a/src/platform/tests/Makefile.am +++ b/src/platform/tests/Makefile.am @@ -14,6 +14,10 @@ AM_CPPFLAGS = \ $(GUDEV_CFLAGS) \ $(LIBNL_CFLAGS) +if REQUIRE_ROOT_TESTS +AM_CPPFLAGS += -DREQUIRE_ROOT_TESTS=1 +endif + PLATFORM_SOURCES = \ ../nm-platform.c \ ../nm-fake-platform.c \ @@ -106,20 +110,7 @@ test_cleanup_linux_CPPFLAGS = \ -DKERNEL_HACKS=1 test_cleanup_linux_LDADD = $(PLATFORM_LDADD) -# Unfortunately, we cannot run nm-linux-platform-test as an automatic test -# program by default, as it requires root access and modifies kernel -# configuration. -# -# However, we can check whether the fake platform fakes platform behavior -# correctly. +#@VALGRIND_RULES@ +TESTS = test-link-fake test-address-fake test-route-fake test-cleanup-fake test-link-linux test-address-linux test-route-linux test-cleanup-linux -@VALGRIND_RULES@ -USERTESTS = test-link-fake test-address-fake test-route-fake test-cleanup-fake -ROOTTESTS = test-link-linux test-address-linux test-route-linux test-cleanup-linux -# If explicitly enabled, we can run the root tests -if RUN_ROOT_TESTS -TESTS = $(USERTESTS) $(ROOTTESTS) -else -TESTS = $(USERTESTS) -endif diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 686536f857..1c8550593b 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -145,9 +145,20 @@ int main (int argc, char **argv) { int result; + const char *program = *argv; nmtst_init (&argc, &argv, NULL, "ALL"); + if (SETUP == nm_linux_platform_setup && getuid() != 0) { +#ifdef REQUIRE_ROOT_TESTS + g_message ("Fail test: requires root privileges (%s)", program); + return EXIT_FAILURE; +#else + g_message ("Skipping test: requires root privileges (%s)", program); + return 77; +#endif + } + SETUP (); setup_tests (); From ae863a69545fcfd995cdda661d216149efddd284 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Wed, 23 Apr 2014 16:54:54 +0200 Subject: [PATCH 27/30] platform/test: allow running root tests as sudo Call to nmtst_reexec_sudo(), which allows you to specify a program via environment variable to exec the test. This is useful to exec the test program with sudo. NMTST_DEBUG="no-debug,sudo-cmd=$PWD/tools/test-sudo-wrapper.sh" make -C src/platform/tests/ check Signed-off-by: Thomas Haller --- src/platform/tests/test-common.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 1c8550593b..8ca77f21db 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -150,6 +150,9 @@ main (int argc, char **argv) nmtst_init (&argc, &argv, NULL, "ALL"); if (SETUP == nm_linux_platform_setup && getuid() != 0) { + /* Try to exec as sudo, this function does not return, if a sudo-cmd is set. */ + nmtst_reexec_sudo (); + #ifdef REQUIRE_ROOT_TESTS g_message ("Fail test: requires root privileges (%s)", program); return EXIT_FAILURE; From 8ce1eb3837df095cdd33d5595fb5ee8553e45a97 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 24 Apr 2014 21:01:58 +0200 Subject: [PATCH 28/30] nmtst: add new mode where tests assert against logged messages (assert_messages) In this mode, nmtst itself will not log anything and not set the logging level. Also, it will set g_log_set_always_fatal(). This is for tests that want to assert against all logged messages via g_test_expect_message(). In this mode also setting the logging level via NMTST_DEBUG variable has no effect. The test is expected to manage the logging level itself and changing the logging level might interfere with the test. As a showcase, move keyfile/tests/test-keyfile.c to nmtst. Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 54 ++++++++++++++++--- src/platform/tests/test-common.c | 2 +- .../plugins/keyfile/tests/test-keyfile.c | 13 ++--- src/tests/test-ip6-config.c | 3 +- 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 97937a90bc..292b903c7f 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -42,6 +42,7 @@ struct __nmtst_internal guint32 rand_seed; GRand *rand; gboolean is_debug; + gboolean assert_logging; char *sudo_cmd; char **orig_argv; }; @@ -58,6 +59,16 @@ nmtst_initialized (void) return !!__nmtst_internal.rand0; } +#define __NMTST_LOG(cmd, fmt, ...) \ + G_STMT_START { \ + g_assert (nmtst_initialized ()); \ + if (!__nmtst_internal.assert_logging) { \ + cmd (fmt, __VA_ARGS__); \ + } else { \ + printf (fmt "\n", __VA_ARGS__); \ + } \ + } G_STMT_END + /* split the string inplace at specific delimiters, allowing escaping with '\\'. * Returns a zero terminated array of pointers into @str. * @@ -125,7 +136,7 @@ nmtst_free (void) } inline static void -nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_domains) +__nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_level, const char *log_domains) { static gsize atexit_registered = 0; GError *error = NULL; @@ -140,6 +151,7 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma g_assert (!((!!argc) ^ (!!argv))); g_assert (!argc || (g_strv_length (*argv) == *argc)); + g_assert (!assert_logging || (!log_level && !log_domains)); if (argc) __nmtst_internal.orig_argv = g_strdupv (*argv); @@ -151,6 +163,8 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma g_test_init (argc, argv, NULL); } + __nmtst_internal.assert_logging = !!assert_logging; + #if !GLIB_CHECK_VERSION (2, 35, 0) g_type_init (); #endif @@ -218,12 +232,21 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma log_level = is_debug ? "DEBUG" : "WARN"; } - if (log_level || log_domains) { - gboolean success = FALSE; + if (!__nmtst_internal.assert_logging) { + gboolean success = TRUE; #ifdef NM_LOGGING_H success = nm_logging_setup (log_level, log_domains, NULL, NULL); #endif g_assert (success); + } else { +#if GLIB_CHECK_VERSION(2,34,0) + /* We were called not to set logging levels. This means, that the user + * expects to assert against (all) messages. Any uncought message is fatal. */ + g_log_set_always_fatal (G_LOG_LEVEL_MASK); +#else + /* g_test_expect_message() is a NOP, so allow any messages */ + g_log_set_always_fatal (G_LOG_FATAL_MASK); +#endif } if (!nm_utils_init (&error)) @@ -232,7 +255,7 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma /* Delay messages until we setup logging. */ for (i = 0; i < debug_messages->len; i++) - g_message ("%s", g_array_index (debug_messages, const char *, i)); + __NMTST_LOG (g_message, "%s", g_array_index (debug_messages, const char *, i)); g_strfreev ((char **) g_array_free (debug_messages, FALSE)); g_free (c_log_level); @@ -244,6 +267,25 @@ nmtst_init (int *argc, char ***argv, const char *log_level, const char *log_doma } } +#ifdef NM_LOGGING_H +inline static void +nmtst_init_with_logging (int *argc, char ***argv, const char *log_level, const char *log_domains) +{ + __nmtst_init (argc, argv, FALSE, log_level, log_domains); +} +inline static void +nmtst_init_assert_logging (int *argc, char ***argv) +{ + __nmtst_init (argc, argv, TRUE, NULL, NULL); +} +#else +inline static void +nmtst_init (int *argc, char ***argv, gboolean assert_logging) +{ + __nmtst_init (argc, argv, assert_logging, NULL, NULL); +} +#endif + inline static gboolean nmtst_is_debug (void) { @@ -284,7 +326,7 @@ nmtst_get_rand () } __nmtst_internal.rand_seed = seed; - g_message (">> initialize nmtst_get_rand() with seed=%u", seed); + __NMTST_LOG (g_message, ">> initialize nmtst_get_rand() with seed=%u", seed); } return __nmtst_internal.rand; } @@ -311,7 +353,7 @@ nmtst_reexec_sudo (void) return; str = g_strjoinv (" ", __nmtst_internal.orig_argv); - g_message (">> exec %s %s", __nmtst_internal.sudo_cmd, str); + __NMTST_LOG (g_message, ">> exec %s %s", __nmtst_internal.sudo_cmd, str); argv = g_new0 (char *, 1 + g_strv_length (__nmtst_internal.orig_argv) + 1); argv[0] = __nmtst_internal.sudo_cmd; diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c index 8ca77f21db..4c777cce34 100644 --- a/src/platform/tests/test-common.c +++ b/src/platform/tests/test-common.c @@ -147,7 +147,7 @@ main (int argc, char **argv) int result; const char *program = *argv; - nmtst_init (&argc, &argv, NULL, "ALL"); + nmtst_init_with_logging (&argc, &argv, NULL, "ALL"); if (SETUP == nm_linux_platform_setup && getuid() != 0) { /* Try to exec as sudo, this function does not return, if a sudo-cmd is set. */ diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c index 335167ba6c..cc57c1c393 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "reader.h" #include "writer.h" @@ -3409,19 +3410,13 @@ test_read_missing_vlan_setting (void) g_object_unref (connection); } +NMTST_DEFINE (); + int main (int argc, char **argv) { - GError *error = NULL; char *base; -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - g_log_set_always_fatal (G_LOG_LEVEL_MASK); - - if (!nm_utils_init (&error)) - FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + nmtst_init_assert_logging (&argc, &argv); /* The tests */ test_read_valid_wired_connection (); diff --git a/src/tests/test-ip6-config.c b/src/tests/test-ip6-config.c index 8d376aa3ac..75fe28eef6 100644 --- a/src/tests/test-ip6-config.c +++ b/src/tests/test-ip6-config.c @@ -24,6 +24,7 @@ #include "nm-ip6-config.h" +#include "nm-logging.h" #include "nm-test-utils.h" static NMIP6Config * @@ -324,7 +325,7 @@ NMTST_DEFINE(); int main (int argc, char **argv) { - nmtst_init (&argc, &argv, NULL, NULL); + nmtst_init_with_logging (&argc, &argv, NULL, "ALL"); g_test_add_func ("/ip6-config/subtract", test_subtract); g_test_add_func ("/ip6-config/compare-with-source", test_compare_with_source); From 9114794f65ef1f1ba4127f94cdd3c47238b15c91 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 25 Apr 2014 14:17:07 +0200 Subject: [PATCH 29/30] nmtst: turn on g_debug() messages in nmtst_init() when debug logging is enabled In tests nm-logging will directly write using g_log. Also, non-core components use g_log() for logging. glib will not print messages with level G_LOG_LEVEL_INFO or G_LOG_LEVEL_DEBUG unless G_MESSAGES_DEBUG is set. When the user specifies NMTST_DEBUG turning on 'debug' or 'log-level=DEBUG' it can be reasonably assumed that he wants to see debug messages. nmtst_init() now sets G_MESSAGES_DEBUG=all. The user can disable this behaviour, by setting instead G_MESSAGES_DEBUG='', because nmtst_init() will not reset an existing G_MESSAGES_DEBUG. Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index 292b903c7f..ca1508b108 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -249,6 +249,19 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ #endif } + if (!__nmtst_internal.assert_logging && + (is_debug || (log_level && !g_ascii_strcasecmp (log_level, "DEBUG"))) && + !g_getenv ("G_MESSAGES_DEBUG")) + { + /* if we are @is_debug or @log_level=="DEBUG" and + * G_MESSAGES_DEBUG is unset, we set G_MESSAGES_DEBUG=all. + * To disable this default behaviour, set G_MESSAGES_DEBUG='' */ + + /* Note that g_setenv is not thread safe, but you should anyway call + * nmtst_init() at the very start. */ + g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); + } + if (!nm_utils_init (&error)) g_error ("failed to initialize libnm-util: %s", error->message); g_assert (!error); From 48b5ba7cea3716faa493116d4c54c1e266917c4a Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 25 Apr 2014 15:34:49 +0200 Subject: [PATCH 30/30] nmtst: add NMTST_DEBUG=no-expect-message for debugging assert_message tests Some tests want to assert against the messages logged using g_test_expect_message(). In this mode, nmtst will not log anything itself. Interpret the option no-expect-message which turns g_test_expect_message() into a NOP and turns logging on. The use of this is for debugging such tests, without asserting against the messages but printing them instead. For tests that are not in the assert_message mode, the option has no effect. Example: NMTST_DEBUG=debug,no-expect-message make -C src/settings/plugins/keyfile/tests/ check Signed-off-by: Thomas Haller --- include/nm-test-utils.h | 33 +++++++++++++++++-- libnm-util/tests/test-general.c | 10 ++---- .../ifcfg-rh/tests/test-ifcfg-rh-utils.c | 4 +++ .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 23 +++---------- src/settings/plugins/ifnet/tests/test_all.c | 8 ++--- .../tests/test-supplicant-config.c | 10 ++---- src/tests/test-dhcp-options.c | 15 ++------- 7 files changed, 52 insertions(+), 51 deletions(-) diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h index ca1508b108..83c4080fe0 100644 --- a/include/nm-test-utils.h +++ b/include/nm-test-utils.h @@ -43,6 +43,7 @@ struct __nmtst_internal GRand *rand; gboolean is_debug; gboolean assert_logging; + gboolean no_expect_message; char *sudo_cmd; char **orig_argv; }; @@ -62,7 +63,7 @@ nmtst_initialized (void) #define __NMTST_LOG(cmd, fmt, ...) \ G_STMT_START { \ g_assert (nmtst_initialized ()); \ - if (!__nmtst_internal.assert_logging) { \ + if (!__nmtst_internal.assert_logging || __nmtst_internal.no_expect_message) { \ cmd (fmt, __VA_ARGS__); \ } else { \ printf (fmt "\n", __VA_ARGS__); \ @@ -146,6 +147,7 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ char *sudo_cmd = NULL; GArray *debug_messages = g_array_new (TRUE, FALSE, sizeof (char *)); int i; + gboolean no_expect_message = FALSE; g_assert (!nmtst_initialized ()); @@ -160,6 +162,10 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ /* g_test_init() is a variadic function, so we cannot pass it * (variadic) arguments. If you need to pass additional parameters, * call nmtst_init() with argc==NULL and call g_test_init() yourself. */ + + /* g_test_init() sets g_log_set_always_fatal() for G_LOG_LEVEL_WARNING + * and G_LOG_LEVEL_CRITICAL. So, beware that the test will fail if you + * have any WARN or ERR log messages -- unless you g_test_expect_message(). */ g_test_init (argc, argv, NULL); } @@ -200,6 +206,8 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ } else if (!g_ascii_strncasecmp (debug, "sudo-cmd=", strlen ("sudo-cmd="))) { g_free (sudo_cmd); sudo_cmd = g_strdup (&debug[strlen ("sudo-cmd=")]); + } else if (!g_ascii_strcasecmp (debug, "no-expect-message")) { + no_expect_message = TRUE; } else { char *msg = g_strdup_printf (">>> nmtst: ignore unrecognized NMTST_DEBUG option \"%s\"", debug); @@ -225,6 +233,7 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ __nmtst_internal.is_debug = is_debug; __nmtst_internal.rand0 = g_rand_new_with_seed (0); __nmtst_internal.sudo_cmd = sudo_cmd; + __nmtst_internal.no_expect_message = no_expect_message; if (!log_level && log_domains) { /* if the log level is not specified (but the domain is), we assume @@ -238,6 +247,11 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ success = nm_logging_setup (log_level, log_domains, NULL, NULL); #endif g_assert (success); + } else if (__nmtst_internal.no_expect_message) { + /* We have a test that would be assert_logging, but the user specified no_expect_message. + * This transforms g_test_expect_message() into a NOP, but we also have to relax + * g_log_set_always_fatal(), which was set by g_test_init(). */ + g_log_set_always_fatal (G_LOG_FATAL_MASK); } else { #if GLIB_CHECK_VERSION(2,34,0) /* We were called not to set logging levels. This means, that the user @@ -249,7 +263,7 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ #endif } - if (!__nmtst_internal.assert_logging && + if ((!__nmtst_internal.assert_logging || (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message)) && (is_debug || (log_level && !g_ascii_strcasecmp (log_level, "DEBUG"))) && !g_getenv ("G_MESSAGES_DEBUG")) { @@ -306,6 +320,21 @@ nmtst_is_debug (void) return __nmtst_internal.is_debug; } +#if GLIB_CHECK_VERSION(2,34,0) +#undef g_test_expect_message +#define g_test_expect_message(...) \ + G_STMT_START { \ + g_assert (nmtst_initialized ()); \ + if (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message) { \ + g_debug ("nmtst: swallow g_test_expect_message %s", G_STRINGIFY ((__VA_ARGS__))); \ + } else { \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + g_test_expect_message (__VA_ARGS__); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + } \ + } G_STMT_END +#endif + inline static GRand * nmtst_get_rand0 () { diff --git a/libnm-util/tests/test-general.c b/libnm-util/tests/test-general.c index bc63251754..5a54c558cb 100644 --- a/libnm-util/tests/test-general.c +++ b/libnm-util/tests/test-general.c @@ -2484,17 +2484,13 @@ test_setting_old_uuid (void) g_assert (success == TRUE); } +NMTST_DEFINE (); + int main (int argc, char **argv) { - GError *error = NULL; char *base; -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - if (!nm_utils_init (&error)) - FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + nmtst_init (&argc, &argv, TRUE); /* The tests */ test_setting_vpn_items (); diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c index cdb1f1f274..39c81027fe 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils.c @@ -113,10 +113,14 @@ test_ignored (const char *desc, const char *path, gboolean expected_ignored) ASSERT (result == expected_ignored, desc, "unexpected ignore result for path '%s'", path); } +NMTST_DEFINE (); + int main (int argc, char **argv) { char *base; + nmtst_init (&argc, &argv, TRUE); + /* The tests */ test_get_ifcfg_name ("get-ifcfg-name-bad", "/foo/bar/adfasdfadf", FALSE, NULL); test_get_ifcfg_name ("get-ifcfg-name-good", "/foo/bar/ifcfg-FooBar", FALSE, "FooBar"); diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 5d91b2add3..9e0706def6 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -54,6 +54,7 @@ #include "reader.h" #include "writer.h" #include "utils.h" +#include "nm-logging.h" #include "nm-test-utils.h" @@ -14377,27 +14378,11 @@ test_svUnescape () #define TPATH "/settings/plugins/ifcfg-rh/" +NMTST_DEFINE (); + int main (int argc, char **argv) { - GError *error = NULL; - gboolean success; - - g_test_init (&argc, &argv, NULL); -#if GLIB_CHECK_VERSION(2,34,0) - /* consider even unexpected g_message()s to be fatal */ - g_log_set_always_fatal (G_LOG_LEVEL_MASK); -#else - /* g_test_expect_message() is dummied out, so allow warnings */ - g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); -#endif - -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - success = nm_utils_init (&error); - g_assert_no_error (error); - g_assert (success); + nmtst_init_assert_logging (&argc, &argv); g_test_add_func (TPATH "svUnescape", test_svUnescape); diff --git a/src/settings/plugins/ifnet/tests/test_all.c b/src/settings/plugins/ifnet/tests/test_all.c index dc93dcccd6..c320ed5f8f 100644 --- a/src/settings/plugins/ifnet/tests/test_all.c +++ b/src/settings/plugins/ifnet/tests/test_all.c @@ -451,16 +451,16 @@ test_missing_config () "get connection should fail with 'Unknown config for eth8'"); } +NMTST_DEFINE (); + int main (int argc, char **argv) { char *f; -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - nm_linux_platform_setup (); + + nmtst_init_assert_logging (&argc, &argv); nm_logging_setup ("WARN", "DEFAULT", NULL, NULL); f = g_build_filename (argv[1], "net", NULL); diff --git a/src/supplicant-manager/tests/test-supplicant-config.c b/src/supplicant-manager/tests/test-supplicant-config.c index 2b917625a6..ce884a8dd5 100644 --- a/src/supplicant-manager/tests/test-supplicant-config.c +++ b/src/supplicant-manager/tests/test-supplicant-config.c @@ -494,17 +494,13 @@ test_wifi_wpa_psk_types (void) test_wifi_wpa_psk ("wifi-wep-psk-passphrase", TYPE_STRING, key2, (gconstpointer) key2, strlen (key2)); } +NMTST_DEFINE (); + int main (int argc, char **argv) { - GError *error = NULL; char *base; -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - if (!nm_utils_init (&error)) - FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + nmtst_init (&argc, &argv, TRUE); /* The tests */ test_wifi_open (); diff --git a/src/tests/test-dhcp-options.c b/src/tests/test-dhcp-options.c index 96e9b5c822..5df17e587c 100644 --- a/src/tests/test-dhcp-options.c +++ b/src/tests/test-dhcp-options.c @@ -837,24 +837,15 @@ test_ip4_prefix_classless (gconstpointer test_data) g_hash_table_destroy (options); } +NMTST_DEFINE (); + int main (int argc, char **argv) { - GError *error = NULL; char *path; const char *clients[2][2] = { {DHCLIENT_PATH, "dhclient"}, {DHCPCD_PATH, "dhcpcd"} }; guint32 i; - g_test_init (&argc, &argv, NULL); -#if !GLIB_CHECK_VERSION(2,34,0) - g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL); -#endif - -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - if (!nm_utils_init (&error)) - FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message); + nmtst_init_assert_logging (&argc, &argv); nm_logging_setup ("WARN", "DEFAULT", NULL, NULL); for (i = 0; i < 2; i++) {