libnm,json: merge branch 'th/libnm_jansson-2'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/559
This commit is contained in:
Thomas Haller 2020-07-09 13:49:25 +02:00
commit 341111ff31
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
20 changed files with 855 additions and 527 deletions

1
.gitignore vendored
View file

@ -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

View file

@ -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) \

View file

@ -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

View file

@ -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"

View file

@ -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],

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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

View file

@ -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 *

View file

@ -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);
int with_json_vt;
/* 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);
for (with_json_vt = 0; with_json_vt < 2; with_json_vt++) {
const NMJsonVt *vt;
/* 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);
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);
}
/*****************************************************************************/

View file

@ -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;
}

View file

@ -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 *
@ -978,6 +970,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,
@ -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",

View file

@ -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'

View file

@ -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')

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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);
#endif /* __NM_JSON_AUX_H__ */
/* 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__ */

View file

@ -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

View file

@ -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 ();
}

View file

@ -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);