diff options
| author | Sebastien Bacher <seb128@ubuntu.com> | 2021-01-11 18:07:03 +0100 |
|---|---|---|
| committer | Sebastien Bacher <seb128@ubuntu.com> | 2021-01-11 18:15:57 +0100 |
| commit | 2567f558da3eb9911678227d4aeb15162e707d89 (patch) | |
| tree | 13c80b0e091c8ba585b14b966cda998f95f1936d /shared/nm-glib-aux/tests | |
| parent | 02d99ffd62ede29cffcb45fcbe33d044b7406d3a (diff) | |
| parent | f54032b30e1ddd84f10a339e0caf493772e049a7 (diff) | |
Merge branch 'debian/master' into ubuntu/master
Diffstat (limited to 'shared/nm-glib-aux/tests')
| -rw-r--r-- | shared/nm-glib-aux/tests/meson.build | 42 | ||||
| -rw-r--r-- | shared/nm-glib-aux/tests/test-json-aux.c | 167 | ||||
| -rw-r--r-- | shared/nm-glib-aux/tests/test-shared-general.c | 1774 |
3 files changed, 1322 insertions, 661 deletions
diff --git a/shared/nm-glib-aux/tests/meson.build b/shared/nm-glib-aux/tests/meson.build index f6328db9..8136eff9 100644 --- a/shared/nm-glib-aux/tests/meson.build +++ b/shared/nm-glib-aux/tests/meson.build @@ -1,23 +1,43 @@ # SPDX-License-Identifier: LGPL-2.1+ -test_unit = 'test-shared-general' - -c_flags = [ - '-DNETWORKMANAGER_COMPILATION_TEST', - '-DNETWORKMANAGER_COMPILATION=(NM_NETWORKMANAGER_COMPILATION_GLIB|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG)', -] - exe = executable( - test_unit, - test_unit + '.c', - c_args: c_flags, + 'test-shared-general', + 'test-shared-general.c', + c_args: [ + '-DNETWORKMANAGER_COMPILATION_TEST', + '-DNETWORKMANAGER_COMPILATION=(NM_NETWORKMANAGER_COMPILATION_GLIB|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG)', + ], dependencies: libnm_utils_base_dep, link_with: libnm_systemd_logging_stub, ) test( - 'shared/nm-glib-aux/' + test_unit, + 'shared/nm-glib-aux/test-shared-general', test_script, args: test_args + [exe.full_path()], timeout: default_test_timeout, ) + +if jansson_dep.found() + exe = executable( + 'test-json-aux', + 'test-json-aux.c', + c_args: [ + '-DNETWORKMANAGER_COMPILATION_TEST', + '-DNETWORKMANAGER_COMPILATION=(NM_NETWORKMANAGER_COMPILATION_GLIB|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG)', + ], + dependencies: [ + libnm_utils_base_dep, + jansson_dep, + dl_dep, + ], + link_with: libnm_systemd_logging_stub, + ) + + test( + 'shared/nm-glib-aux/test-json-aux', + test_script, + args: test_args + [exe.full_path()], + timeout: default_test_timeout, + ) +endif diff --git a/shared/nm-glib-aux/tests/test-json-aux.c b/shared/nm-glib-aux/tests/test-json-aux.c new file mode 100644 index 00000000..5331c015 --- /dev/null +++ b/shared/nm-glib-aux/tests/test-json-aux.c @@ -0,0 +1,167 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#define NM_TEST_UTILS_NO_LIBNM 1 + +#include "nm-default.h" + +#include <jansson.h> + +#include "nm-glib-aux/nm-json-aux.h" + +#include "nm-utils/nm-test-utils.h" + +/*****************************************************************************/ + +static void +test_jansson(void) +{ + const NMJsonVt * vt; + nm_auto_decref_json nm_json_t *js1 = NULL; + nm_auto_decref_json nm_json_t *js2 = NULL; + +#define _ASSERT_FIELD(type1, type2, field) \ + G_STMT_START \ + { \ + G_STATIC_ASSERT_EXPR(sizeof(((type1 *) NULL)->field) == sizeof(((type2 *) NULL)->field)); \ + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(type1, field) == G_STRUCT_OFFSET(type2, field)); \ + } \ + G_STMT_END + + G_STATIC_ASSERT_EXPR(NM_JSON_REJECT_DUPLICATES == JSON_REJECT_DUPLICATES); + + G_STATIC_ASSERT_EXPR(sizeof(nm_json_type) == sizeof(json_type)); + + G_STATIC_ASSERT_EXPR((int) NM_JSON_OBJECT == JSON_OBJECT); + G_STATIC_ASSERT_EXPR((int) NM_JSON_ARRAY == JSON_ARRAY); + G_STATIC_ASSERT_EXPR((int) NM_JSON_STRING == JSON_STRING); + G_STATIC_ASSERT_EXPR((int) NM_JSON_INTEGER == JSON_INTEGER); + G_STATIC_ASSERT_EXPR((int) NM_JSON_REAL == JSON_REAL); + G_STATIC_ASSERT_EXPR((int) NM_JSON_TRUE == JSON_TRUE); + G_STATIC_ASSERT_EXPR((int) NM_JSON_FALSE == JSON_FALSE); + G_STATIC_ASSERT_EXPR((int) NM_JSON_NULL == JSON_NULL); + + G_STATIC_ASSERT_EXPR(sizeof(nm_json_int_t) == sizeof(json_int_t)); + + G_STATIC_ASSERT_EXPR(sizeof(nm_json_t) == sizeof(json_t)); + _ASSERT_FIELD(nm_json_t, json_t, refcount); + _ASSERT_FIELD(nm_json_t, json_t, type); + + G_STATIC_ASSERT_EXPR(NM_JSON_ERROR_TEXT_LENGTH == JSON_ERROR_TEXT_LENGTH); + G_STATIC_ASSERT_EXPR(NM_JSON_ERROR_SOURCE_LENGTH == JSON_ERROR_SOURCE_LENGTH); + + G_STATIC_ASSERT_EXPR(sizeof(nm_json_error_t) == sizeof(json_error_t)); + _ASSERT_FIELD(nm_json_error_t, json_error_t, line); + _ASSERT_FIELD(nm_json_error_t, json_error_t, column); + _ASSERT_FIELD(nm_json_error_t, json_error_t, position); + _ASSERT_FIELD(nm_json_error_t, json_error_t, source); + _ASSERT_FIELD(nm_json_error_t, json_error_t, text); + + vt = nm_json_vt(); + + g_assert(vt); + g_assert(vt->loaded); + + js1 = vt->nm_json_loads("{ \"a\": 5 }", 0, NULL); + g_assert(js1); + nm_json_decref(vt, g_steal_pointer(&js1)); + + js2 = vt->nm_json_loads("{ \"a\": 6 }", 0, NULL); + g_assert(js2); + +#define CHECK_FCN(vt, fcn, nm_type, js_type) \ + G_STMT_START \ + { \ + const NMJsonVt *const _vt = (vt); \ + _nm_unused nm_type = (_vt->nm_##fcn); \ + _nm_unused js_type = (fcn); \ + \ + g_assert(_vt->nm_##fcn); \ + g_assert(_f_nm); \ + g_assert(_f_js); \ + g_assert(_f_nm == _vt->nm_##fcn); \ + } \ + G_STMT_END + + CHECK_FCN(vt, json_array, nm_json_t * (*_f_nm)(void), json_t * (*_f_js)(void) ); + CHECK_FCN(vt, + json_array_append_new, + int (*_f_nm)(nm_json_t *, nm_json_t *), + int (*_f_js)(json_t *, json_t *)); + CHECK_FCN(vt, + json_array_get, + nm_json_t * (*_f_nm)(const nm_json_t *, gsize), + json_t * (*_f_js)(const json_t *, size_t)); + CHECK_FCN(vt, + json_array_size, + gsize(*_f_nm)(const nm_json_t *), + size_t(*_f_js)(const json_t *)); + CHECK_FCN(vt, json_delete, void (*_f_nm)(nm_json_t *), void (*_f_js)(json_t *)); + CHECK_FCN(vt, + json_dumps, + char *(*_f_nm)(const nm_json_t *, gsize), + char *(*_f_js)(const json_t *, size_t)); + CHECK_FCN(vt, json_false, nm_json_t * (*_f_nm)(void), json_t * (*_f_js)(void) ); + CHECK_FCN(vt, json_integer, nm_json_t * (*_f_nm)(nm_json_int_t), json_t * (*_f_js)(json_int_t)); + CHECK_FCN(vt, + json_integer_value, + nm_json_int_t(*_f_nm)(const nm_json_t *), + json_int_t(*_f_js)(const json_t *)); + CHECK_FCN(vt, + json_loads, + nm_json_t * (*_f_nm)(const char *, gsize, nm_json_error_t *), + json_t * (*_f_js)(const char *, size_t, json_error_t *) ); + CHECK_FCN(vt, json_object, nm_json_t * (*_f_nm)(void), json_t * (*_f_js)(void) ); + CHECK_FCN(vt, + json_object_del, + int (*_f_nm)(nm_json_t *, const char *), + int (*_f_js)(json_t *, const char *)); + CHECK_FCN(vt, + json_object_get, + nm_json_t * (*_f_nm)(const nm_json_t *, const char *), + json_t * (*_f_js)(const json_t *, const char *) ); + CHECK_FCN(vt, json_object_iter, void *(*_f_nm)(nm_json_t *), void *(*_f_js)(json_t *) ); + CHECK_FCN(vt, + json_object_iter_key, + const char *(*_f_nm)(void *), + const char *(*_f_js)(void *) ); + CHECK_FCN(vt, + json_object_iter_next, + void *(*_f_nm)(nm_json_t *, void *), + void *(*_f_js)(json_t *, void *) ); + CHECK_FCN(vt, json_object_iter_value, nm_json_t * (*_f_nm)(void *), json_t * (*_f_js)(void *) ); + CHECK_FCN(vt, + json_object_key_to_iter, + void *(*_f_nm)(const char *), + void *(*_f_js)(const char *) ); + CHECK_FCN(vt, + json_object_set_new, + int (*_f_nm)(nm_json_t *, const char *, nm_json_t *), + int (*_f_js)(json_t *, const char *, json_t *)); + CHECK_FCN(vt, + json_object_size, + gsize(*_f_nm)(const nm_json_t *), + size_t(*_f_js)(const json_t *)); + CHECK_FCN(vt, + json_string, + nm_json_t * (*_f_nm)(const char *), + json_t * (*_f_js)(const char *) ); + CHECK_FCN(vt, + json_string_value, + const char *(*_f_nm)(const nm_json_t *), + const char *(*_f_js)(const json_t *) ); + CHECK_FCN(vt, json_true, nm_json_t * (*_f_nm)(void), json_t * (*_f_js)(void) ); +} + +/*****************************************************************************/ + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + nmtst_init(&argc, &argv, TRUE); + + g_test_add_func("/general/test_jansson", test_jansson); + + return g_test_run(); +} diff --git a/shared/nm-glib-aux/tests/test-shared-general.c b/shared/nm-glib-aux/tests/test-shared-general.c index 5c8bdf18..84e0a6f0 100644 --- a/shared/nm-glib-aux/tests/test-shared-general.c +++ b/shared/nm-glib-aux/tests/test-shared-general.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ /* * Copyright (C) 2018 Red Hat, Inc. */ @@ -17,781 +17,1255 @@ /*****************************************************************************/ +G_STATIC_ASSERT(NM_AF_UNSPEC == AF_UNSPEC); +G_STATIC_ASSERT(NM_AF_INET == AF_INET); +G_STATIC_ASSERT(NM_AF_INET6 == AF_INET6); + +G_STATIC_ASSERT(NM_AF_INET_SIZE == sizeof(in_addr_t)); +G_STATIC_ASSERT(NM_AF_INET_SIZE == sizeof(struct in_addr)); +G_STATIC_ASSERT(NM_AF_INET6_SIZE == sizeof(struct in6_addr)); + +G_STATIC_ASSERT(4 == _nm_alignof(in_addr_t)); +G_STATIC_ASSERT(4 == _nm_alignof(struct in_addr)); +G_STATIC_ASSERT(4 == _nm_alignof(struct in6_addr)); +G_STATIC_ASSERT(4 == _nm_alignof(NMIPAddr)); + +/*****************************************************************************/ + static void -test_gpid (void) +test_gpid(void) { - const int *int_ptr; - GPid pid = 42; - - /* We redefine G_PID_FORMAT, because it's only available since glib 2.53.5. - * - * Also, this is the format for GPid, which for glib is always a typedef - * for "int". Add a check for that here. - * - * G_PID_FORMAT is not about pid_t, which might be a smaller int, and which we would - * check with SIZEOF_PID_T. */ - G_STATIC_ASSERT (sizeof (GPid) == sizeof (int)); - - g_assert_cmpstr (""G_PID_FORMAT, ==, "i"); - - /* check that it's really "int". We will get a compiler warning, if that's not - * the case. */ - int_ptr = &pid; - g_assert_cmpint (*int_ptr, ==, 42); + const int *int_ptr; + GPid pid = 42; + + /* We redefine G_PID_FORMAT, because it's only available since glib 2.53.5. + * + * Also, this is the format for GPid, which for glib is always a typedef + * for "int". Add a check for that here. + * + * G_PID_FORMAT is not about pid_t, which might be a smaller int, and which we would + * check with SIZEOF_PID_T. */ + G_STATIC_ASSERT(sizeof(GPid) == sizeof(int)); + + g_assert_cmpstr("" G_PID_FORMAT, ==, "i"); + + /* check that it's really "int". We will get a compiler warning, if that's not + * the case. */ + int_ptr = &pid; + g_assert_cmpint(*int_ptr, ==, 42); } /*****************************************************************************/ static void -test_monotonic_timestamp (void) +test_monotonic_timestamp(void) { - g_assert (nm_utils_get_monotonic_timestamp_sec () > 0); + g_assert(nm_utils_get_monotonic_timestamp_sec() > 0); } /*****************************************************************************/ static void -test_nmhash (void) +test_nmhash(void) { - int rnd; + int rnd; - nm_utils_random_bytes (&rnd, sizeof (rnd)); + nm_utils_random_bytes(&rnd, sizeof(rnd)); - g_assert (nm_hash_val (555, 4) != 0); + g_assert(nm_hash_val(555, 4) != 0); } /*****************************************************************************/ static const char * -_make_strv_foo (void) +_make_strv_foo(void) { - return "foo"; + return "foo"; } -static const char *const*const _tst_make_strv_1 = NM_MAKE_STRV ("1", "2"); +static const char *const *const _tst_make_strv_1 = NM_MAKE_STRV("1", "2"); static void -test_make_strv (void) +test_make_strv(void) { - const char *const*v1a = NM_MAKE_STRV ("a"); - const char *const*v1b = NM_MAKE_STRV ("a", ); - const char *const*v2a = NM_MAKE_STRV ("a", "b"); - const char *const*v2b = NM_MAKE_STRV ("a", "b", ); - const char *const v3[] = { "a", "b", }; - const char *const*v4b = NM_MAKE_STRV ("a", _make_strv_foo (), ); - - g_assert (NM_PTRARRAY_LEN (v1a) == 1); - g_assert (NM_PTRARRAY_LEN (v1b) == 1); - g_assert (NM_PTRARRAY_LEN (v2a) == 2); - g_assert (NM_PTRARRAY_LEN (v2b) == 2); - - g_assert (NM_PTRARRAY_LEN (_tst_make_strv_1) == 2); - g_assert_cmpstr (_tst_make_strv_1[0], ==, "1"); - g_assert_cmpstr (_tst_make_strv_1[1], ==, "2"); - /* writing the static read-only variable leads to crash .*/ - //((char **) _tst_make_strv_1)[0] = NULL; - //((char **) _tst_make_strv_1)[2] = "c"; - - G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (v3) == 2); - - g_assert (NM_PTRARRAY_LEN (v4b) == 2); - - G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (NM_MAKE_STRV ("a", "b" )) == 3); - G_STATIC_ASSERT_EXPR (G_N_ELEMENTS (NM_MAKE_STRV ("a", "b", )) == 3); - - nm_strquote_a (300, ""); + const char *const *v1a = NM_MAKE_STRV("a"); + const char *const *v1b = NM_MAKE_STRV("a", ); + const char *const *v2a = NM_MAKE_STRV("a", "b"); + const char *const *v2b = NM_MAKE_STRV("a", "b", ); + const char *const v3[] = { + "a", + "b", + }; + const char *const *v4b = NM_MAKE_STRV("a", _make_strv_foo(), ); + + g_assert(NM_PTRARRAY_LEN(v1a) == 1); + g_assert(NM_PTRARRAY_LEN(v1b) == 1); + g_assert(NM_PTRARRAY_LEN(v2a) == 2); + g_assert(NM_PTRARRAY_LEN(v2b) == 2); + + g_assert(NM_PTRARRAY_LEN(_tst_make_strv_1) == 2); + g_assert_cmpstr(_tst_make_strv_1[0], ==, "1"); + g_assert_cmpstr(_tst_make_strv_1[1], ==, "2"); + /* writing the static read-only variable leads to crash .*/ + //((char **) _tst_make_strv_1)[0] = NULL; + //((char **) _tst_make_strv_1)[2] = "c"; + + G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(v3) == 2); + + g_assert(NM_PTRARRAY_LEN(v4b) == 2); + + G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(NM_MAKE_STRV("a", "b")) == 3); + G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(NM_MAKE_STRV("a", "b", )) == 3); + + nm_strquote_a(300, ""); } /*****************************************************************************/ typedef enum { - TEST_NM_STRDUP_ENUM_m1 = -1, - TEST_NM_STRDUP_ENUM_3 = 3, + TEST_NM_STRDUP_ENUM_m1 = -1, + TEST_NM_STRDUP_ENUM_3 = 3, } TestNMStrdupIntEnum; static void -test_nm_strdup_int (void) +test_nm_strdup_int(void) { -#define _NM_STRDUP_INT_TEST(num, str) \ - G_STMT_START { \ - gs_free char *_s1 = NULL; \ - \ - _s1 = nm_strdup_int ((num)); \ - \ - g_assert (_s1); \ - g_assert_cmpstr (_s1, ==, str); \ - } G_STMT_END - -#define _NM_STRDUP_INT_TEST_TYPED(type, num) \ - G_STMT_START { \ - type _num = ((type) num); \ - \ - _NM_STRDUP_INT_TEST (_num, G_STRINGIFY (num)); \ - } G_STMT_END - - _NM_STRDUP_INT_TEST_TYPED (char, 0); - _NM_STRDUP_INT_TEST_TYPED (char, 1); - _NM_STRDUP_INT_TEST_TYPED (guint8, 0); - _NM_STRDUP_INT_TEST_TYPED (gint8, 25); - _NM_STRDUP_INT_TEST_TYPED (char, 47); - _NM_STRDUP_INT_TEST_TYPED (short, 47); - _NM_STRDUP_INT_TEST_TYPED (int, 47); - _NM_STRDUP_INT_TEST_TYPED (long, 47); - _NM_STRDUP_INT_TEST_TYPED (unsigned char, 47); - _NM_STRDUP_INT_TEST_TYPED (unsigned short, 47); - _NM_STRDUP_INT_TEST_TYPED (unsigned, 47); - _NM_STRDUP_INT_TEST_TYPED (unsigned long, 47); - _NM_STRDUP_INT_TEST_TYPED (gint64, 9223372036854775807); - _NM_STRDUP_INT_TEST_TYPED (gint64, -9223372036854775807); - _NM_STRDUP_INT_TEST_TYPED (guint64, 0); - _NM_STRDUP_INT_TEST_TYPED (guint64, 9223372036854775807); - - _NM_STRDUP_INT_TEST (TEST_NM_STRDUP_ENUM_m1, "-1"); - _NM_STRDUP_INT_TEST (TEST_NM_STRDUP_ENUM_3, "3"); +#define _NM_STRDUP_INT_TEST(num, str) \ + G_STMT_START \ + { \ + gs_free char *_s1 = NULL; \ + \ + _s1 = nm_strdup_int((num)); \ + \ + g_assert(_s1); \ + g_assert_cmpstr(_s1, ==, str); \ + } \ + G_STMT_END + +#define _NM_STRDUP_INT_TEST_TYPED(type, num) \ + G_STMT_START \ + { \ + type _num = ((type) num); \ + \ + _NM_STRDUP_INT_TEST(_num, G_STRINGIFY(num)); \ + } \ + G_STMT_END + + _NM_STRDUP_INT_TEST_TYPED(char, 0); + _NM_STRDUP_INT_TEST_TYPED(char, 1); + _NM_STRDUP_INT_TEST_TYPED(guint8, 0); + _NM_STRDUP_INT_TEST_TYPED(gint8, 25); + _NM_STRDUP_INT_TEST_TYPED(char, 47); + _NM_STRDUP_INT_TEST_TYPED(short, 47); + _NM_STRDUP_INT_TEST_TYPED(int, 47); + _NM_STRDUP_INT_TEST_TYPED(long, 47); + _NM_STRDUP_INT_TEST_TYPED(unsigned char, 47); + _NM_STRDUP_INT_TEST_TYPED(unsigned short, 47); + _NM_STRDUP_INT_TEST_TYPED(unsigned, 47); + _NM_STRDUP_INT_TEST_TYPED(unsigned long, 47); + _NM_STRDUP_INT_TEST_TYPED(gint64, 9223372036854775807); + _NM_STRDUP_INT_TEST_TYPED(gint64, -9223372036854775807); + _NM_STRDUP_INT_TEST_TYPED(guint64, 0); + _NM_STRDUP_INT_TEST_TYPED(guint64, 9223372036854775807); + + _NM_STRDUP_INT_TEST(TEST_NM_STRDUP_ENUM_m1, "-1"); + _NM_STRDUP_INT_TEST(TEST_NM_STRDUP_ENUM_3, "3"); } /*****************************************************************************/ static void -test_nm_strndup_a (void) +test_nm_strndup_a(void) { - int run; - - for (run = 0; run < 20; run++) { - gs_free char *input = NULL; - char ch; - gsize i, l; - - input = g_strnfill (nmtst_get_rand_uint32 () % 20, 'x'); - - for (i = 0; input[i]; i++) { - while ((ch = ((char) nmtst_get_rand_uint32 ())) == '\0') { - /* repeat. */ - } - input[i] = ch; - } - - { - gs_free char *dup_free = NULL; - const char *dup; - - l = strlen (input) + 1; - dup = nm_strndup_a (10, input, l - 1, &dup_free); - g_assert_cmpstr (dup, ==, input); - if (strlen (dup) < 10) - g_assert (!dup_free); - else - g_assert (dup == dup_free); - } - - { - gs_free char *dup_free = NULL; - const char *dup; - - l = nmtst_get_rand_uint32 () % 23; - dup = nm_strndup_a (10, input, l, &dup_free); - g_assert (strncmp (dup, input, l) == 0); - g_assert (strlen (dup) <= l); - if (l < 10) - g_assert (!dup_free); - else - g_assert (dup == dup_free); - if (strlen (input) < l) - g_assert (nm_utils_memeqzero (&dup[strlen (input)], l - strlen (input))); - } - } + int run; + + for (run = 0; run < 20; run++) { + gs_free char *input = NULL; + char ch; + gsize i, l; + + input = g_strnfill(nmtst_get_rand_uint32() % 20, 'x'); + + for (i = 0; input[i]; i++) { + while ((ch = ((char) nmtst_get_rand_uint32())) == '\0') { + /* repeat. */ + } + input[i] = ch; + } + + { + gs_free char *dup_free = NULL; + const char * dup; + + l = strlen(input) + 1; + dup = nm_strndup_a(10, input, l - 1, &dup_free); + g_assert_cmpstr(dup, ==, input); + if (strlen(dup) < 10) + g_assert(!dup_free); + else + g_assert(dup == dup_free); + } + + { + gs_free char *dup_free = NULL; + const char * dup; + + l = nmtst_get_rand_uint32() % 23; + dup = nm_strndup_a(10, input, l, &dup_free); + g_assert(strncmp(dup, input, l) == 0); + g_assert(strlen(dup) <= l); + if (l < 10) + g_assert(!dup_free); + else + g_assert(dup == dup_free); + if (strlen(input) < l) + g_assert(nm_utils_memeqzero(&dup[strlen(input)], l - strlen(input))); + } + } } /*****************************************************************************/ static void -test_nm_ip4_addr_is_localhost (void) +test_nm_ip4_addr_is_localhost(void) { - g_assert ( nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("127.0.0.0"))); - g_assert ( nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("127.0.0.1"))); - g_assert ( nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("127.5.0.1"))); - g_assert (!nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("126.5.0.1"))); - g_assert (!nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("128.5.0.1"))); - g_assert (!nm_ip4_addr_is_localhost (nmtst_inet4_from_string ("129.5.0.1"))); + g_assert(nm_ip4_addr_is_localhost(nmtst_inet4_from_string("127.0.0.0"))); + g_assert(nm_ip4_addr_is_localhost(nmtst_inet4_from_string("127.0.0.1"))); + g_assert(nm_ip4_addr_is_localhost(nmtst_inet4_from_string("127.5.0.1"))); + g_assert(!nm_ip4_addr_is_localhost(nmtst_inet4_from_string("126.5.0.1"))); + g_assert(!nm_ip4_addr_is_localhost(nmtst_inet4_from_string("128.5.0.1"))); + g_assert(!nm_ip4_addr_is_localhost(nmtst_inet4_from_string("129.5.0.1"))); } /*****************************************************************************/ static void -test_unaligned (void) +test_unaligned(void) { - int shift; + int shift; - for (shift = 0; shift <= 32; shift++) { - guint8 buf[100] = { }; - guint8 val = 0; + for (shift = 0; shift <= 32; shift++) { + guint8 buf[100] = {}; + guint8 val = 0; - while (val == 0) - val = nmtst_get_rand_uint32 () % 256; + while (val == 0) + val = nmtst_get_rand_uint32() % 256; - buf[shift] = val; + buf[shift] = val; - g_assert_cmpint (unaligned_read_le64 (&buf[shift]), ==, (guint64) val); - g_assert_cmpint (unaligned_read_be64 (&buf[shift]), ==, ((guint64) val) << 56); - g_assert_cmpint (unaligned_read_ne64 (&buf[shift]), !=, 0); + g_assert_cmpint(unaligned_read_le64(&buf[shift]), ==, (guint64) val); + g_assert_cmpint(unaligned_read_be64(&buf[shift]), ==, ((guint64) val) << 56); + g_assert_cmpint(unaligned_read_ne64(&buf[shift]), !=, 0); - g_assert_cmpint (unaligned_read_le32 (&buf[shift]), ==, (guint32) val); - g_assert_cmpint (unaligned_read_be32 (&buf[shift]), ==, ((guint32) val) << 24); - g_assert_cmpint (unaligned_read_ne32 (&buf[shift]), !=, 0); + g_assert_cmpint(unaligned_read_le32(&buf[shift]), ==, (guint32) val); + g_assert_cmpint(unaligned_read_be32(&buf[shift]), ==, ((guint32) val) << 24); + g_assert_cmpint(unaligned_read_ne32(&buf[shift]), !=, 0); - g_assert_cmpint (unaligned_read_le16 (&buf[shift]), ==, (guint16) val); - g_assert_cmpint (unaligned_read_be16 (&buf[shift]), ==, ((guint16) val) << 8); - g_assert_cmpint (unaligned_read_ne16 (&buf[shift]), !=, 0); - } + g_assert_cmpint(unaligned_read_le16(&buf[shift]), ==, (guint16) val); + g_assert_cmpint(unaligned_read_be16(&buf[shift]), ==, ((guint16) val) << 8); + g_assert_cmpint(unaligned_read_ne16(&buf[shift]), !=, 0); + } } /*****************************************************************************/ static void -_strv_cmp_fuzz_input (const char *const*in, - gssize l, - const char ***out_strv_free_shallow, - char ***out_strv_free_deep, - const char *const* *out_s1, - const char *const* *out_s2) +_strv_cmp_fuzz_input(const char *const * in, + gssize l, + const char *** out_strv_free_shallow, + char *** out_strv_free_deep, + const char *const **out_s1, + const char *const **out_s2) { - const char **strv; - gsize i; - - /* Fuzz the input argument. It will return two output arrays that are semantically - * equal the input. */ - - if (nmtst_get_rand_bool ()) { - char **ss; - - if (l < 0) - ss = g_strdupv ((char **) in); - else if (l == 0) { - ss = nmtst_get_rand_bool () - ? NULL - : g_new0 (char *, 1); - } else { - ss = nm_memdup (in, sizeof (const char *) * l); - for (i = 0; i < (gsize) l; i++) - ss[i] = g_strdup (ss[i]); - } - strv = (const char **) ss; - *out_strv_free_deep = ss; - } else { - if (l < 0) { - strv = in - ? nm_memdup (in, sizeof (const char *) * (NM_PTRARRAY_LEN (in) + 1)) - : NULL; - } else if (l == 0) { - strv = nmtst_get_rand_bool () - ? NULL - : g_new0 (const char *, 1); - } else - strv = nm_memdup (in, sizeof (const char *) * l); - *out_strv_free_shallow = strv; - } - - *out_s1 = in; - *out_s2 = strv; - - if (nmtst_get_rand_bool ()) { - /* randomly swap the original and the clone. That means, out_s1 is either - * the input argument (as-is) or the sementically equal clone. */ - NM_SWAP (*out_s1, *out_s2); - } - if (nmtst_get_rand_bool ()) { - /* randomly make s1 and s2 the same. This is for testing that - * comparing two identical pointers yields the same result. */ - *out_s2 = *out_s1; - } + const char **strv; + gsize i; + + /* Fuzz the input argument. It will return two output arrays that are semantically + * equal the input. */ + + if (nmtst_get_rand_bool()) { + char **ss; + + if (l < 0) + ss = g_strdupv((char **) in); + else if (l == 0) { + ss = nmtst_get_rand_bool() ? NULL : g_new0(char *, 1); + } else { + ss = nm_memdup(in, sizeof(const char *) * l); + for (i = 0; i < (gsize) l; i++) + ss[i] = g_strdup(ss[i]); + } + strv = (const char **) ss; + *out_strv_free_deep = ss; + } else { + if (l < 0) { + strv = in ? nm_memdup(in, sizeof(const char *) * (NM_PTRARRAY_LEN(in) + 1)) : NULL; + } else if (l == 0) { + strv = nmtst_get_rand_bool() ? NULL : g_new0(const char *, 1); + } else + strv = nm_memdup(in, sizeof(const char *) * l); + *out_strv_free_shallow = strv; + } + + *out_s1 = in; + *out_s2 = strv; + + if (nmtst_get_rand_bool()) { + /* randomly swap the original and the clone. That means, out_s1 is either + * the input argument (as-is) or the sementically equal clone. */ + NM_SWAP(out_s1, out_s2); + } + if (nmtst_get_rand_bool()) { + /* randomly make s1 and s2 the same. This is for testing that + * comparing two identical pointers yields the same result. */ + *out_s2 = *out_s1; + } } static void -_strv_cmp_free_deep (char **strv, - gssize len) +_strv_cmp_free_deep(char **strv, gssize len) { - gssize i; - - if (strv) { - if (len < 0) - g_strfreev (strv); - else { - for (i = 0; i < len; i++) - g_free (strv[i]); - g_free (strv); - } - } + gssize i; + + if (strv) { + if (len < 0) + g_strfreev(strv); + else { + for (i = 0; i < len; i++) + g_free(strv[i]); + g_free(strv); + } + } } static void -test_strv_cmp (void) +test_strv_cmp(void) { - const char *const strv0[1] = { }; - const char *const strv1[2] = { "", }; - -#define _STRV_CMP(a1, l1, a2, l2, equal) \ - G_STMT_START { \ - gssize _l1 = (l1); \ - gssize _l2 = (l2); \ - const char *const*_a1; \ - const char *const*_a2; \ - const char *const*_a1x; \ - const char *const*_a2x; \ - char **_a1_free_deep = NULL; \ - char **_a2_free_deep = NULL; \ - gs_free const char **_a1_free_shallow = NULL; \ - gs_free const char **_a2_free_shallow = NULL; \ - int _c1, _c2; \ - \ - _strv_cmp_fuzz_input ((a1), _l1, &_a1_free_shallow, &_a1_free_deep, &_a1, &_a1x); \ - _strv_cmp_fuzz_input ((a2), _l2, &_a2_free_shallow, &_a2_free_deep, &_a2, &_a2x); \ - \ - _c1 = _nm_utils_strv_cmp_n (_a1, _l1, _a2, _l2); \ - _c2 = _nm_utils_strv_cmp_n (_a2, _l2, _a1, _l1); \ - if (equal) { \ - g_assert_cmpint (_c1, ==, 0); \ - g_assert_cmpint (_c2, ==, 0); \ - } else { \ - g_assert_cmpint (_c1, ==, -1); \ - g_assert_cmpint (_c2, ==, 1); \ - } \ - \ - /* Compare with self. _strv_cmp_fuzz_input() randomly swapped the arguments (_a1 and _a1x). - * Either way, the arrays must compare equal to their semantically equal alternative. */ \ - g_assert_cmpint (_nm_utils_strv_cmp_n (_a1, _l1, _a1x, _l1), ==, 0); \ - g_assert_cmpint (_nm_utils_strv_cmp_n (_a2, _l2, _a2x, _l2), ==, 0); \ - \ - _strv_cmp_free_deep (_a1_free_deep, _l1); \ - _strv_cmp_free_deep (_a2_free_deep, _l2); \ - } G_STMT_END - - _STRV_CMP (NULL, -1, NULL, -1, TRUE); - - _STRV_CMP (NULL, -1, NULL, 0, FALSE); - _STRV_CMP (NULL, -1, strv0, 0, FALSE); - _STRV_CMP (NULL, -1, strv0, -1, FALSE); - - _STRV_CMP (NULL, 0, NULL, 0, TRUE); - _STRV_CMP (NULL, 0, strv0, 0, TRUE); - _STRV_CMP (NULL, 0, strv0, -1, TRUE); - _STRV_CMP (strv0, 0, strv0, 0, TRUE); - _STRV_CMP (strv0, 0, strv0, -1, TRUE); - _STRV_CMP (strv0, -1, strv0, -1, TRUE); - - _STRV_CMP (NULL, 0, strv1, -1, FALSE); - _STRV_CMP (NULL, 0, strv1, 1, FALSE); - _STRV_CMP (strv0, 0, strv1, -1, FALSE); - _STRV_CMP (strv0, 0, strv1, 1, FALSE); - _STRV_CMP (strv0, -1, strv1, -1, FALSE); - _STRV_CMP (strv0, -1, strv1, 1, FALSE); - - _STRV_CMP (strv1, -1, strv1, 1, TRUE); - _STRV_CMP (strv1, 1, strv1, 1, TRUE); + const char *const strv0[1] = {}; + const char *const strv1[2] = { + "", + }; + +#define _STRV_CMP(a1, l1, a2, l2, equal) \ + G_STMT_START \ + { \ + gssize _l1 = (l1); \ + gssize _l2 = (l2); \ + const char *const * _a1; \ + const char *const * _a2; \ + const char *const * _a1x; \ + const char *const * _a2x; \ + char ** _a1_free_deep = NULL; \ + char ** _a2_free_deep = NULL; \ + gs_free const char **_a1_free_shallow = NULL; \ + gs_free const char **_a2_free_shallow = NULL; \ + int _c1, _c2; \ + \ + _strv_cmp_fuzz_input((a1), _l1, &_a1_free_shallow, &_a1_free_deep, &_a1, &_a1x); \ + _strv_cmp_fuzz_input((a2), _l2, &_a2_free_shallow, &_a2_free_deep, &_a2, &_a2x); \ + \ + _c1 = _nm_utils_strv_cmp_n(_a1, _l1, _a2, _l2); \ + _c2 = _nm_utils_strv_cmp_n(_a2, _l2, _a1, _l1); \ + if (equal) { \ + g_assert_cmpint(_c1, ==, 0); \ + g_assert_cmpint(_c2, ==, 0); \ + } else { \ + g_assert_cmpint(_c1, ==, -1); \ + g_assert_cmpint(_c2, ==, 1); \ + } \ + \ + /* Compare with self. _strv_cmp_fuzz_input() randomly swapped the arguments (_a1 and _a1x). + * Either way, the arrays must compare equal to their semantically equal alternative. */ \ + g_assert_cmpint(_nm_utils_strv_cmp_n(_a1, _l1, _a1x, _l1), ==, 0); \ + g_assert_cmpint(_nm_utils_strv_cmp_n(_a2, _l2, _a2x, _l2), ==, 0); \ + \ + _strv_cmp_free_deep(_a1_free_deep, _l1); \ + _strv_cmp_free_deep(_a2_free_deep, _l2); \ + } \ + G_STMT_END + + _STRV_CMP(NULL, -1, NULL, -1, TRUE); + + _STRV_CMP(NULL, -1, NULL, 0, FALSE); + _STRV_CMP(NULL, -1, strv0, 0, FALSE); + _STRV_CMP(NULL, -1, strv0, -1, FALSE); + + _STRV_CMP(NULL, 0, NULL, 0, TRUE); + _STRV_CMP(NULL, 0, strv0, 0, TRUE); + _STRV_CMP(NULL, 0, strv0, -1, TRUE); + _STRV_CMP(strv0, 0, strv0, 0, TRUE); + _STRV_CMP(strv0, 0, strv0, -1, TRUE); + _STRV_CMP(strv0, -1, strv0, -1, TRUE); + + _STRV_CMP(NULL, 0, strv1, -1, FALSE); + _STRV_CMP(NULL, 0, strv1, 1, FALSE); + _STRV_CMP(strv0, 0, strv1, -1, FALSE); + _STRV_CMP(strv0, 0, strv1, 1, FALSE); + _STRV_CMP(strv0, -1, strv1, -1, FALSE); + _STRV_CMP(strv0, -1, strv1, 1, FALSE); + + _STRV_CMP(strv1, -1, strv1, 1, TRUE); + _STRV_CMP(strv1, 1, strv1, 1, TRUE); } /*****************************************************************************/ static void -_do_strstrip_avoid_copy (const char *str) +_do_strstrip_avoid_copy(const char *str) { - gs_free char *str1 = g_strdup (str); - gs_free char *str2 = g_strdup (str); - gs_free char *str3 = NULL; - gs_free char *str4 = NULL; - const char *s3; - const char *s4; - - if (str1) - g_strstrip (str1); - - nm_strstrip (str2); - - g_assert_cmpstr (str1, ==, str2); - - s3 = nm_strstrip_avoid_copy (str, &str3); - g_assert_cmpstr (str1, ==, s3); - - s4 = nm_strstrip_avoid_copy_a (10, str, &str4); - g_assert_cmpstr (str1, ==, s4); - g_assert (!str == !s4); - g_assert (!s4 || strlen (s4) <= strlen (str)); - if (s4 && s4 == &str[strlen (str) - strlen (s4)]) { - g_assert (!str4); - g_assert (s3 == s4); - } else if (s4 && strlen (s4) >= 10) { - g_assert (str4); - g_assert (s4 == str4); - } else - g_assert (!str4); - - if (!nm_streq0 (str1, str)) - _do_strstrip_avoid_copy (str1); + gs_free char *str1 = g_strdup(str); + gs_free char *str2 = g_strdup(str); + gs_free char *str3 = NULL; + gs_free char *str4 = NULL; + const char * s3; + const char * s4; + + if (str1) + g_strstrip(str1); + + nm_strstrip(str2); + + g_assert_cmpstr(str1, ==, str2); + + s3 = nm_strstrip_avoid_copy(str, &str3); + g_assert_cmpstr(str1, ==, s3); + + s4 = nm_strstrip_avoid_copy_a(10, str, &str4); + g_assert_cmpstr(str1, ==, s4); + g_assert(!str == !s4); + g_assert(!s4 || strlen(s4) <= strlen(str)); + if (s4 && s4 == &str[strlen(str) - strlen(s4)]) { + g_assert(!str4); + g_assert(s3 == s4); + } else if (s4 && strlen(s4) >= 10) { + g_assert(str4); + g_assert(s4 == str4); + } else + g_assert(!str4); + + if (!nm_streq0(str1, str)) + _do_strstrip_avoid_copy(str1); } static void -test_strstrip_avoid_copy (void) +test_strstrip_avoid_copy(void) { - _do_strstrip_avoid_copy (NULL); - _do_strstrip_avoid_copy (""); - _do_strstrip_avoid_copy (" "); - _do_strstrip_avoid_copy (" a "); - _do_strstrip_avoid_copy (" 012345678 "); - _do_strstrip_avoid_copy (" 0123456789 "); - _do_strstrip_avoid_copy (" 01234567890 "); - _do_strstrip_avoid_copy (" 012345678901 "); + _do_strstrip_avoid_copy(NULL); + _do_strstrip_avoid_copy(""); + _do_strstrip_avoid_copy(" "); + _do_strstrip_avoid_copy(" a "); + _do_strstrip_avoid_copy(" 012345678 "); + _do_strstrip_avoid_copy(" 0123456789 "); + _do_strstrip_avoid_copy(" 01234567890 "); + _do_strstrip_avoid_copy(" 012345678901 "); } /*****************************************************************************/ static void -test_nm_utils_bin2hexstr (void) +test_nm_utils_bin2hexstr(void) { - int n_run; - - for (n_run = 0; n_run < 100; n_run++) { - guint8 buf[100]; - guint8 buf2[G_N_ELEMENTS (buf) + 1]; - gsize len = nmtst_get_rand_uint32 () % (G_N_ELEMENTS (buf) + 1); - char strbuf1[G_N_ELEMENTS (buf) * 3]; - gboolean allocate = nmtst_get_rand_bool (); - char delimiter = nmtst_get_rand_bool () ? ':' : '\0'; - gboolean upper_case = nmtst_get_rand_bool (); - gsize expected_strlen; - char *str_hex; - gsize required_len; - gboolean outlen_set; - gsize outlen; - guint8 *bin2; - - nmtst_rand_buf (NULL, buf, len); - - if (len == 0) - expected_strlen = 0; - else if (delimiter != '\0') - expected_strlen = (len * 3u) - 1; - else - expected_strlen = len * 2u; - - g_assert_cmpint (expected_strlen, <, G_N_ELEMENTS (strbuf1)); - - str_hex = nm_utils_bin2hexstr_full (buf, len, delimiter, upper_case, !allocate ? strbuf1 : NULL); - - g_assert (str_hex); - if (!allocate) - g_assert (str_hex == strbuf1); - g_assert_cmpint (strlen (str_hex), ==, expected_strlen); - - g_assert (NM_STRCHAR_ALL (str_hex, ch, (ch >= '0' && ch <= '9') - || ch == delimiter - || ( upper_case - ? (ch >= 'A' && ch <= 'F') - : (ch >= 'a' && ch <= 'f')))); - - required_len = nmtst_get_rand_bool () ? len : 0u; - - outlen_set = required_len == 0 || nmtst_get_rand_bool (); - - memset (buf2, 0, sizeof (buf2)); - - bin2 = nm_utils_hexstr2bin_full (str_hex, - nmtst_get_rand_bool (), - delimiter != '\0' && nmtst_get_rand_bool (), - delimiter != '\0' - ? nmtst_rand_select ((const char *) ":", ":-") - : nmtst_rand_select ((const char *) ":", ":-", "", NULL), - required_len, - buf2, - len, - outlen_set ? &outlen : NULL); - if (len > 0) { - g_assert (bin2); - g_assert (bin2 == buf2); - } else - g_assert (!bin2); - - if (outlen_set) - g_assert_cmpint (outlen, ==, len); - - g_assert_cmpmem (buf, len, buf2, len); - - g_assert (buf2[len] == '\0'); - - if (allocate) - g_free (str_hex); - } + int n_run; + + for (n_run = 0; n_run < 500; n_run++) { + guint8 buf[100]; + guint8 buf2[G_N_ELEMENTS(buf) + 1]; + gsize len = nmtst_get_rand_uint32() % (G_N_ELEMENTS(buf) + 1); + char strbuf1[G_N_ELEMENTS(buf) * 3]; + gboolean allocate = nmtst_get_rand_bool(); + char delimiter = nmtst_get_rand_bool() ? ':' : '\0'; + gboolean upper_case = nmtst_get_rand_bool(); + gboolean hexdigit_pairs_mangled; + gsize expected_strlen; + char * str_hex; + gsize required_len; + gboolean outlen_set; + gsize outlen; + guint8 * bin2; + guint i, j; + + nmtst_rand_buf(NULL, buf, len); + + if (len == 0) + expected_strlen = 0; + else if (delimiter != '\0') + expected_strlen = (len * 3u) - 1; + else + expected_strlen = len * 2u; + + g_assert_cmpint(expected_strlen, <, G_N_ELEMENTS(strbuf1)); + + str_hex = + nm_utils_bin2hexstr_full(buf, len, delimiter, upper_case, !allocate ? strbuf1 : NULL); + + g_assert(str_hex); + if (!allocate) + g_assert(str_hex == strbuf1); + g_assert_cmpint(strlen(str_hex), ==, expected_strlen); + + g_assert(NM_STRCHAR_ALL( + str_hex, + ch, + (ch >= '0' && ch <= '9') || ch == delimiter + || (upper_case ? (ch >= 'A' && ch <= 'F') : (ch >= 'a' && ch <= 'f')))); + + hexdigit_pairs_mangled = FALSE; + if (delimiter && len > 1 && nmtst_get_rand_bool()) { + /* randomly convert "0?" sequences to single digits, so we can get hexdigit_pairs_required + * parameter. */ + g_assert(strlen(str_hex) >= 5); + g_assert(str_hex[2] == delimiter); + i = 0; + j = 0; + for (;;) { + g_assert(g_ascii_isxdigit(str_hex[i])); + g_assert(g_ascii_isxdigit(str_hex[i + 1])); + g_assert(NM_IN_SET(str_hex[i + 2], delimiter, '\0')); + if (str_hex[i] == '0' && nmtst_get_rand_bool()) { + i++; + str_hex[j++] = str_hex[i++]; + hexdigit_pairs_mangled = TRUE; + } else { + str_hex[j++] = str_hex[i++]; + str_hex[j++] = str_hex[i++]; + } + if (str_hex[i] == '\0') { + str_hex[j] = '\0'; + break; + } + g_assert(str_hex[i] == delimiter); + str_hex[j++] = str_hex[i++]; + } + } + + required_len = nmtst_get_rand_bool() ? len : 0u; + + outlen_set = required_len == 0 || nmtst_get_rand_bool(); + + memset(buf2, 0, sizeof(buf2)); + + bin2 = nm_utils_hexstr2bin_full(str_hex, + nmtst_get_rand_bool(), + delimiter != '\0' && nmtst_get_rand_bool(), + !hexdigit_pairs_mangled && nmtst_get_rand_bool(), + delimiter != '\0' + ? nmtst_rand_select((const char *) ":", ":-") + : nmtst_rand_select((const char *) ":", ":-", "", NULL), + required_len, + buf2, + len, + outlen_set ? &outlen : NULL); + if (len > 0) { + g_assert(bin2); + g_assert(bin2 == buf2); + } else + g_assert(!bin2); + + if (outlen_set) + g_assert_cmpint(outlen, ==, len); + + g_assert_cmpmem(buf, len, buf2, len); + + g_assert(buf2[len] == '\0'); + + if (hexdigit_pairs_mangled) { + /* we mangled the hexstr to contain single digits. Trying to parse with + * hexdigit_pairs_required must now fail. */ + bin2 = nm_utils_hexstr2bin_full( + str_hex, + nmtst_get_rand_bool(), + delimiter != '\0' && nmtst_get_rand_bool(), + TRUE, + delimiter != '\0' ? nmtst_rand_select((const char *) ":", ":-") + : nmtst_rand_select((const char *) ":", ":-", "", NULL), + required_len, + buf2, + len, + outlen_set ? &outlen : NULL); + g_assert(!bin2); + } + + if (allocate) + g_free(str_hex); + } } /*****************************************************************************/ static void -test_nm_ref_string (void) +test_nm_ref_string(void) { - nm_auto_ref_string NMRefString *s1 = NULL; - NMRefString *s2; + nm_auto_ref_string NMRefString *s1 = NULL; + NMRefString * s2; - s1 = nm_ref_string_new ("hallo"); - g_assert (s1); - g_assert_cmpstr (s1->str, ==, "hallo"); - g_assert_cmpint (s1->len, ==, strlen ("hallo")); + s1 = nm_ref_string_new("hallo"); + g_assert(s1); + g_assert_cmpstr(s1->str, ==, "hallo"); + g_assert_cmpint(s1->len, ==, strlen("hallo")); - s2 = nm_ref_string_new ("hallo"); - g_assert (s2 == s1); - nm_ref_string_unref (s2); + s2 = nm_ref_string_new("hallo"); + g_assert(s2 == s1); + nm_ref_string_unref(s2); - s2 = nm_ref_string_new (NULL); - g_assert (!s2); - nm_ref_string_unref (s2); + s2 = nm_ref_string_new(NULL); + g_assert(!s2); + nm_ref_string_unref(s2); #define STR_WITH_NUL "hallo\0test\0" - s2 = nm_ref_string_new_len (STR_WITH_NUL, NM_STRLEN (STR_WITH_NUL)); - g_assert (s2); - g_assert_cmpstr (s2->str, ==, "hallo"); - g_assert_cmpint (s2->len, ==, NM_STRLEN (STR_WITH_NUL)); - g_assert_cmpint (s2->len, >, strlen (s2->str)); - g_assert_cmpmem (s2->str, s2->len, STR_WITH_NUL, NM_STRLEN (STR_WITH_NUL)); - g_assert (s2->str[s2->len] == '\0'); - nm_ref_string_unref (s2); + s2 = nm_ref_string_new_len(STR_WITH_NUL, NM_STRLEN(STR_WITH_NUL)); + g_assert(s2); + g_assert_cmpstr(s2->str, ==, "hallo"); + g_assert_cmpint(s2->len, ==, NM_STRLEN(STR_WITH_NUL)); + g_assert_cmpint(s2->len, >, strlen(s2->str)); + g_assert_cmpmem(s2->str, s2->len, STR_WITH_NUL, NM_STRLEN(STR_WITH_NUL)); + g_assert(s2->str[s2->len] == '\0'); + nm_ref_string_unref(s2); +} + +/*****************************************************************************/ + +static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( + _do_string_table_lookup, + int, + { ; }, + { return -1; }, + {"0", 0}, + {"1", 1}, + {"2", 2}, + {"3", 3}, ) + + static void test_string_table_lookup(void) +{ + const char *const args[] = { + NULL, + "0", + "1", + "2", + "3", + "x", + }; + int i; + + for (i = 0; i < G_N_ELEMENTS(args); i++) { + const char *needle = args[i]; + const int val2 = _nm_utils_ascii_str_to_int64(needle, 10, 0, 100, -1); + int val; + + val = _do_string_table_lookup(needle); + g_assert_cmpint(val, ==, val2); + } +} + +/*****************************************************************************/ + +static void +test_nm_utils_get_next_realloc_size(void) +{ + static const struct { + gsize requested; + gsize reserved_true; + gsize reserved_false; + } test_data[] = { + {0, 8, 8}, + {1, 8, 8}, + {8, 8, 8}, + {9, 16, 16}, + {16, 16, 16}, + {17, 32, 32}, + {32, 32, 32}, + {33, 40, 40}, + {40, 40, 40}, + {41, 104, 104}, + {104, 104, 104}, + {105, 232, 232}, + {232, 232, 232}, + {233, 488, 488}, + {488, 488, 488}, + {489, 1000, 1000}, + {1000, 1000, 1000}, + {1001, 2024, 2024}, + {2024, 2024, 2024}, + {2025, 4072, 4072}, + {4072, 4072, 4072}, + {4073, 8168, 8168}, + {8168, 8168, 8168}, + {8169, 12264, 16360}, + {12263, 12264, 16360}, + {12264, 12264, 16360}, + {12265, 16360, 16360}, + {16360, 16360, 16360}, + {16361, 20456, 32744}, + {20456, 20456, 32744}, + {20457, 24552, 32744}, + {24552, 24552, 32744}, + {24553, 28648, 32744}, + {28648, 28648, 32744}, + {28649, 32744, 32744}, + {32744, 32744, 32744}, + {32745, 36840, 65512}, + {36840, 36840, 65512}, + {G_MAXSIZE - 0x1000u, G_MAXSIZE, G_MAXSIZE}, + {G_MAXSIZE - 25u, G_MAXSIZE, G_MAXSIZE}, + {G_MAXSIZE - 24u, G_MAXSIZE, G_MAXSIZE}, + {G_MAXSIZE - 1u, G_MAXSIZE, G_MAXSIZE}, + {G_MAXSIZE, G_MAXSIZE, G_MAXSIZE}, + {NM_UTILS_GET_NEXT_REALLOC_SIZE_32, + NM_UTILS_GET_NEXT_REALLOC_SIZE_32, + NM_UTILS_GET_NEXT_REALLOC_SIZE_32}, + {NM_UTILS_GET_NEXT_REALLOC_SIZE_40, + NM_UTILS_GET_NEXT_REALLOC_SIZE_40, + NM_UTILS_GET_NEXT_REALLOC_SIZE_40}, + {NM_UTILS_GET_NEXT_REALLOC_SIZE_104, + NM_UTILS_GET_NEXT_REALLOC_SIZE_104, + NM_UTILS_GET_NEXT_REALLOC_SIZE_104}, + {NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, + NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, + NM_UTILS_GET_NEXT_REALLOC_SIZE_1000}, + }; + guint i; + + G_STATIC_ASSERT_EXPR(NM_UTILS_GET_NEXT_REALLOC_SIZE_104 == 104u); + G_STATIC_ASSERT_EXPR(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000 == 1000u); + + for (i = 0; i < G_N_ELEMENTS(test_data) + 5000u; i++) { + gsize requested0; + + if (i < G_N_ELEMENTS(test_data)) + requested0 = test_data[i].requested; + else { + /* find some interesting random values for testing. */ + switch (nmtst_get_rand_uint32() % 5) { + case 0: + requested0 = nmtst_get_rand_size(); + break; + case 1: + /* values close to G_MAXSIZE. */ + requested0 = G_MAXSIZE - (nmtst_get_rand_uint32() % 12000u); + break; + case 2: + /* values around G_MAXSIZE/2. */ + requested0 = (G_MAXSIZE / 2u) + 6000u - (nmtst_get_rand_uint32() % 12000u); + break; + case 3: + /* values around powers of 2. */ + requested0 = (((gsize) 1) << (nmtst_get_rand_uint32() % (sizeof(gsize) * 8u))) + + 6000u - (nmtst_get_rand_uint32() % 12000u); + break; + case 4: + /* values around 4k borders. */ + requested0 = (nmtst_get_rand_size() & ~((gsize) 0xFFFu)) + 30u + - (nmtst_get_rand_uint32() % 60u); + break; + default: + g_assert_not_reached(); + } + } + + { + const gsize requested = requested0; + const gsize reserved_true = nm_utils_get_next_realloc_size(TRUE, requested); + const gsize reserved_false = nm_utils_get_next_realloc_size(FALSE, requested); + + g_assert_cmpuint(reserved_true, >, 0); + g_assert_cmpuint(reserved_false, >, 0); + g_assert_cmpuint(reserved_true, >=, requested); + g_assert_cmpuint(reserved_false, >=, requested); + g_assert_cmpuint(reserved_false, >=, reserved_true); + + if (i < G_N_ELEMENTS(test_data)) { + g_assert_cmpuint(reserved_true, ==, test_data[i].reserved_true); + g_assert_cmpuint(reserved_false, ==, test_data[i].reserved_false); + } + + /* reserved_false is generally the next power of two - 24. */ + if (reserved_false == G_MAXSIZE) + g_assert_cmpuint(requested, >, G_MAXSIZE / 2u - 24u); + else { + g_assert_cmpuint(reserved_false, <=, G_MAXSIZE - 24u); + if (reserved_false >= 40) { + const gsize _pow2 = reserved_false + 24u; + + /* reserved_false must always be a power of two minus 24. */ + g_assert_cmpuint(_pow2, >=, 64u); + g_assert_cmpuint(_pow2, >, requested); + g_assert(nm_utils_is_power_of_two(_pow2)); + + /* but _pow2/2 must also be smaller than what we requested. */ + g_assert_cmpuint(_pow2 / 2u - 24u, <, requested); + } else { + /* smaller values are hard-coded. */ + } + } + + /* reserved_true is generally the next 4k border - 24. */ + if (reserved_true == G_MAXSIZE) + g_assert_cmpuint(requested, >, G_MAXSIZE - 0x1000u - 24u); + else { + g_assert_cmpuint(reserved_true, <=, G_MAXSIZE - 24u); + if (reserved_true > 8168u) { + const gsize page_border = reserved_true + 24u; + + /* reserved_true must always be aligned to 4k (minus 24). */ + g_assert_cmpuint(page_border % 0x1000u, ==, 0); + if (requested > 0x1000u - 24u) { + /* page_border not be more than 4k above requested. */ + g_assert_cmpuint(page_border, >=, 0x1000u - 24u); + g_assert_cmpuint(page_border - 0x1000u - 24u, <, requested); + } + } else { + /* for smaller sizes, reserved_true and reserved_false are the same. */ + g_assert_cmpuint(reserved_true, ==, reserved_false); + } + } + } + } } /*****************************************************************************/ -static -NM_UTILS_STRING_TABLE_LOOKUP_DEFINE ( - _do_string_table_lookup, - int, - { ; }, - { return -1; }, - { "0", 0 }, - { "1", 1 }, - { "2", 2 }, - { "3", 3 }, -) +static void +test_nm_str_buf(void) +{ + guint i_run; + + for (i_run = 0; TRUE; i_run++) { + nm_auto_str_buf NMStrBuf strbuf = {}; + nm_auto_free_gstring GString *gstr = NULL; + int i, j, k; + int c; + + nm_str_buf_init(&strbuf, nmtst_get_rand_uint32() % 200u + 1u, nmtst_get_rand_bool()); + + if (i_run < 1000) { + c = nmtst_get_rand_word_length(NULL); + for (i = 0; i < c; i++) + nm_str_buf_append_c(&strbuf, '0' + (i % 10)); + gstr = g_string_new(nm_str_buf_get_str(&strbuf)); + j = nmtst_get_rand_uint32() % (strbuf.len + 1); + k = nmtst_get_rand_uint32() % (strbuf.len - j + 2) - 1; + + nm_str_buf_erase(&strbuf, j, k, nmtst_get_rand_bool()); + g_string_erase(gstr, j, k); + g_assert_cmpstr(gstr->str, ==, nm_str_buf_get_str(&strbuf)); + } else + return; + } +} + +/*****************************************************************************/ static void -test_string_table_lookup (void) +test_nm_utils_parse_next_line(void) { - const char *const args[] = { NULL, "0", "1", "2", "3", "x", }; - int i; + const char *data; + const char *data0; + gsize data_len; + const char *line_start; + gsize line_len; + int i_run; + gsize j, k; + + data = NULL; + data_len = 0; + g_assert(!nm_utils_parse_next_line(&data, &data_len, &line_start, &line_len)); + + for (i_run = 0; i_run < 1000; i_run++) { + gs_unref_ptrarray GPtrArray *strv = g_ptr_array_new_with_free_func(g_free); + gs_unref_ptrarray GPtrArray *strv2 = g_ptr_array_new_with_free_func(g_free); + gsize strv_len = nmtst_get_rand_word_length(NULL); + nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(0, nmtst_get_rand_bool()); + + /* create a list of random words. */ + for (j = 0; j < strv_len; j++) { + gsize w_len = nmtst_get_rand_word_length(NULL); + NMStrBuf w_buf = + NM_STR_BUF_INIT(nmtst_get_rand_uint32() % (w_len + 1), nmtst_get_rand_bool()); + + for (k = 0; k < w_len; k++) + nm_str_buf_append_c(&w_buf, '0' + (k % 10)); + nm_str_buf_maybe_expand(&w_buf, 1, TRUE); + g_ptr_array_add(strv, nm_str_buf_finalize(&w_buf, NULL)); + } + + /* join the list of random words with (random) line delimiters + * ("\0", "\n", "\r" or EOF). */ + for (j = 0; j < strv_len; j++) { + nm_str_buf_append(&strbuf, strv->pdata[j]); +again: + switch (nmtst_get_rand_uint32() % 5) { + case 0: + nm_str_buf_append_c(&strbuf, '\0'); + break; + case 1: + if (strbuf.len > 0 + && (nm_str_buf_get_str_unsafe(&strbuf))[strbuf.len - 1] == '\r') { + /* the previous line was empty and terminated by "\r". We + * must not join with "\n". Retry. */ + goto again; + } + nm_str_buf_append_c(&strbuf, '\n'); + break; + case 2: + nm_str_buf_append_c(&strbuf, '\r'); + break; + case 3: + nm_str_buf_append(&strbuf, "\r\n"); + break; + case 4: + /* the last word randomly is delimited or not, but not if the last + * word is "". */ + if (j + 1 < strv_len) { + /* it's not the last word. Retry. */ + goto again; + } + g_assert(j == strv_len - 1); + if (((const char *) strv->pdata[j])[0] == '\0') { + /* if the last word was "", we need a delimiter (to parse it back). + * Retry. */ + goto again; + } + /* The final delimiter gets omitted. It's EOF. */ + break; + } + } + + data0 = nm_str_buf_get_str_unsafe(&strbuf); + if (!data0 && nmtst_get_rand_bool()) { + nm_str_buf_maybe_expand(&strbuf, 1, TRUE); + data0 = nm_str_buf_get_str_unsafe(&strbuf); + g_assert(data0); + } + data_len = strbuf.len; + g_assert((data_len > 0 && data0) || data_len == 0); + data = data0; + while (nm_utils_parse_next_line(&data, &data_len, &line_start, &line_len)) { + g_assert(line_start); + g_assert(line_start >= data0); + g_assert(line_start < &data0[strbuf.len]); + g_assert(!memchr(line_start, '\0', line_len)); + g_ptr_array_add(strv2, g_strndup(line_start, line_len)); + } + g_assert(data_len == 0); + if (data0) + g_assert(data == &data0[strbuf.len]); + else + g_assert(!data); + + g_assert(_nm_utils_strv_cmp_n((const char *const *) strv->pdata, + strv->len, + (const char *const *) strv2->pdata, + strv2->len) + == 0); + } +} - for (i = 0; i < G_N_ELEMENTS (args); i++) { - const char *needle = args[i]; - const int val2 = _nm_utils_ascii_str_to_int64 (needle, 10, 0, 100, -1); - int val; +/*****************************************************************************/ - val = _do_string_table_lookup (needle); - g_assert_cmpint (val, ==, val2); - } +static void +test_in_strset_ascii_case(void) +{ + const char *x; + + x = NULL; + g_assert(NM_IN_STRSET_ASCII_CASE(x, NULL)); + g_assert(NM_IN_STRSET_ASCII_CASE(x, NULL, "b")); + g_assert(!NM_IN_STRSET_ASCII_CASE(x, "b")); + + x = "b"; + g_assert(NM_IN_STRSET(x, "b")); + g_assert(NM_IN_STRSET_ASCII_CASE(x, "b")); + g_assert(!NM_IN_STRSET(x, "B")); + g_assert(NM_IN_STRSET_ASCII_CASE(x, "B")); } /*****************************************************************************/ static void -test_nm_utils_get_next_realloc_size (void) +test_is_specific_hostname(void) { - static const struct { - gsize requested; - gsize reserved_true; - gsize reserved_false; - } test_data[] = { - { 0, 8, 8 }, - { 1, 8, 8 }, - { 8, 8, 8 }, - { 9, 16, 16 }, - { 16, 16, 16 }, - { 17, 32, 32 }, - { 32, 32, 32 }, - { 33, 40, 40 }, - { 40, 40, 40 }, - { 41, 104, 104 }, - { 104, 104, 104 }, - { 105, 232, 232 }, - { 232, 232, 232 }, - { 233, 488, 488 }, - { 488, 488, 488 }, - { 489, 1000, 1000 }, - { 1000, 1000, 1000 }, - { 1001, 2024, 2024 }, - { 2024, 2024, 2024 }, - { 2025, 4072, 4072 }, - { 4072, 4072, 4072 }, - { 4073, 8168, 8168 }, - { 8168, 8168, 8168 }, - { 8169, 12264, 16360 }, - { 12263, 12264, 16360 }, - { 12264, 12264, 16360 }, - { 12265, 16360, 16360 }, - { 16360, 16360, 16360 }, - { 16361, 20456, 32744 }, - { 20456, 20456, 32744 }, - { 20457, 24552, 32744 }, - { 24552, 24552, 32744 }, - { 24553, 28648, 32744 }, - { 28648, 28648, 32744 }, - { 28649, 32744, 32744 }, - { 32744, 32744, 32744 }, - { 32745, 36840, 65512 }, - { 36840, 36840, 65512 }, - { G_MAXSIZE - 0x1000u, G_MAXSIZE, G_MAXSIZE }, - { G_MAXSIZE - 25u, G_MAXSIZE, G_MAXSIZE }, - { G_MAXSIZE - 24u, G_MAXSIZE, G_MAXSIZE }, - { G_MAXSIZE - 1u, G_MAXSIZE, G_MAXSIZE }, - { G_MAXSIZE, G_MAXSIZE, G_MAXSIZE }, - { NM_UTILS_GET_NEXT_REALLOC_SIZE_104, NM_UTILS_GET_NEXT_REALLOC_SIZE_104, NM_UTILS_GET_NEXT_REALLOC_SIZE_104 }, - { NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, NM_UTILS_GET_NEXT_REALLOC_SIZE_1000 }, - }; - guint i; - - G_STATIC_ASSERT_EXPR (NM_UTILS_GET_NEXT_REALLOC_SIZE_104 == 104u); - G_STATIC_ASSERT_EXPR (NM_UTILS_GET_NEXT_REALLOC_SIZE_1000 == 1000u); - - for (i = 0; i < G_N_ELEMENTS (test_data) + 5000u; i++) { - gsize requested0; - - if (i < G_N_ELEMENTS (test_data)) - requested0 = test_data[i].requested; - else { - /* find some interesting random values for testing. */ - switch (nmtst_get_rand_uint32 () % 5) { - case 0: - requested0 = nmtst_get_rand_size (); - break; - case 1: - /* values close to G_MAXSIZE. */ - requested0 = G_MAXSIZE - (nmtst_get_rand_uint32 () % 12000u); - break; - case 2: - /* values around G_MAXSIZE/2. */ - requested0 = (G_MAXSIZE / 2u) + 6000u - (nmtst_get_rand_uint32 () % 12000u); - break; - case 3: - /* values around powers of 2. */ - requested0 = (((gsize) 1) << (nmtst_get_rand_uint32 () % (sizeof (gsize) * 8u))) + 6000u - (nmtst_get_rand_uint32 () % 12000u); - break; - case 4: - /* values around 4k borders. */ - requested0 = (nmtst_get_rand_size () & ~((gsize) 0xFFFu)) + 30u - (nmtst_get_rand_uint32 () % 60u); - break; - default: g_assert_not_reached (); - } - } - - { - const gsize requested = requested0; - const gsize reserved_true = nm_utils_get_next_realloc_size (TRUE, requested); - const gsize reserved_false = nm_utils_get_next_realloc_size (FALSE, requested); - - g_assert_cmpuint (reserved_true, >, 0); - g_assert_cmpuint (reserved_false, >, 0); - g_assert_cmpuint (reserved_true, >=, requested); - g_assert_cmpuint (reserved_false, >=, requested); - g_assert_cmpuint (reserved_false, >=, reserved_true); - - if (i < G_N_ELEMENTS (test_data)) { - g_assert_cmpuint (reserved_true, ==, test_data[i].reserved_true); - g_assert_cmpuint (reserved_false, ==, test_data[i].reserved_false); - } - - /* reserved_false is generally the next power of two - 24. */ - if (reserved_false == G_MAXSIZE) - g_assert_cmpuint (requested, >, G_MAXSIZE / 2u - 24u); - else { - g_assert_cmpuint (reserved_false, <=, G_MAXSIZE - 24u); - if (reserved_false >= 40) { - const gsize _pow2 = reserved_false + 24u; - - /* reserved_false must always be a power of two minus 24. */ - g_assert_cmpuint (_pow2, >=, 64u); - g_assert_cmpuint (_pow2, >, requested); - g_assert (nm_utils_is_power_of_two (_pow2)); - - /* but _pow2/2 must also be smaller than what we requested. */ - g_assert_cmpuint (_pow2 / 2u - 24u, <, requested); - } else { - /* smaller values are hard-coded. */ - } - } - - /* reserved_true is generally the next 4k border - 24. */ - if (reserved_true == G_MAXSIZE) - g_assert_cmpuint (requested, >, G_MAXSIZE - 0x1000u - 24u); - else { - g_assert_cmpuint (reserved_true, <=, G_MAXSIZE - 24u); - if (reserved_true > 8168u) { - const gsize page_border = reserved_true + 24u; - - /* reserved_true must always be aligned to 4k (minus 24). */ - g_assert_cmpuint (page_border % 0x1000u, ==, 0); - if (requested > 0x1000u - 24u) { - /* page_border not be more than 4k above requested. */ - g_assert_cmpuint (page_border, >=, 0x1000u - 24u); - g_assert_cmpuint (page_border - 0x1000u - 24u, <, requested); - } - } else { - /* for smaller sizes, reserved_true and reserved_false are the same. */ - g_assert_cmpuint (reserved_true, ==, reserved_false); - } - } - - } - } + g_assert(!nm_utils_is_specific_hostname(NULL)); + g_assert(!nm_utils_is_specific_hostname("")); + g_assert(!nm_utils_is_specific_hostname("(none)")); + g_assert(nm_utils_is_specific_hostname("(NONE)")); + + g_assert(!nm_utils_is_specific_hostname("localhost")); + g_assert(!nm_utils_is_specific_hostname("lOcalHost")); + g_assert(!nm_utils_is_specific_hostname("LOCALHOST")); + + g_assert(!nm_utils_is_specific_hostname("LOCALHOST.localdomain")); + + g_assert(nm_utils_is_specific_hostname("xlocalhost")); + g_assert(nm_utils_is_specific_hostname("lOcalHxost")); + g_assert(nm_utils_is_specific_hostname("LOCALxHOST")); + + g_assert(!nm_utils_is_specific_hostname("foo.LOCALHOST")); + g_assert(!nm_utils_is_specific_hostname("foo.LOCALHOsT6.")); + g_assert(!nm_utils_is_specific_hostname("foo.LOCALHOsT6.localdomain6")); + g_assert(!nm_utils_is_specific_hostname(".LOCALHOsT6.localdomain6")); + g_assert(!nm_utils_is_specific_hostname("LOCALHOsT6.localdomain6")); + g_assert(!nm_utils_is_specific_hostname("LOCALHOsT6.localdomain6.")); + g_assert(nm_utils_is_specific_hostname("LOCALHOsT6.localdomain.")); + + g_assert(nm_utils_is_specific_hostname(" ")); } /*****************************************************************************/ static void -test_nm_str_buf (void) +test_strv_dup_packed(void) { - guint i_run; - - for (i_run = 0; TRUE; i_run++) { - nm_auto_str_buf NMStrBuf strbuf = { }; - nm_auto_free_gstring GString *gstr = NULL; - int i, j, k; - int c; - - nm_str_buf_init (&strbuf, - nmtst_get_rand_uint32 () % 200u + 1u, - nmtst_get_rand_bool ()); - - if (i_run < 1000) { - c = nmtst_get_rand_word_length (NULL); - for (i = 0; i < c; i++) - nm_str_buf_append_c (&strbuf, '0' + (i % 10)); - gstr = g_string_new (nm_str_buf_get_str (&strbuf)); - j = nmtst_get_rand_uint32 () % (strbuf.len + 1); - k = nmtst_get_rand_uint32 () % (strbuf.len - j + 2) - 1; - - nm_str_buf_erase (&strbuf, j, k, nmtst_get_rand_bool ()); - g_string_erase (gstr, j, k); - g_assert_cmpstr (gstr->str, ==, nm_str_buf_get_str (&strbuf)); - } else - return; - } + gs_unref_ptrarray GPtrArray *src = NULL; + int i_run; + + src = g_ptr_array_new_with_free_func(g_free); + + for (i_run = 0; i_run < 500; i_run++) { + const int strv_len = nmtst_get_rand_word_length(NULL); + gs_free const char **strv_cpy = NULL; + const char *const * strv_src; + int i, j; + + g_ptr_array_set_size(src, 0); + for (i = 0; i < strv_len; i++) { + const int word_len = nmtst_get_rand_word_length(NULL); + NMStrBuf sbuf = NM_STR_BUF_INIT(0, nmtst_get_rand_bool()); + + for (j = 0; j < word_len; j++) + nm_str_buf_append_c(&sbuf, 'a' + (nmtst_get_rand_uint32() % 20)); + + g_ptr_array_add(src, nm_str_buf_finalize(&sbuf, NULL) ?: g_new0(char, 1)); + } + g_ptr_array_add(src, NULL); + + strv_src = (const char *const *) src->pdata; + g_assert(strv_src); + g_assert(NM_PTRARRAY_LEN(strv_src) == strv_len); + + strv_cpy = + nm_utils_strv_dup_packed(strv_src, + nmtst_get_rand_bool() ? (gssize) strv_len : (gssize) -1); + if (strv_len == 0) + g_assert(!strv_cpy); + else + g_assert(strv_cpy); + g_assert(NM_PTRARRAY_LEN(strv_cpy) == strv_len); + if (strv_cpy) + g_assert(_nm_utils_strv_equal((char **) strv_cpy, (char **) strv_src)); + } +} + +/*****************************************************************************/ + +static int +_hash_func_cmp_direct(gconstpointer a, gconstpointer b, gpointer user_data) +{ + NM_CMP_DIRECT(GPOINTER_TO_INT(a), GPOINTER_TO_INT(b)); + return 0; +} + +static void +test_utils_hashtable_cmp(void) +{ + static struct { + int val_i; + const char *val_s; + } vals[] = { + { + 0, + "0", + }, + { + 1, + "1", + }, + { + 2, + "2", + }, + { + 3, + "3", + }, + { + 4, + "4", + }, + { + 5, + "5", + }, + { + 6, + "6", + }, + { + 7, + "7", + }, + { + 8, + "8", + }, + { + 9, + "9", + }, + { + 0, + "a", + }, + { + 1, + "a", + }, + { + 2, + "a", + }, + { + 3, + "a", + }, + { + 4, + "a", + }, + { + 5, + "a", + }, + { + 0, + "0", + }, + { + 0, + "1", + }, + { + 0, + "2", + }, + { + 0, + "3", + }, + { + 0, + "4", + }, + { + 0, + "5", + }, + }; + guint test_run; + int is_num_key; + + for (test_run = 0; test_run < 30; test_run++) { + for (is_num_key = 0; is_num_key < 2; is_num_key++) { + GHashFunc func_key_hash = is_num_key ? nm_direct_hash : nm_str_hash; + GEqualFunc func_key_equal = is_num_key ? g_direct_equal : g_str_equal; + GCompareDataFunc func_key_cmp = + is_num_key ? _hash_func_cmp_direct : (GCompareDataFunc) nm_strcmp_with_data; + GCompareDataFunc func_val_cmp = + !is_num_key ? _hash_func_cmp_direct : (GCompareDataFunc) nm_strcmp_with_data; + gs_unref_hashtable GHashTable *h1 = NULL; + gs_unref_hashtable GHashTable *h2 = NULL; + gboolean has_same_keys; + guint i, n; + + h1 = g_hash_table_new(func_key_hash, func_key_equal); + h2 = g_hash_table_new(func_key_hash, func_key_equal); + + n = nmtst_get_rand_word_length(NULL); + for (i = 0; i < n; i++) { + typeof(vals[0]) *v = &vals[nmtst_get_rand_uint32() % G_N_ELEMENTS(vals)]; + gconstpointer v_key = is_num_key ? GINT_TO_POINTER(v->val_i) : v->val_s; + gconstpointer v_val = !is_num_key ? GINT_TO_POINTER(v->val_i) : v->val_s; + + g_hash_table_insert(h1, (gpointer) v_key, (gpointer) v_val); + g_hash_table_insert(h2, (gpointer) v_key, (gpointer) v_val); + } + + g_assert(nm_utils_hashtable_same_keys(h1, h2)); + g_assert(nm_utils_hashtable_equal(h1, h2, NULL, NULL)); + g_assert(nm_utils_hashtable_equal(h1, h2, func_val_cmp, NULL)); + g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, NULL, NULL) == 0); + g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, NULL, NULL) == 0); + g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, func_val_cmp, NULL) == 0); + g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, func_val_cmp, NULL) == 0); + + n = nmtst_get_rand_word_length(NULL) + 1; + has_same_keys = TRUE; + for (i = 0; i < n; i++) { +again: +{ + typeof(vals[0]) *v = &vals[nmtst_get_rand_uint32() % G_N_ELEMENTS(vals)]; + gconstpointer v_key = is_num_key ? GINT_TO_POINTER(v->val_i) : v->val_s; + gconstpointer v_val = !is_num_key ? GINT_TO_POINTER(v->val_i) : v->val_s; + gpointer v_key2; + gpointer v_val2; + + if (g_hash_table_lookup_extended(h1, v_key, &v_key2, &v_val2)) { + g_assert(func_key_cmp(v_key, v_key2, NULL) == 0); + if (func_val_cmp(v_val, v_val2, NULL) == 0) + goto again; + } else + has_same_keys = FALSE; + + g_hash_table_insert(h2, (gpointer) v_key, (gpointer) v_val); +} + } + + if (has_same_keys) { + g_assert(nm_utils_hashtable_same_keys(h1, h2)); + g_assert(nm_utils_hashtable_equal(h1, h2, NULL, NULL)); + g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, NULL, NULL) == 0); + g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, NULL, NULL) == 0); + } else { + g_assert(!nm_utils_hashtable_same_keys(h1, h2)); + g_assert(!nm_utils_hashtable_equal(h1, h2, NULL, NULL)); + g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, NULL, NULL) != 0); + g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, NULL, NULL) != 0); + } + g_assert(!nm_utils_hashtable_equal(h1, h2, func_val_cmp, NULL)); + g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, func_val_cmp, NULL) != 0); + g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, func_val_cmp, NULL) != 0); + } + } } /*****************************************************************************/ -NMTST_DEFINE (); +NMTST_DEFINE(); -int main (int argc, char **argv) +int +main(int argc, char **argv) { - nmtst_init (&argc, &argv, TRUE); - - g_test_add_func ("/general/test_gpid", test_gpid); - g_test_add_func ("/general/test_monotonic_timestamp", test_monotonic_timestamp); - g_test_add_func ("/general/test_nmhash", test_nmhash); - g_test_add_func ("/general/test_nm_make_strv", test_make_strv); - g_test_add_func ("/general/test_nm_strdup_int", test_nm_strdup_int); - g_test_add_func ("/general/test_nm_strndup_a", test_nm_strndup_a); - g_test_add_func ("/general/test_nm_ip4_addr_is_localhost", test_nm_ip4_addr_is_localhost); - g_test_add_func ("/general/test_unaligned", test_unaligned); - g_test_add_func ("/general/test_strv_cmp", test_strv_cmp); - g_test_add_func ("/general/test_strstrip_avoid_copy", test_strstrip_avoid_copy); - g_test_add_func ("/general/test_nm_utils_bin2hexstr", test_nm_utils_bin2hexstr); - g_test_add_func ("/general/test_nm_ref_string", test_nm_ref_string); - g_test_add_func ("/general/test_string_table_lookup", test_string_table_lookup); - g_test_add_func ("/general/test_nm_utils_get_next_realloc_size", test_nm_utils_get_next_realloc_size); - g_test_add_func ("/general/test_nm_str_buf", test_nm_str_buf); - - return g_test_run (); + nmtst_init(&argc, &argv, TRUE); + + g_test_add_func("/general/test_gpid", test_gpid); + g_test_add_func("/general/test_monotonic_timestamp", test_monotonic_timestamp); + g_test_add_func("/general/test_nmhash", test_nmhash); + g_test_add_func("/general/test_nm_make_strv", test_make_strv); + g_test_add_func("/general/test_nm_strdup_int", test_nm_strdup_int); + g_test_add_func("/general/test_nm_strndup_a", test_nm_strndup_a); + g_test_add_func("/general/test_nm_ip4_addr_is_localhost", test_nm_ip4_addr_is_localhost); + g_test_add_func("/general/test_unaligned", test_unaligned); + g_test_add_func("/general/test_strv_cmp", test_strv_cmp); + g_test_add_func("/general/test_strstrip_avoid_copy", test_strstrip_avoid_copy); + g_test_add_func("/general/test_nm_utils_bin2hexstr", test_nm_utils_bin2hexstr); + g_test_add_func("/general/test_nm_ref_string", test_nm_ref_string); + g_test_add_func("/general/test_string_table_lookup", test_string_table_lookup); + g_test_add_func("/general/test_nm_utils_get_next_realloc_size", + test_nm_utils_get_next_realloc_size); + g_test_add_func("/general/test_nm_str_buf", test_nm_str_buf); + g_test_add_func("/general/test_nm_utils_parse_next_line", test_nm_utils_parse_next_line); + g_test_add_func("/general/test_in_strset_ascii_case", test_in_strset_ascii_case); + g_test_add_func("/general/test_is_specific_hostname", test_is_specific_hostname); + g_test_add_func("/general/test_strv_dup_packed", test_strv_dup_packed); + g_test_add_func("/general/test_utils_hashtable_cmp", test_utils_hashtable_cmp); + + return g_test_run(); } |