diff options
| author | Michael Biebl <biebl@debian.org> | 2020-06-29 22:15:58 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-06-29 22:15:58 +0200 |
| commit | 10ae7d8cd706062742d0cdb1803d49909aef9e06 (patch) | |
| tree | cb89e8b475cec18f22b1abfe45f1d63da7e3f440 /libnm-core | |
| parent | a54ac63bbf9b2c71026ac9028a8ffaf186cf3c82 (diff) | |
New upstream version 1.25.91 upstream/1.25.91
Diffstat (limited to 'libnm-core')
| -rw-r--r-- | libnm-core/nm-core-internal.h | 2 | ||||
| -rw-r--r-- | libnm-core/nm-core-types.h | 1 | ||||
| -rw-r--r-- | libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c | 30 | ||||
| -rw-r--r-- | libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h | 4 | ||||
| -rw-r--r-- | libnm-core/nm-setting-ip-config.c | 57 | ||||
| -rw-r--r-- | libnm-core/nm-setting-ip-config.h | 1 | ||||
| -rw-r--r-- | libnm-core/nm-setting-match.c | 52 | ||||
| -rw-r--r-- | libnm-core/tests/test-general.c | 234 |
8 files changed, 354 insertions, 27 deletions
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 6d7661b9..1d67b094 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -347,7 +347,7 @@ const char **_nm_ip_address_get_attribute_names (const NMIPAddress *addr, gboole void _nm_setting_wired_clear_s390_options (NMSettingWired *setting); -gboolean _nm_ip_route_attribute_validate_all (const NMIPRoute *route); +gboolean _nm_ip_route_attribute_validate_all (const NMIPRoute *route, GError **error); const char **_nm_ip_route_get_attribute_names (const NMIPRoute *route, gboolean sorted, guint *out_length); GHashTable *_nm_ip_route_get_attributes (NMIPRoute *route); diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h index ce59ec03..0237e676 100644 --- a/libnm-core/nm-core-types.h +++ b/libnm-core/nm-core-types.h @@ -65,7 +65,6 @@ typedef struct _NMSettingWirelessSecurity NMSettingWirelessSecurity; typedef struct _NMSettingWpan NMSettingWpan; typedef struct _NMSimpleConnection NMSimpleConnection; -NM_AVAILABLE_IN_1_26 typedef gboolean (*NMUtilsPredicateStr) (const char *str); #endif /* __NM_CORE_TYPES_H__ */ diff --git a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c index df2f2e77..8d2ea09c 100644 --- a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c +++ b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.c @@ -6,6 +6,8 @@ #include "nm-common-macros.h" +#include <linux/rtnetlink.h> + /*****************************************************************************/ gboolean @@ -178,3 +180,31 @@ nm_client_permission_result_to_string (NMClientPermissionResult permission) nm_assert_not_reached (); return NULL; } + +NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( + nm_utils_route_type_by_name, + guint8, + { nm_assert (name); }, + { return RTN_UNSPEC; }, + { "blackhole", RTN_BLACKHOLE }, + { "broadcast", RTN_BROADCAST }, + { "local", RTN_LOCAL }, + { "multicast", RTN_MULTICAST }, + { "nat", RTN_NAT }, + { "prohibit", RTN_PROHIBIT }, + { "throw", RTN_THROW }, + { "unicast", RTN_UNICAST }, + { "unreachable", RTN_UNREACHABLE }, +); + +NM_UTILS_ENUM2STR_DEFINE (nm_utils_route_type2str, guint8, + NM_UTILS_ENUM2STR (RTN_BLACKHOLE, "blackhole"), + NM_UTILS_ENUM2STR (RTN_BROADCAST, "broadcast"), + NM_UTILS_ENUM2STR (RTN_LOCAL, "local"), + NM_UTILS_ENUM2STR (RTN_MULTICAST, "multicast"), + NM_UTILS_ENUM2STR (RTN_NAT, "nat"), + NM_UTILS_ENUM2STR (RTN_PROHIBIT, "prohibit"), + NM_UTILS_ENUM2STR (RTN_THROW, "throw"), + NM_UTILS_ENUM2STR (RTN_UNICAST, "unicast"), + NM_UTILS_ENUM2STR (RTN_UNREACHABLE, "unreachable"), +); diff --git a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h index a35a5e15..afc214d4 100644 --- a/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h +++ b/libnm-core/nm-libnm-core-intern/nm-libnm-core-utils.h @@ -112,4 +112,8 @@ NMClientPermission nm_auth_permission_from_string (const char *str); NMClientPermissionResult nm_client_permission_result_from_string (const char *nm); const char *nm_client_permission_result_to_string (NMClientPermissionResult permission); +guint8 nm_utils_route_type_by_name (const char *name); + +const char *nm_utils_route_type2str (guint8 val, char *buf, gsize len); + #endif /* __NM_LIBNM_SHARED_UTILS_H__ */ diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index 09a34283..bc811291 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -1214,6 +1214,7 @@ static const NMVariantAttributeSpec *const ip_route_attribute_spec[] = { NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_SRC, G_VARIANT_TYPE_STRING, .v4 = TRUE, .v6 = TRUE, .str_type = 'a', ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TABLE, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TOS, G_VARIANT_TYPE_BYTE, .v4 = TRUE, ), + NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_TYPE, G_VARIANT_TYPE_STRING, .v4 = TRUE, .v6 = TRUE, .str_type = 'T', ), NM_VARIANT_ATTRIBUTE_SPEC_DEFINE (NM_IP_ROUTE_ATTRIBUTE_WINDOW, G_VARIANT_TYPE_UINT32, .v4 = TRUE, .v6 = TRUE, ), NULL, }; @@ -1339,6 +1340,18 @@ nm_ip_route_attribute_validate (const char *name, } break; } + case 'T': /* route type. */ + if (!NM_IN_SET (nm_utils_route_type_by_name (string), + RTN_UNICAST, + RTN_LOCAL)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("%s is not a valid route type"), + string); + return FALSE; + } + break; default: break; } @@ -1348,22 +1361,48 @@ nm_ip_route_attribute_validate (const char *name, } gboolean -_nm_ip_route_attribute_validate_all (const NMIPRoute *route) +_nm_ip_route_attribute_validate_all (const NMIPRoute *route, GError **error) { GHashTableIter iter; const char *key; GVariant *val; + guint8 u8; g_return_val_if_fail (route, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); if (!route->attributes) return TRUE; g_hash_table_iter_init (&iter, route->attributes); while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) { - if (!nm_ip_route_attribute_validate (key, val, route->family, NULL, NULL)) + if (!nm_ip_route_attribute_validate (key, val, route->family, NULL, error)) return FALSE; } + + if ((val = g_hash_table_lookup (route->attributes, + NM_IP_ROUTE_ATTRIBUTE_TYPE))) { + nm_assert (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING)); + u8 = nm_utils_route_type_by_name (g_variant_get_string (val, NULL)); + + if ( u8 == RTN_LOCAL + && route->family == AF_INET + && (val = g_hash_table_lookup (route->attributes, NM_IP_ROUTE_ATTRIBUTE_SCOPE))) { + nm_assert (g_variant_is_of_type (val, G_VARIANT_TYPE_BYTE)); + u8 = g_variant_get_byte (val); + + if (!NM_IN_SET(u8, + RT_SCOPE_HOST, + RT_SCOPE_NOWHERE)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("route scope is invalid")); + return FALSE; + } + } + } + return TRUE; } @@ -5020,6 +5059,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) /* Validate routes */ for (i = 0; i < priv->routes->len; i++) { + gs_free_error GError *local = NULL; NMIPRoute *route = (NMIPRoute *) priv->routes->pdata[i]; if (nm_ip_route_get_family (route) != NM_SETTING_IP_CONFIG_GET_FAMILY (setting)) { @@ -5031,6 +5071,19 @@ verify (NMSetting *setting, NMConnection *connection, GError **error) g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTES); return FALSE; } + + if (!_nm_ip_route_attribute_validate_all (route, &local)) { + g_set_error (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("invalid attribute: %s"), + local->message); + g_prefix_error (error, + "%s.%s: ", + nm_setting_get_name (setting), + NM_SETTING_IP_CONFIG_ROUTES); + return FALSE; + } } if (priv->routing_rules) { diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h index ae77480c..0c655d26 100644 --- a/libnm-core/nm-setting-ip-config.h +++ b/libnm-core/nm-setting-ip-config.h @@ -164,6 +164,7 @@ gboolean nm_ip_route_attribute_validate (const char *name, #define NM_IP_ROUTE_ATTRIBUTE_SRC "src" #define NM_IP_ROUTE_ATTRIBUTE_TABLE "table" #define NM_IP_ROUTE_ATTRIBUTE_TOS "tos" +#define NM_IP_ROUTE_ATTRIBUTE_TYPE "type" #define NM_IP_ROUTE_ATTRIBUTE_WINDOW "window" /*****************************************************************************/ diff --git a/libnm-core/nm-setting-match.c b/libnm-core/nm-setting-match.c index 8fb513e5..940cc68d 100644 --- a/libnm-core/nm-setting-match.c +++ b/libnm-core/nm-setting-match.c @@ -659,16 +659,16 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_INTERFACE_NAME: - g_value_set_boxed (value, nm_strvarray_get_strv (&self->interface_name, NULL)); + g_value_set_boxed (value, nm_strvarray_get_strv_non_empty (self->interface_name, NULL)); break; case PROP_KERNEL_COMMAND_LINE: - g_value_set_boxed (value, nm_strvarray_get_strv (&self->kernel_command_line, NULL)); + g_value_set_boxed (value, nm_strvarray_get_strv_non_empty (self->kernel_command_line, NULL)); break; case PROP_DRIVER: - g_value_set_boxed (value, nm_strvarray_get_strv (&self->driver, NULL)); + g_value_set_boxed (value, nm_strvarray_get_strv_non_empty (self->driver, NULL)); break; case PROP_PATH: - g_value_set_boxed (value, nm_strvarray_get_strv (&self->path, NULL)); + g_value_set_boxed (value, nm_strvarray_get_strv_non_empty (self->path, NULL)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -796,6 +796,7 @@ finalize (GObject *object) nm_clear_pointer (&self->interface_name, g_array_unref); nm_clear_pointer (&self->kernel_command_line, g_array_unref); nm_clear_pointer (&self->driver, g_array_unref); + nm_clear_pointer (&self->path, g_array_unref); G_OBJECT_CLASS (nm_setting_match_parent_class)->finalize (object); } @@ -816,13 +817,19 @@ nm_setting_match_class_init (NMSettingMatchClass *klass) * NMSettingMatch:interface-name * * A list of interface names to match. Each element is a shell wildcard - * pattern. When an element is prefixed with exclamation mark (!) the - * condition is inverted. + * pattern. * - * A candidate interface name is considered matching when both these - * conditions are satisfied: (a) any of the elements not prefixed with '!' - * matches or there aren't such elements; (b) none of the elements - * prefixed with '!' match. + * An element can be prefixed with a pipe symbol (|) or an ampersand (&). + * The former means that the element is optional and the latter means that + * it is mandatory. If there are any optional elements, than the match + * evaluates to true if at least one of the optional element matches + * (logical OR). If there are any mandatory elements, then they all + * must match (logical AND). By default, an element is optional. This means + * that an element "foo" behaves the same as "|foo". An element can also be inverted + * with exclamation mark (!) between the pipe symbol (or the ampersand) and before + * the pattern. Note that "!foo" is a shortcut for the mandatory match "&!foo". Finally, + * a backslash can be used at the beginning of the element (after the optional special characters) + * to escape the start of the pattern. For example, "&\\!a" is an mandatory match for literally "!a". * * Since: 1.14 **/ @@ -844,6 +851,10 @@ nm_setting_match_class_init (NMSettingMatchClass *klass) * of an assignment. In the latter case, the exact assignment is looked for * with right and left hand side matching. * + * See NMSettingMatch:interface-name for how special characters '|', '&', + * '!' and '\\' are used for optional and mandatory matches and inverting the + * pattern. + * * Since: 1.26 **/ obj_properties[PROP_KERNEL_COMMAND_LINE] = @@ -857,11 +868,10 @@ nm_setting_match_class_init (NMSettingMatchClass *klass) * NMSettingMatch:driver * * A list of driver names to match. Each element is a shell wildcard pattern. - * When an element is prefixed with exclamation mark (!) the condition is - * inverted. A candidate driver name is considered matching when both these - * conditions are satisfied: (a) any of the elements not prefixed with '!' - * matches or there aren't such elements; (b) none of the elements prefixed - * with '!' match. + * + * See NMSettingMatch:interface-name for how special characters '|', '&', + * '!' and '\\' are used for optional and mandatory matches and inverting the + * pattern. * * Since: 1.26 **/ @@ -872,7 +882,6 @@ nm_setting_match_class_init (NMSettingMatchClass *klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - /** * NMSettingMatch:path * @@ -890,14 +899,11 @@ nm_setting_match_class_init (NMSettingMatchClass *klass) * property exported by NetworkManager ("nmcli -f general.path device * show $dev"). * - * Each element of the list is a shell wildcard pattern. When an - * element is prefixed with exclamation mark (!) the condition is - * inverted. + * Each element of the list is a shell wildcard pattern. * - * A candidate path is considered matching when both these - * conditions are satisfied: (a) any of the elements not prefixed with '!' - * matches or there aren't such elements; (b) none of the elements - * prefixed with '!' match. + * See NMSettingMatch:interface-name for how special characters '|', '&', + * '!' and '\\' are used for optional and mandatory matches and inverting the + * pattern. * * Since: 1.26 **/ diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index a6fb7007..f70a7d5a 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -13,6 +13,8 @@ #include "nm-std-aux/c-list-util.h" #include "nm-glib-aux/nm-enum-utils.h" +#include "nm-glib-aux/nm-str-buf.h" +#include "systemd/nm-sd-utils-shared.h" #include "nm-utils.h" #include "nm-setting-private.h" @@ -2020,6 +2022,11 @@ test_setting_ip_route_attributes (void) TEST_ATTR ("src", string, "1.2.3.0/24", AF_INET, FALSE, TRUE); TEST_ATTR ("src", string, "fd01::12", AF_INET6, TRUE, TRUE); + TEST_ATTR ("type", string, "local", AF_INET, TRUE, TRUE); + TEST_ATTR ("type", string, "local", AF_INET6, TRUE, TRUE); + TEST_ATTR ("type", string, "unicast", AF_INET, TRUE, TRUE); + TEST_ATTR ("type", string, "unicast", AF_INET6, TRUE, TRUE); + #undef TEST_ATTR } @@ -8864,7 +8871,232 @@ test_connection_ovs_ifname (gconstpointer test_data) } } +/*****************************************************************************/ + +static gboolean +_strsplit_quoted_char_needs_escaping (char ch) +{ + return NM_IN_SET (ch, '\'', '\"', '\\') + || strchr (NM_ASCII_WHITESPACES, ch); +} + +static char * +_strsplit_quoted_create_str_rand (gssize len) +{ + NMStrBuf strbuf = NM_STR_BUF_INIT (nmtst_get_rand_uint32 () % 200, nmtst_get_rand_bool ()); + + g_assert (len >= -1); + + if (len == -1) + len = nmtst_get_rand_word_length (NULL); + + while (len-- > 0) { + char ch; + + ch = nmtst_rand_select ('a', ' ', '\\', '"', '\'', nmtst_get_rand_uint32 () % 255 + 1); + g_assert (ch); + nm_str_buf_append_c (&strbuf, ch); + } + + if (!strbuf.allocated) + nm_str_buf_maybe_expand (&strbuf, 1, nmtst_get_rand_bool ()); + return nm_str_buf_finalize (&strbuf, NULL); +} + +static char ** +_strsplit_quoted_create_strv_rand (void) +{ + guint len = nmtst_get_rand_word_length (NULL); + char **ptr; + guint i; + + ptr = g_new (char *, len + 1); + for (i = 0; i < len; i++) + ptr[i] = _strsplit_quoted_create_str_rand (-1); + ptr[i] = NULL; + return ptr; +} + +static char * +_strsplit_quoted_join_strv_rand (const char *const*strv) +{ + NMStrBuf strbuf = NM_STR_BUF_INIT (nmtst_get_rand_uint32 () % 200, nmtst_get_rand_bool ()); + char *result; + gsize l; + gsize l2; + gsize *p_l2 = nmtst_get_rand_bool () ? &l2 : NULL; + gsize i; + + g_assert (strv); + + nm_str_buf_append_c_repeated (&strbuf, ' ', nmtst_get_rand_word_length (NULL) / 4); + for (i = 0; strv[i]; i++) { + const char *s = strv[i]; + gsize j; + char quote; + + nm_str_buf_append_c_repeated (&strbuf, ' ', 1 + nmtst_get_rand_word_length (NULL) / 4); + + j = 0; + quote = '\0'; + while (TRUE) { + char ch = s[j++]; + + /* extract_first_word*/ + if (quote != '\0') { + if (ch == '\0') { + nm_str_buf_append_c (&strbuf, quote); + break; + } + if ( ch == quote + || ch == '\\' + || nmtst_get_rand_uint32 () % 5 == 0) + nm_str_buf_append_c (&strbuf, '\\'); + nm_str_buf_append_c (&strbuf, ch); + if (nmtst_get_rand_uint32 () % 3 == 0) { + nm_str_buf_append_c (&strbuf, quote); + quote = '\0'; + goto next_maybe_quote; + } + continue; + } + + if (ch == '\0') { + if (s == strv[i]) { + quote = nmtst_rand_select ('\'', '"'); + nm_str_buf_append_c_repeated (&strbuf, quote, 2); + } + break; + } + + if ( _strsplit_quoted_char_needs_escaping (ch) + || nmtst_get_rand_uint32 () % 5 == 0) + nm_str_buf_append_c (&strbuf, '\\'); + + nm_str_buf_append_c (&strbuf, ch); + +next_maybe_quote: + if (nmtst_get_rand_uint32 () % 5 == 0) { + quote = nmtst_rand_select ('\'', '\"'); + nm_str_buf_append_c (&strbuf, quote); + if (nmtst_get_rand_uint32 () % 5 == 0) { + nm_str_buf_append_c (&strbuf, quote); + quote = '\0'; + } + } + } + } + nm_str_buf_append_c_repeated (&strbuf, ' ', nmtst_get_rand_word_length (NULL) / 4); + + nm_str_buf_maybe_expand (&strbuf, 1, nmtst_get_rand_bool ()); + + l = strbuf.len; + result = nm_str_buf_finalize (&strbuf, p_l2); + g_assert (!p_l2 || l == *p_l2); + g_assert (strlen (result) == l); + return result; +} + +static void +_strsplit_quoted_assert_strv (const char *topic, + const char *str, + const char *const*strv1, + const char *const*strv2) +{ + nm_auto_str_buf NMStrBuf s1 = { }; + nm_auto_str_buf NMStrBuf s2 = { }; + gs_free char *str_escaped = NULL; + int i; + + g_assert (str); + g_assert (strv1); + g_assert (strv2); + + if (_nm_utils_strv_equal ((char **) strv1, (char **) strv2)) + return; + + for (i = 0; strv1[i]; i++) { + gs_free char *s = g_strescape (strv1[i], NULL); + + g_print (">>> [%s] strv1[%d] = \"%s\"\n", topic, i, s); + if (i > 0) + nm_str_buf_append_c (&s1, ' '); + nm_str_buf_append_printf (&s1, "\"%s\"", s); + } + + for (i = 0; strv2[i]; i++) { + gs_free char *s = g_strescape (strv2[i], NULL); + + g_print (">>> [%s] strv2[%d] = \"%s\"\n", topic, i, s); + if (i > 0) + nm_str_buf_append_c (&s2, ' '); + nm_str_buf_append_printf (&s2, "\"%s\"", s); + } + + nm_str_buf_maybe_expand (&s1, 1, FALSE); + nm_str_buf_maybe_expand (&s2, 1, FALSE); + + str_escaped = g_strescape (str, NULL); + g_error ("compared words differs: [%s] str=\"%s\"; strv1=%s; strv2=%s", topic, str_escaped, nm_str_buf_get_str (&s1), nm_str_buf_get_str (&s2)); +} +static void +_strsplit_quoted_test (const char *str, + const char *const*strv_expected) +{ + gs_strfreev char **strv_systemd = NULL; + gs_strfreev char **strv_nm = NULL; + int r; + + g_assert (str); + + r = nmtst_systemd_extract_first_word_all (str, &strv_systemd); + g_assert_cmpint (r, ==, 1); + g_assert (strv_systemd); + + if (!strv_expected) + strv_expected = (const char *const*) strv_systemd; + + _strsplit_quoted_assert_strv ("systemd", str, strv_expected, (const char *const*) strv_systemd); + + strv_nm = nm_utils_strsplit_quoted (str); + g_assert (strv_nm); + _strsplit_quoted_assert_strv ("nm", str, strv_expected, (const char *const*) strv_nm); +} + +static void +test_strsplit_quoted (void) +{ + int i_run; + + _strsplit_quoted_test ("", NM_MAKE_STRV ()); + _strsplit_quoted_test (" ", NM_MAKE_STRV ()); + _strsplit_quoted_test (" ", NM_MAKE_STRV ()); + _strsplit_quoted_test (" \t", NM_MAKE_STRV ()); + _strsplit_quoted_test ("a b", NM_MAKE_STRV ("a", "b")); + _strsplit_quoted_test ("a\\ b", NM_MAKE_STRV ("a b")); + _strsplit_quoted_test (" a\\ \"b\"", NM_MAKE_STRV ("a b")); + _strsplit_quoted_test (" a\\ \"b\" c \n", NM_MAKE_STRV ("a b", "c")); + + for (i_run = 0; i_run < 1000; i_run++) { + gs_strfreev char **strv = NULL; + gs_free char *str = NULL; + + /* create random strv array and join them carefully so that splitting + * them will yield the original value. */ + strv = _strsplit_quoted_create_strv_rand (); + str = _strsplit_quoted_join_strv_rand ((const char *const*) strv); + _strsplit_quoted_test (str, (const char *const*) strv); + } + + /* Create random words and assert that systemd and our implementation can + * both split them (and in the exact same way). */ + for (i_run = 0; i_run < 1000; i_run++) { + gs_free char *s = _strsplit_quoted_create_str_rand (nmtst_get_rand_uint32 () % 150); + + _strsplit_quoted_test (s, NULL); + } +} /*****************************************************************************/ @@ -9042,5 +9274,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/test_nm_ip_addr_zero", test_nm_ip_addr_zero); + g_test_add_func ("/core/general/test_strsplit_quoted", test_strsplit_quoted); + return g_test_run (); } |