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.
This commit is contained in:
Thomas Haller 2017-01-20 19:50:25 +01:00
parent 7dde8d8106
commit b957403efd
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);