2019-09-10 11:19:01 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2014-07-24 08:53:33 -04:00
|
|
|
/*
|
2019-10-01 09:20:35 +02:00
|
|
|
* Copyright (C) 2008 - 2018 Red Hat, Inc.
|
2014-07-24 08:53:33 -04:00
|
|
|
*/
|
|
|
|
|
|
2015-04-10 09:16:11 +02:00
|
|
|
#define NM_GLIB_COMPAT_H_TEST
|
|
|
|
|
|
2016-02-19 14:57:48 +01:00
|
|
|
#include "nm-default.h"
|
2014-11-13 10:07:02 -05:00
|
|
|
|
shared: add nm_utils_g_main_context_create_integrate_source() for integrating a GMainContext in another
We will rework NMClient entirely. Then, the synchronous initialization will also use
the asynchronous code paths. The difference will be that with synchronous initialization,
all D-Bus interaction will be done with an internal GMainContext as current thread default,
and that internal context will run until initialization completes.
Note that even after initialization completes, it cannot be swapped back to the user's
(outer) GMainContext. That is because contexts are essentially the queue for our
D-Bus events, and we cannot swap from one queue to the other in a race
free manner (or a full resync). In other words, the two contexts are not in sync,
so after using the internal context NMClient needs to stick to that (at least, until
the name owner gets lost, which gives an opportunity to resync and switch back to the
user's main context).
We thus need to hook the internal (inner) GMainContext with the user's (outer) context,
so when the user iterates the outer context, events on the inner context get dispatched.
Add nm_utils_g_main_context_create_integrate_source() to create such a GSource for
integrating two contexts.
Note that the use-case here is limited: the integrated, inner main context must
not be explicitly iterated except from being dispatched by the integrating
source. Otherwise, you'd get recursive runs, possible deadlocks and general
ugliness. NMClient must show restrain how to use the inner context while it is
integrated.
2019-11-02 16:55:43 +01:00
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
2019-04-14 13:36:32 +02:00
|
|
|
#include "nm-std-aux/c-list-util.h"
|
2019-04-15 08:16:00 +02:00
|
|
|
#include "nm-glib-aux/nm-enum-utils.h"
|
2020-06-22 19:43:35 +02:00
|
|
|
#include "nm-glib-aux/nm-str-buf.h"
|
|
|
|
|
#include "systemd/nm-sd-utils-shared.h"
|
2017-07-08 13:30:00 +02:00
|
|
|
|
2016-02-19 14:57:48 +01:00
|
|
|
#include "nm-utils.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
#include "nm-setting-private.h"
|
2014-10-21 22:09:52 -04:00
|
|
|
#include "nm-utils.h"
|
2015-04-01 11:47:42 +02:00
|
|
|
#include "nm-utils-private.h"
|
2014-10-21 22:09:52 -04:00
|
|
|
#include "nm-core-internal.h"
|
2015-06-04 15:05:33 +02:00
|
|
|
#include "nm-core-tests-enum-types.h"
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
#include "nm-team-utils.h"
|
2014-10-21 22:09:52 -04:00
|
|
|
|
|
|
|
|
#include "nm-setting-8021x.h"
|
|
|
|
|
#include "nm-setting-adsl.h"
|
|
|
|
|
#include "nm-setting-bluetooth.h"
|
|
|
|
|
#include "nm-setting-bond.h"
|
|
|
|
|
#include "nm-setting-bridge.h"
|
|
|
|
|
#include "nm-setting-bridge-port.h"
|
|
|
|
|
#include "nm-setting-cdma.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
#include "nm-setting-connection.h"
|
libnm, cli, ifcfg-rh: add NMSettingEthtool setting
Note that in NetworkManager API (D-Bus, libnm, and nmcli),
the features are called "feature-xyz". The "feature-" prefix
is used, because NMSettingEthtool possibly will gain support
for options that are not only -K|--offload|--features, for
example -C|--coalesce.
The "xzy" suffix is either how ethtool utility calls the feature
("tso", "rx"). Or, if ethtool utility specifies no alias for that
feature, it's the name from kernel's ETH_SS_FEATURES ("tx-tcp6-segmentation").
If possible, we prefer ethtool utility's naming.
Also note, how the features "feature-sg", "feature-tso", and
"feature-tx" actually refer to multiple underlying kernel features
at once. This too follows what ethtool utility does.
The functionality is not yet implemented server-side.
2018-07-16 23:37:55 +02:00
|
|
|
#include "nm-setting-ethtool.h"
|
2014-10-21 22:09:52 -04:00
|
|
|
#include "nm-setting-generic.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
#include "nm-setting-gsm.h"
|
2014-10-21 22:09:52 -04:00
|
|
|
#include "nm-setting-infiniband.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
#include "nm-setting-ip4-config.h"
|
2014-10-21 22:09:52 -04:00
|
|
|
#include "nm-setting-ip6-config.h"
|
|
|
|
|
#include "nm-setting-olpc-mesh.h"
|
|
|
|
|
#include "nm-setting-ppp.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
#include "nm-setting-pppoe.h"
|
|
|
|
|
#include "nm-setting-serial.h"
|
2014-10-21 22:09:52 -04:00
|
|
|
#include "nm-setting-team.h"
|
|
|
|
|
#include "nm-setting-team-port.h"
|
2017-03-24 12:41:04 +01:00
|
|
|
#include "nm-setting-user.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
#include "nm-setting-vlan.h"
|
2014-10-21 22:09:52 -04:00
|
|
|
#include "nm-setting-vpn.h"
|
|
|
|
|
#include "nm-setting-wimax.h"
|
|
|
|
|
#include "nm-setting-wired.h"
|
|
|
|
|
#include "nm-setting-wireless.h"
|
|
|
|
|
#include "nm-setting-wireless-security.h"
|
2018-03-09 10:51:49 +01:00
|
|
|
#include "nm-setting-wpan.h"
|
2014-10-21 22:09:52 -04:00
|
|
|
#include "nm-simple-connection.h"
|
2020-01-02 07:37:59 +01:00
|
|
|
#include "nm-keyfile/nm-keyfile-internal.h"
|
2019-04-15 08:16:00 +02:00
|
|
|
#include "nm-glib-aux/nm-dedup-multi.h"
|
shared: build helper "libnm-libnm-core-{intern|aux}.la" library for libnm-core
"libnm-core" implements common functionality for "NetworkManager" and
"libnm".
Note that clients like "nmcli" cannot access the internal API provided
by "libnm-core". So, if nmcli wants to do something that is also done by
"libnm-core", , "libnm", or "NetworkManager", the code would have to be
duplicated.
Instead, such code can be in "libnm-libnm-core-{intern|aux}.la".
Note that:
0) "libnm-libnm-core-intern.la" is used by libnm-core itsself.
On the other hand, "libnm-libnm-core-aux.la" is not used by
libnm-core, but provides utilities on top of it.
1) they both extend "libnm-core" with utlities that are not public
API of libnm itself. Maybe part of the code should one day become
public API of libnm. On the other hand, this is code for which
we may not want to commit to a stable interface or which we
don't want to provide as part of the API.
2) "libnm-libnm-core-intern.la" is statically linked by "libnm-core"
and thus directly available to "libnm" and "NetworkManager".
On the other hand, "libnm-libnm-core-aux.la" may be used by "libnm"
and "NetworkManager".
Both libraries may be statically linked by libnm clients (like
nmcli).
3) it must only use glib, libnm-glib-aux.la, and the public API
of libnm-core.
This is important: it must not use "libnm-core/nm-core-internal.h"
nor "libnm-core/nm-utils-private.h" so the static library is usable
by nmcli which couldn't access these.
Note that "shared/nm-meta-setting.c" is an entirely different case,
because it behaves differently depending on whether linking against
"libnm-core" or the client programs. As such, this file must be compiled
twice.
(cherry picked from commit af07ed01c04867e281cc3982a7ab0d244d4f8e2e)
2019-04-15 09:26:53 +02:00
|
|
|
#include "nm-libnm-core-intern/nm-ethtool-utils.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2015-06-04 15:05:33 +02:00
|
|
|
#include "test-general-enums.h"
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-06-15 15:29:10 +02:00
|
|
|
#include "nm-utils/nm-test-utils.h"
|
2016-02-19 14:57:48 +01:00
|
|
|
|
2015-11-11 13:33:46 +01:00
|
|
|
/* When passing a "bool" typed argument to a variadic function that
|
|
|
|
|
* expects a gboolean, the compiler will promote the integer type
|
|
|
|
|
* to have at least size (int). That way:
|
|
|
|
|
* g_object_set (obj, PROP_BOOL, bool_val, NULL);
|
|
|
|
|
* will just work correctly. */
|
|
|
|
|
G_STATIC_ASSERT (sizeof (gboolean) == sizeof (int));
|
|
|
|
|
G_STATIC_ASSERT (sizeof (bool) <= sizeof (int));
|
|
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2019-03-20 10:43:54 +01:00
|
|
|
static void
|
|
|
|
|
test_nm_ascii_spaces (void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
const char *const S = NM_ASCII_SPACES;
|
|
|
|
|
|
|
|
|
|
for (i = 0; S[i]; i++)
|
|
|
|
|
g_assert (!strchr (&S[i + 1], S[i]));
|
|
|
|
|
|
|
|
|
|
for (i = 0; S[i] != '\0'; i++)
|
|
|
|
|
g_assert (g_ascii_isspace (S[i]));
|
|
|
|
|
|
|
|
|
|
g_assert (!g_ascii_isspace ((char) 0));
|
|
|
|
|
for (i = 1; i < 0x100; i++) {
|
|
|
|
|
if (g_ascii_isspace ((char) i))
|
|
|
|
|
g_assert (strchr (S, (char) i));
|
|
|
|
|
else
|
|
|
|
|
g_assert (!strchr (S, (char) i));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-10-16 12:38:16 +02:00
|
|
|
typedef struct _nm_packed {
|
|
|
|
|
int v0;
|
|
|
|
|
char v1;
|
|
|
|
|
double v2;
|
|
|
|
|
guint8 v3;
|
|
|
|
|
} TestHashStruct;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_test_hash_struct (int v0, char v1, double v2, guint8 v3)
|
|
|
|
|
{
|
|
|
|
|
const TestHashStruct s = {
|
|
|
|
|
.v0 = v0,
|
|
|
|
|
.v1 = v1,
|
|
|
|
|
.v2 = v2,
|
|
|
|
|
.v3 = v3,
|
|
|
|
|
};
|
|
|
|
|
NMHashState h;
|
|
|
|
|
guint hh;
|
|
|
|
|
|
|
|
|
|
nm_hash_init (&h, 100);
|
|
|
|
|
nm_hash_update (&h, &s, sizeof (s));
|
|
|
|
|
hh = nm_hash_complete (&h);
|
|
|
|
|
|
|
|
|
|
nm_hash_init (&h, 100);
|
|
|
|
|
nm_hash_update_val (&h, v0);
|
|
|
|
|
nm_hash_update_val (&h, v1);
|
|
|
|
|
nm_hash_update_val (&h, v2);
|
|
|
|
|
nm_hash_update_val (&h, v3);
|
|
|
|
|
g_assert_cmpint (hh, ==, nm_hash_complete (&h));
|
|
|
|
|
|
|
|
|
|
nm_hash_init (&h, 100);
|
|
|
|
|
nm_hash_update_vals (&h, v0, v1, v2, v3);
|
|
|
|
|
g_assert_cmpint (hh, ==, nm_hash_complete (&h));
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-13 14:00:22 +02:00
|
|
|
static guint
|
|
|
|
|
_test_hash_str (const char *str)
|
|
|
|
|
{
|
|
|
|
|
NMHashState h;
|
|
|
|
|
guint v, v2;
|
|
|
|
|
const guint SEED = 10;
|
|
|
|
|
|
|
|
|
|
nm_hash_init (&h, SEED);
|
2017-10-13 17:16:23 +02:00
|
|
|
nm_hash_update_str0 (&h, str);
|
2017-10-13 14:00:22 +02:00
|
|
|
v = nm_hash_complete (&h);
|
|
|
|
|
|
2017-10-13 17:16:23 +02:00
|
|
|
/* assert that hashing a string and a buffer yields the
|
|
|
|
|
* same result.
|
|
|
|
|
*
|
|
|
|
|
* I think that is a desirable property. */
|
|
|
|
|
nm_hash_init (&h, SEED);
|
|
|
|
|
nm_hash_update_mem (&h, str, strlen (str));
|
|
|
|
|
v2 = nm_hash_complete (&h);
|
|
|
|
|
|
2017-10-13 14:00:22 +02:00
|
|
|
g_assert (v == v2);
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-16 12:38:16 +02:00
|
|
|
#define _test_hash_vals(type, ...) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
NMHashState h0, h1, h2, h3; \
|
|
|
|
|
const type v[] = { __VA_ARGS__ }; \
|
|
|
|
|
guint h; \
|
|
|
|
|
guint i; \
|
|
|
|
|
\
|
|
|
|
|
nm_hash_init (&h0, 10); \
|
|
|
|
|
nm_hash_init (&h1, 10); \
|
|
|
|
|
nm_hash_init (&h2, 10); \
|
|
|
|
|
nm_hash_init (&h3, 10); \
|
|
|
|
|
\
|
|
|
|
|
/* assert that it doesn't matter, whether we hash the values individually,
|
|
|
|
|
* or all at once, or via the convenience macros nm_hash_update_val()
|
|
|
|
|
* and nm_hash_update_vals(). */ \
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (v); i++) { \
|
|
|
|
|
nm_hash_update (&h0, &v[i], sizeof (type)); \
|
|
|
|
|
nm_hash_update_val (&h1, v[i]); \
|
|
|
|
|
} \
|
|
|
|
|
nm_hash_update_vals (&h2, __VA_ARGS__); \
|
|
|
|
|
nm_hash_update (&h3, v, sizeof (v)); \
|
|
|
|
|
\
|
|
|
|
|
h = nm_hash_complete (&h0); \
|
|
|
|
|
g_assert_cmpint (h, ==, nm_hash_complete (&h1)); \
|
|
|
|
|
g_assert_cmpint (h, ==, nm_hash_complete (&h2)); \
|
|
|
|
|
g_assert_cmpint (h, ==, nm_hash_complete (&h3)); \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
2017-10-13 14:00:22 +02:00
|
|
|
static void
|
|
|
|
|
test_nm_hash (void)
|
|
|
|
|
{
|
2017-11-15 15:39:50 +01:00
|
|
|
g_assert (nm_hash_static (0));
|
|
|
|
|
g_assert (nm_hash_static (777));
|
|
|
|
|
|
2017-11-15 15:14:19 +01:00
|
|
|
g_assert (nm_hash_str (NULL));
|
|
|
|
|
g_assert (nm_hash_str (""));
|
|
|
|
|
g_assert (nm_hash_str ("a"));
|
|
|
|
|
|
2017-11-15 15:33:32 +01:00
|
|
|
g_assert (nm_hash_ptr (NULL));
|
|
|
|
|
g_assert (nm_hash_ptr (""));
|
|
|
|
|
g_assert (nm_hash_ptr ("a"));
|
|
|
|
|
|
2017-10-13 14:00:22 +02:00
|
|
|
_test_hash_str ("");
|
|
|
|
|
_test_hash_str ("a");
|
|
|
|
|
_test_hash_str ("aa");
|
|
|
|
|
_test_hash_str ("diceros bicornis longipes");
|
2017-10-16 12:38:16 +02:00
|
|
|
|
|
|
|
|
/* assert that nm_hash_update_vals() is the same as calling nm_hash_update_val() multiple times. */
|
|
|
|
|
_test_hash_vals (int, 1);
|
|
|
|
|
_test_hash_vals (int, 1, 2);
|
|
|
|
|
_test_hash_vals (int, 1, 2, 3);
|
|
|
|
|
_test_hash_vals (int, 1, 2, 3, 4);
|
|
|
|
|
_test_hash_vals (long, 1l);
|
|
|
|
|
_test_hash_vals (long, 1l, 2l, 3l, 4l, 5l);
|
|
|
|
|
|
|
|
|
|
_test_hash_struct (10, 'a', 5.4, 7);
|
|
|
|
|
_test_hash_struct (-10, '\0', -5.4e49, 255);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 1, 0), ==, 0x002);
|
|
|
|
|
g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 1, 1), ==, 0x003);
|
|
|
|
|
g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 1, 1, 0, 0, 0, 0), ==, 0x030);
|
|
|
|
|
g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 1, 1, 0, 0, 0, 1), ==, 0x031);
|
|
|
|
|
g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint8, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031);
|
|
|
|
|
g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint16, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031);
|
|
|
|
|
g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint16, 0, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x031);
|
|
|
|
|
g_assert_cmpint (NM_HASH_COMBINE_BOOLS (guint16, 1, 0, 0, 1, 1, 0, 0, 0, 1), ==, 0x131);
|
2017-10-13 14:00:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-08-15 12:32:37 +02:00
|
|
|
static void
|
|
|
|
|
test_nm_g_slice_free_fcn (void)
|
|
|
|
|
{
|
|
|
|
|
gpointer p;
|
2017-12-07 12:31:55 +01:00
|
|
|
struct {
|
|
|
|
|
char a1;
|
|
|
|
|
char a2;
|
|
|
|
|
} xx;
|
2017-08-15 12:32:37 +02:00
|
|
|
|
|
|
|
|
p = g_slice_new (gint64);
|
|
|
|
|
(nm_g_slice_free_fcn (gint64)) (p);
|
|
|
|
|
|
|
|
|
|
p = g_slice_new (gint32);
|
|
|
|
|
(nm_g_slice_free_fcn (gint32)) (p);
|
|
|
|
|
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
p = g_slice_new (int);
|
|
|
|
|
(nm_g_slice_free_fcn (int)) (p);
|
2017-08-15 12:32:37 +02:00
|
|
|
|
|
|
|
|
p = g_slice_new (gint64);
|
|
|
|
|
nm_g_slice_free_fcn_gint64 (p);
|
2017-12-07 12:31:55 +01:00
|
|
|
|
|
|
|
|
p = g_slice_alloc (sizeof (xx));
|
|
|
|
|
(nm_g_slice_free_fcn (xx)) (p);
|
2017-08-15 12:32:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-09-14 19:14:01 +02:00
|
|
|
static void
|
2019-04-03 17:32:59 +02:00
|
|
|
_do_test_nm_utils_strsplit_set_f_one (NMUtilsStrsplitSetFlags flags,
|
|
|
|
|
const char *str,
|
|
|
|
|
gsize words_len,
|
|
|
|
|
const char *const*exp_words)
|
2017-09-14 19:14:01 +02:00
|
|
|
{
|
2019-04-16 12:34:11 +02:00
|
|
|
#define DELIMITERS " \n"
|
|
|
|
|
#define DELIMITERS_C ' ', '\n'
|
2019-04-03 17:32:59 +02:00
|
|
|
|
2017-09-14 19:14:01 +02:00
|
|
|
gs_free const char **words = NULL;
|
2019-04-03 17:32:59 +02:00
|
|
|
gsize i, j, k;
|
|
|
|
|
const gboolean f_allow_escaping = NM_FLAGS_HAS (flags, NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING);
|
|
|
|
|
const gboolean f_preserve_empty = NM_FLAGS_HAS (flags, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY);
|
|
|
|
|
const char *s1;
|
|
|
|
|
gsize initial_offset;
|
|
|
|
|
gs_strfreev char **words_g = NULL;
|
|
|
|
|
|
|
|
|
|
g_assert (!NM_FLAGS_ANY (flags, ~( NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING
|
|
|
|
|
| NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY)));
|
|
|
|
|
|
|
|
|
|
/* assert that the epected words are valid (and don't contain unescaped delimiters). */
|
|
|
|
|
for (i = 0; i < words_len; i++) {
|
|
|
|
|
const char *w = exp_words[i];
|
|
|
|
|
|
|
|
|
|
g_assert (w);
|
|
|
|
|
if (!f_preserve_empty)
|
|
|
|
|
g_assert (w[0]);
|
|
|
|
|
for (k = 0; w[k]; ) {
|
|
|
|
|
if ( f_allow_escaping
|
|
|
|
|
&& w[k] == '\\') {
|
|
|
|
|
k++;
|
|
|
|
|
if (w[k] == '\0')
|
|
|
|
|
break;
|
|
|
|
|
k++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
g_assert (!NM_IN_SET (w[k], DELIMITERS_C));
|
|
|
|
|
k++;
|
|
|
|
|
}
|
|
|
|
|
if (!f_allow_escaping)
|
|
|
|
|
g_assert (!NM_STRCHAR_ANY (w, ch, NM_IN_SET (ch, DELIMITERS_C)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initial_offset = (f_preserve_empty || !str)
|
|
|
|
|
? 0u
|
|
|
|
|
: strspn (str, DELIMITERS);
|
|
|
|
|
|
|
|
|
|
/* first compare our expected values with what g_strsplit_set() would
|
|
|
|
|
* do. */
|
|
|
|
|
words_g = str ? g_strsplit_set (str, DELIMITERS, -1) : NULL;
|
|
|
|
|
if (str == NULL) {
|
|
|
|
|
g_assert_cmpint (words_len, ==, 0);
|
|
|
|
|
g_assert (!words_g);
|
|
|
|
|
} else if (nm_streq0 (str, "")) {
|
|
|
|
|
g_assert_cmpint (words_len, ==, 0);
|
|
|
|
|
g_assert (words_g);
|
|
|
|
|
g_assert (!words_g[0]);
|
|
|
|
|
} else {
|
|
|
|
|
g_assert (words_g);
|
|
|
|
|
g_assert (words_g[0]);
|
|
|
|
|
if (!f_allow_escaping) {
|
|
|
|
|
if (!f_preserve_empty) {
|
|
|
|
|
for (i = 0, j = 0; words_g[i]; i++) {
|
|
|
|
|
if (words_g[i][0] == '\0')
|
|
|
|
|
g_free (words_g[i]);
|
|
|
|
|
else
|
|
|
|
|
words_g[j++] = words_g[i];
|
|
|
|
|
}
|
|
|
|
|
words_g[j] = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (f_preserve_empty)
|
|
|
|
|
g_assert_cmpint (words_len, >, 0);
|
|
|
|
|
for (i = 0; i < words_len; i++) {
|
|
|
|
|
g_assert (exp_words[i]);
|
|
|
|
|
g_assert_cmpstr (exp_words[i], ==, words_g[i]);
|
|
|
|
|
}
|
|
|
|
|
g_assert (words_g[words_len] == NULL);
|
|
|
|
|
g_assert_cmpint (NM_PTRARRAY_LEN (words_g), ==, words_len);
|
|
|
|
|
g_assert (_nm_utils_strv_cmp_n (exp_words, words_len, NM_CAST_STRV_CC (words_g), -1) == 0);
|
|
|
|
|
}
|
2019-04-03 15:44:19 +02:00
|
|
|
}
|
2017-09-14 19:14:01 +02:00
|
|
|
|
2019-04-03 17:32:59 +02:00
|
|
|
if ( flags == NM_UTILS_STRSPLIT_SET_FLAGS_NONE
|
|
|
|
|
&& nmtst_get_rand_bool ())
|
|
|
|
|
words = nm_utils_strsplit_set (str, DELIMITERS);
|
|
|
|
|
else if ( flags == NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY
|
|
|
|
|
&& nmtst_get_rand_bool ())
|
|
|
|
|
words = nm_utils_strsplit_set_with_empty (str, DELIMITERS);
|
|
|
|
|
else
|
|
|
|
|
words = nm_utils_strsplit_set_full (str, DELIMITERS, flags);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (NM_PTRARRAY_LEN (words), ==, words_len);
|
|
|
|
|
|
|
|
|
|
if (words_len == 0) {
|
2017-09-14 19:14:01 +02:00
|
|
|
g_assert (!words);
|
|
|
|
|
g_assert ( !str
|
2019-04-03 17:32:59 +02:00
|
|
|
|| NM_STRCHAR_ALL (str, ch, NM_IN_SET (ch, DELIMITERS_C)));
|
2017-09-14 19:14:01 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2019-04-03 17:32:59 +02:00
|
|
|
|
2017-09-14 19:14:01 +02:00
|
|
|
g_assert (words);
|
2019-04-03 17:32:59 +02:00
|
|
|
for (i = 0; i < words_len; i++)
|
|
|
|
|
g_assert_cmpstr (exp_words[i], ==, words[i]);
|
|
|
|
|
g_assert (words[words_len] == NULL);
|
|
|
|
|
|
|
|
|
|
g_assert (_nm_utils_strv_cmp_n (exp_words, words_len, words, -1) == 0);
|
|
|
|
|
|
|
|
|
|
s1 = words[0];
|
|
|
|
|
g_assert (s1 >= (char *) &words[words_len + 1]);
|
|
|
|
|
s1 = &s1[strlen (str)];
|
|
|
|
|
for (i = 1; i < words_len; i++) {
|
|
|
|
|
g_assert (&(words[i - 1])[strlen (words[i - 1])] < words[i]);
|
|
|
|
|
g_assert (words[i] <= s1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* while strsplit removes all delimiters, we can relatively easily find them
|
|
|
|
|
* in the original string. Assert that the original string and the pointer offsets
|
|
|
|
|
* of words correspond. In particular, find idx_delim_after and idx_delim_before
|
|
|
|
|
* to determine which delimiter was after/before a word. */
|
|
|
|
|
{
|
|
|
|
|
gsize idx_word_start;
|
|
|
|
|
gsize idx_delim_after_old = G_MAXSIZE;
|
|
|
|
|
|
|
|
|
|
idx_word_start = initial_offset;
|
|
|
|
|
for (i = 0; i < words_len; i++) {
|
|
|
|
|
const gsize l_i = strlen (words[i]);
|
|
|
|
|
gsize idx_delim_after;
|
|
|
|
|
gsize idx_delim_before;
|
|
|
|
|
|
|
|
|
|
/* find the delimiter *after* words[i]. We can do that by looking at the next
|
|
|
|
|
* word and calculating the pointer difference.
|
|
|
|
|
*
|
|
|
|
|
* The delimiter after the very last word is '\0' and requires strlen() to find. */
|
|
|
|
|
idx_delim_after = initial_offset + ((words[i] - words[0]) + l_i);
|
|
|
|
|
if (idx_delim_after != idx_word_start + l_i) {
|
|
|
|
|
g_assert (!f_preserve_empty);
|
|
|
|
|
g_assert_cmpint (idx_word_start + l_i, <, idx_delim_after);
|
|
|
|
|
idx_word_start = idx_delim_after - l_i;
|
|
|
|
|
}
|
|
|
|
|
if (i + 1 < words_len) {
|
|
|
|
|
gsize x = initial_offset + ((words[i + 1] - words[0]) - 1);
|
|
|
|
|
|
|
|
|
|
if (idx_delim_after != x) {
|
|
|
|
|
g_assert (!f_preserve_empty);
|
|
|
|
|
g_assert_cmpint (idx_delim_after, <, x);
|
|
|
|
|
for (k = idx_delim_after; k <= x; k++)
|
|
|
|
|
g_assert (NM_IN_SET (str[k], DELIMITERS_C));
|
|
|
|
|
}
|
|
|
|
|
g_assert (NM_IN_SET (str[idx_delim_after], DELIMITERS_C));
|
|
|
|
|
} else {
|
|
|
|
|
if (f_preserve_empty)
|
|
|
|
|
g_assert (NM_IN_SET (str[idx_delim_after], '\0'));
|
|
|
|
|
else
|
|
|
|
|
g_assert (NM_IN_SET (str[idx_delim_after], '\0', DELIMITERS_C));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* find the delimiter *before* words[i]. */
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
/* there is only a delimiter *before*, with !f_preserve_empty and leading
|
|
|
|
|
* delimiters. */
|
|
|
|
|
idx_delim_before = G_MAXSIZE;
|
|
|
|
|
if (initial_offset > 0) {
|
|
|
|
|
g_assert (!f_preserve_empty);
|
|
|
|
|
idx_delim_before = initial_offset - 1;
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
idx_delim_before = initial_offset + (words[i] - words[0]) - 1;
|
|
|
|
|
if (idx_delim_before != G_MAXSIZE)
|
|
|
|
|
g_assert (NM_IN_SET (str[idx_delim_before], DELIMITERS_C));
|
|
|
|
|
if (idx_delim_after_old != idx_delim_before) {
|
|
|
|
|
g_assert (!f_preserve_empty);
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
g_assert_cmpint (initial_offset, >, 0);
|
|
|
|
|
g_assert_cmpint (idx_delim_before, !=, G_MAXSIZE);
|
|
|
|
|
g_assert_cmpint (idx_delim_before, ==, initial_offset - 1);
|
|
|
|
|
} else {
|
|
|
|
|
g_assert_cmpint (idx_delim_after_old, !=, G_MAXSIZE);
|
|
|
|
|
g_assert_cmpint (idx_delim_before, !=, G_MAXSIZE);
|
|
|
|
|
g_assert_cmpint (idx_delim_after_old, <, idx_delim_before);
|
|
|
|
|
for (k = idx_delim_after_old; k <= idx_delim_before; k++)
|
|
|
|
|
g_assert (NM_IN_SET (str[k], DELIMITERS_C));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (k = 0; k < l_i; ) {
|
|
|
|
|
if ( f_allow_escaping
|
|
|
|
|
&& str[idx_word_start + k] == '\\') {
|
|
|
|
|
k++;
|
|
|
|
|
if (k >= l_i)
|
|
|
|
|
break;
|
|
|
|
|
k++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
g_assert (!NM_IN_SET (str[idx_word_start + k], DELIMITERS_C));
|
|
|
|
|
k++;
|
|
|
|
|
}
|
|
|
|
|
g_assert (strncmp (words[i], &str[idx_word_start], l_i) == 0);
|
|
|
|
|
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
const char *s = &(words[i - 1])[strlen (words[i - 1]) + 1];
|
|
|
|
|
|
|
|
|
|
if (s != words[i]) {
|
|
|
|
|
g_assert (!f_preserve_empty);
|
|
|
|
|
g_assert (s < words[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
idx_word_start += l_i + 1;
|
|
|
|
|
idx_delim_after_old = idx_delim_after;
|
|
|
|
|
}
|
2017-09-14 19:14:01 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-03 17:32:59 +02:00
|
|
|
static void
|
|
|
|
|
_do_test_nm_utils_strsplit_set_f (NMUtilsStrsplitSetFlags flags,
|
|
|
|
|
const char *str,
|
|
|
|
|
gsize words_len,
|
|
|
|
|
const char *const*exp_words)
|
|
|
|
|
{
|
|
|
|
|
_do_test_nm_utils_strsplit_set_f_one (flags, str, words_len, exp_words);
|
|
|
|
|
|
|
|
|
|
if (NM_FLAGS_HAS (flags, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY)) {
|
|
|
|
|
gs_unref_ptrarray GPtrArray *exp_words2 = NULL;
|
|
|
|
|
gsize k;
|
|
|
|
|
|
|
|
|
|
exp_words2 = g_ptr_array_new ();
|
|
|
|
|
for (k = 0; k < words_len; k++) {
|
|
|
|
|
if (exp_words[k][0] != '\0')
|
|
|
|
|
g_ptr_array_add (exp_words2, (gpointer) exp_words[k]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_do_test_nm_utils_strsplit_set_f_one (flags & (~NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY),
|
|
|
|
|
str,
|
|
|
|
|
exp_words2->len,
|
|
|
|
|
(const char *const*) exp_words2->pdata);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define do_test_nm_utils_strsplit_set_f(flags, str, ...) \
|
|
|
|
|
_do_test_nm_utils_strsplit_set_f (flags, \
|
|
|
|
|
str, \
|
|
|
|
|
NM_NARG (__VA_ARGS__), \
|
|
|
|
|
NM_MAKE_STRV (__VA_ARGS__))
|
|
|
|
|
|
|
|
|
|
#define do_test_nm_utils_strsplit_set(allow_escaping, str, ...) \
|
|
|
|
|
do_test_nm_utils_strsplit_set_f ( (allow_escaping) \
|
|
|
|
|
? NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING \
|
|
|
|
|
: NM_UTILS_STRSPLIT_SET_FLAGS_NONE, \
|
|
|
|
|
str, \
|
|
|
|
|
##__VA_ARGS__)
|
2017-09-14 19:14:01 +02:00
|
|
|
|
2019-04-16 12:34:11 +02:00
|
|
|
static void
|
|
|
|
|
_do_test_nm_utils_strsplit_set_simple (NMUtilsStrsplitSetFlags flags,
|
|
|
|
|
const char *str,
|
|
|
|
|
gsize words_len,
|
|
|
|
|
const char *const*exp_words)
|
|
|
|
|
{
|
|
|
|
|
gs_free const char **tokens = NULL;
|
|
|
|
|
gsize n_tokens;
|
|
|
|
|
|
|
|
|
|
tokens = nm_utils_strsplit_set_full (str, DELIMITERS, flags);
|
|
|
|
|
|
|
|
|
|
if (!tokens) {
|
|
|
|
|
g_assert_cmpint (words_len, ==, 0);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert (str && str[0]);
|
|
|
|
|
g_assert_cmpint (words_len, >, 0);
|
|
|
|
|
n_tokens = NM_PTRARRAY_LEN (tokens);
|
|
|
|
|
|
|
|
|
|
if (_nm_utils_strv_cmp_n (exp_words, words_len, tokens, -1) != 0) {
|
|
|
|
|
gsize i;
|
|
|
|
|
|
|
|
|
|
g_print (">>> split \"%s\" (flags %x) got %zu tokens (%zu expected)\n", str, (guint) flags, n_tokens, words_len);
|
|
|
|
|
for (i = 0; i < NM_MAX (n_tokens, words_len); i++) {
|
|
|
|
|
const char *s1 = i < n_tokens ? tokens[i] : NULL;
|
|
|
|
|
const char *s2 = i < words_len ? exp_words[i] : NULL;
|
|
|
|
|
|
|
|
|
|
g_print (">>> [%zu]: %s - %s%s%s vs. %s%s%s\n",
|
|
|
|
|
i,
|
|
|
|
|
nm_streq0 (s1, s2) ? "same" : "diff",
|
|
|
|
|
NM_PRINT_FMT_QUOTE_STRING (s1),
|
|
|
|
|
NM_PRINT_FMT_QUOTE_STRING (s2));
|
|
|
|
|
}
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
g_assert_cmpint (words_len, ==, NM_PTRARRAY_LEN (tokens));
|
|
|
|
|
}
|
|
|
|
|
#define do_test_nm_utils_strsplit_set_simple(flags, str, ...) \
|
|
|
|
|
_do_test_nm_utils_strsplit_set_simple ((flags), (str), NM_NARG (__VA_ARGS__), NM_MAKE_STRV (__VA_ARGS__))
|
|
|
|
|
|
2017-09-14 19:14:01 +02:00
|
|
|
static void
|
|
|
|
|
test_nm_utils_strsplit_set (void)
|
|
|
|
|
{
|
2019-04-03 17:32:59 +02:00
|
|
|
gs_unref_ptrarray GPtrArray *words_exp = NULL;
|
|
|
|
|
guint test_run;
|
|
|
|
|
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_NONE, NULL);
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_NONE, "");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_NONE, " ");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_NONE, "a b", "a", "b");
|
|
|
|
|
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, NULL);
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, " ", "", "");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, " ", "", "", "");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "a ", "a", "", "");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "a b", "a", "", "b");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, " ab b", "", "ab", "", "b");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "ab b", "ab", "", "b");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "abb", "abb");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "abb bb ", "abb", "", "bb", "");
|
|
|
|
|
do_test_nm_utils_strsplit_set_f (NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, "abb bcb ", "abb", "bcb", "");
|
|
|
|
|
|
2018-08-09 09:28:30 +02:00
|
|
|
do_test_nm_utils_strsplit_set (FALSE, NULL);
|
|
|
|
|
do_test_nm_utils_strsplit_set (FALSE, "");
|
2019-04-16 12:34:11 +02:00
|
|
|
do_test_nm_utils_strsplit_set (FALSE, "\n");
|
|
|
|
|
do_test_nm_utils_strsplit_set (TRUE, " \t\n", "\t");
|
2018-08-09 09:28:30 +02:00
|
|
|
do_test_nm_utils_strsplit_set (FALSE, "a", "a");
|
|
|
|
|
do_test_nm_utils_strsplit_set (FALSE, "a b", "a", "b");
|
|
|
|
|
do_test_nm_utils_strsplit_set (FALSE, "a\rb", "a\rb");
|
|
|
|
|
do_test_nm_utils_strsplit_set (FALSE, " a\rb ", "a\rb");
|
|
|
|
|
do_test_nm_utils_strsplit_set (FALSE, " a bbbd afds ere", "a", "bbbd", "afds", "ere");
|
|
|
|
|
do_test_nm_utils_strsplit_set (FALSE,
|
|
|
|
|
"1 2 3 4 5 6 7 8 9 0 "
|
2017-09-14 19:14:01 +02:00
|
|
|
"1 2 3 4 5 6 7 8 9 0 "
|
|
|
|
|
"1 2 3 4 5 6 7 8 9 0",
|
|
|
|
|
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
|
|
|
|
|
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
|
|
|
|
|
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
|
2018-08-09 09:28:30 +02:00
|
|
|
do_test_nm_utils_strsplit_set (TRUE, "\\", "\\");
|
|
|
|
|
do_test_nm_utils_strsplit_set (TRUE, "\\ ", "\\ ");
|
|
|
|
|
do_test_nm_utils_strsplit_set (TRUE, "\\\\", "\\\\");
|
|
|
|
|
do_test_nm_utils_strsplit_set (TRUE, "\\\t", "\\\t");
|
|
|
|
|
do_test_nm_utils_strsplit_set (TRUE, "foo\\", "foo\\");
|
|
|
|
|
do_test_nm_utils_strsplit_set (TRUE, "bar foo\\", "bar", "foo\\");
|
|
|
|
|
do_test_nm_utils_strsplit_set (TRUE, "\\ a b\\ \\ c", "\\ a", "b\\ \\ ", "c");
|
2019-04-03 17:32:59 +02:00
|
|
|
|
|
|
|
|
words_exp = g_ptr_array_new_with_free_func (g_free);
|
|
|
|
|
for (test_run = 0; test_run < 100; test_run++) {
|
|
|
|
|
gboolean f_allow_escaping = nmtst_get_rand_bool ();
|
2019-05-30 08:33:14 +02:00
|
|
|
guint words_len = nmtst_get_rand_uint32 () % 100;
|
2019-04-03 17:32:59 +02:00
|
|
|
gs_free char *str = NULL;
|
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
|
|
g_ptr_array_set_size (words_exp, 0);
|
|
|
|
|
for (i = 0; i < words_len; i++) {
|
|
|
|
|
guint word_len;
|
|
|
|
|
char *word;
|
|
|
|
|
guint j;
|
|
|
|
|
|
2019-05-30 08:33:14 +02:00
|
|
|
word_len = nmtst_get_rand_uint32 ();
|
2019-04-03 17:32:59 +02:00
|
|
|
if ((word_len % 100) < 30)
|
|
|
|
|
word_len = 0;
|
|
|
|
|
else
|
|
|
|
|
word_len = (word_len >> 10) % 100;
|
|
|
|
|
word = g_new (char, word_len + 3);
|
|
|
|
|
for (j = 0; j < word_len; ) {
|
2019-05-30 08:33:14 +02:00
|
|
|
guint32 p = nmtst_get_rand_uint32 ();
|
2019-04-03 17:32:59 +02:00
|
|
|
static const char delimiters_arr[] = { DELIMITERS_C };
|
|
|
|
|
static const char regular_chars[] = "abcdefghijklmnopqrstuvwxyz";
|
|
|
|
|
|
|
|
|
|
if ( !f_allow_escaping
|
|
|
|
|
|| (p % 1000) < 700) {
|
|
|
|
|
if (((p >> 20) % 100) < 20)
|
|
|
|
|
word[j++] = '\\';
|
|
|
|
|
word[j++] = regular_chars[(p >> 11) % (G_N_ELEMENTS (regular_chars) - 1)];
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
word[j++] = '\\';
|
|
|
|
|
word[j++] = delimiters_arr[(p >> 11) % G_N_ELEMENTS (delimiters_arr)];
|
|
|
|
|
}
|
|
|
|
|
word[j] = '\0';
|
|
|
|
|
g_ptr_array_add (words_exp, word);
|
|
|
|
|
}
|
|
|
|
|
g_ptr_array_add (words_exp, NULL);
|
|
|
|
|
|
|
|
|
|
str = g_strjoinv (" ", (char **) words_exp->pdata);
|
|
|
|
|
|
|
|
|
|
if ( str[0] == '\0'
|
|
|
|
|
&& words_len > 0) {
|
|
|
|
|
g_assert (words_len == 1);
|
|
|
|
|
g_assert_cmpstr (words_exp->pdata[0], ==, "");
|
|
|
|
|
words_len = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_do_test_nm_utils_strsplit_set_f ( (f_allow_escaping ? NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING : NM_UTILS_STRSPLIT_SET_FLAGS_NONE)
|
|
|
|
|
| NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY,
|
|
|
|
|
str,
|
|
|
|
|
words_len,
|
|
|
|
|
(const char *const*) words_exp->pdata);
|
|
|
|
|
}
|
2019-04-16 12:34:11 +02:00
|
|
|
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "\t", "\t");
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, "\t");
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY,
|
|
|
|
|
"\t", "");
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP | NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY,
|
|
|
|
|
"\t\\\t\t\t\\\t", "\t\t\t\t");
|
|
|
|
|
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "\ta", "\ta");
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, "\ta", "a");
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "\ta\\ b\t\\ ", "\ta b\t ");
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, "\ta\\ b\t\\ \t", "a b\t ");
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "a\\ b", "a ", "b");
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED, "\ta\\ b", "\ta ", "b");
|
|
|
|
|
do_test_nm_utils_strsplit_set_simple (NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, "\ta\\ b", "a ", "b");
|
2017-09-14 19:14:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2020-03-27 09:29:43 +01:00
|
|
|
static char *
|
|
|
|
|
_escaped_tokens_create_random_word_full (const char *const*tokens,
|
|
|
|
|
gsize n_tokens,
|
|
|
|
|
gsize len)
|
|
|
|
|
{
|
|
|
|
|
GString *gstr = g_string_new (NULL);
|
|
|
|
|
gsize i;
|
|
|
|
|
char random_token[2] = { 0 };
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
const char *token = tokens[nmtst_get_rand_uint32 () % n_tokens];
|
|
|
|
|
|
|
|
|
|
if (!token[0]) {
|
|
|
|
|
do {
|
|
|
|
|
random_token[0] = nmtst_get_rand_uint32 ();
|
|
|
|
|
} while (random_token[0] == '\0');
|
|
|
|
|
token = random_token;
|
|
|
|
|
}
|
|
|
|
|
g_string_append (gstr, token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* reallocate the string, so that we don't have any excess memory from
|
|
|
|
|
* the GString buffer. This is so that valgrind may better detect an out
|
|
|
|
|
* or range access. */
|
|
|
|
|
return nm_str_realloc (g_string_free (gstr, FALSE));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* set to 1 to exclude characters that are annoying to see in the debugger
|
|
|
|
|
* and printf() output. */
|
|
|
|
|
#define ESCAPED_TOKENS_ONLY_NICE_CHARS 0
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
_escaped_tokens_create_random_whitespace (void)
|
|
|
|
|
{
|
|
|
|
|
static const char *tokens[] = {
|
|
|
|
|
" ",
|
|
|
|
|
#if !ESCAPED_TOKENS_ONLY_NICE_CHARS
|
|
|
|
|
"\n",
|
|
|
|
|
"\t",
|
|
|
|
|
"\r",
|
|
|
|
|
"\f",
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return _escaped_tokens_create_random_word_full (tokens, G_N_ELEMENTS (tokens), nmtst_get_rand_word_length (NULL) / 4u);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
_escaped_tokens_create_random_word (void)
|
|
|
|
|
{
|
|
|
|
|
static const char *tokens[] = {
|
|
|
|
|
"a",
|
|
|
|
|
"b",
|
|
|
|
|
"c",
|
|
|
|
|
" ",
|
|
|
|
|
",",
|
|
|
|
|
"=",
|
|
|
|
|
"\\",
|
|
|
|
|
#if !ESCAPED_TOKENS_ONLY_NICE_CHARS
|
|
|
|
|
"\n",
|
|
|
|
|
"\f",
|
|
|
|
|
":",
|
|
|
|
|
"",
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return _escaped_tokens_create_random_word_full (tokens, G_N_ELEMENTS (tokens), nmtst_get_rand_word_length (NULL));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_escaped_tokens_str_append_delimiter (GString *str,
|
|
|
|
|
gboolean strict,
|
|
|
|
|
gboolean needs_delimiter)
|
|
|
|
|
{
|
|
|
|
|
guint len = nmtst_get_rand_word_length (NULL) / 10u;
|
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
|
|
again:
|
|
|
|
|
if (!strict) {
|
|
|
|
|
g_string_append (str, (s = _escaped_tokens_create_random_whitespace ()));
|
|
|
|
|
nm_clear_g_free (&s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (needs_delimiter)
|
|
|
|
|
g_string_append_c (str, ',');
|
|
|
|
|
|
|
|
|
|
if (!strict) {
|
|
|
|
|
g_string_append (str, (s = _escaped_tokens_create_random_whitespace ()));
|
|
|
|
|
nm_clear_g_free (&s);
|
|
|
|
|
if (len-- > 0) {
|
|
|
|
|
needs_delimiter = TRUE;
|
|
|
|
|
goto again;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_escaped_tokens_split (char *str, const char **out_key, const char **out_val)
|
|
|
|
|
{
|
|
|
|
|
const char *key;
|
|
|
|
|
const char *val;
|
|
|
|
|
gsize len = strlen (str);
|
|
|
|
|
|
|
|
|
|
g_assert (str);
|
|
|
|
|
|
|
|
|
|
nm_utils_escaped_tokens_options_split (str, &key, &val);
|
|
|
|
|
g_assert (key);
|
|
|
|
|
g_assert (key == str);
|
|
|
|
|
if (val) {
|
|
|
|
|
g_assert (val > str);
|
|
|
|
|
g_assert (val > key);
|
|
|
|
|
g_assert (val <= &str[len]);
|
|
|
|
|
}
|
|
|
|
|
NM_SET_OUT (out_key, key);
|
|
|
|
|
NM_SET_OUT (out_val, val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_escaped_tokens_combine (GString *combined,
|
|
|
|
|
const char *key,
|
|
|
|
|
const char *val,
|
|
|
|
|
gboolean strict,
|
|
|
|
|
gboolean allow_append_delimiter_before,
|
|
|
|
|
gboolean needs_delimiter_after)
|
|
|
|
|
{
|
|
|
|
|
gs_free char *escaped_key = NULL;
|
|
|
|
|
gs_free char *escaped_val = NULL;
|
|
|
|
|
|
|
|
|
|
if (allow_append_delimiter_before)
|
|
|
|
|
_escaped_tokens_str_append_delimiter (combined, strict, FALSE);
|
|
|
|
|
g_string_append (combined, nm_utils_escaped_tokens_options_escape_key (key, &escaped_key));
|
|
|
|
|
if (val) {
|
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
|
|
if (!strict) {
|
|
|
|
|
g_string_append (combined, (s = _escaped_tokens_create_random_whitespace ()));
|
|
|
|
|
nm_clear_g_free (&s);
|
|
|
|
|
}
|
|
|
|
|
g_string_append_c (combined, '=');
|
|
|
|
|
if (!strict) {
|
|
|
|
|
g_string_append (combined, (s = _escaped_tokens_create_random_whitespace ()));
|
|
|
|
|
nm_clear_g_free (&s);
|
|
|
|
|
}
|
|
|
|
|
g_string_append (combined, nm_utils_escaped_tokens_options_escape_val (val, &escaped_val));
|
|
|
|
|
}
|
|
|
|
|
_escaped_tokens_str_append_delimiter (combined, strict, needs_delimiter_after);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_escaped_tokens_check_one_impl (const char *expected_key,
|
|
|
|
|
const char *expected_val,
|
|
|
|
|
const char *expected_combination,
|
|
|
|
|
const char *const*other,
|
|
|
|
|
gsize n_other)
|
|
|
|
|
{
|
|
|
|
|
nm_auto_free_gstring GString *combined = g_string_new (NULL);
|
|
|
|
|
gsize i;
|
|
|
|
|
|
|
|
|
|
g_assert (expected_key);
|
|
|
|
|
g_assert (expected_combination);
|
|
|
|
|
g_assert (other);
|
|
|
|
|
|
|
|
|
|
_escaped_tokens_combine (combined,
|
|
|
|
|
expected_key,
|
|
|
|
|
expected_val,
|
|
|
|
|
TRUE,
|
|
|
|
|
TRUE,
|
|
|
|
|
FALSE);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (combined->str, ==, expected_combination);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n_other + 2u; i++) {
|
|
|
|
|
nm_auto_free_gstring GString *str0 = NULL;
|
|
|
|
|
gs_free const char **strv_split = NULL;
|
|
|
|
|
gs_free char *strv_split0 = NULL;
|
|
|
|
|
const char *comb;
|
|
|
|
|
const char *key;
|
|
|
|
|
const char *val;
|
|
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
|
comb = expected_combination;
|
|
|
|
|
else if (i == 1) {
|
|
|
|
|
_escaped_tokens_combine (nm_gstring_prepare (&str0),
|
|
|
|
|
expected_key,
|
|
|
|
|
expected_val,
|
|
|
|
|
FALSE,
|
|
|
|
|
TRUE,
|
|
|
|
|
FALSE);
|
|
|
|
|
comb = str0->str;
|
|
|
|
|
} else
|
|
|
|
|
comb = other[i - 2];
|
|
|
|
|
|
|
|
|
|
strv_split = nm_utils_escaped_tokens_options_split_list (comb);
|
|
|
|
|
if (!strv_split) {
|
|
|
|
|
g_assert_cmpstr (expected_key, ==, "");
|
|
|
|
|
g_assert_cmpstr (expected_val, ==, NULL);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
g_assert (expected_val || expected_key[0]);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpuint (NM_PTRARRAY_LEN (strv_split), ==, 1u);
|
|
|
|
|
|
|
|
|
|
strv_split0 = g_strdup (strv_split[0]);
|
|
|
|
|
|
|
|
|
|
_escaped_tokens_split (strv_split0, &key, &val);
|
|
|
|
|
g_assert_cmpstr (key, ==, expected_key);
|
|
|
|
|
g_assert_cmpstr (val, ==, expected_val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define _escaped_tokens_check_one(expected_key, expected_val, expected_combination, ...) \
|
|
|
|
|
_escaped_tokens_check_one_impl (expected_key, expected_val, expected_combination, NM_MAKE_STRV (__VA_ARGS__), NM_NARG (__VA_ARGS__))
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_escaped_tokens (void)
|
|
|
|
|
{
|
|
|
|
|
int i_run;
|
|
|
|
|
|
|
|
|
|
for (i_run = 0; i_run < 1000; i_run++) {
|
|
|
|
|
const guint num_options = nmtst_get_rand_word_length (NULL);
|
|
|
|
|
gs_unref_ptrarray GPtrArray *options = g_ptr_array_new_with_free_func (g_free);
|
|
|
|
|
nm_auto_free_gstring GString *combined = g_string_new (NULL);
|
|
|
|
|
gs_free const char **strv_split = NULL;
|
|
|
|
|
guint i_option;
|
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
|
|
/* Generate a list of random words for option key-value pairs. */
|
|
|
|
|
for (i_option = 0; i_option < 2u * num_options; i_option++) {
|
|
|
|
|
char *word = NULL;
|
|
|
|
|
|
|
|
|
|
if ( i_option % 2u == 1
|
|
|
|
|
&& nmtst_get_rand_uint32 () % 5 == 0
|
|
|
|
|
&& strlen (options->pdata[options->len - 1]) > 0u) {
|
|
|
|
|
/* For some options, leave the value unset and only generate a key.
|
|
|
|
|
*
|
|
|
|
|
* If key is "", then we cannot do that, because the test below would try
|
|
|
|
|
* to append "" to the combined list, which the parser then would drop.
|
|
|
|
|
* Only test omitting the value, if strlen() of the key is positive. */
|
|
|
|
|
} else
|
|
|
|
|
word = _escaped_tokens_create_random_word ();
|
|
|
|
|
g_ptr_array_add (options, word);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Combine the options in one comma separated list, with proper escaping. */
|
|
|
|
|
for (i_option = 0; i_option < num_options; i_option++) {
|
|
|
|
|
_escaped_tokens_combine (combined,
|
|
|
|
|
options->pdata[2u*i_option + 0u],
|
|
|
|
|
options->pdata[2u*i_option + 1u],
|
|
|
|
|
FALSE,
|
|
|
|
|
i_option == 0,
|
|
|
|
|
i_option != num_options - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ensure that we can split and parse the options without difference. */
|
|
|
|
|
strv_split = nm_utils_escaped_tokens_options_split_list (combined->str);
|
|
|
|
|
for (i_option = 0; i_option < num_options; i_option++) {
|
|
|
|
|
const char *expected_key = options->pdata[2u*i_option + 0u];
|
|
|
|
|
const char *expected_val = options->pdata[2u*i_option + 1u];
|
|
|
|
|
gs_free char *s_split = i_option < NM_PTRARRAY_LEN (strv_split) ? g_strdup (strv_split[i_option]) : NULL;
|
|
|
|
|
const char *key = NULL;
|
|
|
|
|
const char *val = NULL;
|
|
|
|
|
|
|
|
|
|
if (s_split)
|
|
|
|
|
_escaped_tokens_split (s_split, &key, &val);
|
|
|
|
|
|
|
|
|
|
if ( !nm_streq0 (key, expected_key)
|
|
|
|
|
|| !nm_streq0 (val, expected_val)) {
|
|
|
|
|
g_print (">>> ASSERTION IS ABOUT TO FAIL for item %5d of %5d\n", i_option, num_options);
|
|
|
|
|
g_print (">>> combined = \"%s\"\n", combined->str);
|
|
|
|
|
g_print (">>> %c parsed[%5d].key = \"%s\"\n", nm_streq (key, expected_key) ? ' ' : 'X', i_option, key);
|
|
|
|
|
g_print (">>> %c parsed[%5d].val = %s%s%s\n", nm_streq0 (val, expected_val) ? ' ' : 'X', i_option, NM_PRINT_FMT_QUOTE_STRING (val));
|
|
|
|
|
for (i = 0; i < num_options; i++) {
|
|
|
|
|
g_print (">>> %c original[%5d].key = \"%s\"\n", i == i_option ? '*' : ' ', i, (char *) options->pdata[2u*i + 0u]);
|
|
|
|
|
g_print (">>> %c original[%5d].val = %s%s%s\n", i == i_option ? '*' : ' ', i, NM_PRINT_FMT_QUOTE_STRING ((char *) options->pdata[2u*i + 1u]));
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < NM_PTRARRAY_LEN (strv_split); i++)
|
|
|
|
|
g_print (">>> split[%5d] = \"%s\"\n", i, strv_split[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (key, ==, expected_key);
|
|
|
|
|
g_assert_cmpstr (val, ==, expected_val);
|
|
|
|
|
}
|
|
|
|
|
g_assert_cmpint (NM_PTRARRAY_LEN (strv_split), ==, num_options);
|
|
|
|
|
|
|
|
|
|
/* Above we show a full round-trip of random option key-value pairs, that they can
|
|
|
|
|
* without loss escape, concatenate, split-list, and split. This proofed that every
|
|
|
|
|
* option key-value pair can be represented as a combined string and parsed back.
|
|
|
|
|
*
|
|
|
|
|
* Now, just check that we can also parse arbitrary random words in nm_utils_escaped_tokens_options_split().
|
|
|
|
|
* split() is a non-injective surjective function. As we check the round-trip above for random words, where
|
|
|
|
|
* options-split() is the last step, we show that every random word can be the output of the function
|
|
|
|
|
* (which shows, the surjective part).
|
|
|
|
|
*
|
|
|
|
|
* But multiple random input arguments, may map to the same output argument (non-injective).
|
|
|
|
|
* Just test whether we can handle random input words without crashing. For that, just use the
|
|
|
|
|
* above generate list of random words.
|
|
|
|
|
*/
|
|
|
|
|
for (i = 0; i < 1u + 2u * i_option; i++) {
|
|
|
|
|
gs_free char *str = NULL;
|
|
|
|
|
const char *cstr;
|
|
|
|
|
|
|
|
|
|
if (i == 0)
|
|
|
|
|
cstr = combined->str;
|
|
|
|
|
else
|
|
|
|
|
cstr = options->pdata[i - 1u];
|
|
|
|
|
if (!cstr)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
str = g_strdup (cstr);
|
|
|
|
|
_escaped_tokens_split (str, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_escaped_tokens_check_one ("", NULL, "");
|
|
|
|
|
_escaped_tokens_check_one ("", "", "=", " =");
|
|
|
|
|
_escaped_tokens_check_one ("a", "b", "a=b", "a = b");
|
|
|
|
|
_escaped_tokens_check_one ("a\\=", "b\\=", "a\\\\\\==b\\\\=", "a\\\\\\==b\\\\\\=");
|
|
|
|
|
_escaped_tokens_check_one ("\\=", "\\=", "\\\\\\==\\\\=", "\\\\\\==\\\\\\=");
|
|
|
|
|
_escaped_tokens_check_one (" ", "bb=", "\\ =bb=", "\\ =bb\\=");
|
|
|
|
|
_escaped_tokens_check_one (" ", "bb\\=", "\\ =bb\\\\=", "\\ =bb\\\\\\=");
|
|
|
|
|
_escaped_tokens_check_one ("a b", "a b", "a b=a b");
|
|
|
|
|
_escaped_tokens_check_one ("a b", "a b", "a b=a b");
|
|
|
|
|
_escaped_tokens_check_one ("a = b", "a = b", "a \\= b=a = b", "a \\= b=a \\= b");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-07-08 13:30:00 +02:00
|
|
|
typedef struct {
|
|
|
|
|
int val;
|
|
|
|
|
CList lst;
|
|
|
|
|
} CListSort;
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
_c_list_sort_cmp (const CList *lst_a, const CList *lst_b, const void *user_data)
|
|
|
|
|
{
|
|
|
|
|
const CListSort *a, *b;
|
|
|
|
|
|
|
|
|
|
g_assert (lst_a);
|
|
|
|
|
g_assert (lst_b);
|
|
|
|
|
g_assert (lst_a != lst_b);
|
|
|
|
|
|
|
|
|
|
a = c_list_entry (lst_a, CListSort, lst);
|
|
|
|
|
b = c_list_entry (lst_b, CListSort, lst);
|
|
|
|
|
|
|
|
|
|
if (a->val < b->val)
|
|
|
|
|
return -1;
|
|
|
|
|
if (a->val > b->val)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-12-28 19:52:39 +01:00
|
|
|
_do_test_c_list_sort (CListSort *elements, guint n_list, gboolean headless)
|
2017-07-08 13:30:00 +02:00
|
|
|
{
|
|
|
|
|
CList head, *iter, *iter_prev, *lst;
|
2017-12-28 19:52:39 +01:00
|
|
|
guint i;
|
2017-07-08 13:30:00 +02:00
|
|
|
const CListSort *el_prev;
|
2017-12-28 19:52:39 +01:00
|
|
|
CListSort *el;
|
2017-07-08 13:30:00 +02:00
|
|
|
|
|
|
|
|
c_list_init (&head);
|
2017-12-28 19:52:39 +01:00
|
|
|
for (i = 0; i < n_list; i++) {
|
|
|
|
|
el = &elements[i];
|
2019-05-30 08:33:14 +02:00
|
|
|
el->val = nmtst_get_rand_uint32 () % (2*n_list);
|
2017-12-28 19:52:39 +01:00
|
|
|
c_list_link_tail (&head, &el->lst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (headless) {
|
|
|
|
|
lst = head.next;
|
|
|
|
|
c_list_unlink_stale (&head);
|
|
|
|
|
lst = c_list_sort_headless (lst, _c_list_sort_cmp, NULL);
|
|
|
|
|
g_assert (lst);
|
|
|
|
|
g_assert (lst->next);
|
|
|
|
|
g_assert (lst->prev);
|
|
|
|
|
g_assert (c_list_length (lst) == n_list - 1);
|
|
|
|
|
iter_prev = lst->prev;
|
|
|
|
|
for (iter = lst; iter != lst; iter = iter->next) {
|
|
|
|
|
g_assert (iter);
|
|
|
|
|
g_assert (iter->next);
|
|
|
|
|
g_assert (iter->prev == iter_prev);
|
|
|
|
|
}
|
|
|
|
|
c_list_link_before (lst, &head);
|
|
|
|
|
} else
|
|
|
|
|
c_list_sort (&head, _c_list_sort_cmp, NULL);
|
|
|
|
|
|
|
|
|
|
g_assert (!c_list_is_empty (&head));
|
|
|
|
|
g_assert (c_list_length (&head) == n_list);
|
|
|
|
|
|
|
|
|
|
el_prev = NULL;
|
|
|
|
|
c_list_for_each (iter, &head) {
|
|
|
|
|
el = c_list_entry (iter, CListSort, lst);
|
|
|
|
|
g_assert (el >= elements && el < &elements[n_list]);
|
|
|
|
|
if (el_prev) {
|
|
|
|
|
if (el_prev->val == el->val)
|
|
|
|
|
g_assert (el_prev < el);
|
|
|
|
|
else
|
|
|
|
|
g_assert (el_prev->val < el->val);
|
|
|
|
|
g_assert (iter->prev == &el_prev->lst);
|
|
|
|
|
g_assert (el_prev->lst.next == iter);
|
|
|
|
|
}
|
|
|
|
|
el_prev = el;
|
|
|
|
|
}
|
|
|
|
|
g_assert (head.prev == &el_prev->lst);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_c_list_sort (void)
|
|
|
|
|
{
|
|
|
|
|
const guint N_ELEMENTS = 10000;
|
|
|
|
|
guint n_list, repeat;
|
|
|
|
|
gs_free CListSort *elements = NULL;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
CList head;
|
|
|
|
|
|
|
|
|
|
c_list_init (&head);
|
|
|
|
|
c_list_sort (&head, _c_list_sort_cmp, NULL);
|
|
|
|
|
g_assert (c_list_length (&head) == 0);
|
|
|
|
|
g_assert (c_list_is_empty (&head));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
elements = g_new0 (CListSort, N_ELEMENTS);
|
|
|
|
|
for (n_list = 1; n_list < N_ELEMENTS; n_list++) {
|
|
|
|
|
if (n_list > 150) {
|
2019-05-30 08:33:14 +02:00
|
|
|
n_list += nmtst_get_rand_uint32 () % n_list;
|
2017-12-28 19:52:39 +01:00
|
|
|
if (n_list >= N_ELEMENTS)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
const guint N_REPEAT = n_list > 50 ? 1 : 5;
|
|
|
|
|
|
|
|
|
|
for (repeat = 0; repeat < N_REPEAT; repeat++)
|
2019-05-30 08:33:14 +02:00
|
|
|
_do_test_c_list_sort (elements, n_list, nmtst_get_rand_uint32 () % 2);
|
2017-07-08 13:30:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
typedef struct {
|
|
|
|
|
NMDedupMultiObj parent;
|
|
|
|
|
guint val;
|
|
|
|
|
guint other;
|
|
|
|
|
} DedupObj;
|
|
|
|
|
|
|
|
|
|
static const NMDedupMultiObjClass dedup_obj_class;
|
|
|
|
|
|
|
|
|
|
static DedupObj *
|
|
|
|
|
_dedup_obj_assert (const NMDedupMultiObj *obj)
|
|
|
|
|
{
|
|
|
|
|
DedupObj *o;
|
|
|
|
|
|
|
|
|
|
g_assert (obj);
|
|
|
|
|
o = (DedupObj *) obj;
|
|
|
|
|
g_assert (o->parent.klass == &dedup_obj_class);
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
g_assert (o->parent._ref_count > 0);
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
g_assert (o->val > 0);
|
|
|
|
|
return o;
|
|
|
|
|
}
|
|
|
|
|
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
static const NMDedupMultiObj *
|
|
|
|
|
_dedup_obj_clone (const NMDedupMultiObj *obj)
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
{
|
|
|
|
|
DedupObj *o, *o2;
|
|
|
|
|
|
|
|
|
|
o = _dedup_obj_assert (obj);
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
o2 = g_slice_new0 (DedupObj);
|
|
|
|
|
o2->parent.klass = &dedup_obj_class;
|
|
|
|
|
o2->parent._ref_count = 1;
|
|
|
|
|
o2->val = o->val;
|
|
|
|
|
o2->other = o->other;
|
|
|
|
|
return (NMDedupMultiObj *) o2;
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
_dedup_obj_destroy (NMDedupMultiObj *obj)
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
{
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
DedupObj *o = (DedupObj *) obj;
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
nm_assert (o->parent._ref_count == 0);
|
|
|
|
|
o->parent._ref_count = 1;
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
o = _dedup_obj_assert (obj);
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
g_slice_free (DedupObj, o);
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
}
|
|
|
|
|
|
2017-10-17 11:53:08 +02:00
|
|
|
static void
|
|
|
|
|
_dedup_obj_full_hash_update (const NMDedupMultiObj *obj, NMHashState *h)
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
{
|
|
|
|
|
const DedupObj *o;
|
|
|
|
|
|
|
|
|
|
o = _dedup_obj_assert (obj);
|
2017-10-17 11:53:08 +02:00
|
|
|
nm_hash_update_vals (h,
|
|
|
|
|
o->val,
|
|
|
|
|
o->other);
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_dedup_obj_full_equal (const NMDedupMultiObj *obj_a,
|
|
|
|
|
const NMDedupMultiObj *obj_b)
|
|
|
|
|
{
|
|
|
|
|
const DedupObj *o_a = _dedup_obj_assert (obj_a);
|
|
|
|
|
const DedupObj *o_b = _dedup_obj_assert (obj_b);
|
|
|
|
|
|
|
|
|
|
return o_a->val == o_b->val
|
|
|
|
|
&& o_a->other == o_b->other;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NMDedupMultiObjClass dedup_obj_class = {
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
.obj_clone = _dedup_obj_clone,
|
|
|
|
|
.obj_destroy = _dedup_obj_destroy,
|
2017-10-17 11:53:08 +02:00
|
|
|
.obj_full_hash_update = _dedup_obj_full_hash_update,
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
.obj_full_equal = _dedup_obj_full_equal,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define DEDUP_OBJ_INIT(val_val, other_other) \
|
|
|
|
|
(&((DedupObj) { \
|
|
|
|
|
.parent = { \
|
|
|
|
|
.klass = &dedup_obj_class, \
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
._ref_count = NM_OBJ_REF_COUNT_STACKINIT, \
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
}, \
|
|
|
|
|
.val = (val_val), \
|
|
|
|
|
.other = (other_other), \
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
NMDedupMultiIdxType parent;
|
|
|
|
|
guint partition_size;
|
|
|
|
|
guint val_mod;
|
|
|
|
|
} DedupIdxType;
|
|
|
|
|
|
|
|
|
|
static const NMDedupMultiIdxTypeClass dedup_idx_type_class;
|
|
|
|
|
|
|
|
|
|
static const DedupIdxType *
|
|
|
|
|
_dedup_idx_assert (const NMDedupMultiIdxType *idx_type)
|
|
|
|
|
{
|
|
|
|
|
DedupIdxType *t;
|
|
|
|
|
|
|
|
|
|
g_assert (idx_type);
|
|
|
|
|
t = (DedupIdxType *) idx_type;
|
|
|
|
|
g_assert (t->parent.klass == &dedup_idx_type_class);
|
|
|
|
|
g_assert (t->partition_size > 0);
|
|
|
|
|
g_assert (t->val_mod > 0);
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-17 11:53:08 +02:00
|
|
|
static void
|
|
|
|
|
_dedup_idx_obj_id_hash_update (const NMDedupMultiIdxType *idx_type,
|
|
|
|
|
const NMDedupMultiObj *obj,
|
|
|
|
|
NMHashState *h)
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
{
|
|
|
|
|
const DedupIdxType *t;
|
|
|
|
|
const DedupObj *o;
|
|
|
|
|
|
|
|
|
|
t = _dedup_idx_assert (idx_type);
|
|
|
|
|
o = _dedup_obj_assert (obj);
|
|
|
|
|
|
2017-10-17 11:53:08 +02:00
|
|
|
nm_hash_update_val (h, o->val / t->partition_size);
|
|
|
|
|
nm_hash_update_val (h, o->val % t->val_mod);
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_dedup_idx_obj_id_equal (const NMDedupMultiIdxType *idx_type,
|
|
|
|
|
const NMDedupMultiObj *obj_a,
|
|
|
|
|
const NMDedupMultiObj *obj_b)
|
|
|
|
|
{
|
|
|
|
|
const DedupIdxType *t;
|
|
|
|
|
const DedupObj *o_a;
|
|
|
|
|
const DedupObj *o_b;
|
|
|
|
|
|
|
|
|
|
t = _dedup_idx_assert (idx_type);
|
|
|
|
|
o_a = _dedup_obj_assert (obj_a);
|
|
|
|
|
o_b = _dedup_obj_assert (obj_b);
|
|
|
|
|
|
|
|
|
|
return (o_a->val / t->partition_size) == (o_b->val / t->partition_size)
|
|
|
|
|
&& (o_a->val % t->val_mod) == (o_b->val % t->val_mod);
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-17 11:53:08 +02:00
|
|
|
static void
|
|
|
|
|
_dedup_idx_obj_partition_hash_update (const NMDedupMultiIdxType *idx_type,
|
|
|
|
|
const NMDedupMultiObj *obj,
|
|
|
|
|
NMHashState *h)
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
{
|
|
|
|
|
const DedupIdxType *t;
|
|
|
|
|
const DedupObj *o;
|
|
|
|
|
|
|
|
|
|
t = _dedup_idx_assert (idx_type);
|
|
|
|
|
o = _dedup_obj_assert (obj);
|
|
|
|
|
|
2017-10-17 11:53:08 +02:00
|
|
|
nm_hash_update_val (h, o->val / t->partition_size);
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_dedup_idx_obj_partition_equal (const NMDedupMultiIdxType *idx_type,
|
|
|
|
|
const NMDedupMultiObj *obj_a,
|
|
|
|
|
const NMDedupMultiObj *obj_b)
|
|
|
|
|
{
|
|
|
|
|
const DedupIdxType *t;
|
|
|
|
|
const DedupObj *o_a;
|
|
|
|
|
const DedupObj *o_b;
|
|
|
|
|
|
|
|
|
|
t = _dedup_idx_assert (idx_type);
|
|
|
|
|
o_a = _dedup_obj_assert (obj_a);
|
|
|
|
|
o_b = _dedup_obj_assert (obj_b);
|
|
|
|
|
|
|
|
|
|
return (o_a->val / t->partition_size) == (o_b->val / t->partition_size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const NMDedupMultiIdxTypeClass dedup_idx_type_class = {
|
2017-10-17 11:53:08 +02:00
|
|
|
.idx_obj_id_hash_update = _dedup_idx_obj_id_hash_update,
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
.idx_obj_id_equal = _dedup_idx_obj_id_equal,
|
2017-10-17 11:53:08 +02:00
|
|
|
.idx_obj_partition_hash_update = _dedup_idx_obj_partition_hash_update,
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
.idx_obj_partition_equal = _dedup_idx_obj_partition_equal,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const DedupIdxType *
|
|
|
|
|
DEDUP_IDX_TYPE_INIT (DedupIdxType *idx_type, guint partition_size, guint val_mod)
|
|
|
|
|
{
|
|
|
|
|
nm_dedup_multi_idx_type_init ((NMDedupMultiIdxType *) idx_type, &dedup_idx_type_class);
|
|
|
|
|
idx_type->val_mod = val_mod;
|
|
|
|
|
idx_type->partition_size = partition_size;
|
|
|
|
|
return idx_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_dedup_idx_add (NMDedupMultiIndex *idx, const DedupIdxType *idx_type, const DedupObj *obj, NMDedupMultiIdxMode mode, const NMDedupMultiEntry **out_entry)
|
|
|
|
|
{
|
|
|
|
|
g_assert (idx);
|
|
|
|
|
_dedup_idx_assert ((NMDedupMultiIdxType *) idx_type);
|
|
|
|
|
if (obj)
|
|
|
|
|
_dedup_obj_assert ((NMDedupMultiObj *) obj);
|
|
|
|
|
return nm_dedup_multi_index_add (idx, (NMDedupMultiIdxType *) idx_type,
|
|
|
|
|
obj, mode, out_entry, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_dedup_head_entry_assert (const NMDedupMultiHeadEntry *entry)
|
|
|
|
|
{
|
|
|
|
|
g_assert (entry);
|
|
|
|
|
g_assert (entry->len > 0);
|
|
|
|
|
g_assert (entry->len == c_list_length (&entry->lst_entries_head));
|
|
|
|
|
g_assert (entry->idx_type);
|
|
|
|
|
g_assert (entry->is_head);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const DedupObj *
|
|
|
|
|
_dedup_entry_assert (const NMDedupMultiEntry *entry)
|
|
|
|
|
{
|
|
|
|
|
g_assert (entry);
|
|
|
|
|
g_assert (!c_list_is_empty (&entry->lst_entries));
|
|
|
|
|
g_assert (entry->head);
|
|
|
|
|
g_assert (!entry->is_head);
|
|
|
|
|
g_assert (entry->head != (gpointer) entry);
|
|
|
|
|
_dedup_head_entry_assert (entry->head);
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
return _dedup_obj_assert (entry->obj);
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const DedupIdxType *
|
|
|
|
|
_dedup_entry_get_idx_type (const NMDedupMultiEntry *entry)
|
|
|
|
|
{
|
|
|
|
|
_dedup_entry_assert (entry);
|
|
|
|
|
|
|
|
|
|
g_assert (entry->head);
|
|
|
|
|
g_assert (entry->head->idx_type);
|
|
|
|
|
return _dedup_idx_assert (entry->head->idx_type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_dedup_entry_assert_all (const NMDedupMultiEntry *entry, gssize expected_idx, const DedupObj *const*expected_obj)
|
|
|
|
|
{
|
|
|
|
|
gsize n, i;
|
|
|
|
|
CList *iter;
|
|
|
|
|
|
|
|
|
|
g_assert (entry);
|
|
|
|
|
_dedup_entry_assert (entry);
|
|
|
|
|
|
|
|
|
|
g_assert (expected_obj);
|
|
|
|
|
n = NM_PTRARRAY_LEN (expected_obj);
|
|
|
|
|
|
|
|
|
|
g_assert (n == c_list_length (&entry->lst_entries));
|
|
|
|
|
|
|
|
|
|
g_assert (expected_idx >= -1 && expected_idx < n);
|
|
|
|
|
g_assert (entry->head);
|
|
|
|
|
if (expected_idx == -1)
|
|
|
|
|
g_assert (entry->head == (gpointer) entry);
|
|
|
|
|
else
|
|
|
|
|
g_assert (entry->head != (gpointer) entry);
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
c_list_for_each (iter, &entry->head->lst_entries_head) {
|
|
|
|
|
const NMDedupMultiEntry *entry_current = c_list_entry (iter, NMDedupMultiEntry, lst_entries);
|
|
|
|
|
const DedupObj *obj_current;
|
|
|
|
|
const DedupIdxType *idx_type = _dedup_entry_get_idx_type (entry_current);
|
|
|
|
|
|
|
|
|
|
obj_current = _dedup_entry_assert (entry_current);
|
|
|
|
|
g_assert (obj_current);
|
|
|
|
|
g_assert (i < n);
|
|
|
|
|
if (expected_idx == i)
|
|
|
|
|
g_assert (entry_current == entry);
|
|
|
|
|
g_assert (idx_type->parent.klass->idx_obj_partition_equal (&idx_type->parent,
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
entry_current->obj,
|
|
|
|
|
c_list_entry (entry->head->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj));
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#define _dedup_entry_assert_all(entry, expected_idx, ...) _dedup_entry_assert_all (entry, expected_idx, (const DedupObj *const[]) { __VA_ARGS__, NULL })
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_dedup_multi (void)
|
|
|
|
|
{
|
|
|
|
|
NMDedupMultiIndex *idx;
|
|
|
|
|
DedupIdxType IDX_20_3_a_stack;
|
|
|
|
|
const DedupIdxType *const IDX_20_3_a = DEDUP_IDX_TYPE_INIT (&IDX_20_3_a_stack, 20, 3);
|
|
|
|
|
const NMDedupMultiEntry *entry1;
|
|
|
|
|
|
|
|
|
|
idx = nm_dedup_multi_index_new ();
|
|
|
|
|
|
|
|
|
|
g_assert (_dedup_idx_add (idx, IDX_20_3_a, DEDUP_OBJ_INIT (1, 1), NM_DEDUP_MULTI_IDX_MODE_APPEND, &entry1));
|
|
|
|
|
_dedup_entry_assert_all (entry1, 0, DEDUP_OBJ_INIT (1, 1));
|
|
|
|
|
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
g_assert (nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 1)));
|
|
|
|
|
g_assert (!nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 2)));
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
|
|
|
|
|
g_assert (_dedup_idx_add (idx, IDX_20_3_a, DEDUP_OBJ_INIT (1, 2), NM_DEDUP_MULTI_IDX_MODE_APPEND, &entry1));
|
|
|
|
|
_dedup_entry_assert_all (entry1, 0, DEDUP_OBJ_INIT (1, 2));
|
|
|
|
|
|
core: remove NMDedupMultiBox object and track NMDedupMultiObj instances directly
Implement the reference counting of NMPObject as part of
NMDedupMultiObj and get rid of NMDedupMultiBox.
With this change, the NMPObject is aware in which NMDedupMultiIndex
instance it is tracked.
- this saves an additional GSlice allocation for the NMDedupMultiBox.
- it is immediately known, whether an NMPObject is tracked by a
certain NMDedupMultiIndex or not. This saves an additional hash
lookup.
- previously, when all idx-types cease to reference an NMDedupMultiObj
instance, it was removed. Now, a tracked objects stays in the
NMDedupMultiIndex until it's last reference is deleted. This possibly
extends the lifetime of the object and we may reuse it better.
- it is no longer possible to add one object to more then one
NMDedupMultiIndex instance. As we anyway want to have only one
instance to deduplicate the objects, this is fine.
- the ref-counting implementation is now part of NMDedupMultiObj.
Previously, NMDedupMultiIndex could also track objects that were
not ref-counted. Hoever, the object anyway *must* implement the
NMDedupMultiObj API, so this flexibility is unneeded and was not
used.
- a downside is, that NMPObject grows by one pointer size, even if
it isn't tracked in the NMDedupMultiIndex. But we really want to
put all objects into the index for sharing and deduplication. So
this downside should be acceptable. Still, code like
nmp_object_stackinit*() needs to handle a larger object.
2017-07-02 23:46:06 +02:00
|
|
|
g_assert (!nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 1)));
|
|
|
|
|
g_assert (nm_dedup_multi_index_obj_find (idx, (NMDedupMultiObj *) DEDUP_OBJ_INIT (1, 2)));
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
|
|
|
|
|
g_assert (_dedup_idx_add (idx, IDX_20_3_a, DEDUP_OBJ_INIT (2, 2), NM_DEDUP_MULTI_IDX_MODE_APPEND, &entry1));
|
|
|
|
|
_dedup_entry_assert_all (entry1, 1, DEDUP_OBJ_INIT (1, 2), DEDUP_OBJ_INIT (2, 2));
|
|
|
|
|
|
|
|
|
|
nm_dedup_multi_index_unref (idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-03-23 16:04:54 +01:00
|
|
|
static NMConnection *
|
|
|
|
|
_connection_new_from_dbus (GVariant *dict, GError **error)
|
|
|
|
|
{
|
|
|
|
|
return _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, error);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
|
|
|
|
vpn_check_func (const char *key, const char *value, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
if (!strcmp (key, "foobar1")) {
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpstr (value, ==, "blahblah1");
|
2014-07-24 08:53:33 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcmp (key, "foobar2")) {
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpstr (value, ==, "blahblah2");
|
2014-07-24 08:53:33 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcmp (key, "foobar3")) {
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpstr (value, ==, "blahblah3");
|
2014-07-24 08:53:33 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strcmp (key, "foobar4")) {
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpstr (value, ==, "blahblah4");
|
2014-07-24 08:53:33 -04:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_not_reached ();
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
vpn_check_empty_func (const char *key, const char *value, gpointer user_data)
|
|
|
|
|
{
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_not_reached ();
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_vpn_items (void)
|
|
|
|
|
{
|
2019-01-04 11:28:27 +01:00
|
|
|
gs_unref_object NMConnection *connection = NULL;
|
|
|
|
|
NMSettingVpn *s_vpn;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2019-01-04 11:28:27 +01:00
|
|
|
connection = nmtst_create_minimal_connection ("vpn-items", NULL, NM_SETTING_VPN_SETTING_NAME, NULL);
|
|
|
|
|
|
|
|
|
|
s_vpn = nm_connection_get_setting_vpn (connection);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "foobar1", "blahblah1");
|
|
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "foobar2", "blahblah2");
|
|
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "foobar3", "blahblah3");
|
|
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "foobar4", "blahblah4");
|
|
|
|
|
|
|
|
|
|
/* Ensure that added values are all present */
|
2016-02-14 14:09:21 +01:00
|
|
|
nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_func, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_remove_data_item (s_vpn, "foobar1");
|
|
|
|
|
nm_setting_vpn_remove_data_item (s_vpn, "foobar2");
|
|
|
|
|
nm_setting_vpn_remove_data_item (s_vpn, "foobar3");
|
|
|
|
|
nm_setting_vpn_remove_data_item (s_vpn, "foobar4");
|
|
|
|
|
|
2019-01-04 11:28:27 +01:00
|
|
|
g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL));
|
|
|
|
|
g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL));
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_secret (s_vpn, "foobar1", "blahblah1");
|
2019-01-04 11:28:27 +01:00
|
|
|
|
|
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL));
|
|
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL));
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_secret (s_vpn, "foobar2", "blahblah2");
|
|
|
|
|
nm_setting_vpn_add_secret (s_vpn, "foobar3", "blahblah3");
|
|
|
|
|
nm_setting_vpn_add_secret (s_vpn, "foobar4", "blahblah4");
|
|
|
|
|
|
|
|
|
|
/* Ensure that added values are all present */
|
2016-02-14 14:09:21 +01:00
|
|
|
nm_setting_vpn_foreach_secret (s_vpn, vpn_check_func, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_remove_secret (s_vpn, "foobar1");
|
|
|
|
|
nm_setting_vpn_remove_secret (s_vpn, "foobar2");
|
|
|
|
|
nm_setting_vpn_remove_secret (s_vpn, "foobar3");
|
2019-01-04 11:28:27 +01:00
|
|
|
|
|
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL));
|
|
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL));
|
|
|
|
|
|
|
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "foobar4-flags", "blahblah4");
|
|
|
|
|
|
|
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL));
|
|
|
|
|
|
|
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "foobar4-flags", "2");
|
|
|
|
|
|
|
|
|
|
g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL));
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_remove_secret (s_vpn, "foobar4");
|
|
|
|
|
|
2019-01-04 11:28:27 +01:00
|
|
|
g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL));
|
|
|
|
|
g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL));
|
|
|
|
|
|
|
|
|
|
nm_setting_vpn_remove_data_item (s_vpn, "foobar4-flags");
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
/* Try to add some blank values and make sure they are rejected */
|
2019-03-16 21:21:43 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0]));
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_data_item (s_vpn, NULL, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2019-03-16 21:21:43 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0]));
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "", "");
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "foobar1", "");
|
2020-03-26 12:41:13 +01:00
|
|
|
g_assert_cmpstr (nm_setting_vpn_get_data_item (s_vpn, "foobar1"), ==, "");
|
|
|
|
|
|
|
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL);
|
|
|
|
|
g_assert_cmpstr (nm_setting_vpn_get_data_item (s_vpn, "foobar1"), ==, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2019-03-16 21:21:43 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0]));
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_data_item (s_vpn, NULL, "blahblah1");
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2019-03-16 21:21:43 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0]));
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_data_item (s_vpn, "", "blahblah1");
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_empty_func, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Try to add some blank secrets and make sure they are rejected */
|
2019-03-16 21:21:43 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0]));
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_secret (s_vpn, NULL, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2019-03-16 21:21:43 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0]));
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_secret (s_vpn, "", "");
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
nm_setting_vpn_add_secret (s_vpn, "foobar1", "");
|
libnm: allow setting empty vpn.secrets item
Like for data, now also allow empty secrets to be added to the VPN
setting.
For one, this avoids an assertion failure, where keyfile reader wouldn't
check whether a secret key is set to the empty word.
For data, it's more clear that we want to allow setting empty data
values. VPN settings are only interpreted by the VPN plugin, so libnm
and the daemon shouldn't prevent empty settings. It can be useful to
distinguish between unset (NULL) and empty values.
For secrets, it's less clear that empty secrets shall be allowed. I
think it should. Of course, the empty secret likely isn't a correct
nor valid secret. But libnm cannot validate the secrets anyway. It's
up to the VPN plugin to handle this in any way they see fit.
Also, already before, the user could set NM_SETTING_VPN_SECRETS to
a string dictionary with empty passwords. So, the API didn't fully
prevent that. Only certain API wouldn't play along.
2020-03-26 12:41:13 +01:00
|
|
|
|
|
|
|
|
nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2019-03-16 21:21:43 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0]));
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_secret (s_vpn, NULL, "blahblah1");
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2019-03-16 21:21:43 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key && key[0]));
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_add_secret (s_vpn, "", "blahblah1");
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
nm_setting_vpn_foreach_secret (s_vpn, vpn_check_empty_func, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_vpn_update_secrets (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
NMSettingVpn *s_vpn;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariantBuilder settings_builder, vpn_builder, secrets_builder;
|
|
|
|
|
GVariant *settings;
|
2014-07-24 08:53:33 -04:00
|
|
|
gboolean success;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
const char *tmp;
|
|
|
|
|
const char *key1 = "foobar";
|
|
|
|
|
const char *key2 = "blahblah";
|
|
|
|
|
const char *val1 = "value1";
|
|
|
|
|
const char *val2 = "value2";
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_vpn));
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_init (&settings_builder, NM_VARIANT_TYPE_CONNECTION);
|
|
|
|
|
g_variant_builder_init (&vpn_builder, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_variant_builder_init (&secrets_builder, G_VARIANT_TYPE ("a{ss}"));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_add (&secrets_builder, "{ss}", key1, val1);
|
|
|
|
|
g_variant_builder_add (&secrets_builder, "{ss}", key2, val2);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_add (&vpn_builder, "{sv}",
|
|
|
|
|
NM_SETTING_VPN_SECRETS,
|
|
|
|
|
g_variant_builder_end (&secrets_builder));
|
|
|
|
|
g_variant_builder_add (&settings_builder, "{sa{sv}}",
|
|
|
|
|
NM_SETTING_VPN_SETTING_NAME,
|
|
|
|
|
&vpn_builder);
|
|
|
|
|
settings = g_variant_builder_end (&settings_builder);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
success = nm_connection_update_secrets (connection, NM_SETTING_VPN_SETTING_NAME, settings, &error);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Read the secrets back out */
|
|
|
|
|
tmp = nm_setting_vpn_get_secret (s_vpn, key1);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (tmp);
|
|
|
|
|
g_assert_cmpstr (tmp, ==, val1);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
tmp = nm_setting_vpn_get_secret (s_vpn, key2);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (tmp);
|
|
|
|
|
g_assert_cmpstr (tmp, ==, val2);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (settings);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define TO_DEL_NUM 50
|
|
|
|
|
typedef struct {
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
NMSettingVpn *s_vpn;
|
2014-07-24 08:53:33 -04:00
|
|
|
char *to_del[TO_DEL_NUM];
|
|
|
|
|
guint called;
|
|
|
|
|
} IterInfo;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
del_iter_func (const char *key, const char *value, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
IterInfo *info = user_data;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* Record how many times this function gets called; it should get called
|
|
|
|
|
* exactly as many times as there are keys in the hash table, regardless
|
|
|
|
|
* of what keys we delete from the table.
|
|
|
|
|
*/
|
|
|
|
|
info->called++;
|
|
|
|
|
|
|
|
|
|
/* During the iteration, remove a bunch of stuff from the table */
|
|
|
|
|
if (info->called == 1) {
|
|
|
|
|
for (i = 0; i < TO_DEL_NUM; i++)
|
|
|
|
|
nm_setting_vpn_remove_data_item (info->s_vpn, info->to_del[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_vpn_modify_during_foreach (void)
|
|
|
|
|
{
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
NMSettingVpn *s_vpn;
|
2014-07-24 08:53:33 -04:00
|
|
|
IterInfo info;
|
|
|
|
|
char *key, *val;
|
|
|
|
|
int i, u = 0;
|
|
|
|
|
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (s_vpn);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < TO_DEL_NUM * 2; i++) {
|
|
|
|
|
key = g_strdup_printf ("adsfasdfadf%d", i);
|
|
|
|
|
val = g_strdup_printf ("42263236236awt%d", i);
|
|
|
|
|
nm_setting_vpn_add_data_item (s_vpn, key, val);
|
|
|
|
|
|
|
|
|
|
/* Cache some keys to delete */
|
|
|
|
|
if (i % 2)
|
|
|
|
|
info.to_del[u++] = g_strdup (key);
|
|
|
|
|
|
|
|
|
|
g_free (key);
|
|
|
|
|
g_free (val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Iterate over current table keys */
|
|
|
|
|
info.s_vpn = s_vpn;
|
|
|
|
|
info.called = 0;
|
|
|
|
|
nm_setting_vpn_foreach_data_item (s_vpn, del_iter_func, &info);
|
|
|
|
|
|
|
|
|
|
/* Make sure all the things we removed during iteration are really gone */
|
|
|
|
|
for (i = 0; i < TO_DEL_NUM; i++) {
|
|
|
|
|
g_assert_cmpstr (nm_setting_vpn_get_data_item (s_vpn, info.to_del[i]), ==, NULL);
|
|
|
|
|
g_free (info.to_del[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* And make sure the foreach callback was called the same number of times
|
|
|
|
|
* as there were keys in the table at the beginning of the foreach.
|
|
|
|
|
*/
|
|
|
|
|
g_assert_cmpint (info.called, ==, TO_DEL_NUM * 2);
|
|
|
|
|
|
|
|
|
|
g_object_unref (s_vpn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_ip4_config_labels (void)
|
|
|
|
|
{
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip4;
|
2014-09-16 16:42:46 -04:00
|
|
|
NMIPAddress *addr;
|
2014-09-16 16:38:04 -04:00
|
|
|
GVariant *label;
|
2014-07-24 08:53:33 -04:00
|
|
|
GPtrArray *addrs;
|
2014-08-21 13:19:53 -04:00
|
|
|
char **labels;
|
2014-09-16 16:38:04 -04:00
|
|
|
NMConnection *conn;
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
GVariant *dict, *dict2, *setting_dict, *value;
|
2014-07-24 08:53:33 -04:00
|
|
|
GError *error = NULL;
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_set (G_OBJECT (s_ip4),
|
2014-10-19 17:30:10 -04:00
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
2014-07-24 08:53:33 -04:00
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
/* addr 1 */
|
2014-12-19 13:16:30 +01:00
|
|
|
addr = nm_ip_address_new (AF_INET, "1.2.3.4", 24, &error);
|
2014-09-16 16:42:46 -04:00
|
|
|
g_assert_no_error (error);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
2014-09-16 16:42:46 -04:00
|
|
|
nm_ip_address_unref (addr);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 0);
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert (label == NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-28 12:49:56 -04:00
|
|
|
/* The 'address-labels' property should be omitted from the serialization if
|
|
|
|
|
* there are no non-NULL labels.
|
|
|
|
|
*/
|
|
|
|
|
conn = nmtst_create_minimal_connection ("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
nm_connection_add_setting (conn, nm_setting_duplicate (NM_SETTING (s_ip4)));
|
|
|
|
|
dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
|
|
|
|
|
g_object_unref (conn);
|
|
|
|
|
|
|
|
|
|
setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_assert (setting_dict != NULL);
|
|
|
|
|
|
|
|
|
|
value = g_variant_lookup_value (setting_dict, "address-labels", NULL);
|
|
|
|
|
g_assert (value == NULL);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (setting_dict);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
/* Now back to constructing the original s_ip4... */
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
/* addr 2 */
|
2014-12-19 13:16:30 +01:00
|
|
|
addr = nm_ip_address_new (AF_INET, "2.3.4.5", 24, &error);
|
2014-09-16 16:42:46 -04:00
|
|
|
g_assert_no_error (error);
|
2017-12-11 14:06:10 +01:00
|
|
|
nm_ip_address_set_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("eth0:1"));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
2014-09-16 16:42:46 -04:00
|
|
|
nm_ip_address_unref (addr);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 1);
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert (label != NULL);
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* addr 3 */
|
2014-12-19 13:16:30 +01:00
|
|
|
addr = nm_ip_address_new (AF_INET, "3.4.5.6", 24, &error);
|
2014-09-16 16:42:46 -04:00
|
|
|
g_assert_no_error (error);
|
2017-12-11 14:06:10 +01:00
|
|
|
nm_ip_address_set_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
2014-09-16 16:42:46 -04:00
|
|
|
nm_ip_address_unref (addr);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 2);
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert (label == NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Remove addr 1 and re-verify remaining addresses */
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_remove_address (s_ip4, 0);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 0);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert (label != NULL);
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 1);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert (label == NULL);
|
|
|
|
|
|
2014-11-14 11:46:19 -05:00
|
|
|
/* If we serialize as the daemon, the labels should appear in the D-Bus
|
|
|
|
|
* serialization under both 'address-labels' and 'address-data'.
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
*/
|
2014-09-16 16:38:04 -04:00
|
|
|
conn = nmtst_create_minimal_connection ("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
nm_connection_add_setting (conn, NM_SETTING (s_ip4));
|
2014-11-14 11:46:19 -05:00
|
|
|
_nm_utils_is_manager_process = TRUE;
|
2014-09-16 16:38:04 -04:00
|
|
|
dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
|
2014-11-14 11:46:19 -05:00
|
|
|
_nm_utils_is_manager_process = FALSE;
|
2014-09-16 16:38:04 -04:00
|
|
|
g_object_unref (conn);
|
|
|
|
|
|
|
|
|
|
setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_assert (setting_dict != NULL);
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
|
2014-09-16 16:38:04 -04:00
|
|
|
value = g_variant_lookup_value (setting_dict, "address-labels", G_VARIANT_TYPE_STRING_ARRAY);
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
g_variant_get (value, "^as", &labels);
|
|
|
|
|
g_assert_cmpint (g_strv_length (labels), ==, 2);
|
|
|
|
|
g_assert_cmpstr (labels[0], ==, "eth0:1");
|
|
|
|
|
g_assert_cmpstr (labels[1], ==, "");
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
g_strfreev (labels);
|
|
|
|
|
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
|
|
|
|
|
addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
g_assert (addrs != NULL);
|
|
|
|
|
g_assert_cmpint (addrs->len, ==, 2);
|
|
|
|
|
addr = addrs->pdata[0];
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
g_assert (label != NULL);
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
|
|
|
|
|
addr = addrs->pdata[1];
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
g_assert (label == NULL);
|
|
|
|
|
g_ptr_array_unref (addrs);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (setting_dict);
|
|
|
|
|
|
|
|
|
|
/* We should be able to deserialize the labels from either 'address-labels'
|
|
|
|
|
* or 'address-data'.
|
|
|
|
|
*/
|
|
|
|
|
dict2 = g_variant_ref (dict);
|
|
|
|
|
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict,
|
|
|
|
|
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
"address-data");
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (conn);
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 0);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert (label != NULL);
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 1);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert (label == NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
g_object_unref (conn);
|
|
|
|
|
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict2,
|
|
|
|
|
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
"address-labels");
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict2, &error);
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_variant_unref (dict2);
|
|
|
|
|
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (conn);
|
|
|
|
|
|
|
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 0);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
|
|
|
|
|
|
|
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 1);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
g_assert (label == NULL);
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
/* Test explicit property assignment */
|
|
|
|
|
g_object_get (G_OBJECT (s_ip4),
|
2014-10-19 17:30:10 -04:00
|
|
|
NM_SETTING_IP_CONFIG_ADDRESSES, &addrs,
|
2014-07-24 08:53:33 -04:00
|
|
|
NULL);
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_clear_addresses (s_ip4);
|
|
|
|
|
g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_object_set (G_OBJECT (s_ip4),
|
2014-10-19 17:30:10 -04:00
|
|
|
NM_SETTING_IP_CONFIG_ADDRESSES, addrs,
|
2014-07-24 08:53:33 -04:00
|
|
|
NULL);
|
2014-06-24 12:46:03 -04:00
|
|
|
g_ptr_array_unref (addrs);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
|
2014-10-19 17:30:10 -04:00
|
|
|
g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 2);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 0);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert (label != NULL);
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 1);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
|
2017-12-11 14:06:10 +01:00
|
|
|
label = nm_ip_address_get_attribute (addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
|
2014-09-16 16:38:04 -04:00
|
|
|
g_assert (label == NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-09-16 16:38:04 -04:00
|
|
|
g_object_unref (conn);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-11-14 11:46:19 -05:00
|
|
|
static void
|
|
|
|
|
test_setting_ip4_config_address_data (void)
|
|
|
|
|
{
|
|
|
|
|
NMSettingIPConfig *s_ip4;
|
|
|
|
|
NMIPAddress *addr;
|
|
|
|
|
GPtrArray *addrs;
|
|
|
|
|
NMConnection *conn;
|
|
|
|
|
GVariant *dict, *setting_dict, *value;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
|
|
|
|
|
g_object_set (G_OBJECT (s_ip4),
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
/* addr 1 */
|
2014-12-19 13:16:30 +01:00
|
|
|
addr = nm_ip_address_new (AF_INET, "1.2.3.4", 24, &error);
|
2014-11-14 11:46:19 -05:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
nm_ip_address_set_attribute (addr, "one", g_variant_new_string ("foo"));
|
|
|
|
|
nm_ip_address_set_attribute (addr, "two", g_variant_new_int32 (42));
|
|
|
|
|
|
|
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
|
|
|
|
nm_ip_address_unref (addr);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
|
2014-11-14 11:46:19 -05:00
|
|
|
|
|
|
|
|
/* addr 2 */
|
2014-12-19 13:16:30 +01:00
|
|
|
addr = nm_ip_address_new (AF_INET, "2.3.4.5", 24, &error);
|
2014-11-14 11:46:19 -05:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
|
|
|
|
nm_ip_address_unref (addr);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
|
2014-11-14 11:46:19 -05:00
|
|
|
|
|
|
|
|
/* The client-side D-Bus serialization should include the attributes in
|
|
|
|
|
* "address-data", and should not have an "addresses" property.
|
|
|
|
|
*/
|
|
|
|
|
conn = nmtst_create_minimal_connection ("address-data test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
nm_connection_add_setting (conn, NM_SETTING (s_ip4));
|
|
|
|
|
dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
|
|
|
|
|
|
|
|
|
|
setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_assert (setting_dict != NULL);
|
|
|
|
|
|
|
|
|
|
value = g_variant_lookup_value (setting_dict, "addresses", NULL);
|
|
|
|
|
g_assert (value == NULL);
|
|
|
|
|
|
|
|
|
|
value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
|
|
|
|
|
addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
g_assert (addrs != NULL);
|
|
|
|
|
g_assert_cmpint (addrs->len, ==, 2);
|
|
|
|
|
|
|
|
|
|
addr = addrs->pdata[0];
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.2.3.4");
|
2014-11-14 11:46:19 -05:00
|
|
|
value = nm_ip_address_get_attribute (addr, "one");
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "foo");
|
|
|
|
|
value = nm_ip_address_get_attribute (addr, "two");
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
g_assert_cmpint (g_variant_get_int32 (value), ==, 42);
|
|
|
|
|
|
|
|
|
|
g_ptr_array_unref (addrs);
|
|
|
|
|
g_variant_unref (setting_dict);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
/* The daemon-side serialization should include both 'addresses' and 'address-data' */
|
|
|
|
|
_nm_utils_is_manager_process = TRUE;
|
|
|
|
|
dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
|
|
|
|
|
_nm_utils_is_manager_process = FALSE;
|
|
|
|
|
|
|
|
|
|
setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_assert (setting_dict != NULL);
|
|
|
|
|
|
|
|
|
|
value = g_variant_lookup_value (setting_dict, "addresses", G_VARIANT_TYPE ("aau"));
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
|
|
|
|
|
value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (setting_dict);
|
|
|
|
|
g_object_unref (conn);
|
|
|
|
|
|
|
|
|
|
/* When we reserialize that dictionary as a client, 'address-data' will be preferred. */
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2014-11-14 11:46:19 -05:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (conn);
|
|
|
|
|
|
|
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 0);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.2.3.4");
|
2014-11-14 11:46:19 -05:00
|
|
|
value = nm_ip_address_get_attribute (addr, "one");
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "foo");
|
|
|
|
|
value = nm_ip_address_get_attribute (addr, "two");
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
g_assert_cmpint (g_variant_get_int32 (value), ==, 42);
|
|
|
|
|
|
|
|
|
|
/* But on the server side, 'addresses' will have precedence. */
|
|
|
|
|
_nm_utils_is_manager_process = TRUE;
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2014-11-14 11:46:19 -05:00
|
|
|
_nm_utils_is_manager_process = FALSE;
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (conn);
|
|
|
|
|
|
|
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 0);
|
2014-12-19 13:16:30 +01:00
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.2.3.4");
|
2014-11-14 11:46:19 -05:00
|
|
|
value = nm_ip_address_get_attribute (addr, "one");
|
|
|
|
|
g_assert (value == NULL);
|
|
|
|
|
value = nm_ip_address_get_attribute (addr, "two");
|
|
|
|
|
g_assert (value == NULL);
|
|
|
|
|
|
|
|
|
|
g_object_unref (conn);
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-15 15:06:24 +01:00
|
|
|
static void
|
|
|
|
|
test_setting_ip_route_attributes (void)
|
|
|
|
|
{
|
|
|
|
|
GVariant *variant;
|
|
|
|
|
gboolean res, known;
|
|
|
|
|
|
|
|
|
|
#define TEST_ATTR(name, type, value, family, exp_res, exp_known) \
|
|
|
|
|
variant = g_variant_new_ ## type (value); \
|
|
|
|
|
res = nm_ip_route_attribute_validate (name, variant, family, &known, NULL); \
|
|
|
|
|
g_assert (res == exp_res); \
|
|
|
|
|
g_assert (known == exp_known); \
|
|
|
|
|
g_variant_unref (variant);
|
|
|
|
|
|
|
|
|
|
TEST_ATTR ("foo", uint32, 12, AF_INET, FALSE, FALSE);
|
|
|
|
|
|
|
|
|
|
TEST_ATTR ("tos", byte, 127, AF_INET, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("tos", string, "0x28", AF_INET, FALSE, TRUE);
|
|
|
|
|
|
|
|
|
|
TEST_ATTR ("cwnd", uint32, 10, AF_INET, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("cwnd", string, "11", AF_INET, FALSE, TRUE);
|
|
|
|
|
|
|
|
|
|
TEST_ATTR ("lock-mtu", boolean, TRUE, AF_INET, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("lock-mtu", uint32, 1, AF_INET, FALSE, TRUE);
|
|
|
|
|
|
2017-03-15 09:29:47 +01:00
|
|
|
TEST_ATTR ("from", string, "fd01::1", AF_INET6, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("from", string, "fd01::1/64", AF_INET6, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("from", string, "fd01::1/128", AF_INET6, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("from", string, "fd01::1/129", AF_INET6, FALSE, TRUE);
|
|
|
|
|
TEST_ATTR ("from", string, "fd01::1/a", AF_INET6, FALSE, TRUE);
|
|
|
|
|
TEST_ATTR ("from", string, "abc/64", AF_INET6, FALSE, TRUE);
|
|
|
|
|
TEST_ATTR ("from", string, "1.2.3.4", AF_INET, FALSE, TRUE);
|
|
|
|
|
TEST_ATTR ("from", string, "1.2.3.4", AF_INET6, FALSE, TRUE);
|
|
|
|
|
|
|
|
|
|
TEST_ATTR ("src", string, "1.2.3.4", AF_INET, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("src", string, "1.2.3.4", AF_INET6, FALSE, TRUE);
|
|
|
|
|
TEST_ATTR ("src", string, "1.2.3.0/24", AF_INET, FALSE, TRUE);
|
|
|
|
|
TEST_ATTR ("src", string, "fd01::12", AF_INET6, TRUE, TRUE);
|
2017-02-15 15:06:24 +01:00
|
|
|
|
2020-05-29 17:53:02 +02:00
|
|
|
TEST_ATTR ("type", string, "local", AF_INET, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("type", string, "local", AF_INET6, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("type", string, "unicast", AF_INET, TRUE, TRUE);
|
|
|
|
|
TEST_ATTR ("type", string, "unicast", AF_INET6, TRUE, TRUE);
|
|
|
|
|
|
2017-02-15 15:06:24 +01:00
|
|
|
#undef TEST_ATTR
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
|
|
|
|
test_setting_gsm_apn_spaces (void)
|
|
|
|
|
{
|
2015-02-09 15:17:53 +01:00
|
|
|
gs_unref_object NMSettingGsm *s_gsm = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
const char *tmp;
|
|
|
|
|
|
|
|
|
|
s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (s_gsm);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Trailing space */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar ", NULL);
|
|
|
|
|
tmp = nm_setting_gsm_get_apn (s_gsm);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpstr (tmp, ==, "foobar");
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Leading space */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_APN, " foobar", NULL);
|
|
|
|
|
tmp = nm_setting_gsm_get_apn (s_gsm);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpstr (tmp, ==, "foobar");
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_gsm_apn_bad_chars (void)
|
|
|
|
|
{
|
2015-02-09 15:17:53 +01:00
|
|
|
gs_unref_object NMSettingGsm *s_gsm = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (s_gsm);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Make sure a valid APN works */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar123.-baz", NULL);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Random invalid chars */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_APN, "@#%$@#%@#%", NULL);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Spaces */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar baz", NULL);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* 0 characters long */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_APN, "", NULL);
|
2019-08-25 15:27:37 +02:00
|
|
|
g_assert (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* 65-character long */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_APN, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl1", NULL);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_gsm_apn_underscore (void)
|
|
|
|
|
{
|
2015-02-09 15:17:53 +01:00
|
|
|
gs_unref_object NMSettingGsm *s_gsm = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
|
|
|
|
|
g_assert (s_gsm);
|
|
|
|
|
|
|
|
|
|
/* 65-character long */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar_baz", NULL);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_gsm_without_number (void)
|
|
|
|
|
{
|
2015-02-09 15:17:53 +01:00
|
|
|
gs_unref_object NMSettingGsm *s_gsm = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
|
|
|
|
|
g_assert (s_gsm);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, NULL, NULL);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "", NULL);
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2015-10-01 12:44:28 -05:00
|
|
|
static void
|
|
|
|
|
test_setting_gsm_sim_operator_id (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMSettingGsm *s_gsm = NULL;
|
|
|
|
|
|
|
|
|
|
s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
|
|
|
|
|
g_assert (s_gsm);
|
|
|
|
|
|
|
|
|
|
/* Valid */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "12345", NULL);
|
|
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "123456", NULL);
|
|
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
|
|
|
|
|
|
|
|
|
|
/* Invalid */
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "", NULL);
|
|
|
|
|
nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, " ", NULL);
|
|
|
|
|
nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "abcdef", NULL);
|
|
|
|
|
nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static NMSettingWirelessSecurity *
|
|
|
|
|
make_test_wsec_setting (const char *detail)
|
|
|
|
|
{
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
|
|
|
|
|
|
|
|
|
s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (s_wsec);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_object_set (s_wsec,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, "foobarbaz",
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_PSK, "random psk",
|
2014-06-26 16:47:46 -04:00
|
|
|
NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED,
|
2014-07-24 08:53:33 -04:00
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, "aaaaaaaaaa",
|
|
|
|
|
NULL);
|
|
|
|
|
return s_wsec;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
static gboolean
|
|
|
|
|
_variant_contains (GVariant *vardict, const char *key)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_variant GVariant *value = NULL;
|
2014-08-16 10:09:48 -04:00
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
value = g_variant_lookup_value (vardict, key, NULL);
|
|
|
|
|
return !!value;
|
|
|
|
|
}
|
2014-08-16 10:09:48 -04:00
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
2014-08-06 19:35:31 -04:00
|
|
|
test_setting_to_dbus_all (void)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *dict;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-06 19:35:31 -04:00
|
|
|
s_wsec = make_test_wsec_setting ("setting-to-dbus-all");
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2019-06-27 09:07:16 +02:00
|
|
|
dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Make sure all keys are there */
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT));
|
|
|
|
|
g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME));
|
|
|
|
|
g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_PSK));
|
|
|
|
|
g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (dict);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (s_wsec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-08-06 19:35:31 -04:00
|
|
|
test_setting_to_dbus_no_secrets (void)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *dict;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-06 19:35:31 -04:00
|
|
|
s_wsec = make_test_wsec_setting ("setting-to-dbus-no-secrets");
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2019-06-27 09:07:16 +02:00
|
|
|
dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_NO_SECRETS, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Make sure non-secret keys are there */
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT));
|
|
|
|
|
g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Make sure secrets are not there */
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_PSK));
|
|
|
|
|
g_assert (!_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (dict);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (s_wsec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-08-06 19:35:31 -04:00
|
|
|
test_setting_to_dbus_only_secrets (void)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *dict;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-06 19:35:31 -04:00
|
|
|
s_wsec = make_test_wsec_setting ("setting-to-dbus-only-secrets");
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2019-06-27 09:07:16 +02:00
|
|
|
dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ONLY_SECRETS, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
/* Make sure non-secret keys are not there */
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT));
|
|
|
|
|
g_assert (!_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
/* Make sure secrets are there */
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_PSK));
|
|
|
|
|
g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (dict);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (s_wsec);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-30 10:57:45 -04:00
|
|
|
static void
|
|
|
|
|
test_setting_to_dbus_transform (void)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *s_wired;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *dict, *val;
|
2014-07-30 10:57:45 -04:00
|
|
|
const char *test_mac_address = "11:22:33:44:55:66";
|
2014-08-16 10:09:48 -04:00
|
|
|
const guint8 *dbus_mac_address;
|
|
|
|
|
guint8 cmp_mac_address[ETH_ALEN];
|
|
|
|
|
gsize len;
|
2014-07-30 10:57:45 -04:00
|
|
|
|
|
|
|
|
s_wired = nm_setting_wired_new ();
|
|
|
|
|
g_object_set (s_wired,
|
|
|
|
|
NM_SETTING_WIRED_MAC_ADDRESS, test_mac_address,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (nm_setting_wired_get_mac_address (NM_SETTING_WIRED (s_wired)), ==, test_mac_address);
|
|
|
|
|
|
2019-06-27 09:07:16 +02:00
|
|
|
dict = _nm_setting_to_dbus (s_wired, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL);
|
2014-08-16 10:09:48 -04:00
|
|
|
g_assert (dict != NULL);
|
2014-07-30 10:57:45 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
val = g_variant_lookup_value (dict, NM_SETTING_WIRED_MAC_ADDRESS, G_VARIANT_TYPE_BYTESTRING);
|
2014-07-30 10:57:45 -04:00
|
|
|
g_assert (val != NULL);
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
dbus_mac_address = g_variant_get_fixed_array (val, &len, 1);
|
|
|
|
|
g_assert_cmpint (len, ==, ETH_ALEN);
|
2014-07-30 10:57:45 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
nm_utils_hwaddr_aton (test_mac_address, cmp_mac_address, ETH_ALEN);
|
|
|
|
|
g_assert (memcmp (dbus_mac_address, cmp_mac_address, ETH_ALEN) == 0);
|
2014-07-30 10:57:45 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (val);
|
|
|
|
|
g_variant_unref (dict);
|
2014-07-30 10:57:45 -04:00
|
|
|
g_object_unref (s_wired);
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-26 16:47:46 -04:00
|
|
|
static void
|
|
|
|
|
test_setting_to_dbus_enum (void)
|
|
|
|
|
{
|
2014-09-24 09:12:46 -04:00
|
|
|
NMSetting *s_ip6, *s_wsec, *s_serial;
|
2014-06-26 16:47:46 -04:00
|
|
|
GVariant *dict, *val;
|
|
|
|
|
|
|
|
|
|
/* enum */
|
|
|
|
|
s_ip6 = nm_setting_ip6_config_new ();
|
|
|
|
|
g_object_set (s_ip6,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_IP6_PRIVACY, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
|
|
|
|
|
NULL);
|
|
|
|
|
|
2019-06-27 09:07:16 +02:00
|
|
|
dict = _nm_setting_to_dbus (s_ip6, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL);
|
2014-06-26 16:47:46 -04:00
|
|
|
g_assert (dict != NULL);
|
|
|
|
|
|
|
|
|
|
val = g_variant_lookup_value (dict, NM_SETTING_IP6_CONFIG_IP6_PRIVACY, G_VARIANT_TYPE_INT32);
|
|
|
|
|
g_assert (val != NULL);
|
|
|
|
|
g_assert_cmpint (g_variant_get_int32 (val), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
|
|
|
|
|
g_variant_unref (val);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
g_object_unref (s_ip6);
|
|
|
|
|
|
|
|
|
|
/* flags (and a transformed enum) */
|
|
|
|
|
s_wsec = nm_setting_wireless_security_new ();
|
|
|
|
|
g_object_set (s_wsec,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, NM_WEP_KEY_TYPE_KEY,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
|
|
|
|
|
NM_SETTING_SECRET_FLAG_NOT_SAVED),
|
|
|
|
|
NULL);
|
|
|
|
|
|
2019-06-27 09:07:16 +02:00
|
|
|
dict = _nm_setting_to_dbus (s_wsec, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL);
|
2014-06-26 16:47:46 -04:00
|
|
|
g_assert (dict != NULL);
|
|
|
|
|
|
|
|
|
|
val = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, G_VARIANT_TYPE_UINT32);
|
|
|
|
|
g_assert (val != NULL);
|
|
|
|
|
g_assert_cmpint (g_variant_get_uint32 (val), ==, NM_WEP_KEY_TYPE_KEY);
|
|
|
|
|
g_variant_unref (val);
|
|
|
|
|
|
|
|
|
|
val = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, G_VARIANT_TYPE_UINT32);
|
|
|
|
|
g_assert (val != NULL);
|
|
|
|
|
g_assert_cmpint (g_variant_get_uint32 (val), ==, (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
|
|
|
|
|
NM_SETTING_SECRET_FLAG_NOT_SAVED));
|
|
|
|
|
g_variant_unref (val);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
g_object_unref (s_wsec);
|
2014-09-24 09:12:46 -04:00
|
|
|
|
|
|
|
|
/* another transformed enum */
|
|
|
|
|
s_serial = nm_setting_serial_new ();
|
|
|
|
|
g_object_set (s_serial,
|
|
|
|
|
NM_SETTING_SERIAL_PARITY, NM_SETTING_SERIAL_PARITY_ODD,
|
|
|
|
|
NULL);
|
|
|
|
|
|
2019-06-27 09:07:16 +02:00
|
|
|
dict = _nm_setting_to_dbus (s_serial, NULL, NM_CONNECTION_SERIALIZE_ALL, NULL);
|
2014-09-24 09:12:46 -04:00
|
|
|
g_assert (dict != NULL);
|
|
|
|
|
|
|
|
|
|
val = g_variant_lookup_value (dict, NM_SETTING_SERIAL_PARITY, G_VARIANT_TYPE_BYTE);
|
|
|
|
|
g_assert (val != NULL);
|
|
|
|
|
g_assert_cmpint (g_variant_get_byte (val), ==, 'o');
|
|
|
|
|
g_variant_unref (val);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
g_object_unref (s_serial);
|
2014-06-26 16:47:46 -04:00
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
2014-08-06 19:35:31 -04:00
|
|
|
test_connection_to_dbus_setting_name (void)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *dict;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-08-06 19:35:31 -04:00
|
|
|
s_wsec = make_test_wsec_setting ("connection-to-dbus-setting-name");
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_wsec));
|
|
|
|
|
|
2019-01-04 11:28:27 +01:00
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL));
|
|
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_wsec,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL));
|
|
|
|
|
g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_wsec,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, NM_SETTING_SECRET_FLAG_NONE,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NONE,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL));
|
|
|
|
|
g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL));
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
/* Make sure the keys of the first level dict are setting names, not
|
2014-07-24 08:53:33 -04:00
|
|
|
* the GType name of the setting objects.
|
|
|
|
|
*/
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (dict);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-29 18:42:02 -04:00
|
|
|
static void
|
|
|
|
|
test_connection_to_dbus_deprecated_props (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSetting *s_wireless;
|
2014-06-26 10:42:11 -04:00
|
|
|
GBytes *ssid;
|
2014-07-29 18:42:02 -04:00
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *dict, *wireless_dict, *sec_val;
|
2014-07-29 18:42:02 -04:00
|
|
|
|
|
|
|
|
connection = nmtst_create_minimal_connection ("test-connection-to-dbus-deprecated-props",
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_WIRELESS_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_wireless = nm_setting_wireless_new ();
|
2014-06-26 10:42:11 -04:00
|
|
|
ssid = g_bytes_new ("1234567", 7);
|
2014-07-29 18:42:02 -04:00
|
|
|
g_object_set (s_wireless,
|
|
|
|
|
NM_SETTING_WIRELESS_SSID, ssid,
|
|
|
|
|
NULL);
|
2014-06-26 10:42:11 -04:00
|
|
|
g_bytes_unref (ssid);
|
2014-07-29 18:42:02 -04:00
|
|
|
nm_connection_add_setting (connection, s_wireless);
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
/* Serialization should not have an 802-11-wireless.security property */
|
|
|
|
|
dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
|
|
|
|
|
g_assert (dict != NULL);
|
2014-07-29 18:42:02 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
wireless_dict = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_assert (wireless_dict != NULL);
|
2014-07-29 18:42:02 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
sec_val = g_variant_lookup_value (wireless_dict, "security", NULL);
|
2014-07-29 18:42:02 -04:00
|
|
|
g_assert (sec_val == NULL);
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (wireless_dict);
|
|
|
|
|
g_variant_unref (dict);
|
2014-07-29 18:42:02 -04:00
|
|
|
|
|
|
|
|
/* Now add an NMSettingWirelessSecurity and try again */
|
|
|
|
|
s_wsec = make_test_wsec_setting ("test-connection-to-dbus-deprecated-props");
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_wsec));
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
|
|
|
|
|
g_assert (dict != NULL);
|
2014-07-29 18:42:02 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
wireless_dict = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_assert (wireless_dict != NULL);
|
2014-07-29 18:42:02 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
sec_val = g_variant_lookup_value (wireless_dict, "security", NULL);
|
|
|
|
|
g_assert (g_variant_is_of_type (sec_val, G_VARIANT_TYPE_STRING));
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (sec_val, NULL), ==, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
|
2014-07-29 18:42:02 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (sec_val);
|
|
|
|
|
g_variant_unref (wireless_dict);
|
|
|
|
|
g_variant_unref (dict);
|
2014-07-29 18:42:02 -04:00
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
2014-08-06 19:35:31 -04:00
|
|
|
test_setting_new_from_dbus (void)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *dict;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
s_wsec = make_test_wsec_setting ("setting-new-from-dbus");
|
2019-06-27 09:07:16 +02:00
|
|
|
dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (s_wsec);
|
|
|
|
|
|
libnm-core: allow strict and relaxed error behavior for _nm_setting_new_from_dbus()
In some situations, we want strict checking of errors, for example when
NetworkManager receives a new connection from a client, the connection
must make sense as a whole (and since NetworkManager service is backward
compatible to the clients and not the other way around, there is no
excuse for sending invalid data to the server).
In other situations, we want a best-effort behavior. Like when
NetworkManager sends a connection to its clients, those clients
want to extract as many properties as they understand, but in order
to be forward compatible against newer server versions, invalid
or unknown properties must be accepted.
Previously, a mixture of both was done. Some issues caused a failure
to create a new NMSetting, other invalid parts were just silently
ignored or triggered a g_warning() in glib.
Now allow for both. When doing strict-validation, be more strict and
reject all unknown properties and catch when the user sets an invalid
argument. On the other hand, allow for a best-effort mode that
effectively cannot fail and will return a new NMSetting instance.
For now, add NMSettingParseFlags so that the caller can choose the
old behavior, strict parsing, or best effort.
This patch doesn't have any externally visible change except that
no more g_warnings will be emitted.
2016-03-18 13:42:50 +01:00
|
|
|
s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, NULL);
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (dict);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_assert (s_wsec);
|
|
|
|
|
g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk");
|
|
|
|
|
g_assert_cmpstr (nm_setting_wireless_security_get_leap_username (s_wsec), ==, "foobarbaz");
|
|
|
|
|
g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "random psk");
|
|
|
|
|
g_object_unref (s_wsec);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-30 10:57:45 -04:00
|
|
|
static void
|
|
|
|
|
test_setting_new_from_dbus_transform (void)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *s_wired;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *dict;
|
|
|
|
|
GVariantBuilder builder;
|
2014-07-30 10:57:45 -04:00
|
|
|
const char *test_mac_address = "11:22:33:44:55:66";
|
2014-08-16 10:09:48 -04:00
|
|
|
guint8 dbus_mac_address[ETH_ALEN];
|
2014-07-30 10:57:45 -04:00
|
|
|
GError *error = NULL;
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
nm_utils_hwaddr_aton (test_mac_address, dbus_mac_address, ETH_ALEN);
|
2014-07-30 10:57:45 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}",
|
|
|
|
|
NM_SETTING_WIRED_MAC_ADDRESS,
|
|
|
|
|
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
|
|
|
|
dbus_mac_address, ETH_ALEN, 1));
|
|
|
|
|
dict = g_variant_builder_end (&builder);
|
2014-07-30 10:57:45 -04:00
|
|
|
|
libnm-core: allow strict and relaxed error behavior for _nm_setting_new_from_dbus()
In some situations, we want strict checking of errors, for example when
NetworkManager receives a new connection from a client, the connection
must make sense as a whole (and since NetworkManager service is backward
compatible to the clients and not the other way around, there is no
excuse for sending invalid data to the server).
In other situations, we want a best-effort behavior. Like when
NetworkManager sends a connection to its clients, those clients
want to extract as many properties as they understand, but in order
to be forward compatible against newer server versions, invalid
or unknown properties must be accepted.
Previously, a mixture of both was done. Some issues caused a failure
to create a new NMSetting, other invalid parts were just silently
ignored or triggered a g_warning() in glib.
Now allow for both. When doing strict-validation, be more strict and
reject all unknown properties and catch when the user sets an invalid
argument. On the other hand, allow for a best-effort mode that
effectively cannot fail and will return a new NMSetting instance.
For now, add NMSettingParseFlags so that the caller can choose the
old behavior, strict parsing, or best effort.
This patch doesn't have any externally visible change except that
no more g_warnings will be emitted.
2016-03-18 13:42:50 +01:00
|
|
|
s_wired = _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRED, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error);
|
2014-07-30 10:57:45 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (nm_setting_wired_get_mac_address (NM_SETTING_WIRED (s_wired)), ==, test_mac_address);
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (dict);
|
2014-07-30 10:57:45 -04:00
|
|
|
g_object_unref (s_wired);
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-26 16:47:46 -04:00
|
|
|
static void
|
|
|
|
|
test_setting_new_from_dbus_enum (void)
|
|
|
|
|
{
|
|
|
|
|
NMSettingIP6Config *s_ip6;
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
2014-09-24 09:12:46 -04:00
|
|
|
NMSettingSerial *s_serial;
|
2014-06-26 16:47:46 -04:00
|
|
|
GVariant *dict;
|
|
|
|
|
GVariantBuilder builder;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
/* enum */
|
|
|
|
|
g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}",
|
|
|
|
|
NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
|
|
|
|
|
g_variant_new_int32 (NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
|
|
|
|
|
dict = g_variant_builder_end (&builder);
|
|
|
|
|
|
libnm-core: allow strict and relaxed error behavior for _nm_setting_new_from_dbus()
In some situations, we want strict checking of errors, for example when
NetworkManager receives a new connection from a client, the connection
must make sense as a whole (and since NetworkManager service is backward
compatible to the clients and not the other way around, there is no
excuse for sending invalid data to the server).
In other situations, we want a best-effort behavior. Like when
NetworkManager sends a connection to its clients, those clients
want to extract as many properties as they understand, but in order
to be forward compatible against newer server versions, invalid
or unknown properties must be accepted.
Previously, a mixture of both was done. Some issues caused a failure
to create a new NMSetting, other invalid parts were just silently
ignored or triggered a g_warning() in glib.
Now allow for both. When doing strict-validation, be more strict and
reject all unknown properties and catch when the user sets an invalid
argument. On the other hand, allow for a best-effort mode that
effectively cannot fail and will return a new NMSetting instance.
For now, add NMSettingParseFlags so that the caller can choose the
old behavior, strict parsing, or best effort.
This patch doesn't have any externally visible change except that
no more g_warnings will be emitted.
2016-03-18 13:42:50 +01:00
|
|
|
s_ip6 = (NMSettingIP6Config *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_IP6_CONFIG, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error);
|
2014-06-26 16:47:46 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (s_ip6), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
g_object_unref (s_ip6);
|
|
|
|
|
|
|
|
|
|
/* flags (and a transformed enum) */
|
|
|
|
|
g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}",
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
|
|
|
|
|
g_variant_new_uint32 (NM_WEP_KEY_TYPE_KEY));
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}",
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS,
|
|
|
|
|
g_variant_new_uint32 (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
|
|
|
|
|
NM_SETTING_SECRET_FLAG_NOT_SAVED));
|
|
|
|
|
dict = g_variant_builder_end (&builder);
|
|
|
|
|
|
libnm-core: allow strict and relaxed error behavior for _nm_setting_new_from_dbus()
In some situations, we want strict checking of errors, for example when
NetworkManager receives a new connection from a client, the connection
must make sense as a whole (and since NetworkManager service is backward
compatible to the clients and not the other way around, there is no
excuse for sending invalid data to the server).
In other situations, we want a best-effort behavior. Like when
NetworkManager sends a connection to its clients, those clients
want to extract as many properties as they understand, but in order
to be forward compatible against newer server versions, invalid
or unknown properties must be accepted.
Previously, a mixture of both was done. Some issues caused a failure
to create a new NMSetting, other invalid parts were just silently
ignored or triggered a g_warning() in glib.
Now allow for both. When doing strict-validation, be more strict and
reject all unknown properties and catch when the user sets an invalid
argument. On the other hand, allow for a best-effort mode that
effectively cannot fail and will return a new NMSetting instance.
For now, add NMSettingParseFlags so that the caller can choose the
old behavior, strict parsing, or best effort.
This patch doesn't have any externally visible change except that
no more g_warnings will be emitted.
2016-03-18 13:42:50 +01:00
|
|
|
s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error);
|
2014-06-26 16:47:46 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (nm_setting_wireless_security_get_wep_key_type (s_wsec), ==, NM_WEP_KEY_TYPE_KEY);
|
|
|
|
|
g_assert_cmpint (nm_setting_wireless_security_get_wep_key_flags (s_wsec), ==, (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
|
|
|
|
|
NM_SETTING_SECRET_FLAG_NOT_SAVED));
|
|
|
|
|
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
g_object_unref (s_wsec);
|
2014-09-24 09:12:46 -04:00
|
|
|
|
|
|
|
|
/* another transformed enum */
|
|
|
|
|
g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}",
|
|
|
|
|
NM_SETTING_SERIAL_PARITY,
|
|
|
|
|
g_variant_new_byte ('E'));
|
|
|
|
|
dict = g_variant_builder_end (&builder);
|
|
|
|
|
|
libnm-core: allow strict and relaxed error behavior for _nm_setting_new_from_dbus()
In some situations, we want strict checking of errors, for example when
NetworkManager receives a new connection from a client, the connection
must make sense as a whole (and since NetworkManager service is backward
compatible to the clients and not the other way around, there is no
excuse for sending invalid data to the server).
In other situations, we want a best-effort behavior. Like when
NetworkManager sends a connection to its clients, those clients
want to extract as many properties as they understand, but in order
to be forward compatible against newer server versions, invalid
or unknown properties must be accepted.
Previously, a mixture of both was done. Some issues caused a failure
to create a new NMSetting, other invalid parts were just silently
ignored or triggered a g_warning() in glib.
Now allow for both. When doing strict-validation, be more strict and
reject all unknown properties and catch when the user sets an invalid
argument. On the other hand, allow for a best-effort mode that
effectively cannot fail and will return a new NMSetting instance.
For now, add NMSettingParseFlags so that the caller can choose the
old behavior, strict parsing, or best effort.
This patch doesn't have any externally visible change except that
no more g_warnings will be emitted.
2016-03-18 13:42:50 +01:00
|
|
|
s_serial = (NMSettingSerial *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_SERIAL, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error);
|
2014-09-24 09:12:46 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (nm_setting_serial_get_parity (s_serial), ==, NM_SETTING_SERIAL_PARITY_EVEN);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
g_object_unref (s_serial);
|
2014-06-26 16:47:46 -04:00
|
|
|
}
|
|
|
|
|
|
2015-01-15 12:19:06 -05:00
|
|
|
static void
|
|
|
|
|
test_setting_new_from_dbus_bad (void)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
NMConnection *conn;
|
|
|
|
|
GBytes *ssid;
|
|
|
|
|
GPtrArray *addrs;
|
|
|
|
|
GVariant *orig_dict, *dict;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
/* We want to test:
|
|
|
|
|
* - ordinary scalar properties
|
|
|
|
|
* - string properties
|
|
|
|
|
* - GBytes-valued properties (which are handled specially by set_property_from_dbus())
|
|
|
|
|
* - enum/flags-valued properties
|
|
|
|
|
* - overridden properties
|
|
|
|
|
* - transformed properties
|
|
|
|
|
*
|
|
|
|
|
* No single setting class has examples of all of these, so we need two settings.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
conn = nm_simple_connection_new ();
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_connection_new ();
|
|
|
|
|
g_object_set (setting,
|
|
|
|
|
NM_SETTING_CONNECTION_ID, "test",
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, "83c5a841-1759-4cdb-bfce-8d4087956497",
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (conn, setting);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_wireless_new ();
|
|
|
|
|
ssid = g_bytes_new ("my-ssid", 7);
|
|
|
|
|
g_object_set (setting,
|
|
|
|
|
/* scalar */
|
|
|
|
|
NM_SETTING_WIRELESS_RATE, 100,
|
|
|
|
|
/* string */
|
|
|
|
|
NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
|
|
|
|
|
/* GBytes */
|
|
|
|
|
NM_SETTING_WIRELESS_SSID, ssid,
|
|
|
|
|
/* transformed */
|
|
|
|
|
NM_SETTING_WIRELESS_BSSID, "00:11:22:33:44:55",
|
|
|
|
|
NULL);
|
|
|
|
|
g_bytes_unref (ssid);
|
|
|
|
|
nm_connection_add_setting (conn, setting);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_ip6_config_new ();
|
|
|
|
|
addrs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
|
|
|
|
|
g_ptr_array_add (addrs, nm_ip_address_new (AF_INET6, "1234::5678", 64, NULL));
|
|
|
|
|
g_object_set (setting,
|
|
|
|
|
/* enum */
|
|
|
|
|
NM_SETTING_IP6_CONFIG_IP6_PRIVACY, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR,
|
|
|
|
|
/* overridden */
|
|
|
|
|
NM_SETTING_IP_CONFIG_ADDRESSES, addrs,
|
|
|
|
|
/* (needed in order to verify()) */
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
|
|
|
|
NULL);
|
|
|
|
|
g_ptr_array_unref (addrs);
|
|
|
|
|
nm_connection_add_setting (conn, setting);
|
|
|
|
|
|
|
|
|
|
orig_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
|
|
|
|
|
g_object_unref (conn);
|
|
|
|
|
|
|
|
|
|
/* sanity-check */
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (orig_dict, &error);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (conn);
|
|
|
|
|
g_object_unref (conn);
|
|
|
|
|
|
|
|
|
|
/* Compatible mismatches */
|
|
|
|
|
|
|
|
|
|
dict = g_variant_ref (orig_dict);
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRELESS_RATE,
|
|
|
|
|
"i", 10);
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_assert (conn);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
setting = nm_connection_get_setting (conn, NM_TYPE_SETTING_WIRELESS);
|
|
|
|
|
g_assert (setting);
|
|
|
|
|
g_assert_cmpint (nm_setting_wireless_get_rate (NM_SETTING_WIRELESS (setting)), ==, 10);
|
|
|
|
|
g_object_unref (conn);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
dict = g_variant_ref (orig_dict);
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
|
|
|
|
|
"i", NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_assert (conn);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
setting = nm_connection_get_setting (conn, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
g_assert (setting);
|
|
|
|
|
g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (setting)), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
|
|
|
|
|
g_object_unref (conn);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
/* Incompatible mismatches */
|
|
|
|
|
|
|
|
|
|
dict = g_variant_ref (orig_dict);
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRELESS_RATE,
|
|
|
|
|
"s", "ten");
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
g_assert (g_str_has_prefix (error->message, "802-11-wireless.rate:"));
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
dict = g_variant_ref (orig_dict);
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRELESS_MODE,
|
|
|
|
|
"b", FALSE);
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
g_assert (g_str_has_prefix (error->message, "802-11-wireless.mode:"));
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
dict = g_variant_ref (orig_dict);
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRELESS_SSID,
|
|
|
|
|
"s", "fred");
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
g_assert (g_str_has_prefix (error->message, "802-11-wireless.ssid:"));
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
dict = g_variant_ref (orig_dict);
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRELESS_BSSID,
|
|
|
|
|
"i", 42);
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
g_assert (g_str_has_prefix (error->message, "802-11-wireless.bssid:"));
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
dict = g_variant_ref (orig_dict);
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
|
|
|
|
|
"s", "private");
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
g_assert (g_str_has_prefix (error->message, "ipv6.ip6-privacy:"));
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
dict = g_variant_ref (orig_dict);
|
|
|
|
|
NMTST_VARIANT_EDITOR (dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP_CONFIG_ADDRESSES,
|
|
|
|
|
"s", "1234::5678");
|
|
|
|
|
);
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (dict, &error);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
g_assert (g_str_has_prefix (error->message, "ipv6.addresses:"));
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
g_variant_unref (dict);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (orig_dict);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static NMConnection *
|
|
|
|
|
new_test_connection (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
char *uuid;
|
|
|
|
|
guint64 timestamp = time (NULL);
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
setting = nm_setting_connection_new ();
|
|
|
|
|
uuid = nm_utils_uuid_generate ();
|
|
|
|
|
g_object_set (G_OBJECT (setting),
|
|
|
|
|
NM_SETTING_CONNECTION_ID, "foobar",
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, uuid,
|
|
|
|
|
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_CONNECTION_TIMESTAMP, timestamp,
|
|
|
|
|
NULL);
|
|
|
|
|
g_free (uuid);
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_wired_new ();
|
|
|
|
|
g_object_set (G_OBJECT (setting),
|
|
|
|
|
NM_SETTING_WIRED_MTU, 1592,
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_ip4_config_new ();
|
|
|
|
|
g_object_set (G_OBJECT (setting),
|
2014-10-19 17:30:10 -04:00
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
|
|
|
|
NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, "eyeofthetiger",
|
2014-07-24 08:53:33 -04:00
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
return connection;
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
static GVariant *
|
|
|
|
|
new_connection_dict (char **out_uuid,
|
2014-07-24 08:53:33 -04:00
|
|
|
const char **out_expected_id,
|
|
|
|
|
const char **out_expected_ip6_method)
|
|
|
|
|
{
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariantBuilder conn_builder, setting_builder;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_init (&conn_builder, NM_VARIANT_TYPE_CONNECTION);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
*out_uuid = nm_utils_uuid_generate ();
|
|
|
|
|
*out_expected_id = "My happy connection";
|
|
|
|
|
*out_expected_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
|
|
|
|
|
|
|
|
|
|
/* Connection setting */
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_variant_builder_add (&setting_builder, "{sv}",
|
|
|
|
|
NM_SETTING_NAME,
|
|
|
|
|
g_variant_new_string (NM_SETTING_CONNECTION_SETTING_NAME));
|
|
|
|
|
g_variant_builder_add (&setting_builder, "{sv}",
|
|
|
|
|
NM_SETTING_CONNECTION_ID,
|
|
|
|
|
g_variant_new_string (*out_expected_id));
|
|
|
|
|
g_variant_builder_add (&setting_builder, "{sv}",
|
|
|
|
|
NM_SETTING_CONNECTION_UUID,
|
|
|
|
|
g_variant_new_string (*out_uuid));
|
|
|
|
|
g_variant_builder_add (&setting_builder, "{sv}",
|
|
|
|
|
NM_SETTING_CONNECTION_TYPE,
|
|
|
|
|
g_variant_new_string (NM_SETTING_WIRED_SETTING_NAME));
|
|
|
|
|
|
|
|
|
|
g_variant_builder_add (&conn_builder, "{sa{sv}}",
|
|
|
|
|
NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
&setting_builder);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Wired setting */
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_variant_builder_add (&conn_builder, "{sa{sv}}",
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
&setting_builder);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* IP6 */
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_variant_builder_add (&setting_builder, "{sv}",
|
2014-10-19 17:30:10 -04:00
|
|
|
NM_SETTING_IP_CONFIG_METHOD,
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_new_string (*out_expected_ip6_method));
|
|
|
|
|
g_variant_builder_add (&conn_builder, "{sa{sv}}",
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
&setting_builder);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
return g_variant_builder_end (&conn_builder);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-29 10:44:31 +01:00
|
|
|
test_connection_replace_settings (void)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *new_settings;
|
2014-07-24 08:53:33 -04:00
|
|
|
GError *error = NULL;
|
|
|
|
|
gboolean success;
|
|
|
|
|
NMSettingConnection *s_con;
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip6;
|
2014-07-24 08:53:33 -04:00
|
|
|
char *uuid = NULL;
|
|
|
|
|
const char *expected_id = NULL, *expected_method = NULL;
|
|
|
|
|
|
|
|
|
|
connection = new_test_connection ();
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
new_settings = new_connection_dict (&uuid, &expected_id, &expected_method);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (new_settings);
|
|
|
|
|
|
|
|
|
|
/* Replace settings and test */
|
|
|
|
|
success = nm_connection_replace_settings (connection, new_settings, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
g_assert (s_con);
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
|
|
|
|
|
|
|
|
|
|
g_assert (nm_connection_get_setting_wired (connection));
|
|
|
|
|
g_assert (!nm_connection_get_setting_ip4_config (connection));
|
|
|
|
|
|
|
|
|
|
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
g_assert (s_ip6);
|
2014-10-19 17:30:10 -04:00
|
|
|
g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, expected_method);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_free (uuid);
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (new_settings);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-10-29 10:44:31 +01:00
|
|
|
test_connection_replace_settings_from_connection (void)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMConnection *connection, *replacement;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSetting *setting;
|
2014-06-26 10:42:11 -04:00
|
|
|
GBytes *ssid;
|
2014-07-24 08:53:33 -04:00
|
|
|
char *uuid = NULL;
|
|
|
|
|
const char *expected_id = "Awesome connection";
|
|
|
|
|
|
|
|
|
|
connection = new_test_connection ();
|
|
|
|
|
g_assert (connection);
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
replacement = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (replacement);
|
|
|
|
|
|
|
|
|
|
/* New connection setting */
|
|
|
|
|
setting = nm_setting_connection_new ();
|
|
|
|
|
g_assert (setting);
|
|
|
|
|
|
|
|
|
|
uuid = nm_utils_uuid_generate ();
|
|
|
|
|
g_object_set (setting,
|
|
|
|
|
NM_SETTING_CONNECTION_ID, expected_id,
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, uuid,
|
|
|
|
|
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (replacement, setting);
|
|
|
|
|
|
|
|
|
|
/* New wifi setting */
|
|
|
|
|
setting = nm_setting_wireless_new ();
|
|
|
|
|
g_assert (setting);
|
|
|
|
|
|
2014-06-26 10:42:11 -04:00
|
|
|
ssid = g_bytes_new ("1234567", 7);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_set (setting,
|
|
|
|
|
NM_SETTING_WIRELESS_SSID, ssid,
|
|
|
|
|
NM_SETTING_WIRELESS_MODE, "infrastructure",
|
|
|
|
|
NULL);
|
2014-06-26 10:42:11 -04:00
|
|
|
g_bytes_unref (ssid);
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_add_setting (replacement, setting);
|
|
|
|
|
|
|
|
|
|
/* Replace settings and test */
|
libnm-core: fix up connection deserialize/copy/replace semantics
libnm-util's connection deserializing/copying/replacing functions have
odd semantics where sometimes they both modify a connection AND return
an error. libnm-core tried to improve things by guaranteeing that the
connection would not be modified if the new settings were invalid, but
this ended up breaking a bunch of places that needed to be able to
work with invalid connections. So re-fix the functions by reverting
back to the old semantics, but having return values that clearly
distinguish whether the connection was modified or not.
For comparison:
- nm_connection_new_from_hash() / nm_simple_connection_new_from_dbus():
- libnm-util: returns a valid connection or NULL.
- OLD libnm-core: returned a valid connection or NULL.
- NEW libnm-core: returns a valid connection or NULL.
- nm_connection_duplicate() / nm_simple_connection_new_clone():
- libnm-util: always succeeds, whether or not the connection is
valid.
- OLD libnm-core: returned a valid connection or NULL
- NEW libnm-core: always succeeds, whether or not the connection
is valid.
- nm_connection_replace_settings_from_connection():
- libnm-util: always replaces the settings, but returns FALSE if
the connection is now invalid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: always replaces the settings, and has no
return value. (The modified connection is valid if and only if
the replaced-from connection was valid; just like with the
libnm-util version.)
- nm_connection_replace_settings():
- libnm-util: returns TRUE if the new settings are valid, or
FALSE if either (a) the new settings could not be deserialized
and the connection is unchanged, or (b) the new settings were
deserialized, and the connection was updated, but is now not
valid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: returns TRUE if the connection was updated
(whether or not it is valid), or FALSE if the new settings
could not be deserialized and the connection is unchanged.
2014-09-15 14:05:52 -04:00
|
|
|
nm_connection_replace_settings_from_connection (connection, replacement);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
g_assert (s_con);
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
|
|
|
|
|
|
|
|
|
|
g_assert (!nm_connection_get_setting_wired (connection));
|
|
|
|
|
g_assert (!nm_connection_get_setting_ip6_config (connection));
|
|
|
|
|
g_assert (nm_connection_get_setting_wireless (connection));
|
|
|
|
|
|
|
|
|
|
g_free (uuid);
|
|
|
|
|
g_object_unref (replacement);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-22 10:14:38 -04:00
|
|
|
static void
|
|
|
|
|
test_connection_replace_settings_bad (void)
|
|
|
|
|
{
|
libnm-core: fix up connection deserialize/copy/replace semantics
libnm-util's connection deserializing/copying/replacing functions have
odd semantics where sometimes they both modify a connection AND return
an error. libnm-core tried to improve things by guaranteeing that the
connection would not be modified if the new settings were invalid, but
this ended up breaking a bunch of places that needed to be able to
work with invalid connections. So re-fix the functions by reverting
back to the old semantics, but having return values that clearly
distinguish whether the connection was modified or not.
For comparison:
- nm_connection_new_from_hash() / nm_simple_connection_new_from_dbus():
- libnm-util: returns a valid connection or NULL.
- OLD libnm-core: returned a valid connection or NULL.
- NEW libnm-core: returns a valid connection or NULL.
- nm_connection_duplicate() / nm_simple_connection_new_clone():
- libnm-util: always succeeds, whether or not the connection is
valid.
- OLD libnm-core: returned a valid connection or NULL
- NEW libnm-core: always succeeds, whether or not the connection
is valid.
- nm_connection_replace_settings_from_connection():
- libnm-util: always replaces the settings, but returns FALSE if
the connection is now invalid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: always replaces the settings, and has no
return value. (The modified connection is valid if and only if
the replaced-from connection was valid; just like with the
libnm-util version.)
- nm_connection_replace_settings():
- libnm-util: returns TRUE if the new settings are valid, or
FALSE if either (a) the new settings could not be deserialized
and the connection is unchanged, or (b) the new settings were
deserialized, and the connection was updated, but is now not
valid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: returns TRUE if the connection was updated
(whether or not it is valid), or FALSE if the new settings
could not be deserialized and the connection is unchanged.
2014-09-15 14:05:52 -04:00
|
|
|
NMConnection *connection, *new_connection;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *new_settings;
|
|
|
|
|
GVariantBuilder builder, setting_builder;
|
2014-08-22 10:14:38 -04:00
|
|
|
GError *error = NULL;
|
|
|
|
|
gboolean success;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
new_connection = new_test_connection ();
|
|
|
|
|
g_assert (nm_connection_verify (new_connection, NULL));
|
|
|
|
|
s_con = nm_connection_get_setting_connection (new_connection);
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, NULL,
|
|
|
|
|
NM_SETTING_CONNECTION_ID, "bad-connection",
|
|
|
|
|
NULL);
|
|
|
|
|
g_assert (!nm_connection_verify (new_connection, NULL));
|
|
|
|
|
|
libnm-core: fix up connection deserialize/copy/replace semantics
libnm-util's connection deserializing/copying/replacing functions have
odd semantics where sometimes they both modify a connection AND return
an error. libnm-core tried to improve things by guaranteeing that the
connection would not be modified if the new settings were invalid, but
this ended up breaking a bunch of places that needed to be able to
work with invalid connections. So re-fix the functions by reverting
back to the old semantics, but having return values that clearly
distinguish whether the connection was modified or not.
For comparison:
- nm_connection_new_from_hash() / nm_simple_connection_new_from_dbus():
- libnm-util: returns a valid connection or NULL.
- OLD libnm-core: returned a valid connection or NULL.
- NEW libnm-core: returns a valid connection or NULL.
- nm_connection_duplicate() / nm_simple_connection_new_clone():
- libnm-util: always succeeds, whether or not the connection is
valid.
- OLD libnm-core: returned a valid connection or NULL
- NEW libnm-core: always succeeds, whether or not the connection
is valid.
- nm_connection_replace_settings_from_connection():
- libnm-util: always replaces the settings, but returns FALSE if
the connection is now invalid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: always replaces the settings, and has no
return value. (The modified connection is valid if and only if
the replaced-from connection was valid; just like with the
libnm-util version.)
- nm_connection_replace_settings():
- libnm-util: returns TRUE if the new settings are valid, or
FALSE if either (a) the new settings could not be deserialized
and the connection is unchanged, or (b) the new settings were
deserialized, and the connection was updated, but is now not
valid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: returns TRUE if the connection was updated
(whether or not it is valid), or FALSE if the new settings
could not be deserialized and the connection is unchanged.
2014-09-15 14:05:52 -04:00
|
|
|
/* nm_connection_replace_settings_from_connection() should succeed */
|
|
|
|
|
connection = new_test_connection ();
|
|
|
|
|
nm_connection_replace_settings_from_connection (connection, new_connection);
|
|
|
|
|
g_assert_cmpstr (nm_connection_get_id (connection), ==, "bad-connection");
|
|
|
|
|
g_assert (!nm_connection_verify (connection, NULL));
|
|
|
|
|
g_object_unref (connection);
|
2014-08-22 10:14:38 -04:00
|
|
|
|
libnm-core: fix up connection deserialize/copy/replace semantics
libnm-util's connection deserializing/copying/replacing functions have
odd semantics where sometimes they both modify a connection AND return
an error. libnm-core tried to improve things by guaranteeing that the
connection would not be modified if the new settings were invalid, but
this ended up breaking a bunch of places that needed to be able to
work with invalid connections. So re-fix the functions by reverting
back to the old semantics, but having return values that clearly
distinguish whether the connection was modified or not.
For comparison:
- nm_connection_new_from_hash() / nm_simple_connection_new_from_dbus():
- libnm-util: returns a valid connection or NULL.
- OLD libnm-core: returned a valid connection or NULL.
- NEW libnm-core: returns a valid connection or NULL.
- nm_connection_duplicate() / nm_simple_connection_new_clone():
- libnm-util: always succeeds, whether or not the connection is
valid.
- OLD libnm-core: returned a valid connection or NULL
- NEW libnm-core: always succeeds, whether or not the connection
is valid.
- nm_connection_replace_settings_from_connection():
- libnm-util: always replaces the settings, but returns FALSE if
the connection is now invalid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: always replaces the settings, and has no
return value. (The modified connection is valid if and only if
the replaced-from connection was valid; just like with the
libnm-util version.)
- nm_connection_replace_settings():
- libnm-util: returns TRUE if the new settings are valid, or
FALSE if either (a) the new settings could not be deserialized
and the connection is unchanged, or (b) the new settings were
deserialized, and the connection was updated, but is now not
valid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: returns TRUE if the connection was updated
(whether or not it is valid), or FALSE if the new settings
could not be deserialized and the connection is unchanged.
2014-09-15 14:05:52 -04:00
|
|
|
/* nm_connection_replace_settings() should succeed */
|
2014-08-22 10:14:38 -04:00
|
|
|
new_settings = nm_connection_to_dbus (new_connection, NM_CONNECTION_SERIALIZE_ALL);
|
|
|
|
|
g_assert (new_settings != NULL);
|
|
|
|
|
|
libnm-core: fix up connection deserialize/copy/replace semantics
libnm-util's connection deserializing/copying/replacing functions have
odd semantics where sometimes they both modify a connection AND return
an error. libnm-core tried to improve things by guaranteeing that the
connection would not be modified if the new settings were invalid, but
this ended up breaking a bunch of places that needed to be able to
work with invalid connections. So re-fix the functions by reverting
back to the old semantics, but having return values that clearly
distinguish whether the connection was modified or not.
For comparison:
- nm_connection_new_from_hash() / nm_simple_connection_new_from_dbus():
- libnm-util: returns a valid connection or NULL.
- OLD libnm-core: returned a valid connection or NULL.
- NEW libnm-core: returns a valid connection or NULL.
- nm_connection_duplicate() / nm_simple_connection_new_clone():
- libnm-util: always succeeds, whether or not the connection is
valid.
- OLD libnm-core: returned a valid connection or NULL
- NEW libnm-core: always succeeds, whether or not the connection
is valid.
- nm_connection_replace_settings_from_connection():
- libnm-util: always replaces the settings, but returns FALSE if
the connection is now invalid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: always replaces the settings, and has no
return value. (The modified connection is valid if and only if
the replaced-from connection was valid; just like with the
libnm-util version.)
- nm_connection_replace_settings():
- libnm-util: returns TRUE if the new settings are valid, or
FALSE if either (a) the new settings could not be deserialized
and the connection is unchanged, or (b) the new settings were
deserialized, and the connection was updated, but is now not
valid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: returns TRUE if the connection was updated
(whether or not it is valid), or FALSE if the new settings
could not be deserialized and the connection is unchanged.
2014-09-15 14:05:52 -04:00
|
|
|
connection = new_test_connection ();
|
|
|
|
|
success = nm_connection_replace_settings (connection, new_settings, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (nm_connection_get_id (connection), ==, "bad-connection");
|
|
|
|
|
g_assert (!nm_connection_verify (connection, NULL));
|
|
|
|
|
g_object_unref (connection);
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (new_settings);
|
libnm-core: fix up connection deserialize/copy/replace semantics
libnm-util's connection deserializing/copying/replacing functions have
odd semantics where sometimes they both modify a connection AND return
an error. libnm-core tried to improve things by guaranteeing that the
connection would not be modified if the new settings were invalid, but
this ended up breaking a bunch of places that needed to be able to
work with invalid connections. So re-fix the functions by reverting
back to the old semantics, but having return values that clearly
distinguish whether the connection was modified or not.
For comparison:
- nm_connection_new_from_hash() / nm_simple_connection_new_from_dbus():
- libnm-util: returns a valid connection or NULL.
- OLD libnm-core: returned a valid connection or NULL.
- NEW libnm-core: returns a valid connection or NULL.
- nm_connection_duplicate() / nm_simple_connection_new_clone():
- libnm-util: always succeeds, whether or not the connection is
valid.
- OLD libnm-core: returned a valid connection or NULL
- NEW libnm-core: always succeeds, whether or not the connection
is valid.
- nm_connection_replace_settings_from_connection():
- libnm-util: always replaces the settings, but returns FALSE if
the connection is now invalid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: always replaces the settings, and has no
return value. (The modified connection is valid if and only if
the replaced-from connection was valid; just like with the
libnm-util version.)
- nm_connection_replace_settings():
- libnm-util: returns TRUE if the new settings are valid, or
FALSE if either (a) the new settings could not be deserialized
and the connection is unchanged, or (b) the new settings were
deserialized, and the connection was updated, but is now not
valid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: returns TRUE if the connection was updated
(whether or not it is valid), or FALSE if the new settings
could not be deserialized and the connection is unchanged.
2014-09-15 14:05:52 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
/* But given an invalid dict, it should fail */
|
|
|
|
|
g_variant_builder_init (&builder, NM_VARIANT_TYPE_CONNECTION);
|
|
|
|
|
g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_variant_builder_add (&builder, "{sa{sv}}",
|
|
|
|
|
"ip-over-avian-carrier",
|
|
|
|
|
&setting_builder);
|
|
|
|
|
new_settings = g_variant_builder_end (&builder);
|
libnm-core: fix up connection deserialize/copy/replace semantics
libnm-util's connection deserializing/copying/replacing functions have
odd semantics where sometimes they both modify a connection AND return
an error. libnm-core tried to improve things by guaranteeing that the
connection would not be modified if the new settings were invalid, but
this ended up breaking a bunch of places that needed to be able to
work with invalid connections. So re-fix the functions by reverting
back to the old semantics, but having return values that clearly
distinguish whether the connection was modified or not.
For comparison:
- nm_connection_new_from_hash() / nm_simple_connection_new_from_dbus():
- libnm-util: returns a valid connection or NULL.
- OLD libnm-core: returned a valid connection or NULL.
- NEW libnm-core: returns a valid connection or NULL.
- nm_connection_duplicate() / nm_simple_connection_new_clone():
- libnm-util: always succeeds, whether or not the connection is
valid.
- OLD libnm-core: returned a valid connection or NULL
- NEW libnm-core: always succeeds, whether or not the connection
is valid.
- nm_connection_replace_settings_from_connection():
- libnm-util: always replaces the settings, but returns FALSE if
the connection is now invalid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: always replaces the settings, and has no
return value. (The modified connection is valid if and only if
the replaced-from connection was valid; just like with the
libnm-util version.)
- nm_connection_replace_settings():
- libnm-util: returns TRUE if the new settings are valid, or
FALSE if either (a) the new settings could not be deserialized
and the connection is unchanged, or (b) the new settings were
deserialized, and the connection was updated, but is now not
valid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: returns TRUE if the connection was updated
(whether or not it is valid), or FALSE if the new settings
could not be deserialized and the connection is unchanged.
2014-09-15 14:05:52 -04:00
|
|
|
|
|
|
|
|
connection = new_test_connection ();
|
2014-08-22 10:14:38 -04:00
|
|
|
success = nm_connection_replace_settings (connection, new_settings, &error);
|
libnm-core: fix up connection deserialize/copy/replace semantics
libnm-util's connection deserializing/copying/replacing functions have
odd semantics where sometimes they both modify a connection AND return
an error. libnm-core tried to improve things by guaranteeing that the
connection would not be modified if the new settings were invalid, but
this ended up breaking a bunch of places that needed to be able to
work with invalid connections. So re-fix the functions by reverting
back to the old semantics, but having return values that clearly
distinguish whether the connection was modified or not.
For comparison:
- nm_connection_new_from_hash() / nm_simple_connection_new_from_dbus():
- libnm-util: returns a valid connection or NULL.
- OLD libnm-core: returned a valid connection or NULL.
- NEW libnm-core: returns a valid connection or NULL.
- nm_connection_duplicate() / nm_simple_connection_new_clone():
- libnm-util: always succeeds, whether or not the connection is
valid.
- OLD libnm-core: returned a valid connection or NULL
- NEW libnm-core: always succeeds, whether or not the connection
is valid.
- nm_connection_replace_settings_from_connection():
- libnm-util: always replaces the settings, but returns FALSE if
the connection is now invalid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: always replaces the settings, and has no
return value. (The modified connection is valid if and only if
the replaced-from connection was valid; just like with the
libnm-util version.)
- nm_connection_replace_settings():
- libnm-util: returns TRUE if the new settings are valid, or
FALSE if either (a) the new settings could not be deserialized
and the connection is unchanged, or (b) the new settings were
deserialized, and the connection was updated, but is now not
valid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: returns TRUE if the connection was updated
(whether or not it is valid), or FALSE if the new settings
could not be deserialized and the connection is unchanged.
2014-09-15 14:05:52 -04:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING);
|
2015-02-06 13:31:06 +01:00
|
|
|
g_clear_error (&error);
|
2014-08-22 10:14:38 -04:00
|
|
|
g_assert (!success);
|
|
|
|
|
|
libnm-core: fix up connection deserialize/copy/replace semantics
libnm-util's connection deserializing/copying/replacing functions have
odd semantics where sometimes they both modify a connection AND return
an error. libnm-core tried to improve things by guaranteeing that the
connection would not be modified if the new settings were invalid, but
this ended up breaking a bunch of places that needed to be able to
work with invalid connections. So re-fix the functions by reverting
back to the old semantics, but having return values that clearly
distinguish whether the connection was modified or not.
For comparison:
- nm_connection_new_from_hash() / nm_simple_connection_new_from_dbus():
- libnm-util: returns a valid connection or NULL.
- OLD libnm-core: returned a valid connection or NULL.
- NEW libnm-core: returns a valid connection or NULL.
- nm_connection_duplicate() / nm_simple_connection_new_clone():
- libnm-util: always succeeds, whether or not the connection is
valid.
- OLD libnm-core: returned a valid connection or NULL
- NEW libnm-core: always succeeds, whether or not the connection
is valid.
- nm_connection_replace_settings_from_connection():
- libnm-util: always replaces the settings, but returns FALSE if
the connection is now invalid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: always replaces the settings, and has no
return value. (The modified connection is valid if and only if
the replaced-from connection was valid; just like with the
libnm-util version.)
- nm_connection_replace_settings():
- libnm-util: returns TRUE if the new settings are valid, or
FALSE if either (a) the new settings could not be deserialized
and the connection is unchanged, or (b) the new settings were
deserialized, and the connection was updated, but is now not
valid.
- OLD libnm-core: either replaced the settings and returned TRUE
(if the settings were valid), or else left the connection
unchanged and returned FALSE (if not).
- NEW libnm-core: returns TRUE if the connection was updated
(whether or not it is valid), or FALSE if the new settings
could not be deserialized and the connection is unchanged.
2014-09-15 14:05:52 -04:00
|
|
|
g_assert (nm_connection_verify (connection, NULL));
|
|
|
|
|
g_object_unref (connection);
|
2014-08-22 10:14:38 -04:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (new_settings);
|
2014-08-22 10:14:38 -04:00
|
|
|
g_object_unref (new_connection);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
2014-10-29 10:44:31 +01:00
|
|
|
test_connection_new_from_dbus (void)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *new_settings;
|
2014-07-24 08:53:33 -04:00
|
|
|
GError *error = NULL;
|
|
|
|
|
NMSettingConnection *s_con;
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip6;
|
2014-07-24 08:53:33 -04:00
|
|
|
char *uuid = NULL;
|
|
|
|
|
const char *expected_id = NULL, *expected_method = NULL;
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
new_settings = new_connection_dict (&uuid, &expected_id, &expected_method);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (new_settings);
|
|
|
|
|
|
|
|
|
|
/* Replace settings and test */
|
2016-03-23 16:04:54 +01:00
|
|
|
connection = _connection_new_from_dbus (new_settings, &error);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (connection);
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
g_assert (s_con);
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
|
|
|
|
|
|
|
|
|
|
g_assert (nm_connection_get_setting_wired (connection));
|
2014-11-27 15:59:08 +01:00
|
|
|
g_assert (nm_connection_get_setting_ip4_config (connection));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
g_assert (s_ip6);
|
2014-10-19 17:30:10 -04:00
|
|
|
g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, expected_method);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_free (uuid);
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (new_settings);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
check_permission (NMSettingConnection *s_con,
|
|
|
|
|
guint32 idx,
|
2016-02-14 14:09:21 +01:00
|
|
|
const char *expected_uname)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
|
|
|
|
gboolean success;
|
|
|
|
|
const char *ptype = NULL, *pitem = NULL, *detail = NULL;
|
|
|
|
|
|
|
|
|
|
success = nm_setting_connection_get_permission (s_con, 0, &ptype, &pitem, &detail);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpstr (ptype, ==, "user");
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (pitem);
|
|
|
|
|
g_assert_cmpstr (pitem, ==, expected_uname);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!detail);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define TEST_UNAME "asdfasfasdf"
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_connection_permissions_helpers (void)
|
|
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
gboolean success;
|
|
|
|
|
char buf[9] = { 0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00 };
|
2014-08-21 13:19:53 -04:00
|
|
|
char **perms;
|
2014-07-24 08:53:33 -04:00
|
|
|
const char *expected_perm = "user:" TEST_UNAME ":";
|
|
|
|
|
|
|
|
|
|
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
|
|
|
|
|
|
|
|
|
|
/* Ensure a bad [type] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strcmp (ptype, "user") == 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
success = nm_setting_connection_add_permission (s_con, "foobar", "blah", NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a bad [type] is rejected */
|
2019-03-16 21:21:43 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (ptype && ptype[0]));
|
2014-07-24 08:53:33 -04:00
|
|
|
success = nm_setting_connection_add_permission (s_con, NULL, "blah", NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a bad [item] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (uname));
|
|
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (p != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
success = nm_setting_connection_add_permission (s_con, "user", NULL, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a bad [item] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (uname[0] != '\0'));
|
|
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (p != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
success = nm_setting_connection_add_permission (s_con, "user", "", NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure an [item] with ':' is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strchr (uname, ':') == NULL));
|
|
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (p != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
success = nm_setting_connection_add_permission (s_con, "user", "ad:asdf", NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a non-UTF-8 [item] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (g_utf8_validate (uname, -1, NULL) == TRUE));
|
|
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (p != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
success = nm_setting_connection_add_permission (s_con, "user", buf, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a non-NULL [detail] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (detail == NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
success = nm_setting_connection_add_permission (s_con, "user", "dafasdf", "asdf");
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (!success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a valid call results in success */
|
|
|
|
|
success = nm_setting_connection_add_permission (s_con, "user", TEST_UNAME, NULL);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (success);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 1);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
check_permission (s_con, 0, TEST_UNAME);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Check the actual GObject property just to be paranoid */
|
2014-08-21 13:19:53 -04:00
|
|
|
g_object_get (G_OBJECT (s_con), NM_SETTING_CONNECTION_PERMISSIONS, &perms, NULL);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert (perms);
|
|
|
|
|
g_assert_cmpint (g_strv_length (perms), ==, 1);
|
|
|
|
|
g_assert_cmpstr (perms[0], ==, expected_perm);
|
2014-08-21 13:19:53 -04:00
|
|
|
g_strfreev (perms);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Now remove that permission and ensure we have 0 permissions */
|
|
|
|
|
nm_setting_connection_remove_permission (s_con, 0);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_object_unref (s_con);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_permission_property (NMSettingConnection *s_con,
|
|
|
|
|
const char *ptype,
|
|
|
|
|
const char *pitem,
|
|
|
|
|
int pitem_len,
|
|
|
|
|
const char *detail)
|
|
|
|
|
{
|
|
|
|
|
GString *str;
|
2014-08-21 13:19:53 -04:00
|
|
|
char *perms[2];
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
str = g_string_sized_new (50);
|
|
|
|
|
if (ptype)
|
|
|
|
|
g_string_append (str, ptype);
|
|
|
|
|
g_string_append_c (str, ':');
|
|
|
|
|
|
|
|
|
|
if (pitem) {
|
|
|
|
|
if (pitem_len >= 0)
|
|
|
|
|
g_string_append_len (str, pitem, pitem_len);
|
|
|
|
|
else
|
|
|
|
|
g_string_append (str, pitem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_string_append_c (str, ':');
|
|
|
|
|
|
|
|
|
|
if (detail)
|
|
|
|
|
g_string_append (str, detail);
|
|
|
|
|
|
2014-08-21 13:19:53 -04:00
|
|
|
perms[0] = str->str;
|
|
|
|
|
perms[1] = NULL;
|
|
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_PERMISSIONS, perms, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_string_free (str, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_connection_permissions_property (void)
|
|
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
gboolean success;
|
|
|
|
|
char buf[9] = { 0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00 };
|
|
|
|
|
|
|
|
|
|
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
|
|
|
|
|
|
|
|
|
|
/* Ensure a bad [type] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
add_permission_property (s_con, "foobar", "blah", -1, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a bad [type] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
add_permission_property (s_con, NULL, "blah", -1, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a bad [item] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (last_colon > str));
|
2014-07-24 08:53:33 -04:00
|
|
|
add_permission_property (s_con, "user", NULL, -1, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a bad [item] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (last_colon > str));
|
2014-07-24 08:53:33 -04:00
|
|
|
add_permission_property (s_con, "user", "", -1, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure an [item] with ':' in the middle is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (str[i] != ':'));
|
2014-07-24 08:53:33 -04:00
|
|
|
add_permission_property (s_con, "user", "ad:asdf", -1, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure an [item] with ':' at the end is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (str[i] != ':'));
|
2014-07-24 08:53:33 -04:00
|
|
|
add_permission_property (s_con, "user", "adasdfaf:", -1, NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a non-UTF-8 [item] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (g_utf8_validate (str, -1, NULL) == TRUE));
|
2014-07-24 08:53:33 -04:00
|
|
|
add_permission_property (s_con, "user", buf, (int) sizeof (buf), NULL);
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a non-NULL [detail] is rejected */
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (*(last_colon + 1) == '\0'));
|
2014-07-24 08:53:33 -04:00
|
|
|
add_permission_property (s_con, "user", "dafasdf", -1, "asdf");
|
|
|
|
|
g_test_assert_expected_messages ();
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Ensure a valid call results in success */
|
|
|
|
|
success = nm_setting_connection_add_permission (s_con, "user", TEST_UNAME, NULL);
|
2017-12-18 08:36:51 +01:00
|
|
|
g_assert (success);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 1);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-02-14 14:09:21 +01:00
|
|
|
check_permission (s_con, 0, TEST_UNAME);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Now remove that permission and ensure we have 0 permissions */
|
|
|
|
|
nm_setting_connection_remove_permission (s_con, 0);
|
2016-02-14 14:09:21 +01:00
|
|
|
g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_object_unref (s_con);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_compare_same (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *a, *b;
|
|
|
|
|
|
|
|
|
|
a = new_test_connection ();
|
2014-08-13 14:34:29 -04:00
|
|
|
b = nm_simple_connection_new_clone (a);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
|
|
|
|
|
g_object_unref (a);
|
|
|
|
|
g_object_unref (b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_compare_key_only_in_a (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *a, *b;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
a = new_test_connection ();
|
2014-08-13 14:34:29 -04:00
|
|
|
b = nm_simple_connection_new_clone (a);
|
2014-07-24 08:53:33 -04:00
|
|
|
s_con = (NMSettingConnection *) nm_connection_get_setting (b, NM_TYPE_SETTING_CONNECTION);
|
|
|
|
|
g_assert (s_con);
|
|
|
|
|
g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL);
|
|
|
|
|
|
|
|
|
|
g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
|
|
|
|
|
g_object_unref (a);
|
|
|
|
|
g_object_unref (b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_compare_setting_only_in_a (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *a, *b;
|
|
|
|
|
|
|
|
|
|
a = new_test_connection ();
|
2014-08-13 14:34:29 -04:00
|
|
|
b = nm_simple_connection_new_clone (a);
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_remove_setting (b, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
|
|
|
|
|
g_object_unref (a);
|
|
|
|
|
g_object_unref (b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_compare_key_only_in_b (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *a, *b;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
a = new_test_connection ();
|
2014-08-13 14:34:29 -04:00
|
|
|
b = nm_simple_connection_new_clone (a);
|
2014-07-24 08:53:33 -04:00
|
|
|
s_con = (NMSettingConnection *) nm_connection_get_setting (b, NM_TYPE_SETTING_CONNECTION);
|
|
|
|
|
g_assert (s_con);
|
|
|
|
|
g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL);
|
|
|
|
|
|
|
|
|
|
g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
|
|
|
|
|
g_object_unref (a);
|
|
|
|
|
g_object_unref (b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_compare_setting_only_in_b (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *a, *b;
|
|
|
|
|
|
|
|
|
|
a = new_test_connection ();
|
2014-08-13 14:34:29 -04:00
|
|
|
b = nm_simple_connection_new_clone (a);
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_remove_setting (a, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
|
|
|
|
|
g_object_unref (a);
|
|
|
|
|
g_object_unref (b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
const char *key_name;
|
|
|
|
|
guint32 result;
|
|
|
|
|
} DiffKey;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
const char *name;
|
|
|
|
|
DiffKey keys[30];
|
|
|
|
|
} DiffSetting;
|
|
|
|
|
|
|
|
|
|
#define ARRAY_LEN(a) (sizeof (a) / sizeof (a[0]))
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ensure_diffs (GHashTable *diffs, const DiffSetting *check, gsize n_check)
|
|
|
|
|
{
|
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
|
|
g_assert (g_hash_table_size (diffs) == n_check);
|
|
|
|
|
|
|
|
|
|
/* Loop through the settings */
|
|
|
|
|
for (i = 0; i < n_check; i++) {
|
|
|
|
|
GHashTable *setting_hash;
|
|
|
|
|
guint z = 0;
|
|
|
|
|
|
|
|
|
|
setting_hash = g_hash_table_lookup (diffs, check[i].name);
|
|
|
|
|
g_assert (setting_hash);
|
|
|
|
|
|
|
|
|
|
/* Get the number of keys to check */
|
|
|
|
|
while (check[i].keys[z].key_name)
|
|
|
|
|
z++;
|
|
|
|
|
g_assert (g_hash_table_size (setting_hash) == z);
|
|
|
|
|
|
|
|
|
|
/* Now compare the actual keys */
|
|
|
|
|
for (z = 0; check[i].keys[z].key_name; z++) {
|
|
|
|
|
NMSettingDiffResult result;
|
|
|
|
|
|
|
|
|
|
result = GPOINTER_TO_UINT (g_hash_table_lookup (setting_hash, check[i].keys[z].key_name));
|
|
|
|
|
g_assert (result == check[i].keys[z].result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_diff_a_only (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
GHashTable *out_diffs = NULL;
|
|
|
|
|
gboolean same;
|
|
|
|
|
const DiffSetting settings[] = {
|
|
|
|
|
{ NM_SETTING_CONNECTION_SETTING_NAME, {
|
|
|
|
|
{ NM_SETTING_CONNECTION_ID, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_CONNECTION_UUID, NM_SETTING_DIFF_RESULT_IN_A },
|
2016-06-21 16:41:05 +02:00
|
|
|
{ NM_SETTING_CONNECTION_STABLE_ID, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-07-24 08:53:33 -04:00
|
|
|
{ NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_CONNECTION_TYPE, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_CONNECTION_TIMESTAMP, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_CONNECTION_AUTOCONNECT, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-08-25 20:39:40 +02:00
|
|
|
{ NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A },
|
2016-10-08 10:27:15 +02:00
|
|
|
{ NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, NM_SETTING_DIFF_RESULT_IN_A },
|
all: add connection.multi-connect property for wildcard profiles
Add a new option that allows to activate a profile multiple times
(at the same time). Previoulsy, all profiles were implicitly
NM_SETTING_CONNECTION_MULTI_CONNECT_SINGLE, meaning, that activating
a profile that is already active will deactivate it first.
This will make more sense, as we also add more match-options how
profiles can be restricted to particular devices. We already have
connection.type, connection.interface-name, and (ethernet|wifi).mac-address
to restrict a profile to particular devices. For example, it is however
not possible to specify a wildcard like "eth*" to match a profile to
a set of devices by interface-name. That is another missing feature,
and once we extend the matching capabilities, it makes more sense to
activate a profile multiple times.
See also https://bugzilla.redhat.com/show_bug.cgi?id=997998, which
previously changed that a connection is restricted to a single activation
at a time. This work relaxes that again.
This only adds the new property, it is not used nor implemented yet.
https://bugzilla.redhat.com/show_bug.cgi?id=1555012
2018-04-10 11:45:35 +02:00
|
|
|
{ NM_SETTING_CONNECTION_MULTI_CONNECT, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-07-24 08:53:33 -04:00
|
|
|
{ NM_SETTING_CONNECTION_READ_ONLY, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_CONNECTION_PERMISSIONS, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_CONNECTION_ZONE, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_CONNECTION_MASTER, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_DIFF_RESULT_IN_A },
|
2015-05-06 10:54:35 +02:00
|
|
|
{ NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-07-24 08:53:33 -04:00
|
|
|
{ NM_SETTING_CONNECTION_SECONDARIES, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A },
|
2015-04-27 17:45:53 +02:00
|
|
|
{ NM_SETTING_CONNECTION_METERED, NM_SETTING_DIFF_RESULT_IN_A },
|
2015-10-07 11:48:30 +02:00
|
|
|
{ NM_SETTING_CONNECTION_LLDP, NM_SETTING_DIFF_RESULT_IN_A },
|
2017-11-02 09:25:40 +01:00
|
|
|
{ NM_SETTING_CONNECTION_AUTH_RETRIES, NM_SETTING_DIFF_RESULT_IN_A },
|
2017-11-10 14:49:27 +02:00
|
|
|
{ NM_SETTING_CONNECTION_MDNS, NM_SETTING_DIFF_RESULT_IN_A },
|
2018-08-31 10:48:18 +02:00
|
|
|
{ NM_SETTING_CONNECTION_LLMNR, NM_SETTING_DIFF_RESULT_IN_A },
|
2020-04-08 07:30:08 +00:00
|
|
|
{ NM_SETTING_CONNECTION_MUD_URL, NM_SETTING_DIFF_RESULT_IN_A },
|
2019-07-01 10:01:28 +02:00
|
|
|
{ NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-07-24 08:53:33 -04:00
|
|
|
{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }
|
|
|
|
|
} },
|
|
|
|
|
{ NM_SETTING_WIRED_SETTING_NAME, {
|
|
|
|
|
{ NM_SETTING_WIRED_PORT, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_SPEED, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_DUPLEX, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_AUTO_NEGOTIATE, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_CLONED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A },
|
all: make MAC address randomization algorithm configurable
For the per-connection settings "ethernet.cloned-mac-address"
and "wifi.cloned-mac-address", and for the per-device setting
"wifi.scan-rand-mac-address", we may generate MAC addresses using
either the "random" or "stable" algorithm.
Add new properties "generate-mac-address-mask" that allow to configure
which bits of the MAC address will be scrambled.
By default, the "random" and "stable" algorithms scamble all bits
of the MAC address, including the OUI part and generate a locally-
administered, unicast address.
By specifying a MAC address mask, we can now configure to perserve
parts of the current MAC address of the device. For example, setting
"FF:FF:FF:00:00:00" will preserve the first 3 octects of the current
MAC address.
One can also explicitly specify a MAC address to use instead of the
current MAC address. For example, "FF:FF:FF:00:00:00 68:F7:28:00:00:00"
sets the OUI part of the MAC address to "68:F7:28" while scrambling
the last 3 octects.
Similarly, "02:00:00:00:00:00 00:00:00:00:00:00" will scamble
all bits of the MAC address, except clearing the second-least
significant bit. Thus, creating a burned-in address, globally
administered.
One can also supply a list of MAC addresses like
"FF:FF:FF:00:00:00 68:F7:28:00:00:00 00:0C:29:00:00:00 ..." in which
case a MAC address is choosen randomly.
To fully scamble the MAC address one can configure
"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00".
which also randomly creates either a locally or globally administered
address.
With this, the following macchanger options can be implemented:
`macchanger --random`
This is the default if no mask is configured.
-> ""
while is the same as:
-> "00:00:00:00:00:00"
-> "02:00:00:00:00:00 02:00:00:00:00:00"
`macchanger --random --bia`
-> "02:00:00:00:00:00 00:00:00:00:00:00"
`macchanger --ending`
This option cannot be fully implemented, because macchanger
uses the current MAC address but also implies --bia.
-> "FF:FF:FF:00:00:00"
This would yields the same result only if the current MAC address
is already a burned-in address too. Otherwise, it has not the same
effect as --ending.
-> "FF:FF:FF:00:00:00 <MAC_ADDR>"
Alternatively, instead of using the current MAC address,
spell the OUI part out. But again, that is not really the
same as macchanger does because you explictly have to name
the OUI part to use.
`machanger --another`
`machanger --another_any`
-> "FF:FF:FF:00:00:00 <MAC_ADDR> <MAC_ADDR> ..."
"$(printf "FF:FF:FF:00:00:00 %s\n" "$(sed -n 's/^\([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) .*/\1:\2:\3:00:00:00/p' /usr/share/macchanger/wireless.list | xargs)")"
2016-06-22 20:31:39 +02:00
|
|
|
{ NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-07-24 08:53:33 -04:00
|
|
|
{ NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_MTU, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_S390_SUBCHANNELS, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_S390_NETTYPE, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_S390_OPTIONS, NM_SETTING_DIFF_RESULT_IN_A },
|
2015-05-11 21:59:51 +02:00
|
|
|
{ NM_SETTING_WIRED_WAKE_ON_LAN, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-07-24 08:53:33 -04:00
|
|
|
{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
|
|
|
|
|
} },
|
|
|
|
|
{ NM_SETTING_IP4_CONFIG_SETTING_NAME, {
|
2014-10-19 17:30:10 -04:00
|
|
|
{ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_IP_CONFIG_DNS, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_IP_CONFIG_DNS_SEARCH, NM_SETTING_DIFF_RESULT_IN_A },
|
2015-03-26 08:57:02 +01:00
|
|
|
{ NM_SETTING_IP_CONFIG_DNS_OPTIONS, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-10-19 17:30:10 -04:00
|
|
|
{ NM_SETTING_IP_CONFIG_ADDRESSES, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-10-20 21:30:56 -04:00
|
|
|
{ NM_SETTING_IP_CONFIG_GATEWAY, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-10-19 17:30:10 -04:00
|
|
|
{ NM_SETTING_IP_CONFIG_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-08-27 19:57:24 +02:00
|
|
|
{ NM_SETTING_IP_CONFIG_ROUTE_METRIC, NM_SETTING_DIFF_RESULT_IN_A },
|
all: rework configuring route table support by adding "route-table" setting
We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
2017-09-28 08:40:41 +02:00
|
|
|
{ NM_SETTING_IP_CONFIG_ROUTE_TABLE, NM_SETTING_DIFF_RESULT_IN_A },
|
2019-03-14 12:04:21 +01:00
|
|
|
{ NM_SETTING_IP_CONFIG_ROUTING_RULES, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-10-19 17:30:10 -04:00
|
|
|
{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-08-27 19:57:24 +02:00
|
|
|
{ NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A },
|
2016-02-03 11:12:07 +01:00
|
|
|
{ NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-10-19 17:30:10 -04:00
|
|
|
{ NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A },
|
2019-07-09 11:26:02 +02:00
|
|
|
{ NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS,NM_SETTING_DIFF_RESULT_IN_A },
|
2015-10-13 14:10:01 +02:00
|
|
|
{ NM_SETTING_IP4_CONFIG_DHCP_FQDN, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-10-19 17:30:10 -04:00
|
|
|
{ NM_SETTING_IP_CONFIG_NEVER_DEFAULT, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NM_SETTING_IP_CONFIG_MAY_FAIL, NM_SETTING_DIFF_RESULT_IN_A },
|
2015-09-07 18:00:10 +02:00
|
|
|
{ NM_SETTING_IP_CONFIG_DAD_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A },
|
2016-04-23 15:57:04 +02:00
|
|
|
{ NM_SETTING_IP_CONFIG_DNS_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A },
|
2019-10-15 10:27:10 +02:00
|
|
|
{ NM_SETTING_IP_CONFIG_DHCP_IAID, NM_SETTING_DIFF_RESULT_IN_A },
|
2014-07-24 08:53:33 -04:00
|
|
|
{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
|
|
|
|
|
} },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
connection = new_test_connection ();
|
|
|
|
|
|
|
|
|
|
same = nm_connection_diff (connection, NULL, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
|
|
|
|
|
g_assert (same == FALSE);
|
|
|
|
|
g_assert (out_diffs != NULL);
|
|
|
|
|
g_assert (g_hash_table_size (out_diffs) > 0);
|
|
|
|
|
|
|
|
|
|
ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
|
|
|
|
|
|
|
|
|
|
g_hash_table_destroy (out_diffs);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_diff_same (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *a, *b;
|
|
|
|
|
GHashTable *out_diffs = NULL;
|
|
|
|
|
gboolean same;
|
|
|
|
|
|
|
|
|
|
a = new_test_connection ();
|
2014-08-13 14:34:29 -04:00
|
|
|
b = nm_simple_connection_new_clone (a);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
|
|
|
|
|
g_assert (same == TRUE);
|
|
|
|
|
g_assert (out_diffs == NULL);
|
|
|
|
|
g_object_unref (a);
|
|
|
|
|
g_object_unref (b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_diff_different (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *a, *b;
|
|
|
|
|
GHashTable *out_diffs = NULL;
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip4;
|
2014-07-24 08:53:33 -04:00
|
|
|
gboolean same;
|
|
|
|
|
const DiffSetting settings[] = {
|
|
|
|
|
{ NM_SETTING_IP4_CONFIG_SETTING_NAME, {
|
2014-10-19 17:30:10 -04:00
|
|
|
{ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B },
|
2014-07-24 08:53:33 -04:00
|
|
|
{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
|
|
|
|
|
} },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
a = new_test_connection ();
|
2014-08-13 14:34:29 -04:00
|
|
|
b = nm_simple_connection_new_clone (a);
|
2014-07-24 08:53:33 -04:00
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (a);
|
|
|
|
|
g_assert (s_ip4);
|
|
|
|
|
g_object_set (G_OBJECT (s_ip4),
|
2014-10-19 17:30:10 -04:00
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
2014-07-24 08:53:33 -04:00
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
|
|
|
|
|
g_assert (same == FALSE);
|
|
|
|
|
g_assert (out_diffs != NULL);
|
|
|
|
|
g_assert (g_hash_table_size (out_diffs) > 0);
|
|
|
|
|
|
|
|
|
|
ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
|
|
|
|
|
|
|
|
|
|
g_hash_table_destroy (out_diffs);
|
|
|
|
|
g_object_unref (a);
|
|
|
|
|
g_object_unref (b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_diff_no_secrets (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *a, *b;
|
|
|
|
|
GHashTable *out_diffs = NULL;
|
|
|
|
|
NMSetting *s_pppoe;
|
|
|
|
|
gboolean same;
|
|
|
|
|
const DiffSetting settings[] = {
|
|
|
|
|
{ NM_SETTING_PPPOE_SETTING_NAME, {
|
|
|
|
|
{ NM_SETTING_PPPOE_PASSWORD, NM_SETTING_DIFF_RESULT_IN_B },
|
|
|
|
|
{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
|
|
|
|
|
} },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
a = new_test_connection ();
|
|
|
|
|
s_pppoe = nm_setting_pppoe_new ();
|
|
|
|
|
g_object_set (G_OBJECT (s_pppoe),
|
|
|
|
|
NM_SETTING_PPPOE_USERNAME, "thomas",
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (a, s_pppoe);
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
b = nm_simple_connection_new_clone (a);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Add a secret to B */
|
|
|
|
|
s_pppoe = NM_SETTING (nm_connection_get_setting_pppoe (b));
|
|
|
|
|
g_assert (s_pppoe);
|
|
|
|
|
g_object_set (G_OBJECT (s_pppoe),
|
|
|
|
|
NM_SETTING_PPPOE_PASSWORD, "secretpassword",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
/* Make sure the diff returns no results as secrets are ignored */
|
|
|
|
|
same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &out_diffs);
|
|
|
|
|
g_assert (same == TRUE);
|
|
|
|
|
g_assert (out_diffs == NULL);
|
|
|
|
|
|
|
|
|
|
/* Now make sure the diff returns results if secrets are not ignored */
|
|
|
|
|
same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
|
|
|
|
|
g_assert (same == FALSE);
|
|
|
|
|
g_assert (out_diffs != NULL);
|
|
|
|
|
g_assert (g_hash_table_size (out_diffs) > 0);
|
|
|
|
|
|
|
|
|
|
ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
|
|
|
|
|
|
|
|
|
|
g_hash_table_destroy (out_diffs);
|
|
|
|
|
g_object_unref (a);
|
|
|
|
|
g_object_unref (b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_diff_inferrable (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *a, *b;
|
|
|
|
|
GHashTable *out_diffs = NULL;
|
|
|
|
|
gboolean same;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSettingWired *s_wired;
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip4;
|
2014-07-24 08:53:33 -04:00
|
|
|
char *uuid;
|
|
|
|
|
const DiffSetting settings[] = {
|
|
|
|
|
{ NM_SETTING_CONNECTION_SETTING_NAME, {
|
|
|
|
|
{ NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A },
|
|
|
|
|
{ NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
|
|
|
|
|
} },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
a = new_test_connection ();
|
2014-08-13 14:34:29 -04:00
|
|
|
b = nm_simple_connection_new_clone (a);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Change the UUID, wired MTU, and set ignore-auto-dns */
|
|
|
|
|
s_con = nm_connection_get_setting_connection (a);
|
|
|
|
|
g_assert (s_con);
|
|
|
|
|
uuid = nm_utils_uuid_generate ();
|
|
|
|
|
g_object_set (G_OBJECT (s_con),
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, uuid,
|
|
|
|
|
NM_SETTING_CONNECTION_ID, "really neat connection",
|
|
|
|
|
NULL);
|
|
|
|
|
g_free (uuid);
|
|
|
|
|
|
|
|
|
|
s_wired = nm_connection_get_setting_wired (a);
|
|
|
|
|
g_assert (s_wired);
|
|
|
|
|
g_object_set (G_OBJECT (s_wired), NM_SETTING_WIRED_MTU, 300, NULL);
|
|
|
|
|
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (a);
|
|
|
|
|
g_assert (s_ip4);
|
2014-10-19 17:30:10 -04:00
|
|
|
g_object_set (G_OBJECT (s_ip4), NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, TRUE, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Make sure the diff returns no results as secrets are ignored */
|
|
|
|
|
same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs);
|
|
|
|
|
g_assert (same == TRUE);
|
|
|
|
|
g_assert (out_diffs == NULL);
|
|
|
|
|
|
|
|
|
|
/* And change a INFERRABLE property to ensure that it shows up in the diff results */
|
|
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, "usb0", NULL);
|
|
|
|
|
|
|
|
|
|
/* Make sure the diff returns no results as secrets are ignored */
|
|
|
|
|
same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs);
|
|
|
|
|
g_assert (same == FALSE);
|
|
|
|
|
g_assert (out_diffs != NULL);
|
|
|
|
|
g_assert (g_hash_table_size (out_diffs) > 0);
|
|
|
|
|
|
|
|
|
|
ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
|
|
|
|
|
|
|
|
|
|
g_hash_table_destroy (out_diffs);
|
|
|
|
|
g_object_unref (a);
|
|
|
|
|
g_object_unref (b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_generic_settings (NMConnection *connection, const char *ctype)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
char *uuid;
|
|
|
|
|
|
|
|
|
|
uuid = nm_utils_uuid_generate ();
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_connection_new ();
|
|
|
|
|
g_object_set (setting,
|
|
|
|
|
NM_SETTING_CONNECTION_ID, "asdfasdfadf",
|
|
|
|
|
NM_SETTING_CONNECTION_TYPE, ctype,
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, uuid,
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
g_free (uuid);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_ip4_config_new ();
|
2014-10-19 17:30:10 -04:00
|
|
|
g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_ip6_config_new ();
|
2014-10-19 17:30:10 -04:00
|
|
|
g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_good_base_types (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
gboolean success;
|
|
|
|
|
GError *error = NULL;
|
2014-06-26 10:42:11 -04:00
|
|
|
GBytes *ssid;
|
2014-07-30 10:57:45 -04:00
|
|
|
const char *bdaddr = "11:22:33:44:55:66";
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Try a basic wired connection */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_WIRED_SETTING_NAME);
|
|
|
|
|
setting = nm_setting_wired_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
|
|
|
|
|
/* Try a wired PPPoE connection */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_PPPOE_SETTING_NAME);
|
|
|
|
|
setting = nm_setting_pppoe_new ();
|
|
|
|
|
g_object_set (setting, NM_SETTING_PPPOE_USERNAME, "bob smith", NULL);
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
|
|
|
|
|
/* Wifi connection */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_WIRELESS_SETTING_NAME);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_wireless_new ();
|
2014-06-26 10:42:11 -04:00
|
|
|
ssid = g_bytes_new ("1234567", 7);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_set (setting,
|
2014-06-26 10:42:11 -04:00
|
|
|
NM_SETTING_WIRELESS_SSID, ssid,
|
2014-07-24 08:53:33 -04:00
|
|
|
NM_SETTING_WIRELESS_MODE, "infrastructure",
|
|
|
|
|
NULL);
|
2014-06-26 10:42:11 -04:00
|
|
|
g_bytes_unref (ssid);
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
|
|
|
|
|
/* Bluetooth connection */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_BLUETOOTH_SETTING_NAME);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_bluetooth_new ();
|
|
|
|
|
g_object_set (setting,
|
2014-07-30 10:57:45 -04:00
|
|
|
NM_SETTING_BLUETOOTH_BDADDR, bdaddr,
|
2014-07-24 08:53:33 -04:00
|
|
|
NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
|
|
|
|
|
/* WiMAX connection */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_WIMAX_SETTING_NAME);
|
|
|
|
|
setting = nm_setting_wimax_new ();
|
|
|
|
|
g_object_set (setting, NM_SETTING_WIMAX_NETWORK_NAME, "CLEAR", NULL);
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
|
|
|
|
|
/* GSM connection */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_GSM_SETTING_NAME);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_gsm_new ();
|
|
|
|
|
g_object_set (setting,
|
|
|
|
|
NM_SETTING_GSM_APN, "metered.billing.sucks",
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
/* CDMA connection */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_CDMA_SETTING_NAME);
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_cdma_new ();
|
|
|
|
|
g_object_set (setting,
|
|
|
|
|
NM_SETTING_CDMA_NUMBER, "#777",
|
|
|
|
|
NM_SETTING_CDMA_USERNAME, "foobar@vzw.com",
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_bad_base_types (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
gboolean success;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
/* Test various non-base connection types to make sure they are rejected;
|
|
|
|
|
* using a fake 'wired' connection so the rest of it verifies
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* Connection setting */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_CONNECTION_SETTING_NAME);
|
|
|
|
|
setting = nm_setting_wired_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2014-10-11 15:02:16 -04:00
|
|
|
g_assert (g_str_has_prefix (error->message, "connection.type: "));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (success == FALSE);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
|
|
|
|
|
/* PPP setting */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_PPP_SETTING_NAME);
|
|
|
|
|
setting = nm_setting_wired_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
setting = nm_setting_ppp_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2014-10-11 15:02:16 -04:00
|
|
|
g_assert (g_str_has_prefix (error->message, "connection.type: "));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (success == FALSE);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
|
|
|
|
|
/* Serial setting */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_SERIAL_SETTING_NAME);
|
|
|
|
|
setting = nm_setting_wired_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
setting = nm_setting_serial_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2014-10-11 15:02:16 -04:00
|
|
|
g_assert (g_str_has_prefix (error->message, "connection.type: "));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (success == FALSE);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
|
|
|
|
|
/* IP4 setting */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_IP4_CONFIG_SETTING_NAME);
|
|
|
|
|
setting = nm_setting_wired_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2014-10-11 15:02:16 -04:00
|
|
|
g_assert (g_str_has_prefix (error->message, "connection.type: "));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (success == FALSE);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
|
|
|
|
|
/* IP6 setting */
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
add_generic_settings (connection, NM_SETTING_IP6_CONFIG_SETTING_NAME);
|
|
|
|
|
setting = nm_setting_wired_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
success = nm_connection_verify (connection, &error);
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2014-10-11 15:02:16 -04:00
|
|
|
g_assert (g_str_has_prefix (error->message, "connection.type: "));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (success == FALSE);
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_compare_id (void)
|
|
|
|
|
{
|
2015-02-09 15:17:53 +01:00
|
|
|
gs_unref_object NMSetting *old = NULL, *new = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
|
|
old = nm_setting_connection_new ();
|
|
|
|
|
g_object_set (old,
|
|
|
|
|
NM_SETTING_CONNECTION_ID, "really awesome cool connection",
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, "fbbd59d5-acab-4e30-8f86-258d272617e7",
|
|
|
|
|
NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
new = nm_setting_duplicate (old);
|
|
|
|
|
g_object_set (new, NM_SETTING_CONNECTION_ID, "some different connection id", NULL);
|
|
|
|
|
|
|
|
|
|
/* First make sure they are different */
|
|
|
|
|
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
|
|
|
|
|
g_assert (success == FALSE);
|
|
|
|
|
|
|
|
|
|
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_IGNORE_ID);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
}
|
|
|
|
|
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
static void
|
|
|
|
|
test_setting_compare_addresses (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMSetting *s1 = NULL, *s2 = NULL;
|
|
|
|
|
gboolean success;
|
|
|
|
|
NMIPAddress *a;
|
|
|
|
|
GHashTable *result = NULL;
|
|
|
|
|
|
|
|
|
|
s1 = nm_setting_ip4_config_new ();
|
|
|
|
|
s2 = nm_setting_ip4_config_new ();
|
|
|
|
|
|
|
|
|
|
a = nm_ip_address_new (AF_INET, "192.168.7.5", 24, NULL);
|
|
|
|
|
|
2017-12-11 14:06:10 +01:00
|
|
|
nm_ip_address_set_attribute (a, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("xoxoxo"));
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
nm_setting_ip_config_add_address ((NMSettingIPConfig *) s1, a);
|
|
|
|
|
|
2017-12-11 14:06:10 +01:00
|
|
|
nm_ip_address_set_attribute (a, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("hello"));
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
nm_setting_ip_config_add_address ((NMSettingIPConfig *) s2, a);
|
|
|
|
|
|
|
|
|
|
nm_ip_address_unref (a);
|
|
|
|
|
|
2019-05-30 08:33:14 +02:00
|
|
|
if (nmtst_get_rand_uint32 () % 2)
|
2020-03-23 08:04:33 +01:00
|
|
|
NM_SWAP (s1, s2);
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
|
|
|
|
|
success = nm_setting_compare (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT);
|
|
|
|
|
g_assert (!success);
|
|
|
|
|
|
|
|
|
|
success = nm_setting_diff (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result);
|
|
|
|
|
g_assert (!success);
|
all: use nm_clear_pointer() instead of g_clear_pointer()
g_clear_pointer() would always cast the destroy notify function
pointer to GDestroyNotify. That means, it lost some type safety, like
GPtrArray *ptr_arr = ...
g_clear_pointer (&ptr_arr, g_array_unref);
Since glib 2.58 ([1]), g_clear_pointer() is also more type safe. But
this is not used by NetworkManager, because we don't set
GLIB_VERSION_MIN_REQUIRED to 2.58.
[1] https://gitlab.gnome.org/GNOME/glib/-/commit/f9a9902aac826ab4aecc25f6eb533a418a4fa559
We have nm_clear_pointer() to avoid this issue for a long time (pre
1.12.0). Possibly we should redefine in our source tree g_clear_pointer()
as nm_clear_pointer(). However, I don't like to patch glib functions
with our own variant. Arguably, we do patch g_clear_error() in
such a manner. But there the point is to make the function inlinable.
Also, nm_clear_pointer() returns a boolean that indicates whether
anything was cleared. That is sometimes useful. I think we should
just consistently use nm_clear_pointer() instead, which does always
the preferable thing.
Replace:
sed 's/\<g_clear_pointer *(\([^;]*\), *\([a-z_A-Z0-9]\+\) *)/nm_clear_pointer (\1, \2)/g' $(git grep -l g_clear_pointer) -i
2020-03-23 11:09:24 +01:00
|
|
|
nm_clear_pointer (&result, g_hash_table_unref);
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_compare_routes (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMSetting *s1 = NULL, *s2 = NULL;
|
|
|
|
|
gboolean success;
|
|
|
|
|
NMIPRoute *r;
|
|
|
|
|
GHashTable *result = NULL;
|
|
|
|
|
|
|
|
|
|
s1 = nm_setting_ip4_config_new ();
|
|
|
|
|
s2 = nm_setting_ip4_config_new ();
|
|
|
|
|
|
|
|
|
|
r = nm_ip_route_new (AF_INET, "192.168.12.0", 24, "192.168.11.1", 473, NULL);
|
|
|
|
|
|
2017-12-11 14:06:10 +01:00
|
|
|
nm_ip_route_set_attribute (r, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("xoxoxo"));
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
nm_setting_ip_config_add_route ((NMSettingIPConfig *) s1, r);
|
|
|
|
|
|
2017-12-11 14:06:10 +01:00
|
|
|
nm_ip_route_set_attribute (r, NM_IP_ADDRESS_ATTRIBUTE_LABEL, g_variant_new_string ("hello"));
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
nm_setting_ip_config_add_route ((NMSettingIPConfig *) s2, r);
|
|
|
|
|
|
|
|
|
|
nm_ip_route_unref (r);
|
|
|
|
|
|
2019-05-30 08:33:14 +02:00
|
|
|
if (nmtst_get_rand_uint32 () % 2)
|
2020-03-23 08:04:33 +01:00
|
|
|
NM_SWAP (s1, s2);
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
|
|
|
|
|
success = nm_setting_compare (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT);
|
|
|
|
|
g_assert (!success);
|
|
|
|
|
|
|
|
|
|
success = nm_setting_diff (s1, s2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &result);
|
|
|
|
|
g_assert (!success);
|
all: use nm_clear_pointer() instead of g_clear_pointer()
g_clear_pointer() would always cast the destroy notify function
pointer to GDestroyNotify. That means, it lost some type safety, like
GPtrArray *ptr_arr = ...
g_clear_pointer (&ptr_arr, g_array_unref);
Since glib 2.58 ([1]), g_clear_pointer() is also more type safe. But
this is not used by NetworkManager, because we don't set
GLIB_VERSION_MIN_REQUIRED to 2.58.
[1] https://gitlab.gnome.org/GNOME/glib/-/commit/f9a9902aac826ab4aecc25f6eb533a418a4fa559
We have nm_clear_pointer() to avoid this issue for a long time (pre
1.12.0). Possibly we should redefine in our source tree g_clear_pointer()
as nm_clear_pointer(). However, I don't like to patch glib functions
with our own variant. Arguably, we do patch g_clear_error() in
such a manner. But there the point is to make the function inlinable.
Also, nm_clear_pointer() returns a boolean that indicates whether
anything was cleared. That is sometimes useful. I think we should
just consistently use nm_clear_pointer() instead, which does always
the preferable thing.
Replace:
sed 's/\<g_clear_pointer *(\([^;]*\), *\([a-z_A-Z0-9]\+\) *)/nm_clear_pointer (\1, \2)/g' $(git grep -l g_clear_pointer) -i
2020-03-23 11:09:24 +01:00
|
|
|
nm_clear_pointer (&result, g_hash_table_unref);
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
}
|
|
|
|
|
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
static void
|
|
|
|
|
test_setting_compare_wired_cloned_mac_address (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMSetting *old = NULL, *new = NULL;
|
|
|
|
|
gboolean success;
|
|
|
|
|
gs_free char *str1 = NULL;
|
|
|
|
|
|
|
|
|
|
old = nm_setting_wired_new ();
|
|
|
|
|
g_object_set (old,
|
|
|
|
|
NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "stable",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr ("stable", ==, nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) old));
|
|
|
|
|
g_object_get (old, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL);
|
|
|
|
|
g_assert_cmpstr ("stable", ==, str1);
|
2020-03-23 11:00:43 +01:00
|
|
|
nm_clear_g_free (&str1);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
|
|
|
|
new = nm_setting_duplicate (old);
|
|
|
|
|
g_object_set (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr ("11:22:33:44:55:66", ==, nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) new));
|
|
|
|
|
g_object_get (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL);
|
|
|
|
|
g_assert_cmpstr ("11:22:33:44:55:66", ==, str1);
|
2020-03-23 11:00:43 +01:00
|
|
|
nm_clear_g_free (&str1);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
|
|
|
|
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
|
|
|
|
|
g_assert (!success);
|
|
|
|
|
g_clear_object (&new);
|
|
|
|
|
|
|
|
|
|
new = nm_setting_duplicate (old);
|
|
|
|
|
g_object_set (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "stable-bia", NULL);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr ("stable-bia", ==, nm_setting_wired_get_cloned_mac_address ((NMSettingWired *) new));
|
|
|
|
|
g_object_get (new, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, &str1, NULL);
|
|
|
|
|
g_assert_cmpstr ("stable-bia", ==, str1);
|
2020-03-23 11:00:43 +01:00
|
|
|
nm_clear_g_free (&str1);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
|
|
|
|
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
|
|
|
|
|
g_assert (!success);
|
|
|
|
|
g_clear_object (&new);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_compare_wireless_cloned_mac_address (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMSetting *old = NULL, *new = NULL;
|
|
|
|
|
gboolean success;
|
|
|
|
|
gs_free char *str1 = NULL;
|
|
|
|
|
|
|
|
|
|
old = nm_setting_wireless_new ();
|
|
|
|
|
g_object_set (old,
|
|
|
|
|
NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "stable",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr ("stable", ==, nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) old));
|
|
|
|
|
g_object_get (old, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL);
|
|
|
|
|
g_assert_cmpstr ("stable", ==, str1);
|
2020-03-23 11:00:43 +01:00
|
|
|
nm_clear_g_free (&str1);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
|
|
|
|
new = nm_setting_duplicate (old);
|
|
|
|
|
g_object_set (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "11:22:33:44:55:66", NULL);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr ("11:22:33:44:55:66", ==, nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) new));
|
|
|
|
|
g_object_get (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL);
|
|
|
|
|
g_assert_cmpstr ("11:22:33:44:55:66", ==, str1);
|
2020-03-23 11:00:43 +01:00
|
|
|
nm_clear_g_free (&str1);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
|
|
|
|
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
|
|
|
|
|
g_assert (!success);
|
|
|
|
|
g_clear_object (&new);
|
|
|
|
|
|
|
|
|
|
new = nm_setting_duplicate (old);
|
|
|
|
|
g_object_set (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "stable-bia", NULL);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr ("stable-bia", ==, nm_setting_wireless_get_cloned_mac_address ((NMSettingWireless *) new));
|
|
|
|
|
g_object_get (new, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, &str1, NULL);
|
|
|
|
|
g_assert_cmpstr ("stable-bia", ==, str1);
|
2016-09-28 15:34:52 +02:00
|
|
|
nm_clear_g_free (&str1);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
|
|
|
|
|
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
|
|
|
|
|
g_assert (!success);
|
|
|
|
|
g_clear_object (&new);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-18 14:20:12 +01:00
|
|
|
static void
|
|
|
|
|
test_setting_compare_timestamp (void)
|
|
|
|
|
{
|
2015-02-09 15:17:53 +01:00
|
|
|
gs_unref_object NMSetting *old = NULL, *new = NULL;
|
2014-11-18 14:20:12 +01:00
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
|
|
old = nm_setting_connection_new ();
|
|
|
|
|
g_object_set (old,
|
|
|
|
|
NM_SETTING_CONNECTION_ID, "ignore timestamp connection",
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, "b047a198-0e0a-4f0e-a653-eea09bb35e40",
|
|
|
|
|
NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
|
2014-11-19 16:01:43 +01:00
|
|
|
NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 1234567890,
|
2014-11-18 14:20:12 +01:00
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
new = nm_setting_duplicate (old);
|
2014-11-19 16:01:43 +01:00
|
|
|
g_object_set (new, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 1416316539, NULL);
|
2014-11-18 14:20:12 +01:00
|
|
|
|
|
|
|
|
/* First make sure they are different */
|
|
|
|
|
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
|
|
|
|
|
g_assert (success == FALSE);
|
|
|
|
|
|
|
|
|
|
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP);
|
|
|
|
|
g_assert (success);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-19 00:49:43 +02:00
|
|
|
typedef struct {
|
|
|
|
|
NMSettingSecretFlags secret_flags;
|
|
|
|
|
NMSettingCompareFlags comp_flags;
|
|
|
|
|
gboolean remove_secret;
|
|
|
|
|
} TestDataCompareSecrets;
|
|
|
|
|
|
|
|
|
|
static TestDataCompareSecrets *
|
|
|
|
|
test_data_compare_secrets_new (NMSettingSecretFlags secret_flags,
|
|
|
|
|
NMSettingCompareFlags comp_flags,
|
|
|
|
|
gboolean remove_secret)
|
|
|
|
|
{
|
|
|
|
|
TestDataCompareSecrets *data = g_new0 (TestDataCompareSecrets, 1);
|
|
|
|
|
|
|
|
|
|
data->secret_flags = secret_flags;
|
|
|
|
|
data->comp_flags = comp_flags;
|
|
|
|
|
data->remove_secret = remove_secret;
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-09 14:41:55 +01:00
|
|
|
static void
|
|
|
|
|
_test_compare_secrets_check_diff (NMSetting *a,
|
|
|
|
|
NMSetting *b,
|
|
|
|
|
NMSettingCompareFlags flags,
|
|
|
|
|
gboolean exp_same_psk,
|
|
|
|
|
gboolean exp_same_psk_flags)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_hashtable GHashTable *h = NULL;
|
|
|
|
|
NMSettingDiffResult _RESULT_IN_A = NM_SETTING_DIFF_RESULT_IN_A;
|
|
|
|
|
NMSettingDiffResult _RESULT_IN_B = NM_SETTING_DIFF_RESULT_IN_B;
|
|
|
|
|
gboolean invert_results;
|
|
|
|
|
gboolean diff_result;
|
|
|
|
|
NMSettingSecretFlags a_psk_flags = nm_setting_wireless_security_get_psk_flags (NM_SETTING_WIRELESS_SECURITY (a));
|
|
|
|
|
NMSettingSecretFlags b_psk_flags = nm_setting_wireless_security_get_psk_flags (NM_SETTING_WIRELESS_SECURITY (b));
|
|
|
|
|
const char *a_psk = nm_setting_wireless_security_get_psk (NM_SETTING_WIRELESS_SECURITY (a));
|
|
|
|
|
const char *b_psk = nm_setting_wireless_security_get_psk (NM_SETTING_WIRELESS_SECURITY (b));
|
|
|
|
|
|
|
|
|
|
g_assert (NM_IS_SETTING_WIRELESS_SECURITY (a));
|
|
|
|
|
g_assert (NM_IS_SETTING_WIRELESS_SECURITY (b));
|
|
|
|
|
|
|
|
|
|
invert_results = nmtst_get_rand_bool ();
|
|
|
|
|
if (invert_results) {
|
|
|
|
|
_RESULT_IN_A = NM_SETTING_DIFF_RESULT_IN_B;
|
|
|
|
|
_RESULT_IN_B = NM_SETTING_DIFF_RESULT_IN_A;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diff_result = nm_setting_diff (a, b, flags, invert_results, &h);
|
|
|
|
|
|
|
|
|
|
g_assert (exp_same_psk_flags == (a_psk_flags == b_psk_flags));
|
|
|
|
|
|
|
|
|
|
if (nm_streq0 (a_psk, b_psk))
|
|
|
|
|
g_assert (exp_same_psk);
|
|
|
|
|
else {
|
|
|
|
|
if (flags == NM_SETTING_COMPARE_FLAG_EXACT)
|
|
|
|
|
g_assert (!exp_same_psk);
|
|
|
|
|
else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) {
|
|
|
|
|
if ( !NM_FLAGS_HAS (a_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)
|
|
|
|
|
&& !NM_FLAGS_HAS (b_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED))
|
|
|
|
|
g_assert (!exp_same_psk);
|
|
|
|
|
else if ( !NM_FLAGS_HAS (a_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)
|
|
|
|
|
&& NM_FLAGS_HAS (b_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED))
|
|
|
|
|
g_assert (!exp_same_psk);
|
|
|
|
|
else
|
|
|
|
|
g_assert (exp_same_psk);
|
|
|
|
|
} else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) {
|
|
|
|
|
if ( !NM_FLAGS_HAS (a_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)
|
|
|
|
|
&& !NM_FLAGS_HAS (b_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED))
|
|
|
|
|
g_assert (!exp_same_psk);
|
|
|
|
|
else if ( !NM_FLAGS_HAS (a_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)
|
|
|
|
|
&& NM_FLAGS_HAS (b_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED))
|
|
|
|
|
g_assert (!exp_same_psk);
|
|
|
|
|
else
|
|
|
|
|
g_assert (exp_same_psk);
|
|
|
|
|
} else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
|
|
|
|
|
g_assert (exp_same_psk);
|
|
|
|
|
else
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert (diff_result == (exp_same_psk && exp_same_psk_flags));
|
|
|
|
|
g_assert (diff_result == (!h));
|
|
|
|
|
|
|
|
|
|
if (!diff_result) {
|
|
|
|
|
if (flags == NM_SETTING_COMPARE_FLAG_EXACT)
|
|
|
|
|
g_assert (!exp_same_psk);
|
|
|
|
|
else if ( NM_IN_SET (flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS,
|
|
|
|
|
NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
|
|
|
|
|
&& (a_psk_flags != b_psk_flags)
|
|
|
|
|
&& nm_setting_wireless_security_get_psk_flags (NM_SETTING_WIRELESS_SECURITY (a)) == NM_SETTING_SECRET_FLAG_NONE)
|
|
|
|
|
g_assert (!exp_same_psk);
|
|
|
|
|
else
|
|
|
|
|
g_assert (exp_same_psk);
|
|
|
|
|
|
|
|
|
|
g_assert ((!exp_same_psk) == g_hash_table_contains (h, NM_SETTING_WIRELESS_SECURITY_PSK));
|
|
|
|
|
if (!exp_same_psk) {
|
|
|
|
|
if (nm_setting_wireless_security_get_psk (NM_SETTING_WIRELESS_SECURITY (a)))
|
|
|
|
|
g_assert_cmpint (GPOINTER_TO_UINT (g_hash_table_lookup (h, NM_SETTING_WIRELESS_SECURITY_PSK)), ==, _RESULT_IN_A);
|
|
|
|
|
else
|
|
|
|
|
g_assert_cmpint (GPOINTER_TO_UINT (g_hash_table_lookup (h, NM_SETTING_WIRELESS_SECURITY_PSK)), ==, _RESULT_IN_B);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert ((!exp_same_psk_flags) == g_hash_table_contains (h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS));
|
|
|
|
|
if (!exp_same_psk_flags) {
|
|
|
|
|
if (nm_setting_wireless_security_get_psk_flags (NM_SETTING_WIRELESS_SECURITY (a)) != NM_SETTING_SECRET_FLAG_NONE)
|
|
|
|
|
g_assert_cmpint (GPOINTER_TO_UINT (g_hash_table_lookup (h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)), ==, _RESULT_IN_A);
|
|
|
|
|
else
|
|
|
|
|
g_assert_cmpint (GPOINTER_TO_UINT (g_hash_table_lookup (h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)), ==, _RESULT_IN_B);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (g_hash_table_size (h), ==, (!exp_same_psk) + (!exp_same_psk_flags));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert (diff_result == nm_setting_compare (a, b, flags));
|
|
|
|
|
g_assert (diff_result == nm_setting_compare (b, a, flags));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
2014-08-19 00:49:43 +02:00
|
|
|
test_setting_compare_secrets (gconstpointer test_data)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-08-19 00:49:43 +02:00
|
|
|
const TestDataCompareSecrets *data = test_data;
|
2019-01-09 14:41:55 +01:00
|
|
|
gs_unref_object NMConnection *conn_old = NULL;
|
|
|
|
|
gs_unref_object NMConnection *conn_new = NULL;
|
|
|
|
|
gs_unref_object NMSetting *old = NULL;
|
|
|
|
|
gs_unref_object NMSetting *new = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Make sure that a connection with transient/unsaved secrets compares
|
|
|
|
|
* successfully to the same connection without those secrets.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
old = nm_setting_wireless_security_new ();
|
|
|
|
|
g_object_set (old,
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
|
|
|
|
|
NM_SETTING_WIRELESS_SECURITY_PSK, "really cool psk",
|
|
|
|
|
NULL);
|
2014-08-19 00:49:43 +02:00
|
|
|
nm_setting_set_secret_flags (old, NM_SETTING_WIRELESS_SECURITY_PSK, data->secret_flags, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
new = nm_setting_duplicate (old);
|
2019-01-09 14:41:55 +01:00
|
|
|
if (data->remove_secret)
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_set (new, NM_SETTING_WIRELESS_SECURITY_PSK, NULL, NULL);
|
|
|
|
|
|
2019-01-09 14:41:55 +01:00
|
|
|
g_assert ((!data->remove_secret) == nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT));
|
|
|
|
|
g_assert ((!data->remove_secret) == nm_setting_compare (new, old, NM_SETTING_COMPARE_FLAG_EXACT));
|
|
|
|
|
|
|
|
|
|
_test_compare_secrets_check_diff (old, new, NM_SETTING_COMPARE_FLAG_EXACT, !data->remove_secret, TRUE);
|
|
|
|
|
_test_compare_secrets_check_diff (new, old, NM_SETTING_COMPARE_FLAG_EXACT, !data->remove_secret, TRUE);
|
|
|
|
|
|
|
|
|
|
g_assert (nm_setting_compare (old, new, data->comp_flags));
|
|
|
|
|
g_assert (nm_setting_compare (new, old, data->comp_flags));
|
|
|
|
|
|
|
|
|
|
_test_compare_secrets_check_diff (old, new, data->comp_flags, TRUE, TRUE);
|
|
|
|
|
_test_compare_secrets_check_diff (new, old, data->comp_flags, TRUE, TRUE);
|
|
|
|
|
|
|
|
|
|
/* OK. Try again, but this time not only change the secret, also let the secret flags differ... */
|
|
|
|
|
if (data->secret_flags != NM_SETTING_SECRET_FLAG_NONE) {
|
|
|
|
|
nm_setting_set_secret_flags (new, NM_SETTING_WIRELESS_SECURITY_PSK, NM_SETTING_SECRET_FLAG_NONE, NULL);
|
|
|
|
|
|
|
|
|
|
_test_compare_secrets_check_diff (old, new, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, FALSE);
|
|
|
|
|
_test_compare_secrets_check_diff (new, old, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, FALSE);
|
|
|
|
|
|
|
|
|
|
_test_compare_secrets_check_diff (old, new, data->comp_flags, TRUE, FALSE);
|
|
|
|
|
_test_compare_secrets_check_diff (new, old, data->comp_flags, FALSE, FALSE);
|
|
|
|
|
|
|
|
|
|
nm_setting_set_secret_flags (new, NM_SETTING_WIRELESS_SECURITY_PSK, data->secret_flags, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2019-01-09 14:41:55 +01:00
|
|
|
conn_old = nmtst_create_minimal_connection ("test-compare-secrets", NULL, NM_SETTING_WIRELESS_SETTING_NAME, NULL);
|
|
|
|
|
nm_connection_add_setting (conn_old, nm_setting_duplicate (old));
|
|
|
|
|
conn_new = nm_simple_connection_new_clone (conn_old);
|
|
|
|
|
nm_connection_add_setting (conn_new, nm_setting_duplicate (new));
|
|
|
|
|
|
|
|
|
|
g_assert ((!data->remove_secret) == nm_connection_compare (conn_old, conn_new, NM_SETTING_COMPARE_FLAG_EXACT));
|
|
|
|
|
g_assert ((!data->remove_secret) == nm_connection_compare (conn_new, conn_old, NM_SETTING_COMPARE_FLAG_EXACT));
|
|
|
|
|
|
|
|
|
|
g_assert (nm_connection_compare (conn_old, conn_new, data->comp_flags));
|
|
|
|
|
g_assert (nm_connection_compare (conn_new, conn_old, data->comp_flags));
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-08-19 00:49:43 +02:00
|
|
|
test_setting_compare_vpn_secrets (gconstpointer test_data)
|
2014-07-24 08:53:33 -04:00
|
|
|
{
|
2014-08-19 00:49:43 +02:00
|
|
|
const TestDataCompareSecrets *data = test_data;
|
2015-02-09 15:17:53 +01:00
|
|
|
gs_unref_object NMSetting *old = NULL, *new = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
|
|
/* Make sure that a connection with transient/unsaved secrets compares
|
|
|
|
|
* successfully to the same connection without those secrets.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
old = nm_setting_vpn_new ();
|
|
|
|
|
nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "foobarbaz", "really secret password");
|
|
|
|
|
nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "asdfasdfasdf", "really adfasdfasdfasdf");
|
|
|
|
|
nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "0123456778", "abcdefghijklmnpqrstuvqxyz");
|
|
|
|
|
nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "borkbork", "yet another really secret password");
|
2014-08-19 00:49:43 +02:00
|
|
|
nm_setting_set_secret_flags (old, "borkbork", data->secret_flags, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* Clear "borkbork" from the duplicated setting */
|
|
|
|
|
new = nm_setting_duplicate (old);
|
2014-08-19 00:49:43 +02:00
|
|
|
if (data->remove_secret) {
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_setting_vpn_remove_secret (NM_SETTING_VPN (new), "borkbork");
|
|
|
|
|
|
|
|
|
|
/* First make sure they are different */
|
|
|
|
|
success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
|
|
|
|
|
g_assert (success == FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-19 00:49:43 +02:00
|
|
|
success = nm_setting_compare (old, new, data->comp_flags);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (success);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_hwaddr_aton_ether_normal (void)
|
|
|
|
|
{
|
|
|
|
|
guint8 buf[100];
|
|
|
|
|
guint8 expected[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
|
|
|
|
|
|
2014-07-04 15:59:19 -04:00
|
|
|
g_assert (nm_utils_hwaddr_aton ("00:11:22:33:44:55", buf, ETH_ALEN) != NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_hwaddr_aton_ib_normal (void)
|
|
|
|
|
{
|
|
|
|
|
guint8 buf[100];
|
|
|
|
|
const char *source = "00:11:22:33:44:55:66:77:88:99:01:12:23:34:45:56:67:78:89:90";
|
|
|
|
|
guint8 expected[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
|
|
|
|
|
0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
|
|
|
|
|
0x90 };
|
|
|
|
|
|
2014-07-04 15:59:19 -04:00
|
|
|
g_assert (nm_utils_hwaddr_aton (source, buf, INFINIBAND_ALEN) != NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_hwaddr_aton_no_leading_zeros (void)
|
|
|
|
|
{
|
|
|
|
|
guint8 buf[100];
|
|
|
|
|
guint8 expected[ETH_ALEN] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05 };
|
|
|
|
|
|
2014-07-04 15:59:19 -04:00
|
|
|
g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:44:5", buf, ETH_ALEN) != NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_hwaddr_aton_malformed (void)
|
|
|
|
|
{
|
|
|
|
|
guint8 buf[100];
|
|
|
|
|
|
2014-07-04 15:59:19 -04:00
|
|
|
g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:a@%%", buf, ETH_ALEN) == NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-06-16 11:30:47 -04:00
|
|
|
static void
|
|
|
|
|
test_hwaddr_equal (void)
|
|
|
|
|
{
|
|
|
|
|
const char *string = "00:1a:2b:03:44:05";
|
|
|
|
|
const char *upper_string = "00:1A:2B:03:44:05";
|
|
|
|
|
const char *bad_string = "0:1a:2b:3:44:5";
|
|
|
|
|
const guint8 binary[ETH_ALEN] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05 };
|
|
|
|
|
const char *other_string = "1a:2b:03:44:05:00";
|
|
|
|
|
const guint8 other_binary[ETH_ALEN] = { 0x1A, 0x2B, 0x03, 0x44, 0x05, 0x00 };
|
|
|
|
|
const char *long_string = "00:1a:2b:03:44:05:06:07";
|
|
|
|
|
const guint8 long_binary[8] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05, 0x06, 0x07 };
|
|
|
|
|
const char *null_string = "00:00:00:00:00:00";
|
|
|
|
|
const guint8 null_binary[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
|
|
|
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (string, -1, string, -1));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (string, -1, upper_string, -1));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (string, -1, bad_string, -1));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (string, -1, binary, sizeof (binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (string, -1, other_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (string, -1, other_binary, sizeof (other_binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (string, -1, long_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (string, -1, long_binary, sizeof (long_binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (string, -1, null_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (string, -1, null_binary, sizeof (null_binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (string, -1, NULL, ETH_ALEN));
|
|
|
|
|
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), string, -1));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), upper_string, -1));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), bad_string, -1));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), binary, sizeof (binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), other_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), other_binary, sizeof (other_binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), long_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), long_binary, sizeof (long_binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), null_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), null_binary, sizeof (null_binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), NULL, ETH_ALEN));
|
|
|
|
|
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_string, -1, string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_string, -1, upper_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_string, -1, bad_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_string, -1, binary, sizeof (binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_string, -1, other_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_string, -1, other_binary, sizeof (other_binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_string, -1, long_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_string, -1, long_binary, sizeof (long_binary)));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (null_string, -1, null_string, -1));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (null_string, -1, null_binary, sizeof (null_binary)));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (null_string, -1, NULL, ETH_ALEN));
|
|
|
|
|
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), upper_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), bad_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), binary, sizeof (binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), other_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), other_binary, sizeof (other_binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), long_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), long_binary, sizeof (long_binary)));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), null_string, -1));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), null_binary, sizeof (null_binary)));
|
|
|
|
|
g_assert (nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), NULL, ETH_ALEN));
|
2019-11-14 15:08:31 +01:00
|
|
|
|
libnm: don't compare invalid mac addresses as equal in nm_utils_hwaddr_matches()
By passing as length of the MAC addresses -1 for both arguments, one
could get through to compare empty strings, NULL, and addresses longer
than the maximum. Such addresses are not valid, and they should never
compare equal (not even to themselves).
This is a change in behavior of public API, but it never made sense to
claim two addresses are equal, when they are not even valid addresses.
Also, avoid undefined behavior with "NULL, -1, NULL, -1" arguments,
where we would call memcmp() with zero length and NULL arguments.
UBSan flags that too.
2020-05-13 22:48:34 +02:00
|
|
|
g_assert (!nm_utils_hwaddr_matches (NULL, -1, NULL, -1));
|
2019-11-14 15:08:31 +01:00
|
|
|
g_assert (!nm_utils_hwaddr_matches (NULL, -1, string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (string, -1, NULL, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (NULL, -1, null_string, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_string, -1, NULL, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (NULL, -1, binary, sizeof (binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), NULL, -1));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (NULL, -1, null_binary, sizeof (null_binary)));
|
|
|
|
|
g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), NULL, -1));
|
2014-06-16 11:30:47 -04:00
|
|
|
}
|
|
|
|
|
|
2014-10-28 08:32:25 -04:00
|
|
|
static void
|
|
|
|
|
test_hwaddr_canonical (void)
|
|
|
|
|
{
|
|
|
|
|
const char *string = "00:1A:2B:03:44:05";
|
|
|
|
|
const char *lower_string = "00:1a:2b:03:44:05";
|
|
|
|
|
const char *short_string = "0:1a:2b:3:44:5";
|
2014-10-28 08:56:07 -04:00
|
|
|
const char *hyphen_string = "00-1a-2b-03-44-05";
|
2014-10-28 08:32:25 -04:00
|
|
|
const char *invalid_string = "00:1A:2B";
|
|
|
|
|
char *canonical;
|
|
|
|
|
|
|
|
|
|
canonical = nm_utils_hwaddr_canonical (string, ETH_ALEN);
|
|
|
|
|
g_assert_cmpstr (canonical, ==, string);
|
|
|
|
|
g_free (canonical);
|
|
|
|
|
|
|
|
|
|
canonical = nm_utils_hwaddr_canonical (lower_string, ETH_ALEN);
|
|
|
|
|
g_assert_cmpstr (canonical, ==, string);
|
|
|
|
|
g_free (canonical);
|
|
|
|
|
|
|
|
|
|
canonical = nm_utils_hwaddr_canonical (short_string, ETH_ALEN);
|
|
|
|
|
g_assert_cmpstr (canonical, ==, string);
|
|
|
|
|
g_free (canonical);
|
|
|
|
|
|
2014-10-28 08:56:07 -04:00
|
|
|
canonical = nm_utils_hwaddr_canonical (hyphen_string, ETH_ALEN);
|
|
|
|
|
g_assert_cmpstr (canonical, ==, string);
|
|
|
|
|
g_free (canonical);
|
|
|
|
|
|
2014-10-28 08:32:25 -04:00
|
|
|
canonical = nm_utils_hwaddr_canonical (invalid_string, ETH_ALEN);
|
|
|
|
|
g_assert_cmpstr (canonical, ==, NULL);
|
|
|
|
|
|
|
|
|
|
canonical = nm_utils_hwaddr_canonical (invalid_string, -1);
|
|
|
|
|
g_assert_cmpstr (canonical, ==, invalid_string);
|
|
|
|
|
g_free (canonical);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
|
|
|
|
test_connection_changed_cb (NMConnection *connection, gboolean *data)
|
|
|
|
|
{
|
|
|
|
|
*data = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-14 16:45:53 +01:00
|
|
|
static guint32
|
|
|
|
|
_netmask_to_prefix (guint32 netmask)
|
|
|
|
|
{
|
|
|
|
|
guint32 prefix;
|
|
|
|
|
guint8 v;
|
|
|
|
|
const guint8 *p = (guint8 *) &netmask;
|
|
|
|
|
|
|
|
|
|
if (p[3]) {
|
|
|
|
|
prefix = 24;
|
|
|
|
|
v = p[3];
|
|
|
|
|
} else if (p[2]) {
|
|
|
|
|
prefix = 16;
|
|
|
|
|
v = p[2];
|
|
|
|
|
} else if (p[1]) {
|
|
|
|
|
prefix = 8;
|
|
|
|
|
v = p[1];
|
|
|
|
|
} else {
|
|
|
|
|
prefix = 0;
|
|
|
|
|
v = p[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (v) {
|
|
|
|
|
prefix++;
|
|
|
|
|
v <<= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (prefix, <=, 32);
|
|
|
|
|
|
|
|
|
|
/* we re-implemented the netmask-to-prefix code differently. Check
|
|
|
|
|
* that they agree. */
|
|
|
|
|
g_assert_cmpint (prefix, ==, nm_utils_ip4_netmask_to_prefix (netmask));
|
|
|
|
|
|
|
|
|
|
return prefix;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
|
|
|
|
test_ip4_prefix_to_netmask (void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i<=32; i++) {
|
2017-09-05 15:25:34 +02:00
|
|
|
guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i);
|
2018-12-14 16:45:53 +01:00
|
|
|
int plen = _netmask_to_prefix (netmask);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_assert_cmpint (i, ==, plen);
|
|
|
|
|
{
|
|
|
|
|
guint32 msk = 0x80000000;
|
|
|
|
|
guint32 netmask2 = 0;
|
|
|
|
|
guint32 prefix = i;
|
|
|
|
|
while (prefix > 0) {
|
|
|
|
|
netmask2 |= msk;
|
|
|
|
|
msk >>= 1;
|
|
|
|
|
prefix--;
|
|
|
|
|
}
|
|
|
|
|
g_assert_cmpint (netmask, ==, (guint32) htonl (netmask2));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_ip4_netmask_to_prefix (void)
|
|
|
|
|
{
|
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
|
|
GRand *rand = g_rand_new ();
|
|
|
|
|
|
|
|
|
|
g_rand_set_seed (rand, 1);
|
|
|
|
|
|
|
|
|
|
for (i = 2; i<=32; i++) {
|
2017-09-05 15:25:34 +02:00
|
|
|
guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i);
|
|
|
|
|
guint32 netmask_lowest_bit = netmask & ~_nm_utils_ip4_prefix_to_netmask (i-1);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2018-12-14 16:45:53 +01:00
|
|
|
g_assert_cmpint (i, ==, _netmask_to_prefix (netmask));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
for (j = 0; j < 2*i; j++) {
|
|
|
|
|
guint32 r = g_rand_int (rand);
|
|
|
|
|
guint32 netmask_holey;
|
|
|
|
|
guint32 prefix_holey;
|
|
|
|
|
|
|
|
|
|
netmask_holey = (netmask & r) | netmask_lowest_bit;
|
|
|
|
|
|
|
|
|
|
if (netmask_holey == netmask)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* create an invalid netmask with holes and check that the function
|
|
|
|
|
* returns the longest prefix. */
|
2018-12-14 16:45:53 +01:00
|
|
|
prefix_holey = _netmask_to_prefix (netmask_holey);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_assert_cmpint (i, ==, prefix_holey);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_rand_free (rand);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define ASSERT_CHANGED(statement) \
|
2016-02-14 14:09:21 +01:00
|
|
|
G_STMT_START { \
|
2014-07-24 08:53:33 -04:00
|
|
|
changed = FALSE; \
|
|
|
|
|
statement; \
|
|
|
|
|
g_assert (changed); \
|
2016-02-14 14:09:21 +01:00
|
|
|
} G_STMT_END
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
#define ASSERT_UNCHANGED(statement) \
|
2016-02-14 14:09:21 +01:00
|
|
|
G_STMT_START { \
|
2014-07-24 08:53:33 -04:00
|
|
|
changed = FALSE; \
|
|
|
|
|
statement; \
|
|
|
|
|
g_assert (!changed); \
|
2016-02-14 14:09:21 +01:00
|
|
|
} G_STMT_END
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
|
|
|
|
|
connection = new_test_connection ();
|
|
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
|
|
|
|
/* Add new setting */
|
|
|
|
|
ASSERT_CHANGED (nm_connection_add_setting (connection, nm_setting_vlan_new ()));
|
|
|
|
|
|
|
|
|
|
/* Remove existing setting */
|
|
|
|
|
ASSERT_CHANGED (nm_connection_remove_setting (connection, NM_TYPE_SETTING_VLAN));
|
|
|
|
|
|
|
|
|
|
/* Remove non-existing setting */
|
|
|
|
|
ASSERT_UNCHANGED (nm_connection_remove_setting (connection, NM_TYPE_SETTING_VLAN));
|
|
|
|
|
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_connection_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
NMSettingConnection *s_con;
|
2015-02-09 15:17:53 +01:00
|
|
|
gs_free char *uuid = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
|
|
|
|
s_con = (NMSettingConnection *) nm_setting_connection_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_con));
|
|
|
|
|
|
|
|
|
|
ASSERT_CHANGED (g_object_set (s_con, NM_SETTING_CONNECTION_ID, "adfadfasdfaf", NULL));
|
|
|
|
|
|
|
|
|
|
ASSERT_CHANGED (nm_setting_connection_add_permission (s_con, "user", "billsmith", NULL));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_connection_remove_permission (s_con, 0));
|
|
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (iter != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_connection_remove_permission (s_con, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
uuid = nm_utils_uuid_generate ();
|
|
|
|
|
ASSERT_CHANGED (nm_setting_connection_add_secondary (s_con, uuid));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_connection_remove_secondary (s_con, 0));
|
|
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_connection_remove_secondary (s_con, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_bond_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
NMSettingBond *s_bond;
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
|
|
|
|
s_bond = (NMSettingBond *) nm_setting_bond_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_bond));
|
|
|
|
|
|
|
|
|
|
ASSERT_CHANGED (nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY));
|
|
|
|
|
ASSERT_UNCHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY));
|
|
|
|
|
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_ip4_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip4;
|
2014-09-16 16:42:46 -04:00
|
|
|
NMIPAddress *addr;
|
|
|
|
|
NMIPRoute *route;
|
|
|
|
|
GError *error = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_ip4));
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip4, "11.22.0.0"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip4, 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns->len));
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip4, 1));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_dns (s_ip4, "33.44.0.0");
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_clear_dns (s_ip4));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_search->len));
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 1));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_clear_dns_searches (s_ip4));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-20 21:30:56 -04:00
|
|
|
addr = nm_ip_address_new (AF_INET, "22.33.0.0", 24, &error);
|
2014-09-16 16:42:46 -04:00
|
|
|
g_assert_no_error (error);
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip4, addr));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip4, 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->addresses->len));
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip4, 1));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_clear_addresses (s_ip4));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-09-16 16:42:46 -04:00
|
|
|
route = nm_ip_route_new (AF_INET, "22.33.0.0", 24, NULL, 0, &error);
|
|
|
|
|
g_assert_no_error (error);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip4, route));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip4, 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->routes->len));
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip4, 1));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_route (s_ip4, route);
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_clear_routes (s_ip4));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2015-03-26 08:57:02 +01:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_dns_option (s_ip4, "debug"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 0));
|
|
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_options->len));
|
2015-03-26 08:57:02 +01:00
|
|
|
ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2014-09-16 16:42:46 -04:00
|
|
|
nm_ip_address_unref (addr);
|
|
|
|
|
nm_ip_route_unref (route);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_ip6_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
2014-10-19 17:30:10 -04:00
|
|
|
NMSettingIPConfig *s_ip6;
|
2014-09-16 16:42:46 -04:00
|
|
|
NMIPAddress *addr;
|
|
|
|
|
NMIPRoute *route;
|
|
|
|
|
GError *error = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_ip6));
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip6, "1:2:3::4:5:6"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip6, 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns->len));
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip6, 1));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_dns (s_ip6, "1:2:3::4:5:6");
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_clear_dns (s_ip6));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->dns_search->len));
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 1));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com");
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_clear_dns_searches (s_ip6));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-20 21:30:56 -04:00
|
|
|
addr = nm_ip_address_new (AF_INET6, "1:2:3::4:5:6", 64, &error);
|
2014-09-16 16:42:46 -04:00
|
|
|
g_assert_no_error (error);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip6, addr));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip6, 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->addresses->len));
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip6, 1));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_address (s_ip6, addr);
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_clear_addresses (s_ip6));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-09-16 16:42:46 -04:00
|
|
|
route = nm_ip_route_new (AF_INET6, "1:2:3::4:5:6", 128, NULL, 0, &error);
|
|
|
|
|
g_assert_no_error (error);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip6, route));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip6, 0));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx >= 0 && idx < priv->routes->len));
|
2014-10-19 17:30:10 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip6, 1));
|
2014-07-24 08:53:33 -04:00
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
2014-10-19 17:30:10 -04:00
|
|
|
nm_setting_ip_config_add_route (s_ip6, route);
|
|
|
|
|
ASSERT_CHANGED (nm_setting_ip_config_clear_routes (s_ip6));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-09-16 16:42:46 -04:00
|
|
|
nm_ip_address_unref (addr);
|
|
|
|
|
nm_ip_route_unref (route);
|
2014-07-24 08:53:33 -04:00
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_vlan_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
NMSettingVlan *s_vlan;
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
|
|
|
|
s_vlan = (NMSettingVlan *) nm_setting_vlan_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_vlan));
|
|
|
|
|
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1, 3));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 0));
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx < g_slist_length (list)));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_INGRESS_MAP, "1:3"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vlan_clear_priorities (s_vlan, NM_VLAN_INGRESS_MAP));
|
|
|
|
|
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1, 3));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 0));
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (idx < g_slist_length (list)));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_EGRESS_MAP, "1:3"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vlan_clear_priorities (s_vlan, NM_VLAN_EGRESS_MAP));
|
|
|
|
|
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_vpn_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
NMSettingVpn *s_vpn;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_vpn));
|
|
|
|
|
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vpn_add_data_item (s_vpn, "foobar", "baz"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vpn_remove_data_item (s_vpn, "foobar"));
|
|
|
|
|
ASSERT_UNCHANGED (nm_setting_vpn_remove_data_item (s_vpn, "not added"));
|
|
|
|
|
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vpn_add_secret (s_vpn, "foobar", "baz"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_vpn_remove_secret (s_vpn, "foobar"));
|
|
|
|
|
ASSERT_UNCHANGED (nm_setting_vpn_remove_secret (s_vpn, "not added"));
|
|
|
|
|
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_wired_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
NMSettingWired *s_wired;
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
|
|
|
|
s_wired = (NMSettingWired *) nm_setting_wired_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_wired));
|
|
|
|
|
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wired_add_s390_option (s_wired, "portno", "1"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wired_remove_s390_option (s_wired, "portno"));
|
|
|
|
|
ASSERT_UNCHANGED (nm_setting_wired_remove_s390_option (s_wired, "layer2"));
|
|
|
|
|
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_wireless_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
NMSettingWireless *s_wifi;
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
|
|
|
|
s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_wifi));
|
|
|
|
|
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_add_seen_bssid (s_wifi, "00:11:22:33:44:55"));
|
|
|
|
|
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_wireless_security_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
|
|
|
|
s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_wsec));
|
|
|
|
|
|
|
|
|
|
/* Protos */
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_security_add_proto (s_wsec, "wpa"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 0));
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
nm_setting_wireless_security_add_proto (s_wsec, "wep");
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_security_clear_protos (s_wsec));
|
|
|
|
|
|
|
|
|
|
/* Pairwise ciphers */
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 0));
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
nm_setting_wireless_security_add_pairwise (s_wsec, "tkip");
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_security_clear_pairwise (s_wsec));
|
|
|
|
|
|
|
|
|
|
/* Group ciphers */
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_security_add_group (s_wsec, "ccmp"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_security_remove_group (s_wsec, 0));
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_wireless_security_remove_group (s_wsec, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
nm_setting_wireless_security_add_group (s_wsec, "tkip");
|
|
|
|
|
ASSERT_CHANGED (nm_setting_wireless_security_clear_groups (s_wsec));
|
|
|
|
|
|
|
|
|
|
/* WEP key secret flags */
|
|
|
|
|
ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key0", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
|
|
|
|
|
ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key1", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
|
|
|
|
|
ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key2", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
|
|
|
|
|
ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key3", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
|
|
|
|
|
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_802_1x_changed_signal (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *connection;
|
|
|
|
|
gboolean changed = FALSE;
|
|
|
|
|
NMSetting8021x *s_8021x;
|
|
|
|
|
|
2014-08-13 14:34:29 -04:00
|
|
|
connection = nm_simple_connection_new ();
|
2014-07-24 08:53:33 -04:00
|
|
|
g_signal_connect (connection,
|
|
|
|
|
NM_CONNECTION_CHANGED,
|
|
|
|
|
(GCallback) test_connection_changed_cb,
|
|
|
|
|
&changed);
|
|
|
|
|
|
|
|
|
|
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_8021x));
|
|
|
|
|
|
|
|
|
|
/* EAP methods */
|
|
|
|
|
ASSERT_CHANGED (nm_setting_802_1x_add_eap_method (s_8021x, "tls"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 0));
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
|
|
|
|
|
ASSERT_CHANGED (nm_setting_802_1x_clear_eap_methods (s_8021x));
|
|
|
|
|
|
|
|
|
|
/* alternate subject matches */
|
|
|
|
|
ASSERT_CHANGED (nm_setting_802_1x_add_altsubject_match (s_8021x, "EMAIL:server@example.com"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 0));
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
nm_setting_802_1x_add_altsubject_match (s_8021x, "EMAIL:server@example.com");
|
|
|
|
|
ASSERT_CHANGED (nm_setting_802_1x_clear_altsubject_matches (s_8021x));
|
|
|
|
|
|
|
|
|
|
/* phase2 alternate subject matches */
|
|
|
|
|
ASSERT_CHANGED (nm_setting_802_1x_add_phase2_altsubject_match (s_8021x, "EMAIL:server@example.com"));
|
|
|
|
|
ASSERT_CHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 0));
|
2018-01-02 11:21:20 +01:00
|
|
|
NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (elt != NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
ASSERT_UNCHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 1));
|
|
|
|
|
g_test_assert_expected_messages ();
|
|
|
|
|
|
|
|
|
|
nm_setting_802_1x_add_phase2_altsubject_match (s_8021x, "EMAIL:server@example.com");
|
|
|
|
|
ASSERT_CHANGED (nm_setting_802_1x_clear_phase2_altsubject_matches (s_8021x));
|
|
|
|
|
|
|
|
|
|
g_object_unref (connection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_old_uuid (void)
|
|
|
|
|
{
|
2015-02-09 15:17:53 +01:00
|
|
|
gs_unref_object NMSetting *setting = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
/* NetworkManager-0.9.4.0 generated 40-character UUIDs with no dashes,
|
|
|
|
|
* like this one. Test that we maintain compatibility. */
|
|
|
|
|
const char *uuid = "f43bec2cdd60e5da381ebb1eb1fa39f3cc52660c";
|
|
|
|
|
|
|
|
|
|
setting = nm_setting_connection_new ();
|
|
|
|
|
g_object_set (G_OBJECT (setting),
|
|
|
|
|
NM_SETTING_CONNECTION_ID, "uuidtest",
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, uuid,
|
|
|
|
|
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
2014-12-12 14:42:27 +01:00
|
|
|
nmtst_assert_setting_verifies (NM_SETTING (setting));
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-12-01 13:03:23 +01:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_normalize_uuid (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection ("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
|
|
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
|
|
|
|
|
|
|
|
|
g_object_set (nm_connection_get_setting_connection (con),
|
|
|
|
|
NM_SETTING_CONNECTION_UUID, NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-12-01 13:03:23 +01:00
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
/*
|
|
|
|
|
* Test normalization of interface-name
|
2014-08-16 10:09:48 -04:00
|
|
|
*/
|
2014-07-24 08:53:33 -04:00
|
|
|
static void
|
|
|
|
|
test_connection_normalize_virtual_iface_name (void)
|
|
|
|
|
{
|
2014-08-04 19:57:20 -04:00
|
|
|
NMConnection *con = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSettingVlan *s_vlan;
|
2014-08-16 10:09:48 -04:00
|
|
|
GVariant *connection_dict, *setting_dict, *var;
|
2014-08-04 19:57:20 -04:00
|
|
|
GError *error = NULL;
|
2014-07-24 08:53:33 -04:00
|
|
|
const char *IFACE_NAME = "iface";
|
|
|
|
|
const char *IFACE_VIRT = "iface-X";
|
|
|
|
|
|
2014-08-13 15:02:30 +02:00
|
|
|
con = nmtst_create_minimal_connection ("test1",
|
|
|
|
|
"22001632-bbb4-4616-b277-363dce3dfb5b",
|
|
|
|
|
NM_SETTING_VLAN_SETTING_NAME,
|
|
|
|
|
&s_con);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-13 15:02:30 +02:00
|
|
|
nm_connection_add_setting (con,
|
|
|
|
|
g_object_new (NM_TYPE_SETTING_IP4_CONFIG,
|
2014-10-19 17:30:10 -04:00
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
2014-08-13 15:02:30 +02:00
|
|
|
NULL));
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-13 15:02:30 +02:00
|
|
|
nm_connection_add_setting (con,
|
|
|
|
|
g_object_new (NM_TYPE_SETTING_IP6_CONFIG,
|
2014-10-19 17:30:10 -04:00
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
2014-08-13 15:02:30 +02:00
|
|
|
NULL));
|
|
|
|
|
|
|
|
|
|
s_vlan = nm_connection_get_setting_vlan (con);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_object_set (G_OBJECT (s_vlan),
|
|
|
|
|
NM_SETTING_VLAN_PARENT, "eth0",
|
|
|
|
|
NULL);
|
|
|
|
|
|
2014-08-13 15:02:30 +02:00
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, IFACE_NAME, NULL);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
|
|
|
|
g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_NAME);
|
2014-08-13 15:02:30 +02:00
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
connection_dict = nm_connection_to_dbus (con, NM_CONNECTION_SERIALIZE_ALL);
|
2014-08-04 19:57:20 -04:00
|
|
|
g_object_unref (con);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-04 19:57:20 -04:00
|
|
|
/* Serialized form should include vlan.interface-name as well. */
|
2014-08-16 10:09:48 -04:00
|
|
|
setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_VLAN_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_assert (setting_dict != NULL);
|
|
|
|
|
var = g_variant_lookup_value (setting_dict, "interface-name", NULL);
|
|
|
|
|
g_assert (var != NULL);
|
|
|
|
|
g_assert (g_variant_is_of_type (var, G_VARIANT_TYPE_STRING));
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (var, NULL), ==, IFACE_NAME);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (setting_dict);
|
|
|
|
|
g_variant_unref (var);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2020-02-17 17:40:17 +01:00
|
|
|
/* If vlan.interface-name will be ignored. */
|
2014-09-05 14:40:37 -04:00
|
|
|
NMTST_VARIANT_EDITOR (connection_dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_VLAN_SETTING_NAME,
|
|
|
|
|
"interface-name",
|
|
|
|
|
"s",
|
|
|
|
|
":::this-is-not-a-valid-interface-name:::");
|
|
|
|
|
);
|
2014-08-16 10:09:48 -04:00
|
|
|
|
2016-03-23 16:04:54 +01:00
|
|
|
con = _connection_new_from_dbus (connection_dict, &error);
|
2020-02-17 17:40:17 +01:00
|
|
|
nmtst_assert_success (con, error);
|
|
|
|
|
g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_NAME);
|
|
|
|
|
g_clear_object (&con);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2014-08-04 19:57:20 -04:00
|
|
|
/* If vlan.interface-name is valid, but doesn't match, it will be ignored. */
|
2014-09-05 14:40:37 -04:00
|
|
|
NMTST_VARIANT_EDITOR (connection_dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_VLAN_SETTING_NAME,
|
|
|
|
|
"interface-name",
|
|
|
|
|
"s",
|
|
|
|
|
IFACE_VIRT);
|
|
|
|
|
);
|
2014-07-24 08:53:33 -04:00
|
|
|
|
2016-03-23 16:04:54 +01:00
|
|
|
con = _connection_new_from_dbus (connection_dict, &error);
|
2014-08-04 19:57:20 -04:00
|
|
|
g_assert_no_error (error);
|
2014-08-13 15:02:30 +02:00
|
|
|
|
|
|
|
|
g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_NAME);
|
2014-08-04 19:57:20 -04:00
|
|
|
s_con = nm_connection_get_setting_connection (con);
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, IFACE_NAME);
|
|
|
|
|
g_object_unref (con);
|
|
|
|
|
|
|
|
|
|
/* But removing connection.interface-name should result in vlan.connection-name
|
|
|
|
|
* being "promoted".
|
|
|
|
|
*/
|
2014-09-05 14:40:37 -04:00
|
|
|
NMTST_VARIANT_EDITOR (connection_dict,
|
|
|
|
|
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME);
|
|
|
|
|
);
|
2014-08-04 19:57:20 -04:00
|
|
|
|
2016-03-23 16:04:54 +01:00
|
|
|
con = _connection_new_from_dbus (connection_dict, &error);
|
2014-08-04 19:57:20 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_VIRT);
|
|
|
|
|
s_con = nm_connection_get_setting_connection (con);
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, IFACE_VIRT);
|
|
|
|
|
g_object_unref (con);
|
|
|
|
|
|
2014-08-16 10:09:48 -04:00
|
|
|
g_variant_unref (connection_dict);
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|
|
|
|
|
|
2014-07-08 18:36:02 +02:00
|
|
|
static void
|
|
|
|
|
_test_connection_normalize_type_normalizable_setting (const char *type,
|
|
|
|
|
void (*prepare_normalizable_fcn) (NMConnection *con))
|
|
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSetting *s_base;
|
|
|
|
|
GType base_type;
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
gs_free char *id = g_strdup_printf ("%s[%s]", G_STRFUNC, type);
|
|
|
|
|
|
|
|
|
|
base_type = nm_setting_lookup_type (type);
|
|
|
|
|
g_assert (base_type != G_TYPE_INVALID);
|
2017-06-01 13:43:52 +02:00
|
|
|
g_assert (_nm_setting_type_get_base_type_priority (base_type) != NM_SETTING_PRIORITY_INVALID);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con);
|
|
|
|
|
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NULL);
|
|
|
|
|
|
|
|
|
|
if (prepare_normalizable_fcn)
|
|
|
|
|
prepare_normalizable_fcn (con);
|
|
|
|
|
|
|
|
|
|
g_assert (!nm_connection_get_setting_by_name (con, type));
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
|
2016-02-15 00:37:22 +01:00
|
|
|
nmtst_connection_normalize (con);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
s_base = nm_connection_get_setting_by_name (con, type);
|
|
|
|
|
g_assert (s_base);
|
|
|
|
|
g_assert (G_OBJECT_TYPE (s_base) == base_type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_test_connection_normalize_type_unnormalizable_setting (const char *type)
|
|
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
GType base_type;
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
gs_free char *id = g_strdup_printf ("%s[%s]", G_STRFUNC, type);
|
|
|
|
|
|
|
|
|
|
base_type = nm_setting_lookup_type (type);
|
|
|
|
|
g_assert (base_type != G_TYPE_INVALID);
|
2017-06-01 13:43:52 +02:00
|
|
|
g_assert (_nm_setting_type_get_base_type_priority (base_type) != NM_SETTING_PRIORITY_INVALID);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con);
|
|
|
|
|
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NULL);
|
|
|
|
|
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
|
2014-07-08 18:36:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_test_connection_normalize_type_normalizable_type (const char *type,
|
|
|
|
|
NMSetting *(*add_setting_fcn) (NMConnection *con))
|
|
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSetting *s_base;
|
|
|
|
|
GType base_type;
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
gs_free char *id = g_strdup_printf ("%s[%s]", G_STRFUNC, type);
|
|
|
|
|
|
|
|
|
|
base_type = nm_setting_lookup_type (type);
|
|
|
|
|
g_assert (base_type != G_TYPE_INVALID);
|
2017-06-01 13:43:52 +02:00
|
|
|
g_assert (_nm_setting_type_get_base_type_priority (base_type) != NM_SETTING_PRIORITY_INVALID);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con);
|
|
|
|
|
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
if (add_setting_fcn)
|
|
|
|
|
s_base = add_setting_fcn (con);
|
|
|
|
|
else {
|
|
|
|
|
s_base = NM_SETTING (g_object_new (base_type, NULL));
|
|
|
|
|
nm_connection_add_setting (con, s_base);
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-22 20:11:40 +02:00
|
|
|
g_assert (!nm_setting_connection_get_connection_type (s_con));
|
2014-07-08 18:36:02 +02:00
|
|
|
g_assert (nm_connection_get_setting_by_name (con, type) == s_base);
|
|
|
|
|
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
2016-02-15 00:37:22 +01:00
|
|
|
nmtst_connection_normalize (con);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
g_assert_cmpstr (nm_connection_get_connection_type (con), ==, type);
|
|
|
|
|
g_assert (nm_connection_get_setting_by_name (con, type) == s_base);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_adsl (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_ADSL,
|
|
|
|
|
NM_SETTING_ADSL_USERNAME, "test-user",
|
|
|
|
|
NM_SETTING_ADSL_PROTOCOL, NM_SETTING_ADSL_PROTOCOL_PPPOA,
|
|
|
|
|
NM_SETTING_ADSL_ENCAPSULATION, NM_SETTING_ADSL_ENCAPSULATION_VCMUX,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_bluetooth (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_BLUETOOTH,
|
2014-07-30 10:57:45 -04:00
|
|
|
NM_SETTING_BLUETOOTH_BDADDR, "11:22:33:44:55:66",
|
2014-07-08 18:36:02 +02:00
|
|
|
NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_bond (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_BOND, NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (con);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bond",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_bridge (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_BRIDGE, NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (con);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bridge",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_cdma (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_CDMA,
|
|
|
|
|
NM_SETTING_CDMA_NUMBER, "test-number",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_infiniband (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_INFINIBAND,
|
|
|
|
|
NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_olpc_mesh (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
const char *ssid_data = "ssid-test";
|
2014-06-26 10:42:11 -04:00
|
|
|
GBytes *ssid;
|
2014-07-08 18:36:02 +02:00
|
|
|
|
2014-06-26 10:42:11 -04:00
|
|
|
ssid = g_bytes_new (ssid_data, strlen (ssid_data));
|
2014-07-08 18:36:02 +02:00
|
|
|
setting = g_object_new (NM_TYPE_SETTING_OLPC_MESH,
|
|
|
|
|
NM_SETTING_OLPC_MESH_SSID, ssid,
|
|
|
|
|
NM_SETTING_OLPC_MESH_CHANNEL, 1,
|
|
|
|
|
NULL);
|
2014-06-26 10:42:11 -04:00
|
|
|
g_bytes_unref (ssid);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_team (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_TEAM, NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
|
|
|
|
|
s_con = nm_connection_get_setting_connection (con);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "test-team",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_vlan (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_VLAN,
|
|
|
|
|
NM_SETTING_VLAN_PARENT, "test-parent",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_vpn (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_VPN,
|
|
|
|
|
NM_SETTING_VPN_SERVICE_TYPE, "test-vpn-service-type",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_wimax (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
|
|
|
|
|
setting = g_object_new (NM_TYPE_SETTING_WIMAX,
|
|
|
|
|
NM_SETTING_WIMAX_NETWORK_NAME, "test-network",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NMSetting *
|
|
|
|
|
_add_setting_fcn_wireless (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
const char *ssid_data = "ssid-test";
|
2014-06-26 10:42:11 -04:00
|
|
|
GBytes *ssid;
|
2014-07-08 18:36:02 +02:00
|
|
|
|
2014-06-26 10:42:11 -04:00
|
|
|
ssid = g_bytes_new (ssid_data, strlen (ssid_data));
|
2014-07-08 18:36:02 +02:00
|
|
|
setting = g_object_new (NM_TYPE_SETTING_WIRELESS,
|
|
|
|
|
NM_SETTING_WIRELESS_SSID, ssid,
|
|
|
|
|
NULL);
|
2014-06-26 10:42:11 -04:00
|
|
|
g_bytes_unref (ssid);
|
2014-07-08 18:36:02 +02:00
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, setting);
|
|
|
|
|
return setting;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_prepare_normalizable_fcn_vlan (NMConnection *con)
|
|
|
|
|
{
|
|
|
|
|
nm_connection_add_setting (con, g_object_new (NM_TYPE_SETTING_WIRED,
|
2014-07-30 10:57:45 -04:00
|
|
|
NM_SETTING_WIRED_MAC_ADDRESS, "11:22:33:44:55:66",
|
2014-07-08 18:36:02 +02:00
|
|
|
NULL));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_normalize_type (void)
|
|
|
|
|
{
|
|
|
|
|
guint i;
|
|
|
|
|
struct {
|
|
|
|
|
const char *type;
|
|
|
|
|
gboolean normalizable;
|
|
|
|
|
NMSetting *(*add_setting_fcn) (NMConnection *con);
|
|
|
|
|
void (*prepare_normalizable_fcn) (NMConnection *con);
|
|
|
|
|
} types[] = {
|
|
|
|
|
{ NM_SETTING_GENERIC_SETTING_NAME, TRUE },
|
|
|
|
|
{ NM_SETTING_GSM_SETTING_NAME, TRUE },
|
|
|
|
|
{ NM_SETTING_WIRED_SETTING_NAME, TRUE },
|
|
|
|
|
{ NM_SETTING_VLAN_SETTING_NAME, TRUE, _add_setting_fcn_vlan, _prepare_normalizable_fcn_vlan },
|
|
|
|
|
|
|
|
|
|
{ NM_SETTING_ADSL_SETTING_NAME, FALSE, _add_setting_fcn_adsl },
|
|
|
|
|
{ NM_SETTING_BLUETOOTH_SETTING_NAME, FALSE, _add_setting_fcn_bluetooth },
|
|
|
|
|
{ NM_SETTING_BOND_SETTING_NAME, FALSE, _add_setting_fcn_bond },
|
|
|
|
|
{ NM_SETTING_BRIDGE_SETTING_NAME, FALSE, _add_setting_fcn_bridge },
|
|
|
|
|
{ NM_SETTING_CDMA_SETTING_NAME, FALSE, _add_setting_fcn_cdma },
|
|
|
|
|
{ NM_SETTING_INFINIBAND_SETTING_NAME, FALSE, _add_setting_fcn_infiniband },
|
|
|
|
|
{ NM_SETTING_OLPC_MESH_SETTING_NAME, FALSE, _add_setting_fcn_olpc_mesh },
|
|
|
|
|
{ NM_SETTING_TEAM_SETTING_NAME, FALSE, _add_setting_fcn_team },
|
|
|
|
|
{ NM_SETTING_VLAN_SETTING_NAME, FALSE, _add_setting_fcn_vlan },
|
|
|
|
|
{ NM_SETTING_VPN_SETTING_NAME, FALSE, _add_setting_fcn_vpn },
|
|
|
|
|
{ NM_SETTING_WIMAX_SETTING_NAME, FALSE, _add_setting_fcn_wimax },
|
|
|
|
|
{ NM_SETTING_WIRELESS_SETTING_NAME, FALSE, _add_setting_fcn_wireless },
|
|
|
|
|
{ 0 },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (i = 0; types[i].type; i++) {
|
|
|
|
|
const char *type = types[i].type;
|
|
|
|
|
|
|
|
|
|
if (types[i].normalizable)
|
|
|
|
|
_test_connection_normalize_type_normalizable_setting (type, types[i].prepare_normalizable_fcn);
|
|
|
|
|
else
|
|
|
|
|
_test_connection_normalize_type_unnormalizable_setting (type);
|
|
|
|
|
_test_connection_normalize_type_normalizable_type (type, types[i].add_setting_fcn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 17:05:10 +02:00
|
|
|
static void
|
|
|
|
|
test_connection_normalize_slave_type_1 (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_normalize_slave_type_1",
|
|
|
|
|
"cc4cd5df-45dc-483e-b291-6b76c2338ecb",
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME, &s_con);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, "invalid-type",
|
|
|
|
|
NULL);
|
|
|
|
|
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2014-07-07 17:05:10 +02:00
|
|
|
g_assert (!nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, "bridge",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_assert (!nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
|
2016-02-15 00:37:22 +01:00
|
|
|
nmtst_connection_normalize (con);
|
2014-07-07 17:05:10 +02:00
|
|
|
g_assert (nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_normalize_slave_type_2 (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_normalize_slave_type_2",
|
|
|
|
|
"40bea008-ca72-439a-946b-e65f827656f9",
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME, &s_con);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, "invalid-type",
|
|
|
|
|
NULL);
|
|
|
|
|
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2014-07-07 17:05:10 +02:00
|
|
|
g_assert (!nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (con, nm_setting_bridge_port_new ());
|
|
|
|
|
|
|
|
|
|
g_assert (nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NULL);
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
2016-02-15 00:37:22 +01:00
|
|
|
nmtst_connection_normalize (con);
|
2014-07-07 17:05:10 +02:00
|
|
|
g_assert (nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-13 02:35:26 +02:00
|
|
|
static void
|
|
|
|
|
test_connection_normalize_infiniband_mtu (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
NMSettingInfiniband *s_infini;
|
2019-04-05 09:49:38 +02:00
|
|
|
guint mtu_regular = nmtst_rand_select (2044, 2045, 65520);
|
2014-08-13 02:35:26 +02:00
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_normalize_infiniband_mtu", NULL,
|
|
|
|
|
NM_SETTING_INFINIBAND_SETTING_NAME, NULL);
|
|
|
|
|
|
|
|
|
|
s_infini = nm_connection_get_setting_infiniband (con);
|
|
|
|
|
g_object_set (s_infini,
|
|
|
|
|
NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_infini,
|
|
|
|
|
NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
|
2019-04-05 09:49:38 +02:00
|
|
|
NM_SETTING_INFINIBAND_MTU, (guint) mtu_regular,
|
2014-08-13 02:35:26 +02:00
|
|
|
NULL);
|
2016-02-15 00:37:22 +01:00
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
|
|
|
|
nmtst_connection_normalize (con);
|
2019-04-05 09:49:38 +02:00
|
|
|
g_assert_cmpint (mtu_regular, ==, nm_setting_infiniband_get_mtu (s_infini));
|
2014-08-13 02:35:26 +02:00
|
|
|
|
|
|
|
|
g_object_set (s_infini,
|
|
|
|
|
NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
|
2019-04-05 09:49:38 +02:00
|
|
|
NM_SETTING_INFINIBAND_MTU, (guint) 65521,
|
2014-08-13 02:35:26 +02:00
|
|
|
NULL);
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2016-02-15 00:37:22 +01:00
|
|
|
nmtst_connection_normalize (con);
|
2019-04-05 09:49:38 +02:00
|
|
|
g_assert_cmpint (65520, ==, nm_setting_infiniband_get_mtu (s_infini));
|
2014-08-13 02:35:26 +02:00
|
|
|
|
|
|
|
|
g_object_set (s_infini,
|
|
|
|
|
NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
|
2019-04-05 09:49:38 +02:00
|
|
|
NM_SETTING_INFINIBAND_MTU, (guint) mtu_regular,
|
2014-08-13 02:35:26 +02:00
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_without_normalization (con);
|
2019-04-05 09:49:38 +02:00
|
|
|
g_assert_cmpint (mtu_regular, ==, nm_setting_infiniband_get_mtu (s_infini));
|
2014-08-13 02:35:26 +02:00
|
|
|
|
|
|
|
|
g_object_set (s_infini,
|
|
|
|
|
NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
|
|
|
|
|
NM_SETTING_INFINIBAND_MTU, (guint) 65521,
|
|
|
|
|
NULL);
|
libnm-core: merge NMSetting*Error into NMConnectionError
Each setting type was defining its own error type, but most of them
had exactly the same three errors ("unknown", "missing property", and
"invalid property"), and none of the other values was of much use
programmatically anyway.
So, this commit merges NMSettingError, NMSettingAdslError, etc, all
into NMConnectionError. (The reason for merging into NMConnectionError
rather than NMSettingError is that we also already have
"NMSettingsError", for errors related to the settings service, so
"NMConnectionError" is a less-confusable name for settings/connection
errors than "NMSettingError".)
Also, make sure that all of the affected error messages are localized,
and (where appropriate) prefix them with the relevant property name.
Renamed error codes:
NM_SETTING_ERROR_PROPERTY_NOT_FOUND -> NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND
NM_SETTING_ERROR_PROPERTY_NOT_SECRET -> NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET
Remapped error codes:
NM_SETTING_*_ERROR_MISSING_PROPERTY -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_*_ERROR_INVALID_PROPERTY -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BLUETOOTH_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_INVALID_SETTING
NM_SETTING_BOND_ERROR_INVALID_OPTION -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_BOND_ERROR_MISSING_OPTION -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_CONNECTION_ERROR_TYPE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_CONNECTION_ERROR_SLAVE_SETTING_NOT_FOUND -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_IP4_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_VLAN_ERROR_INVALID_PARENT -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_MISSING_802_1X_SETTING -> NM_CONNECTION_ERROR_MISSING_SETTING
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_802_1X -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_LEAP_REQUIRES_USERNAME -> NM_CONNECTION_ERROR_MISSING_PROPERTY
NM_SETTING_WIRELESS_SECURITY_ERROR_SHARED_KEY_REQUIRES_WEP -> NM_CONNECTION_ERROR_INVALID_PROPERTY
NM_SETTING_WIRELESS_ERROR_CHANNEL_REQUIRES_BAND -> NM_CONNECTION_ERROR_MISSING_PROPERTY
Dropped error codes (were previously defined but unused):
NM_SETTING_CDMA_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_CONNECTION_ERROR_IP_CONFIG_NOT_ALLOWED
NM_SETTING_GSM_ERROR_MISSING_SERIAL_SETTING
NM_SETTING_PPP_ERROR_REQUIRE_MPPE_NOT_ALLOWED
NM_SETTING_PPPOE_ERROR_MISSING_PPP_SETTING
NM_SETTING_SERIAL_ERROR_MISSING_PPP_SETTING
NM_SETTING_WIRELESS_ERROR_MISSING_SECURITY_SETTING
2014-10-20 13:52:23 -04:00
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
2016-02-15 00:37:22 +01:00
|
|
|
nmtst_connection_normalize (con);
|
2014-08-13 02:35:26 +02:00
|
|
|
g_assert_cmpint (65520, ==, nm_setting_infiniband_get_mtu (s_infini));
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-22 13:45:08 +02:00
|
|
|
static void
|
|
|
|
|
test_connection_normalize_gateway_never_default (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
NMSettingIPConfig *s_ip4, *s_ip6;
|
|
|
|
|
NMIPAddress *addr;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection ("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
|
|
|
|
|
|
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
|
|
|
|
|
g_object_set (G_OBJECT (s_ip4),
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
addr = nm_ip_address_new (AF_INET, "1.1.1.1", 24, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
|
|
|
|
nm_ip_address_unref (addr);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ip4,
|
|
|
|
|
NM_SETTING_IP_CONFIG_GATEWAY, "1.1.1.254",
|
|
|
|
|
NM_SETTING_IP_CONFIG_NEVER_DEFAULT, FALSE,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
|
|
|
|
|
g_object_set (s_ip6,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, (NMSetting *) s_ip4);
|
|
|
|
|
nm_connection_add_setting (con, (NMSetting *) s_ip6);
|
2016-10-04 16:44:39 +02:00
|
|
|
nm_connection_add_setting (con, nm_setting_proxy_new ());
|
2016-04-22 13:45:08 +02:00
|
|
|
|
|
|
|
|
nmtst_assert_connection_verifies_without_normalization (con);
|
|
|
|
|
g_assert_cmpstr ("1.1.1.254", ==, nm_setting_ip_config_get_gateway (s_ip4));
|
|
|
|
|
|
|
|
|
|
/* Now set never-default to TRUE and check that the gateway is
|
|
|
|
|
* removed during normalization
|
|
|
|
|
* */
|
|
|
|
|
g_object_set (s_ip4,
|
|
|
|
|
NM_SETTING_IP_CONFIG_NEVER_DEFAULT, TRUE,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nmtst_assert_connection_verifies_after_normalization (con,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
g_assert_cmpstr (NULL, ==, nm_setting_ip_config_get_gateway (s_ip4));
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 17:05:42 +02:00
|
|
|
static void
|
|
|
|
|
test_connection_normalize_may_fail (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
NMSettingIPConfig *s_ip4, *s_ip6;
|
|
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection ("test2", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
|
|
|
|
|
|
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
|
|
|
|
|
g_object_set (G_OBJECT (s_ip4),
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
|
|
|
|
|
NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
|
|
|
|
|
g_object_set (s_ip6,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
|
|
|
|
NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, (NMSetting *) s_ip4);
|
|
|
|
|
nm_connection_add_setting (con, (NMSetting *) s_ip6);
|
|
|
|
|
|
2016-10-04 16:44:39 +02:00
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
2016-07-01 17:05:42 +02:00
|
|
|
|
|
|
|
|
/* Now set method=disabled/ignore and check that may-fail becomes TRUE
|
|
|
|
|
* after normalization
|
|
|
|
|
* */
|
|
|
|
|
g_object_set (s_ip4,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ip6,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nmtst_assert_connection_verifies (con);
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
g_assert_cmpint (nm_setting_ip_config_get_may_fail (s_ip4), ==, TRUE);
|
|
|
|
|
g_assert_cmpint (nm_setting_ip_config_get_may_fail (s_ip6), ==, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-12 18:51:00 +02:00
|
|
|
static void
|
|
|
|
|
test_connection_normalize_shared_addresses (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
NMSettingIPConfig *s_ip4, *s_ip6;
|
|
|
|
|
NMIPAddress *addr;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection ("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
|
|
|
|
|
|
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
|
|
|
|
|
g_object_set (G_OBJECT (s_ip4),
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_SHARED,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
addr = nm_ip_address_new (AF_INET, "1.1.1.1", 24, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
|
|
|
|
nm_ip_address_unref (addr);
|
|
|
|
|
|
|
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
|
|
|
|
|
g_object_set (s_ip6,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, (NMSetting *) s_ip4);
|
|
|
|
|
nm_connection_add_setting (con, (NMSetting *) s_ip6);
|
|
|
|
|
|
2016-10-04 16:44:39 +02:00
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
2016-09-12 18:51:00 +02:00
|
|
|
|
|
|
|
|
/* Now we add other addresses and check that they are
|
|
|
|
|
* removed during normalization
|
|
|
|
|
* */
|
|
|
|
|
addr = nm_ip_address_new (AF_INET, "2.2.2.2", 24, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
|
|
|
|
nm_ip_address_unref (addr);
|
|
|
|
|
|
|
|
|
|
addr = nm_ip_address_new (AF_INET, "3.3.3.3", 24, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
|
|
|
|
nm_ip_address_unref (addr);
|
|
|
|
|
|
|
|
|
|
nmtst_assert_connection_verifies_after_normalization (con,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
g_assert_cmpuint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 1);
|
|
|
|
|
addr = nm_setting_ip_config_get_address (s_ip4, 0);
|
|
|
|
|
g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.1.1.1");
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-27 14:30:18 +02:00
|
|
|
static void
|
|
|
|
|
test_connection_normalize_ovs_interface_type_system (gconstpointer test_data)
|
|
|
|
|
{
|
|
|
|
|
const guint TEST_CASE = GPOINTER_TO_UINT (test_data);
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSettingOvsInterface *s_ovs_if;
|
|
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_normalize_ovs_interface_type_system",
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME, &s_con);
|
|
|
|
|
|
|
|
|
|
switch (TEST_CASE) {
|
|
|
|
|
case 1:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
|
|
|
|
|
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME);
|
|
|
|
|
s_ovs_if = nm_connection_get_setting_ovs_interface (con);
|
|
|
|
|
g_assert (s_ovs_if);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "system");
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ());
|
|
|
|
|
nm_connection_add_setting (con, NM_SETTING (s_ovs_if));
|
|
|
|
|
|
|
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
|
|
|
|
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME);
|
|
|
|
|
g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con));
|
|
|
|
|
g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "system");
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ());
|
|
|
|
|
nm_connection_add_setting (con, NM_SETTING (s_ovs_if));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "system",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_without_normalization (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME);
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ());
|
|
|
|
|
nm_connection_add_setting (con, NM_SETTING (s_ovs_if));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "internal",
|
|
|
|
|
NULL);
|
|
|
|
|
/* the setting doesn't verify, because the interface-type must be "system". */
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ());
|
|
|
|
|
nm_connection_add_setting (con, NM_SETTING (s_ovs_if));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "system",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME);
|
|
|
|
|
g_assert (s_con == nm_connection_get_setting_connection (con));
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME);
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BRIDGE_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ());
|
|
|
|
|
nm_connection_add_setting (con, NM_SETTING (s_ovs_if));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "system",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_BRIDGE_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, nm_setting_bridge_port_new ());
|
|
|
|
|
|
|
|
|
|
s_ovs_if = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new ());
|
|
|
|
|
nm_connection_add_setting (con, NM_SETTING (s_ovs_if));
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "system",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_connection_normalize_ovs_interface_type_ovs_interface (gconstpointer test_data)
|
|
|
|
|
{
|
|
|
|
|
const guint TEST_CASE = GPOINTER_TO_UINT (test_data);
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSettingOvsInterface *s_ovs_if;
|
|
|
|
|
NMSettingOvsPatch *s_ovs_patch;
|
|
|
|
|
NMSettingIP4Config *s_ip4;
|
|
|
|
|
NMSettingIP6Config *s_ip6;
|
|
|
|
|
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_normalize_ovs_interface_type_ovs_interface",
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME, &s_con);
|
|
|
|
|
s_ovs_if = nm_connection_get_setting_ovs_interface (con);
|
|
|
|
|
g_assert (s_ovs_if);
|
|
|
|
|
|
|
|
|
|
switch (TEST_CASE) {
|
|
|
|
|
case 1:
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_PROXY_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME);
|
|
|
|
|
g_assert (s_con == nm_connection_get_setting_connection (con));
|
|
|
|
|
g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con));
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "internal");
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_PROXY_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME);
|
|
|
|
|
g_assert (s_con == nm_connection_get_setting_connection (con));
|
|
|
|
|
g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con));
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "internal");
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "internal",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_PROXY_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME);
|
|
|
|
|
g_assert (s_con == nm_connection_get_setting_connection (con));
|
|
|
|
|
g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con));
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "internal");
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "internal",
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (con, nm_setting_ip4_config_new ());
|
|
|
|
|
nm_connection_add_setting (con, nm_setting_ip6_config_new ());
|
|
|
|
|
nm_connection_add_setting (con, nm_setting_proxy_new ());
|
|
|
|
|
s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting_ip4_config (con));
|
|
|
|
|
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (con));
|
|
|
|
|
g_object_set (s_ip4,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, "auto",
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ip6,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, "auto",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_without_normalization (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_PROXY_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME);
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "internal",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_PROXY_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME);
|
|
|
|
|
g_assert (s_con == nm_connection_get_setting_connection (con));
|
|
|
|
|
g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con));
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "internal");
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "system",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "bogus",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
break;
|
|
|
|
|
case 9:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "patch",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "patch",
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (con, nm_setting_ovs_patch_new ());
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
|
|
|
|
break;
|
|
|
|
|
case 11:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "adsf",
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "patch",
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (con, nm_setting_ovs_patch_new ());
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
|
|
|
|
|
break;
|
|
|
|
|
case 12:
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER, "master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "adsf",
|
|
|
|
|
NULL);
|
|
|
|
|
g_object_set (s_ovs_if,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE, "patch",
|
|
|
|
|
NULL);
|
|
|
|
|
s_ovs_patch = NM_SETTING_OVS_PATCH (nm_setting_ovs_patch_new ());
|
|
|
|
|
nm_connection_add_setting (con, NM_SETTING (s_ovs_patch));
|
|
|
|
|
g_object_set (s_ovs_patch,
|
|
|
|
|
NM_SETTING_OVS_PATCH_PEER, "1.2.3.4",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_and_normalizable (con);
|
|
|
|
|
nmtst_connection_normalize (con);
|
|
|
|
|
nmtst_assert_connection_has_settings (con, NM_SETTING_CONNECTION_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_PROXY_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME,
|
|
|
|
|
NM_SETTING_OVS_PATCH_SETTING_NAME);
|
|
|
|
|
g_assert (s_con == nm_connection_get_setting_connection (con));
|
|
|
|
|
g_assert (s_ovs_if == nm_connection_get_setting_ovs_interface (con));
|
|
|
|
|
g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_OVS_PORT_SETTING_NAME);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ovs_interface_get_interface_type (s_ovs_if), ==, "patch");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-20 21:30:56 -04:00
|
|
|
static void
|
|
|
|
|
test_setting_ip4_gateway (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *conn;
|
|
|
|
|
NMSettingIPConfig *s_ip4;
|
|
|
|
|
NMIPAddress *addr;
|
|
|
|
|
GVariant *conn_dict, *ip4_dict, *value;
|
|
|
|
|
GVariantIter iter;
|
|
|
|
|
GVariant *addr_var;
|
2014-12-19 12:46:03 +01:00
|
|
|
guint32 addr_vals_0[] = { htonl (0xc0a8010a), 0x00000018, htonl (0x00000000) };
|
|
|
|
|
guint32 addr_vals_1[] = { htonl (0xc0a8010b), 0x00000018, htonl (0xc0a80101) };
|
2014-12-03 11:10:17 -05:00
|
|
|
GVariantBuilder addrs_builder;
|
2014-10-20 21:30:56 -04:00
|
|
|
GError *error = NULL;
|
|
|
|
|
|
2018-11-26 16:49:51 +01:00
|
|
|
nmtst_assert_ip4_address (addr_vals_0[0], "192.168.1.10");
|
2014-12-19 12:46:03 +01:00
|
|
|
|
2014-11-14 11:46:19 -05:00
|
|
|
/* When serializing on the daemon side, ipv4.gateway is copied to the first
|
|
|
|
|
* entry of ipv4.addresses
|
|
|
|
|
*/
|
2014-10-20 21:30:56 -04:00
|
|
|
conn = nmtst_create_minimal_connection ("test_setting_ip4_gateway", NULL,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
|
|
|
|
|
g_object_set (s_ip4,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
|
|
|
|
|
NM_SETTING_IP_CONFIG_GATEWAY, "192.168.1.1",
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (conn, NM_SETTING (s_ip4));
|
|
|
|
|
|
|
|
|
|
addr = nm_ip_address_new (AF_INET, "192.168.1.10", 24, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
nm_setting_ip_config_add_address (s_ip4, addr);
|
|
|
|
|
nm_ip_address_unref (addr);
|
|
|
|
|
|
2014-11-14 11:46:19 -05:00
|
|
|
_nm_utils_is_manager_process = TRUE;
|
2014-10-20 21:30:56 -04:00
|
|
|
conn_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
|
2014-11-14 11:46:19 -05:00
|
|
|
_nm_utils_is_manager_process = FALSE;
|
2014-10-20 21:30:56 -04:00
|
|
|
g_object_unref (conn);
|
|
|
|
|
|
|
|
|
|
ip4_dict = g_variant_lookup_value (conn_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_assert (ip4_dict != NULL);
|
|
|
|
|
|
|
|
|
|
value = g_variant_lookup_value (ip4_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING);
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "192.168.1.1");
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
|
|
|
|
|
value = g_variant_lookup_value (ip4_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE ("aau"));
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
|
|
|
|
|
g_variant_iter_init (&iter, value);
|
|
|
|
|
while (g_variant_iter_next (&iter, "@au", &addr_var)) {
|
|
|
|
|
const guint32 *addr_array;
|
|
|
|
|
gsize length;
|
|
|
|
|
|
|
|
|
|
addr_array = g_variant_get_fixed_array (addr_var, &length, sizeof (guint32));
|
|
|
|
|
g_assert_cmpint (length, ==, 3);
|
2018-11-26 16:49:51 +01:00
|
|
|
nmtst_assert_ip4_address (addr_array[2], "192.168.1.1");
|
2014-10-20 21:30:56 -04:00
|
|
|
g_variant_unref (addr_var);
|
|
|
|
|
}
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (ip4_dict);
|
|
|
|
|
|
2014-12-03 11:10:17 -05:00
|
|
|
/* When deserializing an old-style connection, the first non-0 gateway in
|
|
|
|
|
* ipv4.addresses is copied to :gateway.
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
*/
|
2014-10-20 21:30:56 -04:00
|
|
|
NMTST_VARIANT_EDITOR (conn_dict,
|
|
|
|
|
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP_CONFIG_GATEWAY);
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
"address-data");
|
2014-10-20 21:30:56 -04:00
|
|
|
);
|
|
|
|
|
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (conn_dict, &error);
|
2014-10-20 21:30:56 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1");
|
|
|
|
|
|
|
|
|
|
g_object_unref (conn);
|
2014-12-03 11:10:17 -05:00
|
|
|
|
|
|
|
|
/* Try again with the gateway in the second address. */
|
|
|
|
|
g_variant_builder_init (&addrs_builder, G_VARIANT_TYPE ("aau"));
|
|
|
|
|
g_variant_builder_add (&addrs_builder, "@au",
|
|
|
|
|
g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
|
|
|
|
|
addr_vals_0, 3, 4));
|
|
|
|
|
g_variant_builder_add (&addrs_builder, "@au",
|
|
|
|
|
g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
|
|
|
|
|
addr_vals_1, 3, 4));
|
|
|
|
|
|
|
|
|
|
NMTST_VARIANT_EDITOR (conn_dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
|
|
|
|
|
"addresses", "aau", &addrs_builder);
|
|
|
|
|
);
|
|
|
|
|
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (conn_dict, &error);
|
2014-12-03 11:10:17 -05:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_variant_unref (conn_dict);
|
|
|
|
|
|
|
|
|
|
s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1");
|
|
|
|
|
|
|
|
|
|
g_object_unref (conn);
|
2014-10-20 21:30:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_ip6_gateway (void)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *conn;
|
|
|
|
|
NMSettingIPConfig *s_ip6;
|
|
|
|
|
NMIPAddress *addr;
|
|
|
|
|
GVariant *conn_dict, *ip6_dict, *value;
|
|
|
|
|
GVariantIter iter;
|
|
|
|
|
GVariant *gateway_var;
|
2014-12-03 11:10:17 -05:00
|
|
|
GVariantBuilder addrs_builder;
|
|
|
|
|
guint8 addr_bytes_0[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a };
|
|
|
|
|
guint8 addr_bytes_1[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b };
|
|
|
|
|
guint8 gateway_bytes_1[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
|
2014-10-20 21:30:56 -04:00
|
|
|
GError *error = NULL;
|
|
|
|
|
|
2014-11-14 11:46:19 -05:00
|
|
|
/* When serializing on the daemon side, ipv6.gateway is copied to the first
|
|
|
|
|
* entry of ipv6.addresses
|
|
|
|
|
*/
|
2014-10-20 21:30:56 -04:00
|
|
|
conn = nmtst_create_minimal_connection ("test_setting_ip6_gateway", NULL,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
|
|
|
|
|
g_object_set (s_ip6,
|
|
|
|
|
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
|
|
|
|
|
NM_SETTING_IP_CONFIG_GATEWAY, "abcd::1",
|
|
|
|
|
NULL);
|
|
|
|
|
nm_connection_add_setting (conn, NM_SETTING (s_ip6));
|
|
|
|
|
|
|
|
|
|
addr = nm_ip_address_new (AF_INET6, "abcd::10", 64, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
nm_setting_ip_config_add_address (s_ip6, addr);
|
|
|
|
|
nm_ip_address_unref (addr);
|
|
|
|
|
|
2014-11-14 11:46:19 -05:00
|
|
|
_nm_utils_is_manager_process = TRUE;
|
2014-10-20 21:30:56 -04:00
|
|
|
conn_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
|
2014-11-14 11:46:19 -05:00
|
|
|
_nm_utils_is_manager_process = FALSE;
|
2014-10-20 21:30:56 -04:00
|
|
|
g_object_unref (conn);
|
|
|
|
|
|
|
|
|
|
ip6_dict = g_variant_lookup_value (conn_dict, NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
|
|
|
|
|
g_assert (ip6_dict != NULL);
|
|
|
|
|
|
|
|
|
|
value = g_variant_lookup_value (ip6_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING);
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "abcd::1");
|
2015-02-06 13:31:06 +01:00
|
|
|
g_variant_unref (value);
|
2014-10-20 21:30:56 -04:00
|
|
|
|
|
|
|
|
value = g_variant_lookup_value (ip6_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE ("a(ayuay)"));
|
|
|
|
|
g_assert (value != NULL);
|
|
|
|
|
|
|
|
|
|
g_variant_iter_init (&iter, value);
|
|
|
|
|
while (g_variant_iter_next (&iter, "(@ayu@ay)", NULL, NULL, &gateway_var)) {
|
|
|
|
|
const guint8 *gateway_bytes;
|
|
|
|
|
gsize length;
|
|
|
|
|
|
|
|
|
|
gateway_bytes = g_variant_get_fixed_array (gateway_var, &length, 1);
|
|
|
|
|
g_assert_cmpint (length, ==, 16);
|
2018-11-26 16:49:51 +01:00
|
|
|
nmtst_assert_ip6_address ((struct in6_addr *) gateway_bytes, "abcd::1");
|
2014-10-20 21:30:56 -04:00
|
|
|
g_variant_unref (gateway_var);
|
|
|
|
|
}
|
|
|
|
|
g_variant_unref (value);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (ip6_dict);
|
|
|
|
|
|
2014-12-03 11:10:17 -05:00
|
|
|
/* When deserializing an old-style connection, the first non-0 gateway in
|
|
|
|
|
* ipv6.addresses is copied to :gateway.
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
*/
|
2014-10-20 21:30:56 -04:00
|
|
|
NMTST_VARIANT_EDITOR (conn_dict,
|
|
|
|
|
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
NM_SETTING_IP_CONFIG_GATEWAY);
|
libnm-core, libnm, core: add AddressData and RouteData properties
Add AddressData and RouteData properties to NMSettingIPConfig and
NMIP[46]Config. These are like the existing "addresses" and "routes"
properties, but using strings and containing additional attributes,
like NMIPAddress and NMIPRoute.
This only affects the D-Bus representations; there are no API changes
to NMSettingIP{,4,6}Config or NMIP{4,6}Config as a result of this; the
additional information is just added to the existing 'addresses' and
'routes' properties.
NMSettingIP4Config and NMSettingIP6Config now always generate both
old-style data ('addresses', 'address-labels', 'routes') and new-style
data ('address-data', 'gateway', 'route-data') when serializing to
D-Bus, for backward compatibility. When deserializing, they will fill
in the 'addresses' and 'routes' properties from the new-style data if
it is present (ignoring the old-style data), or from the old-style
data if the new-style isn't present.
The daemon-side NMIP4Config and NMIP6Config always emit changes for
both 'Addresses'/'Routes' and 'AddressData'/'RouteData'. The
libnm-side classes initially listen for changes on both properties,
but start ignoring the 'Addresses' and 'Routes' properties once they
know the daemon is also providing 'AddressData' and 'RouteData'.
2014-10-21 08:33:18 -04:00
|
|
|
NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
"address-data");
|
2014-10-20 21:30:56 -04:00
|
|
|
);
|
|
|
|
|
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (conn_dict, &error);
|
2014-10-20 21:30:56 -04:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd::1");
|
|
|
|
|
|
|
|
|
|
g_object_unref (conn);
|
2014-12-03 11:10:17 -05:00
|
|
|
|
|
|
|
|
/* Try again with the gateway in the second address. */
|
|
|
|
|
g_variant_builder_init (&addrs_builder, G_VARIANT_TYPE ("a(ayuay)"));
|
|
|
|
|
g_variant_builder_add (&addrs_builder, "(@ayu@ay)",
|
|
|
|
|
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
|
|
|
|
addr_bytes_0, 16, 1),
|
|
|
|
|
64,
|
|
|
|
|
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
|
|
|
|
&in6addr_any, 16, 1));
|
|
|
|
|
g_variant_builder_add (&addrs_builder, "(@ayu@ay)",
|
|
|
|
|
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
|
|
|
|
addr_bytes_1, 16, 1),
|
|
|
|
|
64,
|
|
|
|
|
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
|
|
|
|
|
gateway_bytes_1, 16, 1));
|
|
|
|
|
|
|
|
|
|
NMTST_VARIANT_EDITOR (conn_dict,
|
|
|
|
|
NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
|
|
|
|
"addresses", "a(ayuay)", &addrs_builder);
|
|
|
|
|
);
|
|
|
|
|
|
2016-03-23 16:04:54 +01:00
|
|
|
conn = _connection_new_from_dbus (conn_dict, &error);
|
2014-12-03 11:10:17 -05:00
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_variant_unref (conn_dict);
|
|
|
|
|
|
|
|
|
|
s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn);
|
|
|
|
|
g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd::1");
|
|
|
|
|
|
|
|
|
|
g_object_unref (conn);
|
2014-10-20 21:30:56 -04:00
|
|
|
}
|
|
|
|
|
|
2014-11-06 17:51:09 -06:00
|
|
|
typedef struct {
|
|
|
|
|
const char *str;
|
|
|
|
|
const guint8 expected[20];
|
|
|
|
|
const guint expected_len;
|
|
|
|
|
} HexItem;
|
|
|
|
|
|
2015-05-20 17:53:25 +02:00
|
|
|
static void
|
|
|
|
|
test_setting_compare_default_strv (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMConnection *c1 = NULL, *c2 = NULL;
|
|
|
|
|
char **strv;
|
|
|
|
|
NMSettingIPConfig *s_ip2, *s_ip1;
|
|
|
|
|
gboolean compare;
|
|
|
|
|
GHashTable *out_settings = NULL;
|
|
|
|
|
|
|
|
|
|
c1 = nmtst_create_minimal_connection ("test_compare_default_strv", NULL,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME, NULL);
|
|
|
|
|
nmtst_assert_connection_verifies_and_normalizable (c1);
|
2016-02-15 00:37:22 +01:00
|
|
|
nmtst_connection_normalize (c1);
|
2015-05-20 17:53:25 +02:00
|
|
|
|
|
|
|
|
c2 = nm_simple_connection_new_clone (c1);
|
|
|
|
|
nmtst_assert_connection_verifies_without_normalization (c2);
|
|
|
|
|
|
|
|
|
|
nmtst_assert_connection_equals (c1, FALSE, c2, FALSE);
|
|
|
|
|
|
|
|
|
|
s_ip1 = nm_connection_get_setting_ip4_config (c1);
|
|
|
|
|
s_ip2 = nm_connection_get_setting_ip4_config (c2);
|
|
|
|
|
|
|
|
|
|
nm_setting_ip_config_clear_dns_options (s_ip2, FALSE);
|
|
|
|
|
g_object_get (G_OBJECT (s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL);
|
|
|
|
|
g_assert (!strv);
|
|
|
|
|
nmtst_assert_connection_equals (c1, FALSE, c2, FALSE);
|
|
|
|
|
|
|
|
|
|
nm_setting_ip_config_clear_dns_options (s_ip2, TRUE);
|
|
|
|
|
g_object_get (G_OBJECT (s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL);
|
|
|
|
|
g_assert (strv && !strv[0]);
|
|
|
|
|
g_strfreev (strv);
|
|
|
|
|
|
|
|
|
|
compare = nm_setting_diff ((NMSetting *) s_ip1, (NMSetting *) s_ip2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &out_settings);
|
|
|
|
|
g_assert (!compare);
|
|
|
|
|
g_assert (out_settings);
|
|
|
|
|
g_assert (g_hash_table_contains (out_settings, NM_SETTING_IP_CONFIG_DNS_OPTIONS));
|
|
|
|
|
g_hash_table_unref (out_settings);
|
|
|
|
|
out_settings = NULL;
|
|
|
|
|
|
|
|
|
|
compare = nm_connection_diff (c1, c2, NM_SETTING_COMPARE_FLAG_EXACT, &out_settings);
|
|
|
|
|
g_assert (!compare);
|
|
|
|
|
g_assert (out_settings);
|
|
|
|
|
g_hash_table_unref (out_settings);
|
|
|
|
|
out_settings = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-24 12:41:04 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_setting_user_data (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_object NMSettingUser *s_user = NULL;
|
|
|
|
|
|
|
|
|
|
s_user = NM_SETTING_USER (nm_setting_user_new ());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2018-12-29 13:01:28 +01:00
|
|
|
typedef union {
|
|
|
|
|
struct sockaddr sa;
|
|
|
|
|
struct sockaddr_in in;
|
|
|
|
|
struct sockaddr_in6 in6;
|
|
|
|
|
} SockAddrUnion;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_sock_addr_endpoint (const char *endpoint,
|
|
|
|
|
const char *host,
|
|
|
|
|
gint32 port)
|
|
|
|
|
{
|
|
|
|
|
nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL;
|
|
|
|
|
const char *s_endpoint;
|
|
|
|
|
const char *s_host;
|
|
|
|
|
gint32 s_port;
|
|
|
|
|
SockAddrUnion sockaddr = { };
|
|
|
|
|
|
|
|
|
|
g_assert (endpoint);
|
2019-04-18 09:45:35 +02:00
|
|
|
g_assert ((!host) == (port == -1));
|
2018-12-29 13:01:28 +01:00
|
|
|
g_assert (port >= -1 && port <= G_MAXUINT16);
|
|
|
|
|
|
|
|
|
|
ep = nm_sock_addr_endpoint_new (endpoint);
|
|
|
|
|
g_assert (ep);
|
|
|
|
|
|
|
|
|
|
s_endpoint = nm_sock_addr_endpoint_get_endpoint (ep);
|
|
|
|
|
s_host = nm_sock_addr_endpoint_get_host (ep);
|
|
|
|
|
s_port = nm_sock_addr_endpoint_get_port (ep);
|
|
|
|
|
g_assert_cmpstr (endpoint, ==, s_endpoint);
|
|
|
|
|
g_assert_cmpstr (host, ==, s_host);
|
|
|
|
|
g_assert_cmpint (port, ==, s_port);
|
|
|
|
|
|
|
|
|
|
g_assert (!nm_sock_addr_endpoint_get_fixed_sockaddr (ep, &sockaddr));
|
|
|
|
|
|
|
|
|
|
if (endpoint[0] != ' ') {
|
|
|
|
|
gs_free char *endpoint2 = NULL;
|
|
|
|
|
|
|
|
|
|
/* also test with a leading space */
|
|
|
|
|
endpoint2 = g_strdup_printf (" %s", endpoint);
|
|
|
|
|
_sock_addr_endpoint (endpoint2, host, port);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (endpoint[0] && endpoint[strlen (endpoint) - 1] != ' ') {
|
|
|
|
|
gs_free char *endpoint2 = NULL;
|
|
|
|
|
|
|
|
|
|
/* also test with a trailing space */
|
|
|
|
|
endpoint2 = g_strdup_printf ("%s ", endpoint);
|
|
|
|
|
_sock_addr_endpoint (endpoint2, host, port);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_sock_addr_endpoint_fixed (const char *endpoint,
|
|
|
|
|
const char *host,
|
|
|
|
|
guint16 port,
|
|
|
|
|
guint scope_id)
|
|
|
|
|
{
|
|
|
|
|
nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL;
|
|
|
|
|
const char *s_endpoint;
|
|
|
|
|
const char *s_host;
|
|
|
|
|
gint32 s_port;
|
|
|
|
|
int addr_family;
|
|
|
|
|
NMIPAddr addrbin;
|
|
|
|
|
SockAddrUnion sockaddr = { };
|
|
|
|
|
|
|
|
|
|
g_assert (endpoint);
|
|
|
|
|
g_assert (host);
|
|
|
|
|
g_assert (port > 0);
|
|
|
|
|
|
|
|
|
|
if (!nm_utils_parse_inaddr_bin (AF_UNSPEC, host, &addr_family, &addrbin))
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
|
|
|
|
|
ep = nm_sock_addr_endpoint_new (endpoint);
|
|
|
|
|
g_assert (ep);
|
|
|
|
|
|
|
|
|
|
s_endpoint = nm_sock_addr_endpoint_get_endpoint (ep);
|
|
|
|
|
s_host = nm_sock_addr_endpoint_get_host (ep);
|
|
|
|
|
s_port = nm_sock_addr_endpoint_get_port (ep);
|
|
|
|
|
g_assert_cmpstr (endpoint, ==, s_endpoint);
|
|
|
|
|
g_assert_cmpstr (NULL, !=, s_host);
|
|
|
|
|
g_assert_cmpint (port, ==, s_port);
|
|
|
|
|
|
|
|
|
|
if (!nm_sock_addr_endpoint_get_fixed_sockaddr (ep, &sockaddr))
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (sockaddr.sa.sa_family, ==, addr_family);
|
|
|
|
|
if (addr_family == AF_INET) {
|
|
|
|
|
const SockAddrUnion s = {
|
|
|
|
|
.in = {
|
|
|
|
|
.sin_family = AF_INET,
|
|
|
|
|
.sin_addr = addrbin.addr4_struct,
|
|
|
|
|
.sin_port = htons (port),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (sockaddr.in.sin_addr.s_addr, ==, addrbin.addr4);
|
|
|
|
|
g_assert_cmpint (sockaddr.in.sin_port, ==, htons (port));
|
|
|
|
|
g_assert (memcmp (&s, &sockaddr, sizeof (s.in)) == 0);
|
|
|
|
|
} else if (addr_family == AF_INET6) {
|
|
|
|
|
const SockAddrUnion s = {
|
|
|
|
|
.in6 = {
|
|
|
|
|
.sin6_family = AF_INET6,
|
|
|
|
|
.sin6_addr = addrbin.addr6,
|
|
|
|
|
.sin6_scope_id = scope_id,
|
|
|
|
|
.sin6_port = htons (port),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
g_assert (memcmp (&sockaddr.in6.sin6_addr, &addrbin, sizeof (addrbin.addr6)) == 0);
|
|
|
|
|
g_assert_cmpint (sockaddr.in6.sin6_port, ==, htons (port));
|
|
|
|
|
g_assert_cmpint (sockaddr.in6.sin6_scope_id, ==, scope_id);
|
|
|
|
|
g_assert_cmpint (sockaddr.in6.sin6_flowinfo, ==, 0);
|
|
|
|
|
g_assert (memcmp (&s, &sockaddr, sizeof (s.in6)) == 0);
|
|
|
|
|
} else
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_sock_addr_endpoint (void)
|
|
|
|
|
{
|
|
|
|
|
_sock_addr_endpoint ("", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint (":", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("a", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("a:", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint (":a", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("[]:a", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("[]a", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("[]:", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("[a]b", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("[a:b", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("[a[:b", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("a:6", "a", 6);
|
|
|
|
|
_sock_addr_endpoint ("a:6", "a", 6);
|
|
|
|
|
_sock_addr_endpoint ("[a]:6", "a", 6);
|
|
|
|
|
_sock_addr_endpoint ("[a]:6", "a", 6);
|
|
|
|
|
_sock_addr_endpoint ("[a]:655", "a", 655);
|
|
|
|
|
_sock_addr_endpoint ("[ab]:][6", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("[ab]:]:[6", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("[a[]:b", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("[192.169.6.x]:6", "192.169.6.x", 6);
|
|
|
|
|
_sock_addr_endpoint ("[192.169.6.x]:0", NULL, -1);
|
|
|
|
|
_sock_addr_endpoint ("192.169.6.7:0", NULL, -1);
|
|
|
|
|
|
|
|
|
|
_sock_addr_endpoint_fixed ("192.169.6.7:6", "192.169.6.7", 6, 0);
|
|
|
|
|
_sock_addr_endpoint_fixed ("[192.169.6.7]:6", "192.169.6.7", 6, 0);
|
|
|
|
|
_sock_addr_endpoint_fixed ("[a:b::]:6", "a:b::", 6, 0);
|
|
|
|
|
_sock_addr_endpoint_fixed ("[a:b::%7]:6", "a:b::", 6, 7);
|
|
|
|
|
_sock_addr_endpoint_fixed ("a:b::1%75:6", "a:b::1", 6, 75);
|
|
|
|
|
_sock_addr_endpoint_fixed ("a:b::1%0:64", "a:b::1", 64, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2014-11-06 17:51:09 -06:00
|
|
|
static void
|
|
|
|
|
test_hexstr2bin (void)
|
|
|
|
|
{
|
|
|
|
|
static const HexItem items[] = {
|
|
|
|
|
{ "aaBBCCddDD10496a", { 0xaa, 0xbb, 0xcc, 0xdd, 0xdd, 0x10, 0x49, 0x6a }, 8 },
|
|
|
|
|
{ "aa:bb:cc:dd:10:49:6a", { 0xaa, 0xbb, 0xcc, 0xdd, 0x10, 0x49, 0x6a }, 7 },
|
|
|
|
|
{ "0xccddeeff", { 0xcc, 0xdd, 0xee, 0xff }, 4 },
|
|
|
|
|
{ "1:2:66:77:80", { 0x01, 0x02, 0x66, 0x77, 0x80 }, 5 },
|
|
|
|
|
{ "e", { 0x0e }, 1 },
|
2016-11-27 14:47:07 +01:00
|
|
|
{ "ef", { 0xef }, 1 },
|
|
|
|
|
{ "efa" },
|
|
|
|
|
{ "efad", { 0xef, 0xad }, 2 },
|
|
|
|
|
{ "ef:a", { 0xef, 0x0a }, 2 },
|
2014-11-06 17:51:09 -06:00
|
|
|
{ "aabb1199:" },
|
|
|
|
|
{ ":aabb1199" },
|
|
|
|
|
{ "aabb$$dd" },
|
|
|
|
|
{ "aab:ccc:ddd" },
|
|
|
|
|
{ "aab::ccc:ddd" },
|
|
|
|
|
};
|
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (items); i++) {
|
2018-08-22 21:35:33 +02:00
|
|
|
gs_unref_bytes GBytes *b = NULL;
|
|
|
|
|
|
2014-11-06 17:51:09 -06:00
|
|
|
b = nm_utils_hexstr2bin (items[i].str);
|
2018-08-22 20:49:43 +02:00
|
|
|
if (items[i].expected_len)
|
2014-11-06 17:51:09 -06:00
|
|
|
g_assert (b);
|
2018-08-22 20:49:43 +02:00
|
|
|
else
|
|
|
|
|
g_assert (!b);
|
|
|
|
|
g_assert (nm_utils_gbytes_equal_mem (b, items[i].expected, items[i].expected_len));
|
2014-11-06 17:51:09 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-11-28 14:26:24 +01:00
|
|
|
|
2017-10-05 14:27:24 +02:00
|
|
|
static void
|
|
|
|
|
_do_strquote (const char *str, gsize buf_len, const char *expected)
|
|
|
|
|
{
|
2019-05-30 08:33:14 +02:00
|
|
|
char canary = (char) nmtst_get_rand_uint32 ();
|
2017-10-05 14:27:24 +02:00
|
|
|
gs_free char *buf_full = g_malloc (buf_len + 2);
|
|
|
|
|
char *buf = &buf_full[1];
|
|
|
|
|
const char *b;
|
|
|
|
|
|
|
|
|
|
buf[-1] = canary;
|
|
|
|
|
buf[buf_len] = canary;
|
|
|
|
|
|
|
|
|
|
if (buf_len == 0) {
|
|
|
|
|
b = nm_strquote (NULL, 0, str);
|
|
|
|
|
g_assert (b == NULL);
|
|
|
|
|
g_assert (expected == NULL);
|
|
|
|
|
b = nm_strquote (buf, 0, str);
|
|
|
|
|
g_assert (b == buf);
|
|
|
|
|
} else {
|
|
|
|
|
b = nm_strquote (buf, buf_len, str);
|
|
|
|
|
g_assert (b == buf);
|
|
|
|
|
g_assert (strlen (b) < buf_len);
|
|
|
|
|
g_assert_cmpstr (expected, ==, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert (buf[-1] == canary);
|
|
|
|
|
g_assert (buf[buf_len] == canary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_strquote (void)
|
|
|
|
|
{
|
|
|
|
|
_do_strquote (NULL, 0, NULL);
|
|
|
|
|
_do_strquote ("", 0, NULL);
|
|
|
|
|
_do_strquote ("a", 0, NULL);
|
|
|
|
|
_do_strquote ("ab", 0, NULL);
|
|
|
|
|
|
|
|
|
|
_do_strquote (NULL, 1, "");
|
|
|
|
|
_do_strquote (NULL, 2, "(");
|
|
|
|
|
_do_strquote (NULL, 3, "(n");
|
|
|
|
|
_do_strquote (NULL, 4, "(nu");
|
|
|
|
|
_do_strquote (NULL, 5, "(nul");
|
|
|
|
|
_do_strquote (NULL, 6, "(null");
|
|
|
|
|
_do_strquote (NULL, 7, "(null)");
|
|
|
|
|
_do_strquote (NULL, 8, "(null)");
|
|
|
|
|
_do_strquote (NULL, 100, "(null)");
|
|
|
|
|
|
|
|
|
|
_do_strquote ("", 1, "");
|
|
|
|
|
_do_strquote ("", 2, "^");
|
|
|
|
|
_do_strquote ("", 3, "\"\"");
|
|
|
|
|
_do_strquote ("", 4, "\"\"");
|
|
|
|
|
_do_strquote ("", 5, "\"\"");
|
|
|
|
|
_do_strquote ("", 100, "\"\"");
|
|
|
|
|
|
|
|
|
|
_do_strquote ("a", 1, "");
|
|
|
|
|
_do_strquote ("a", 2, "^");
|
|
|
|
|
_do_strquote ("a", 3, "\"^");
|
|
|
|
|
_do_strquote ("a", 4, "\"a\"");
|
|
|
|
|
_do_strquote ("a", 5, "\"a\"");
|
|
|
|
|
_do_strquote ("a", 6, "\"a\"");
|
|
|
|
|
_do_strquote ("a", 100, "\"a\"");
|
|
|
|
|
|
|
|
|
|
_do_strquote ("ab", 1, "");
|
|
|
|
|
_do_strquote ("ab", 2, "^");
|
|
|
|
|
_do_strquote ("ab", 3, "\"^");
|
|
|
|
|
_do_strquote ("ab", 4, "\"a^");
|
|
|
|
|
_do_strquote ("ab", 5, "\"ab\"");
|
|
|
|
|
_do_strquote ("ab", 6, "\"ab\"");
|
|
|
|
|
_do_strquote ("ab", 7, "\"ab\"");
|
|
|
|
|
_do_strquote ("ab", 100, "\"ab\"");
|
|
|
|
|
|
|
|
|
|
_do_strquote ("abc", 1, "");
|
|
|
|
|
_do_strquote ("abc", 2, "^");
|
|
|
|
|
_do_strquote ("abc", 3, "\"^");
|
|
|
|
|
_do_strquote ("abc", 4, "\"a^");
|
|
|
|
|
_do_strquote ("abc", 5, "\"ab^");
|
|
|
|
|
_do_strquote ("abc", 6, "\"abc\"");
|
|
|
|
|
_do_strquote ("abc", 7, "\"abc\"");
|
|
|
|
|
_do_strquote ("abc", 100, "\"abc\"");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2018-10-31 08:25:28 +01:00
|
|
|
#define UUID_NS_ZERO "00000000-0000-0000-0000-000000000000"
|
2014-11-28 12:11:49 +01:00
|
|
|
#define UUID_NS_DNS "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
|
2018-10-31 08:25:28 +01:00
|
|
|
#define UUID_NS_URL "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
|
|
|
|
|
#define UUID_NS_OID "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
|
|
|
|
|
#define UUID_NS_X500 "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
|
2014-11-28 12:11:49 +01:00
|
|
|
|
2018-10-31 10:38:01 +01:00
|
|
|
static const NMUuid *
|
|
|
|
|
_uuid (const char *str)
|
|
|
|
|
{
|
|
|
|
|
static NMUuid u;
|
|
|
|
|
|
|
|
|
|
g_assert (str);
|
|
|
|
|
g_assert (_nm_utils_uuid_parse (str, &u));
|
|
|
|
|
return &u;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-28 14:26:24 +01:00
|
|
|
static void
|
2014-11-27 18:40:18 +01:00
|
|
|
_test_uuid (int uuid_type, const char *expected_uuid, const char *str, gssize slen, gpointer type_args)
|
2014-11-28 14:26:24 +01:00
|
|
|
{
|
|
|
|
|
gs_free char *uuid_test = NULL;
|
|
|
|
|
|
2014-11-27 18:40:18 +01:00
|
|
|
uuid_test = nm_utils_uuid_generate_from_string (str, slen, uuid_type, type_args);
|
2014-11-28 14:26:24 +01:00
|
|
|
|
|
|
|
|
g_assert (uuid_test);
|
|
|
|
|
g_assert (nm_utils_is_uuid (uuid_test));
|
|
|
|
|
|
2018-10-31 08:25:28 +01:00
|
|
|
if (!nm_streq (uuid_test, expected_uuid)) {
|
|
|
|
|
g_error ("UUID test failed: type=%d; text=%s, len=%lld, ns=%s, uuid=%s, expected=%s",
|
|
|
|
|
uuid_type,
|
|
|
|
|
str,
|
|
|
|
|
(long long) slen,
|
2018-10-31 08:27:41 +01:00
|
|
|
NM_IN_SET (uuid_type, NM_UTILS_UUID_TYPE_VERSION3,
|
|
|
|
|
NM_UTILS_UUID_TYPE_VERSION5)
|
2018-10-31 08:25:28 +01:00
|
|
|
? (((const char *) type_args) ?: "(all-zero)")
|
|
|
|
|
: (type_args ? "(unknown)" : "(null)"),
|
|
|
|
|
uuid_test,
|
|
|
|
|
expected_uuid);
|
2014-11-28 14:26:24 +01:00
|
|
|
}
|
2014-11-27 18:40:18 +01:00
|
|
|
|
2014-12-04 16:49:47 +01:00
|
|
|
if (slen < 0) {
|
|
|
|
|
/* also test that passing slen==-1 yields the same result as passing strlen(str). */
|
2014-11-27 18:40:18 +01:00
|
|
|
_test_uuid (uuid_type, expected_uuid, str, strlen (str), type_args);
|
2014-12-04 16:49:47 +01:00
|
|
|
} else if (str && slen == 0) {
|
|
|
|
|
/* also test if we accept NULL for slen==0 */
|
|
|
|
|
_test_uuid (uuid_type, expected_uuid, NULL, 0, type_args);
|
|
|
|
|
}
|
2014-11-28 12:11:49 +01:00
|
|
|
|
2018-10-31 08:27:41 +01:00
|
|
|
if ( NM_IN_SET (uuid_type, NM_UTILS_UUID_TYPE_VERSION3,
|
|
|
|
|
NM_UTILS_UUID_TYPE_VERSION5)
|
2018-10-31 08:25:28 +01:00
|
|
|
&& !type_args) {
|
|
|
|
|
/* For version3 and version5, a missing @type_args is equal to UUID_NS_ZERO */
|
|
|
|
|
_test_uuid (uuid_type, expected_uuid, str, slen, UUID_NS_ZERO);
|
2014-12-04 16:49:47 +01:00
|
|
|
}
|
2014-11-28 14:26:24 +01:00
|
|
|
}
|
|
|
|
|
|
2018-10-31 08:25:28 +01:00
|
|
|
typedef struct {
|
|
|
|
|
const char *uuid3;
|
2018-10-31 08:27:41 +01:00
|
|
|
const char *uuid5;
|
2018-10-31 08:25:28 +01:00
|
|
|
} ExpectedUuids;
|
|
|
|
|
|
2014-11-28 14:26:24 +01:00
|
|
|
static void
|
|
|
|
|
test_nm_utils_uuid_generate_from_string (void)
|
|
|
|
|
{
|
2018-10-31 08:25:28 +01:00
|
|
|
const ExpectedUuids zero_uuids[] = {
|
2018-10-31 08:27:41 +01:00
|
|
|
{ .uuid3 = "19826852-5007-3022-a72a-212f66e9fac3", .uuid5 = "b6c54489-38a0-5f50-a60a-fd8d76219cae", },
|
|
|
|
|
{ .uuid3 = "9153af2e-fc8e-34f3-9e8b-81f73b33d0cb", .uuid5 = "11116e73-1c03-5de6-9130-5f9925ae8ab4", },
|
|
|
|
|
{ .uuid3 = "2f06a3ae-d78d-30d7-b898-088a0e0b76f6", .uuid5 = "1087ebe8-1ef8-5d97-8873-735b4949004d", },
|
|
|
|
|
{ .uuid3 = "aca948e0-1468-3a51-9f2e-c688a484efd7", .uuid5 = "7e57d004-2b97-5e7a-b45f-5387367791cd", },
|
|
|
|
|
{ .uuid3 = "b74e537a-53e8-3808-9abd-58546a6542bd", .uuid5 = "1dd80df1-492c-5dc5-aec2-6bf0e104f923", },
|
|
|
|
|
{ .uuid3 = "1b00958a-7d76-3d08-8aba-c66c5828658c", .uuid5 = "f797f61e-a392-5acf-af25-b46057f1c8e8", },
|
|
|
|
|
{ .uuid3 = "7ba18f7d-c9cf-3b48-a89e-ad79243135cc", .uuid5 = "e02c9780-2fc5-5d57-b92f-4cc3a64bff16", },
|
|
|
|
|
{ .uuid3 = "9baf0978-1a60-35c5-9e9b-bec8d259fd4e", .uuid5 = "94167980-f909-527e-a4af-bc3155f586d3", },
|
|
|
|
|
{ .uuid3 = "588668c0-7631-39c7-9976-c7d414adf7ba", .uuid5 = "9e3eefda-b56e-56bd-8a3a-0b8009d4a536", },
|
|
|
|
|
{ .uuid3 = "8edb3613-9612-3b32-9dd7-0a01aa8ed453", .uuid5 = "9b75648e-d38c-54e8-adee-1fb295a079c9", },
|
|
|
|
|
{ .uuid3 = "f3b34394-63a5-3773-9014-1f8a50d765b8", .uuid5 = "dd56b598-9e74-58c3-b3e8-2c623780b8ed", },
|
|
|
|
|
{ .uuid3 = "0572965f-05b8-342b-b225-d5c29d449eee", .uuid5 = "5666449a-fb7e-55b7-ae9f-0552e6513a10", },
|
|
|
|
|
{ .uuid3 = "6f7177c3-77b0-3f42-82a8-7031e25fcccf", .uuid5 = "10b38db9-82fc-528e-9ddb-1f09b7dbf907", },
|
|
|
|
|
{ .uuid3 = "d1e0f845-bc1b-368c-b8c8-49ab0b9e486b", .uuid5 = "85492596-9468-5845-9c7f-d4ae999cb751", },
|
|
|
|
|
{ .uuid3 = "46371ea3-c8a3-34d8-b2cf-2fa90bda4378", .uuid5 = "22b1c0dd-aa5d-54a4-8768-5adfd0d112bd", },
|
|
|
|
|
{ .uuid3 = "f1e6b499-9b68-343b-a5c5-ece7acc49a68", .uuid5 = "9cc429f8-200e-52a3-9e3b-ef134afa1e29", },
|
|
|
|
|
{ .uuid3 = "9ed06458-c712-31dd-aba5-6cf79879fabe", .uuid5 = "3949f95c-5d76-5ee2-af60-8e2d8fcf649d", },
|
|
|
|
|
{ .uuid3 = "4ddd5cd7-bc83-36aa-909c-4e660f57c830", .uuid5 = "0e994a02-069b-58fb-b3a4-d7dc94e90fca", },
|
|
|
|
|
{ .uuid3 = "335fa537-0909-395d-a696-6f41827dcbeb", .uuid5 = "17db3a41-de9b-5c6b-904d-833943209b3c", },
|
|
|
|
|
{ .uuid3 = "dbd58444-05ad-3edd-adc7-4393ecbcb43c", .uuid5 = "1bd906f2-05f9-5ab5-a39a-4c17a188f886", },
|
|
|
|
|
{ .uuid3 = "a1c62d82-d13c-361b-8f4e-ca91bc2f7fc5", .uuid5 = "ce6550fd-95b7-57e4-9aa7-461522666be4", },
|
|
|
|
|
{ .uuid3 = "e943d83e-3f82-307f-81ed-b7a7bcd0743e", .uuid5 = "04aa09ee-b420-57ac-8a23-5d99907fb0a1", },
|
|
|
|
|
{ .uuid3 = "cabf46dd-9f09-375c-8f6e-f2a8cf114709", .uuid5 = "8ece2c62-0c31-5c55-b7c6-155381e3780e", },
|
|
|
|
|
{ .uuid3 = "19beddf3-f2fb-340f-96ac-4f394960b7a7", .uuid5 = "5762a9f9-9a21-59ab-b0d2-2cb90027ef7f", },
|
|
|
|
|
{ .uuid3 = "08d835c2-f4ca-394c-ba7f-2494d8b60c6c", .uuid5 = "23c8409d-4b5f-5b6a-b946-41e49bad6c78", },
|
|
|
|
|
{ .uuid3 = "3b8c6847-5331-35bf-9cd9-ced50e53cd7c", .uuid5 = "e8e396be-95d5-5569-8edc-e0b64c2b7613", },
|
|
|
|
|
{ .uuid3 = "e601f160-484b-3254-8f3b-0a25c7203d8a", .uuid5 = "bc8b3cbc-ad5b-5808-a1b0-e0f7a1ad68a3", },
|
|
|
|
|
{ .uuid3 = "e5e492ed-5349-379d-b7de-a370a51e44a3", .uuid5 = "62c5ed3f-9afa-59ad-874f-a9dd8afc69d4", },
|
|
|
|
|
{ .uuid3 = "c40111f6-fe97-305e-bfce-7db730c3d2ec", .uuid5 = "66877a72-7243-59ed-b9e3-b5023b6da9c2", },
|
|
|
|
|
{ .uuid3 = "21e18ea8-95c2-362b-9ca9-25d6a0ff2dff", .uuid5 = "49a49eee-7e86-5d66-837a-8a8810cb5562", },
|
|
|
|
|
{ .uuid3 = "adab623b-1343-307f-80d8-58d005376ad9", .uuid5 = "e4a2a7ed-3bf3-53cf-a2bb-154dbb39a38c", },
|
|
|
|
|
{ .uuid3 = "67e9fc7c-dafe-356d-ac1a-a63ce3f44813", .uuid5 = "50cacfc9-f5d2-52dd-897c-a25a0927b816", },
|
|
|
|
|
{ .uuid3 = "36cc7f20-126c-3e40-94e7-737ac7486547", .uuid5 = "ca629991-3f2b-5e86-9bb7-37a335f7d809", },
|
|
|
|
|
{ .uuid3 = "fe282996-ac5e-3d13-b478-5def30007a8e", .uuid5 = "c1adf8a7-f72a-58ae-82d5-d18807f12e2e", },
|
|
|
|
|
{ .uuid3 = "3bfe339c-05ae-3233-a1a5-ebf1ead589db", .uuid5 = "6120c3cd-24e1-5ce4-987b-f8bfee2e4633", },
|
|
|
|
|
{ .uuid3 = "d1d90bc7-da4a-3cd7-a7c8-a1a89765d8ee", .uuid5 = "433d6a26-c319-5fcf-9a30-5ec6ad59d109", },
|
|
|
|
|
{ .uuid3 = "10b88a02-0102-359b-81e9-7e3b0ff7d25e", .uuid5 = "77d228d9-1b96-59e2-a07e-a8fdd4f62884", },
|
|
|
|
|
{ .uuid3 = "7da5e4f2-6df0-3aca-a1b0-b7f8b1340e1d", .uuid5 = "698259bf-a32b-5e00-9ec6-88b12278c4ad", },
|
|
|
|
|
{ .uuid3 = "cbe24d98-ca20-3058-86b6-24a6b36ceff0", .uuid5 = "60dbca63-704f-5666-9f64-f4e1a630c4aa", },
|
|
|
|
|
{ .uuid3 = "04d84e6a-b793-3993-afbf-bae7cfc42b49", .uuid5 = "79d63ec0-a39d-557d-8299-f4c97acfadc3", },
|
|
|
|
|
{ .uuid3 = "fdd157d8-a537-350a-9cc9-1930e8666c63", .uuid5 = "7df7f75e-a146-5a76-828b-bac052db312b", },
|
|
|
|
|
{ .uuid3 = "0bea36bb-24a7-3ee6-a98d-116433c14cd4", .uuid5 = "2bcca2e9-2879-53e3-b09d-cbbfd58771b2", },
|
|
|
|
|
{ .uuid3 = "52b040a4-1b84-32d2-b758-f82386f7e0f0", .uuid5 = "cb7bdca3-e9f7-50cd-b72e-73cb9ff24f62", },
|
|
|
|
|
{ .uuid3 = "0f0a4e26-e034-3021-acf2-4e886af43092", .uuid5 = "8e428e2b-5da3-5368-b760-5ca07ccbd819", },
|
|
|
|
|
{ .uuid3 = "819d3cd1-afe5-3e4a-9f0c-945e25d09879", .uuid5 = "f340ef4d-139c-567a-b0fc-7c495336674e", },
|
|
|
|
|
{ .uuid3 = "e7df1a3b-c9f8-3e5a-88d6-ba72b2a0f27b", .uuid5 = "7e3f5fd2-3c93-58d6-9f35-6e0192445b11", },
|
|
|
|
|
{ .uuid3 = "0854bedf-74ba-3f2b-b823-dc2c90d27c76", .uuid5 = "bc112b6b-c5de-5ee9-b816-808792743a20", },
|
|
|
|
|
{ .uuid3 = "a1b8c3ba-f821-32ef-a3fd-b97b3855efa8", .uuid5 = "47f8f82d-9fcd-553c-90c5-3f3cb3ad00ad", },
|
|
|
|
|
{ .uuid3 = "9458f819-079b-3033-9430-ba10f576c067", .uuid5 = "bee5c091-5f01-51fa-86bb-e9488fd3b4da", },
|
|
|
|
|
{ .uuid3 = "8e1f240a-e386-3e00-866a-6f9da1e3503f", .uuid5 = "8ea92cea-d741-566f-a44a-d51e65b4c5e4", },
|
2018-10-31 08:25:28 +01:00
|
|
|
};
|
|
|
|
|
const ExpectedUuids dns_uuids[] = {
|
2018-10-31 08:27:41 +01:00
|
|
|
{ .uuid3 = "4385125b-dd1e-3025-880f-3311517cc8d5", .uuid5 = "6af613b6-569c-5c22-9c37-2ed93f31d3af", },
|
|
|
|
|
{ .uuid3 = "afd0b036-625a-3aa8-b639-9dc8c8fff0ff", .uuid5 = "b04965e6-a9bb-591f-8f8a-1adcb2c8dc39", },
|
|
|
|
|
{ .uuid3 = "9c45c2f1-1761-3daa-ad31-1ff8703ae846", .uuid5 = "4b166dbe-d99d-5091-abdd-95b83330ed3a", },
|
|
|
|
|
{ .uuid3 = "15e0ba07-10e4-3d7f-aaff-c00fed873c88", .uuid5 = "98123fde-012f-5ff3-8b50-881449dac91a", },
|
|
|
|
|
{ .uuid3 = "bc27b4db-bc0f-34f9-ae8e-4b72f2d51b60", .uuid5 = "6ed955c6-506a-5343-9be4-2c0afae02eef", },
|
|
|
|
|
{ .uuid3 = "7586bfed-b8b8-3bb3-9c95-09a4a79dc0f7", .uuid5 = "c8691da2-158a-5ed6-8537-0e6f140801f2", },
|
|
|
|
|
{ .uuid3 = "881430b6-8d28-3175-b87d-e81f2f5978c6", .uuid5 = "a6c4fc8f-6950-51de-a9ae-2c519c465071", },
|
|
|
|
|
{ .uuid3 = "24075675-98ae-354e-89ca-0126a9ad36e3", .uuid5 = "a9f96b98-dd44-5216-ab0d-dbfc6b262edf", },
|
|
|
|
|
{ .uuid3 = "2c269ea4-dbfd-32dd-9bd7-a5c22677d18b", .uuid5 = "e99caacd-6c45-5906-bd9f-b79e62f25963", },
|
|
|
|
|
{ .uuid3 = "44eb0948-118f-3f28-87e4-f61c8f889aba", .uuid5 = "e4d80b30-151e-51b5-9f4f-18a3b82718e6", },
|
|
|
|
|
{ .uuid3 = "fc72beeb-f790-36ee-a73d-33888c9d8880", .uuid5 = "0159d6c7-973f-5e7a-a9a0-d195d0ea6fe2", },
|
|
|
|
|
{ .uuid3 = "1e46afa2-6176-3cd3-9750-3015846723df", .uuid5 = "7fef88f7-411d-5669-b42d-bf5fc7f9b58b", },
|
|
|
|
|
{ .uuid3 = "0042b01d-95bd-343f-bd9f-3186bfd63508", .uuid5 = "52524d6e-10dc-5261-aa36-8b2efcbaa5f0", },
|
|
|
|
|
{ .uuid3 = "115ff52f-d605-3b4b-98fe-c0ea57f4930c", .uuid5 = "91c274f2-9a0d-5ce6-ac3d-7529f452df21", },
|
|
|
|
|
{ .uuid3 = "ed0221e8-ac7d-393b-821d-25183567885b", .uuid5 = "0ff1e264-520d-543a-87dd-181a491e667e", },
|
|
|
|
|
{ .uuid3 = "508ef333-85a6-314c-bcf3-17ddc32b2216", .uuid5 = "23986425-d3a5-5e13-8bab-299745777a8d", },
|
|
|
|
|
{ .uuid3 = "a4715ee0-524a-37cc-beb2-a0b5030757b7", .uuid5 = "c15b38c9-9a3e-543c-a703-dd742f25b4d5", },
|
|
|
|
|
{ .uuid3 = "d1c72756-aaec-3470-a2f2-97415f44d72f", .uuid5 = "db680066-c83d-5ed7-89a4-1d79466ea62d", },
|
|
|
|
|
{ .uuid3 = "7aec2f01-586e-3d53-b8f3-6cf7e6b649a4", .uuid5 = "cadb7952-2bba-5609-88d4-8e47ec4e7920", },
|
|
|
|
|
{ .uuid3 = "3d234b88-8d6f-319a-91ea-edb6059fc825", .uuid5 = "35140057-a2a4-5adb-a500-46f8ed8b66a9", },
|
|
|
|
|
{ .uuid3 = "d2568554-93ec-30c7-9e15-f383be19e5bb", .uuid5 = "66e549b7-01e2-5d07-98d5-430f74d8d3b2", },
|
|
|
|
|
{ .uuid3 = "800e59a7-dd0f-3114-8e58-ab7e213895ca", .uuid5 = "292c8e99-2378-55aa-83d8-350e0ac3f1cc", },
|
|
|
|
|
{ .uuid3 = "3b7d03f0-e067-3d72-84f4-e410ac36ef57", .uuid5 = "0e3b230a-0509-55d8-96a0-9875f387a2be", },
|
|
|
|
|
{ .uuid3 = "8762be68-de95-391a-94a0-c5fd0446e037", .uuid5 = "4c507660-a83b-55c0-9b2b-83eccb07723d", },
|
|
|
|
|
{ .uuid3 = "2bd8b4c9-01af-3cd0-aced-94ee6e2004b8", .uuid5 = "a1b9b633-da11-58be-b1a9-5cfa2848f186", },
|
|
|
|
|
{ .uuid3 = "a627d6a4-394a-33f5-b68e-22bfb6488d01", .uuid5 = "c2708a8b-120a-56f5-a30d-990048af87cc", },
|
|
|
|
|
{ .uuid3 = "6a592510-17d9-3925-b321-4a8d4927f8d0", .uuid5 = "e7263999-68b6-5a23-b530-af25b7efd632", },
|
|
|
|
|
{ .uuid3 = "9ee72491-59c4-333c-bb93-fe733a842fdb", .uuid5 = "ce1ae2d5-3454-5952-97ff-36ff935bcfe9", },
|
|
|
|
|
{ .uuid3 = "2591c62c-0a9d-3c28-97bc-fa0401556a3c", .uuid5 = "33677b87-bc8d-5ff6-9a25-fe60225e4bf0", },
|
|
|
|
|
{ .uuid3 = "7912be1e-4562-373b-92e2-3d6d2123bc8e", .uuid5 = "ed2305ae-e8f9-5387-b860-3d80ae6c02f7", },
|
|
|
|
|
{ .uuid3 = "09370cda-89a4-3a48-b592-9c0486e0d5e4", .uuid5 = "604ed872-ae2d-5d91-8e3e-572f3a3aaaa5", },
|
|
|
|
|
{ .uuid3 = "de5980d3-a137-373c-850b-ca3e5f100779", .uuid5 = "8f8173d9-2f8d-5636-a693-24d9f79ba651", },
|
|
|
|
|
{ .uuid3 = "9441501d-f633-365a-8955-9df443edc762", .uuid5 = "36eb8d4d-b854-51f1-9fdf-3735964225d5", },
|
|
|
|
|
{ .uuid3 = "434ada18-13ce-3c08-8b40-a1a1ae030569", .uuid5 = "3493b6ca-f84b-56a9-97cc-c0bd1c46c4c0", },
|
|
|
|
|
{ .uuid3 = "a13b6160-bd23-3710-a150-41d800dd30b4", .uuid5 = "f413ea13-fcd9-5b44-9d22-1fa1f7b063a5", },
|
|
|
|
|
{ .uuid3 = "73a67c12-c5f0-3288-ad6a-c78aea0917b0", .uuid5 = "f468d924-d23b-56c2-b90f-3d1cf4b45337", },
|
|
|
|
|
{ .uuid3 = "a126ee4f-a222-357d-b71b-7d3f226c559f", .uuid5 = "8828c9d6-ed76-5c09-bf64-ba9e9cd90896", },
|
|
|
|
|
{ .uuid3 = "48f4f36b-b015-3137-9b6e-351bb175c7f7", .uuid5 = "facb7618-55ca-5c30-9cba-fd567b6c0611", },
|
|
|
|
|
{ .uuid3 = "3fe8f6a3-fe4a-3487-89d6-dd06c6ad02e3", .uuid5 = "96f3de0e-6412-5434-b406-67ef3352ab85", },
|
|
|
|
|
{ .uuid3 = "d68fa2d4-adc9-3b20-ac77-42585cd1d59f", .uuid5 = "9ebacb89-40ab-52b3-93a2-9054611d8f55", },
|
|
|
|
|
{ .uuid3 = "819f86a3-31d5-3e72-a83e-142c3a3e4832", .uuid5 = "681046ff-9129-5ade-b11c-769864e02184", },
|
|
|
|
|
{ .uuid3 = "9957b433-ddc8-3113-a3e6-5512cf13dab1", .uuid5 = "c13d0b5d-1ca3-57b6-a23f-8586bca44928", },
|
|
|
|
|
{ .uuid3 = "5aab6e0c-b7d3-379c-92e3-2bfbb5572511", .uuid5 = "7c411b5e-9d3f-50b5-9c28-62096e41c4ed", },
|
|
|
|
|
{ .uuid3 = "11c8ff30-3a7d-3547-80a7-d61b8abeeda8", .uuid5 = "f825aafe-6696-5121-b263-6b2c408b7f43", },
|
|
|
|
|
{ .uuid3 = "98799b9f-1c5e-30b3-930f-e412b862cbe4", .uuid5 = "f2b4caea-61c3-5bed-8ce7-d8b9d16e129e", },
|
|
|
|
|
{ .uuid3 = "9bdf2544-31d8-3555-94b0-6a749118a996", .uuid5 = "3593855a-6557-5736-8cab-172c6987f949", },
|
|
|
|
|
{ .uuid3 = "ddcfb9b3-e990-3985-9021-546a2711e7e5", .uuid5 = "36392431-d554-5385-b876-7bc6e1cb26b3", },
|
|
|
|
|
{ .uuid3 = "190d7a78-1484-3136-80a6-40f28852785c", .uuid5 = "7e645493-0898-5501-8155-e8578b4f5224", },
|
|
|
|
|
{ .uuid3 = "6ed693e4-7dc0-3210-856b-a6eb4cc73e13", .uuid5 = "14dc6a81-0491-5683-baaf-7582a61c5798", },
|
|
|
|
|
{ .uuid3 = "b6a14b21-e73a-3ce2-9076-a804c434f5c6", .uuid5 = "883e0a9c-e3b3-5f9c-8073-2913cbbb99ec", },
|
2018-10-31 08:25:28 +01:00
|
|
|
};
|
|
|
|
|
char i_str[30];
|
|
|
|
|
guint i;
|
|
|
|
|
|
2014-12-04 16:49:47 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "d41d8cd9-8f00-b204-e980-0998ecf8427e", "", -1, NULL);
|
2014-11-27 18:40:18 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "0cc175b9-c0f1-b6a8-31c3-99e269772661", "a", -1, NULL);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "098f6bcd-4621-d373-cade-4e832627b4f6", "test", -1, NULL);
|
2014-12-04 16:49:47 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "70350f60-27bc-e371-3f6b-76473084309b", "a\0b", 3, NULL);
|
2014-11-27 18:40:18 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "59c0547b-7fe2-1c15-2cce-e328e8bf6742", "/etc/NetworkManager/system-connections/em1", -1, NULL);
|
2014-11-28 14:26:24 +01:00
|
|
|
|
2018-10-31 07:32:23 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "4ae71336-e44b-39bf-b9d2-752e234818a5", "", -1, NULL);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "0531103a-d8fc-3dd4-b972-d98e4750994e", "a", -1, NULL);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "96e17d7a-ac89-38cf-95e1-bf5098da34e1", "test", -1, NULL);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "8156568e-4ae6-3f34-a93e-18e2c6cbbf78", "a\0b", 3, NULL);
|
2014-11-28 12:11:49 +01:00
|
|
|
|
2018-10-31 07:32:23 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "c87ee674-4ddc-3efe-a74e-dfe25da5d7b3", "", -1, UUID_NS_DNS);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "4c104dd0-4821-30d5-9ce3-0e7a1f8b7c0d", "a", -1, UUID_NS_DNS);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "45a113ac-c7f2-30b0-90a5-a399ab912716", "test", -1, UUID_NS_DNS);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "002a0ada-f547-375a-bab5-896a11d1927e", "a\0b", 3, UUID_NS_DNS);
|
2018-10-31 08:25:28 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "9a75f5f2-195e-31a9-9d07-8c18b5d3b285", "test123", -1, UUID_NS_DNS);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "ec794efe-a384-3b11-a0b6-ec8995bc6acc", "x", -1, UUID_NS_DNS);
|
|
|
|
|
|
2018-10-31 08:27:41 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, "a7650b9f-f19f-5300-8a13-91160ea8de2c", "a\0b", 3, NULL);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, "4f3f2898-69e3-5a0d-820a-c4e87987dbce", "a", -1, UUID_NS_DNS);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, "05b16a01-46c6-56dd-bd6e-c6dfb4a1427a", "x", -1, UUID_NS_DNS);
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, "c9ed566a-6b79-5d3a-b2b7-96a936b48cf3", "test123", -1, UUID_NS_DNS);
|
|
|
|
|
|
2018-10-31 08:25:28 +01:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (zero_uuids); i++) {
|
|
|
|
|
nm_sprintf_buf (i_str, "%u", i),
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, zero_uuids[i].uuid3, i_str, -1, NULL);
|
2018-10-31 08:27:41 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, zero_uuids[i].uuid5, i_str, -1, NULL);
|
2018-10-31 08:25:28 +01:00
|
|
|
}
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (dns_uuids); i++) {
|
|
|
|
|
nm_sprintf_buf (i_str, "%u", i),
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, dns_uuids[i].uuid3, i_str, -1, UUID_NS_DNS);
|
2018-10-31 08:27:41 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, dns_uuids[i].uuid5, i_str, -1, UUID_NS_DNS);
|
2018-10-31 08:25:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* examples from cpython unit tests: */
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "6fa459ea-ee8a-3ca4-894e-db77e160355e", "python.org", -1, UUID_NS_DNS);
|
2018-10-31 08:27:41 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, "886313e1-3b8a-5372-9b90-0c9aee199e5d", "python.org", -1, UUID_NS_DNS);
|
2018-10-31 08:25:28 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "9fe8e8c4-aaa8-32a9-a55c-4535a88b748d", "http://python.org/", -1, UUID_NS_URL);
|
2018-10-31 08:27:41 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, "4c565f0d-3f5a-5890-b41b-20cf47701c5e", "http://python.org/", -1, UUID_NS_URL);
|
2018-10-31 08:25:28 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "dd1a1cef-13d5-368a-ad82-eca71acd4cd1", "1.3.6.1", -1, UUID_NS_OID);
|
2018-10-31 08:27:41 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, "1447fa61-5277-5fef-a9b3-fbc6e44f4af3", "1.3.6.1", -1, UUID_NS_OID);
|
2018-10-31 08:25:28 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION3, "658d3002-db6b-3040-a1d1-8ddd7d189a4d", "c=ca", -1, UUID_NS_X500);
|
2018-10-31 08:27:41 +01:00
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, "cc957dd1-a972-5349-98cd-874190002798", "c=ca", -1, UUID_NS_X500);
|
|
|
|
|
|
|
|
|
|
_test_uuid (NM_UTILS_UUID_TYPE_VERSION5, "74738ff5-5367-5958-9aee-98fffdcd1876", "www.example.org", -1, UUID_NS_DNS);
|
2014-11-28 14:26:24 +01:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-02-22 20:15:52 +01:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
__test_uuid (const char *expected_uuid, const char *str, gssize slen, char *uuid_test)
|
|
|
|
|
{
|
|
|
|
|
g_assert (uuid_test);
|
|
|
|
|
g_assert (nm_utils_is_uuid (uuid_test));
|
|
|
|
|
|
|
|
|
|
if (strcmp (uuid_test, expected_uuid)) {
|
|
|
|
|
g_error ("UUID test failed (1): text=%s, len=%lld, expected=%s, uuid_test=%s",
|
|
|
|
|
str, (long long) slen, expected_uuid, uuid_test);
|
|
|
|
|
}
|
|
|
|
|
g_free (uuid_test);
|
|
|
|
|
|
2018-10-31 07:32:23 +01:00
|
|
|
uuid_test = nm_utils_uuid_generate_from_string (str, slen, NM_UTILS_UUID_TYPE_VERSION3, NM_UTILS_UUID_NS);
|
2015-02-22 20:15:52 +01:00
|
|
|
|
|
|
|
|
g_assert (uuid_test);
|
|
|
|
|
g_assert (nm_utils_is_uuid (uuid_test));
|
|
|
|
|
|
|
|
|
|
if (strcmp (uuid_test, expected_uuid)) {
|
|
|
|
|
g_error ("UUID test failed (2): text=%s; len=%lld, expected=%s, uuid2=%s",
|
|
|
|
|
str, (long long) slen, expected_uuid, uuid_test);
|
|
|
|
|
}
|
|
|
|
|
g_free (uuid_test);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define _test_uuid(expected_uuid, str, strlen, ...) __test_uuid (expected_uuid, str, strlen, _nm_utils_uuid_generate_from_strings(__VA_ARGS__, NULL))
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_uuid_generate_from_strings (void)
|
|
|
|
|
{
|
2019-02-08 13:34:37 +01:00
|
|
|
const NMUuid uuid0 = { };
|
2018-10-31 10:38:01 +01:00
|
|
|
|
|
|
|
|
g_assert_cmpmem (&uuid0, sizeof (uuid0), _uuid ("00000000-0000-0000-0000-000000000000"), 16);
|
|
|
|
|
|
|
|
|
|
g_assert (nm_utils_uuid_is_null (NULL));
|
|
|
|
|
g_assert (nm_utils_uuid_is_null (&uuid0));
|
|
|
|
|
g_assert ( nm_utils_uuid_is_null (_uuid ("00000000-0000-0000-0000-000000000000")));
|
|
|
|
|
g_assert (!nm_utils_uuid_is_null (_uuid ("10000000-0000-0000-0000-000000000000")));
|
|
|
|
|
|
2015-02-22 20:15:52 +01:00
|
|
|
_test_uuid ("b07c334a-399b-32de-8d50-58e4e08f98e3", "", 0, NULL);
|
|
|
|
|
_test_uuid ("b8a426cb-bcb5-30a3-bd8f-6786fea72df9", "\0", 1, "");
|
|
|
|
|
_test_uuid ("12a4a982-7aae-39e1-951e-41aeb1250959", "a\0", 2, "a");
|
|
|
|
|
_test_uuid ("69e22c7e-f89f-3a43-b239-1cb52ed8db69", "aa\0", 3, "aa");
|
|
|
|
|
_test_uuid ("59829fd3-5ad5-3d90-a7b0-4911747e4088", "\0\0", 2, "", "");
|
|
|
|
|
_test_uuid ("01ad0e06-6c50-3384-8d86-ddab81421425", "a\0\0", 3, "a", "");
|
|
|
|
|
_test_uuid ("e1ed8647-9ed3-3ec8-8c6d-e8204524d71d", "aa\0\0", 4, "aa", "");
|
|
|
|
|
_test_uuid ("fb1c7cd6-275c-3489-9382-83b900da8af0", "\0a\0", 3, "", "a");
|
|
|
|
|
_test_uuid ("5d79494e-c4ba-31a6-80a2-d6016ccd7e17", "a\0a\0", 4, "a", "a");
|
|
|
|
|
_test_uuid ("fd698d86-1b60-3ebe-855f-7aada9950a8d", "aa\0a\0", 5, "aa", "a");
|
|
|
|
|
_test_uuid ("8c573b48-0f01-30ba-bb94-c5f59f4fe517", "\0aa\0", 4, "", "aa");
|
|
|
|
|
_test_uuid ("2bdd3d46-eb83-3c53-a41b-a724d04b5544", "a\0aa\0", 5, "a", "aa");
|
|
|
|
|
_test_uuid ("13d4b780-07c1-3ba7-b449-81c4844ef039", "aa\0aa\0", 6, "aa", "aa");
|
|
|
|
|
_test_uuid ("dd265bf7-c05a-3037-9939-b9629858a477", "a\0b\0", 4, "a", "b");
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2014-11-28 14:26:24 +01:00
|
|
|
|
2015-02-22 11:54:03 +01:00
|
|
|
static void
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_check (const char *str, guint base, gint64 min,
|
|
|
|
|
gint64 max, gint64 fallback, int exp_errno,
|
|
|
|
|
gint64 exp_val)
|
|
|
|
|
{
|
|
|
|
|
gint64 v;
|
|
|
|
|
|
|
|
|
|
errno = 1;
|
|
|
|
|
v = _nm_utils_ascii_str_to_int64 (str, base, min, max, fallback);
|
|
|
|
|
g_assert_cmpint (errno, ==, exp_errno);
|
|
|
|
|
g_assert_cmpint (v, ==, exp_val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do (const char *str, guint base, gint64 min,
|
|
|
|
|
gint64 max, gint64 fallback, int exp_errno,
|
|
|
|
|
gint64 exp_val)
|
|
|
|
|
{
|
|
|
|
|
const char *sign = "";
|
|
|
|
|
const char *val;
|
|
|
|
|
static const char *whitespaces[] = {
|
|
|
|
|
"",
|
|
|
|
|
" ",
|
|
|
|
|
"\r\n\t",
|
|
|
|
|
" \r\n\t ",
|
|
|
|
|
" \r\n\t \t\r\n\t",
|
|
|
|
|
NULL,
|
|
|
|
|
};
|
|
|
|
|
static const char *nulls[] = {
|
|
|
|
|
"",
|
|
|
|
|
"0",
|
|
|
|
|
"00",
|
|
|
|
|
"0000",
|
|
|
|
|
"0000000000000000",
|
|
|
|
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
|
|
|
"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
|
|
|
|
NULL,
|
|
|
|
|
};
|
|
|
|
|
const char **ws_pre, **ws_post, **null;
|
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
|
|
if (str == NULL || exp_errno != 0) {
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_check (str, base, min, max, fallback, exp_errno, exp_val);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strncmp (str, "-", 1) == 0)
|
|
|
|
|
sign = "-";
|
|
|
|
|
|
|
|
|
|
val = str + strlen (sign);
|
|
|
|
|
|
|
|
|
|
for (ws_pre = whitespaces; *ws_pre; ws_pre++) {
|
|
|
|
|
for (ws_post = whitespaces; *ws_post; ws_post++) {
|
|
|
|
|
for (null = nulls; *null; null++) {
|
|
|
|
|
for (i = 0; ; i++) {
|
|
|
|
|
char *s;
|
|
|
|
|
const char *str_base = "";
|
|
|
|
|
|
|
|
|
|
if (base == 16) {
|
|
|
|
|
if (i == 1)
|
|
|
|
|
str_base = "0x";
|
|
|
|
|
else if (i > 1)
|
|
|
|
|
break;
|
|
|
|
|
} else if (base == 8) {
|
|
|
|
|
if (i == 1)
|
|
|
|
|
str_base = "0";
|
|
|
|
|
else if (i > 1)
|
|
|
|
|
break;
|
|
|
|
|
} else if (base == 0) {
|
|
|
|
|
if (i > 0)
|
|
|
|
|
break;
|
|
|
|
|
/* with base==0, a leading zero would be interpreted as octal. Only test without *null */
|
|
|
|
|
if ((*null)[0])
|
|
|
|
|
break;
|
|
|
|
|
} else {
|
|
|
|
|
if (i > 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = g_strdup_printf ("%s%s%s%s%s%s", *ws_pre, sign, str_base, *null, val, *ws_post);
|
|
|
|
|
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_check (s, base, min, max, fallback, exp_errno, exp_val);
|
|
|
|
|
g_free (s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_ascii_str_to_int64 (void)
|
|
|
|
|
{
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do (NULL, 10, 0, 10000, -1, EINVAL, -1);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("", 10, 0, 10000, -1, EINVAL, -1);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("1x", 10, 0, 10000, -1, EINVAL, -1);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("4711", 10, 0, 10000, -1, 0, 4711);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("10000", 10, 0, 10000, -1, 0, 10000);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("10001", 10, 0, 10000, -1, ERANGE, -1);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("FF", 16, 0, 10000, -1, 0, 255);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("FF", 10, 0, 10000, -2, EINVAL, -2);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("9223372036854775807", 10, 0, G_MAXINT64, -2, 0, G_MAXINT64);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("7FFFFFFFFFFFFFFF", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("9223372036854775808", 10, 0, G_MAXINT64, -2, ERANGE, -2);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64, 0, -2, 0, G_MININT64);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64+1, 0, -2, ERANGE, -2);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("-9223372036854775809", 10, G_MININT64, 0, -2, ERANGE, -2);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("1.0", 10, 1, 1, -1, EINVAL, -1);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("1x0", 16, -10, 10, -100, EINVAL, -100);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("0", 16, -10, 10, -100, 0, 0);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("10001111", 2, -1000, 1000, -100000, 0, 0x8F);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("-10001111", 2, -1000, 1000, -100000, 0, -0x8F);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("1111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7F);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFF);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("11111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFF);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, 0x4000000000000000);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("1000000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, ERANGE, -1);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0, -0x4000000000000000);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("0x70", 10, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("4711", 0, G_MININT64, G_MAXINT64, -1, 0, 4711);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("04711", 0, G_MININT64, G_MAXINT64, -1, 0, 04711);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("0x4711", 0, G_MININT64, G_MAXINT64, -1, 0, 0x4711);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("080", 0, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("070", 0, G_MININT64, G_MAXINT64, -1, 0, 7*8);
|
|
|
|
|
test_nm_utils_ascii_str_to_int64_do ("0x70", 0, G_MININT64, G_MAXINT64, -1, 0, 0x70);
|
2019-11-08 07:47:29 +01:00
|
|
|
|
|
|
|
|
g_assert_cmpint (21, ==, _nm_utils_ascii_str_to_int64 ("025", 0, 0, 1000, -1));
|
|
|
|
|
g_assert_cmpint (21, ==, _nm_utils_ascii_str_to_int64 ("0025", 0, 0, 1000, -1));
|
|
|
|
|
g_assert_cmpint (25, ==, _nm_utils_ascii_str_to_int64 ("025", 10, 0, 1000, -1));
|
|
|
|
|
g_assert_cmpint (25, ==, _nm_utils_ascii_str_to_int64 ("0025", 10, 0, 1000, -1));
|
2015-02-22 11:54:03 +01:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-02-22 11:54:03 +01:00
|
|
|
|
2015-05-22 18:52:22 +02:00
|
|
|
static void
|
2015-08-05 16:23:00 +02:00
|
|
|
test_nm_utils_strstrdictkey (void)
|
2015-05-22 18:52:22 +02:00
|
|
|
{
|
|
|
|
|
#define _VALUES_STATIC(_v1, _v2) { .v1 = _v1, .v2 = _v2, .v_static = _nm_utils_strstrdictkey_static (_v1, _v2), }
|
|
|
|
|
const struct {
|
|
|
|
|
const char *v1;
|
|
|
|
|
const char *v2;
|
|
|
|
|
NMUtilsStrStrDictKey *v_static;
|
|
|
|
|
} *val1, *val2, values[] = {
|
|
|
|
|
{ NULL, NULL },
|
|
|
|
|
{ "", NULL },
|
|
|
|
|
{ NULL, "" },
|
|
|
|
|
{ "a", NULL },
|
|
|
|
|
{ NULL, "a" },
|
|
|
|
|
_VALUES_STATIC ("", ""),
|
|
|
|
|
_VALUES_STATIC ("a", ""),
|
|
|
|
|
_VALUES_STATIC ("", "a"),
|
|
|
|
|
_VALUES_STATIC ("a", "b"),
|
|
|
|
|
};
|
|
|
|
|
guint i, j;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (values); i++) {
|
|
|
|
|
gs_free NMUtilsStrStrDictKey *key1 = NULL;
|
|
|
|
|
|
|
|
|
|
val1 = &values[i];
|
|
|
|
|
|
|
|
|
|
key1 = _nm_utils_strstrdictkey_create (val1->v1, val1->v2);
|
|
|
|
|
if (val1->v_static) {
|
|
|
|
|
g_assert (_nm_utils_strstrdictkey_equal (key1, val1->v_static));
|
|
|
|
|
g_assert (_nm_utils_strstrdictkey_equal (val1->v_static, key1));
|
|
|
|
|
g_assert_cmpint (_nm_utils_strstrdictkey_hash (key1), ==, _nm_utils_strstrdictkey_hash (val1->v_static));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < G_N_ELEMENTS (values); j++) {
|
|
|
|
|
gs_free NMUtilsStrStrDictKey *key2 = NULL;
|
|
|
|
|
|
|
|
|
|
val2 = &values[j];
|
|
|
|
|
key2 = _nm_utils_strstrdictkey_create (val2->v1, val2->v2);
|
|
|
|
|
if (i != j) {
|
|
|
|
|
g_assert (!_nm_utils_strstrdictkey_equal (key1, key2));
|
|
|
|
|
g_assert (!_nm_utils_strstrdictkey_equal (key2, key1));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-05-22 18:52:22 +02:00
|
|
|
|
2017-04-06 09:47:05 +02:00
|
|
|
static guint
|
|
|
|
|
_g_strv_length (gconstpointer arr)
|
|
|
|
|
{
|
|
|
|
|
return arr ? g_strv_length ((char **) arr) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_ptrarray_len (void)
|
|
|
|
|
{
|
|
|
|
|
#define _PTRARRAY_cmp(len, arr) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
g_assert_cmpint (len, ==, NM_PTRARRAY_LEN (arr)); \
|
|
|
|
|
g_assert_cmpint (len, ==, _g_strv_length (arr)); \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
#define _PTRARRAY_LEN0(T) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
T **vnull = NULL; \
|
|
|
|
|
T *const*vnull1 = NULL; \
|
|
|
|
|
T *const*const vnull2 = NULL; \
|
|
|
|
|
T *v0[] = { NULL }; \
|
|
|
|
|
T *const*v01 = v0; \
|
|
|
|
|
T *const*const v02 = v0; \
|
|
|
|
|
T **const v03 = v0; \
|
|
|
|
|
\
|
|
|
|
|
_PTRARRAY_cmp (0, vnull); \
|
|
|
|
|
_PTRARRAY_cmp (0, vnull1); \
|
|
|
|
|
_PTRARRAY_cmp (0, vnull2); \
|
|
|
|
|
_PTRARRAY_cmp (0, v0); \
|
|
|
|
|
_PTRARRAY_cmp (0, v01); \
|
|
|
|
|
_PTRARRAY_cmp (0, v02); \
|
|
|
|
|
_PTRARRAY_cmp (0, v03); \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
|
|
_PTRARRAY_LEN0 (char);
|
|
|
|
|
_PTRARRAY_LEN0 (const char);
|
|
|
|
|
_PTRARRAY_LEN0 (int);
|
|
|
|
|
_PTRARRAY_LEN0 (const int);
|
|
|
|
|
_PTRARRAY_LEN0 (void *);
|
|
|
|
|
_PTRARRAY_LEN0 (void);
|
|
|
|
|
_PTRARRAY_LEN0 (const void);
|
|
|
|
|
|
|
|
|
|
#define _PTRARRAY_LENn(T) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
T x[5] = { 0 }; \
|
|
|
|
|
\
|
|
|
|
|
T *v1[] = { &x[0], NULL }; \
|
|
|
|
|
T *const*v11 = v1; \
|
|
|
|
|
T *const*const v12 = v1; \
|
|
|
|
|
T **const v13 = v1; \
|
|
|
|
|
\
|
|
|
|
|
T *v2[] = { &x[0], &x[1], NULL }; \
|
|
|
|
|
T *const*v21 = v2; \
|
|
|
|
|
T *const*const v22 = v2; \
|
|
|
|
|
T **const v23 = v2; \
|
|
|
|
|
\
|
|
|
|
|
_PTRARRAY_cmp (1, v1); \
|
|
|
|
|
_PTRARRAY_cmp (1, v11); \
|
|
|
|
|
_PTRARRAY_cmp (1, v12); \
|
|
|
|
|
_PTRARRAY_cmp (1, v13); \
|
|
|
|
|
\
|
|
|
|
|
_PTRARRAY_cmp (2, v2); \
|
|
|
|
|
_PTRARRAY_cmp (2, v21); \
|
|
|
|
|
_PTRARRAY_cmp (2, v22); \
|
|
|
|
|
_PTRARRAY_cmp (2, v23); \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
|
|
_PTRARRAY_LENn (char);
|
|
|
|
|
_PTRARRAY_LENn (const char);
|
|
|
|
|
_PTRARRAY_LENn (int);
|
|
|
|
|
_PTRARRAY_LENn (const int);
|
|
|
|
|
_PTRARRAY_LENn (void *);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2015-04-01 11:47:42 +02:00
|
|
|
static void
|
2015-05-20 12:31:10 +02:00
|
|
|
test_nm_utils_dns_option_validate_do (char *option, gboolean ipv6, const NMUtilsDNSOptionDesc *descs,
|
2015-04-01 11:47:42 +02:00
|
|
|
gboolean exp_result, char *exp_name, gboolean exp_value)
|
|
|
|
|
{
|
|
|
|
|
char *name;
|
|
|
|
|
long value = 0;
|
|
|
|
|
gboolean result;
|
|
|
|
|
|
|
|
|
|
result = _nm_utils_dns_option_validate (option, &name, &value, ipv6, descs);
|
|
|
|
|
|
|
|
|
|
g_assert (result == exp_result);
|
|
|
|
|
g_assert_cmpstr (name, ==, exp_name);
|
|
|
|
|
g_assert (value == exp_value);
|
|
|
|
|
|
|
|
|
|
g_free (name);
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 12:31:10 +02:00
|
|
|
static const NMUtilsDNSOptionDesc opt_descs[] = {
|
2015-04-01 11:47:42 +02:00
|
|
|
/* name num ipv6 */
|
|
|
|
|
{ "opt1", FALSE, FALSE },
|
|
|
|
|
{ "opt2", TRUE, FALSE },
|
|
|
|
|
{ "opt3", FALSE, TRUE },
|
|
|
|
|
{ "opt4", TRUE, TRUE },
|
|
|
|
|
{ NULL, FALSE, FALSE }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_dns_option_validate (void)
|
|
|
|
|
{
|
|
|
|
|
/* opt ipv6 descs result name value */
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("", FALSE, NULL, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do (":", FALSE, NULL, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do (":1", FALSE, NULL, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do (":val", FALSE, NULL, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt", FALSE, NULL, TRUE, "opt", -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt:", FALSE, NULL, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt:12", FALSE, NULL, TRUE, "opt", 12);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt:12 ", FALSE, NULL, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt:val", FALSE, NULL, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt:2val", FALSE, NULL, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt:2:3", FALSE, NULL, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt-6", FALSE, NULL, TRUE, "opt-6", -1);
|
|
|
|
|
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt1", FALSE, opt_descs, TRUE, "opt1", -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt1", TRUE, opt_descs, TRUE, "opt1", -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt1:3", FALSE, opt_descs, FALSE, NULL, -1);
|
|
|
|
|
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt2", FALSE, opt_descs, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt2:5", FALSE, opt_descs, TRUE, "opt2", 5);
|
|
|
|
|
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt3", FALSE, opt_descs, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt3", TRUE, opt_descs, TRUE, "opt3", -1);
|
|
|
|
|
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt4", FALSE, opt_descs, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt4", TRUE, opt_descs, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt4:40", FALSE, opt_descs, FALSE, NULL, -1);
|
|
|
|
|
test_nm_utils_dns_option_validate_do ("opt4:40", TRUE, opt_descs, TRUE, "opt4", 40);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_dns_option_find_idx (void)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *options;
|
|
|
|
|
|
|
|
|
|
options = g_ptr_array_new ();
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (options, "debug");
|
|
|
|
|
g_ptr_array_add (options, "timeout:5");
|
|
|
|
|
g_ptr_array_add (options, "edns0");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "debug"), ==, 0);
|
|
|
|
|
g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "debug:1"), ==, 0);
|
|
|
|
|
g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "timeout"), ==, 1);
|
|
|
|
|
g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "timeout:5"), ==, 1);
|
|
|
|
|
g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "timeout:2"), ==, 1);
|
|
|
|
|
g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "edns0"), ==, 2);
|
|
|
|
|
g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "rotate"), ==, -1);
|
|
|
|
|
g_assert_cmpint (_nm_utils_dns_option_find_idx (options, ""), ==, -1);
|
|
|
|
|
|
|
|
|
|
g_ptr_array_free (options, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-04-01 11:47:42 +02:00
|
|
|
|
2016-03-11 13:17:24 +01:00
|
|
|
static void
|
|
|
|
|
_json_config_check_valid (const char *conf, gboolean expected)
|
|
|
|
|
{
|
2016-06-02 10:01:33 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2016-03-11 13:17:24 +01:00
|
|
|
gboolean res;
|
|
|
|
|
|
2016-09-23 10:30:50 +02:00
|
|
|
res = nm_utils_is_json_object (conf, &error);
|
2016-03-11 13:17:24 +01:00
|
|
|
g_assert_cmpint (res, ==, expected);
|
|
|
|
|
g_assert (res || error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_check_valid_json (void)
|
|
|
|
|
{
|
|
|
|
|
_json_config_check_valid (NULL, FALSE);
|
|
|
|
|
_json_config_check_valid ("", FALSE);
|
Revert "Makefile: rework team compilation flags"
I don't think we should do this.
- renamining/dropping configure options is still an annoyance,
because it requires to different ./configure options depending
on the version. The rename from --enable-teamctl to --enable-team
might be theoretically nice, but more annoying then helpful.
- There is no strict dependency between --enable-team and
--enable-json-validation. At most, one could argue that
when enabling the team plugin (--enable-teamctl), then
libnm must also be build with --enable-json-validation.
But in fact, the team plugin will happily work with a
libnm that doesn't link against libjansson.
That is --enable-teamctl --disable-json-validation will work
in practice just fine.
On the other hand, libnm is a client library to create connection
profiles, fully supporting team profiles also makes sense if the
actual plugin is not installed (or build). Thus, --disable-teamctl
--enable-json-validation certainly makes sense.
At this point, one might ask whether libnm is even still complete without
libjansson. Maybe libnm should *require* --enable-json-validation.
But that is not what the patch was doing, and it would also need
some careful consideration before doing so.
This reverts commit 9d5cd7eae8edc8c558d26f04ffd163effafe57f9.
2017-12-08 08:56:46 +01:00
|
|
|
#if WITH_JSON_VALIDATION
|
2016-03-11 13:17:24 +01:00
|
|
|
_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 */
|
|
|
|
|
_json_config_check_valid ("{ }", TRUE);
|
2017-01-17 23:44:03 +01:00
|
|
|
_json_config_check_valid ("{'%!-a1} ", TRUE);
|
|
|
|
|
_json_config_check_valid (" {'%!-a1}", TRUE);
|
|
|
|
|
_json_config_check_valid ("{'%!-a1", FALSE);
|
2016-03-11 13:17:24 +01:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_team_config_equal_check (const char *conf1,
|
|
|
|
|
const char *conf2,
|
|
|
|
|
gboolean port_config,
|
|
|
|
|
gboolean expected)
|
|
|
|
|
{
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
nm_auto_free_team_setting NMTeamSetting *team_a = NULL;
|
|
|
|
|
nm_auto_free_team_setting NMTeamSetting *team_b = NULL;
|
|
|
|
|
gboolean is_same;
|
|
|
|
|
|
|
|
|
|
if (nmtst_get_rand_bool ())
|
2020-03-23 08:04:33 +01:00
|
|
|
NM_SWAP (conf1, conf2);
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
|
2019-05-12 11:16:55 +02:00
|
|
|
if (!nm_streq0 (conf1, conf2)) {
|
|
|
|
|
_team_config_equal_check (conf1, conf1, port_config, TRUE);
|
|
|
|
|
_team_config_equal_check (conf2, conf2, port_config, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
team_a = nm_team_setting_new (port_config, conf1);
|
|
|
|
|
team_b = nm_team_setting_new (port_config, conf2);
|
|
|
|
|
|
|
|
|
|
is_same = (nm_team_setting_cmp (team_a, team_b, TRUE) == 0);
|
|
|
|
|
g_assert_cmpint (is_same, ==, expected);
|
|
|
|
|
|
|
|
|
|
if (nm_streq0 (conf1, conf2)) {
|
|
|
|
|
g_assert_cmpint (nm_team_setting_cmp (team_a, team_b, FALSE), ==, 0);
|
|
|
|
|
g_assert (expected);
|
|
|
|
|
} else
|
|
|
|
|
g_assert_cmpint (nm_team_setting_cmp (team_a, team_b, FALSE), !=, 0);
|
2016-03-11 13:17:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_team_config_equal (void)
|
|
|
|
|
{
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
_team_config_equal_check ("",
|
|
|
|
|
"",
|
|
|
|
|
TRUE,
|
|
|
|
|
TRUE);
|
|
|
|
|
_team_config_equal_check ("",
|
|
|
|
|
" ",
|
|
|
|
|
TRUE,
|
|
|
|
|
TRUE);
|
2016-03-11 13:17:24 +01:00
|
|
|
_team_config_equal_check ("{}",
|
|
|
|
|
"{ }",
|
|
|
|
|
TRUE,
|
|
|
|
|
TRUE);
|
|
|
|
|
_team_config_equal_check ("{}",
|
|
|
|
|
"{",
|
|
|
|
|
TRUE,
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
TRUE);
|
|
|
|
|
_team_config_equal_check ("{ \"a\": 1 }",
|
|
|
|
|
"{ \"a\": 1 }",
|
|
|
|
|
TRUE,
|
|
|
|
|
TRUE);
|
|
|
|
|
_team_config_equal_check ("{ \"a\": 1 }",
|
|
|
|
|
"{ \"a\": 1 }",
|
|
|
|
|
TRUE,
|
|
|
|
|
TRUE);
|
2016-03-11 13:17:24 +01:00
|
|
|
|
|
|
|
|
/* team config */
|
|
|
|
|
_team_config_equal_check ("{ }",
|
|
|
|
|
"{ \"runner\" : { \"name\" : \"random\"} }",
|
|
|
|
|
FALSE,
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
!WITH_JSON_VALIDATION);
|
2016-03-11 13:17:24 +01:00
|
|
|
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }",
|
|
|
|
|
"{ \"runner\" : { \"name\" : \"random\"} }",
|
|
|
|
|
FALSE,
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
!WITH_JSON_VALIDATION);
|
2016-03-11 13:17:24 +01:00
|
|
|
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"} }",
|
|
|
|
|
"{ \"runner\" : { \"name\" : \"random\"} }",
|
|
|
|
|
FALSE,
|
|
|
|
|
TRUE);
|
2017-10-09 20:55:38 +02:00
|
|
|
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"loadbalance\"} }",
|
|
|
|
|
"{ \"runner\" : { \"name\" : \"loadbalance\"} }",
|
|
|
|
|
FALSE,
|
|
|
|
|
TRUE);
|
2016-03-11 13:17:24 +01:00
|
|
|
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth0\" : {} } }",
|
|
|
|
|
"{ \"runner\" : { \"name\" : \"random\"}, \"ports\" : { \"eth1\" : {} } }",
|
|
|
|
|
FALSE,
|
|
|
|
|
TRUE);
|
2017-10-09 20:55:38 +02:00
|
|
|
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }",
|
|
|
|
|
"{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }",
|
|
|
|
|
FALSE,
|
libnm/team: fix handling default values and stricter validate team config
For each artifical team property we need to track whether it was
explicitly set (i.e., present in JSON/GVariant or set by the user
via NMSettingTeam/NMSettingTeamPort API).
--
As a plus, libnm is now no longer concerned with the underling default values
that teamd uses. For example, the effective default value for "notify_peers.count"
depends on the selected runner. But libnm does not need to care, it only cares
wheher the property is set in JSON or not. This also means that the default (e.g. as
interesting to `nmcli -o con show $PROFILE`) is independent from other properties
(like the runner).
Also change the default value for the GObject properties of
NMSettingTeam and NMSettingTeamPort to indicate the "unset" value.
For most properties, the default value is a special value that is
not a valid configuration itself.
For some properties the default value is itself a valid value, namely,
"runner.active", "runner.fast_rate", "port.sticky" and "port.prio".
As far as NMTeamSetting is concerned, it distinguishes between unset
value and set value (including the default value). That means,
when it parses a JSON or GVariant, it will remember whether the property
was present or not.
When using API of NMSettingTeam/NMSettingTeamPort to set a property to the
default value, it marks the property as unset. For example, setting
NM_SETTING_TEAM_RUNNER_ACTIVE to TRUE (the default), means that the
value will not be serialized to JSON/GVariant. For the above 4
properties (where the default value is itself a valid value) this is a
limitation of libnm API, as it does not allow to explicitly set
'"runner": { "active": true }'. See SET_FIELD_MODE_SET_UNLESS_DEFAULT,
Note that changing the default value for properties of NMSetting is problematic,
because it changes behavior for how settings are parsed from keyfile/GVariant.
For team settings that's not the case, because if a JSON "config" is
present, all other properties are ignore. Also, we serialize properties
to JSON/GVariant depending on whether it's marked as present, and not
whether the value is set to the default (_nm_team_settings_property_to_dbus()).
--
While at it, sticter validate the settings. Note that if a setting is
initialized from JSON, the strict validation is not not performed. That
means, such a setting will always validate, regardless whether the values
in JSON are invalid according to libnm. Only when using the extended
properties, strict validation is turned on.
Note that libnm serializes the properties to GVariant both as JSON "config"
and extended properties. Since when parsing a setting from GVariant will
prefer the "config" (if present), in most cases also validation is
performed.
Likewise, settings plugins (keyfile, ifcfg-rh) only persist the JSON
config to disk. When loading a setting from file, strict validation is
also not performed.
The stricter validation only happens if as last operation one of the
artificial properties was set, or if the setting was created from a
GVariant that has no "config" field.
--
This is a (another) change in behavior.
2019-05-31 10:48:47 +02:00
|
|
|
!WITH_JSON_VALIDATION);
|
2017-10-09 20:55:38 +02:00
|
|
|
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"roundrobin\"} }",
|
|
|
|
|
"{ \"runner\" : { \"name\" : \"roundrobin\", \"tx_hash\" : [ \"eth\", \"ipv4\", \"ipv6\" ] } }",
|
|
|
|
|
FALSE,
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
!WITH_JSON_VALIDATION);
|
2017-10-09 20:55:38 +02:00
|
|
|
_team_config_equal_check ("{ \"runner\" : { \"name\" : \"lacp\"} }",
|
|
|
|
|
"{ \"runner\" : { \"name\" : \"lacp\", \"tx_hash\" : [ \"eth\" ] } }",
|
|
|
|
|
FALSE,
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
!WITH_JSON_VALIDATION);
|
2016-03-11 13:17:24 +01:00
|
|
|
|
|
|
|
|
/* team port config */
|
|
|
|
|
_team_config_equal_check ("{ }",
|
|
|
|
|
"{ \"link_watch\" : { \"name\" : \"ethtool\"} }",
|
|
|
|
|
TRUE,
|
libnm/team: fix handling default values and stricter validate team config
For each artifical team property we need to track whether it was
explicitly set (i.e., present in JSON/GVariant or set by the user
via NMSettingTeam/NMSettingTeamPort API).
--
As a plus, libnm is now no longer concerned with the underling default values
that teamd uses. For example, the effective default value for "notify_peers.count"
depends on the selected runner. But libnm does not need to care, it only cares
wheher the property is set in JSON or not. This also means that the default (e.g. as
interesting to `nmcli -o con show $PROFILE`) is independent from other properties
(like the runner).
Also change the default value for the GObject properties of
NMSettingTeam and NMSettingTeamPort to indicate the "unset" value.
For most properties, the default value is a special value that is
not a valid configuration itself.
For some properties the default value is itself a valid value, namely,
"runner.active", "runner.fast_rate", "port.sticky" and "port.prio".
As far as NMTeamSetting is concerned, it distinguishes between unset
value and set value (including the default value). That means,
when it parses a JSON or GVariant, it will remember whether the property
was present or not.
When using API of NMSettingTeam/NMSettingTeamPort to set a property to the
default value, it marks the property as unset. For example, setting
NM_SETTING_TEAM_RUNNER_ACTIVE to TRUE (the default), means that the
value will not be serialized to JSON/GVariant. For the above 4
properties (where the default value is itself a valid value) this is a
limitation of libnm API, as it does not allow to explicitly set
'"runner": { "active": true }'. See SET_FIELD_MODE_SET_UNLESS_DEFAULT,
Note that changing the default value for properties of NMSetting is problematic,
because it changes behavior for how settings are parsed from keyfile/GVariant.
For team settings that's not the case, because if a JSON "config" is
present, all other properties are ignore. Also, we serialize properties
to JSON/GVariant depending on whether it's marked as present, and not
whether the value is set to the default (_nm_team_settings_property_to_dbus()).
--
While at it, sticter validate the settings. Note that if a setting is
initialized from JSON, the strict validation is not not performed. That
means, such a setting will always validate, regardless whether the values
in JSON are invalid according to libnm. Only when using the extended
properties, strict validation is turned on.
Note that libnm serializes the properties to GVariant both as JSON "config"
and extended properties. Since when parsing a setting from GVariant will
prefer the "config" (if present), in most cases also validation is
performed.
Likewise, settings plugins (keyfile, ifcfg-rh) only persist the JSON
config to disk. When loading a setting from file, strict validation is
also not performed.
The stricter validation only happens if as last operation one of the
artificial properties was set, or if the setting was created from a
GVariant that has no "config" field.
--
This is a (another) change in behavior.
2019-05-31 10:48:47 +02:00
|
|
|
!WITH_JSON_VALIDATION);
|
2016-03-11 13:17:24 +01:00
|
|
|
_team_config_equal_check ("{ }",
|
|
|
|
|
"{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
|
|
|
|
|
TRUE,
|
libnm: rework team handling of JSON config
Completely refactor the team/JSON handling in libnm's NMSettingTeam and
NMSettingTeamPort.
- team handling was added as rh#1398925. The goal is to have a more
convenient way to set properties than constructing JSON. This requires
libnm to implement the hard task of parsing JSON (and exposing well-understood
properties) and generating JSON (based on these "artificial" properties).
But not only libnm. In particular nmcli and the D-Bus API must make this
"simpler" API accessible.
- since NMSettingTeam and NMSettingTeamPort are conceptually the same,
add "libnm-core/nm-team-utils.h" and NMTeamSetting that tries to
handle the similar code side-by-sdie.
The setting classes now just delegate for everything to NMTeamSetting.
- Previously, there was a very fuzzy understanding of the provided
JSON config. Tighten that up, when setting a JSON config it
regenerates/parses all other properties and tries to make the
best of it. When modifying any abstraction property, the entire
JSON config gets regenerated. In particular, don't try to merge
existing JSON config with the new fields. If the user uses the
abstraction API, then the entire JSON gets replaced.
For example note that nm_setting_team_add_link_watcher() would not
be reflected in the JSON config (a bug). That only accidentally worked
because client would serializing the changed link watcher to
GVariant/D-Bus, then NetworkManager would set it via g_object_set(),
which would renerate the JSON, and finally persist it to disk. But
as far as libnm is concerned, nm_setting_team_add_link_watcher() would
bring the settings instance in an inconsistent state where JSON and
the link watcher property disagree. Setting any property must
immediately update both the JSON and the abstraction API.
- when constucting a team setting from D-Bus, we would previously parse
both "config" and abstraction properties. That is wrong. Since our
settings plugins only support JSON, all information must be present
in the JSON config anyway. So, when "config" is present, only the JSON
must be parsed. In the best case, the other information is redudant and
contributes nothing. In the worse case, they information differs
(which might happen if the client version differs from the server
version). As the settings plugin only supports JSON, it's wrong to
consider redundant, differing information from D-Bus.
- we now only convert string to JSON or back when needed. Previously,
setting a property resulted in parsing several JSON multiple times
(per property). All operations should now scale well and be reasonably
efficient.
- also the property-changed signals are now handled correctly. Since
NMTeamSetting knows the current state of all attributes, it can emit
the exact property changed signals for what changed.
- we no longer use libjansson to generate the JSON. JSON is supposed
to be a machine readable exchange format, hence a major goal is
to be easily handled by applications. While parsing JSON is not so
trivial, writing a well-known set of values to JSON is.
The advantage is that when you build libnm without libjansson support,
then we still can convert the artificial properties to JSON.
- Requiring libjansson in libnm is a burden, because most of the time
it is not needed (as most users don't create team configurations). With
this change we only require it to parse the team settings (no longer to
write them). It should be reasonably simple to use a more minimalistic
JSON parser that is sufficient for us, so that we can get rid of the
libjansson dependency (for libnm). This also avoids the pain that we have
due to the symbol collision of libjansson and libjson-glib.
https://bugzilla.redhat.com/show_bug.cgi?id=1691619
2019-05-06 12:36:41 +02:00
|
|
|
TRUE);
|
2016-03-11 13:17:24 +01:00
|
|
|
_team_config_equal_check ("{ \"link_watch\" : { \"name\" : \"ethtool\"} }",
|
|
|
|
|
"{ \"link_watch\" : { \"name\" : \"arp_ping\"} }",
|
|
|
|
|
TRUE,
|
libnm/team: fix handling default values and stricter validate team config
For each artifical team property we need to track whether it was
explicitly set (i.e., present in JSON/GVariant or set by the user
via NMSettingTeam/NMSettingTeamPort API).
--
As a plus, libnm is now no longer concerned with the underling default values
that teamd uses. For example, the effective default value for "notify_peers.count"
depends on the selected runner. But libnm does not need to care, it only cares
wheher the property is set in JSON or not. This also means that the default (e.g. as
interesting to `nmcli -o con show $PROFILE`) is independent from other properties
(like the runner).
Also change the default value for the GObject properties of
NMSettingTeam and NMSettingTeamPort to indicate the "unset" value.
For most properties, the default value is a special value that is
not a valid configuration itself.
For some properties the default value is itself a valid value, namely,
"runner.active", "runner.fast_rate", "port.sticky" and "port.prio".
As far as NMTeamSetting is concerned, it distinguishes between unset
value and set value (including the default value). That means,
when it parses a JSON or GVariant, it will remember whether the property
was present or not.
When using API of NMSettingTeam/NMSettingTeamPort to set a property to the
default value, it marks the property as unset. For example, setting
NM_SETTING_TEAM_RUNNER_ACTIVE to TRUE (the default), means that the
value will not be serialized to JSON/GVariant. For the above 4
properties (where the default value is itself a valid value) this is a
limitation of libnm API, as it does not allow to explicitly set
'"runner": { "active": true }'. See SET_FIELD_MODE_SET_UNLESS_DEFAULT,
Note that changing the default value for properties of NMSetting is problematic,
because it changes behavior for how settings are parsed from keyfile/GVariant.
For team settings that's not the case, because if a JSON "config" is
present, all other properties are ignore. Also, we serialize properties
to JSON/GVariant depending on whether it's marked as present, and not
whether the value is set to the default (_nm_team_settings_property_to_dbus()).
--
While at it, sticter validate the settings. Note that if a setting is
initialized from JSON, the strict validation is not not performed. That
means, such a setting will always validate, regardless whether the values
in JSON are invalid according to libnm. Only when using the extended
properties, strict validation is turned on.
Note that libnm serializes the properties to GVariant both as JSON "config"
and extended properties. Since when parsing a setting from GVariant will
prefer the "config" (if present), in most cases also validation is
performed.
Likewise, settings plugins (keyfile, ifcfg-rh) only persist the JSON
config to disk. When loading a setting from file, strict validation is
also not performed.
The stricter validation only happens if as last operation one of the
artificial properties was set, or if the setting was created from a
GVariant that has no "config" field.
--
This is a (another) change in behavior.
2019-05-31 10:48:47 +02:00
|
|
|
!WITH_JSON_VALIDATION);
|
2016-03-11 13:17:24 +01:00
|
|
|
_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);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2016-03-11 13:17:24 +01:00
|
|
|
|
2015-05-12 09:24:05 +02:00
|
|
|
enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED {
|
|
|
|
|
_DUMMY_1 = -1,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED {
|
|
|
|
|
_DUMMY_2,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64 {
|
|
|
|
|
_DUMMY_3 = (1LL << 40),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64 {
|
|
|
|
|
_DUMMY_4a = -1,
|
|
|
|
|
_DUMMY_4b = (1LL << 40),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define test_nm_utils_is_power_of_two_do(type, x, expect) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
typeof (x) x1 = (x); \
|
|
|
|
|
type x2 = (type) x1; \
|
|
|
|
|
\
|
2017-05-22 13:28:35 +02:00
|
|
|
g_assert_cmpint (expect, ==, nm_utils_is_power_of_two (x1)); \
|
|
|
|
|
if ( ((typeof (x1)) x2) == x1 \
|
|
|
|
|
&& ((typeof (x2)) x1) == x2 \
|
|
|
|
|
&& x2 > 0) { \
|
2015-05-12 09:24:05 +02:00
|
|
|
/* x2 equals @x, and is positive. Compare to @expect */ \
|
|
|
|
|
g_assert_cmpint (expect, ==, nm_utils_is_power_of_two (x2)); \
|
2017-05-22 13:28:35 +02:00
|
|
|
} else if (!(x2 > 0)) { \
|
|
|
|
|
/* a non positive value is always FALSE. */ \
|
|
|
|
|
g_assert_cmpint (FALSE, ==, nm_utils_is_power_of_two (x2)); \
|
|
|
|
|
} \
|
|
|
|
|
if (x2) { \
|
|
|
|
|
x2 = -x2; \
|
|
|
|
|
if (!(x2 > 0)) { \
|
|
|
|
|
/* for negative values, we return FALSE. */ \
|
|
|
|
|
g_assert_cmpint (FALSE, ==, nm_utils_is_power_of_two (x2)); \
|
|
|
|
|
} \
|
2015-05-12 09:24:05 +02:00
|
|
|
} \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
|
|
static void
|
2015-06-19 13:06:37 +02:00
|
|
|
test_nm_utils_is_power_of_two (void)
|
2015-05-12 09:24:05 +02:00
|
|
|
{
|
|
|
|
|
guint64 xyes, xno;
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
int i, j;
|
2015-05-12 09:24:05 +02:00
|
|
|
GRand *rand = nmtst_get_rand ();
|
|
|
|
|
int numbits;
|
|
|
|
|
|
|
|
|
|
for (i = -1; i < 64; i++) {
|
|
|
|
|
|
|
|
|
|
/* find a (positive) x which is a power of two. */
|
|
|
|
|
if (i == -1)
|
|
|
|
|
xyes = 0;
|
|
|
|
|
else {
|
2017-04-17 13:19:36 +02:00
|
|
|
xyes = (((guint64) 1) << i);
|
2015-05-12 09:24:05 +02:00
|
|
|
g_assert (xyes != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xno = xyes;
|
|
|
|
|
if (xyes != 0) {
|
|
|
|
|
again:
|
|
|
|
|
/* Find another @xno, that is not a power of two. Do that,
|
|
|
|
|
* by randomly setting bits. */
|
|
|
|
|
numbits = g_rand_int_range (rand, 1, 65);
|
|
|
|
|
while (xno != ~((guint64) 0) && numbits > 0) {
|
2017-04-17 13:19:36 +02:00
|
|
|
guint64 v = (((guint64) 1) << g_rand_int_range (rand, 0, 64));
|
2015-05-12 09:24:05 +02:00
|
|
|
|
|
|
|
|
if ((xno | v) != xno) {
|
|
|
|
|
xno |= v;
|
|
|
|
|
--numbits;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (xno == xyes)
|
|
|
|
|
goto again;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < 2; j++) {
|
|
|
|
|
gboolean expect = j == 0;
|
|
|
|
|
guint64 x = expect ? xyes : xno;
|
|
|
|
|
|
2017-05-22 13:28:35 +02:00
|
|
|
if (expect && xyes == 0)
|
2015-05-12 09:24:05 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* check if @x is as @expect, when casted to a certain data type. */
|
|
|
|
|
test_nm_utils_is_power_of_two_do (gint8, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (guint8, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (gint16, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (guint16, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (gint32, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (guint32, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (gint64, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (guint64, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (char, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (unsigned char, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (signed char, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64, x, expect);
|
|
|
|
|
test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64, x, expect);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-05-12 09:24:05 +02:00
|
|
|
|
2015-06-23 15:05:25 +02:00
|
|
|
static int
|
|
|
|
|
_test_find_binary_search_cmp (gconstpointer a, gconstpointer b, gpointer dummy)
|
|
|
|
|
{
|
|
|
|
|
int ia, ib;
|
|
|
|
|
|
|
|
|
|
ia = GPOINTER_TO_INT (a);
|
|
|
|
|
ib = GPOINTER_TO_INT (b);
|
|
|
|
|
|
|
|
|
|
if (ia == ib)
|
|
|
|
|
return 0;
|
|
|
|
|
if (ia < ib)
|
|
|
|
|
return -1;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_test_find_binary_search_do (const int *array, gsize len)
|
|
|
|
|
{
|
|
|
|
|
gsize i;
|
2017-12-07 15:20:42 +01:00
|
|
|
gssize idx, idx_first, idx_last;
|
2016-09-23 15:03:41 +02:00
|
|
|
gs_free gconstpointer *parray = g_new (gconstpointer, len);
|
|
|
|
|
const int NEEDLE = 0;
|
|
|
|
|
gconstpointer pneedle = GINT_TO_POINTER (NEEDLE);
|
2015-06-23 15:05:25 +02:00
|
|
|
gssize expected_result;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
parray[i] = GINT_TO_POINTER (array[i]);
|
|
|
|
|
|
|
|
|
|
expected_result = _nm_utils_ptrarray_find_first (parray, len, pneedle);
|
|
|
|
|
|
2018-08-01 11:03:02 +02:00
|
|
|
idx = nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL, &idx_first, &idx_last);
|
2017-12-07 15:20:42 +01:00
|
|
|
if (expected_result >= 0) {
|
2015-06-23 15:05:25 +02:00
|
|
|
g_assert_cmpint (expected_result, ==, idx);
|
2017-12-07 15:20:42 +01:00
|
|
|
} else {
|
2015-06-23 15:05:25 +02:00
|
|
|
gssize idx2 = ~idx;
|
|
|
|
|
g_assert_cmpint (idx, <, 0);
|
|
|
|
|
|
|
|
|
|
g_assert (idx2 >= 0);
|
|
|
|
|
g_assert (idx2 <= len);
|
|
|
|
|
g_assert (idx2 - 1 < 0 || _test_find_binary_search_cmp (parray[idx2 - 1], pneedle, NULL) < 0);
|
|
|
|
|
g_assert (idx2 >= len || _test_find_binary_search_cmp (parray[idx2], pneedle, NULL) > 0);
|
|
|
|
|
}
|
2017-12-07 15:20:42 +01:00
|
|
|
g_assert_cmpint (idx, ==, idx_first);
|
|
|
|
|
g_assert_cmpint (idx, ==, idx_last);
|
2015-06-23 15:05:25 +02:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
int cmp;
|
|
|
|
|
|
|
|
|
|
cmp = _test_find_binary_search_cmp (parray[i], pneedle, NULL);
|
|
|
|
|
if (cmp == 0) {
|
|
|
|
|
g_assert (pneedle == parray[i]);
|
|
|
|
|
g_assert (idx >= 0);
|
|
|
|
|
g_assert (i == idx);
|
|
|
|
|
} else {
|
|
|
|
|
g_assert (pneedle != parray[i]);
|
|
|
|
|
if (cmp < 0) {
|
|
|
|
|
if (idx < 0)
|
|
|
|
|
g_assert (i < ~idx);
|
|
|
|
|
else
|
|
|
|
|
g_assert (i < idx);
|
|
|
|
|
} else {
|
|
|
|
|
if (idx < 0)
|
|
|
|
|
g_assert (i >= ~idx);
|
|
|
|
|
else
|
|
|
|
|
g_assert (i >= idx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-09-23 13:37:22 +02:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_test_find_binary_search_do_uint32 (const int *int_array, gsize len)
|
|
|
|
|
{
|
|
|
|
|
gssize idx;
|
|
|
|
|
const int OFFSET = 100;
|
|
|
|
|
const int NEEDLE = 0 + OFFSET;
|
|
|
|
|
gssize expected_result = -1;
|
2017-12-11 18:21:34 +01:00
|
|
|
guint32 array[30];
|
|
|
|
|
|
|
|
|
|
g_assert (len <= G_N_ELEMENTS (array));
|
2016-09-23 13:37:22 +02:00
|
|
|
|
|
|
|
|
/* the test data has negative values. Shift them... */
|
|
|
|
|
for (idx = 0; idx < len; idx++) {
|
|
|
|
|
int v = int_array[idx];
|
|
|
|
|
|
|
|
|
|
g_assert (v > -OFFSET);
|
|
|
|
|
g_assert (v < OFFSET);
|
|
|
|
|
g_assert (idx == 0 || v > int_array[idx - 1]);
|
|
|
|
|
array[idx] = (guint32) (int_array[idx] + OFFSET);
|
|
|
|
|
if (array[idx] == NEEDLE)
|
|
|
|
|
expected_result = idx;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-28 12:26:37 +02:00
|
|
|
idx = nm_utils_array_find_binary_search (array,
|
|
|
|
|
sizeof (guint32),
|
|
|
|
|
len,
|
|
|
|
|
&NEEDLE,
|
|
|
|
|
nm_cmp_uint32_p_with_data,
|
|
|
|
|
NULL);
|
2016-09-23 13:37:22 +02:00
|
|
|
if (expected_result >= 0)
|
|
|
|
|
g_assert_cmpint (expected_result, ==, idx);
|
|
|
|
|
else {
|
|
|
|
|
gssize idx2 = ~idx;
|
|
|
|
|
g_assert_cmpint (idx, <, 0);
|
|
|
|
|
|
|
|
|
|
g_assert (idx2 >= 0);
|
|
|
|
|
g_assert (idx2 <= len);
|
|
|
|
|
g_assert (idx2 - 1 < 0 || array[idx2 - 1] < NEEDLE);
|
|
|
|
|
g_assert (idx2 >= len || array[idx2] > NEEDLE);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-06-23 15:05:25 +02:00
|
|
|
#define test_find_binary_search_do(...) \
|
|
|
|
|
G_STMT_START { \
|
2016-09-23 15:03:41 +02:00
|
|
|
const int _array[] = { __VA_ARGS__ }; \
|
2015-06-23 15:05:25 +02:00
|
|
|
_test_find_binary_search_do (_array, G_N_ELEMENTS (_array)); \
|
2016-09-23 13:37:22 +02:00
|
|
|
_test_find_binary_search_do_uint32 (_array, G_N_ELEMENTS (_array)); \
|
2015-06-23 15:05:25 +02:00
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_ptrarray_find_binary_search (void)
|
|
|
|
|
{
|
|
|
|
|
test_find_binary_search_do ( 0);
|
|
|
|
|
test_find_binary_search_do ( -1, 0);
|
|
|
|
|
test_find_binary_search_do ( -2, -1, 0);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1, 0);
|
|
|
|
|
test_find_binary_search_do ( 0, 1);
|
|
|
|
|
test_find_binary_search_do ( 0, 1, 2);
|
|
|
|
|
test_find_binary_search_do ( -1, 0, 1, 2);
|
|
|
|
|
test_find_binary_search_do ( -2, -1, 0, 1, 2);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1, 0, 1, 2);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1, 0, 1, 2);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1, 0, 1, 2, 3);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1, 0, 1, 2, 3, 4);
|
|
|
|
|
|
|
|
|
|
test_find_binary_search_do ( -1);
|
|
|
|
|
test_find_binary_search_do ( -2, -1);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1);
|
|
|
|
|
test_find_binary_search_do ( 1);
|
|
|
|
|
test_find_binary_search_do ( 1, 2);
|
|
|
|
|
test_find_binary_search_do ( -1, 1, 2);
|
|
|
|
|
test_find_binary_search_do ( -2, -1, 1, 2);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1, 1, 2);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1, 1, 2);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1, 1, 2, 3);
|
|
|
|
|
test_find_binary_search_do (-3, -2, -1, 1, 2, 3, 4);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-07 15:20:42 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#define BIN_SEARCH_W_DUPS_LEN 100
|
|
|
|
|
#define BIN_SEARCH_W_DUPS_JITTER 10
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
_test_bin_search2_cmp (gconstpointer pa,
|
|
|
|
|
gconstpointer pb,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
int a = GPOINTER_TO_INT (pa);
|
|
|
|
|
int b = GPOINTER_TO_INT (pb);
|
|
|
|
|
|
|
|
|
|
g_assert (a >= 0 && a <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER);
|
|
|
|
|
g_assert (b >= 0 && b <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER);
|
|
|
|
|
NM_CMP_DIRECT (a, b);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
_test_bin_search2_cmp_p (gconstpointer pa,
|
|
|
|
|
gconstpointer pb,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
return _test_bin_search2_cmp (*((gpointer *) pa), *((gpointer *) pb), NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_ptrarray_find_binary_search_with_duplicates (void)
|
|
|
|
|
{
|
|
|
|
|
gssize idx, idx2, idx_first2, idx_first, idx_last;
|
|
|
|
|
int i_test, i_len, i;
|
|
|
|
|
gssize j;
|
|
|
|
|
gconstpointer arr[BIN_SEARCH_W_DUPS_LEN];
|
|
|
|
|
const int N_TEST = 10;
|
|
|
|
|
|
|
|
|
|
for (i_test = 0; i_test < N_TEST; i_test++) {
|
|
|
|
|
for (i_len = 0; i_len < BIN_SEARCH_W_DUPS_LEN; i_len++) {
|
|
|
|
|
|
|
|
|
|
/* fill with random numbers... surely there are some duplicates
|
|
|
|
|
* there... or maybe even there are none... */
|
|
|
|
|
for (i = 0; i < i_len; i++)
|
2019-05-30 08:33:14 +02:00
|
|
|
arr[i] = GINT_TO_POINTER (nmtst_get_rand_uint32 () % (i_len + BIN_SEARCH_W_DUPS_JITTER));
|
2017-12-07 15:20:42 +01:00
|
|
|
g_qsort_with_data (arr,
|
|
|
|
|
i_len,
|
|
|
|
|
sizeof (gpointer),
|
|
|
|
|
_test_bin_search2_cmp_p,
|
|
|
|
|
NULL);
|
|
|
|
|
for (i = 0; i < i_len + BIN_SEARCH_W_DUPS_JITTER; i++) {
|
|
|
|
|
gconstpointer p = GINT_TO_POINTER (i);
|
|
|
|
|
|
2018-08-01 11:03:02 +02:00
|
|
|
idx = nm_utils_ptrarray_find_binary_search (arr, i_len, p, _test_bin_search2_cmp, NULL, &idx_first, &idx_last);
|
2017-12-07 15:20:42 +01:00
|
|
|
|
|
|
|
|
idx_first2 = _nm_utils_ptrarray_find_first (arr, i_len, p);
|
|
|
|
|
|
2018-07-28 12:26:37 +02:00
|
|
|
idx2 = nm_utils_array_find_binary_search (arr, sizeof (gpointer), i_len, &p, _test_bin_search2_cmp_p, NULL);
|
2017-12-07 15:20:42 +01:00
|
|
|
g_assert_cmpint (idx, ==, idx2);
|
|
|
|
|
|
|
|
|
|
if (idx_first2 < 0) {
|
|
|
|
|
g_assert_cmpint (idx, <, 0);
|
|
|
|
|
g_assert_cmpint (idx, ==, idx_first);
|
|
|
|
|
g_assert_cmpint (idx, ==, idx_last);
|
|
|
|
|
idx = ~idx;
|
|
|
|
|
g_assert_cmpint (idx, >=, 0);
|
|
|
|
|
g_assert_cmpint (idx, <=, i_len);
|
|
|
|
|
if (i_len == 0)
|
|
|
|
|
g_assert_cmpint (idx, ==, 0);
|
|
|
|
|
else {
|
|
|
|
|
g_assert (idx == i_len || GPOINTER_TO_INT (arr[idx]) > i);
|
|
|
|
|
g_assert (idx == 0 || GPOINTER_TO_INT (arr[idx - 1]) < i);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
g_assert_cmpint (idx_first, ==, idx_first2);
|
|
|
|
|
g_assert_cmpint (idx_first, >=, 0);
|
|
|
|
|
g_assert_cmpint (idx_last, <, i_len);
|
|
|
|
|
g_assert_cmpint (idx_first, <=, idx_last);
|
|
|
|
|
g_assert_cmpint (idx, >=, idx_first);
|
|
|
|
|
g_assert_cmpint (idx, <=, idx_last);
|
|
|
|
|
for (j = idx_first; j < idx_last; j++)
|
|
|
|
|
g_assert (GPOINTER_TO_INT (arr[j]) == i);
|
|
|
|
|
g_assert (idx_first == 0 || GPOINTER_TO_INT (arr[idx_first - 1]) < i);
|
|
|
|
|
g_assert (idx_last == i_len - 1 || GPOINTER_TO_INT (arr[idx_last + 1]) > i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2018-05-29 12:07:53 +02:00
|
|
|
|
2015-06-04 15:05:33 +02:00
|
|
|
static void
|
2018-05-29 12:07:53 +02:00
|
|
|
_test_nm_utils_enum_to_str_do_full (GType type,
|
|
|
|
|
int flags,
|
|
|
|
|
const char *exp_str,
|
|
|
|
|
const NMUtilsEnumValueInfo *value_infos)
|
2015-06-04 15:05:33 +02:00
|
|
|
{
|
2018-05-29 12:07:53 +02:00
|
|
|
gs_free char *str = NULL;
|
|
|
|
|
int flags2;
|
|
|
|
|
gs_free char *err_token = NULL;
|
2015-06-04 15:05:33 +02:00
|
|
|
gboolean result;
|
|
|
|
|
|
2018-05-29 12:07:53 +02:00
|
|
|
g_assert (exp_str);
|
2015-06-04 15:05:33 +02:00
|
|
|
|
2018-05-29 12:07:53 +02:00
|
|
|
str = _nm_utils_enum_to_str_full (type, flags, ", ", value_infos);
|
|
|
|
|
g_assert_cmpstr (str, ==, exp_str);
|
|
|
|
|
|
|
|
|
|
if (!value_infos) {
|
|
|
|
|
gs_free char *str2 = NULL;
|
|
|
|
|
|
|
|
|
|
str2 = nm_utils_enum_to_str (type, flags);
|
|
|
|
|
g_assert_cmpstr (str2, ==, exp_str);
|
|
|
|
|
}
|
2015-06-04 15:05:33 +02:00
|
|
|
|
2018-05-29 12:07:53 +02:00
|
|
|
result = _nm_utils_enum_from_str_full (type, str, &flags2, &err_token, value_infos);
|
|
|
|
|
g_assert (result == TRUE);
|
|
|
|
|
g_assert_cmpint (flags2, ==, flags);
|
|
|
|
|
g_assert_cmpstr (err_token, ==, NULL);
|
2015-06-04 15:05:33 +02:00
|
|
|
}
|
|
|
|
|
|
2018-05-29 12:07:53 +02:00
|
|
|
#define _test_nm_utils_enum_to_str_do(...) _test_nm_utils_enum_to_str_do_full (__VA_ARGS__, NULL)
|
|
|
|
|
|
2015-06-04 15:05:33 +02:00
|
|
|
static void
|
2018-05-29 12:07:53 +02:00
|
|
|
_test_nm_utils_enum_from_str_do_full (GType type,
|
|
|
|
|
const char *str,
|
|
|
|
|
gboolean exp_result,
|
|
|
|
|
int exp_flags,
|
|
|
|
|
const char *exp_err_token,
|
|
|
|
|
const NMUtilsEnumValueInfo *value_infos)
|
2015-06-04 15:05:33 +02:00
|
|
|
{
|
2018-05-29 12:07:53 +02:00
|
|
|
int flags;
|
|
|
|
|
gs_free char *err_token = NULL;
|
|
|
|
|
gboolean result;
|
2015-06-23 15:05:25 +02:00
|
|
|
|
2018-05-29 12:07:53 +02:00
|
|
|
result = _nm_utils_enum_from_str_full (type, str, &flags, &err_token, value_infos);
|
|
|
|
|
|
|
|
|
|
g_assert (result == exp_result);
|
|
|
|
|
g_assert_cmpint (flags, ==, exp_flags);
|
|
|
|
|
g_assert_cmpstr (err_token, ==, exp_err_token);
|
|
|
|
|
|
|
|
|
|
if (!value_infos) {
|
|
|
|
|
int flags2;
|
|
|
|
|
gs_free char *err_token2 = NULL;
|
|
|
|
|
gboolean result2;
|
|
|
|
|
|
|
|
|
|
result2 = nm_utils_enum_from_str (type, str, &flags2, &err_token2);
|
|
|
|
|
g_assert (result2 == exp_result);
|
|
|
|
|
g_assert_cmpint (flags2, ==, exp_flags);
|
|
|
|
|
g_assert_cmpstr (err_token2, ==, exp_err_token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result) {
|
|
|
|
|
int flags2;
|
|
|
|
|
gs_free char *str2 = NULL;
|
|
|
|
|
gs_free char *err_token2 = NULL;
|
|
|
|
|
|
|
|
|
|
str2 = _nm_utils_enum_to_str_full (type, flags, ", ", value_infos);
|
|
|
|
|
g_assert (str2);
|
|
|
|
|
|
|
|
|
|
result = _nm_utils_enum_from_str_full (type, str2, &flags2, &err_token2, value_infos);
|
|
|
|
|
g_assert (result == TRUE);
|
|
|
|
|
g_assert_cmpint (flags2, ==, flags);
|
|
|
|
|
g_assert_cmpstr (err_token, ==, NULL);
|
|
|
|
|
}
|
2015-06-04 15:05:33 +02:00
|
|
|
}
|
|
|
|
|
|
2018-05-29 12:07:53 +02:00
|
|
|
#define _test_nm_utils_enum_from_str_do(...) _test_nm_utils_enum_from_str_do_full(__VA_ARGS__, NULL)
|
|
|
|
|
|
2015-09-06 13:11:11 +02:00
|
|
|
static void
|
2018-05-29 12:07:53 +02:00
|
|
|
_test_nm_utils_enum_get_values_do (GType type, int from, int to, const char *exp_str)
|
2015-09-06 13:11:11 +02:00
|
|
|
{
|
2018-05-29 12:07:53 +02:00
|
|
|
gs_free const char **strv = NULL;
|
|
|
|
|
gs_free char *str = NULL;
|
|
|
|
|
|
|
|
|
|
g_assert (exp_str);
|
2015-09-06 13:11:11 +02:00
|
|
|
|
|
|
|
|
strv = nm_utils_enum_get_values (type, from, to);
|
|
|
|
|
g_assert (strv);
|
|
|
|
|
str = g_strjoinv (",", (char **) strv);
|
|
|
|
|
g_assert_cmpstr (str, ==, exp_str);
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-29 12:07:53 +02:00
|
|
|
static void
|
|
|
|
|
test_nm_utils_enum (void)
|
2015-06-04 15:05:33 +02:00
|
|
|
{
|
|
|
|
|
GType bool_enum = nm_test_general_bool_enum_get_type();
|
|
|
|
|
GType meta_flags = nm_test_general_meta_flags_get_type();
|
|
|
|
|
GType color_flags = nm_test_general_color_flags_get_type();
|
2018-05-29 12:07:53 +02:00
|
|
|
static const NMUtilsEnumValueInfo color_value_infos[] = {
|
|
|
|
|
{
|
|
|
|
|
.nick = "nick-4d",
|
|
|
|
|
.value = 0x4D,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.nick = "nick-5",
|
|
|
|
|
.value = 5,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.nick = "nick-red",
|
|
|
|
|
.value = NM_TEST_GENERAL_COLOR_FLAGS_RED,
|
|
|
|
|
},
|
2018-05-29 14:33:21 +02:00
|
|
|
{ 0 },
|
2018-05-29 12:07:53 +02:00
|
|
|
};
|
2015-06-04 15:05:33 +02:00
|
|
|
|
2018-05-29 12:07:53 +02:00
|
|
|
_test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, "yes");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN, "unknown");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_INVALID, "4");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_67, "67");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_46, "64");
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "none");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_FOO |
|
|
|
|
|
NM_TEST_GENERAL_META_FLAGS_BAR |
|
|
|
|
|
NM_TEST_GENERAL_META_FLAGS_BAZ, "foo, bar, baz");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (meta_flags, 0xFF, "foo, bar, baz, 0xf8");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_0x8, "0x8");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_0x4, "0x10");
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED, "red");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_WHITE, "0x1");
|
|
|
|
|
_test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED |
|
|
|
|
|
NM_TEST_GENERAL_COLOR_FLAGS_GREEN, "red, green");
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_to_str_do_full (color_flags,
|
|
|
|
|
NM_TEST_GENERAL_COLOR_FLAGS_RED
|
|
|
|
|
| NM_TEST_GENERAL_COLOR_FLAGS_GREEN,
|
|
|
|
|
"nick-red, green",
|
|
|
|
|
color_value_infos);
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_to_str_do_full (color_flags,
|
|
|
|
|
0x4D
|
|
|
|
|
| NM_TEST_GENERAL_COLOR_FLAGS_RED
|
|
|
|
|
| NM_TEST_GENERAL_COLOR_FLAGS_GREEN,
|
|
|
|
|
"nick-4d",
|
|
|
|
|
color_value_infos);
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_to_str_do_full (color_flags,
|
|
|
|
|
5
|
|
|
|
|
| NM_TEST_GENERAL_COLOR_FLAGS_GREEN,
|
|
|
|
|
"nick-5, green",
|
|
|
|
|
color_value_infos);
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_from_str_do (bool_enum, "", FALSE, 0, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (bool_enum, " ", FALSE, 0, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (bool_enum, "invalid", FALSE, 0, "invalid");
|
|
|
|
|
_test_nm_utils_enum_from_str_do (bool_enum, "yes", TRUE, NM_TEST_GENERAL_BOOL_ENUM_YES, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (bool_enum, "no", TRUE, NM_TEST_GENERAL_BOOL_ENUM_NO, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (bool_enum, "yes,no", FALSE, 0, "yes,no");
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_from_str_do (meta_flags, "", TRUE, 0, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (meta_flags, " ", TRUE, 0, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (meta_flags, "foo", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (meta_flags, "foo,baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
|
2015-09-14 14:23:50 +02:00
|
|
|
NM_TEST_GENERAL_META_FLAGS_BAZ, NULL);
|
2018-05-29 12:07:53 +02:00
|
|
|
_test_nm_utils_enum_from_str_do (meta_flags, "foo, baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
|
|
|
|
|
NM_TEST_GENERAL_META_FLAGS_BAZ, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (meta_flags, "foo,,bar", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
|
|
|
|
|
NM_TEST_GENERAL_META_FLAGS_BAR, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (meta_flags, "foo,baz,quux,bar", FALSE, 0, "quux");
|
|
|
|
|
_test_nm_utils_enum_from_str_do (meta_flags, "foo,0x6", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO | 0x6, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (meta_flags, "0x30,0x08,foo", TRUE, 0x39, NULL);
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_from_str_do (color_flags, "green", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_GREEN, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (color_flags, "blue,red", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_BLUE |
|
|
|
|
|
NM_TEST_GENERAL_COLOR_FLAGS_RED, NULL);
|
|
|
|
|
_test_nm_utils_enum_from_str_do (color_flags, "blue,white", FALSE, 0, "white");
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_from_str_do_full (color_flags,
|
|
|
|
|
"nick-red",
|
|
|
|
|
TRUE,
|
|
|
|
|
NM_TEST_GENERAL_COLOR_FLAGS_RED,
|
|
|
|
|
NULL,
|
|
|
|
|
color_value_infos);
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_from_str_do_full (color_flags,
|
|
|
|
|
"0x4D",
|
|
|
|
|
TRUE,
|
|
|
|
|
0x4D,
|
|
|
|
|
NULL,
|
|
|
|
|
color_value_infos);
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_from_str_do_full (color_flags,
|
|
|
|
|
"green,nick-4d",
|
|
|
|
|
TRUE,
|
|
|
|
|
0x4D
|
|
|
|
|
| NM_TEST_GENERAL_COLOR_FLAGS_GREEN,
|
|
|
|
|
NULL,
|
|
|
|
|
color_value_infos);
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_from_str_do_full (color_flags,
|
|
|
|
|
"nick-4d,nick-red,nick-5,green,nick-red",
|
|
|
|
|
TRUE,
|
2018-05-29 11:26:11 +02:00
|
|
|
0x4D
|
|
|
|
|
| NM_TEST_GENERAL_COLOR_FLAGS_GREEN,
|
2018-05-29 12:07:53 +02:00
|
|
|
NULL,
|
|
|
|
|
color_value_infos);
|
|
|
|
|
|
|
|
|
|
_test_nm_utils_enum_get_values_do (bool_enum, 0, G_MAXINT, "no,yes,maybe,unknown,67,64");
|
|
|
|
|
_test_nm_utils_enum_get_values_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES,
|
|
|
|
|
NM_TEST_GENERAL_BOOL_ENUM_MAYBE, "yes,maybe");
|
|
|
|
|
_test_nm_utils_enum_get_values_do (meta_flags, 0, G_MAXINT, "none,foo,bar,baz,0x8,0x10");
|
|
|
|
|
_test_nm_utils_enum_get_values_do (color_flags, 0, G_MAXINT, "blue,red,green");
|
2015-06-04 15:05:33 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-08-12 13:04:12 +02:00
|
|
|
|
2017-05-16 18:50:21 +02:00
|
|
|
static void
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
_do_test_utils_str_utf8safe_unescape (const char *str, const char *expected, gsize expected_len)
|
2017-05-16 18:50:21 +02:00
|
|
|
{
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
gsize l;
|
|
|
|
|
const char *s;
|
|
|
|
|
gs_free gpointer buf_free_1 = NULL;
|
|
|
|
|
gs_free char *str_free_1 = NULL;
|
2017-05-16 18:50:21 +02:00
|
|
|
|
2020-05-04 09:52:16 +02:00
|
|
|
s = nm_utils_buf_utf8safe_unescape (str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &l, &buf_free_1);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert_cmpint (expected_len, ==, l);
|
|
|
|
|
g_assert_cmpstr (s, ==, expected);
|
2017-05-16 18:50:21 +02:00
|
|
|
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
if (str == NULL) {
|
|
|
|
|
g_assert (!s);
|
|
|
|
|
g_assert (!buf_free_1);
|
|
|
|
|
g_assert_cmpint (l, ==, 0);
|
|
|
|
|
} else {
|
|
|
|
|
g_assert (s);
|
|
|
|
|
if (!strchr (str, '\\')) {
|
|
|
|
|
g_assert (!buf_free_1);
|
|
|
|
|
g_assert (s == str);
|
|
|
|
|
g_assert_cmpint (l, ==, strlen (str));
|
|
|
|
|
} else {
|
|
|
|
|
g_assert (buf_free_1);
|
|
|
|
|
g_assert (s == buf_free_1);
|
|
|
|
|
g_assert (memcmp (s, expected, expected_len) == 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( expected
|
|
|
|
|
&& l == strlen (expected)) {
|
|
|
|
|
/* there are no embeeded NULs. Check that nm_utils_str_utf8safe_unescape() yields the same result. */
|
2020-05-04 09:52:16 +02:00
|
|
|
s = nm_utils_str_utf8safe_unescape (str, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_1);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert_cmpstr (s, ==, expected);
|
|
|
|
|
if (strchr (str, '\\')) {
|
|
|
|
|
g_assert (str_free_1 != str);
|
|
|
|
|
g_assert (s == str_free_1);
|
|
|
|
|
} else
|
|
|
|
|
g_assert (s == str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define do_test_utils_str_utf8safe_unescape(str, expected) \
|
|
|
|
|
_do_test_utils_str_utf8safe_unescape (""str"", expected, NM_STRLEN (expected))
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_do_test_utils_str_utf8safe (const char *str, gsize str_len, const char *expected, NMUtilsStrUtf8SafeFlags flags)
|
|
|
|
|
{
|
|
|
|
|
const char *str_safe;
|
|
|
|
|
const char *buf_safe;
|
|
|
|
|
const char *s;
|
|
|
|
|
gs_free char *str_free_1 = NULL;
|
|
|
|
|
gs_free char *str_free_2 = NULL;
|
|
|
|
|
gs_free char *str_free_3 = NULL;
|
|
|
|
|
gs_free char *str_free_4 = NULL;
|
|
|
|
|
gs_free char *str_free_5 = NULL;
|
|
|
|
|
gs_free char *str_free_6 = NULL;
|
|
|
|
|
gs_free char *str_free_7 = NULL;
|
|
|
|
|
gs_free char *str_free_8 = NULL;
|
|
|
|
|
gboolean str_has_nul = FALSE;
|
2018-09-09 12:19:07 +02:00
|
|
|
#define RND_FLAG ((nmtst_get_rand_bool ()) ? NM_UTILS_STR_UTF8_SAFE_FLAG_NONE : NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET)
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
|
2018-09-09 12:19:07 +02:00
|
|
|
buf_safe = nm_utils_buf_utf8safe_escape (str, str_len, flags | RND_FLAG, &str_free_1);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
|
2018-09-09 12:19:07 +02:00
|
|
|
str_safe = nm_utils_str_utf8safe_escape (str, flags | RND_FLAG, &str_free_2);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
|
|
|
|
|
if (str_len == 0) {
|
|
|
|
|
g_assert (buf_safe == NULL);
|
|
|
|
|
g_assert (str_free_1 == NULL);
|
|
|
|
|
g_assert (str_safe == str);
|
|
|
|
|
g_assert (str == NULL || str[0] == '\0');
|
|
|
|
|
g_assert (str_free_2 == NULL);
|
|
|
|
|
} else if (str_len == strlen (str)) {
|
|
|
|
|
g_assert (buf_safe);
|
|
|
|
|
g_assert_cmpstr (buf_safe, ==, str_safe);
|
|
|
|
|
|
|
|
|
|
/* nm_utils_buf_utf8safe_escape() can only return a pointer equal to the input string,
|
|
|
|
|
* if and only if str_len is negative. Otherwise, the input str won't be NUL terminated
|
|
|
|
|
* and cannot be returned. */
|
|
|
|
|
g_assert (buf_safe != str);
|
|
|
|
|
g_assert (buf_safe == str_free_1);
|
|
|
|
|
} else
|
|
|
|
|
str_has_nul = TRUE;
|
|
|
|
|
|
2018-09-09 12:19:07 +02:00
|
|
|
str_free_3 = nm_utils_str_utf8safe_escape_cp (str, flags | RND_FLAG);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert_cmpstr (str_free_3, ==, str_safe);
|
|
|
|
|
g_assert ((!str && !str_free_3) || (str != str_free_3));
|
|
|
|
|
|
|
|
|
|
if (str_len > 0)
|
|
|
|
|
_do_test_utils_str_utf8safe_unescape (buf_safe, str, str_len);
|
2017-05-16 18:50:21 +02:00
|
|
|
|
|
|
|
|
if (expected == NULL) {
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert (!str_has_nul);
|
|
|
|
|
|
2017-05-16 18:50:21 +02:00
|
|
|
g_assert (str_safe == str);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert (!str_free_2);
|
2017-05-16 18:50:21 +02:00
|
|
|
if (str) {
|
|
|
|
|
g_assert (!strchr (str, '\\'));
|
|
|
|
|
g_assert (g_utf8_validate (str, -1, NULL));
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 09:52:16 +02:00
|
|
|
g_assert (str == nm_utils_str_utf8safe_unescape (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_4));
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert (!str_free_4);
|
2017-05-16 18:50:21 +02:00
|
|
|
|
2020-05-04 09:52:16 +02:00
|
|
|
str_free_5 = nm_utils_str_utf8safe_unescape_cp (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
2017-05-16 18:50:21 +02:00
|
|
|
if (str) {
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert (str_free_5 != str);
|
|
|
|
|
g_assert_cmpstr (str_free_5, ==, str);
|
2017-05-16 18:50:21 +02:00
|
|
|
} else
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert (!str_free_5);
|
2017-05-16 18:50:21 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
if (!str_has_nul) {
|
|
|
|
|
g_assert (str);
|
|
|
|
|
g_assert (str_safe != str);
|
|
|
|
|
g_assert (str_safe == str_free_2);
|
|
|
|
|
g_assert ( strchr (str, '\\')
|
|
|
|
|
|| !g_utf8_validate (str, -1, NULL)
|
|
|
|
|
|| ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII)
|
|
|
|
|
&& NM_STRCHAR_ANY (str, ch, (guchar) ch >= 127))
|
|
|
|
|
|| ( NM_FLAGS_HAS (flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL)
|
|
|
|
|
&& NM_STRCHAR_ANY (str, ch, (guchar) ch < ' ')));
|
|
|
|
|
g_assert (g_utf8_validate (str_safe, -1, NULL));
|
|
|
|
|
|
|
|
|
|
str_free_6 = g_strcompress (str_safe);
|
|
|
|
|
g_assert_cmpstr (str, ==, str_free_6);
|
2017-05-16 18:50:21 +02:00
|
|
|
|
2020-05-04 09:52:16 +02:00
|
|
|
str_free_7 = nm_utils_str_utf8safe_unescape_cp (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert (str_free_7 != str);
|
|
|
|
|
g_assert_cmpstr (str_free_7, ==, str);
|
2017-05-16 18:50:21 +02:00
|
|
|
|
2020-05-04 09:52:16 +02:00
|
|
|
s = nm_utils_str_utf8safe_unescape (str_safe, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, &str_free_8);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert (str_free_8 != str);
|
|
|
|
|
g_assert (s == str_free_8);
|
|
|
|
|
g_assert_cmpstr (str_free_8, ==, str);
|
2017-05-16 18:50:21 +02:00
|
|
|
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
g_assert_cmpstr (str_safe, ==, expected);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (buf_safe, ==, expected);
|
2017-05-16 18:50:21 +02:00
|
|
|
|
|
|
|
|
}
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
#define do_test_utils_str_utf8safe(str, expected, flags) \
|
|
|
|
|
_do_test_utils_str_utf8safe (""str"", NM_STRLEN (str), expected, flags)
|
2017-05-16 18:50:21 +02:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_utils_str_utf8safe (void)
|
|
|
|
|
{
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
_do_test_utils_str_utf8safe (NULL, 0, NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
|
2017-05-16 18:50:21 +02:00
|
|
|
do_test_utils_str_utf8safe ("", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
do_test_utils_str_utf8safe ("\\", "\\\\", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\\a", "\\\\a", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
2017-05-16 18:50:21 +02:00
|
|
|
do_test_utils_str_utf8safe ("\314", "\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\314\315x\315\315x", "\\314\\315x\\315\\315x", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\314\315xx", "\\314\\315xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\314xx", "\\314xx", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\xa0", "\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\xe2\x91\xa0", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\xe2\xe2\x91\xa0", "\\342\xe2\x91\xa0", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\xe2\xe2\x91\xa0\xa0", "\\342\xe2\x91\xa0\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("a", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("ab", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("ab\314", "ab\\314", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("ab\314adsf", "ab\\314adsf", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("abadsf", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("abäb", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("x\xa0", "x\\240", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("Ä\304ab\\äb", "Ä\\304ab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("Äab\\äb", "Äab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("ÄÄab\\äb", "ÄÄab\\\\äb", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("㈞abä㈞b", NULL, NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("abäb", "ab\\303\\244b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII);
|
|
|
|
|
do_test_utils_str_utf8safe ("ab\ab", "ab\\007b", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
|
shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.
Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.
This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-12 11:43:25 +02:00
|
|
|
|
|
|
|
|
do_test_utils_str_utf8safe ("\0", "\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\0a\0", "\\000a\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\\\0", "\\\\\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\n\0", "\n\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_NONE);
|
|
|
|
|
do_test_utils_str_utf8safe ("\n\0", "\\012\\000", NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL);
|
|
|
|
|
|
|
|
|
|
do_test_utils_str_utf8safe_unescape ("\n\\0", "\n\0");
|
|
|
|
|
do_test_utils_str_utf8safe_unescape ("\n\\01", "\n\01");
|
|
|
|
|
do_test_utils_str_utf8safe_unescape ("\n\\012", "\n\012");
|
|
|
|
|
do_test_utils_str_utf8safe_unescape ("\n\\.", "\n.");
|
|
|
|
|
do_test_utils_str_utf8safe_unescape ("\\n\\.3\\r", "\n.3\r");
|
2017-05-16 18:50:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2015-08-12 13:04:12 +02:00
|
|
|
static int
|
|
|
|
|
_test_nm_in_set_get (int *call_counter, gboolean allow_called, int value)
|
|
|
|
|
{
|
|
|
|
|
g_assert (call_counter);
|
|
|
|
|
*call_counter += 1;
|
|
|
|
|
if (!allow_called)
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_test_nm_in_set_assert (int *call_counter, int expected)
|
|
|
|
|
{
|
|
|
|
|
g_assert (call_counter);
|
|
|
|
|
g_assert_cmpint (expected, ==, *call_counter);
|
|
|
|
|
*call_counter = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_in_set (void)
|
|
|
|
|
{
|
|
|
|
|
int call_counter = 0;
|
|
|
|
|
|
|
|
|
|
#define G(x) _test_nm_in_set_get (&call_counter, TRUE, x)
|
|
|
|
|
#define N(x) _test_nm_in_set_get (&call_counter, FALSE, x)
|
|
|
|
|
#define _ASSERT(expected, expr) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
_test_nm_in_set_assert (&call_counter, 0); \
|
|
|
|
|
g_assert (expr); \
|
|
|
|
|
_test_nm_in_set_assert (&call_counter, (expected)); \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
_ASSERT (1, !NM_IN_SET (-1, G( 1)));
|
|
|
|
|
_ASSERT (1, NM_IN_SET (-1, G(-1)));
|
|
|
|
|
|
|
|
|
|
_ASSERT (2, !NM_IN_SET (-1, G( 1), G( 2)));
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (1, NM_IN_SET (-1, G(-1), N( 2)));
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (2, NM_IN_SET (-1, G( 1), G(-1)));
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (1, NM_IN_SET (-1, G(-1), N(-1)));
|
2015-08-12 13:04:12 +02:00
|
|
|
|
|
|
|
|
_ASSERT (3, !NM_IN_SET (-1, G( 1), G( 2), G( 3)));
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (1, NM_IN_SET (-1, G(-1), N( 2), N( 3)));
|
|
|
|
|
_ASSERT (2, NM_IN_SET (-1, G( 1), G(-1), N( 3)));
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (3, NM_IN_SET (-1, G( 1), G( 2), G(-1)));
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (2, NM_IN_SET (-1, G( 1), G(-1), N(-1)));
|
|
|
|
|
_ASSERT (1, NM_IN_SET (-1, G(-1), N( 2), N(-1)));
|
|
|
|
|
_ASSERT (1, NM_IN_SET (-1, G(-1), N(-1), N( 3)));
|
|
|
|
|
_ASSERT (1, NM_IN_SET (-1, G(-1), N(-1), N(-1)));
|
2015-08-12 13:04:12 +02:00
|
|
|
|
|
|
|
|
_ASSERT (4, !NM_IN_SET (-1, G( 1), G( 2), G( 3), G( 4)));
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (1, NM_IN_SET (-1, G(-1), N( 2), N( 3), N( 4)));
|
|
|
|
|
_ASSERT (2, NM_IN_SET (-1, G( 1), G(-1), N( 3), N( 4)));
|
|
|
|
|
_ASSERT (3, NM_IN_SET (-1, G( 1), G( 2), G(-1), N( 4)));
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (4, NM_IN_SET (-1, G( 1), G( 2), G( 3), G(-1)));
|
|
|
|
|
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (4, NM_IN_SET (-1, G( 1), G( 2), G( 3), G(-1), G( 5)));
|
2016-02-11 17:24:33 +01:00
|
|
|
_ASSERT (5, NM_IN_SET (-1, G( 1), G( 2), G( 3), G( 4), G(-1)));
|
|
|
|
|
_ASSERT (6, NM_IN_SET (-1, G( 1), G( 2), G( 3), G( 4), G( 5), G( -1)));
|
2015-08-12 13:04:12 +02:00
|
|
|
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (1, !NM_IN_SET_SE (-1, G( 1)));
|
|
|
|
|
_ASSERT (1, NM_IN_SET_SE (-1, G(-1)));
|
2015-08-12 13:04:12 +02:00
|
|
|
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (2, !NM_IN_SET_SE (-1, G( 1), G( 2)));
|
|
|
|
|
_ASSERT (2, NM_IN_SET_SE (-1, G(-1), G( 2)));
|
|
|
|
|
_ASSERT (2, NM_IN_SET_SE (-1, G( 1), G(-1)));
|
|
|
|
|
_ASSERT (2, NM_IN_SET_SE (-1, G(-1), G(-1)));
|
2015-08-12 13:04:12 +02:00
|
|
|
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (3, !NM_IN_SET_SE (-1, G( 1), G( 2), G( 3)));
|
|
|
|
|
_ASSERT (3, NM_IN_SET_SE (-1, G(-1), G( 2), G( 3)));
|
|
|
|
|
_ASSERT (3, NM_IN_SET_SE (-1, G( 1), G(-1), G( 3)));
|
|
|
|
|
_ASSERT (3, NM_IN_SET_SE (-1, G( 1), G( 2), G(-1)));
|
|
|
|
|
_ASSERT (3, NM_IN_SET_SE (-1, G( 1), G(-1), G(-1)));
|
|
|
|
|
_ASSERT (3, NM_IN_SET_SE (-1, G(-1), G( 2), G(-1)));
|
|
|
|
|
_ASSERT (3, NM_IN_SET_SE (-1, G(-1), G(-1), G( 3)));
|
|
|
|
|
_ASSERT (3, NM_IN_SET_SE (-1, G(-1), G(-1), G(-1)));
|
2015-08-12 13:04:12 +02:00
|
|
|
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (4, !NM_IN_SET_SE (-1, G( 1), G( 2), G( 3), G( 4)));
|
|
|
|
|
_ASSERT (4, NM_IN_SET_SE (-1, G(-1), G( 2), G( 3), G( 4)));
|
|
|
|
|
_ASSERT (4, NM_IN_SET_SE (-1, G( 1), G(-1), G( 3), G( 4)));
|
|
|
|
|
_ASSERT (4, NM_IN_SET_SE (-1, G( 1), G( 2), G(-1), G( 4)));
|
|
|
|
|
_ASSERT (4, NM_IN_SET_SE (-1, G( 1), G( 2), G( 3), G(-1)));
|
2015-08-12 13:04:12 +02:00
|
|
|
|
2015-08-12 13:04:12 +02:00
|
|
|
_ASSERT (5, NM_IN_SET_SE (-1, G( 1), G( 2), G( 3), G(-1), G( 5)));
|
2016-02-11 17:24:33 +01:00
|
|
|
_ASSERT (6, NM_IN_SET_SE (-1, G( 1), G( 2), G( 3), G( 4), G( 5), G(-1)));
|
2016-09-22 14:14:22 +02:00
|
|
|
|
libnm-core/tests: avoid -Wstring-compare in unit test for NM_IN_SET()
Clang 10 doesn't like NM_IN_SET() with strings and is right about that:
../libnm-core/tests/test-general.c:7763:9: error: result of comparison against a string literal is unspecified (use an explicit string comparison function instead) [-Werror,-Wstring-compare]
(void) NM_IN_SET ("a", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
However, NM_IN_STRSET() should work.
2020-02-21 15:15:12 +01:00
|
|
|
g_assert (!NM_IN_SET (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16));
|
2015-08-12 13:04:12 +02:00
|
|
|
#undef G
|
|
|
|
|
#undef N
|
|
|
|
|
#undef _ASSERT
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2015-08-12 13:04:12 +02:00
|
|
|
|
2016-02-11 16:53:06 +01:00
|
|
|
static const char *
|
|
|
|
|
_test_nm_in_set_getstr (int *call_counter, gboolean allow_called, const char *value)
|
|
|
|
|
{
|
|
|
|
|
g_assert (call_counter);
|
|
|
|
|
*call_counter += 1;
|
|
|
|
|
if (!allow_called)
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_in_strset (void)
|
|
|
|
|
{
|
|
|
|
|
int call_counter = 0;
|
|
|
|
|
|
|
|
|
|
#define G(x) _test_nm_in_set_getstr (&call_counter, TRUE, x)
|
|
|
|
|
#define N(x) _test_nm_in_set_getstr (&call_counter, FALSE, x)
|
|
|
|
|
#define _ASSERT(expected, expr) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
_test_nm_in_set_assert (&call_counter, 0); \
|
|
|
|
|
g_assert (expr); \
|
|
|
|
|
_test_nm_in_set_assert (&call_counter, (expected)); \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL)));
|
|
|
|
|
_ASSERT (1, !NM_IN_STRSET ("a", G(NULL)));
|
|
|
|
|
_ASSERT (1, !NM_IN_STRSET (NULL, G("a")));
|
|
|
|
|
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET_SE (NULL, G(NULL)));
|
|
|
|
|
_ASSERT (1, !NM_IN_STRSET_SE ("a", G(NULL)));
|
|
|
|
|
_ASSERT (1, !NM_IN_STRSET_SE (NULL, G("a")));
|
|
|
|
|
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N(NULL)));
|
|
|
|
|
_ASSERT (2, !NM_IN_STRSET ("a", G(NULL), G(NULL)));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET (NULL, G("a"), G(NULL)));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N("a")));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET ("a", G(NULL), G("a")));
|
|
|
|
|
_ASSERT (2, !NM_IN_STRSET (NULL, G("a"), G("a")));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N("b")));
|
|
|
|
|
_ASSERT (2, !NM_IN_STRSET ("a", G(NULL), G("b")));
|
|
|
|
|
_ASSERT (2, !NM_IN_STRSET (NULL, G("a"), G("b")));
|
|
|
|
|
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET_SE (NULL, G(NULL), G(NULL)));
|
|
|
|
|
_ASSERT (2, !NM_IN_STRSET_SE ("a", G(NULL), G(NULL)));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET_SE (NULL, G("a"), G(NULL)));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET_SE (NULL, G(NULL), G("a")));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET_SE ("a", G(NULL), G("a")));
|
|
|
|
|
_ASSERT (2, !NM_IN_STRSET_SE (NULL, G("a"), G("a")));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET_SE (NULL, G(NULL), G("b")));
|
|
|
|
|
_ASSERT (2, !NM_IN_STRSET_SE ("a", G(NULL), G("b")));
|
|
|
|
|
_ASSERT (2, !NM_IN_STRSET_SE (NULL, G("a"), G("b")));
|
|
|
|
|
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N(NULL), N(NULL)));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET ("a", G(NULL), G(NULL), G(NULL)));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET (NULL, G("a"), G(NULL), N(NULL)));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N("a"), N(NULL)));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET ("a", G(NULL), G("a"), N(NULL)));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET (NULL, G("a"), G("a"), G(NULL)));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N("b"), N(NULL)));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET ("a", G(NULL), G("b"), G(NULL)));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET (NULL, G("a"), G("b"), G(NULL)));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N(NULL), N("a")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET ("a", G(NULL), G(NULL), G("a")));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET (NULL, G("a"), G(NULL), N("a")));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N("a"), N("a")));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET ("a", G(NULL), G("a"), N("a")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET (NULL, G("a"), G("a"), G("a")));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N("b"), N("a")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET ("a", G(NULL), G("b"), G("a")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET (NULL, G("a"), G("b"), G("a")));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N(NULL), N("b")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET ("a", G(NULL), G(NULL), G("b")));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET (NULL, G("a"), G(NULL), N("b")));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N("a"), N("b")));
|
|
|
|
|
_ASSERT (2, NM_IN_STRSET ("a", G(NULL), G("a"), N("b")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET (NULL, G("a"), G("a"), G("b")));
|
|
|
|
|
_ASSERT (1, NM_IN_STRSET (NULL, G(NULL), N("b"), N("b")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET ("a", G(NULL), G("b"), G("b")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET (NULL, G("a"), G("b"), G("b")));
|
|
|
|
|
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G(NULL), G(NULL), G(NULL)));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET_SE ("a", G(NULL), G(NULL), G(NULL)));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G("a"), G(NULL), G(NULL)));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G(NULL), G("a"), G(NULL)));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE ("a", G(NULL), G("a"), G(NULL)));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G("a"), G("a"), G(NULL)));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G(NULL), G("b"), G(NULL)));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET_SE ("a", G(NULL), G("b"), G(NULL)));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G("a"), G("b"), G(NULL)));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G(NULL), G(NULL), G("a")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE ("a", G(NULL), G(NULL), G("a")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G("a"), G(NULL), G("a")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G(NULL), G("a"), G("a")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE ("a", G(NULL), G("a"), G("a")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET_SE (NULL, G("a"), G("a"), G("a")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G(NULL), G("b"), G("a")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE ("a", G(NULL), G("b"), G("a")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET_SE (NULL, G("a"), G("b"), G("a")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G(NULL), G(NULL), G("b")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET_SE ("a", G(NULL), G(NULL), G("b")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G("a"), G(NULL), G("b")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G(NULL), G("a"), G("b")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE ("a", G(NULL), G("a"), G("b")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET_SE (NULL, G("a"), G("a"), G("b")));
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET_SE (NULL, G(NULL), G("b"), G("b")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET_SE ("a", G(NULL), G("b"), G("b")));
|
|
|
|
|
_ASSERT (3, !NM_IN_STRSET_SE (NULL, G("a"), G("b"), G("b")));
|
|
|
|
|
|
|
|
|
|
_ASSERT (3, NM_IN_STRSET ("a", G(NULL), G("b"), G("a"), N("a")));
|
|
|
|
|
_ASSERT (4, NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("a")));
|
|
|
|
|
_ASSERT (4, !NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("d")));
|
|
|
|
|
|
|
|
|
|
_ASSERT (4, NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("a"), N("a")));
|
|
|
|
|
_ASSERT (5, NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("d"), G("a")));
|
|
|
|
|
_ASSERT (5, !NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("d"), G("e")));
|
|
|
|
|
|
|
|
|
|
_ASSERT (5, NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("d"), G("a"), N("a")));
|
|
|
|
|
_ASSERT (6, NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("d"), G("e"), G("a")));
|
|
|
|
|
_ASSERT (6, !NM_IN_STRSET ("a", G(NULL), G("b"), G("c"), G("d"), G("e"), G("f")));
|
2016-09-22 14:14:22 +02:00
|
|
|
|
libnm-core/tests: avoid -Wstring-compare in unit test for NM_IN_SET()
Clang 10 doesn't like NM_IN_SET() with strings and is right about that:
../libnm-core/tests/test-general.c:7763:9: error: result of comparison against a string literal is unspecified (use an explicit string comparison function instead) [-Werror,-Wstring-compare]
(void) NM_IN_SET ("a", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
However, NM_IN_STRSET() should work.
2020-02-21 15:15:12 +01:00
|
|
|
g_assert (!NM_IN_STRSET (NULL, "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"));
|
|
|
|
|
g_assert (!NM_IN_STRSET ("_", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"));
|
|
|
|
|
g_assert ( NM_IN_STRSET ("10", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"));
|
2016-02-11 16:53:06 +01:00
|
|
|
#undef G
|
|
|
|
|
#undef N
|
|
|
|
|
#undef _ASSERT
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-15 15:06:24 +01:00
|
|
|
static void
|
|
|
|
|
test_route_attributes_parse (void)
|
|
|
|
|
{
|
|
|
|
|
GHashTable *ht;
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
GVariant *variant;
|
|
|
|
|
|
2017-03-15 09:29:47 +01:00
|
|
|
ht = nm_utils_parse_variant_attributes ("mtu=1400 src=1.2.3.4 cwnd=14",
|
2017-02-15 15:06:24 +01:00
|
|
|
' ', '=', FALSE,
|
|
|
|
|
nm_ip_route_get_variant_attribute_spec (),
|
|
|
|
|
&error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (ht);
|
|
|
|
|
g_hash_table_unref (ht);
|
|
|
|
|
|
2017-03-15 09:29:47 +01:00
|
|
|
ht = nm_utils_parse_variant_attributes ("mtu=1400 src=1.2.3.4 cwnd=14 \\",
|
2017-02-15 15:06:24 +01:00
|
|
|
' ', '=', FALSE,
|
|
|
|
|
nm_ip_route_get_variant_attribute_spec (),
|
|
|
|
|
&error);
|
|
|
|
|
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED);
|
|
|
|
|
g_assert (!ht);
|
|
|
|
|
g_clear_error (&error);
|
|
|
|
|
|
2017-03-15 09:29:47 +01:00
|
|
|
ht = nm_utils_parse_variant_attributes ("mtu.1400 src.1\\.2\\.3\\.4 ",
|
2017-02-15 15:06:24 +01:00
|
|
|
' ', '.', FALSE,
|
|
|
|
|
nm_ip_route_get_variant_attribute_spec (),
|
|
|
|
|
&error);
|
|
|
|
|
g_assert (ht);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
variant = g_hash_table_lookup (ht, NM_IP_ROUTE_ATTRIBUTE_MTU);
|
|
|
|
|
g_assert (variant);
|
|
|
|
|
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32));
|
|
|
|
|
g_assert_cmpuint (g_variant_get_uint32 (variant), ==, 1400);
|
|
|
|
|
|
2017-03-15 09:29:47 +01:00
|
|
|
variant = g_hash_table_lookup (ht, NM_IP_ROUTE_ATTRIBUTE_SRC);
|
2017-02-15 15:06:24 +01:00
|
|
|
g_assert (variant);
|
|
|
|
|
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING));
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "1.2.3.4");
|
|
|
|
|
g_hash_table_unref (ht);
|
|
|
|
|
|
2017-03-15 09:29:47 +01:00
|
|
|
ht = nm_utils_parse_variant_attributes ("from:fd01\\:\\:42\\/64/initrwnd:21",
|
2017-02-15 15:06:24 +01:00
|
|
|
'/', ':', FALSE,
|
|
|
|
|
nm_ip_route_get_variant_attribute_spec (),
|
|
|
|
|
&error);
|
|
|
|
|
g_assert (ht);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
variant = g_hash_table_lookup (ht, NM_IP_ROUTE_ATTRIBUTE_INITRWND);
|
|
|
|
|
g_assert (variant);
|
|
|
|
|
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_UINT32));
|
|
|
|
|
g_assert_cmpuint (g_variant_get_uint32 (variant), ==, 21);
|
|
|
|
|
|
2017-03-15 09:29:47 +01:00
|
|
|
variant = g_hash_table_lookup (ht, NM_IP_ROUTE_ATTRIBUTE_FROM);
|
2017-02-15 15:06:24 +01:00
|
|
|
g_assert (variant);
|
|
|
|
|
g_assert (g_variant_is_of_type (variant, G_VARIANT_TYPE_STRING));
|
|
|
|
|
g_assert_cmpstr (g_variant_get_string (variant, NULL), ==, "fd01::42/64");
|
|
|
|
|
g_hash_table_unref (ht);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_route_attributes_format (void)
|
|
|
|
|
{
|
|
|
|
|
gs_unref_hashtable GHashTable *ht = NULL;
|
|
|
|
|
char *str;
|
|
|
|
|
|
2017-11-15 16:06:43 +01:00
|
|
|
ht = g_hash_table_new_full (nm_str_hash, g_str_equal,
|
2017-02-15 15:06:24 +01:00
|
|
|
NULL, (GDestroyNotify) g_variant_unref);
|
|
|
|
|
|
|
|
|
|
str = nm_utils_format_variant_attributes (NULL, ' ', '=');
|
|
|
|
|
g_assert_cmpstr (str, ==, NULL);
|
|
|
|
|
|
|
|
|
|
str = nm_utils_format_variant_attributes (ht, ' ', '=');
|
|
|
|
|
g_assert_cmpstr (str, ==, NULL);
|
|
|
|
|
|
|
|
|
|
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_MTU, g_variant_new_uint32 (5000));
|
|
|
|
|
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_INITRWND, g_variant_new_uint32 (20));
|
|
|
|
|
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_LOCK_MTU, g_variant_new_boolean (TRUE));
|
2017-03-15 09:29:47 +01:00
|
|
|
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_SRC, g_variant_new_string ("aaaa:bbbb::1"));
|
2017-02-15 15:06:24 +01:00
|
|
|
str = nm_utils_format_variant_attributes (ht, ' ', '=');
|
2017-03-15 09:29:47 +01:00
|
|
|
g_assert_cmpstr (str, ==, "initrwnd=20 lock-mtu=true mtu=5000 src=aaaa:bbbb::1");
|
2017-02-15 15:06:24 +01:00
|
|
|
g_hash_table_remove_all (ht);
|
|
|
|
|
g_free (str);
|
|
|
|
|
|
|
|
|
|
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_WINDOW, g_variant_new_uint32 (30000));
|
|
|
|
|
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_INITCWND, g_variant_new_uint32 (21));
|
2017-03-15 09:29:47 +01:00
|
|
|
g_hash_table_insert (ht, NM_IP_ROUTE_ATTRIBUTE_FROM, g_variant_new_string ("aaaa:bbbb:cccc:dddd::/64"));
|
2017-02-15 15:06:24 +01:00
|
|
|
str = nm_utils_format_variant_attributes (ht, '/', ':');
|
2017-03-15 09:29:47 +01:00
|
|
|
g_assert_cmpstr (str, ==, "from:aaaa\\:bbbb\\:cccc\\:dddd\\:\\:\\/64/initcwnd:21/window:30000");
|
2017-02-15 15:06:24 +01:00
|
|
|
g_hash_table_remove_all (ht);
|
|
|
|
|
g_free (str);
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2016-02-11 16:53:06 +01:00
|
|
|
|
2019-11-27 13:13:48 +01:00
|
|
|
static void
|
|
|
|
|
test_variant_attribute_spec (void)
|
|
|
|
|
{
|
|
|
|
|
const NMVariantAttributeSpec *const *const specs_list[] = {
|
|
|
|
|
nm_ip_route_get_variant_attribute_spec (),
|
|
|
|
|
};
|
|
|
|
|
int i_specs;
|
|
|
|
|
|
|
|
|
|
for (i_specs = 0; i_specs < G_N_ELEMENTS (specs_list); i_specs++) {
|
|
|
|
|
const NMVariantAttributeSpec *const *const specs = specs_list[i_specs];
|
|
|
|
|
gsize len;
|
|
|
|
|
gsize i;
|
|
|
|
|
|
|
|
|
|
g_assert (specs);
|
|
|
|
|
|
|
|
|
|
len = NM_PTRARRAY_LEN (specs);
|
|
|
|
|
g_assert_cmpint (len, >, 0u);
|
|
|
|
|
|
|
|
|
|
_nmtst_variant_attribute_spec_assert_sorted (specs, len);
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
g_assert (specs[i] == _nm_variant_attribute_spec_find_binary_search (specs, len, specs[i]->name));
|
|
|
|
|
g_assert (!_nm_variant_attribute_spec_find_binary_search (specs, len, "bogus"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-09-26 16:59:30 +02:00
|
|
|
static gboolean
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
do_test_nm_set_out_called (int *call_count)
|
2016-09-26 16:59:30 +02:00
|
|
|
{
|
|
|
|
|
(*call_count)++;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_set_out (void)
|
|
|
|
|
{
|
|
|
|
|
gboolean val;
|
|
|
|
|
gboolean *p_val;
|
|
|
|
|
int call_count;
|
|
|
|
|
|
|
|
|
|
/* NM_SET_OUT() has an unexpected non-function like behavior
|
|
|
|
|
* wrt. side-effects of the value argument. Test it */
|
|
|
|
|
|
|
|
|
|
p_val = &val;
|
|
|
|
|
call_count = 0;
|
|
|
|
|
NM_SET_OUT (p_val, do_test_nm_set_out_called (&call_count));
|
|
|
|
|
g_assert_cmpint (call_count, ==, 1);
|
|
|
|
|
|
|
|
|
|
p_val = NULL;
|
|
|
|
|
call_count = 0;
|
|
|
|
|
NM_SET_OUT (p_val, do_test_nm_set_out_called (&call_count));
|
|
|
|
|
g_assert_cmpint (call_count, ==, 0);
|
2016-10-11 12:23:02 +02:00
|
|
|
|
|
|
|
|
/* test that we successfully re-defined _G_BOOLEAN_EXPR() */
|
|
|
|
|
#define _T1(a) \
|
|
|
|
|
({ \
|
2016-10-11 14:08:36 +02:00
|
|
|
g_assert (a > 2); \
|
2016-10-11 12:23:02 +02:00
|
|
|
a; \
|
|
|
|
|
})
|
|
|
|
|
g_assert (_T1 (3) > 1);
|
|
|
|
|
#undef _T1
|
2016-09-26 16:59:30 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2016-09-26 16:59:30 +02:00
|
|
|
|
2018-05-25 15:38:21 +02:00
|
|
|
static void
|
|
|
|
|
test_get_start_time_for_pid (void)
|
|
|
|
|
{
|
|
|
|
|
guint64 x_start_time;
|
|
|
|
|
char x_state;
|
|
|
|
|
pid_t x_ppid;
|
|
|
|
|
|
|
|
|
|
x_start_time = nm_utils_get_start_time_for_pid (getpid (), &x_state, &x_ppid);
|
|
|
|
|
|
|
|
|
|
g_assert (x_start_time > 0);
|
|
|
|
|
g_assert (x_ppid == getppid ());
|
|
|
|
|
g_assert (!NM_IN_SET (x_state, '\0', ' '));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2018-07-10 08:45:39 +02:00
|
|
|
static void
|
|
|
|
|
test_nm_va_args_macros (void)
|
|
|
|
|
{
|
|
|
|
|
#define GET_NARG_1(...) \
|
|
|
|
|
NM_NARG (__VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint ( 0, ==, GET_NARG_1 ());
|
|
|
|
|
g_assert_cmpint ( 1, ==, GET_NARG_1 (x));
|
|
|
|
|
g_assert_cmpint ( 2, ==, GET_NARG_1 ( , ));
|
|
|
|
|
g_assert_cmpint ( 2, ==, GET_NARG_1 ( , x));
|
|
|
|
|
g_assert_cmpint ( 2, ==, GET_NARG_1 (x, ));
|
|
|
|
|
g_assert_cmpint ( 2, ==, GET_NARG_1 (x, x));
|
|
|
|
|
g_assert_cmpint ( 3, ==, GET_NARG_1 ( , , ));
|
|
|
|
|
g_assert_cmpint ( 3, ==, GET_NARG_1 ( , , x));
|
|
|
|
|
g_assert_cmpint ( 3, ==, GET_NARG_1 ( , x, ));
|
|
|
|
|
g_assert_cmpint ( 3, ==, GET_NARG_1 ( , x, x));
|
|
|
|
|
g_assert_cmpint ( 3, ==, GET_NARG_1 (x, , ));
|
|
|
|
|
g_assert_cmpint ( 3, ==, GET_NARG_1 (x, , x));
|
|
|
|
|
g_assert_cmpint ( 3, ==, GET_NARG_1 (x, x, ));
|
|
|
|
|
g_assert_cmpint ( 3, ==, GET_NARG_1 (x, x, x));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , , ));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , , x));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , x, ));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 ( , , x, x));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, , ));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, , x));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, x, ));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 ( , x, x, x));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , , ));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , , x));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , x, ));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 (x, , x, x));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, , ));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, , x));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, x, ));
|
|
|
|
|
g_assert_cmpint ( 4, ==, GET_NARG_1 (x, x, x, x));
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint ( 5, ==, GET_NARG_1 (x, x, x, x, x));
|
|
|
|
|
g_assert_cmpint ( 6, ==, GET_NARG_1 (x, x, x, x, x, x));
|
|
|
|
|
g_assert_cmpint ( 7, ==, GET_NARG_1 (x, x, x, x, x, x, x));
|
|
|
|
|
g_assert_cmpint ( 8, ==, GET_NARG_1 (x, x, x, x, x, x, x, x));
|
|
|
|
|
g_assert_cmpint ( 9, ==, GET_NARG_1 (x, x, x, x, x, x, x, x, x));
|
|
|
|
|
g_assert_cmpint (10, ==, GET_NARG_1 (x, x, x, x, x, x, x, x, x, x));
|
|
|
|
|
|
|
|
|
|
G_STATIC_ASSERT_EXPR (0 == GET_NARG_1 ());
|
|
|
|
|
G_STATIC_ASSERT_EXPR (1 == GET_NARG_1 (x));
|
|
|
|
|
G_STATIC_ASSERT_EXPR (2 == GET_NARG_1 (x, x));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
libnm, cli, ifcfg-rh: add NMSettingEthtool setting
Note that in NetworkManager API (D-Bus, libnm, and nmcli),
the features are called "feature-xyz". The "feature-" prefix
is used, because NMSettingEthtool possibly will gain support
for options that are not only -K|--offload|--features, for
example -C|--coalesce.
The "xzy" suffix is either how ethtool utility calls the feature
("tso", "rx"). Or, if ethtool utility specifies no alias for that
feature, it's the name from kernel's ETH_SS_FEATURES ("tx-tcp6-segmentation").
If possible, we prefer ethtool utility's naming.
Also note, how the features "feature-sg", "feature-tso", and
"feature-tx" actually refer to multiple underlying kernel features
at once. This too follows what ethtool utility does.
The functionality is not yet implemented server-side.
2018-07-16 23:37:55 +02:00
|
|
|
static void
|
|
|
|
|
test_ethtool_offload (void)
|
|
|
|
|
{
|
|
|
|
|
const NMEthtoolData *d;
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (nm_ethtool_id_get_by_name ("invalid"), ==, NM_ETHTOOL_ID_UNKNOWN);
|
|
|
|
|
g_assert_cmpint (nm_ethtool_id_get_by_name ("feature-rx"), ==, NM_ETHTOOL_ID_FEATURE_RX);
|
|
|
|
|
|
|
|
|
|
d = nm_ethtool_data_get_by_optname (NM_ETHTOOL_OPTNAME_FEATURE_RXHASH);
|
|
|
|
|
g_assert (d);
|
|
|
|
|
g_assert_cmpint (d->id, ==, NM_ETHTOOL_ID_FEATURE_RXHASH);
|
|
|
|
|
g_assert_cmpstr (d->optname, ==, NM_ETHTOOL_OPTNAME_FEATURE_RXHASH);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
shared: add nm_utils_g_main_context_create_integrate_source() for integrating a GMainContext in another
We will rework NMClient entirely. Then, the synchronous initialization will also use
the asynchronous code paths. The difference will be that with synchronous initialization,
all D-Bus interaction will be done with an internal GMainContext as current thread default,
and that internal context will run until initialization completes.
Note that even after initialization completes, it cannot be swapped back to the user's
(outer) GMainContext. That is because contexts are essentially the queue for our
D-Bus events, and we cannot swap from one queue to the other in a race
free manner (or a full resync). In other words, the two contexts are not in sync,
so after using the internal context NMClient needs to stick to that (at least, until
the name owner gets lost, which gives an opportunity to resync and switch back to the
user's main context).
We thus need to hook the internal (inner) GMainContext with the user's (outer) context,
so when the user iterates the outer context, events on the inner context get dispatched.
Add nm_utils_g_main_context_create_integrate_source() to create such a GSource for
integrating two contexts.
Note that the use-case here is limited: the integrated, inner main context must
not be explicitly iterated except from being dispatched by the integrating
source. Otherwise, you'd get recursive runs, possible deadlocks and general
ugliness. NMClient must show restrain how to use the inner context while it is
integrated.
2019-11-02 16:55:43 +01:00
|
|
|
typedef struct {
|
|
|
|
|
GMainLoop *loop1;
|
|
|
|
|
GMainContext *c2;
|
|
|
|
|
GSource *extra_sources[2];
|
|
|
|
|
bool got_signal[5];
|
|
|
|
|
int fd_2;
|
|
|
|
|
} IntegData;
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_test_integrate_cb_handle (IntegData *d, int signal)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
g_assert (d);
|
|
|
|
|
g_assert (signal >= 0);
|
|
|
|
|
g_assert (signal < G_N_ELEMENTS (d->got_signal));
|
|
|
|
|
|
|
|
|
|
g_assert (!d->got_signal[signal]);
|
|
|
|
|
d->got_signal[signal] = TRUE;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (d->got_signal); i++) {
|
|
|
|
|
if (!d->got_signal[i])
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (i == G_N_ELEMENTS (d->got_signal))
|
|
|
|
|
g_main_loop_quit (d->loop1);
|
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_test_integrate_cb_timeout_1 (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
return _test_integrate_cb_handle (user_data, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_test_integrate_cb_fd_2 (int fd,
|
|
|
|
|
GIOCondition condition,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
IntegData *d = user_data;
|
|
|
|
|
|
|
|
|
|
g_assert (d->got_signal[1]);
|
|
|
|
|
g_assert (d->got_signal[2]);
|
|
|
|
|
g_assert (d->got_signal[3]);
|
|
|
|
|
g_assert (d->extra_sources[0]);
|
|
|
|
|
g_assert (d->extra_sources[1]);
|
|
|
|
|
|
|
|
|
|
return _test_integrate_cb_handle (d, 4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_test_integrate_cb_idle_2 (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
IntegData *d = user_data;
|
|
|
|
|
GSource *extra_source;
|
|
|
|
|
|
|
|
|
|
g_assert (d->got_signal[1]);
|
|
|
|
|
g_assert (d->got_signal[2]);
|
|
|
|
|
g_assert (d->extra_sources[0]);
|
|
|
|
|
g_assert (!d->extra_sources[1]);
|
|
|
|
|
|
2020-01-01 10:30:27 +01:00
|
|
|
extra_source = nm_g_unix_fd_source_new (d->fd_2,
|
|
|
|
|
G_IO_IN,
|
|
|
|
|
G_PRIORITY_DEFAULT,
|
|
|
|
|
_test_integrate_cb_fd_2,
|
|
|
|
|
d,
|
|
|
|
|
NULL);
|
shared: add nm_utils_g_main_context_create_integrate_source() for integrating a GMainContext in another
We will rework NMClient entirely. Then, the synchronous initialization will also use
the asynchronous code paths. The difference will be that with synchronous initialization,
all D-Bus interaction will be done with an internal GMainContext as current thread default,
and that internal context will run until initialization completes.
Note that even after initialization completes, it cannot be swapped back to the user's
(outer) GMainContext. That is because contexts are essentially the queue for our
D-Bus events, and we cannot swap from one queue to the other in a race
free manner (or a full resync). In other words, the two contexts are not in sync,
so after using the internal context NMClient needs to stick to that (at least, until
the name owner gets lost, which gives an opportunity to resync and switch back to the
user's main context).
We thus need to hook the internal (inner) GMainContext with the user's (outer) context,
so when the user iterates the outer context, events on the inner context get dispatched.
Add nm_utils_g_main_context_create_integrate_source() to create such a GSource for
integrating two contexts.
Note that the use-case here is limited: the integrated, inner main context must
not be explicitly iterated except from being dispatched by the integrating
source. Otherwise, you'd get recursive runs, possible deadlocks and general
ugliness. NMClient must show restrain how to use the inner context while it is
integrated.
2019-11-02 16:55:43 +01:00
|
|
|
g_source_attach (extra_source, d->c2);
|
|
|
|
|
|
|
|
|
|
d->extra_sources[1] = extra_source;
|
|
|
|
|
|
|
|
|
|
return _test_integrate_cb_handle (d, 3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_test_integrate_cb_idle_1 (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
IntegData *d = user_data;
|
|
|
|
|
GSource *extra_source;
|
|
|
|
|
|
|
|
|
|
g_assert (d->got_signal[2]);
|
|
|
|
|
g_assert (!d->extra_sources[0]);
|
|
|
|
|
|
|
|
|
|
extra_source = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (extra_source, _test_integrate_cb_idle_2, d, NULL);
|
|
|
|
|
g_source_attach (extra_source, d->c2);
|
|
|
|
|
|
|
|
|
|
d->extra_sources[0] = extra_source;
|
|
|
|
|
|
|
|
|
|
return _test_integrate_cb_handle (d, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_test_integrate_cb_fd_1 (int fd,
|
|
|
|
|
GIOCondition condition,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
IntegData *d = user_data;
|
|
|
|
|
|
|
|
|
|
g_assert (!d->got_signal[1]);
|
|
|
|
|
return _test_integrate_cb_handle (d, 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_test_integrate_maincontext_cb_idle1 (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
guint32 *p_count = user_data;
|
|
|
|
|
|
|
|
|
|
g_assert (*p_count < 5);
|
|
|
|
|
(*p_count)++;
|
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_integrate_maincontext (gconstpointer test_data)
|
|
|
|
|
{
|
|
|
|
|
const guint TEST_IDX = GPOINTER_TO_UINT (test_data);
|
|
|
|
|
GMainContext *c1 = g_main_context_default ();
|
|
|
|
|
nm_auto_unref_gmaincontext GMainContext *c2 = g_main_context_new ();
|
|
|
|
|
nm_auto_destroy_and_unref_gsource GSource *integ_source = NULL;
|
|
|
|
|
|
|
|
|
|
integ_source = nm_utils_g_main_context_create_integrate_source (c2);
|
|
|
|
|
g_source_attach (integ_source, c1);
|
|
|
|
|
|
|
|
|
|
if (TEST_IDX == 1) {
|
|
|
|
|
nm_auto_destroy_and_unref_gsource GSource *idle_source_1 = NULL;
|
|
|
|
|
guint32 count = 0;
|
|
|
|
|
|
|
|
|
|
idle_source_1 = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (idle_source_1, _test_integrate_maincontext_cb_idle1, &count, NULL);
|
|
|
|
|
g_source_attach (idle_source_1, c2);
|
|
|
|
|
|
2020-01-04 08:57:47 +01:00
|
|
|
nmtst_main_context_iterate_until_assert (c1, 2000, count == 5);
|
shared: add nm_utils_g_main_context_create_integrate_source() for integrating a GMainContext in another
We will rework NMClient entirely. Then, the synchronous initialization will also use
the asynchronous code paths. The difference will be that with synchronous initialization,
all D-Bus interaction will be done with an internal GMainContext as current thread default,
and that internal context will run until initialization completes.
Note that even after initialization completes, it cannot be swapped back to the user's
(outer) GMainContext. That is because contexts are essentially the queue for our
D-Bus events, and we cannot swap from one queue to the other in a race
free manner (or a full resync). In other words, the two contexts are not in sync,
so after using the internal context NMClient needs to stick to that (at least, until
the name owner gets lost, which gives an opportunity to resync and switch back to the
user's main context).
We thus need to hook the internal (inner) GMainContext with the user's (outer) context,
so when the user iterates the outer context, events on the inner context get dispatched.
Add nm_utils_g_main_context_create_integrate_source() to create such a GSource for
integrating two contexts.
Note that the use-case here is limited: the integrated, inner main context must
not be explicitly iterated except from being dispatched by the integrating
source. Otherwise, you'd get recursive runs, possible deadlocks and general
ugliness. NMClient must show restrain how to use the inner context while it is
integrated.
2019-11-02 16:55:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (TEST_IDX == 2) {
|
|
|
|
|
nm_auto_destroy_and_unref_gsource GSource *main_timeout_source = NULL;
|
|
|
|
|
nm_auto_destroy_and_unref_gsource GSource *timeout_source_1 = NULL;
|
|
|
|
|
nm_auto_destroy_and_unref_gsource GSource *idle_source_1 = NULL;
|
|
|
|
|
nm_auto_destroy_and_unref_gsource GSource *fd_source_1 = NULL;
|
|
|
|
|
nm_auto_unref_gmainloop GMainLoop *loop1 = NULL;
|
|
|
|
|
nm_auto_close int fd_1 = -1;
|
|
|
|
|
nm_auto_close int fd_2 = -1;
|
|
|
|
|
IntegData d;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
main_timeout_source = g_timeout_source_new (3000);
|
|
|
|
|
g_source_set_callback (main_timeout_source, nmtst_g_source_assert_not_called, NULL, NULL);
|
|
|
|
|
g_source_attach (main_timeout_source, c1);
|
|
|
|
|
|
|
|
|
|
loop1 = g_main_loop_new (c1, FALSE);
|
|
|
|
|
|
|
|
|
|
d = (IntegData) {
|
|
|
|
|
.loop1 = loop1,
|
|
|
|
|
.c2 = c2,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
fd_1 = open ("/dev/null", O_RDONLY | O_CLOEXEC);
|
|
|
|
|
g_assert (fd_1 >= 0);
|
2020-01-01 10:30:27 +01:00
|
|
|
fd_source_1 = nm_g_unix_fd_source_new (fd_1,
|
|
|
|
|
G_IO_IN,
|
|
|
|
|
G_PRIORITY_DEFAULT,
|
|
|
|
|
_test_integrate_cb_fd_1,
|
|
|
|
|
&d,
|
|
|
|
|
NULL);
|
shared: add nm_utils_g_main_context_create_integrate_source() for integrating a GMainContext in another
We will rework NMClient entirely. Then, the synchronous initialization will also use
the asynchronous code paths. The difference will be that with synchronous initialization,
all D-Bus interaction will be done with an internal GMainContext as current thread default,
and that internal context will run until initialization completes.
Note that even after initialization completes, it cannot be swapped back to the user's
(outer) GMainContext. That is because contexts are essentially the queue for our
D-Bus events, and we cannot swap from one queue to the other in a race
free manner (or a full resync). In other words, the two contexts are not in sync,
so after using the internal context NMClient needs to stick to that (at least, until
the name owner gets lost, which gives an opportunity to resync and switch back to the
user's main context).
We thus need to hook the internal (inner) GMainContext with the user's (outer) context,
so when the user iterates the outer context, events on the inner context get dispatched.
Add nm_utils_g_main_context_create_integrate_source() to create such a GSource for
integrating two contexts.
Note that the use-case here is limited: the integrated, inner main context must
not be explicitly iterated except from being dispatched by the integrating
source. Otherwise, you'd get recursive runs, possible deadlocks and general
ugliness. NMClient must show restrain how to use the inner context while it is
integrated.
2019-11-02 16:55:43 +01:00
|
|
|
g_source_attach (fd_source_1, c2);
|
|
|
|
|
|
|
|
|
|
fd_2 = open ("/dev/null", O_RDONLY | O_CLOEXEC);
|
|
|
|
|
g_assert (fd_2 >= 0);
|
|
|
|
|
d.fd_2 = fd_2;
|
|
|
|
|
|
|
|
|
|
idle_source_1 = g_idle_source_new ();
|
|
|
|
|
g_source_set_callback (idle_source_1, _test_integrate_cb_idle_1, &d, NULL);
|
|
|
|
|
g_source_attach (idle_source_1, c2);
|
|
|
|
|
|
|
|
|
|
timeout_source_1 = g_timeout_source_new (5);
|
|
|
|
|
g_source_set_callback (timeout_source_1, _test_integrate_cb_timeout_1, &d, NULL);
|
|
|
|
|
g_source_attach (timeout_source_1, c2);
|
|
|
|
|
|
|
|
|
|
g_main_loop_run (loop1);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (d.extra_sources); i++) {
|
|
|
|
|
g_assert (d.extra_sources[i]);
|
|
|
|
|
nm_clear_pointer (&d.extra_sources[i], nm_g_source_destroy_and_unref);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2020-01-09 10:34:30 +01:00
|
|
|
static void
|
|
|
|
|
test_nm_ip_addr_zero (void)
|
|
|
|
|
{
|
|
|
|
|
in_addr_t a4 = nmtst_inet4_from_string ("0.0.0.0");
|
|
|
|
|
struct in6_addr a6 = *nmtst_inet6_from_string ("::");
|
|
|
|
|
char buf[NM_UTILS_INET_ADDRSTRLEN];
|
2020-01-09 12:32:28 +01:00
|
|
|
NMIPAddr a = NM_IP_ADDR_INIT;
|
|
|
|
|
|
|
|
|
|
g_assert (memcmp (&a, &nm_ip_addr_zero, sizeof (a)) == 0);
|
2020-01-09 10:34:30 +01:00
|
|
|
|
|
|
|
|
g_assert (IN6_IS_ADDR_UNSPECIFIED (&nm_ip_addr_zero.addr6));
|
|
|
|
|
g_assert (memcmp (&nm_ip_addr_zero.addr6, &in6addr_any, sizeof (in6addr_any)) == 0);
|
|
|
|
|
|
|
|
|
|
g_assert (memcmp (&nm_ip_addr_zero, &a4, sizeof (a4)) == 0);
|
|
|
|
|
g_assert (memcmp (&nm_ip_addr_zero, &a6, sizeof (a6)) == 0);
|
|
|
|
|
|
2020-01-09 11:29:27 +01:00
|
|
|
g_assert_cmpstr (_nm_utils_inet4_ntop (nm_ip_addr_zero.addr4, buf), ==, "0.0.0.0");
|
|
|
|
|
g_assert_cmpstr (_nm_utils_inet6_ntop (&nm_ip_addr_zero.addr6, buf), ==, "::");
|
2020-01-09 10:34:30 +01:00
|
|
|
|
|
|
|
|
g_assert_cmpstr (nm_utils_inet_ntop (AF_INET, &nm_ip_addr_zero, buf), ==, "0.0.0.0");
|
|
|
|
|
g_assert_cmpstr (nm_utils_inet_ntop (AF_INET6, &nm_ip_addr_zero, buf), ==, "::");
|
2020-01-09 12:32:28 +01:00
|
|
|
|
|
|
|
|
G_STATIC_ASSERT_EXPR (sizeof (a) == sizeof (a.array));
|
2020-01-09 10:34:30 +01:00
|
|
|
}
|
|
|
|
|
|
2020-02-06 17:17:49 +01:00
|
|
|
static void
|
|
|
|
|
test_connection_ovs_ifname (gconstpointer test_data)
|
|
|
|
|
{
|
|
|
|
|
const guint TEST_CASE = GPOINTER_TO_UINT (test_data);
|
|
|
|
|
gs_unref_object NMConnection *con = NULL;
|
|
|
|
|
NMSettingConnection *s_con = NULL;
|
|
|
|
|
NMSettingOvsBridge *s_ovs_bridge = NULL;
|
|
|
|
|
NMSettingOvsPort *s_ovs_port = NULL;
|
|
|
|
|
NMSettingOvsInterface *s_ovs_iface = NULL;
|
|
|
|
|
NMSettingOvsPatch *s_ovs_patch = NULL;
|
|
|
|
|
const char *ovs_iface_type = NULL;
|
|
|
|
|
|
|
|
|
|
switch (TEST_CASE) {
|
|
|
|
|
case 1:
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_bridge",
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_OVS_BRIDGE_SETTING_NAME, &s_con);
|
|
|
|
|
s_ovs_bridge = nm_connection_get_setting_ovs_bridge (con);
|
|
|
|
|
g_assert (s_ovs_bridge);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_port",
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_OVS_PORT_SETTING_NAME, &s_con);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER,
|
|
|
|
|
"master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE,
|
|
|
|
|
NM_SETTING_OVS_BRIDGE_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ovs_port = nm_connection_get_setting_ovs_port (con);
|
|
|
|
|
g_assert (s_ovs_port);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_interface_patch",
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME, &s_con);
|
|
|
|
|
s_ovs_iface = nm_connection_get_setting_ovs_interface (con);
|
|
|
|
|
g_assert (s_ovs_iface);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER,
|
|
|
|
|
"master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE,
|
|
|
|
|
NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_iface,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE,
|
|
|
|
|
"patch",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ovs_patch = NM_SETTING_OVS_PATCH (nm_setting_ovs_patch_new());
|
|
|
|
|
g_assert (s_ovs_patch);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_patch,
|
|
|
|
|
NM_SETTING_OVS_PATCH_PEER, "1.2.3.4",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, NM_SETTING (s_ovs_patch));
|
|
|
|
|
s_ovs_patch = nm_connection_get_setting_ovs_patch (con);
|
|
|
|
|
g_assert (s_ovs_patch);
|
|
|
|
|
ovs_iface_type = "patch";
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_interface_internal",
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME, &s_con);
|
|
|
|
|
s_ovs_iface = nm_connection_get_setting_ovs_interface (con);
|
|
|
|
|
g_assert (s_ovs_iface);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER,
|
|
|
|
|
"master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE,
|
|
|
|
|
NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_iface,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE,
|
|
|
|
|
"internal",
|
|
|
|
|
NULL);
|
|
|
|
|
ovs_iface_type = "internal";
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_interface_system",
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_WIRED_SETTING_NAME, &s_con);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER,
|
|
|
|
|
"master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE,
|
|
|
|
|
NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s_ovs_iface = NM_SETTING_OVS_INTERFACE (nm_setting_ovs_interface_new());
|
|
|
|
|
g_assert (s_ovs_iface);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_iface,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE,
|
|
|
|
|
"system",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
nm_connection_add_setting (con, NM_SETTING (s_ovs_iface));
|
|
|
|
|
s_ovs_iface = nm_connection_get_setting_ovs_interface (con);
|
|
|
|
|
g_assert (s_ovs_iface);
|
|
|
|
|
|
|
|
|
|
ovs_iface_type = "system";
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
con = nmtst_create_minimal_connection ("test_connection_ovs_ifname_interface_dpdk",
|
|
|
|
|
NULL,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_SETTING_NAME, &s_con);
|
|
|
|
|
s_ovs_iface = nm_connection_get_setting_ovs_interface (con);
|
|
|
|
|
g_assert (s_ovs_iface);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_MASTER,
|
|
|
|
|
"master0",
|
|
|
|
|
NM_SETTING_CONNECTION_SLAVE_TYPE,
|
|
|
|
|
NM_SETTING_OVS_PORT_SETTING_NAME,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
g_object_set (s_ovs_iface,
|
|
|
|
|
NM_SETTING_OVS_INTERFACE_TYPE,
|
|
|
|
|
"dpdk",
|
|
|
|
|
NULL);
|
|
|
|
|
ovs_iface_type = "dpdk";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nm_streq0 (ovs_iface_type, "system")) {
|
|
|
|
|
/* wrong: contains backward slash */
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs\\0",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
|
|
|
|
|
/* wrong: contains forward slash */
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs/0",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* wrong: contains space */
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs 0",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
|
|
|
|
|
/* good */
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs0",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies (con);
|
|
|
|
|
|
2020-02-18 12:16:02 +01:00
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs-br0",
|
|
|
|
|
NULL);
|
|
|
|
|
nmtst_assert_connection_verifies (con);
|
|
|
|
|
|
2020-02-06 17:17:49 +01:00
|
|
|
/* good if bridge, port, or patch interface */
|
|
|
|
|
g_object_set (s_con,
|
|
|
|
|
NM_SETTING_CONNECTION_INTERFACE_NAME, "ovs123123123123130123123",
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
if (!ovs_iface_type || nm_streq (ovs_iface_type, "patch"))
|
|
|
|
|
nmtst_assert_connection_verifies (con);
|
|
|
|
|
else {
|
|
|
|
|
nmtst_assert_connection_unnormalizable (con,
|
|
|
|
|
NM_CONNECTION_ERROR,
|
|
|
|
|
NM_CONNECTION_ERROR_INVALID_PROPERTY);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-22 19:43:35 +02:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
_strsplit_quoted_char_needs_escaping (char ch)
|
|
|
|
|
{
|
|
|
|
|
return NM_IN_SET (ch, '\'', '\"', '\\')
|
|
|
|
|
|| strchr (NM_ASCII_WHITESPACES, ch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
_strsplit_quoted_create_str_rand (gssize len)
|
|
|
|
|
{
|
|
|
|
|
NMStrBuf strbuf = NM_STR_BUF_INIT (nmtst_get_rand_uint32 () % 200, nmtst_get_rand_bool ());
|
|
|
|
|
|
|
|
|
|
g_assert (len >= -1);
|
|
|
|
|
|
|
|
|
|
if (len == -1)
|
|
|
|
|
len = nmtst_get_rand_word_length (NULL);
|
|
|
|
|
|
|
|
|
|
while (len-- > 0) {
|
|
|
|
|
char ch;
|
|
|
|
|
|
|
|
|
|
ch = nmtst_rand_select ('a', ' ', '\\', '"', '\'', nmtst_get_rand_uint32 () % 255 + 1);
|
|
|
|
|
g_assert (ch);
|
|
|
|
|
nm_str_buf_append_c (&strbuf, ch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!strbuf.allocated)
|
|
|
|
|
nm_str_buf_maybe_expand (&strbuf, 1, nmtst_get_rand_bool ());
|
|
|
|
|
return nm_str_buf_finalize (&strbuf, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char **
|
|
|
|
|
_strsplit_quoted_create_strv_rand (void)
|
|
|
|
|
{
|
|
|
|
|
guint len = nmtst_get_rand_word_length (NULL);
|
|
|
|
|
char **ptr;
|
|
|
|
|
guint i;
|
2020-02-06 17:17:49 +01:00
|
|
|
|
2020-06-22 19:43:35 +02:00
|
|
|
ptr = g_new (char *, len + 1);
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
ptr[i] = _strsplit_quoted_create_str_rand (-1);
|
|
|
|
|
ptr[i] = NULL;
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
|
_strsplit_quoted_join_strv_rand (const char *const*strv)
|
|
|
|
|
{
|
|
|
|
|
NMStrBuf strbuf = NM_STR_BUF_INIT (nmtst_get_rand_uint32 () % 200, nmtst_get_rand_bool ());
|
|
|
|
|
char *result;
|
|
|
|
|
gsize l;
|
|
|
|
|
gsize l2;
|
|
|
|
|
gsize *p_l2 = nmtst_get_rand_bool () ? &l2 : NULL;
|
|
|
|
|
gsize i;
|
|
|
|
|
|
|
|
|
|
g_assert (strv);
|
|
|
|
|
|
|
|
|
|
nm_str_buf_append_c_repeated (&strbuf, ' ', nmtst_get_rand_word_length (NULL) / 4);
|
|
|
|
|
for (i = 0; strv[i]; i++) {
|
|
|
|
|
const char *s = strv[i];
|
|
|
|
|
gsize j;
|
|
|
|
|
char quote;
|
|
|
|
|
|
|
|
|
|
nm_str_buf_append_c_repeated (&strbuf, ' ', 1 + nmtst_get_rand_word_length (NULL) / 4);
|
|
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
|
quote = '\0';
|
|
|
|
|
while (TRUE) {
|
|
|
|
|
char ch = s[j++];
|
|
|
|
|
|
|
|
|
|
/* extract_first_word*/
|
|
|
|
|
if (quote != '\0') {
|
|
|
|
|
if (ch == '\0') {
|
|
|
|
|
nm_str_buf_append_c (&strbuf, quote);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ( ch == quote
|
|
|
|
|
|| ch == '\\'
|
|
|
|
|
|| nmtst_get_rand_uint32 () % 5 == 0)
|
|
|
|
|
nm_str_buf_append_c (&strbuf, '\\');
|
|
|
|
|
nm_str_buf_append_c (&strbuf, ch);
|
|
|
|
|
if (nmtst_get_rand_uint32 () % 3 == 0) {
|
|
|
|
|
nm_str_buf_append_c (&strbuf, quote);
|
|
|
|
|
quote = '\0';
|
|
|
|
|
goto next_maybe_quote;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ch == '\0') {
|
|
|
|
|
if (s == strv[i]) {
|
|
|
|
|
quote = nmtst_rand_select ('\'', '"');
|
|
|
|
|
nm_str_buf_append_c_repeated (&strbuf, quote, 2);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( _strsplit_quoted_char_needs_escaping (ch)
|
|
|
|
|
|| nmtst_get_rand_uint32 () % 5 == 0)
|
|
|
|
|
nm_str_buf_append_c (&strbuf, '\\');
|
|
|
|
|
|
|
|
|
|
nm_str_buf_append_c (&strbuf, ch);
|
|
|
|
|
|
|
|
|
|
next_maybe_quote:
|
|
|
|
|
if (nmtst_get_rand_uint32 () % 5 == 0) {
|
|
|
|
|
quote = nmtst_rand_select ('\'', '\"');
|
|
|
|
|
nm_str_buf_append_c (&strbuf, quote);
|
|
|
|
|
if (nmtst_get_rand_uint32 () % 5 == 0) {
|
|
|
|
|
nm_str_buf_append_c (&strbuf, quote);
|
|
|
|
|
quote = '\0';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nm_str_buf_append_c_repeated (&strbuf, ' ', nmtst_get_rand_word_length (NULL) / 4);
|
|
|
|
|
|
|
|
|
|
nm_str_buf_maybe_expand (&strbuf, 1, nmtst_get_rand_bool ());
|
|
|
|
|
|
|
|
|
|
l = strbuf.len;
|
|
|
|
|
result = nm_str_buf_finalize (&strbuf, p_l2);
|
|
|
|
|
g_assert (!p_l2 || l == *p_l2);
|
|
|
|
|
g_assert (strlen (result) == l);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_strsplit_quoted_assert_strv (const char *topic,
|
|
|
|
|
const char *str,
|
|
|
|
|
const char *const*strv1,
|
|
|
|
|
const char *const*strv2)
|
|
|
|
|
{
|
|
|
|
|
nm_auto_str_buf NMStrBuf s1 = { };
|
|
|
|
|
nm_auto_str_buf NMStrBuf s2 = { };
|
|
|
|
|
gs_free char *str_escaped = NULL;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
g_assert (str);
|
|
|
|
|
g_assert (strv1);
|
|
|
|
|
g_assert (strv2);
|
|
|
|
|
|
|
|
|
|
if (_nm_utils_strv_equal ((char **) strv1, (char **) strv2))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (i = 0; strv1[i]; i++) {
|
|
|
|
|
gs_free char *s = g_strescape (strv1[i], NULL);
|
|
|
|
|
|
|
|
|
|
g_print (">>> [%s] strv1[%d] = \"%s\"\n", topic, i, s);
|
|
|
|
|
if (i > 0)
|
|
|
|
|
nm_str_buf_append_c (&s1, ' ');
|
|
|
|
|
nm_str_buf_append_printf (&s1, "\"%s\"", s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; strv2[i]; i++) {
|
|
|
|
|
gs_free char *s = g_strescape (strv2[i], NULL);
|
|
|
|
|
|
|
|
|
|
g_print (">>> [%s] strv2[%d] = \"%s\"\n", topic, i, s);
|
|
|
|
|
if (i > 0)
|
|
|
|
|
nm_str_buf_append_c (&s2, ' ');
|
|
|
|
|
nm_str_buf_append_printf (&s2, "\"%s\"", s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nm_str_buf_maybe_expand (&s1, 1, FALSE);
|
|
|
|
|
nm_str_buf_maybe_expand (&s2, 1, FALSE);
|
|
|
|
|
|
|
|
|
|
str_escaped = g_strescape (str, NULL);
|
|
|
|
|
g_error ("compared words differs: [%s] str=\"%s\"; strv1=%s; strv2=%s", topic, str_escaped, nm_str_buf_get_str (&s1), nm_str_buf_get_str (&s2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_strsplit_quoted_test (const char *str,
|
|
|
|
|
const char *const*strv_expected)
|
|
|
|
|
{
|
|
|
|
|
gs_strfreev char **strv_systemd = NULL;
|
|
|
|
|
gs_strfreev char **strv_nm = NULL;
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
|
|
g_assert (str);
|
|
|
|
|
|
|
|
|
|
r = nmtst_systemd_extract_first_word_all (str, &strv_systemd);
|
|
|
|
|
g_assert_cmpint (r, ==, 1);
|
|
|
|
|
g_assert (strv_systemd);
|
|
|
|
|
|
|
|
|
|
if (!strv_expected)
|
|
|
|
|
strv_expected = (const char *const*) strv_systemd;
|
|
|
|
|
|
|
|
|
|
_strsplit_quoted_assert_strv ("systemd", str, strv_expected, (const char *const*) strv_systemd);
|
|
|
|
|
|
|
|
|
|
strv_nm = nm_utils_strsplit_quoted (str);
|
|
|
|
|
g_assert (strv_nm);
|
|
|
|
|
_strsplit_quoted_assert_strv ("nm", str, strv_expected, (const char *const*) strv_nm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_strsplit_quoted (void)
|
|
|
|
|
{
|
|
|
|
|
int i_run;
|
|
|
|
|
|
|
|
|
|
_strsplit_quoted_test ("", NM_MAKE_STRV ());
|
|
|
|
|
_strsplit_quoted_test (" ", NM_MAKE_STRV ());
|
|
|
|
|
_strsplit_quoted_test (" ", NM_MAKE_STRV ());
|
|
|
|
|
_strsplit_quoted_test (" \t", NM_MAKE_STRV ());
|
|
|
|
|
_strsplit_quoted_test ("a b", NM_MAKE_STRV ("a", "b"));
|
|
|
|
|
_strsplit_quoted_test ("a\\ b", NM_MAKE_STRV ("a b"));
|
|
|
|
|
_strsplit_quoted_test (" a\\ \"b\"", NM_MAKE_STRV ("a b"));
|
|
|
|
|
_strsplit_quoted_test (" a\\ \"b\" c \n", NM_MAKE_STRV ("a b", "c"));
|
|
|
|
|
|
|
|
|
|
for (i_run = 0; i_run < 1000; i_run++) {
|
|
|
|
|
gs_strfreev char **strv = NULL;
|
|
|
|
|
gs_free char *str = NULL;
|
|
|
|
|
|
|
|
|
|
/* create random strv array and join them carefully so that splitting
|
|
|
|
|
* them will yield the original value. */
|
|
|
|
|
strv = _strsplit_quoted_create_strv_rand ();
|
|
|
|
|
str = _strsplit_quoted_join_strv_rand ((const char *const*) strv);
|
|
|
|
|
_strsplit_quoted_test (str, (const char *const*) strv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create random words and assert that systemd and our implementation can
|
|
|
|
|
* both split them (and in the exact same way). */
|
|
|
|
|
for (i_run = 0; i_run < 1000; i_run++) {
|
|
|
|
|
gs_free char *s = _strsplit_quoted_create_str_rand (nmtst_get_rand_uint32 () % 150);
|
|
|
|
|
|
|
|
|
|
_strsplit_quoted_test (s, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-06 17:17:49 +01:00
|
|
|
|
2020-01-09 10:34:30 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2020-06-21 21:59:32 +02:00
|
|
|
static void
|
|
|
|
|
_do_wifi_ghz_freqs (const guint *freqs, const char *band)
|
|
|
|
|
{
|
|
|
|
|
int len;
|
|
|
|
|
int j;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
g_assert (NM_IN_STRSET (band, "a", "bg"));
|
|
|
|
|
g_assert (freqs);
|
|
|
|
|
g_assert (freqs[0] != 0);
|
|
|
|
|
|
|
|
|
|
for (i = 0; freqs[i]; i++) {
|
|
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
|
g_assert (freqs[i] != freqs[j]);
|
|
|
|
|
}
|
|
|
|
|
len = i;
|
|
|
|
|
|
|
|
|
|
g_assert (nm_utils_wifi_freq_to_channel (0) == 0);
|
|
|
|
|
g_assert (nm_utils_wifi_channel_to_freq (0, "bg") == -1);
|
|
|
|
|
g_assert (nm_utils_wifi_channel_to_freq (0, "foo") == 0);
|
|
|
|
|
g_assert (!nm_utils_wifi_is_channel_valid (0, "bg"));
|
|
|
|
|
g_assert (!nm_utils_wifi_is_channel_valid (0, "foo"));
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
guint freq = freqs[i];
|
|
|
|
|
guint32 chan;
|
|
|
|
|
guint32 freq2;
|
|
|
|
|
|
|
|
|
|
chan = nm_utils_wifi_freq_to_channel (freq);
|
|
|
|
|
g_assert (chan != 0);
|
|
|
|
|
|
|
|
|
|
freq2 = nm_utils_wifi_channel_to_freq (chan, band);
|
|
|
|
|
g_assert (freq2 == freq);
|
|
|
|
|
|
|
|
|
|
g_assert (nm_utils_wifi_is_channel_valid (chan, band));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert (freqs[len] == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_nm_utils_wifi_ghz_freqs (void)
|
|
|
|
|
{
|
|
|
|
|
_do_wifi_ghz_freqs (nm_utils_wifi_2ghz_freqs (), "bg");
|
|
|
|
|
_do_wifi_ghz_freqs (nm_utils_wifi_5ghz_freqs (), "a");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2014-07-24 08:53:33 -04:00
|
|
|
NMTST_DEFINE ();
|
|
|
|
|
|
|
|
|
|
int main (int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
nmtst_init (&argc, &argv, TRUE);
|
|
|
|
|
|
2019-03-20 10:43:54 +01:00
|
|
|
g_test_add_func ("/core/general/test_nm_ascii_spaces", test_nm_ascii_spaces);
|
2017-10-13 14:00:22 +02:00
|
|
|
g_test_add_func ("/core/general/test_nm_hash", test_nm_hash);
|
2017-08-15 12:32:37 +02:00
|
|
|
g_test_add_func ("/core/general/test_nm_g_slice_free_fcn", test_nm_g_slice_free_fcn);
|
2017-07-08 13:30:00 +02:00
|
|
|
g_test_add_func ("/core/general/test_c_list_sort", test_c_list_sort);
|
shared: add NMDedupMultiIndex "nm-dedup-multi.h"
Add the NMDedupMultiIndex cache. It basically tracks
objects as doubly linked list. With the addition that
each object and the list head is indexed by a hash table.
Also, it supports tracking multiple distinct lists,
all indexed by the idx-type instance.
It also deduplicates the tracked objects and shares them.
- the objects that can be put into the cache must be immutable
and ref-counted. That is, the cache will deduplicate them
and share the reference. Also, as these objects are immutable
and ref-counted, it is safe that users outside the cache
own them too (as long as they keep them immutable and manage
their reference properly).
The deduplication uses obj_id_hash_func() and obj_id_equal_func().
These functions must cover *every* aspect of the objects when
comparing equality. For example nm_platform_ip4_route_cmp()
would be a function that qualifies as obj_id_equal_func().
The cache creates references to the objects as needed and
gives them back. This happens via obj_get_ref() and
obj_put_ref(). Note that obj_get_ref() is free to create
a new object, for example to convert a stack-allocated object
to a (ref-counted) heap allocated one.
The deduplication process creates NMDedupIndexBox instances
which are the ref-counted entity. In principle, the objects
themself don't need to be ref-counted as that is handled by
the boxing instance.
- The cache doesn't only do deduplication. It is a multi-index,
meaning, callers add objects using a index handle NMDedupMultiIdxType.
The NMDedupMultiIdxType instance is the access handle to lookup
the list and objects inside the cache. Note that the idx-type
instance may partition the objects in distinct lists.
For all operations there are cross-references and hash table lookups.
Hence, every operation of this data structure is O(1) and the memory
overhead for an index tracking an object is constant.
The cache preserves ordering (due to linked list) and exposes the list
as public API. This allows users to iterate the list without any
additional copying of elements.
2017-06-04 22:43:21 +02:00
|
|
|
g_test_add_func ("/core/general/test_dedup_multi", test_dedup_multi);
|
2017-05-16 18:50:21 +02:00
|
|
|
g_test_add_func ("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe);
|
2017-09-14 19:14:01 +02:00
|
|
|
g_test_add_func ("/core/general/test_nm_utils_strsplit_set", test_nm_utils_strsplit_set);
|
2020-03-27 09:29:43 +01:00
|
|
|
g_test_add_func ("/core/general/test_nm_utils_escaped_tokens", test_nm_utils_escaped_tokens);
|
2015-08-12 13:04:12 +02:00
|
|
|
g_test_add_func ("/core/general/test_nm_in_set", test_nm_in_set);
|
2016-02-11 16:53:06 +01:00
|
|
|
g_test_add_func ("/core/general/test_nm_in_strset", test_nm_in_strset);
|
2014-08-19 00:49:43 +02:00
|
|
|
g_test_add_func ("/core/general/test_setting_vpn_items", test_setting_vpn_items);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_vpn_update_secrets", test_setting_vpn_update_secrets);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_vpn_modify_during_foreach", test_setting_vpn_modify_during_foreach);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_ip4_config_labels", test_setting_ip4_config_labels);
|
2014-11-14 11:46:19 -05:00
|
|
|
g_test_add_func ("/core/general/test_setting_ip4_config_address_data", test_setting_ip4_config_address_data);
|
2017-02-15 15:06:24 +01:00
|
|
|
g_test_add_func ("/core/general/test_setting_ip_route_attributes", test_setting_ip_route_attributes);
|
2014-08-19 00:49:43 +02:00
|
|
|
g_test_add_func ("/core/general/test_setting_gsm_apn_spaces", test_setting_gsm_apn_spaces);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_gsm_apn_bad_chars", test_setting_gsm_apn_bad_chars);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_gsm_apn_underscore", test_setting_gsm_apn_underscore);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_gsm_without_number", test_setting_gsm_without_number);
|
2015-10-01 12:44:28 -05:00
|
|
|
g_test_add_func ("/core/general/test_setting_gsm_sim_operator_id", test_setting_gsm_sim_operator_id);
|
2014-08-06 19:35:31 -04:00
|
|
|
g_test_add_func ("/core/general/test_setting_to_dbus_all", test_setting_to_dbus_all);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_to_dbus_no_secrets", test_setting_to_dbus_no_secrets);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_to_dbus_only_secrets", test_setting_to_dbus_only_secrets);
|
2014-07-30 10:57:45 -04:00
|
|
|
g_test_add_func ("/core/general/test_setting_to_dbus_transform", test_setting_to_dbus_transform);
|
2014-06-26 16:47:46 -04:00
|
|
|
g_test_add_func ("/core/general/test_setting_to_dbus_enum", test_setting_to_dbus_enum);
|
2014-08-19 00:49:43 +02:00
|
|
|
g_test_add_func ("/core/general/test_setting_compare_id", test_setting_compare_id);
|
libnm: fix comparing NMSettingIPConfig for address and route properties
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
2016-06-11 00:31:26 +02:00
|
|
|
g_test_add_func ("/core/general/test_setting_compare_addresses", test_setting_compare_addresses);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_compare_routes", test_setting_compare_routes);
|
device: extend MAC address handling including randomization for ethernet and wifi
Extend the "ethernet.cloned-mac-address" and "wifi.cloned-mac-address"
settings. Instead of specifying an explicit MAC address, the additional
special values "permanent", "preserve", "random", "random-bia", "stable" and
"stable-bia" are supported.
"permanent" means to use the permanent hardware address. Previously that
was the default if no explict cloned-mac-address was set. The default is
thus still "permanent", but it can be overwritten by global
configuration.
"preserve" means not to configure the MAC address when activating the
device. That was actually the default behavior before introducing MAC
address handling with commit 1b49f941a69af910b0e68530be7339e8053068e5.
"random" and "random-bia" use a randomized MAC address for each
connection. "stable" and "stable-bia" use a generated, stable
address based on some token. The "bia" suffix says to generate a
burned-in address. The stable method by default uses as token the
connection UUID, but the token can be explicitly choosen via
"stable:<TOKEN>" and "stable-bia:<TOKEN>".
On a D-Bus level, the "cloned-mac-address" is a bytestring and thus
cannot express the new forms. It is replaced by the new
"assigned-mac-address" field. For the GObject property, libnm's API,
nmcli, keyfile, etc. the old name "cloned-mac-address" is still used.
Deprecating the old field seems more complicated then just extending
the use of the existing "cloned-mac-address" field, although the name
doesn't match well with the extended meaning.
There is some overlap with the "wifi.mac-address-randomization" setting.
https://bugzilla.gnome.org/show_bug.cgi?id=705545
https://bugzilla.gnome.org/show_bug.cgi?id=708820
https://bugzilla.gnome.org/show_bug.cgi?id=758301
2016-05-24 15:57:16 +02:00
|
|
|
g_test_add_func ("/core/general/test_setting_compare_wired_cloned_mac_address", test_setting_compare_wired_cloned_mac_address);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_compare_wirless_cloned_mac_address", test_setting_compare_wireless_cloned_mac_address);
|
2014-11-18 14:20:12 +01:00
|
|
|
g_test_add_func ("/core/general/test_setting_compare_timestamp", test_setting_compare_timestamp);
|
2015-09-03 18:15:46 +02:00
|
|
|
#define ADD_FUNC(name, func, secret_flags, comp_flags, remove_secret) \
|
|
|
|
|
g_test_add_data_func_full ("/core/general/" G_STRINGIFY (func) "_" name, \
|
2014-08-19 00:49:43 +02:00
|
|
|
test_data_compare_secrets_new (secret_flags, comp_flags, remove_secret), \
|
|
|
|
|
func, g_free)
|
2015-09-03 18:15:46 +02:00
|
|
|
ADD_FUNC ("agent_owned", test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_AGENT_OWNED, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, TRUE);
|
|
|
|
|
ADD_FUNC ("not_saved", test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_NOT_SAVED, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, TRUE);
|
|
|
|
|
ADD_FUNC ("secrets", test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, TRUE);
|
|
|
|
|
ADD_FUNC ("exact", test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_EXACT, FALSE);
|
|
|
|
|
ADD_FUNC ("agent_owned", test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_AGENT_OWNED, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, TRUE);
|
|
|
|
|
ADD_FUNC ("not_saved", test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_NOT_SAVED, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, TRUE);
|
|
|
|
|
ADD_FUNC ("secrets", test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, TRUE);
|
|
|
|
|
ADD_FUNC ("exact", test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_EXACT, FALSE);
|
2014-08-19 00:49:43 +02:00
|
|
|
g_test_add_func ("/core/general/test_setting_old_uuid", test_setting_old_uuid);
|
|
|
|
|
|
2014-08-06 19:35:31 -04:00
|
|
|
g_test_add_func ("/core/general/test_connection_to_dbus_setting_name", test_connection_to_dbus_setting_name);
|
2014-07-29 18:42:02 -04:00
|
|
|
g_test_add_func ("/core/general/test_connection_to_dbus_deprecated_props", test_connection_to_dbus_deprecated_props);
|
2014-08-06 19:35:31 -04:00
|
|
|
g_test_add_func ("/core/general/test_setting_new_from_dbus", test_setting_new_from_dbus);
|
2014-07-30 10:57:45 -04:00
|
|
|
g_test_add_func ("/core/general/test_setting_new_from_dbus_transform", test_setting_new_from_dbus_transform);
|
2014-06-26 16:47:46 -04:00
|
|
|
g_test_add_func ("/core/general/test_setting_new_from_dbus_enum", test_setting_new_from_dbus_enum);
|
2015-01-15 12:19:06 -05:00
|
|
|
g_test_add_func ("/core/general/test_setting_new_from_dbus_bad", test_setting_new_from_dbus_bad);
|
2014-08-19 00:49:43 +02:00
|
|
|
g_test_add_func ("/core/general/test_connection_replace_settings", test_connection_replace_settings);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_replace_settings_from_connection", test_connection_replace_settings_from_connection);
|
2014-08-22 10:14:38 -04:00
|
|
|
g_test_add_func ("/core/general/test_connection_replace_settings_bad", test_connection_replace_settings_bad);
|
2014-08-06 19:35:31 -04:00
|
|
|
g_test_add_func ("/core/general/test_connection_new_from_dbus", test_connection_new_from_dbus);
|
2014-08-19 00:49:43 +02:00
|
|
|
g_test_add_func ("/core/general/test_connection_normalize_virtual_iface_name", test_connection_normalize_virtual_iface_name);
|
2014-12-01 13:03:23 +01:00
|
|
|
g_test_add_func ("/core/general/test_connection_normalize_uuid", test_connection_normalize_uuid);
|
2014-08-19 00:49:43 +02:00
|
|
|
g_test_add_func ("/core/general/test_connection_normalize_type", test_connection_normalize_type);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_normalize_slave_type_1", test_connection_normalize_slave_type_1);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_normalize_slave_type_2", test_connection_normalize_slave_type_2);
|
2014-08-13 02:35:26 +02:00
|
|
|
g_test_add_func ("/core/general/test_connection_normalize_infiniband_mtu", test_connection_normalize_infiniband_mtu);
|
2016-04-22 13:45:08 +02:00
|
|
|
g_test_add_func ("/core/general/test_connection_normalize_gateway_never_default", test_connection_normalize_gateway_never_default);
|
2016-07-01 17:05:42 +02:00
|
|
|
g_test_add_func ("/core/general/test_connection_normalize_may_fail", test_connection_normalize_may_fail);
|
2016-09-12 18:51:00 +02:00
|
|
|
g_test_add_func ("/core/general/test_connection_normalize_shared_addresses", test_connection_normalize_shared_addresses);
|
2017-10-27 14:30:18 +02:00
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/1", GUINT_TO_POINTER (1), test_connection_normalize_ovs_interface_type_system);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/2", GUINT_TO_POINTER (2), test_connection_normalize_ovs_interface_type_system);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/3", GUINT_TO_POINTER (3), test_connection_normalize_ovs_interface_type_system);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/4", GUINT_TO_POINTER (4), test_connection_normalize_ovs_interface_type_system);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/5", GUINT_TO_POINTER (5), test_connection_normalize_ovs_interface_type_system);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/6", GUINT_TO_POINTER (6), test_connection_normalize_ovs_interface_type_system);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_system/7", GUINT_TO_POINTER (7), test_connection_normalize_ovs_interface_type_system);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/1", GUINT_TO_POINTER (1), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/2", GUINT_TO_POINTER (2), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/3", GUINT_TO_POINTER (3), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/4", GUINT_TO_POINTER (4), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/5", GUINT_TO_POINTER (5), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/6", GUINT_TO_POINTER (6), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/7", GUINT_TO_POINTER (7), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/8", GUINT_TO_POINTER (8), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/9", GUINT_TO_POINTER (9), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/10", GUINT_TO_POINTER (10), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/11", GUINT_TO_POINTER (11), test_connection_normalize_ovs_interface_type_ovs_interface);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_normalize_ovs_interface_type_ovs_interface/12", GUINT_TO_POINTER (12), test_connection_normalize_ovs_interface_type_ovs_interface);
|
2014-08-19 00:49:43 +02:00
|
|
|
|
2020-02-06 17:17:49 +01:00
|
|
|
g_test_add_data_func ("/core/general/test_connection_ovs_ifname/1", GUINT_TO_POINTER (1), test_connection_ovs_ifname);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_ovs_ifname/2", GUINT_TO_POINTER (2), test_connection_ovs_ifname);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_ovs_ifname/3", GUINT_TO_POINTER (3), test_connection_ovs_ifname);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_ovs_ifname/4", GUINT_TO_POINTER (4), test_connection_ovs_ifname);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_ovs_ifname/5", GUINT_TO_POINTER (5), test_connection_ovs_ifname);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_connection_ovs_ifname/6", GUINT_TO_POINTER (6), test_connection_ovs_ifname);
|
|
|
|
|
|
2014-08-19 00:49:43 +02:00
|
|
|
g_test_add_func ("/core/general/test_setting_connection_permissions_helpers", test_setting_connection_permissions_helpers);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_connection_permissions_property", test_setting_connection_permissions_property);
|
|
|
|
|
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_compare_same", test_connection_compare_same);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_compare_key_only_in_a", test_connection_compare_key_only_in_a);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_compare_setting_only_in_a", test_connection_compare_setting_only_in_a);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_compare_key_only_in_b", test_connection_compare_key_only_in_b);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_compare_setting_only_in_b", test_connection_compare_setting_only_in_b);
|
|
|
|
|
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_diff_a_only", test_connection_diff_a_only);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_diff_same", test_connection_diff_same);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_diff_different", test_connection_diff_different);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_diff_no_secrets", test_connection_diff_no_secrets);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_diff_inferrable", test_connection_diff_inferrable);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_good_base_types", test_connection_good_base_types);
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_bad_base_types", test_connection_bad_base_types);
|
|
|
|
|
|
|
|
|
|
g_test_add_func ("/core/general/test_hwaddr_aton_ether_normal", test_hwaddr_aton_ether_normal);
|
|
|
|
|
g_test_add_func ("/core/general/test_hwaddr_aton_ib_normal", test_hwaddr_aton_ib_normal);
|
|
|
|
|
g_test_add_func ("/core/general/test_hwaddr_aton_no_leading_zeros", test_hwaddr_aton_no_leading_zeros);
|
|
|
|
|
g_test_add_func ("/core/general/test_hwaddr_aton_malformed", test_hwaddr_aton_malformed);
|
|
|
|
|
g_test_add_func ("/core/general/test_hwaddr_equal", test_hwaddr_equal);
|
2014-10-28 08:32:25 -04:00
|
|
|
g_test_add_func ("/core/general/test_hwaddr_canonical", test_hwaddr_canonical);
|
2014-08-19 00:49:43 +02:00
|
|
|
|
|
|
|
|
g_test_add_func ("/core/general/test_ip4_prefix_to_netmask", test_ip4_prefix_to_netmask);
|
|
|
|
|
g_test_add_func ("/core/general/test_ip4_netmask_to_prefix", test_ip4_netmask_to_prefix);
|
|
|
|
|
|
|
|
|
|
g_test_add_func ("/core/general/test_connection_changed_signal", test_connection_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_connection_changed_signal", test_setting_connection_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_bond_changed_signal", test_setting_bond_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_ip4_changed_signal", test_setting_ip4_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_ip6_changed_signal", test_setting_ip6_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_vlan_changed_signal", test_setting_vlan_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_vpn_changed_signal", test_setting_vpn_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_wired_changed_signal", test_setting_wired_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_wireless_changed_signal", test_setting_wireless_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_wireless_security_changed_signal", test_setting_wireless_security_changed_signal);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_802_1x_changed_signal", test_setting_802_1x_changed_signal);
|
2014-10-20 21:30:56 -04:00
|
|
|
g_test_add_func ("/core/general/test_setting_ip4_gateway", test_setting_ip4_gateway);
|
|
|
|
|
g_test_add_func ("/core/general/test_setting_ip6_gateway", test_setting_ip6_gateway);
|
2015-05-20 17:53:25 +02:00
|
|
|
g_test_add_func ("/core/general/test_setting_compare_default_strv", test_setting_compare_default_strv);
|
2017-03-24 12:41:04 +01:00
|
|
|
g_test_add_func ("/core/general/test_setting_user_data", test_setting_user_data);
|
2014-08-19 00:49:43 +02:00
|
|
|
|
2018-12-29 13:01:28 +01:00
|
|
|
g_test_add_func ("/core/general/test_sock_addr_endpoint", test_sock_addr_endpoint);
|
|
|
|
|
|
2014-11-06 17:51:09 -06:00
|
|
|
g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin);
|
2017-10-05 14:27:24 +02:00
|
|
|
g_test_add_func ("/core/general/nm_strquote", test_nm_strquote);
|
2014-11-28 14:26:24 +01:00
|
|
|
g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string);
|
2015-02-22 20:15:52 +01:00
|
|
|
g_test_add_func ("/core/general/_nm_utils_uuid_generate_from_strings", test_nm_utils_uuid_generate_from_strings);
|
2014-11-06 17:51:09 -06:00
|
|
|
|
2015-02-22 11:54:03 +01:00
|
|
|
g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
|
2015-05-12 09:24:05 +02:00
|
|
|
g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
|
2018-08-01 11:03:02 +02:00
|
|
|
g_test_add_func ("/core/general/nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
|
|
|
|
|
g_test_add_func ("/core/general/nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates);
|
2015-05-22 18:52:22 +02:00
|
|
|
g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey);
|
2017-04-06 09:47:05 +02:00
|
|
|
g_test_add_func ("/core/general/nm_ptrarray_len", test_nm_ptrarray_len);
|
2015-02-22 11:54:03 +01:00
|
|
|
|
2015-04-01 11:47:42 +02:00
|
|
|
g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate);
|
|
|
|
|
g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx);
|
2016-03-11 13:17:24 +01:00
|
|
|
g_test_add_func ("/core/general/_nm_utils_validate_json", test_nm_utils_check_valid_json);
|
|
|
|
|
g_test_add_func ("/core/general/_nm_utils_team_config_equal", test_nm_utils_team_config_equal);
|
2015-06-04 15:05:33 +02:00
|
|
|
g_test_add_func ("/core/general/test_nm_utils_enum", test_nm_utils_enum);
|
2016-09-26 16:59:30 +02:00
|
|
|
g_test_add_func ("/core/general/nm-set-out", test_nm_set_out);
|
2017-02-15 15:06:24 +01:00
|
|
|
g_test_add_func ("/core/general/route_attributes/parse", test_route_attributes_parse);
|
|
|
|
|
g_test_add_func ("/core/general/route_attributes/format", test_route_attributes_format);
|
2019-11-27 13:13:48 +01:00
|
|
|
g_test_add_func ("/core/general/test_variant_attribute_spec", test_variant_attribute_spec);
|
2015-06-04 15:05:33 +02:00
|
|
|
|
2018-05-25 15:38:21 +02:00
|
|
|
g_test_add_func ("/core/general/get_start_time_for_pid", test_get_start_time_for_pid);
|
2018-07-10 08:45:39 +02:00
|
|
|
g_test_add_func ("/core/general/test_nm_va_args_macros", test_nm_va_args_macros);
|
libnm, cli, ifcfg-rh: add NMSettingEthtool setting
Note that in NetworkManager API (D-Bus, libnm, and nmcli),
the features are called "feature-xyz". The "feature-" prefix
is used, because NMSettingEthtool possibly will gain support
for options that are not only -K|--offload|--features, for
example -C|--coalesce.
The "xzy" suffix is either how ethtool utility calls the feature
("tso", "rx"). Or, if ethtool utility specifies no alias for that
feature, it's the name from kernel's ETH_SS_FEATURES ("tx-tcp6-segmentation").
If possible, we prefer ethtool utility's naming.
Also note, how the features "feature-sg", "feature-tso", and
"feature-tx" actually refer to multiple underlying kernel features
at once. This too follows what ethtool utility does.
The functionality is not yet implemented server-side.
2018-07-16 23:37:55 +02:00
|
|
|
g_test_add_func ("/core/general/test_ethtool_offload", test_ethtool_offload);
|
2018-07-10 08:45:39 +02:00
|
|
|
|
shared: add nm_utils_g_main_context_create_integrate_source() for integrating a GMainContext in another
We will rework NMClient entirely. Then, the synchronous initialization will also use
the asynchronous code paths. The difference will be that with synchronous initialization,
all D-Bus interaction will be done with an internal GMainContext as current thread default,
and that internal context will run until initialization completes.
Note that even after initialization completes, it cannot be swapped back to the user's
(outer) GMainContext. That is because contexts are essentially the queue for our
D-Bus events, and we cannot swap from one queue to the other in a race
free manner (or a full resync). In other words, the two contexts are not in sync,
so after using the internal context NMClient needs to stick to that (at least, until
the name owner gets lost, which gives an opportunity to resync and switch back to the
user's main context).
We thus need to hook the internal (inner) GMainContext with the user's (outer) context,
so when the user iterates the outer context, events on the inner context get dispatched.
Add nm_utils_g_main_context_create_integrate_source() to create such a GSource for
integrating two contexts.
Note that the use-case here is limited: the integrated, inner main context must
not be explicitly iterated except from being dispatched by the integrating
source. Otherwise, you'd get recursive runs, possible deadlocks and general
ugliness. NMClient must show restrain how to use the inner context while it is
integrated.
2019-11-02 16:55:43 +01:00
|
|
|
g_test_add_data_func ("/core/general/test_integrate_maincontext/1", GUINT_TO_POINTER (1), test_integrate_maincontext);
|
|
|
|
|
g_test_add_data_func ("/core/general/test_integrate_maincontext/2", GUINT_TO_POINTER (2), test_integrate_maincontext);
|
|
|
|
|
|
2020-01-09 10:34:30 +01:00
|
|
|
g_test_add_func ("/core/general/test_nm_ip_addr_zero", test_nm_ip_addr_zero);
|
2020-06-21 21:59:32 +02:00
|
|
|
g_test_add_func ("/core/general/test_nm_utils_wifi_ghz_freqs", test_nm_utils_wifi_ghz_freqs);
|
2020-01-09 10:34:30 +01:00
|
|
|
|
2020-06-22 19:43:35 +02:00
|
|
|
g_test_add_func ("/core/general/test_strsplit_quoted", test_strsplit_quoted);
|
|
|
|
|
|
2014-08-19 00:49:43 +02:00
|
|
|
return g_test_run ();
|
2014-07-24 08:53:33 -04:00
|
|
|
}
|