core: refactor evaluation of device's match-spec

Previously, we would have different functions like
  - nm_match_spec_device_type()
  - nm_match_spec_hwaddr()
  - nm_match_spec_s390_subchannels()
  - nm_match_spec_interface_name()
which all would handle one type of match-spec.

So, to get the overall result whether the arguments
match or not, nm_device_spec_match_list() had to stich
them together and iterate the list multiple times.

Refactor the code to have one nm_match_spec_device()
function that gets all relevant paramters.

The upside is:

  - the logic how to evaluate the match-spec is all at one place
    (match_device_eval()) instead of spread over multiple
    functions.

  - It requires iterating the list at most twice. Twice, because
    we do a fast pre-search for "*".

One downside could be, that we have to pass all 4 arguments
for the evaluation, even if the might no be needed. That is,
because "nm-core-utils.c" shall be independend from NMDevice, it
cannot receive a device instance to get the parameters as needed.
As we would add new match-types, the argument list would grow.
However, all arguments are cached and fetching them from the
device's private data is very cheap.

(cherry picked from commit b957403efd)
This commit is contained in:
Thomas Haller 2017-01-20 19:50:25 +01:00
parent 2e8af781c5
commit ba1cc6a288
7 changed files with 396 additions and 381 deletions

View file

@ -1543,19 +1543,12 @@ new_default_connection (NMDevice *self)
return connection;
}
static NMMatchSpecMatchType
spec_match_list (NMDevice *device, const GSList *specs)
static const char *
get_s390_subchannels (NMDevice *device)
{
NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m;
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device);
nm_assert (NM_IS_DEVICE_ETHERNET (device));
if (priv->subchannels)
matched = nm_match_spec_s390_subchannels (specs, priv->subchannels);
if (matched != NM_MATCH_SPEC_NEG_MATCH) {
m = NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->spec_match_list (device, specs);
matched = MAX (matched, m);
}
return matched;
return NM_DEVICE_ETHERNET_GET_PRIVATE ((NMDeviceEthernet *) device)->subchannels;
}
static void
@ -1746,7 +1739,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass)
parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start;
parent_class->get_configured_mtu = get_configured_mtu;
parent_class->deactivate = deactivate;
parent_class->spec_match_list = spec_match_list;
parent_class->get_s390_subchannels = get_s390_subchannels;
parent_class->update_connection = update_connection;
parent_class->carrier_changed = carrier_changed;
parent_class->link_changed = link_changed;

View file

@ -12861,42 +12861,19 @@ nm_device_get_initial_hw_address (NMDevice *self)
gboolean
nm_device_spec_match_list (NMDevice *self, const GSList *specs)
{
NMDeviceClass *klass;
NMMatchSpecMatchType m;
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
if (!specs)
return FALSE;
klass = NM_DEVICE_GET_CLASS (self);
return NM_DEVICE_GET_CLASS (self)->spec_match_list (self, specs) == NM_MATCH_SPEC_MATCH;
}
static NMMatchSpecMatchType
spec_match_list (NMDevice *self, const GSList *specs)
{
NMMatchSpecMatchType matched = NM_MATCH_SPEC_NO_MATCH, m;
const GSList *iter;
const char *hw_addr_perm;
for (iter = specs; iter; iter = g_slist_next (iter)) {
if (!strcmp ((const char *) iter->data, "*")) {
matched = NM_MATCH_SPEC_MATCH;
break;
}
}
hw_addr_perm = nm_device_get_permanent_hw_address (self);
if (hw_addr_perm) {
m = nm_match_spec_hwaddr (specs, hw_addr_perm);
matched = MAX (matched, m);
}
if (matched != NM_MATCH_SPEC_NEG_MATCH) {
m = nm_match_spec_interface_name (specs, nm_device_get_iface (self));
matched = MAX (matched, m);
}
if (matched != NM_MATCH_SPEC_NEG_MATCH) {
m = nm_match_spec_device_type (specs, nm_device_get_type_description (self));
matched = MAX (matched, m);
}
return matched;
m = nm_match_spec_device (specs,
nm_device_get_iface (self),
nm_device_get_type_description (self),
nm_device_get_permanent_hw_address (self),
klass->get_s390_subchannels ? klass->get_s390_subchannels (self) : NULL);
return m == NM_MATCH_SPEC_MATCH;
}
/*****************************************************************************/
@ -13461,7 +13438,6 @@ nm_device_class_init (NMDeviceClass *klass)
klass->have_any_ready_slaves = have_any_ready_slaves;
klass->get_type_description = get_type_description;
klass->spec_match_list = spec_match_list;
klass->can_auto_connect = can_auto_connect;
klass->check_connection_compatible = check_connection_compatible;
klass->check_connection_available = check_connection_available;

