summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-07-09 13:49:25 +0200
committerThomas Haller <thaller@redhat.com>2020-07-09 13:49:25 +0200
commit341111ff315f69363a4aec1081303733fcabe969 (patch)
tree1099ecbc315ea9e152723f2010a9fc4fdd77d384
parent3e5fc04df320486b0f395fe6898c86f4c0144e05 (diff)
parentca7bb15591bb585156bcf17aa3c43817605b05ee (diff)
downloadNetworkManager-341111ff315f69363a4aec1081303733fcabe969.tar.gz
libnm,json: merge branch 'th/libnm_jansson-2'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/559
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am45
-rw-r--r--config.h.meson3
-rw-r--r--configure.ac21
-rw-r--r--libnm-core/meson.build6
-rw-r--r--libnm-core/nm-json.c110
-rw-r--r--libnm-core/nm-json.h39
-rw-r--r--libnm-core/nm-team-utils.c130
-rw-r--r--libnm-core/nm-utils.c30
-rw-r--r--libnm-core/tests/test-general.c185
-rw-r--r--libnm-core/tests/test-keyfile.c3
-rw-r--r--libnm-core/tests/test-setting.c35
-rw-r--r--meson.build12
-rw-r--r--meson_options.txt1
-rw-r--r--shared/nm-glib-aux/nm-jansson.h105
-rw-r--r--shared/nm-glib-aux/nm-json-aux.c155
-rw-r--r--shared/nm-glib-aux/nm-json-aux.h297
-rw-r--r--shared/nm-glib-aux/tests/meson.build42
-rw-r--r--shared/nm-glib-aux/tests/test-json-aux.c163
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c3
20 files changed, 857 insertions, 529 deletions
diff --git a/.gitignore b/.gitignore
index 5cb43a0374..919b1830c9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -131,6 +131,7 @@ test-*.trs
/examples/C/qt/monitor-nm-running
/examples/C/qt/monitor-nm-running.moc
+/shared/nm-glib-aux/tests/test-json-aux
/shared/nm-glib-aux/tests/test-shared-general
/shared/nm-version-macros.h
diff --git a/Makefile.am b/Makefile.am
index e6d55b0bc1..01fd835e17 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -642,6 +642,39 @@ shared_nm_glib_aux_tests_test_shared_general_LDADD = \
###############################################################################
+if WITH_JANSSON
+
+check_programs += shared/nm-glib-aux/tests/test-json-aux
+
+shared_nm_glib_aux_tests_test_json_aux_CPPFLAGS = \
+ $(dflt_cppflags) \
+ -I$(srcdir)/shared \
+ -DNETWORKMANAGER_COMPILATION_TEST \
+ -DNETWORKMANAGER_COMPILATION='(NM_NETWORKMANAGER_COMPILATION_GLIB|NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG)' \
+ $(CODE_COVERAGE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(JANSSON_CFLAGS) \
+ $(SANITIZER_LIB_CFLAGS) \
+ $(NULL)
+
+shared_nm_glib_aux_tests_test_json_aux_LDFLAGS = \
+ $(CODE_COVERAGE_LDFLAGS) \
+ $(SANITIZER_EXEC_LDFLAGS) \
+ $(NULL)
+
+shared_nm_glib_aux_tests_test_json_aux_LDADD = \
+ $(JANSSON_LIBS) \
+ shared/nm-glib-aux/libnm-glib-aux.la \
+ shared/systemd/libnm-systemd-logging-stub.la \
+ shared/nm-std-aux/libnm-std-aux.la \
+ shared/libcsiphash.la \
+ $(GLIB_LIBS) \
+ $(NULL)
+
+endif
+
+###############################################################################
+
noinst_LTLIBRARIES += introspection/libnmdbus.la
introspection_libnmdbus_la_CPPFLAGS = $(GLIB_CFLAGS)
@@ -1031,13 +1064,6 @@ libnm_core_lib_c_real = \
libnm-core/nm-vpn-plugin-info.c \
$(NULL)
-if WITH_JSON_VALIDATION
-libnm_core_lib_h_priv += \
- libnm-core/nm-json.h
-libnm_core_lib_c_real += \
- libnm-core/nm-json.c
-endif
-
libnm_core_lib_c_mkenums = \
libnm-core/nm-core-enum-types.c
@@ -1092,11 +1118,6 @@ libnm_core_libnm_core_la_CPPFLAGS = \
-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE \
$(NULL)
-if WITH_JSON_VALIDATION
-libnm_core_libnm_core_la_CPPFLAGS += $(JANSSON_CFLAGS)
-libnm_core_libnm_core_la_CPPFLAGS += -fcommon
-endif
-
libnm_core_libnm_core_la_SOURCES = \
$(libnm_core_lib_h_pub_real) \
$(libnm_core_lib_h_priv) \
diff --git a/config.h.meson b/config.h.meson
index b421ee1e71..bb5458aa64 100644
--- a/config.h.meson
+++ b/config.h.meson
@@ -212,9 +212,6 @@
/* Define if JANSSON is enabled */
#mesondefine WITH_JANSSON
-/* Define if JSON validation in libnm is enabled */
-#mesondefine WITH_JSON_VALIDATION
-
/* Define if you have libpsl */
#mesondefine WITH_LIBPSL
diff --git a/configure.ac b/configure.ac
index 1e6823b494..86f91e21fe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -583,7 +583,7 @@ PKG_CHECK_MODULES(UUID, uuid)
# Teamd control checks
-PKG_CHECK_MODULES(JANSSON, [jansson >= 2.5], [have_jansson=yes], [have_jansson=no])
+PKG_CHECK_MODULES(JANSSON, [jansson >= 2.7], [have_jansson=yes], [have_jansson=no])
if test "$have_jansson" = "yes"; then
AC_DEFINE(WITH_JANSSON, 1, [Define if JANSSON is enabled])
@@ -596,6 +596,8 @@ if test "$have_jansson" = "yes"; then
fi
AC_DEFINE_UNQUOTED(JANSSON_SONAME, "$JANSSON_SONAME", [Define to path to the Jansson shared library])
else
+ have_jansson=no
+ JANSSON_SONAME=
AC_DEFINE(WITH_JANSSON, 0, [Define if JANSSON is enabled])
fi
AM_CONDITIONAL(WITH_JANSSON, test "${have_jansson}" = "yes")
@@ -622,21 +624,6 @@ if test "${enable_teamdctl}" = "yes"; then
fi
AM_CONDITIONAL(WITH_TEAMDCTL, test "${enable_teamdctl}" = "yes")
-# Jansson for team configuration validation
-AC_ARG_ENABLE(json-validation,
- AS_HELP_STRING([--enable-json-validation], [Enable JSON validation in libnm]),
- [enable_json_validation=${enableval}],
- [enable_json_validation=${have_jansson}])
-if test "${enable_json_validation}" = "no"; then
- AC_DEFINE(WITH_JSON_VALIDATION, 0, [Define if JSON validation in libnm is enabled])
-else
- if test "$have_jansson" = "no"; then
- AC_MSG_ERROR([jansson is needed for team configuration validation. Use --disable-json-validation to build without it.])
- fi
- AC_DEFINE(WITH_JSON_VALIDATION, 1, [Define if JSON validation in libnm is enabled])
-fi
-AM_CONDITIONAL(WITH_JSON_VALIDATION, test "${enable_json_validation}" != "no")
-
# we usually compile with polkit support. --enable-polkit=yes|no only sets the
# default configuration for main.auth-polkit. User can always enable/disable polkit
# authorization via config.
@@ -1366,6 +1353,7 @@ echo " nmcli: $build_nmcli"
echo " nmtui: $build_nmtui"
echo " nm-cloud-setup: $with_nm_cloud_setup"
echo " iwd: $ac_with_iwd"
+echo " jansson: $have_jansson${JANSSON_SONAME:+ (soname: $JANSSON_SONAME)}"
echo
echo "Configuration plugins (main.plugins=${config_plugins_default})"
@@ -1398,7 +1386,6 @@ echo " valgrind: $with_valgrind $with_valgrind_suppressions"
echo " code coverage: $enable_code_coverage"
echo " LTO: $enable_lto"
echo " linker garbage collection: $enable_ld_gc"
-echo " JSON validation for libnm: $enable_json_validation"
echo " crypto: $with_crypto (have-gnutls: $have_crypto_gnutls, have-nss: $have_crypto_nss)"
echo " sanitizers: $sanitizers"
echo " Mozilla Public Suffix List: $with_libpsl"
diff --git a/libnm-core/meson.build b/libnm-core/meson.build
index 89acaf72ad..0509deaa54 100644
--- a/libnm-core/meson.build
+++ b/libnm-core/meson.build
@@ -196,12 +196,6 @@ links = [
libnm_core_c_args = common_c_flags
-if enable_json_validation
- libnm_core_sources += files('nm-json.c')
- deps += jansson_dep
- libnm_core_c_args += ['-fcommon']
-endif
-
libnm_core = static_library(
'nm-core',
sources: libnm_core_sources + libnm_core_enum_sources + nm_meta_setting_source + [nm_version_macro_header],
diff --git a/libnm-core/nm-json.c b/libnm-core/nm-json.c
deleted file mode 100644
index 001d53dbb6..0000000000
--- a/libnm-core/nm-json.c
+++ /dev/null
@@ -1,110 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1+
-/*
- * Copyright (C) 2017, 2018 Red Hat, Inc.
- */
-
-#include "nm-default.h"
-
-#define NM_JANSSON_C
-#include "nm-json.h"
-
-#include <dlfcn.h>
-
-void *_nm_jansson_json_object_iter_value;
-void *_nm_jansson_json_object_key_to_iter;
-void *_nm_jansson_json_integer;
-void *_nm_jansson_json_object_del;
-void *_nm_jansson_json_array_get;
-void *_nm_jansson_json_array_size;
-void *_nm_jansson_json_array_append_new;
-void *_nm_jansson_json_string;
-void *_nm_jansson_json_object_iter_next;
-void *_nm_jansson_json_loads;
-void *_nm_jansson_json_dumps;
-void *_nm_jansson_json_object_iter_key;
-void *_nm_jansson_json_object;
-void *_nm_jansson_json_object_get;
-void *_nm_jansson_json_array;
-void *_nm_jansson_json_false;
-void *_nm_jansson_json_delete;
-void *_nm_jansson_json_true;
-void *_nm_jansson_json_object_size;
-void *_nm_jansson_json_object_set_new;
-void *_nm_jansson_json_object_iter;
-void *_nm_jansson_json_integer_value;
-void *_nm_jansson_json_string_value;
-
-#define TRY_BIND_SYMBOL(symbol) \
- G_STMT_START { \
- void *sym = dlsym (handle, #symbol); \
- if (_nm_jansson_ ## symbol && sym != _nm_jansson_ ## symbol) \
- return FALSE; \
- _nm_jansson_ ## symbol = sym; \
- } G_STMT_END
-
-static gboolean
-bind_symbols (void *handle)
-{
- TRY_BIND_SYMBOL (json_object_iter_value);
- TRY_BIND_SYMBOL (json_object_key_to_iter);
- TRY_BIND_SYMBOL (json_integer);
- TRY_BIND_SYMBOL (json_object_del);
- TRY_BIND_SYMBOL (json_array_get);
- TRY_BIND_SYMBOL (json_array_size);
- TRY_BIND_SYMBOL (json_array_append_new);
- TRY_BIND_SYMBOL (json_string);
- TRY_BIND_SYMBOL (json_object_iter_next);
- TRY_BIND_SYMBOL (json_loads);
- TRY_BIND_SYMBOL (json_dumps);
- TRY_BIND_SYMBOL (json_object_iter_key);
- TRY_BIND_SYMBOL (json_object);
- TRY_BIND_SYMBOL (json_object_get);
- TRY_BIND_SYMBOL (json_array);
- TRY_BIND_SYMBOL (json_false);
- TRY_BIND_SYMBOL (json_delete);
- TRY_BIND_SYMBOL (json_true);
- TRY_BIND_SYMBOL (json_object_size);
- TRY_BIND_SYMBOL (json_object_set_new);
- TRY_BIND_SYMBOL (json_object_iter);
- TRY_BIND_SYMBOL (json_integer_value);
- TRY_BIND_SYMBOL (json_string_value);
-
- return TRUE;
-}
-
-gboolean
-nm_jansson_load (void)
-{
- static enum {
- UNKNOWN,
- AVAILABLE,
- MISSING,
- } state = UNKNOWN;
- void *handle;
- int mode;
-
- if (G_LIKELY (state != UNKNOWN))
- goto out;
-
- /* First just resolve the symbols to see if there's a conflict already. */
- if (!bind_symbols (RTLD_DEFAULT))
- goto out;
-
- mode = RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE | RTLD_DEEPBIND;
-#if defined (ASAN_BUILD)
- /* Address sanitizer is incompatible with RTLD_DEEPBIND. */
- mode &= ~RTLD_DEEPBIND;
-#endif
- handle = dlopen (JANSSON_SONAME, mode);
-
- if (!handle)
- goto out;
-
- /* Now do the actual binding. */
- if (!bind_symbols (handle))
- goto out;
-
- state = AVAILABLE;
-out:
- return state == AVAILABLE;
-}
diff --git a/libnm-core/nm-json.h b/libnm-core/nm-json.h
deleted file mode 100644
index d857fe0275..0000000000
--- a/libnm-core/nm-json.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1+
-/*
- * Copyright (C) 2017, 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_JSON_H__
-#define __NM_JSON_H__
-
-gboolean nm_jansson_load (void);
-
-#ifndef NM_JANSSON_C
-#define json_object_iter_value (*_nm_jansson_json_object_iter_value)
-#define json_object_key_to_iter (*_nm_jansson_json_object_key_to_iter)
-#define json_integer (*_nm_jansson_json_integer)
-#define json_object_del (*_nm_jansson_json_object_del)
-#define json_array_get (*_nm_jansson_json_array_get)
-#define json_array_size (*_nm_jansson_json_array_size)
-#define json_array_append_new (*_nm_jansson_json_array_append_new)
-#define json_string (*_nm_jansson_json_string)
-#define json_object_iter_next (*_nm_jansson_json_object_iter_next)
-#define json_loads (*_nm_jansson_json_loads)
-#define json_dumps (*_nm_jansson_json_dumps)
-#define json_object_iter_key (*_nm_jansson_json_object_iter_key)
-#define json_object (*_nm_jansson_json_object)
-#define json_object_get (*_nm_jansson_json_object_get)
-#define json_array (*_nm_jansson_json_array)
-#define json_false (*_nm_jansson_json_false)
-#define json_delete (*_nm_jansson_json_delete)
-#define json_true (*_nm_jansson_json_true)
-#define json_object_size (*_nm_jansson_json_object_size)
-#define json_object_set_new (*_nm_jansson_json_object_set_new)
-#define json_object_iter (*_nm_jansson_json_object_iter)
-#define json_integer_value (*_nm_jansson_json_integer_value)
-#define json_string_value (*_nm_jansson_json_string_value)
-
-#include "nm-glib-aux/nm-jansson.h"
-#endif
-
-#endif /* __NM_JSON_H__ */
diff --git a/libnm-core/nm-team-utils.c b/libnm-core/nm-team-utils.c
index 084547c8f8..ca18c7d6a0 100644
--- a/libnm-core/nm-team-utils.c
+++ b/libnm-core/nm-team-utils.c
@@ -11,7 +11,6 @@
#include "nm-errors.h"
#include "nm-utils-private.h"
-#include "nm-json.h"
#include "nm-glib-aux/nm-json-aux.h"
#include "nm-core-internal.h"
#include "nm-setting-team.h"
@@ -460,9 +459,9 @@ _team_attr_data_to_json (const TeamAttrData *attr_data,
_team_attr_data_ASSERT (attr_data);
nm_assert (p_field);
- nm_json_aux_gstr_append_obj_name (gstr,
- attr_data->js_keys[attr_data->js_keys_len - 1],
- '\0');
+ nm_json_gstr_append_obj_name (gstr,
+ attr_data->js_keys[attr_data->js_keys_len - 1],
+ '\0');
if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC) {
nm_value_type_to_json (attr_data->value_type, gstr, p_field);
@@ -482,7 +481,7 @@ _team_attr_data_to_json (const TeamAttrData *attr_data,
g_string_append (gstr, "[ ");
for (i = 0; i < v_ptrarray->len; i++) {
if (i > 0)
- nm_json_aux_gstr_append_delimiter (gstr);
+ nm_json_gstr_append_delimiter (gstr);
_link_watcher_to_json (v_ptrarray->pdata[i], gstr);
}
g_string_append (gstr, " ]");
@@ -500,8 +499,8 @@ _team_attr_data_to_json (const TeamAttrData *attr_data,
g_string_append (gstr, "[ ");
for (i = 0; i < v_ptrarray->len; i++) {
if (i > 0)
- nm_json_aux_gstr_append_delimiter (gstr);
- nm_json_aux_gstr_append_string (gstr, v_ptrarray->pdata[i]);
+ nm_json_gstr_append_delimiter (gstr);
+ nm_json_gstr_append_string (gstr, v_ptrarray->pdata[i]);
}
g_string_append (gstr, i > 0 ? " ]" : "]");
}
@@ -671,7 +670,7 @@ _team_setting_field_to_json (const NMTeamSetting *self,
return FALSE;
if (prepend_delimiter)
- nm_json_aux_gstr_append_delimiter (gstr);
+ nm_json_gstr_append_delimiter (gstr);
_team_attr_data_to_json (attr_data,
self->d.is_port,
gstr,
@@ -1108,29 +1107,29 @@ _link_watcher_to_json (const NMTeamLinkWatcher *link_watcher,
if (is_first)
is_first = FALSE;
else
- nm_json_aux_gstr_append_delimiter (gstr);
- nm_json_aux_gstr_append_obj_name (gstr, attr_data->js_key, '\0');
+ nm_json_gstr_append_delimiter (gstr);
+ nm_json_gstr_append_obj_name (gstr, attr_data->js_key, '\0');
nm_value_type_to_json (attr_data->value_type, gstr, &p_val->val);
}
g_string_append (gstr, " }");
}
-#if WITH_JSON_VALIDATION
static NMTeamLinkWatcher *
-_link_watcher_from_json (const json_t *root_js_obj,
+_link_watcher_from_json (const NMJsonVt *vt,
+ const nm_json_t *root_js_obj,
gboolean *out_unrecognized_content)
{
NMValueTypUnioMaybe args[G_N_ELEMENTS (link_watcher_attr_datas)] = { };
const char *j_key;
- json_t *j_val;
+ nm_json_t *j_val;
const char *v_name;
NMTeamLinkWatcher *result = NULL;
- if (!json_is_object (root_js_obj))
+ if (!nm_json_is_object (root_js_obj))
goto fail;
- json_object_foreach ((json_t *) root_js_obj, j_key, j_val) {
+ nm_json_object_foreach (vt, (nm_json_t *) root_js_obj, j_key, j_val) {
const LinkWatcherAttrData *attr_data = NULL;
NMValueTypUnioMaybe *parse_result;
@@ -1154,7 +1153,7 @@ _link_watcher_from_json (const json_t *root_js_obj,
if (parse_result->has)
*out_unrecognized_content = TRUE;
- if (!nm_value_type_from_json (attr_data->value_type, j_val, &parse_result->val))
+ if (!nm_value_type_from_json (vt, attr_data->value_type, j_val, &parse_result->val))
*out_unrecognized_content = TRUE;
else
parse_result->has = TRUE;
@@ -1218,7 +1217,6 @@ fail:
*out_unrecognized_content = TRUE;
return NULL;
}
-#endif
/*****************************************************************************/
@@ -1575,15 +1573,15 @@ nm_team_setting_config_get (const NMTeamSetting *self)
nm_assert (list_is_empty);
- nm_json_aux_gstr_append_obj_name (gstr, "runner", '{');
+ nm_json_gstr_append_obj_name (gstr, "runner", '{');
if (_team_setting_fields_to_json_maybe (self, gstr, !list_is_empty2, attr_lst_runner_pt1, G_N_ELEMENTS (attr_lst_runner_pt1)))
list_is_empty2 = FALSE;
if (_team_setting_has_fields_any_v (self, attr_lst_runner_pt2, G_N_ELEMENTS (attr_lst_runner_pt2))) {
if (!list_is_empty2)
- nm_json_aux_gstr_append_delimiter (gstr);
- nm_json_aux_gstr_append_obj_name (gstr, "tx_balancer", '{');
+ nm_json_gstr_append_delimiter (gstr);
+ nm_json_gstr_append_obj_name (gstr, "tx_balancer", '{');
if (!_team_setting_fields_to_json_maybe (self, gstr, FALSE, attr_lst_runner_pt2, G_N_ELEMENTS (attr_lst_runner_pt2)))
nm_assert_not_reached ();
g_string_append (gstr, " }");
@@ -1600,8 +1598,8 @@ nm_team_setting_config_get (const NMTeamSetting *self)
if (_team_setting_has_fields_any_v (self, attr_lst_notify_peers, G_N_ELEMENTS (attr_lst_notify_peers))) {
if (!list_is_empty)
- nm_json_aux_gstr_append_delimiter (gstr);
- nm_json_aux_gstr_append_obj_name (gstr, "notify_peers", '{');
+ nm_json_gstr_append_delimiter (gstr);
+ nm_json_gstr_append_obj_name (gstr, "notify_peers", '{');
if (!_team_setting_fields_to_json_maybe (self, gstr, FALSE, attr_lst_notify_peers, G_N_ELEMENTS (attr_lst_notify_peers)))
nm_assert_not_reached ();
g_string_append (gstr, " }");
@@ -1610,8 +1608,8 @@ nm_team_setting_config_get (const NMTeamSetting *self)
if (_team_setting_has_fields_any_v (self, attr_lst_mcast_rejoin, G_N_ELEMENTS (attr_lst_mcast_rejoin))) {
if (!list_is_empty)
- nm_json_aux_gstr_append_delimiter (gstr);
- nm_json_aux_gstr_append_obj_name (gstr, "mcast_rejoin", '{');
+ nm_json_gstr_append_delimiter (gstr);
+ nm_json_gstr_append_obj_name (gstr, "mcast_rejoin", '{');
if (!_team_setting_fields_to_json_maybe (self, gstr, FALSE, attr_lst_mcast_rejoin, G_N_ELEMENTS (attr_lst_mcast_rejoin)))
nm_assert_not_reached ();
g_string_append (gstr, " }");
@@ -1641,7 +1639,6 @@ nm_team_setting_config_get (const NMTeamSetting *self)
/*****************************************************************************/
-#if WITH_JSON_VALIDATION
static gboolean
_attr_data_match_keys (const TeamAttrData *attr_data,
const char *const*keys,
@@ -1686,18 +1683,21 @@ _attr_data_find_by_json_key (gboolean is_port,
}
static void
-_js_parse_locate_keys (NMTeamSetting *self,
- json_t *root_js_obj,
- json_t *found_keys[static _NM_TEAM_ATTRIBUTE_NUM],
+_js_parse_locate_keys (const NMJsonVt *vt,
+ NMTeamSetting *self,
+ nm_json_t *root_js_obj,
+ nm_json_t *found_keys[static _NM_TEAM_ATTRIBUTE_NUM],
gboolean *out_unrecognized_content)
{
const char *keys[3];
const char *cur_key1;
const char *cur_key2;
const char *cur_key3;
- json_t *cur_val1;
- json_t *cur_val2;
- json_t *cur_val3;
+ nm_json_t *cur_val1;
+ nm_json_t *cur_val2;
+ nm_json_t *cur_val3;
+
+ nm_assert (vt);
#define _handle(_self, _cur_key, _cur_val, _keys, _level, _found_keys, _out_unrecognized_content) \
({ \
@@ -1713,18 +1713,18 @@ _js_parse_locate_keys (NMTeamSetting *self,
(_found_keys)[_attr_data->team_attr] = (_cur_val); \
_handled = TRUE; \
} else if ( !_attr_data \
- || !json_is_object ((_cur_val))) { \
+ || !nm_json_is_object ((_cur_val))) { \
*(_out_unrecognized_content) = TRUE; \
_handled = TRUE; \
} \
_handled; \
})
- json_object_foreach (root_js_obj, cur_key1, cur_val1) {
+ nm_json_object_foreach (vt, root_js_obj, cur_key1, cur_val1) {
if (!_handle (self, cur_key1, cur_val1, keys, 1, found_keys, out_unrecognized_content)) {
- json_object_foreach (cur_val1, cur_key2, cur_val2) {
+ nm_json_object_foreach (vt, cur_val1, cur_key2, cur_val2) {
if (!_handle (self, cur_key2, cur_val2, keys, 2, found_keys, out_unrecognized_content)) {
- json_object_foreach (cur_val2, cur_key3, cur_val3) {
+ nm_json_object_foreach (vt, cur_val2, cur_key3, cur_val3) {
if (!_handle (self, cur_key3, cur_val3, keys, 3, found_keys, out_unrecognized_content))
*out_unrecognized_content = TRUE;
}
@@ -1737,8 +1737,9 @@ _js_parse_locate_keys (NMTeamSetting *self,
}
static void
-_js_parse_unpack (gboolean is_port,
- json_t *found_keys[static _NM_TEAM_ATTRIBUTE_NUM],
+_js_parse_unpack (const NMJsonVt *vt,
+ gboolean is_port,
+ nm_json_t *found_keys[static _NM_TEAM_ATTRIBUTE_NUM],
bool out_has_lst[static _NM_TEAM_ATTRIBUTE_NUM],
NMValueTypUnion out_val_lst[static _NM_TEAM_ATTRIBUTE_NUM],
gboolean *out_unrecognized_content,
@@ -1747,10 +1748,12 @@ _js_parse_unpack (gboolean is_port,
{
const TeamAttrData *attr_data;
+ nm_assert (vt);
+
for (attr_data = &team_attr_datas[TEAM_ATTR_IDX_CONFIG + 1]; attr_data < &team_attr_datas[G_N_ELEMENTS (team_attr_datas)]; attr_data++) {
NMValueTypUnion *p_out_val;
gboolean valid = FALSE;
- json_t *arg_js_obj;
+ nm_json_t *arg_js_obj;
if (!_team_attr_data_is_relevant (attr_data, is_port))
continue;
@@ -1764,25 +1767,27 @@ _js_parse_unpack (gboolean is_port,
p_out_val = &out_val_lst[attr_data->team_attr];
if (attr_data->value_type != NM_VALUE_TYPE_UNSPEC)
- valid = nm_value_type_from_json (attr_data->value_type, arg_js_obj, p_out_val);
+ valid = nm_value_type_from_json (vt, attr_data->value_type, arg_js_obj, p_out_val);
else if (attr_data->team_attr == NM_TEAM_ATTRIBUTE_LINK_WATCHERS) {
GPtrArray *link_watchers = NULL;
NMTeamLinkWatcher *link_watcher;
nm_assert (out_ptr_array_link_watchers_free && !*out_ptr_array_link_watchers_free);
- if (json_is_array (arg_js_obj)) {
+ if (nm_json_is_array (arg_js_obj)) {
gsize i, len;
- len = json_array_size (arg_js_obj);
+ len = vt->nm_json_array_size (arg_js_obj);
link_watchers = g_ptr_array_new_full (len, (GDestroyNotify) nm_team_link_watcher_unref);
for (i = 0; i < len; i++) {
- link_watcher = _link_watcher_from_json (json_array_get (arg_js_obj, i),
+ link_watcher = _link_watcher_from_json (vt,
+ vt->nm_json_array_get (arg_js_obj, i),
out_unrecognized_content);
if (link_watcher)
g_ptr_array_add (link_watchers, link_watcher);
}
} else {
- link_watcher = _link_watcher_from_json (arg_js_obj,
+ link_watcher = _link_watcher_from_json (vt,
+ arg_js_obj,
out_unrecognized_content);
if (link_watcher) {
link_watchers = g_ptr_array_new_full (1, (GDestroyNotify) nm_team_link_watcher_unref);
@@ -1799,16 +1804,17 @@ _js_parse_unpack (gboolean is_port,
GPtrArray *strv = NULL;
nm_assert (out_ptr_array_master_runner_tx_hash_free && !*out_ptr_array_master_runner_tx_hash_free);
- if (json_is_array (arg_js_obj)) {
+ if (nm_json_is_array (arg_js_obj)) {
gsize i, len;
- len = json_array_size (arg_js_obj);
+ len = vt->nm_json_array_size (arg_js_obj);
if (len > 0) {
strv = g_ptr_array_sized_new (len);
for (i = 0; i < len; i++) {
const char *v_string;
- if ( nm_jansson_json_as_string (json_array_get (arg_js_obj, i),
+ if ( nm_jansson_json_as_string (vt,
+ vt->nm_json_array_get (arg_js_obj, i),
&v_string) <= 0
|| !v_string
|| v_string[0] == '\0') {
@@ -1832,11 +1838,11 @@ _js_parse_unpack (gboolean is_port,
*out_unrecognized_content = TRUE;
}
}
-#endif
guint32
nm_team_setting_config_set (NMTeamSetting *self, const char *js_str)
{
+ const NMJsonVt *vt;
guint32 changed_flags = 0;
gboolean do_set_default = TRUE;
gboolean new_js_str_invalid = FALSE;
@@ -1866,30 +1872,29 @@ nm_team_setting_config_set (NMTeamSetting *self, const char *js_str)
} else
changed_flags |= nm_team_attribute_to_flags (NM_TEAM_ATTRIBUTE_CONFIG);
-#if WITH_JSON_VALIDATION
- {
- nm_auto_decref_json json_t *root_js_obj = NULL;
-
- if (nm_jansson_load ())
- root_js_obj = json_loads (js_str, 0, NULL);
+ if ((vt = nm_json_vt ())) {
+ nm_auto_decref_json nm_json_t *root_js_obj = NULL;
+ root_js_obj = vt->nm_json_loads (js_str, 0, NULL);
if ( !root_js_obj
- || !json_is_object (root_js_obj))
+ || !nm_json_is_object (root_js_obj))
new_js_str_invalid = TRUE;
else {
gboolean unrecognized_content = FALSE;
bool has_lst[_NM_TEAM_ATTRIBUTE_NUM] = { FALSE, };
NMValueTypUnion val_lst[_NM_TEAM_ATTRIBUTE_NUM];
- json_t *found_keys[_NM_TEAM_ATTRIBUTE_NUM] = { NULL, };
+ nm_json_t *found_keys[_NM_TEAM_ATTRIBUTE_NUM] = { NULL, };
gs_unref_ptrarray GPtrArray *ptr_array_master_runner_tx_hash_free = NULL;
gs_unref_ptrarray GPtrArray *ptr_array_link_watchers_free = NULL;
- _js_parse_locate_keys (self,
+ _js_parse_locate_keys (vt,
+ self,
root_js_obj,
found_keys,
&unrecognized_content);
- _js_parse_unpack (self->d.is_port,
+ _js_parse_unpack (vt,
+ self->d.is_port,
found_keys,
has_lst,
val_lst,
@@ -1906,8 +1911,6 @@ nm_team_setting_config_set (NMTeamSetting *self, const char *js_str)
}
}
-#endif
-
if (do_set_default)
changed_flags |= _team_setting_set_default (self);
@@ -2222,6 +2225,7 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self,
GVariantIter iter;
const char *v_key;
GVariant *v_val;
+ const NMJsonVt *vt;
*out_changed = 0;
@@ -2271,10 +2275,12 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self,
variants[attr_data->team_attr] = g_steal_pointer (&v_val_free);
}
+ vt = nm_json_vt ();
+
if (variants[NM_TEAM_ATTRIBUTE_LINK_WATCHERS]) {
if ( variants[NM_TEAM_ATTRIBUTE_CONFIG]
- && WITH_JSON_VALIDATION
+ && vt
&& !NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) {
/* we don't require the content of the "link-watchers" and we also
* don't perform strict validation. No need to parse it. */
@@ -2282,7 +2288,7 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self,
gs_free_error GError *local = NULL;
/* We might need the parsed v_link_watchers array below (because there is no JSON
- * "config" present or because we don't build WITH_JSON_VALIDATION).
+ * "config" present or because we don't have json support).
*
* Or we might run with NM_SETTING_PARSE_FLAGS_STRICT. In that mode, we may not necessarily
* require that the entire setting as a whole validates (if a JSON config is present and
@@ -2310,7 +2316,7 @@ nm_team_setting_reset_from_dbus (NMTeamSetting *self,
? g_variant_get_string (variants[NM_TEAM_ATTRIBUTE_CONFIG], NULL)
: NULL);
- if ( WITH_JSON_VALIDATION
+ if ( vt
&& variants[NM_TEAM_ATTRIBUTE_CONFIG]) {
/* for team settings, the JSON must be able to express all possible options. That means,
* if the GVariant contains both the JSON "config" and other options, then the other options
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index 4127abb54d..b633a5099c 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -16,10 +16,7 @@
#include <sys/stat.h>
#include <linux/pkt_sched.h>
-#if WITH_JSON_VALIDATION
-#include "nm-json.h"
-#endif
-
+#include "nm-glib-aux/nm-json-aux.h"
#include "nm-glib-aux/nm-str-buf.h"
#include "nm-glib-aux/nm-enum-utils.h"
#include "nm-glib-aux/nm-time-utils.h"
@@ -5493,9 +5490,9 @@ _nm_utils_is_json_object_no_validation (const char *str, GError **error)
gboolean
nm_utils_is_json_object (const char *str, GError **error)
{
-#if WITH_JSON_VALIDATION
- nm_auto_decref_json json_t *json = NULL;
- json_error_t jerror;
+ nm_auto_decref_json nm_json_t *json = NULL;
+ const NMJsonVt *vt;
+ nm_json_error_t jerror;
g_return_val_if_fail (!error || !*error, FALSE);
@@ -5507,10 +5504,10 @@ nm_utils_is_json_object (const char *str, GError **error)
return FALSE;
}
- if (!nm_jansson_load ())
+ if (!(vt = nm_json_vt ()))
return _nm_utils_is_json_object_no_validation (str, error);
- json = json_loads (str, JSON_REJECT_DUPLICATES, &jerror);
+ json = vt->nm_json_loads (str, NM_JSON_REJECT_DUPLICATES, &jerror);
if (!json) {
g_set_error (error,
NM_CONNECTION_ERROR,
@@ -5523,7 +5520,7 @@ nm_utils_is_json_object (const char *str, GError **error)
/* valid JSON (depending on the definition) can also be a literal.
* Here we only allow objects. */
- if (!json_is_object (json)) {
+ if (!nm_json_is_object (json)) {
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
@@ -5532,19 +5529,6 @@ nm_utils_is_json_object (const char *str, GError **error)
}
return TRUE;
-#else /* !WITH_JSON_VALIDATION */
- g_return_val_if_fail (!error || !*error, FALSE);
-
- if (!str || !str[0]) {
- g_set_error_literal (error,
- NM_CONNECTION_ERROR,
- NM_CONNECTION_ERROR_INVALID_PROPERTY,
- str ? _("value is NULL") : _("value is empty"));
- return FALSE;
- }
-
- return _nm_utils_is_json_object_no_validation (str, error);
-#endif
}
static char *
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index 040bcb9f1f..1e4efe2452 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -14,6 +14,7 @@
#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 "nm-glib-aux/nm-json-aux.h"
#include "systemd/nm-sd-utils-shared.h"
#include "nm-utils.h"
@@ -7125,17 +7126,19 @@ test_nm_utils_check_valid_json (void)
{
_json_config_check_valid (NULL, FALSE);
_json_config_check_valid ("", FALSE);
-#if WITH_JSON_VALIDATION
- _json_config_check_valid ("{ }", TRUE);
- _json_config_check_valid ("{ \"a\" : 1 }", TRUE);
- _json_config_check_valid ("{ \"a\" : }", FALSE);
-#else
+
/* Without JSON library everything except empty string is considered valid */
+ nmtst_json_vt_reset (FALSE);
_json_config_check_valid ("{ }", TRUE);
_json_config_check_valid ("{'%!-a1} ", TRUE);
_json_config_check_valid (" {'%!-a1}", TRUE);
_json_config_check_valid ("{'%!-a1", FALSE);
-#endif
+
+ if (nmtst_json_vt_reset (TRUE)) {
+ _json_config_check_valid ("{ }", TRUE);
+ _json_config_check_valid ("{ \"a\" : 1 }", TRUE);
+ _json_config_check_valid ("{ \"a\" : }", FALSE);
+ }
}
static void
@@ -7172,86 +7175,96 @@ _team_config_equal_check (const char *conf1,
static void
test_nm_utils_team_config_equal (void)
{
- _team_config_equal_check ("",
- "",
- TRUE,
- TRUE);
- _team_config_equal_check ("",
- " ",
- TRUE,
- TRUE);
- _team_config_equal_check ("{}",
- "{ }",
- TRUE,
- TRUE);
- _team_config_equal_check ("{}",
- "{",
- TRUE,
- TRUE);
- _team_config_equal_check ("{ \"a\": 1 }",
- "{ \"a\": 1 }",
- TRUE,
- TRUE);
- _team_config_equal_check ("{ \"a\": 1 }",
- "{ \"a\": 1 }",
- TRUE,
- TRUE);
-
- /* team config */
- _team_config_equal_check ("{ }",
- "{ \"runner\" : { \"name\" : \"random\"} }",
- FALSE,
- !WITH_JSON_VALIDATION);
- _team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }",
- "{ \"runner\" : { \"name\" : \"random\"} }",
- FALSE,
- !WITH_JSON_VALIDATION);
- _team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"} }",
- "{ \"runner\" : { \"name\" : \"random\"} }",
- FALSE,
- TRUE);
- _team_config_equal_check ("{ \"runner\" : { \"name\" : \"loadbalance\"} }",
- "{ \"runner\" : { \"name\" : \"loadbalance\"} }",
- FALSE,
- TRUE);
- _team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth0\" : {} } }",
- "{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth1\" : {} } }",
- FALSE,
- TRUE);
- _team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }",
- "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }",
- FALSE,
- !WITH_JSON_VALIDATION);
- _team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }",
- "{ \"runner\" : { \"name\" : \"roundrobin\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }",
- FALSE,
- !WITH_JSON_VALIDATION);
- _team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }",
- "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\" ] } }",
- FALSE,
- !WITH_JSON_VALIDATION);
-
- /* team port config */
- _team_config_equal_check ("{ }",
- "{ \"link_watch\" : { \"name\" : \"ethtool\"} }",
- TRUE,
- !WITH_JSON_VALIDATION);
- _team_config_equal_check ("{ }",
- "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
- TRUE,
- TRUE);
- _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"ethtool\"} }",
- "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
- TRUE,
- !WITH_JSON_VALIDATION);
- _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
- "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
- TRUE,
- TRUE);
- _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth0\" : {} } }",
- "{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth1\" : {} } }",
- TRUE,
- TRUE);
+ int with_json_vt;
+
+ for (with_json_vt = 0; with_json_vt < 2; with_json_vt++) {
+ const NMJsonVt *vt;
+
+ vt = nmtst_json_vt_reset (!!with_json_vt);
+
+ _team_config_equal_check ("",
+ "",
+ TRUE,
+ TRUE);
+ _team_config_equal_check ("",
+ " ",
+ TRUE,
+ TRUE);
+ _team_config_equal_check ("{}",
+ "{ }",
+ TRUE,
+ TRUE);
+ _team_config_equal_check ("{}",
+ "{",
+ TRUE,
+ TRUE);
+ _team_config_equal_check ("{ \"a\": 1 }",
+ "{ \"a\": 1 }",
+ TRUE,
+ TRUE);
+ _team_config_equal_check ("{ \"a\": 1 }",
+ "{ \"a\": 1 }",
+ TRUE,
+ TRUE);
+
+ /* team config */
+ _team_config_equal_check ("{ }",
+ "{ \"runner\" : { \"name\" : \"random\"} }",
+ FALSE,
+ !vt);
+ _team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }",
+ "{ \"runner\" : { \"name\" : \"random\"} }",
+ FALSE,
+ !vt);
+ _team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"} }",
+ "{ \"runner\" : { \"name\" : \"random\"} }",
+ FALSE,
+ TRUE);
+ _team_config_equal_check ("{ \"runner\" : { \"name\" : \"loadbalance\"} }",
+ "{ \"runner\" : { \"name\" : \"loadbalance\"} }",
+ FALSE,
+ TRUE);
+ _team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth0\" : {} } }",
+ "{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth1\" : {} } }",
+ FALSE,
+ TRUE);
+ _team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }",
+ "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }",
+ FALSE,
+ !vt);
+ _team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }",
+ "{ \"runner\" : { \"name\" : \"roundrobin\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }",
+ FALSE,
+ !vt);
+ _team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }",
+ "{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\" ] } }",
+ FALSE,
+ !vt);
+
+ /* team port config */
+ _team_config_equal_check ("{ }",
+ "{ \"link_watch\" : { \"name\" : \"ethtool\"} }",
+ TRUE,
+ !vt);
+ _team_config_equal_check ("{ }",
+ "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
+ TRUE,
+ TRUE);
+ _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"ethtool\"} }",
+ "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
+ TRUE,
+ !vt);
+ _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
+ "{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
+ TRUE,
+ TRUE);
+ _team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth0\" : {} } }",
+ "{ \"link_watch\" : { \"name\" : \"arp_ping\"}, \"ports\" : { \"eth1\" : {} } }",
+ TRUE,
+ TRUE);
+ }
+
+ nmtst_json_vt_reset (TRUE);
}
/*****************************************************************************/
diff --git a/libnm-core/tests/test-keyfile.c b/libnm-core/tests/test-keyfile.c
index 23149b618d..c9ec51f01b 100644
--- a/libnm-core/tests/test-keyfile.c
+++ b/libnm-core/tests/test-keyfile.c
@@ -5,6 +5,7 @@
#include "nm-default.h"
+#include "nm-glib-aux/nm-json-aux.h"
#include "nm-keyfile/nm-keyfile-utils.h"
#include "nm-keyfile/nm-keyfile-internal.h"
#include "nm-simple-connection.h"
@@ -627,7 +628,7 @@ test_team_conf_read_invalid (void)
gs_unref_object NMConnection *con = NULL;
NMSettingTeam *s_team;
- if (!WITH_JSON_VALIDATION) {
+ if (!nm_json_vt ()) {
g_test_skip ("team test requires JSON validation");
return;
}
diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c
index 1a32d91a49..1b53baeda3 100644
--- a/libnm-core/tests/test-setting.c
+++ b/libnm-core/tests/test-setting.c
@@ -8,6 +8,7 @@
#include <linux/pkt_sched.h>
#include <net/if.h>
+#include "nm-glib-aux/nm-json-aux.h"
#include "nm-core-internal.h"
#include "nm-utils.h"
#include "nm-utils-private.h"
@@ -32,15 +33,6 @@
/*****************************************************************************/
-/* assert that the define is just a plain integer (boolean). */
-
-G_STATIC_ASSERT ( (WITH_JSON_VALIDATION) == 1
- || (WITH_JSON_VALIDATION) == 0);
-
-_nm_unused static const int _with_json_validation = WITH_JSON_VALIDATION;
-
-/*****************************************************************************/
-
/* converts @dict to a connection. In this case, @dict must be good, without warnings, so that
* NM_SETTING_PARSE_FLAGS_STRICT and NM_SETTING_PARSE_FLAGS_BEST_EFFORT yield the exact same results. */
static NMConnection *
@@ -979,6 +971,24 @@ test_dcb_bandwidth_sums (void)
/*****************************************************************************/
static void
+test_nm_json (void)
+{
+ g_assert (NM_IN_SET (WITH_JANSSON, 0, 1));
+
+#if WITH_JANSSON
+ g_assert (nm_json_vt ());
+#else
+ g_assert (!nm_json_vt ());
+#endif
+
+#if WITH_JANSSON != defined (JANSSON_SONAME)
+#error "WITH_JANSON and JANSSON_SONAME are defined inconsistently."
+#endif
+}
+
+/*****************************************************************************/
+
+static void
_test_team_config_sync (const char *team_config,
int notify_peer_count,
int notify_peers_interval,
@@ -1000,7 +1010,7 @@ _test_team_config_sync (const char *team_config,
guint i, j;
gboolean found;
- if (!WITH_JSON_VALIDATION) {
+ if (!nm_json_vt ()) {
g_test_skip ("team test requires JSON validation");
return;
}
@@ -1265,7 +1275,7 @@ _test_team_port_config_sync (const char *team_port_config,
guint i, j;
gboolean found;
- if (!WITH_JSON_VALIDATION) {
+ if (!nm_json_vt ()) {
g_test_skip ("team test requires JSON validation");
return;
}
@@ -1397,7 +1407,7 @@ _check_team_setting (NMSetting *setting)
: nm_setting_team_get_config (NM_SETTING_TEAM (setting)),
NULL);
- if (WITH_JSON_VALIDATION)
+ if (nm_json_vt ())
nmtst_assert_setting_is_equal (setting, setting2, NM_SETTING_COMPARE_FLAG_EXACT);
g_clear_object (&setting2);
@@ -4095,6 +4105,7 @@ main (int argc, char **argv)
g_test_add_func ("/libnm/settings/bridge/vlans", test_bridge_vlans);
g_test_add_func ("/libnm/settings/bridge/verify", test_bridge_verify);
+ g_test_add_func ("/libnm/test_nm_json", test_nm_json);
g_test_add_func ("/libnm/settings/team/sync_runner_from_config_roundrobin",
test_runner_roundrobin_sync_from_config);
g_test_add_func ("/libnm/settings/team/sync_runner_from_config_broadcast",
diff --git a/meson.build b/meson.build
index 8eed507f08..f8973b4680 100644
--- a/meson.build
+++ b/meson.build
@@ -253,9 +253,10 @@ libudev_dep = dependency('libudev', version: '>= 175')
dbus_dep = dependency('dbus-1', version: '>= 1.1')
libndp_dep = dependency('libndp')
-jansson_dep = dependency('jansson', version: '>= 2.5', required: false)
+jansson_dep = dependency('jansson', version: '>= 2.7', required: false)
config_h.set10('WITH_JANSSON', jansson_dep.found())
+jansson_msg = 'no'
if jansson_dep.found()
jansson_libdir = jansson_dep.get_pkgconfig_variable('libdir')
res = run_command(find_program('eu-readelf', 'readelf'), '-d', join_paths(jansson_libdir, 'libjansson.so'))
@@ -267,6 +268,7 @@ if jansson_dep.found()
endforeach
assert(jansson_soname != '', 'Unable to determine Jansson SONAME')
config_h.set_quoted('JANSSON_SONAME', jansson_soname)
+ jansson_msg = 'yes (soname: ' + jansson_soname + ')'
endif
libsystemd_dep = dependency('libsystemd', version: '>= 209', required: false)
@@ -497,12 +499,6 @@ if enable_teamdctl
assert(libteamdctl_dep.found(), 'You must have libteamdctl installed to build. Use -Dteamdctl=false to disable it')
endif
-enable_json_validation = get_option('json_validation')
-if enable_json_validation
- assert(jansson_dep.found(), 'jansson is needed for team configuration validation. Use -Djson_validation=false to disable it')
-endif
-config_h.set10('WITH_JSON_VALIDATION', enable_json_validation)
-
# polkit
enable_polkit = get_option('polkit')
if enable_polkit
@@ -1013,6 +1009,7 @@ if enable_ppp
output += ' ' + pppd_path + ' plugins:' + pppd_plugin_dir
endif
output += '\n'
+output += ' jansson: ' + jansson_msg + '\n'
output += ' modemmanager-1: ' + enable_modem_manager.to_string() + '\n'
output += ' ofono: ' + enable_ofono.to_string() + '\n'
output += ' concheck: ' + enable_concheck.to_string() + '\n'
@@ -1047,7 +1044,6 @@ output += '\n'
output += ' code coverage: ' + get_option('b_coverage').to_string() + '\n'
output += ' LTO: ' + enable_lto.to_string() + '\n'
output += ' Linker garbage collection: ' + enable_ld_gc.to_string() + '\n'
-output += ' JSON validation for libnm: ' + enable_json_validation.to_string() + '\n'
output += ' crypto: ' + crypto + '\n'
output += ' sanitizers: ' + get_option('b_sanitize') + '\n'
output += ' Mozilla Public Suffix List: ' + enable_libpsl.to_string() + '\n'
diff --git a/meson_options.txt b/meson_options.txt
index a5c6a22fb0..d6306711ec 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -69,6 +69,5 @@ option('valgrind', type: 'array', value: ['no'], description: 'Use valgrind to m
option('valgrind_suppressions', type: 'string', value: '', description: 'Use specific valgrind suppression file')
option('ld_gc', type: 'boolean', value: true, description: 'Enable garbage collection of unused symbols on linking')
option('libpsl', type: 'boolean', value: true, description: 'Link against libpsl')
-option('json_validation', type: 'boolean', value: true, description: 'Enable JSON validation in libnm')
option('crypto', type: 'combo', choices: ['nss', 'gnutls'], value: 'nss', description: 'Cryptography library to use for certificate and key operations')
option('qt', type: 'boolean', value: true, description: 'enable Qt examples')
diff --git a/shared/nm-glib-aux/nm-jansson.h b/shared/nm-glib-aux/nm-jansson.h
index 7c034222c4..9314b50c69 100644
--- a/shared/nm-glib-aux/nm-jansson.h
+++ b/shared/nm-glib-aux/nm-jansson.h
@@ -12,11 +12,6 @@
#include <jansson.h>
-/* Added in Jansson v2.7 */
-#ifndef json_boolean_value
-#define json_boolean_value json_is_true
-#endif
-
/* Added in Jansson v2.8 */
#ifndef json_object_foreach_safe
#define json_object_foreach_safe(object, n, key, value) \
@@ -30,106 +25,6 @@
NM_AUTO_DEFINE_FCN0 (json_t *, _nm_auto_decref_json, json_decref)
#define nm_auto_decref_json nm_auto(_nm_auto_decref_json)
-/*****************************************************************************/
-
-static inline int
-nm_jansson_json_as_bool (const json_t *elem,
- bool *out_val)
-{
- if (!elem)
- return 0;
-
- if (!json_is_boolean (elem))
- return -EINVAL;
-
- NM_SET_OUT (out_val, json_boolean_value (elem));
- return 1;
-}
-
-static inline int
-nm_jansson_json_as_int32 (const json_t *elem,
- gint32 *out_val)
-{
- json_int_t v;
-
- if (!elem)
- return 0;
-
- if (!json_is_integer (elem))
- return -EINVAL;
-
- v = json_integer_value (elem);
- if ( v < (gint64) G_MININT32
- || v > (gint64) G_MAXINT32)
- return -ERANGE;
-
- NM_SET_OUT (out_val, v);
- return 1;
-}
-
-static inline int
-nm_jansson_json_as_int (const json_t *elem,
- int *out_val)
-{
- json_int_t v;
-
- if (!elem)
- return 0;
-
- if (!json_is_integer (elem))
- return -EINVAL;
-
- v = json_integer_value (elem);
- if ( v < (gint64) G_MININT
- || v > (gint64) G_MAXINT)
- return -ERANGE;
-
- NM_SET_OUT (out_val, v);
- return 1;
-}
-
-static inline int
-nm_jansson_json_as_string (const json_t *elem,
- const char **out_val)
-{
- if (!elem)
- return 0;
-
- if (!json_is_string (elem))
- return -EINVAL;
-
- NM_SET_OUT (out_val, json_string_value (elem));
- return 1;
-}
-
-/*****************************************************************************/
-
-#ifdef NM_VALUE_TYPE_DEFINE_FUNCTIONS
-#include "nm-value-type.h"
-static inline gboolean
-nm_value_type_from_json (NMValueType value_type,
- const json_t *elem,
- gpointer out_val)
-{
- switch (value_type) {
- case NM_VALUE_TYPE_BOOL: return (nm_jansson_json_as_bool (elem, out_val) > 0);
- case NM_VALUE_TYPE_INT32: return (nm_jansson_json_as_int32 (elem, out_val) > 0);
- case NM_VALUE_TYPE_INT: return (nm_jansson_json_as_int (elem, out_val) > 0);
-
- /* warning: this overwrites/leaks the previous value. You better have *out_val
- * point to uninitialized memory or NULL. */
- case NM_VALUE_TYPE_STRING: return (nm_jansson_json_as_string (elem, out_val) > 0);
-
- case NM_VALUE_TYPE_UNSPEC:
- break;
- }
- nm_assert_not_reached ();
- return FALSE;
-}
-#endif
-
-/*****************************************************************************/
-
#endif /* WITH_JANSON */
#endif /* __NM_JANSSON_H__ */
diff --git a/shared/nm-glib-aux/nm-json-aux.c b/shared/nm-glib-aux/nm-json-aux.c
index afa92531c6..e9816d7781 100644
--- a/shared/nm-glib-aux/nm-json-aux.c
+++ b/shared/nm-glib-aux/nm-json-aux.c
@@ -1,12 +1,14 @@
// SPDX-License-Identifier: LGPL-2.1+
/*
- * Copyright (C) 2019 Red Hat, Inc.
+ * Copyright (C) 2017 - 2019 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-json-aux.h"
+#include <dlfcn.h>
+
/*****************************************************************************/
static void
@@ -96,9 +98,9 @@ _gstr_append_string_len (GString *gstr,
}
void
-nm_json_aux_gstr_append_string_len (GString *gstr,
- const char *str,
- gsize n)
+nm_json_gstr_append_string_len (GString *gstr,
+ const char *str,
+ gsize n)
{
g_return_if_fail (gstr);
@@ -106,8 +108,8 @@ nm_json_aux_gstr_append_string_len (GString *gstr,
}
void
-nm_json_aux_gstr_append_string (GString *gstr,
- const char *str)
+nm_json_gstr_append_string (GString *gstr,
+ const char *str)
{
g_return_if_fail (gstr);
@@ -118,14 +120,14 @@ nm_json_aux_gstr_append_string (GString *gstr,
}
void
-nm_json_aux_gstr_append_obj_name (GString *gstr,
- const char *key,
- char start_container)
+nm_json_gstr_append_obj_name (GString *gstr,
+ const char *key,
+ char start_container)
{
g_return_if_fail (gstr);
g_return_if_fail (key);
- nm_json_aux_gstr_append_string (gstr, key);
+ nm_json_gstr_append_string (gstr, key);
if (start_container != '\0') {
nm_assert (NM_IN_SET (start_container, '[', '{'));
@@ -133,3 +135,136 @@ nm_json_aux_gstr_append_obj_name (GString *gstr,
} else
g_string_append (gstr, ": ");
}
+
+/*****************************************************************************/
+
+typedef struct {
+ NMJsonVt vt;
+ void *dl_handle;
+} NMJsonVtInternal;
+
+static NMJsonVtInternal *
+_nm_json_vt_internal_load (void)
+{
+ NMJsonVtInternal *v;
+ const char *soname;
+ void *handle;
+
+ v = g_new0 (NMJsonVtInternal, 1);
+
+#if WITH_JANSSON && defined (JANSSON_SONAME)
+ G_STATIC_ASSERT_EXPR (NM_STRLEN (JANSSON_SONAME) > 0);
+ nm_assert (strlen (JANSSON_SONAME) > 0);
+ soname = JANSSON_SONAME;
+#elif !WITH_JANSSON && !defined (JANSSON_SONAME)
+ soname = NULL;
+#else
+#error "WITH_JANSON and JANSSON_SONAME are defined inconsistently."
+#endif
+
+ if (!soname)
+ return v;
+
+ handle = dlopen (soname, RTLD_LAZY
+ | RTLD_LOCAL
+ | RTLD_NODELETE
+#if !defined (ASAN_BUILD)
+ | RTLD_DEEPBIND
+#endif
+ | 0);
+ if (!handle)
+ return v;
+
+#define TRY_BIND_SYMBOL(symbol) \
+ G_STMT_START { \
+ void *_sym = dlsym (handle, #symbol); \
+ \
+ if (!_sym) \
+ goto fail_symbol; \
+ v->vt.nm_ ## symbol = _sym; \
+ } G_STMT_END
+
+ TRY_BIND_SYMBOL (json_array);
+ TRY_BIND_SYMBOL (json_array_append_new);
+ TRY_BIND_SYMBOL (json_array_get);
+ TRY_BIND_SYMBOL (json_array_size);
+ TRY_BIND_SYMBOL (json_delete);
+ TRY_BIND_SYMBOL (json_dumps);
+ TRY_BIND_SYMBOL (json_false);
+ TRY_BIND_SYMBOL (json_integer);
+ TRY_BIND_SYMBOL (json_integer_value);
+ TRY_BIND_SYMBOL (json_loads);
+ TRY_BIND_SYMBOL (json_object);
+ TRY_BIND_SYMBOL (json_object_del);
+ TRY_BIND_SYMBOL (json_object_get);
+ TRY_BIND_SYMBOL (json_object_iter);
+ TRY_BIND_SYMBOL (json_object_iter_key);
+ TRY_BIND_SYMBOL (json_object_iter_next);
+ TRY_BIND_SYMBOL (json_object_iter_value);
+ TRY_BIND_SYMBOL (json_object_key_to_iter);
+ TRY_BIND_SYMBOL (json_object_set_new);
+ TRY_BIND_SYMBOL (json_object_size);
+ TRY_BIND_SYMBOL (json_string);
+ TRY_BIND_SYMBOL (json_string_value);
+ TRY_BIND_SYMBOL (json_true);
+
+ v->vt.loaded = TRUE;
+ v->dl_handle = handle;
+ return v;
+
+fail_symbol:
+ dlclose (&handle);
+ *v = (NMJsonVtInternal) { };
+ return v;
+}
+
+const NMJsonVt *_nm_json_vt_ptr = NULL;
+
+const NMJsonVt *
+_nm_json_vt_init (void)
+{
+ NMJsonVtInternal *v;
+
+again:
+ v = g_atomic_pointer_get ((gpointer *) &_nm_json_vt_ptr);
+ if (G_UNLIKELY (!v)) {
+ v = _nm_json_vt_internal_load ();
+ if (!g_atomic_pointer_compare_and_exchange ((gpointer *) &_nm_json_vt_ptr, NULL, v)) {
+ if (v->dl_handle)
+ dlclose (v->dl_handle);
+ g_free (v);
+ goto again;
+ }
+
+ /* we transfer ownership. */
+ }
+
+ nm_assert (v && v == g_atomic_pointer_get ((gpointer *) &_nm_json_vt_ptr));
+ return &v->vt;
+}
+
+const NMJsonVt *
+nmtst_json_vt_reset (gboolean loaded)
+{
+ NMJsonVtInternal *v_old;
+ NMJsonVtInternal *v;
+
+ v_old = g_atomic_pointer_get ((gpointer *) &_nm_json_vt_ptr);
+
+ if (!loaded) {
+ /* load a fake instance for testing. */
+ v = g_new0 (NMJsonVtInternal, 1);
+ } else
+ v = _nm_json_vt_internal_load ();
+
+ if (!g_atomic_pointer_compare_and_exchange ((gpointer *) &_nm_json_vt_ptr, v_old, v))
+ g_assert_not_reached ();
+
+ if (v_old) {
+ if (v_old->dl_handle)
+ dlclose (v_old->dl_handle);
+ g_free ((gpointer *) v_old);
+ }
+
+ return v->vt.loaded ? &v->vt : NULL;
+}
diff --git a/shared/nm-glib-aux/nm-json-aux.h b/shared/nm-glib-aux/nm-json-aux.h
index ed3be3768f..082b9e5205 100644
--- a/shared/nm-glib-aux/nm-json-aux.h
+++ b/shared/nm-glib-aux/nm-json-aux.h
@@ -1,49 +1,281 @@
// SPDX-License-Identifier: LGPL-2.1+
/*
- * Copyright (C) 2019 Red Hat, Inc.
+ * Copyright (C) 2017 - 2019 Red Hat, Inc.
*/
#ifndef __NM_JSON_AUX_H__
#define __NM_JSON_AUX_H__
+#include "nm-value-type.h"
+
/*****************************************************************************/
static inline GString *
-nm_json_aux_gstr_append_delimiter (GString *gstr)
+nm_json_gstr_append_delimiter (GString *gstr)
{
g_string_append (gstr, ", ");
return gstr;
}
-void nm_json_aux_gstr_append_string_len (GString *gstr,
- const char *str,
- gsize n);
+void nm_json_gstr_append_string_len (GString *gstr,
+ const char *str,
+ gsize n);
-void nm_json_aux_gstr_append_string (GString *gstr,
- const char *str);
+void nm_json_gstr_append_string (GString *gstr,
+ const char *str);
static inline void
-nm_json_aux_gstr_append_bool (GString *gstr,
- gboolean v)
+nm_json_gstr_append_bool (GString *gstr,
+ gboolean v)
{
g_string_append (gstr, v ? "true" : "false");
}
static inline void
-nm_json_aux_gstr_append_int64 (GString *gstr,
- gint64 v)
+nm_json_gstr_append_int64 (GString *gstr,
+ gint64 v)
{
g_string_append_printf (gstr, "%"G_GINT64_FORMAT, v);
}
-void nm_json_aux_gstr_append_obj_name (GString *gstr,
- const char *key,
- char start_container);
+void nm_json_gstr_append_obj_name (GString *gstr,
+ const char *key,
+ char start_container);
+
+/*****************************************************************************/
+
+#define NM_JSON_REJECT_DUPLICATES 0x1
+
+typedef enum {
+ NM_JSON_OBJECT,
+ NM_JSON_ARRAY,
+ NM_JSON_STRING,
+ NM_JSON_INTEGER,
+ NM_JSON_REAL,
+ NM_JSON_TRUE,
+ NM_JSON_FALSE,
+ NM_JSON_NULL,
+} nm_json_type;
+
+typedef struct nm_json_t {
+ nm_json_type type;
+ volatile size_t refcount;
+} nm_json_t;
+
+typedef long long nm_json_int_t;
+
+#define NM_JSON_ERROR_TEXT_LENGTH 160
+#define NM_JSON_ERROR_SOURCE_LENGTH 80
+
+typedef struct nm_json_error_t {
+ int line;
+ int column;
+ int position;
+ char source[NM_JSON_ERROR_SOURCE_LENGTH];
+ char text[NM_JSON_ERROR_TEXT_LENGTH];
+} nm_json_error_t;
+
+typedef struct {
+ gboolean loaded;
+ char *(*nm_json_dumps) (const nm_json_t *json, size_t flags);
+ const char *(*nm_json_object_iter_key) (void *iter);
+ const char *(*nm_json_string_value) (const nm_json_t *json);
+ int (*nm_json_array_append_new) (nm_json_t *json, nm_json_t *value);
+ int (*nm_json_object_del) (nm_json_t *json, const char *key);
+ int (*nm_json_object_set_new) (nm_json_t *json, const char *key, nm_json_t *value);
+ nm_json_int_t (*nm_json_integer_value) (const nm_json_t *json);
+ nm_json_t *(*nm_json_array) (void);
+ nm_json_t *(*nm_json_array_get) (const nm_json_t *json, size_t index);
+ nm_json_t *(*nm_json_false) (void);
+ nm_json_t *(*nm_json_integer) (nm_json_int_t value);
+ nm_json_t *(*nm_json_loads) (const char *string, size_t flags, nm_json_error_t *error);
+ nm_json_t *(*nm_json_object) (void);
+ nm_json_t *(*nm_json_object_get) (const nm_json_t *json, const char *key);
+ nm_json_t *(*nm_json_object_iter_value) (void *);
+ nm_json_t *(*nm_json_string) (const char *value);
+ nm_json_t *(*nm_json_true) (void);
+ size_t (*nm_json_array_size) (const nm_json_t *json);
+ size_t (*nm_json_object_size) (const nm_json_t *json);
+ void (*nm_json_delete) (nm_json_t *json);
+ void *(*nm_json_object_iter) (nm_json_t *json);
+ void *(*nm_json_object_iter_next) (nm_json_t *json, void *iter);
+ void *(*nm_json_object_key_to_iter) (const char *key);
+} NMJsonVt;
+
+extern const NMJsonVt *_nm_json_vt_ptr;
+
+const NMJsonVt *_nm_json_vt_init (void);
+
+static inline const NMJsonVt *
+_nm_json_vt (void)
+{
+ const NMJsonVt *vt;
+
+ vt = g_atomic_pointer_get ((gpointer *) &_nm_json_vt_ptr);
+ if (G_UNLIKELY (!vt)) {
+ vt = _nm_json_vt_init ();
+ nm_assert (vt);
+ }
+ return vt;
+}
+
+static inline const NMJsonVt *
+nm_json_vt (void)
+{
+ const NMJsonVt *vt;
+
+ vt = _nm_json_vt();
+ return vt->loaded ? vt : NULL;
+}
+
+static inline const NMJsonVt *
+nm_json_vt_assert (void)
+{
+ const NMJsonVt *vt;
+
+ vt = _nm_json_vt();
+ nm_assert (vt->loaded);
+ return vt;
+}
+
+const NMJsonVt *nmtst_json_vt_reset (gboolean loaded);
+
+/*****************************************************************************/
+
+#define nm_json_boolean(vt, val) \
+ ((val) ? (vt)->nm_json_true () : (vt)->nm_json_false ())
+
+static inline void
+nm_json_decref (const NMJsonVt *vt, nm_json_t *json)
+{
+ /* Our ref-counting is not threadsafe, unlike libjansson's. But we never
+ * share one json_t instance between threads, and if we would, we would very likely
+ * wrap a mutex around it. */
+ if ( json
+ && json->refcount != (size_t) -1
+ && --json->refcount == 0)
+ vt->nm_json_delete (json);
+}
+
+static inline void
+_nm_auto_decref_json (nm_json_t **p_json)
+{
+ if ( *p_json
+ && (*p_json)->refcount != (size_t) -1
+ && --(*p_json)->refcount == 0)
+ nm_json_vt ()->nm_json_delete (*p_json);
+}
+
+#define nm_auto_decref_json nm_auto(_nm_auto_decref_json)
+
+/*****************************************************************************/
+
+/* the following are implemented as pure macros in jansson.h.
+ * They can be used directly, however, add a nm_json* variant,
+ * to make it explict we don't accidentally use jansson ABI. */
+
+#define nm_json_typeof(json) ((json)->type)
+#define nm_json_is_object(json) ((json) && nm_json_typeof(json) == NM_JSON_OBJECT)
+#define nm_json_is_array(json) ((json) && nm_json_typeof(json) == NM_JSON_ARRAY)
+#define nm_json_is_string(json) ((json) && nm_json_typeof(json) == NM_JSON_STRING)
+#define nm_json_is_integer(json) ((json) && nm_json_typeof(json) == NM_JSON_INTEGER)
+#define nm_json_is_real(json) ((json) && nm_json_typeof(json) == NM_JSON_REAL)
+#define nm_json_is_number(json) (nm_json_is_integer(json) || nm_json_is_real(json))
+#define nm_json_is_true(json) ((json) && nm_json_typeof(json) == NM_JSON_TRUE)
+#define nm_json_is_false(json) ((json) && nm_json_typeof(json) == NM_JSON_FALSE)
+#define nm_json_boolean_value nm_json_is_true
+#define nm_json_is_boolean(json) (nm_json_is_true(json) || nm_json_is_false(json))
+#define nm_json_is_null(json) ((json) && nm_json_typeof(json) == NM_JSON_NULL)
+
+#define nm_json_array_foreach(vt, array, index, value) \
+ for(index = 0; \
+ index < vt->nm_json_array_size (array) && (value = vt->nm_json_array_get (array, index)); \
+ index++)
+
+#define nm_json_object_foreach(vt, object, key, value) \
+ for(key = vt->nm_json_object_iter_key (vt->nm_json_object_iter (object)); \
+ key && (value = vt->nm_json_object_iter_value (vt->nm_json_object_key_to_iter (key))); \
+ key = vt->nm_json_object_iter_key (vt->nm_json_object_iter_next (object, vt->nm_json_object_key_to_iter (key))))
+
+/*****************************************************************************/
+
+static inline int
+nm_jansson_json_as_bool (const nm_json_t *elem,
+ bool *out_val)
+{
+ if (!elem)
+ return 0;
+
+ if (!nm_json_is_boolean (elem))
+ return -EINVAL;
+
+ NM_SET_OUT (out_val, nm_json_boolean_value (elem));
+ return 1;
+}
+
+static inline int
+nm_jansson_json_as_int32 (const NMJsonVt *vt,
+ const nm_json_t *elem,
+ gint32 *out_val)
+{
+ nm_json_int_t v;
+
+ if (!elem)
+ return 0;
+
+ if (!nm_json_is_integer (elem))
+ return -EINVAL;
+
+ v = vt->nm_json_integer_value (elem);
+ if ( v < (gint64) G_MININT32
+ || v > (gint64) G_MAXINT32)
+ return -ERANGE;
+
+ NM_SET_OUT (out_val, v);
+ return 1;
+}
+
+static inline int
+nm_jansson_json_as_int (const NMJsonVt *vt,
+ const nm_json_t *elem,
+ int *out_val)
+{
+ nm_json_int_t v;
+
+ if (!elem)
+ return 0;
+
+ if (!nm_json_is_integer (elem))
+ return -EINVAL;
+
+ v = vt->nm_json_integer_value (elem);
+ if ( v < (gint64) G_MININT
+ || v > (gint64) G_MAXINT)
+ return -ERANGE;
+
+ NM_SET_OUT (out_val, v);
+ return 1;
+}
+
+static inline int
+nm_jansson_json_as_string (const NMJsonVt *vt,
+ const nm_json_t *elem,
+ const char **out_val)
+{
+ if (!elem)
+ return 0;
+
+ if (!nm_json_is_string (elem))
+ return -EINVAL;
+
+ NM_SET_OUT (out_val, vt->nm_json_string_value (elem));
+ return 1;
+}
/*****************************************************************************/
#ifdef NM_VALUE_TYPE_DEFINE_FUNCTIONS
-#include "nm-value-type.h"
+
static inline void
nm_value_type_to_json (NMValueType value_type,
GString *gstr,
@@ -53,17 +285,38 @@ nm_value_type_to_json (NMValueType value_type,
nm_assert (gstr);
switch (value_type) {
- case NM_VALUE_TYPE_BOOL: nm_json_aux_gstr_append_bool (gstr, *((const bool *) p_field)); return;
- case NM_VALUE_TYPE_INT32: nm_json_aux_gstr_append_int64 (gstr, *((const gint32 *) p_field)); return;
- case NM_VALUE_TYPE_INT: nm_json_aux_gstr_append_int64 (gstr, *((const int *) p_field)); return;
- case NM_VALUE_TYPE_STRING: nm_json_aux_gstr_append_string (gstr, *((const char *const *) p_field)); return;
+ case NM_VALUE_TYPE_BOOL: nm_json_gstr_append_bool (gstr, *((const bool *) p_field)); return;
+ case NM_VALUE_TYPE_INT32: nm_json_gstr_append_int64 (gstr, *((const gint32 *) p_field)); return;
+ case NM_VALUE_TYPE_INT: nm_json_gstr_append_int64 (gstr, *((const int *) p_field)); return;
+ case NM_VALUE_TYPE_STRING: nm_json_gstr_append_string (gstr, *((const char *const *) p_field)); return;
case NM_VALUE_TYPE_UNSPEC:
break;
}
nm_assert_not_reached ();
}
-#endif
-/*****************************************************************************/
+static inline gboolean
+nm_value_type_from_json (const NMJsonVt *vt,
+ NMValueType value_type,
+ const nm_json_t *elem,
+ gpointer out_val)
+{
+ switch (value_type) {
+ case NM_VALUE_TYPE_BOOL: return (nm_jansson_json_as_bool (elem, out_val) > 0);
+ case NM_VALUE_TYPE_INT32: return (nm_jansson_json_as_int32 (vt, elem, out_val) > 0);
+ case NM_VALUE_TYPE_INT: return (nm_jansson_json_as_int (vt, elem, out_val) > 0);
+
+ /* warning: this overwrites/leaks the previous value. You better have *out_val
+ * point to uninitialized memory or NULL. */
+ case NM_VALUE_TYPE_STRING: return (nm_jansson_json_as_string (vt, elem, out_val) > 0);
+
+ case NM_VALUE_TYPE_UNSPEC:
+ break;
+ }
+ nm_assert_not_reached ();
+ return FALSE;
+}
+
+#endif /* NM_VALUE_TYPE_DEFINE_FUNCTIONS */
-#endif /* __NM_JSON_AUX_H__ */
+#endif /* __NM_JSON_AUX_H__ */
diff --git a/shared/nm-glib-aux/tests/meson.build b/shared/nm-glib-aux/tests/meson.build
index f6328db916..8136eff935 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 0000000000..cde1bef3b0
--- /dev/null
+++ b/shared/nm-glib-aux/tests/test-json-aux.c
@@ -0,0 +1,163 @@
+// 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/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index 934c4901f9..935ea9fdf8 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -15,6 +15,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include "nm-glib-aux/nm-json-aux.h"
#include "nm-utils.h"
#include "nm-setting-connection.h"
#include "nm-setting-wired.h"
@@ -9129,7 +9130,7 @@ test_read_team_master_invalid (gconstpointer user_data)
gs_free_error GError *error = NULL;
gs_unref_object NMConnection *connection = NULL;
- if (WITH_JSON_VALIDATION) {
+ if (nm_json_vt ()) {
_connection_from_file_fail (PATH_NAME, NULL, TYPE_ETHERNET, &error);
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);