diff options
Diffstat (limited to 'libnm-core/tests/test-general.c')
| -rw-r--r-- | libnm-core/tests/test-general.c | 247 |
1 files changed, 241 insertions, 6 deletions
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 2b1f1e3d..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 } @@ -3334,6 +3341,7 @@ test_connection_diff_a_only (void) { NM_SETTING_CONNECTION_AUTH_RETRIES, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_MDNS, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_LLMNR, NM_SETTING_DIFF_RESULT_IN_A }, + { NM_SETTING_CONNECTION_MUD_URL, NM_SETTING_DIFF_RESULT_IN_A }, { NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A }, { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN } } }, @@ -7814,7 +7822,7 @@ _do_test_utils_str_utf8safe_unescape (const char *str, const char *expected, gsi gs_free gpointer buf_free_1 = NULL; gs_free char *str_free_1 = NULL; - s = nm_utils_buf_utf8safe_unescape (str, &l, &buf_free_1); + s = nm_utils_buf_utf8safe_unescape (str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &l, &buf_free_1); g_assert_cmpint (expected_len, ==, l); g_assert_cmpstr (s, ==, expected); @@ -7838,7 +7846,7 @@ _do_test_utils_str_utf8safe_unescape (const char *str, const char *expected, gsi if ( expected && l == strlen (expected)) { /* there are no embeeded NULs. Check that nm_utils_str_utf8safe_unescape() yields the same result. */ - s = nm_utils_str_utf8safe_unescape (str, &str_free_1); + s = nm_utils_str_utf8safe_unescape (str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_1); g_assert_cmpstr (s, ==, expected); if (strchr (str, '\\')) { g_assert (str_free_1 != str); @@ -7907,10 +7915,10 @@ _do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expecte g_assert (g_utf8_validate (str, -1, NULL)); } - g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, &str_free_4)); + g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_4)); g_assert (!str_free_4); - str_free_5 = nm_utils_str_utf8safe_unescape_cp (str_safe); + str_free_5 = nm_utils_str_utf8safe_unescape_cp (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); if (str) { g_assert (str_free_5 != str); g_assert_cmpstr (str_free_5, ==, str); @@ -7934,11 +7942,11 @@ _do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expecte str_free_6 = g_strcompress (str_safe); g_assert_cmpstr (str, ==, str_free_6); - str_free_7 = nm_utils_str_utf8safe_unescape_cp (str_safe); + str_free_7 = nm_utils_str_utf8safe_unescape_cp (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE); g_assert (str_free_7 != str); g_assert_cmpstr (str_free_7, ==, str); - s = nm_utils_str_utf8safe_unescape (str_safe, &str_free_8); + s = nm_utils_str_utf8safe_unescape (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_8); g_assert (str_free_8 != str); g_assert (s == str_free_8); g_assert_cmpstr (str_free_8, ==, str); @@ -8863,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); + } +} /*****************************************************************************/ @@ -9041,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 (); } |