View file

@ -295,7 +295,7 @@ typedef struct {
const char *(*get_type_description) (NMDevice *self);
NMMatchSpecMatchType (* spec_match_list) (NMDevice *self, const GSList *specs);
const char *(*get_s390_subchannels) (NMDevice *self);
/* Update the connection with currently configured L2 settings */
void (* update_connection) (NMDevice *device, NMConnection *connection);

View file

@ -529,9 +529,9 @@ ignore_config_snippet (GKeyFile *keyfile, gboolean is_base_config)
/* second, interpret the value as match-spec. */
specs = nm_config_get_match_spec (keyfile, NM_CONFIG_KEYFILE_GROUP_CONFIG, NM_CONFIG_KEYFILE_KEY_CONFIG_ENABLE, NULL);
match_type = nm_match_spec_match_config (specs,
_nm_config_match_nm_version,
_nm_config_match_env);
match_type = nm_match_spec_config (specs,
_nm_config_match_nm_version,
_nm_config_match_env);
g_slist_free_full (specs, g_free);
return match_type != NM_MATCH_SPEC_MATCH;

View file

@ -1213,169 +1213,26 @@ nm_utils_read_link_absolute (const char *link_file, GError **error)
#define MATCH_TAG_CONFIG_NM_VERSION_MAX "nm-version-max:"
#define MATCH_TAG_CONFIG_ENV "env:"
#define _spec_has_prefix(pspec, tag) \
({ \
const char **_spec = (pspec); \
gboolean _has = FALSE; \
\
if (!g_ascii_strncasecmp (*_spec, (""tag), NM_STRLEN (tag))) { \
*_spec += NM_STRLEN (tag); \
_has = TRUE; \
} \
_has; \
})
static const char *
_match_except (const char *spec_str, gboolean *out_except)
{
if (!g_ascii_strncasecmp (spec_str, EXCEPT_TAG, NM_STRLEN (EXCEPT_TAG))) {
spec_str += NM_STRLEN (EXCEPT_TAG);
*out_except = TRUE;
} else
*out_except = FALSE;
return spec_str;
}
NMMatchSpecMatchType
nm_match_spec_device_type (const GSList *specs, const char *device_type)
{
const GSList *iter;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
if (!device_type || !*device_type)
return NM_MATCH_SPEC_NO_MATCH;
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec_str = iter->data;
gboolean except;
if (!spec_str || !*spec_str)
continue;
spec_str = _match_except (spec_str, &except);
if (g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)) != 0)
continue;
spec_str += NM_STRLEN (DEVICE_TYPE_TAG);
if (strcmp (spec_str, device_type) == 0) {
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
}
}
return match;
}
NMMatchSpecMatchType
nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
{
const GSList *iter;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
gsize hwaddr_len = 0;
guint8 hwaddr_bin[NM_UTILS_HWADDR_LEN_MAX];
nm_assert (nm_utils_hwaddr_valid (hwaddr, -1));
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec_str = iter->data;
gboolean except;
if (!spec_str || !*spec_str)
continue;
spec_str = _match_except (spec_str, &except);
if ( !g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, NM_STRLEN (INTERFACE_NAME_TAG))
|| !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))
|| !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)))
continue;
if (!g_ascii_strncasecmp (spec_str, MAC_TAG, NM_STRLEN (MAC_TAG)))
spec_str += NM_STRLEN (MAC_TAG);
else if (except)
continue;
if (G_UNLIKELY (hwaddr_len == 0)) {
if (!_nm_utils_hwaddr_aton (hwaddr, hwaddr_bin, sizeof (hwaddr_bin), &hwaddr_len))
g_return_val_if_reached (NM_MATCH_SPEC_NO_MATCH);
}
if (nm_utils_hwaddr_matches (spec_str, -1, hwaddr_bin, hwaddr_len)) {
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
}
}
return match;
}
NMMatchSpecMatchType
nm_match_spec_interface_name (const GSList *specs, const char *interface_name)
{
const GSList *iter;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
g_return_val_if_fail (interface_name != NULL, NM_MATCH_SPEC_NO_MATCH);
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec_str = iter->data;
gboolean use_pattern = FALSE;
gboolean except;
if (!spec_str || !*spec_str)
continue;
spec_str = _match_except (spec_str, &except);
if ( !g_ascii_strncasecmp (spec_str, MAC_TAG, NM_STRLEN (MAC_TAG))
|| !g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))
|| !g_ascii_strncasecmp (spec_str, DEVICE_TYPE_TAG, NM_STRLEN (DEVICE_TYPE_TAG)))
continue;
if (!g_ascii_strncasecmp (spec_str, INTERFACE_NAME_TAG, NM_STRLEN (INTERFACE_NAME_TAG))) {
spec_str += NM_STRLEN (INTERFACE_NAME_TAG);
if (spec_str[0] == '=')
spec_str += 1;
else {
if (spec_str[0] == '~')
spec_str += 1;
use_pattern=TRUE;
}
} else if (except)
continue;
if ( !strcmp (spec_str, interface_name)
|| (use_pattern && g_pattern_match_simple (spec_str, interface_name))) {
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
}
}
return match;
}
#define BUFSIZE 10
static gboolean
parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
match_s390_subchannels_parse (const char *s390_subchannels, guint32 *a, guint32 *b, guint32 *c)
{
const int BUFSIZE = 10;
long unsigned int tmp;
char buf[BUFSIZE + 1];
const char *p = subchannels;
const char *p = s390_subchannels;
int i = 0;
char *pa = NULL, *pb = NULL, *pc = NULL;
g_return_val_if_fail (subchannels != NULL, FALSE);
g_return_val_if_fail (a != NULL, FALSE);
g_return_val_if_fail (*a == 0, FALSE);
g_return_val_if_fail (b != NULL, FALSE);
g_return_val_if_fail (*b == 0, FALSE);
g_return_val_if_fail (c != NULL, FALSE);
g_return_val_if_fail (*c == 0, FALSE);
nm_assert (s390_subchannels);
nm_assert (a != NULL);
nm_assert (*a == 0);
nm_assert (b != NULL);
nm_assert (*b == 0);
nm_assert (c != NULL);
nm_assert (*c == 0);
/* sanity check */
if (!g_ascii_isxdigit (subchannels[0]))
if (!g_ascii_isxdigit (s390_subchannels[0]))
return FALSE;
/* Get the first channel */
@ -1421,47 +1278,225 @@ parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
return TRUE;
}
typedef struct {
const char *s390_subchannels;
gboolean is_parsed;
guint32 a;
guint32 b;
guint32 c;
} MatchS390SubchannelsData;
static gboolean
match_s390_subchannels_ensure (MatchS390SubchannelsData *data)
{
nm_assert (data);
if (data->is_parsed)
return !!data->s390_subchannels;
data->is_parsed = TRUE;
if (!match_s390_subchannels_parse (data->s390_subchannels,
&data->a, &data->b, &data->c)) {
data->s390_subchannels = NULL;
return FALSE;
}
return TRUE;
}
static gboolean
match_s390_subchannels_eval (const char *spec_str,
MatchS390SubchannelsData *data)
{
guint32 a, b, c;
if (!match_s390_subchannels_ensure (data))
return FALSE;
if (!match_s390_subchannels_parse (spec_str, &a, &b, &c))
return FALSE;
return data->a == a && data->b == b && data->c == c;
}
#define _MATCH_CHECK(spec_str, tag) \
({ \
gboolean _has = FALSE; \
\
if (!g_ascii_strncasecmp (spec_str, (""tag""), NM_STRLEN (tag))) { \
spec_str += NM_STRLEN (tag); \
_has = TRUE; \
} \
_has; \
})
static const char *
match_except (const char *spec_str, gboolean *out_except)
{
if (_MATCH_CHECK (spec_str, EXCEPT_TAG))
*out_except = TRUE;
else
*out_except = FALSE;
return spec_str;
}
static gboolean
match_device_eval (const char *spec_str,
gboolean allow_fuzzy,
const char *interface_name,
const char *device_type,
const guint8 *hwaddr_bin,
guint hwaddr_len,
MatchS390SubchannelsData *s390_subchannels_data)
{
nm_assert (!device_type || device_type[0]);
nm_assert (s390_subchannels_data);
if (_MATCH_CHECK (spec_str, DEVICE_TYPE_TAG)) {
return device_type
&& nm_streq (spec_str, device_type);
}
if (_MATCH_CHECK (spec_str, MAC_TAG)) {
return hwaddr_bin
&& nm_utils_hwaddr_matches (spec_str, -1, hwaddr_bin, hwaddr_len);
}
if (_MATCH_CHECK (spec_str, INTERFACE_NAME_TAG)) {
gboolean use_pattern = FALSE;
if (spec_str[0] == '=')
spec_str += 1;
else {
if (spec_str[0] == '~')
spec_str += 1;
use_pattern = TRUE;
}
if (interface_name) {
if (nm_streq (spec_str, interface_name))
return TRUE;
if (use_pattern && g_pattern_match_simple (spec_str, interface_name))
return TRUE;
}
return FALSE;
}
if (_MATCH_CHECK (spec_str, SUBCHAN_TAG))
return match_s390_subchannels_eval (spec_str, s390_subchannels_data);
if (allow_fuzzy) {
if ( hwaddr_bin
&& nm_utils_hwaddr_matches (spec_str, -1, hwaddr_bin, hwaddr_len))
return TRUE;
if ( interface_name
&& nm_streq (spec_str, interface_name))
return TRUE;
}
return FALSE;
}
NMMatchSpecMatchType
nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
nm_match_spec_device (const GSList *specs,
const char *interface_name,
const char *device_type,
const char *hwaddr,
const char *s390_subchannels)
{
const GSList *iter;
guint32 a = 0, b = 0, c = 0;
guint32 spec_a = 0, spec_b = 0, spec_c = 0;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
NMMatchSpecMatchType match;
const char *spec_str;
gboolean except;
guint hwaddr_len = 0;
const guint8 *hwaddr_bin = NULL;
guint8 hwaddr_bin_data[NM_UTILS_HWADDR_LEN_MAX];
MatchS390SubchannelsData s390_subchannels_data = {
.s390_subchannels = s390_subchannels,
};
g_return_val_if_fail (subchannels != NULL, NM_MATCH_SPEC_NO_MATCH);
nm_assert (!hwaddr || nm_utils_hwaddr_valid (hwaddr, -1));
if (!specs)
return NM_MATCH_SPEC_NO_MATCH;
if (!parse_subchannels (subchannels, &a, &b, &c))
return NM_MATCH_SPEC_NO_MATCH;
if (device_type && !*device_type)
device_type = NULL;
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec_str = iter->data;
gboolean except;
if (hwaddr) {
gsize l;
if (!_nm_utils_hwaddr_aton (hwaddr, hwaddr_bin_data, sizeof (hwaddr_bin_data), &l))
g_return_val_if_reached (NM_MATCH_SPEC_NO_MATCH);
hwaddr_bin = hwaddr_bin_data;
hwaddr_len = l;
}
/* first see if there is an all-match "*" */
for (iter = specs; iter; iter = iter->next) {
spec_str = iter->data;
if (!spec_str || spec_str[0] != '*' || spec_str[1] != '\0')
continue;
/* we have a match-all. See if there is a matching except
* which can still change the outcome... */
for (iter = specs; iter; iter = iter->next) {
spec_str = iter->data;
if (!spec_str || !*spec_str)
continue;
spec_str = match_except (spec_str, &except);
if (!except)
continue;
if (!match_device_eval (spec_str,
FALSE,
interface_name,
device_type,
hwaddr_bin,
hwaddr_len,
&s390_subchannels_data))
continue;
return NM_MATCH_SPEC_NEG_MATCH;
}
return NM_MATCH_SPEC_MATCH;
}
match = NM_MATCH_SPEC_NO_MATCH;
for (iter = specs; iter; iter = iter->next) {
spec_str = iter->data;
if (!spec_str || !*spec_str)
continue;
spec_str = _match_except (spec_str, &except);
spec_str = match_except (spec_str, &except);
if (!g_ascii_strncasecmp (spec_str, SUBCHAN_TAG, NM_STRLEN (SUBCHAN_TAG))) {
spec_str += NM_STRLEN (SUBCHAN_TAG);
if (parse_subchannels (spec_str, &spec_a, &spec_b, &spec_c)) {
if (a == spec_a && b == spec_b && c == spec_c) {
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
}
}
if ( !except
&& match == NM_MATCH_SPEC_MATCH) {
/* we have no "except-match" but already match. No need to evaluate
* the match, we cannot match stronger. */
continue;
}
if (!match_device_eval (spec_str,
!except,
interface_name,
device_type,
hwaddr_bin,
hwaddr_len,
&s390_subchannels_data))
continue;
if (except)
return NM_MATCH_SPEC_NEG_MATCH;
match = NM_MATCH_SPEC_MATCH;
}
return match;
}
static gboolean
_match_config_nm_version (const char *str, const char *tag, guint cur_nm_version)
match_config_eval (const char *str, const char *tag, guint cur_nm_version)
{
gs_free char *s_ver = NULL;
gs_strfreev char **s_ver_tokens = NULL;
@ -1524,7 +1559,7 @@ _match_config_nm_version (const char *str, const char *tag, guint cur_nm_version
}
NMMatchSpecMatchType
nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const char *env)
nm_match_spec_config (const GSList *specs, guint cur_nm_version, const char *env)
{
const GSList *iter;
NMMatchSpecMatchType match = NM_MATCH_SPEC_NO_MATCH;
@ -1540,15 +1575,15 @@ nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const cha
if (!spec_str || !*spec_str)
continue;
spec_str = _match_except (spec_str, &except);
spec_str = match_except (spec_str, &except);
if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION))
v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION, cur_nm_version);
else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN))
v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN, cur_nm_version);
else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX))
v_match = _match_config_nm_version (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX, cur_nm_version);
else if (_spec_has_prefix (&spec_str, MATCH_TAG_CONFIG_ENV))
if (_MATCH_CHECK (spec_str, MATCH_TAG_CONFIG_NM_VERSION))
v_match = match_config_eval (spec_str, MATCH_TAG_CONFIG_NM_VERSION, cur_nm_version);
else if (_MATCH_CHECK (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN))
v_match = match_config_eval (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MIN, cur_nm_version);
else if (_MATCH_CHECK (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX))
v_match = match_config_eval (spec_str, MATCH_TAG_CONFIG_NM_VERSION_MAX, cur_nm_version);
else if (_MATCH_CHECK (spec_str, MATCH_TAG_CONFIG_ENV))
v_match = env && env[0] && !strcmp (spec_str, env);
else
continue;
@ -1562,6 +1597,8 @@ nm_match_spec_match_config (const GSList *specs, guint cur_nm_version, const cha
return match;
}
#undef _MATCH_CHECK
/**
* nm_match_spec_split:
* @value: the string of device specs

View file

@ -142,11 +142,14 @@ typedef enum {
NM_MATCH_SPEC_NEG_MATCH = 2,
} NMMatchSpecMatchType;
NMMatchSpecMatchType nm_match_spec_device_type (const GSList *specs, const char *device_type);
NMMatchSpecMatchType nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
NMMatchSpecMatchType nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels);
NMMatchSpecMatchType nm_match_spec_interface_name (const GSList *specs, const char *interface_name);
NMMatchSpecMatchType nm_match_spec_match_config (const GSList *specs, guint nm_version, const char *env);
NMMatchSpecMatchType nm_match_spec_device (const GSList *specs,
const char *interface_name,
const char *device_type,
const char *hwaddr,
const char *s390_subchannels);
NMMatchSpecMatchType nm_match_spec_config (const GSList *specs,
guint nm_version,
const char *env);
GSList *nm_match_spec_split (const char *value);
char *nm_match_spec_join (GSList *specs);

View file

@ -955,6 +955,12 @@ test_connection_sort_autoconnect_priority (void)
/*****************************************************************************/
static NMMatchSpecMatchType
_test_match_device_interface (const GSList *specs, const char *interface_name)
{
return nm_match_spec_device (specs, interface_name, NULL, NULL, NULL);
}
static const char *_test_match_spec_all[] = {
"e",
"em",
@ -984,7 +990,7 @@ _test_match_spec_contains (const char **matches, const char *match)
}
static void
test_match_spec_ifname (const char *spec_str, const char **matches, const char **neg_matches)
_do_test_match_spec_device (const char *spec_str, const char **matches, const char **neg_matches)
{
const char *m;
GSList *specs, *specs_reverse = NULL, *specs_resplit, *specs_i, *specs_j;
@ -1013,20 +1019,20 @@ test_match_spec_ifname (const char *spec_str, const char **matches, const char *
specs_reverse = g_slist_reverse (g_slist_copy (specs));
for (i = 0; matches && matches[i]; i++) {
g_assert (nm_match_spec_interface_name (specs, matches[i]) == NM_MATCH_SPEC_MATCH);
g_assert (nm_match_spec_interface_name (specs_reverse, matches[i]) == NM_MATCH_SPEC_MATCH);
g_assert (_test_match_device_interface (specs, matches[i]) == NM_MATCH_SPEC_MATCH);
g_assert (_test_match_device_interface (specs_reverse, matches[i]) == NM_MATCH_SPEC_MATCH);
}
for (i = 0; neg_matches && neg_matches[i]; i++) {
g_assert (nm_match_spec_interface_name (specs, neg_matches[i]) == NM_MATCH_SPEC_NEG_MATCH);
g_assert (nm_match_spec_interface_name (specs_reverse, neg_matches[i]) == NM_MATCH_SPEC_NEG_MATCH);
g_assert (_test_match_device_interface (specs, neg_matches[i]) == NM_MATCH_SPEC_NEG_MATCH);
g_assert (_test_match_device_interface (specs_reverse, neg_matches[i]) == NM_MATCH_SPEC_NEG_MATCH);
}
for (i = 0; (m = _test_match_spec_all[i]); i++) {
if (_test_match_spec_contains (matches, m))
continue;
if (_test_match_spec_contains (neg_matches, m))
continue;
g_assert (nm_match_spec_interface_name (specs, m) == NM_MATCH_SPEC_NO_MATCH);
g_assert (nm_match_spec_interface_name (specs_reverse, m) == NM_MATCH_SPEC_NO_MATCH);
g_assert (_test_match_device_interface (specs, m) == NM_MATCH_SPEC_NO_MATCH);
g_assert (_test_match_device_interface (specs_reverse, m) == NM_MATCH_SPEC_NO_MATCH);
}
g_slist_free (specs_reverse);
@ -1034,61 +1040,61 @@ test_match_spec_ifname (const char *spec_str, const char **matches, const char *
}
static void
test_nm_match_spec_interface_name (void)
test_match_spec_device (void)
{
#define S(...) ((const char *[]) { __VA_ARGS__, NULL } )
test_match_spec_ifname ("em1",
S ("em1"),
NULL);
test_match_spec_ifname ("em1,em2",
S ("em1", "em2"),
NULL);
test_match_spec_ifname ("em1,em2,interface-name:em2",
S ("em1", "em2"),
NULL);
test_match_spec_ifname ("interface-name:em1",
S ("em1"),
NULL);
test_match_spec_ifname ("interface-name:em*",
S ("em", "em*", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em1", "em11", "em2", "em3"),
NULL);
test_match_spec_ifname ("interface-name:em\\*",
S ("em\\", "em\\*", "em\\1", "em\\11", "em\\2"),
NULL);
test_match_spec_ifname ("interface-name:~em\\*",
S ("em\\", "em\\*", "em\\1", "em\\11", "em\\2"),
NULL);
test_match_spec_ifname ("interface-name:=em*",
S ("em*"),
NULL);
test_match_spec_ifname ("interface-name:em*,except:interface-name:em1*",
S ("em", "em*", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em2", "em3"),
S ("em1", "em11"));
test_match_spec_ifname ("interface-name:em*,except:interface-name:=em*",
S ("em", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em1", "em11", "em2", "em3"),
S ("em*"));
test_match_spec_ifname ("aa,bb,cc\\,dd,e,,",
S ("aa", "bb", "cc,dd", "e"),
NULL);
test_match_spec_ifname ("aa;bb;cc\\;dd;e,;",
S ("aa", "bb", "cc;dd", "e"),
NULL);
test_match_spec_ifname ("interface-name:em\\;1,em\\,2,\\,,\\\\,,em\\\\x",
S ("em;1", "em,2", ",", "\\", "em\\x"),
NULL);
test_match_spec_ifname ("\\s\\s,\\sinterface-name:a,\\s,",
S (" ", " ", " interface-name:a"),
NULL);
test_match_spec_ifname (" aa ; bb ; cc\\;dd ;e , ; \t\\t , ",
S ("aa", "bb", "cc;dd", "e", "\t"),
NULL);
_do_test_match_spec_device ("em1",
S ("em1"),
NULL);
_do_test_match_spec_device ("em1,em2",
S ("em1", "em2"),
NULL);
_do_test_match_spec_device ("em1,em2,interface-name:em2",
S ("em1", "em2"),
NULL);
_do_test_match_spec_device ("interface-name:em1",
S ("em1"),
NULL);
_do_test_match_spec_device ("interface-name:em*",
S ("em", "em*", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em1", "em11", "em2", "em3"),
NULL);
_do_test_match_spec_device ("interface-name:em\\*",
S ("em\\", "em\\*", "em\\1", "em\\11", "em\\2"),
NULL);
_do_test_match_spec_device ("interface-name:~em\\*",
S ("em\\", "em\\*", "em\\1", "em\\11", "em\\2"),
NULL);
_do_test_match_spec_device ("interface-name:=em*",
S ("em*"),
NULL);
_do_test_match_spec_device ("interface-name:em*,except:interface-name:em1*",
S ("em", "em*", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em2", "em3"),
S ("em1", "em11"));
_do_test_match_spec_device ("interface-name:em*,except:interface-name:=em*",
S ("em", "em\\", "em\\*", "em\\1", "em\\11", "em\\2", "em1", "em11", "em2", "em3"),
S ("em*"));
_do_test_match_spec_device ("aa,bb,cc\\,dd,e,,",
S ("aa", "bb", "cc,dd", "e"),
NULL);
_do_test_match_spec_device ("aa;bb;cc\\;dd;e,;",
S ("aa", "bb", "cc;dd", "e"),
NULL);
_do_test_match_spec_device ("interface-name:em\\;1,em\\,2,\\,,\\\\,,em\\\\x",
S ("em;1", "em,2", ",", "\\", "em\\x"),
NULL);
_do_test_match_spec_device ("\\s\\s,\\sinterface-name:a,\\s,",
S (" ", " ", " interface-name:a"),
NULL);
_do_test_match_spec_device (" aa ; bb ; cc\\;dd ;e , ; \t\\t , ",
S ("aa", "bb", "cc;dd", "e", "\t"),
NULL);
#undef S
}
/*****************************************************************************/
static void
_do_test_match_spec_match_config (const char *file, gint line, const char *spec_str, guint version, guint v_maj, guint v_min, guint v_mic, NMMatchSpecMatchType expected)
_do_test_match_spec_config (const char *file, gint line, const char *spec_str, guint version, guint v_maj, guint v_min, guint v_mic, NMMatchSpecMatchType expected)
{
GSList *specs;
NMMatchSpecMatchType match_result;
@ -1103,7 +1109,7 @@ _do_test_match_spec_match_config (const char *file, gint line, const char *spec_
specs = nm_match_spec_split (spec_str);
match_result = nm_match_spec_match_config (specs, version, NULL);
match_result = nm_match_spec_config (specs, version, NULL);
if (expected != match_result)
g_error ("%s:%d: faild comparing \"%s\" with %u.%u.%u. Expected %d, but got %d", file, line, spec_str, v_maj, v_min, v_mic, (int) expected, (int) match_result);
@ -1115,7 +1121,7 @@ _do_test_match_spec_match_config (const char *file, gint line, const char *spec_
NMMatchSpecMatchType match_result2;
match_result2 = nm_match_spec_match_config (specs2, version, NULL);
match_result2 = nm_match_spec_config (specs2, version, NULL);
if (match_result == NM_MATCH_SPEC_NO_MATCH)
g_assert_cmpint (match_result2, ==, NM_MATCH_SPEC_NO_MATCH);
else
@ -1126,105 +1132,105 @@ _do_test_match_spec_match_config (const char *file, gint line, const char *spec_
g_slist_free_full (specs, g_free);
}
#define do_test_match_spec_match_config(spec, v_maj, v_min, v_mic, expected) \
_do_test_match_spec_match_config (__FILE__, __LINE__, (""spec), NM_ENCODE_VERSION ((v_maj), (v_min), (v_mic)), (v_maj), (v_min), (v_mic), (expected))
#define do_test_match_spec_config(spec, v_maj, v_min, v_mic, expected) \
_do_test_match_spec_config (__FILE__, __LINE__, (""spec), NM_ENCODE_VERSION ((v_maj), (v_min), (v_mic)), (v_maj), (v_min), (v_mic), (expected))
static void
test_nm_match_spec_match_config (void)
test_match_spec_config (void)
{
do_test_match_spec_match_config ("", 1, 2, 3, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version:1.2.3", 1, 2, 2, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version:1.2.3", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2.3", 1, 2, 4, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("", 1, 2, 3, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version:1.2.3", 1, 2, 2, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version:1.2.3", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version:1.2.3", 1, 2, 4, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 1, 2, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 2, 2, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 2, 4, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version:1.2", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version:1.2", 1, 1, 2, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version:1.2", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version:1.2", 1, 2, 2, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version:1.2", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version:1.2", 1, 2, 4, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version:1.2", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 1, 1, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 2, 2, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 3, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2.3", 1, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.2.3", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.2.3", 1, 1, 1, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.2.3", 1, 2, 2, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.2.3", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.2.3", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.2.3", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.2.3", 1, 3, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.2.3", 1, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 1, 1, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 3, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 3, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.2", 1, 4, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.2", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.2", 1, 1, 1, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.2", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.2", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.2", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.2", 1, 3, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.2", 1, 3, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.2", 1, 4, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 1, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 3, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 3, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1", 1, 4, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1", 1, 1, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1", 1, 3, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1", 1, 3, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1", 1, 4, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 1, 1, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 2, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 2, 5, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 3, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2.3", 1, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 1, 1, 1, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 1, 2, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 1, 2, 2, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 1, 2, 5, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 1, 3, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2.3", 1, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 1, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 3, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1.2", 1, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2", 0, 2, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2", 1, 1, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1.2", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1.2", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1.2", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1.2", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2", 1, 3, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1.2", 1, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 0, 2, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 1, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 3, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 3, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 1, 4, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-max:1", 2, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-max:1", 0, 2, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1", 1, 1, 1, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1", 1, 2, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1", 1, 2, 3, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1", 1, 2, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1", 1, 3, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1", 1, 3, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1", 1, 4, 30, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-max:1", 2, 4, 30, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("except:nm-version:1.4.8", 1, 6, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,except:nm-version:1.4.8", 1, 6, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("except:nm-version:1.4.8", 1, 6, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,except:nm-version:1.4.8", 1, 6, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 15, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 16, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 17, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 20, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 15, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 16, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 17, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 2, 20, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 5, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 6, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 7, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 8, NM_MATCH_SPEC_NEG_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 9, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 3, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 5, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 6, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 7, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 8, NM_MATCH_SPEC_NEG_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 4, 9, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 5, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 6, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 6, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 7, 7, NM_MATCH_SPEC_MATCH);
do_test_match_spec_match_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 8, 8, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 5, 0, NM_MATCH_SPEC_NO_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 6, 0, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 6, 5, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 7, 7, NM_MATCH_SPEC_MATCH);
do_test_match_spec_config ("nm-version-min:1.6,nm-version-min:1.4.6,nm-version-min:1.2.16,except:nm-version:1.4.8", 1, 8, 8, NM_MATCH_SPEC_MATCH);
}
/*****************************************************************************/
@ -1594,8 +1600,8 @@ main (int argc, char **argv)
g_test_add_func ("/general/connection-sort/autoconnect-priority", test_connection_sort_autoconnect_priority);
g_test_add_func ("/general/nm_match_spec_interface_name", test_nm_match_spec_interface_name);
g_test_add_func ("/general/nm_match_spec_match_config", test_nm_match_spec_match_config);
g_test_add_func ("/general/match-spec/device", test_match_spec_device);
g_test_add_func ("/general/match-spec/config", test_match_spec_config);
g_test_add_func ("/general/duplicate_decl_specifier", test_duplicate_decl_specifier);
g_test_add_func ("/general/reverse_dns/ip4", test_reverse_dns_ip4);