libnm: merge branch 'th/libnm-no-dbus-codegen-3'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/324
This commit is contained in:
Thomas Haller
2019-11-07 13:23:01 +01:00
23 changed files with 681 additions and 455 deletions

View File

@@ -600,6 +600,9 @@ permission_changed (NMClient *client,
if (got_permissions (nmc)) { if (got_permissions (nmc)) {
/* Defer the printing, so that we have a chance to process the other /* Defer the printing, so that we have a chance to process the other
* permission-changed signals. */ * permission-changed signals. */
g_signal_handlers_disconnect_by_func (nmc->client,
G_CALLBACK (permission_changed),
nmc);
g_idle_remove_by_data (nmc); g_idle_remove_by_data (nmc);
g_idle_add (print_permissions, nmc); g_idle_add (print_permissions, nmc);
} }

View File

@@ -91,11 +91,13 @@ import itertools
import subprocess import subprocess
import shlex import shlex
import re import re
import fcntl
import dbus import dbus
import time import time
import random import random
import dbus.service import dbus.service
import dbus.mainloop.glib import dbus.mainloop.glib
import io
############################################################################### ###############################################################################
@@ -173,26 +175,52 @@ class Util:
@staticmethod @staticmethod
def popen_wait(p, timeout = 0): def popen_wait(p, timeout = 0):
if Util.python_has_version(3, 3): (res, b_stdout, b_stderr) = Util.popen_wait_read(p, timeout = timeout, read_std_pipes = False)
if timeout == 0: return res
return p.poll()
try: @staticmethod
return p.wait(timeout) def popen_wait_read(p, timeout = 0, read_std_pipes = True):
except subprocess.TimeoutExpired:
return None
start = NM.utils_get_timestamp_msec() start = NM.utils_get_timestamp_msec()
delay = 0.0005 delay = 0.0005
b_stdout = b''
b_stderr = b''
res = None
while True: while True:
if read_std_pipes:
b_stdout += Util.buffer_read(p.stdout)
b_stderr += Util.buffer_read(p.stderr)
if p.poll() is not None: if p.poll() is not None:
return p.returncode res = p.returncode
break
if timeout == 0: if timeout == 0:
return None break
assert(timeout > 0) assert(timeout > 0)
remaining = timeout - ((NM.utils_get_timestamp_msec() - start) / 1000.0) remaining = timeout - ((NM.utils_get_timestamp_msec() - start) / 1000.0)
if remaining <= 0: if remaining <= 0:
return None break
delay = min(delay * 2, remaining, 0.05) delay = min(delay * 2, remaining, 0.05)
time.sleep(delay) time.sleep(delay)
return (res, b_stdout, b_stderr)
@staticmethod
def buffer_read(buf):
b = b''
while True:
try:
b1 = buf.read()
except io.BlockingIOError:
b1 = b''
except IOError:
b1 = b''
if not b1:
return b
b += b1
@staticmethod
def buffer_set_nonblock(buf):
fd = buf.fileno()
fl = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
@staticmethod @staticmethod
def random_job(jobs): def random_job(jobs):
@@ -459,10 +487,14 @@ class AsyncProcess():
def start(self): def start(self):
if not hasattr(self, '_p'): if not hasattr(self, '_p'):
self._p_start_timestamp = NM.utils_get_timestamp_msec() self._p_start_timestamp = NM.utils_get_timestamp_msec()
self._p_stdout_buf = b''
self._p_stderr_buf = b''
self._p = subprocess.Popen(self._args, self._p = subprocess.Popen(self._args,
stdout = subprocess.PIPE, stdout = subprocess.PIPE,
stderr = subprocess.PIPE, stderr = subprocess.PIPE,
env = self._env) env = self._env)
Util.buffer_set_nonblock(self._p.stdout)
Util.buffer_set_nonblock(self._p.stderr)
def _timeout_remaining_time(self): def _timeout_remaining_time(self):
# note that we call this during poll() and wait_and_complete(). # note that we call this during poll() and wait_and_complete().
@@ -476,7 +508,11 @@ class AsyncProcess():
def poll(self, timeout = 0): def poll(self, timeout = 0):
self.start() self.start()
return_code = Util.popen_wait(self._p, timeout) (return_code, b_stdout, b_stderr) = Util.popen_wait_read(self._p, timeout)
self._p_stdout_buf += b_stdout
self._p_stderr_buf += b_stderr
if return_code is None \ if return_code is None \
and self._timeout_remaining_time() <= 0: and self._timeout_remaining_time() <= 0:
raise Exception("process is still running after timeout: %s" % (' '.join(self._args))) raise Exception("process is still running after timeout: %s" % (' '.join(self._args)))
@@ -488,11 +524,16 @@ class AsyncProcess():
p = self._p p = self._p
self._p = None self._p = None
return_code = Util.popen_wait(p, max(0, self._timeout_remaining_time()) / 1000) (return_code, b_stdout, b_stderr) = Util.popen_wait_read(p, max(0, self._timeout_remaining_time()) / 1000)
(stdout, stderr) = (p.stdout.read(), p.stderr.read()) (stdout, stderr) = (p.stdout.read(), p.stderr.read())
p.stdout.close() p.stdout.close()
p.stderr.close() p.stderr.close()
stdout = self._p_stdout_buf + b_stdout + stdout
stderr = self._p_stderr_buf + b_stderr + stderr
del self._p_stdout_buf
del self._p_stderr_buf
if return_code is None: if return_code is None:
print(stdout) print(stdout)
print(stderr) print(stderr)
@@ -670,6 +711,7 @@ class TestNmcli(NmTestBase):
env['TERM'] = 'linux' env['TERM'] = 'linux'
env['ASAN_OPTIONS'] = 'detect_leaks=0' env['ASAN_OPTIONS'] = 'detect_leaks=0'
env['XDG_CONFIG_HOME'] = PathConfiguration.srcdir() env['XDG_CONFIG_HOME'] = PathConfiguration.srcdir()
env['NM_TEST_CALLING_NUM'] = str(calling_num)
if fatal_warnings is _DEFAULT_ARG or fatal_warnings: if fatal_warnings is _DEFAULT_ARG or fatal_warnings:
env['G_DEBUG'] = 'fatal-warnings' env['G_DEBUG'] = 'fatal-warnings'

View File

@@ -511,16 +511,15 @@ nm_client_wwan_hardware_get_enabled (NMClient *client)
* Determines whether WiMAX is enabled. * Determines whether WiMAX is enabled.
* *
* Returns: %TRUE if WiMAX is enabled * Returns: %TRUE if WiMAX is enabled
*
* Deprecated: 1.22 This function always returns FALSE because WiMax is no longer supported
**/ **/
gboolean gboolean
nm_client_wimax_get_enabled (NMClient *client) nm_client_wimax_get_enabled (NMClient *client)
{ {
g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
if (!nm_client_get_nm_running (client))
return FALSE; return FALSE;
return nm_manager_wimax_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
} }
/** /**
@@ -529,16 +528,13 @@ nm_client_wimax_get_enabled (NMClient *client)
* @enabled: %TRUE to enable WiMAX * @enabled: %TRUE to enable WiMAX
* *
* Enables or disables WiMAX devices. * Enables or disables WiMAX devices.
*
* Deprecated: 1.22 This function does nothing because WiMax is no longer supported
**/ **/
void void
nm_client_wimax_set_enabled (NMClient *client, gboolean enabled) nm_client_wimax_set_enabled (NMClient *client, gboolean enabled)
{ {
g_return_if_fail (NM_IS_CLIENT (client)); g_return_if_fail (NM_IS_CLIENT (client));
if (!nm_client_get_nm_running (client))
return;
nm_manager_wimax_set_enabled (NM_CLIENT_GET_PRIVATE (client)->manager, enabled);
} }
/** /**
@@ -548,16 +544,15 @@ nm_client_wimax_set_enabled (NMClient *client, gboolean enabled)
* Determines whether the WiMAX hardware is enabled. * Determines whether the WiMAX hardware is enabled.
* *
* Returns: %TRUE if the WiMAX hardware is enabled * Returns: %TRUE if the WiMAX hardware is enabled
*
* Deprecated: 1.22 This function always returns FALSE because WiMax is no longer supported
**/ **/
gboolean gboolean
nm_client_wimax_hardware_get_enabled (NMClient *client) nm_client_wimax_hardware_get_enabled (NMClient *client)
{ {
g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
if (!nm_client_get_nm_running (client))
return FALSE; return FALSE;
return nm_manager_wimax_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
} }
/** /**
@@ -3540,12 +3535,9 @@ get_property (GObject *object, guint prop_id,
g_value_set_boolean (value, FALSE); g_value_set_boolean (value, FALSE);
break; break;
case PROP_WIMAX_ENABLED: case PROP_WIMAX_ENABLED:
g_value_set_boolean (value, nm_client_wimax_get_enabled (self)); g_value_set_boolean (value, FALSE);
break; break;
case PROP_WIMAX_HARDWARE_ENABLED: case PROP_WIMAX_HARDWARE_ENABLED:
if (priv->manager)
g_object_get_property (G_OBJECT (priv->manager), pspec->name, value);
else
g_value_set_boolean (value, FALSE); g_value_set_boolean (value, FALSE);
break; break;
case PROP_ACTIVE_CONNECTIONS: case PROP_ACTIVE_CONNECTIONS:
@@ -3643,11 +3635,12 @@ set_property (GObject *object, guint prop_id,
case PROP_NETWORKING_ENABLED: case PROP_NETWORKING_ENABLED:
case PROP_WIRELESS_ENABLED: case PROP_WIRELESS_ENABLED:
case PROP_WWAN_ENABLED: case PROP_WWAN_ENABLED:
case PROP_WIMAX_ENABLED:
case PROP_CONNECTIVITY_CHECK_ENABLED: case PROP_CONNECTIVITY_CHECK_ENABLED:
if (priv->manager) if (priv->manager)
g_object_set_property (G_OBJECT (priv->manager), pspec->name, value); g_object_set_property (G_OBJECT (priv->manager), pspec->name, value);
break; break;
case PROP_WIMAX_ENABLED:
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@@ -4015,7 +4008,7 @@ nm_client_class_init (NMClientClass *client_class)
* *
* Whether WiMAX functionality is enabled. * Whether WiMAX functionality is enabled.
* *
* The property setter is a synchronous D-Bus call. This is deprecated since 1.22. * Deprecated: 1.22: WiMAX is no longer supported and this always returns FALSE. The setter has no effect.
*/ */
obj_properties[PROP_WIMAX_ENABLED] = obj_properties[PROP_WIMAX_ENABLED] =
g_param_spec_boolean (NM_CLIENT_WIMAX_ENABLED, "", "", g_param_spec_boolean (NM_CLIENT_WIMAX_ENABLED, "", "",
@@ -4027,6 +4020,8 @@ nm_client_class_init (NMClientClass *client_class)
* NMClient:wimax-hardware-enabled: * NMClient:wimax-hardware-enabled:
* *
* Whether the WiMAX hardware is enabled. * Whether the WiMAX hardware is enabled.
*
* Deprecated: 1.22: WiMAX is no longer supported and this always returns FALSE.
**/ **/
obj_properties[PROP_WIMAX_HARDWARE_ENABLED] = obj_properties[PROP_WIMAX_HARDWARE_ENABLED] =
g_param_spec_boolean (NM_CLIENT_WIMAX_HARDWARE_ENABLED, "", "", g_param_spec_boolean (NM_CLIENT_WIMAX_HARDWARE_ENABLED, "", "",

View File

@@ -245,11 +245,14 @@ void nm_client_wwan_set_enabled (NMClient *client, gboolean enabled);
gboolean nm_client_wwan_hardware_get_enabled (NMClient *client); gboolean nm_client_wwan_hardware_get_enabled (NMClient *client);
NM_DEPRECATED_IN_1_22
gboolean nm_client_wimax_get_enabled (NMClient *client); gboolean nm_client_wimax_get_enabled (NMClient *client);
NM_DEPRECATED_IN_1_22
_NM_DEPRECATED_SYNC_METHOD _NM_DEPRECATED_SYNC_METHOD
void nm_client_wimax_set_enabled (NMClient *client, gboolean enabled); void nm_client_wimax_set_enabled (NMClient *client, gboolean enabled);
NM_DEPRECATED_IN_1_22
gboolean nm_client_wimax_hardware_get_enabled (NMClient *client); gboolean nm_client_wimax_hardware_get_enabled (NMClient *client);
NM_AVAILABLE_IN_1_10 NM_AVAILABLE_IN_1_10

View File

@@ -1066,6 +1066,10 @@ nm_device_get_managed (NMDevice *device)
* Since: 1.2 * Since: 1.2
* *
* Deprecated: 1.22, use nm_device_set_managed_async() or GDBusConnection * Deprecated: 1.22, use nm_device_set_managed_async() or GDBusConnection
*
* This function is deprecated because it calls a synchronous D-Bus method
* and modifies the content of the NMClient cache client side. Also, it does
* not emit a property changed signal.
**/ **/
void void
nm_device_set_managed (NMDevice *device, gboolean managed) nm_device_set_managed (NMDevice *device, gboolean managed)
@@ -1108,6 +1112,9 @@ nm_device_get_autoconnect (NMDevice *device)
* Enables or disables automatic activation of the #NMDevice. * Enables or disables automatic activation of the #NMDevice.
* *
* Deprecated: 1.22, use nm_device_set_autoconnect_async() or GDBusConnection * Deprecated: 1.22, use nm_device_set_autoconnect_async() or GDBusConnection
*
* This function is deprecated because it calls a synchronous D-Bus method
* and modifies the content of the NMClient cache client side.
**/ **/
void void
nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect) nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect)

View File

@@ -77,11 +77,13 @@ NMDeviceCapabilities nm_device_get_capabilities (NMDevice *device);
gboolean nm_device_get_managed (NMDevice *device); gboolean nm_device_get_managed (NMDevice *device);
NM_AVAILABLE_IN_1_2 NM_AVAILABLE_IN_1_2
NM_DEPRECATED_IN_1_22
_NM_DEPRECATED_SYNC_METHOD _NM_DEPRECATED_SYNC_METHOD
void nm_device_set_managed (NMDevice *device, gboolean managed); void nm_device_set_managed (NMDevice *device, gboolean managed);
gboolean nm_device_get_autoconnect (NMDevice *device); gboolean nm_device_get_autoconnect (NMDevice *device);
NM_DEPRECATED_IN_1_22
_NM_DEPRECATED_SYNC_METHOD _NM_DEPRECATED_SYNC_METHOD
void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect); void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect);

View File

@@ -8,6 +8,9 @@
#include "nm-libnm-utils.h" #include "nm-libnm-utils.h"
#include "nm-glib-aux/nm-time-utils.h"
#include "nm-libnm-core-intern/nm-common-macros.h"
/*****************************************************************************/ /*****************************************************************************/
volatile int _nml_dbus_log_level = 0; volatile int _nml_dbus_log_level = 0;
@@ -43,6 +46,7 @@ _nml_dbus_log (NMLDBusLogLevel level,
gs_free char *msg = NULL; gs_free char *msg = NULL;
va_list args; va_list args;
const char *prefix = ""; const char *prefix = "";
gint64 ts;
/* we only call _nml_dbus_log() after nml_dbus_log_enabled(), which already does /* we only call _nml_dbus_log() after nml_dbus_log_enabled(), which already does
* an atomic access to the variable. Since the value is only initialized once and * an atomic access to the variable. Since the value is only initialized once and
@@ -84,7 +88,13 @@ _nml_dbus_log (NMLDBusLogLevel level,
break; break;
} }
g_printerr ("libnm-dbus: %s%s\n", prefix, msg); ts = nm_utils_clock_gettime_ns (CLOCK_BOOTTIME);
g_printerr ("libnm-dbus: %s[%"G_GINT64_FORMAT".%05"G_GINT64_FORMAT"] %s\n",
prefix,
ts / NM_UTILS_NS_PER_SECOND,
(ts / (NM_UTILS_NS_PER_SECOND / 10000)) % 10000,
msg);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -649,3 +659,85 @@ nm_utils_fixup_product_string (const char *desc)
return desc_full; return desc_full;
} }
/*****************************************************************************/
NMClientPermission
nm_permission_to_client (const char *nm)
{
static const struct {
const char *name;
NMClientPermission perm;
} list[] = {
{ NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS, NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN },
{ NM_AUTH_PERMISSION_NETWORK_CONTROL, NM_CLIENT_PERMISSION_NETWORK_CONTROL },
{ NM_AUTH_PERMISSION_RELOAD, NM_CLIENT_PERMISSION_RELOAD },
{ NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS },
{ NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME },
{ NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN },
{ NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM },
{ NM_AUTH_PERMISSION_SLEEP_WAKE, NM_CLIENT_PERMISSION_SLEEP_WAKE },
{ NM_AUTH_PERMISSION_WIFI_SCAN, NM_CLIENT_PERMISSION_WIFI_SCAN },
{ NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN },
{ NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED },
};
gssize idx;
#if NM_MORE_ASSERTS > 10
{
static gboolean checked = FALSE;
int i, j;
if (!checked) {
checked = TRUE;
for (i = 0; i < G_N_ELEMENTS (list); i++) {
nm_assert (list[i].perm != NM_CLIENT_PERMISSION_NONE);
nm_assert (list[i].name && list[i].name[0]);
if (i > 0) {
if (strcmp (list[i - 1].name, list[i].name) >= 0) {
g_error ("list is not sorted by name: #%d (%s) should be after #%d (%s)",
i - 1, list[i - 1].name, i, list[i].name);
}
}
for (j = i + 1; j < G_N_ELEMENTS (list); j++) {
nm_assert (list[i].perm != list[j].perm);
}
}
}
}
#endif
if (nm) {
idx = nm_utils_array_find_binary_search (list,
sizeof (list[0]),
G_N_ELEMENTS (list),
&nm,
nm_strcmp_p_with_data,
NULL);
if (idx >= 0)
return list[idx].perm;
}
return NM_CLIENT_PERMISSION_NONE;
}
NMClientPermissionResult
nm_permission_result_to_client (const char *nm)
{
if (!nm)
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
if (nm_streq (nm, "yes"))
return NM_CLIENT_PERMISSION_RESULT_YES;
if (nm_streq (nm, "no"))
return NM_CLIENT_PERMISSION_RESULT_NO;
if (nm_streq (nm, "auth"))
return NM_CLIENT_PERMISSION_RESULT_AUTH;
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
}

View File

@@ -8,6 +8,7 @@
#include "nm-types.h" #include "nm-types.h"
#include "nm-glib-aux/nm-ref-string.h" #include "nm-glib-aux/nm-ref-string.h"
#include "nm-client.h"
/*****************************************************************************/ /*****************************************************************************/
@@ -17,6 +18,12 @@
/*****************************************************************************/ /*****************************************************************************/
NMClientPermission nm_permission_to_client (const char *nm);
NMClientPermissionResult nm_permission_result_to_client (const char *nm);
/*****************************************************************************/
typedef enum { typedef enum {
_NML_DBUS_LOG_LEVEL_INITIALIZED = 0x01, _NML_DBUS_LOG_LEVEL_INITIALIZED = 0x01,
@@ -124,9 +131,7 @@ _nml_coerce_property_object_path (NMRefString *path)
{ {
if (!path) if (!path)
return NULL; return NULL;
if (nm_streq (path->str, "/")) return nm_dbus_path_not_empty (path->str);
return NULL;
return path->str;
} }
static inline const char *const* static inline const char *const*

View File

@@ -254,59 +254,6 @@ object_creation_failed (NMObject *object, const char *failed_path)
} }
} }
static NMClientPermission
nm_permission_to_client (const char *nm)
{
if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SLEEP_WAKE))
return NM_CLIENT_PERMISSION_SLEEP_WAKE;
else if (!strcmp (nm, NM_AUTH_PERMISSION_NETWORK_CONTROL))
return NM_CLIENT_PERMISSION_NETWORK_CONTROL;
else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED))
return NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED;
else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN))
return NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
else if (!strcmp (nm, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS))
return NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
else if (!strcmp (nm, NM_AUTH_PERMISSION_RELOAD))
return NM_CLIENT_PERMISSION_RELOAD;
else if (!strcmp (nm, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK))
return NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS;
else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK))
return NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK;
else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SCAN))
return NM_CLIENT_PERMISSION_WIFI_SCAN;
return NM_CLIENT_PERMISSION_NONE;
}
static NMClientPermissionResult
nm_permission_result_to_client (const char *nm)
{
if (!strcmp (nm, "yes"))
return NM_CLIENT_PERMISSION_RESULT_YES;
else if (!strcmp (nm, "no"))
return NM_CLIENT_PERMISSION_RESULT_NO;
else if (!strcmp (nm, "auth"))
return NM_CLIENT_PERMISSION_RESULT_AUTH;
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
}
static void static void
update_permissions (NMManager *self, GVariant *permissions) update_permissions (NMManager *self, GVariant *permissions)
{ {

View File

@@ -10,8 +10,9 @@
#include "nm-test-libnm-utils.h" #include "nm-test-libnm-utils.h"
static GMainLoop *loop = NULL; static struct {
static NMTstcServiceInfo *sinfo; GMainLoop *loop;
} gl = { };
/*****************************************************************************/ /*****************************************************************************/
@@ -24,68 +25,6 @@ loop_quit (gpointer user_data)
/*****************************************************************************/ /*****************************************************************************/
static NMClient *
_nm_client_new_sync (void)
{
NMClient *client;
guint source_1;
GError *error = NULL;
source_1 = g_idle_add (nmtst_g_source_assert_not_called, NULL);
client = g_object_new (NM_TYPE_CLIENT, NULL);
g_assert (NM_IS_CLIENT (client));
if (!g_initable_init (G_INITABLE (client), NULL, &error))
g_assert_not_reached ();
g_assert_no_error (error);
nm_clear_g_source (&source_1);
return client;
}
typedef struct {
GMainLoop *loop;
NMClient *client;
} NewSyncInsideDispatchedData;
static gboolean
_nm_client_new_sync_inside_dispatched_do (gpointer user_data)
{
NewSyncInsideDispatchedData *d = user_data;
g_assert (d->loop);
g_assert (!d->client);
d->client = _nm_client_new_sync ();
g_main_loop_quit (d->loop);
return G_SOURCE_CONTINUE;
}
static NMClient *
_nm_client_new_sync_inside_dispatched (void)
{
NewSyncInsideDispatchedData d = { };
guint source_1;
d.loop = g_main_loop_new (NULL, FALSE);
source_1 = g_idle_add (_nm_client_new_sync_inside_dispatched_do, &d);
g_main_loop_run (d.loop);
g_assert (NM_IS_CLIENT (d.client));
nm_clear_g_source (&source_1);
g_main_loop_unref (d.loop);
return d.client;
}
/*****************************************************************************/
static void static void
devices_notify_cb (NMClient *c, devices_notify_cb (NMClient *c,
GParamSpec *pspec, GParamSpec *pspec,
@@ -109,7 +48,8 @@ devices_notify_cb (NMClient *c,
static void static void
test_device_added (void) test_device_added (void)
{ {
NMClient *client; nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
gs_unref_object NMClient *client = NULL;
const GPtrArray *devices; const GPtrArray *devices;
NMDevice *device; NMDevice *device;
gboolean notified = FALSE; gboolean notified = FALSE;
@@ -119,8 +59,7 @@ test_device_added (void)
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (sinfo))
return; return;
client = nm_client_new (NULL, &error); client = nmtstc_client_new (TRUE);
g_assert_no_error (error);
devices = nm_client_get_devices (client); devices = nm_client_get_devices (client);
g_assert (devices->len == 0); g_assert (devices->len == 0);
@@ -151,9 +90,6 @@ test_device_added (void)
nm_device_delete (device, NULL, &error); nm_device_delete (device, NULL, &error);
g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_SOFTWARE); g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_SOFTWARE);
g_clear_error (&error); g_clear_error (&error);
g_object_unref (client);
g_clear_pointer (&sinfo, nmtstc_service_cleanup);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -190,6 +126,8 @@ devices_sai_notify_cb (NMClient *c,
const GPtrArray *devices; const GPtrArray *devices;
NMDevice *device; NMDevice *device;
g_assert_cmpstr (pspec->name, ==, "devices");
devices = nm_client_get_devices (c); devices = nm_client_get_devices (c);
g_assert (devices); g_assert (devices);
g_assert_cmpint (devices->len, ==, 1); g_assert_cmpint (devices->len, ==, 1);
@@ -205,18 +143,17 @@ devices_sai_notify_cb (NMClient *c,
static void static void
test_device_added_signal_after_init (void) test_device_added_signal_after_init (void)
{ {
NMClient *client; nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
gs_unref_object NMClient *client = NULL;
const GPtrArray *devices; const GPtrArray *devices;
NMDevice *device; NMDevice *device;
guint result = 0; guint result = 0;
GError *error = NULL;
sinfo = nmtstc_service_init (); sinfo = nmtstc_service_init ();
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (sinfo))
return; return;
client = nm_client_new (NULL, &error); client = nmtstc_client_new (TRUE);
g_assert_no_error (error);
devices = nm_client_get_devices (client); devices = nm_client_get_devices (client);
g_assert (devices->len == 0); g_assert (devices->len == 0);
@@ -253,9 +190,6 @@ test_device_added_signal_after_init (void)
device = g_ptr_array_index (devices, 0); device = g_ptr_array_index (devices, 0);
g_assert (device); g_assert (device);
g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0"); g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
g_object_unref (client);
g_clear_pointer (&sinfo, nmtstc_service_cleanup);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -355,19 +289,19 @@ wifi_ap_remove_notify_cb (NMDeviceWifi *w,
static void static void
test_wifi_ap_added_removed (void) test_wifi_ap_added_removed (void)
{ {
NMClient *client; nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
gs_unref_object NMClient *client = NULL;
NMDeviceWifi *wifi; NMDeviceWifi *wifi;
WifiApInfo info = { loop, FALSE, FALSE, 0, 0 }; WifiApInfo info = { gl.loop, FALSE, FALSE, 0, 0 };
GVariant *ret; GVariant *ret;
GError *error = NULL; GError *error = NULL;
char *expected_path = NULL; gs_free char *expected_path = NULL;
sinfo = nmtstc_service_init (); sinfo = nmtstc_service_init ();
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (sinfo))
return; return;
client = nm_client_new (NULL, &error); client = nmtstc_client_new (TRUE);
g_assert_no_error (error);
/*************************************/ /*************************************/
/* Add the wifi device */ /* Add the wifi device */
@@ -406,8 +340,8 @@ test_wifi_ap_added_removed (void)
info.quit_count++; info.quit_count++;
/* Wait for libnm to find the AP */ /* Wait for libnm to find the AP */
info.quit_id = g_timeout_add_seconds (5, loop_quit, loop); info.quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
g_main_loop_run (loop); g_main_loop_run (gl.loop);
g_assert (info.signaled); g_assert (info.signaled);
g_assert (info.notified); g_assert (info.notified);
@@ -445,8 +379,8 @@ test_wifi_ap_added_removed (void)
info.quit_count++; info.quit_count++;
/* Wait for libnm to find the AP */ /* Wait for libnm to find the AP */
info.quit_id = g_timeout_add_seconds (5, loop_quit, loop); info.quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
g_main_loop_run (loop); g_main_loop_run (gl.loop);
g_assert (info.signaled); g_assert (info.signaled);
g_assert (info.notified); g_assert (info.notified);
@@ -454,10 +388,6 @@ test_wifi_ap_added_removed (void)
g_signal_handlers_disconnect_by_func (wifi, wifi_ap_remove_notify_cb, &info); g_signal_handlers_disconnect_by_func (wifi, wifi_ap_remove_notify_cb, &info);
g_free (info.ap_path); g_free (info.ap_path);
g_free (expected_path);
g_object_unref (client);
g_clear_pointer (&sinfo, nmtstc_service_cleanup);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -516,26 +446,12 @@ da_devices_notify_cb (NMClient *c,
da_check_quit (info); da_check_quit (info);
} }
static void
new_client_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
NMClient **out_client = user_data;
GError *error = NULL;
*out_client = nm_client_new_finish (result, &error);
g_assert_no_error (error);
g_assert (*out_client != NULL);
g_main_loop_quit (loop);
}
static void static void
test_devices_array (void) test_devices_array (void)
{ {
NMClient *client = NULL; nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
DaInfo info = { loop }; gs_unref_object NMClient *client = NULL;
DaInfo info = { gl.loop };
NMDevice *wlan0, *eth0, *eth1, *device; NMDevice *wlan0, *eth0, *eth1, *device;
const GPtrArray *devices; const GPtrArray *devices;
GError *error = NULL; GError *error = NULL;
@@ -545,10 +461,7 @@ test_devices_array (void)
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (sinfo))
return; return;
/* Make sure that we test the async codepath in at least one test... */ client = nmtstc_client_new (TRUE);
nm_client_new_async (NULL, new_client_cb, &client);
g_main_loop_run (loop);
g_assert (client != NULL);
/*************************************/ /*************************************/
/* Add some devices */ /* Add some devices */
@@ -598,8 +511,8 @@ test_devices_array (void)
info.quit_count = 2; info.quit_count = 2;
/* Wait for libnm to notice the changes */ /* Wait for libnm to notice the changes */
info.quit_id = g_timeout_add_seconds (5, loop_quit, loop); info.quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
g_main_loop_run (loop); g_main_loop_run (gl.loop);
g_assert_cmpint (info.quit_count, ==, 0); g_assert_cmpint (info.quit_count, ==, 0);
g_signal_handlers_disconnect_by_func (client, da_device_removed_cb, &info); g_signal_handlers_disconnect_by_func (client, da_device_removed_cb, &info);
@@ -617,9 +530,6 @@ test_devices_array (void)
device = nm_client_get_device_by_iface (client, "eth1"); device = nm_client_get_device_by_iface (client, "eth1");
g_assert (NM_IS_DEVICE_ETHERNET (device)); g_assert (NM_IS_DEVICE_ETHERNET (device));
g_assert (device == eth1); g_assert (device == eth1);
g_object_unref (client);
g_clear_pointer (&sinfo, nmtstc_service_cleanup);
} }
static void static void
@@ -630,20 +540,20 @@ nm_running_changed (GObject *client,
int *running_changed = user_data; int *running_changed = user_data;
(*running_changed)++; (*running_changed)++;
g_main_loop_quit (loop); g_main_loop_quit (gl.loop);
} }
static void static void
test_client_nm_running (void) test_client_nm_running (void)
{ {
nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
gs_unref_object NMClient *client1 = NULL; gs_unref_object NMClient *client1 = NULL;
gs_unref_object NMClient *client2 = NULL; gs_unref_object NMClient *client2 = NULL;
guint quit_id; guint quit_id;
int running_changed = 0; int running_changed = 0;
GError *error = NULL; GError *error = NULL;
client1 = nm_client_new (NULL, &error); client1 = nmtstc_client_new (TRUE);
g_assert_no_error (error);
g_assert (!nm_client_get_nm_running (client1)); g_assert (!nm_client_get_nm_running (client1));
g_assert_cmpstr (nm_client_get_version (client1), ==, NULL); g_assert_cmpstr (nm_client_get_version (client1), ==, NULL);
@@ -663,8 +573,7 @@ test_client_nm_running (void)
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (sinfo))
return; return;
client2 = nm_client_new (NULL, &error); client2 = nmtstc_client_new (FALSE);
g_assert_no_error (error);
/* client2 should know that NM is running, but the previously-created /* client2 should know that NM is running, but the previously-created
* client1 hasn't gotten the news yet. * client1 hasn't gotten the news yet.
@@ -674,8 +583,8 @@ test_client_nm_running (void)
g_signal_connect (client1, "notify::" NM_CLIENT_NM_RUNNING, g_signal_connect (client1, "notify::" NM_CLIENT_NM_RUNNING,
G_CALLBACK (nm_running_changed), &running_changed); G_CALLBACK (nm_running_changed), &running_changed);
quit_id = g_timeout_add_seconds (5, loop_quit, loop); quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
g_main_loop_run (loop); g_main_loop_run (gl.loop);
g_assert_cmpint (running_changed, ==, 1); g_assert_cmpint (running_changed, ==, 1);
g_assert (nm_client_get_nm_running (client1)); g_assert (nm_client_get_nm_running (client1));
g_source_remove (quit_id); g_source_remove (quit_id);
@@ -685,8 +594,8 @@ test_client_nm_running (void)
g_assert (nm_client_get_nm_running (client1)); g_assert (nm_client_get_nm_running (client1));
quit_id = g_timeout_add_seconds (5, loop_quit, loop); quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
g_main_loop_run (loop); g_main_loop_run (gl.loop);
g_assert_cmpint (running_changed, ==, 2); g_assert_cmpint (running_changed, ==, 2);
g_assert (!nm_client_get_nm_running (client1)); g_assert (!nm_client_get_nm_running (client1));
g_source_remove (quit_id); g_source_remove (quit_id);
@@ -697,6 +606,9 @@ typedef struct {
NMActiveConnection *ac; NMActiveConnection *ac;
int remaining; int remaining;
NMDevice *device;
gulong ac_signal_id;
} TestACInfo; } TestACInfo;
static void static void
@@ -786,18 +698,17 @@ device_ac_changed_cb (GObject *device,
static void static void
test_active_connections (void) test_active_connections (void)
{ {
NMClient *client; nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
gs_unref_object NMClient *client = NULL;
NMDevice *device; NMDevice *device;
NMConnection *conn; NMConnection *conn;
TestACInfo info = { loop, NULL, 0 }; TestACInfo info = { gl.loop, NULL, 0 };
GError *error = NULL;
sinfo = nmtstc_service_init (); sinfo = nmtstc_service_init ();
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (sinfo))
return; return;
client = nm_client_new (NULL, &error); client = nmtstc_client_new (TRUE);
g_assert_no_error (error);
/* Tell the test service to add a new device */ /* Tell the test service to add a new device */
device = nmtstc_service_add_device (sinfo, client, "AddWiredDevice", "eth0"); device = nmtstc_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
@@ -814,30 +725,25 @@ test_active_connections (void)
/* Two signals plus activate_cb */ /* Two signals plus activate_cb */
info.remaining = 3; info.remaining = 3;
g_main_loop_run (loop); g_main_loop_run (gl.loop);
g_signal_handlers_disconnect_by_func (client, client_acs_changed_cb, &info); g_signal_handlers_disconnect_by_func (client, client_acs_changed_cb, &info);
g_signal_handlers_disconnect_by_func (device, device_ac_changed_cb, &info); g_signal_handlers_disconnect_by_func (device, device_ac_changed_cb, &info);
g_assert (info.ac != NULL); g_assert (info.ac != NULL);
g_object_unref (info.ac); g_object_unref (info.ac);
g_object_unref (client); g_clear_object (&client);
/* Ensure that we can correctly resolve the recursive property link between the /* Ensure that we can correctly resolve the recursive property link between the
* AC and the Device in a newly-created client. * AC and the Device in a newly-created client.
*/ */
client = nm_client_new (NULL, &error); client = nmtstc_client_new (TRUE);
g_assert_no_error (error);
assert_ac_and_device (client); assert_ac_and_device (client);
g_object_unref (client); g_clear_object (&client);
client = NULL; client = nmtstc_client_new (TRUE);
nm_client_new_async (NULL, new_client_cb, &client);
g_main_loop_run (loop);
assert_ac_and_device (client); assert_ac_and_device (client);
g_object_unref (client); g_clear_object (&client);
g_clear_pointer (&sinfo, nmtstc_service_cleanup);
} }
static void static void
@@ -865,8 +771,11 @@ client_devices_changed_cb (GObject *client,
g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0.1"); g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0.1");
if (!nm_device_get_active_connection (device)) { if (!nm_device_get_active_connection (device)) {
g_assert (info->ac_signal_id == 0);
info->remaining++; info->remaining++;
g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION, info->device = device;
g_object_add_weak_pointer (G_OBJECT (device), (gpointer *) &info->device);
info->ac_signal_id = g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION,
G_CALLBACK (device_ac_changed_cb), info); G_CALLBACK (device_ac_changed_cb), info);
} }
@@ -916,20 +825,19 @@ activate_cb (GObject *object,
static void static void
test_activate_virtual (void) test_activate_virtual (void)
{ {
NMClient *client; nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
gs_unref_object NMClient *client = NULL;
NMConnection *conn; NMConnection *conn;
NMSettingConnection *s_con; NMSettingConnection *s_con;
NMSettingVlan *s_vlan; NMSettingVlan *s_vlan;
TestACInfo info = { loop, NULL, 0 }; TestACInfo info = { gl.loop, NULL, 0 };
TestConnectionInfo conn_info = { loop, NULL }; TestConnectionInfo conn_info = { gl.loop, NULL };
GError *error = NULL;
sinfo = nmtstc_service_init (); sinfo = nmtstc_service_init ();
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (sinfo))
return; return;
client = nm_client_new (NULL, &error); client = nmtstc_client_new (TRUE);
g_assert_no_error (error);
nmtstc_service_add_device (sinfo, client, "AddWiredDevice", "eth0"); nmtstc_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
@@ -945,7 +853,7 @@ test_activate_virtual (void)
nm_client_add_connection_async (client, conn, TRUE, nm_client_add_connection_async (client, conn, TRUE,
NULL, add_connection_cb, &conn_info); NULL, add_connection_cb, &conn_info);
g_main_loop_run (loop); g_main_loop_run (gl.loop);
g_object_unref (conn); g_object_unref (conn);
conn = NM_CONNECTION (conn_info.remote); conn = NM_CONNECTION (conn_info.remote);
@@ -965,72 +873,27 @@ test_activate_virtual (void)
*/ */
info.remaining = 3; info.remaining = 3;
g_main_loop_run (loop); g_main_loop_run (gl.loop);
g_signal_handlers_disconnect_by_func (client, client_acs_changed_cb, &info); g_signal_handlers_disconnect_by_func (client, client_acs_changed_cb, &info);
g_signal_handlers_disconnect_by_func (client, client_devices_changed_cb, &info); g_signal_handlers_disconnect_by_func (client, client_devices_changed_cb, &info);
g_assert (info.ac != NULL); g_assert (info.ac != NULL);
g_clear_object (&info.ac);
g_object_unref (info.ac); if (info.device) {
g_object_unref (client); g_object_remove_weak_pointer (G_OBJECT (info.device), (gpointer *) &info.device);
nm_clear_g_signal_handler (info.device, &info.ac_signal_id);
g_clear_pointer (&sinfo, nmtstc_service_cleanup);
} }
static void
activate_failed_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
NMClient *client = NM_CLIENT (object);
NMActiveConnection *ac;
GError *error = NULL;
ac = nm_client_add_and_activate_connection_finish (client, result, &error);
g_assert (ac == NULL);
g_assert_error (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_OBJECT_CREATION_FAILED);
g_clear_error (&error);
g_main_loop_quit (loop);
}
static void
test_activate_failed (void)
{
NMClient *client;
NMDevice *device;
NMConnection *conn;
GError *error = NULL;
sinfo = nmtstc_service_init ();
if (!nmtstc_service_available (sinfo))
return;
client = nm_client_new (NULL, &error);
g_assert_no_error (error);
device = nmtstc_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
/* Note that test-networkmanager-service.py checks for this exact name */
conn = nmtst_create_minimal_connection ("object-creation-failed-test", NULL,
NM_SETTING_WIRED_SETTING_NAME, NULL);
nm_client_add_and_activate_connection_async (client, conn, device, NULL,
NULL, activate_failed_cb, NULL);
g_main_loop_run (loop);
g_object_unref (conn);
g_object_unref (client);
g_clear_pointer (&sinfo, nmtstc_service_cleanup);
} }
static void static void
test_device_connection_compatibility (void) test_device_connection_compatibility (void)
{ {
NMClient *client; nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
NMDevice *device1, *device2; gs_unref_object NMClient *client = NULL;
NMConnection *conn; gs_unref_object NMConnection *conn = NULL;
NMDevice *device1;
NMDevice *device2;
NMSettingWired *s_wired; NMSettingWired *s_wired;
GError *error = NULL; GError *error = NULL;
const char *subchannels[] = { "0.0.8000", "0.0.8001", "0.0.8002", NULL }; const char *subchannels[] = { "0.0.8000", "0.0.8001", "0.0.8002", NULL };
@@ -1043,8 +906,7 @@ test_device_connection_compatibility (void)
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (sinfo))
return; return;
client = nm_client_new (NULL, &error); client = nmtstc_client_new (TRUE);
g_assert_no_error (error);
/* Create two devices */ /* Create two devices */
device1 = nmtstc_service_add_wired_device (sinfo, client, "eth0", hw_addr1, subchannels); device1 = nmtstc_service_add_wired_device (sinfo, client, "eth0", hw_addr1, subchannels);
@@ -1092,11 +954,6 @@ test_device_connection_compatibility (void)
nm_device_connection_compatible (device1, conn, &error); nm_device_connection_compatible (device1, conn, &error);
g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION); g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION);
g_clear_error (&error); g_clear_error (&error);
g_object_unref (conn);
g_object_unref (client);
g_clear_pointer (&sinfo, nmtstc_service_cleanup);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -1179,9 +1036,7 @@ test_connection_invalid (void)
FALSE, FALSE,
&path2); &path2);
client = nmtst_get_rand_bool () client = nmtstc_client_new (TRUE);
? _nm_client_new_sync ()
: _nm_client_new_sync_inside_dispatched ();
connections = nm_client_get_connections (client); connections = nm_client_get_connections (client);
g_assert (connections); g_assert (connections);
@@ -1216,7 +1071,7 @@ test_connection_invalid (void)
FALSE, FALSE,
&path3); &path3);
nmtst_main_loop_run (loop, 1000); nmtst_main_loop_run (gl.loop, 1000);
connections = nm_client_get_connections (client); connections = nm_client_get_connections (client);
g_assert (connections); g_assert (connections);
@@ -1252,7 +1107,7 @@ test_connection_invalid (void)
variant, variant,
FALSE); FALSE);
nmtst_main_loop_run (loop, 100); nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client); connections = nm_client_get_connections (client);
g_assert (connections); g_assert (connections);
@@ -1290,7 +1145,7 @@ test_connection_invalid (void)
variant, variant,
FALSE); FALSE);
nmtst_main_loop_run (loop, 100); nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client); connections = nm_client_get_connections (client);
g_assert (connections); g_assert (connections);
@@ -1325,7 +1180,7 @@ test_connection_invalid (void)
connection, connection,
FALSE); FALSE);
nmtst_main_loop_run (loop, 100); nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client); connections = nm_client_get_connections (client);
g_assert (connections); g_assert (connections);
@@ -1367,7 +1222,7 @@ test_connection_invalid (void)
connection, connection,
FALSE); FALSE);
nmtst_main_loop_run (loop, 100); nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client); connections = nm_client_get_connections (client);
g_assert (connections); g_assert (connections);
@@ -1409,7 +1264,7 @@ test_connection_invalid (void)
connection, connection,
FALSE); FALSE);
nmtst_main_loop_run (loop, 100); nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client); connections = nm_client_get_connections (client);
g_assert (connections); g_assert (connections);
@@ -1448,7 +1303,7 @@ main (int argc, char **argv)
nmtst_init (&argc, &argv, TRUE); nmtst_init (&argc, &argv, TRUE);
loop = g_main_loop_new (NULL, FALSE); gl.loop = g_main_loop_new (NULL, FALSE);
g_test_add_func ("/libnm/device-added", test_device_added); g_test_add_func ("/libnm/device-added", test_device_added);
g_test_add_func ("/libnm/device-added-signal-after-init", test_device_added_signal_after_init); g_test_add_func ("/libnm/device-added-signal-after-init", test_device_added_signal_after_init);
@@ -1457,7 +1312,6 @@ main (int argc, char **argv)
g_test_add_func ("/libnm/client-nm-running", test_client_nm_running); g_test_add_func ("/libnm/client-nm-running", test_client_nm_running);
g_test_add_func ("/libnm/active-connections", test_active_connections); g_test_add_func ("/libnm/active-connections", test_active_connections);
g_test_add_func ("/libnm/activate-virtual", test_activate_virtual); g_test_add_func ("/libnm/activate-virtual", test_activate_virtual);
g_test_add_func ("/libnm/activate-failed", test_activate_failed);
g_test_add_func ("/libnm/device-connection-compatibility", test_device_connection_compatibility); g_test_add_func ("/libnm/device-connection-compatibility", test_device_connection_compatibility);
g_test_add_func ("/libnm/connection/invalid", test_connection_invalid); g_test_add_func ("/libnm/connection/invalid", test_connection_invalid);

View File

@@ -8,12 +8,16 @@
#include <sys/types.h> #include <sys/types.h>
#include <signal.h> #include <signal.h>
#include "nm-glib-aux/nm-time-utils.h"
#include "nm-test-libnm-utils.h" #include "nm-test-libnm-utils.h"
static NMTstcServiceInfo *sinfo; static struct {
static NMClient *client = NULL; NMTstcServiceInfo *sinfo;
GDBusConnection *bus = NULL; NMClient *client;
NMRemoteConnection *remote = NULL; GDBusConnection *bus;
NMRemoteConnection *remote;
} gl = { };
/*****************************************************************************/ /*****************************************************************************/
@@ -25,17 +29,17 @@ add_cb (GObject *s,
gboolean *done = user_data; gboolean *done = user_data;
GError *error = NULL; GError *error = NULL;
remote = nm_client_add_connection_finish (client, result, &error); gl.remote = nm_client_add_connection_finish (gl.client, result, &error);
g_assert_no_error (error); g_assert_no_error (error);
*done = TRUE; *done = TRUE;
g_object_add_weak_pointer (G_OBJECT (remote), (void **) &remote); g_object_add_weak_pointer (G_OBJECT (gl.remote), (void **) &gl.remote);
/* nm_client_add_connection_finish() adds a ref to @remote, but we /* nm_client_add_connection_finish() adds a ref to @remote, but we
* want the weak pointer to be cleared as soon as @client drops its own ref. * want the weak pointer to be cleared as soon as @client drops its own ref.
* So drop ours. * So drop ours.
*/ */
g_object_unref (remote); g_object_unref (gl.remote);
} }
#define TEST_CON_ID "blahblahblah" #define TEST_CON_ID "blahblahblah"
@@ -44,32 +48,27 @@ static void
test_add_connection (void) test_add_connection (void)
{ {
NMConnection *connection; NMConnection *connection;
time_t start, now;
gboolean done = FALSE; gboolean done = FALSE;
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (gl.sinfo))
return; return;
connection = nmtst_create_minimal_connection (TEST_CON_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); connection = nmtst_create_minimal_connection (TEST_CON_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
nm_client_add_connection_async (client, nm_client_add_connection_async (gl.client,
connection, connection,
TRUE, TRUE,
NULL, NULL,
add_cb, add_cb,
&done); &done);
start = time (NULL); nmtst_main_context_iterate_until (NULL, 5000, done);
do {
now = time (NULL); g_assert (gl.remote != NULL);
g_main_context_iteration (NULL, FALSE);
} while ((done == FALSE) && (now - start < 5));
g_assert (done == TRUE);
g_assert (remote != NULL);
/* Make sure the connection is the same as what we added */ /* Make sure the connection is the same as what we added */
g_assert (nm_connection_compare (connection, g_assert (nm_connection_compare (connection,
NM_CONNECTION (remote), NM_CONNECTION (gl.remote),
NM_SETTING_COMPARE_FLAG_EXACT) == TRUE); NM_SETTING_COMPARE_FLAG_EXACT) == TRUE);
g_object_unref (connection); g_object_unref (connection);
} }
@@ -99,7 +98,7 @@ visible_changed_cb (GObject *object, GParamSpec *pspec, gboolean *done)
static void static void
connection_removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done) connection_removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done)
{ {
if (connection == remote) if (connection == gl.remote)
*done = TRUE; *done = TRUE;
} }
@@ -116,7 +115,6 @@ invis_has_settings_cb (NMSetting *setting,
static void static void
test_make_invisible (void) test_make_invisible (void)
{ {
time_t start, now;
const GPtrArray *conns; const GPtrArray *conns;
int i; int i;
GDBusProxy *proxy; GDBusProxy *proxy;
@@ -124,17 +122,17 @@ test_make_invisible (void)
gboolean has_settings = FALSE; gboolean has_settings = FALSE;
char *path; char *path;
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (gl.sinfo))
return; return;
g_assert (remote != NULL); g_assert (gl.remote != NULL);
/* Listen for the remove event when the connection becomes invisible */ /* Listen for the remove event when the connection becomes invisible */
g_signal_connect (remote, "notify::" NM_REMOTE_CONNECTION_VISIBLE, G_CALLBACK (visible_changed_cb), &visible_changed); g_signal_connect (gl.remote, "notify::" NM_REMOTE_CONNECTION_VISIBLE, G_CALLBACK (visible_changed_cb), &visible_changed);
g_signal_connect (client, "connection-removed", G_CALLBACK (connection_removed_cb), &connection_removed); g_signal_connect (gl.client, "connection-removed", G_CALLBACK (connection_removed_cb), &connection_removed);
path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote))); path = g_strdup (nm_connection_get_path (NM_CONNECTION (gl.remote)));
proxy = g_dbus_proxy_new_sync (bus, proxy = g_dbus_proxy_new_sync (gl.bus,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL, NULL,
NM_DBUS_SERVICE, NM_DBUS_SERVICE,
@@ -153,29 +151,23 @@ test_make_invisible (void)
set_visible_cb, NULL); set_visible_cb, NULL);
/* Wait for the connection to be removed */ /* Wait for the connection to be removed */
start = time (NULL); nmtst_main_context_iterate_until (NULL, 5000, visible_changed && connection_removed);
do {
now = time (NULL);
g_main_context_iteration (NULL, FALSE);
} while ((!visible_changed || !connection_removed) && (now - start < 5));
g_assert (visible_changed == TRUE);
g_assert (connection_removed == TRUE);
g_signal_handlers_disconnect_by_func (remote, G_CALLBACK (visible_changed_cb), &visible_changed); g_signal_handlers_disconnect_by_func (gl.remote, G_CALLBACK (visible_changed_cb), &visible_changed);
g_signal_handlers_disconnect_by_func (client, G_CALLBACK (connection_removed_cb), &connection_removed); g_signal_handlers_disconnect_by_func (gl.client, G_CALLBACK (connection_removed_cb), &connection_removed);
/* Ensure NMClient no longer has the connection */ /* Ensure NMClient no longer has the connection */
conns = nm_client_get_connections (client); conns = nm_client_get_connections (gl.client);
for (i = 0; i < conns->len; i++) { for (i = 0; i < conns->len; i++) {
NMConnection *candidate = NM_CONNECTION (conns->pdata[i]); NMConnection *candidate = NM_CONNECTION (conns->pdata[i]);
g_assert ((gpointer) remote != (gpointer) candidate); g_assert ((gpointer) gl.remote != (gpointer) candidate);
g_assert (strcmp (path, nm_connection_get_path (candidate)) != 0); g_assert (strcmp (path, nm_connection_get_path (candidate)) != 0);
} }
/* And ensure the invisible connection no longer has any settings */ /* And ensure the invisible connection no longer has any settings */
g_assert (remote); g_assert (gl.remote);
nm_connection_for_each_setting_value (NM_CONNECTION (remote), nm_connection_for_each_setting_value (NM_CONNECTION (gl.remote),
invis_has_settings_cb, invis_has_settings_cb,
&has_settings); &has_settings);
g_assert (has_settings == FALSE); g_assert (has_settings == FALSE);
@@ -197,7 +189,6 @@ vis_new_connection_cb (NMClient *foo,
static void static void
test_make_visible (void) test_make_visible (void)
{ {
time_t start, now;
const GPtrArray *conns; const GPtrArray *conns;
int i; int i;
GDBusProxy *proxy; GDBusProxy *proxy;
@@ -205,17 +196,17 @@ test_make_visible (void)
char *path; char *path;
NMRemoteConnection *new = NULL; NMRemoteConnection *new = NULL;
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (gl.sinfo))
return; return;
g_assert (remote != NULL); g_assert (gl.remote != NULL);
/* Wait for the new-connection signal when the connection is visible again */ /* Wait for the new-connection signal when the connection is visible again */
g_signal_connect (client, NM_CLIENT_CONNECTION_ADDED, g_signal_connect (gl.client, NM_CLIENT_CONNECTION_ADDED,
G_CALLBACK (vis_new_connection_cb), &new); G_CALLBACK (vis_new_connection_cb), &new);
path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote))); path = g_strdup (nm_connection_get_path (NM_CONNECTION (gl.remote)));
proxy = g_dbus_proxy_new_sync (bus, proxy = g_dbus_proxy_new_sync (gl.bus,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL, NULL,
NM_DBUS_SERVICE, NM_DBUS_SERVICE,
@@ -234,24 +225,19 @@ test_make_visible (void)
set_visible_cb, NULL); set_visible_cb, NULL);
/* Wait for the settings service to announce the connection again */ /* Wait for the settings service to announce the connection again */
start = time (NULL); nmtst_main_context_iterate_until (NULL, 5000, new);
do {
now = time (NULL);
g_main_context_iteration (NULL, FALSE);
} while ((new == NULL) && (now - start < 5));
/* Ensure the new connection is the same as the one we made visible again */ /* Ensure the new connection is the same as the one we made visible again */
g_assert (new); g_assert (new == gl.remote);
g_assert (new == remote);
g_signal_handlers_disconnect_by_func (client, G_CALLBACK (vis_new_connection_cb), &new); g_signal_handlers_disconnect_by_func (gl.client, G_CALLBACK (vis_new_connection_cb), &new);
/* Ensure NMClient has the connection */ /* Ensure NMClient has the connection */
conns = nm_client_get_connections (client); conns = nm_client_get_connections (gl.client);
for (i = 0; i < conns->len; i++) { for (i = 0; i < conns->len; i++) {
NMConnection *candidate = NM_CONNECTION (conns->pdata[i]); NMConnection *candidate = NM_CONNECTION (conns->pdata[i]);
if ((gpointer) remote == (gpointer) candidate) { if ((gpointer) gl.remote == (gpointer) candidate) {
g_assert_cmpstr (path, ==, nm_connection_get_path (candidate)); g_assert_cmpstr (path, ==, nm_connection_get_path (candidate));
g_assert_cmpstr (TEST_CON_ID, ==, nm_connection_get_id (candidate)); g_assert_cmpstr (TEST_CON_ID, ==, nm_connection_get_id (candidate));
found = TRUE; found = TRUE;
@@ -282,7 +268,7 @@ deleted_cb (GObject *proxy,
static void static void
removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done) removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done)
{ {
if (connection == remote) if (connection == gl.remote)
*done = TRUE; *done = TRUE;
} }
@@ -290,27 +276,26 @@ static void
test_remove_connection (void) test_remove_connection (void)
{ {
NMRemoteConnection *connection; NMRemoteConnection *connection;
time_t start, now;
const GPtrArray *conns; const GPtrArray *conns;
int i; int i;
GDBusProxy *proxy; GDBusProxy *proxy;
gboolean done = FALSE; gboolean done = FALSE;
char *path; char *path;
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (gl.sinfo))
return; return;
/* Find a connection to delete */ /* Find a connection to delete */
conns = nm_client_get_connections (client); conns = nm_client_get_connections (gl.client);
g_assert_cmpint (conns->len, >, 0); g_assert_cmpint (conns->len, >, 0);
connection = NM_REMOTE_CONNECTION (conns->pdata[0]); connection = NM_REMOTE_CONNECTION (conns->pdata[0]);
g_assert (connection); g_assert (connection);
g_assert (remote == connection); g_assert (gl.remote == connection);
path = g_strdup (nm_connection_get_path (NM_CONNECTION (connection))); path = g_strdup (nm_connection_get_path (NM_CONNECTION (connection)));
g_signal_connect (client, "connection-removed", G_CALLBACK (removed_cb), &done); g_signal_connect (gl.client, "connection-removed", G_CALLBACK (removed_cb), &done);
proxy = g_dbus_proxy_new_sync (bus, proxy = g_dbus_proxy_new_sync (gl.bus,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL, NULL,
NM_DBUS_SERVICE, NM_DBUS_SERVICE,
@@ -328,18 +313,10 @@ test_remove_connection (void)
NULL, NULL,
deleted_cb, NULL); deleted_cb, NULL);
start = time (NULL); nmtst_main_context_iterate_until (NULL, 5000, done && !gl.remote);
do {
now = time (NULL);
g_main_context_iteration (NULL, FALSE);
if (done && !remote)
break;
} while (now - start < 5);
g_assert (done == TRUE);
g_assert (!remote);
/* Ensure NMClient no longer has the connection */ /* Ensure NMClient no longer has the connection */
conns = nm_client_get_connections (client); conns = nm_client_get_connections (gl.client);
for (i = 0; i < conns->len; i++) { for (i = 0; i < conns->len; i++) {
NMConnection *candidate = NM_CONNECTION (conns->pdata[i]); NMConnection *candidate = NM_CONNECTION (conns->pdata[i]);
@@ -364,7 +341,7 @@ add_remove_cb (GObject *s,
gboolean *done = user_data; gboolean *done = user_data;
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
connection = nm_client_add_connection_finish (client, result, &error); connection = nm_client_add_connection_finish (gl.client, result, &error);
g_assert_error (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_OBJECT_CREATION_FAILED); g_assert_error (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_OBJECT_CREATION_FAILED);
g_assert (connection == NULL); g_assert (connection == NULL);
@@ -374,43 +351,34 @@ add_remove_cb (GObject *s,
static void static void
test_add_remove_connection (void) test_add_remove_connection (void)
{ {
GVariant *ret; gs_unref_variant GVariant *ret = NULL;
GError *error = NULL; GError *error = NULL;
NMConnection *connection; gs_unref_object NMConnection *connection = NULL;
time_t start, now;
gboolean done = FALSE; gboolean done = FALSE;
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (gl.sinfo))
return; return;
/* This will cause the test server to immediately delete the connection /* This will cause the test server to immediately delete the connection
* after creating it. * after creating it.
*/ */
ret = g_dbus_proxy_call_sync (sinfo->proxy, ret = g_dbus_proxy_call_sync (gl.sinfo->proxy,
"AutoRemoveNextConnection", "AutoRemoveNextConnection",
NULL, NULL,
G_DBUS_CALL_FLAGS_NONE, -1, G_DBUS_CALL_FLAGS_NONE, -1,
NULL, NULL,
&error); &error);
g_assert_no_error (error); nmtst_assert_success (ret, error);
g_variant_unref (ret);
connection = nmtst_create_minimal_connection (TEST_ADD_REMOVE_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); connection = nmtst_create_minimal_connection (TEST_ADD_REMOVE_ID, NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
nm_client_add_connection_async (client, nm_client_add_connection_async (gl.client,
connection, connection,
TRUE, TRUE,
NULL, NULL,
add_remove_cb, add_remove_cb,
&done); &done);
start = time (NULL); nmtst_main_context_iterate_until (NULL, 5000, done);
do {
now = time (NULL);
g_main_context_iteration (NULL, FALSE);
} while ((done == FALSE) && (now - start < 5));
g_assert (done == TRUE);
g_object_unref (connection);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -423,7 +391,7 @@ add_bad_cb (GObject *s,
gboolean *done = user_data; gboolean *done = user_data;
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
remote = nm_client_add_connection_finish (client, result, &error); gl.remote = nm_client_add_connection_finish (gl.client, result, &error);
g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
*done = TRUE; *done = TRUE;
@@ -432,31 +400,25 @@ add_bad_cb (GObject *s,
static void static void
test_add_bad_connection (void) test_add_bad_connection (void)
{ {
NMConnection *connection; gs_unref_object NMConnection *connection = NULL;
time_t start, now;
gboolean done = FALSE; gboolean done = FALSE;
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (gl.sinfo))
return; return;
/* The test daemon doesn't support bond connections */ /* The test daemon doesn't support bond connections */
connection = nmtst_create_minimal_connection ("bad connection test", NULL, NM_SETTING_BOND_SETTING_NAME, NULL); connection = nmtst_create_minimal_connection ("bad connection test", NULL, NM_SETTING_BOND_SETTING_NAME, NULL);
nm_client_add_connection_async (client, nm_client_add_connection_async (gl.client,
connection, connection,
TRUE, TRUE,
NULL, NULL,
add_bad_cb, add_bad_cb,
&done); &done);
g_object_unref (connection); g_clear_object (&connection);
start = time (NULL); nmtst_main_context_iterate_until (NULL, 5000, done);
do { g_assert (gl.remote == NULL);
now = time (NULL);
g_main_context_iteration (NULL, FALSE);
} while ((done == FALSE) && (now - start < 5));
g_assert (done == TRUE);
g_assert (remote == NULL);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -469,7 +431,7 @@ save_hostname_cb (GObject *s,
gboolean *done = user_data; gboolean *done = user_data;
gs_free_error GError *error = NULL; gs_free_error GError *error = NULL;
nm_client_save_hostname_finish (client, result, &error); nm_client_save_hostname_finish (gl.client, result, &error);
g_assert_no_error (error); g_assert_no_error (error);
*done = TRUE; *done = TRUE;
@@ -478,27 +440,30 @@ save_hostname_cb (GObject *s,
static void static void
test_save_hostname (void) test_save_hostname (void)
{ {
time_t start, now; gint64 until_ts;
gboolean done = FALSE; gboolean done = FALSE;
GError *error = NULL; GError *error = NULL;
if (!nmtstc_service_available (sinfo)) if (!nmtstc_service_available (gl.sinfo))
return; return;
/* test-networkmanager-service.py requires the hostname to contain a '.' */ /* test-networkmanager-service.py requires the hostname to contain a '.' */
nm_client_save_hostname (client, "foo", NULL, &error); nm_client_save_hostname (gl.client, "foo", NULL, &error);
g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_HOSTNAME); g_assert_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_HOSTNAME);
g_clear_error (&error); g_clear_error (&error);
nm_client_save_hostname_async (client, "example.com", NULL, save_hostname_cb, &done); nm_client_save_hostname_async (gl.client, "example.com", NULL, save_hostname_cb, &done);
start = time (NULL); until_ts = nm_utils_get_monotonic_timestamp_ms () + 5000;
do { while (TRUE) {
now = time (NULL);
g_main_context_iteration (NULL, FALSE); g_main_context_iteration (NULL, FALSE);
} while ((done == FALSE) && (now - start < 5)); if (done)
g_assert (done == TRUE); break;
g_assert (remote == NULL); if (nm_utils_get_monotonic_timestamp_ms () >= until_ts)
g_assert_not_reached ();
}
g_assert (gl.remote == NULL);
} }
/*****************************************************************************/ /*****************************************************************************/
@@ -515,14 +480,12 @@ main (int argc, char **argv)
nmtst_init (&argc, &argv, TRUE); nmtst_init (&argc, &argv, TRUE);
bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); gl.bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
g_assert_no_error (error); nmtst_assert_success (gl.bus, error);
sinfo = nmtstc_service_init (); gl.sinfo = nmtstc_service_init ();
client = nm_client_new (NULL, &error); gl.client = nmtstc_client_new (TRUE);
g_assert_no_error (error);
g_assert (client != NULL);
/* FIXME: these tests assume that they get run in order, but g_test_run() /* FIXME: these tests assume that they get run in order, but g_test_run()
* does not actually guarantee that! * does not actually guarantee that!
@@ -537,9 +500,9 @@ main (int argc, char **argv)
ret = g_test_run (); ret = g_test_run ();
nmtstc_service_cleanup (sinfo); nm_clear_pointer (&gl.sinfo, nmtstc_service_cleanup);
g_object_unref (client); g_clear_object (&gl.client);
g_object_unref (bus); g_clear_object (&gl.bus);
return ret; return ret;
} }

View File

@@ -234,8 +234,9 @@ test_setup (TestSecretAgentData *sadata, gconstpointer test_data)
if (!sadata->sinfo) if (!sadata->sinfo)
return; return;
sadata->client = nm_client_new (NULL, &error); g_assert (g_main_context_get_thread_default () == NULL);
g_assert_no_error (error);
sadata->client = nmtstc_client_new (TRUE);
sadata->loop = g_main_loop_new (NULL, FALSE); sadata->loop = g_main_loop_new (NULL, FALSE);
sadata->timeout_id = g_timeout_add_seconds (5, timeout_assert, NULL); sadata->timeout_id = g_timeout_add_seconds (5, timeout_assert, NULL);

View File

@@ -206,3 +206,34 @@ nm_pdirect_equal (gconstpointer a, gconstpointer b)
&& s2 && s2
&& *s1 == *s2); && *s1 == *s2);
} }
guint
nm_ppdirect_hash (gconstpointer p)
{
const void *const*const*s = p;
if (!s)
return nm_hash_static (396534869u);
if (!*s)
return nm_hash_static (1476102263u);
return nm_direct_hash (**s);
}
gboolean
nm_ppdirect_equal (gconstpointer a, gconstpointer b)
{
const void *const*const*s1 = a;
const void *const*const*s2 = b;
if (s1 == s2)
return TRUE;
if (!s1 || !s2)
return FALSE;
if (*s1 == *s2)
return TRUE;
if (!*s1 || !*s2)
return FALSE;
return **s1 == **s2;
}

View File

@@ -279,12 +279,20 @@ gboolean nm_pstr_equal (gconstpointer a, gconstpointer b);
/*****************************************************************************/ /*****************************************************************************/
/* this hashes/compares the pointer value that we point to. Basically, /* this hashes/compares the pointer value that we point to. Basically,
* (((const void *const*) a) == ((const void *const*) b)). */ * (*((const void *const*) a) == *((const void *const*) b)). */
guint nm_pdirect_hash (gconstpointer p); guint nm_pdirect_hash (gconstpointer p);
gboolean nm_pdirect_equal (gconstpointer a, gconstpointer b); gboolean nm_pdirect_equal (gconstpointer a, gconstpointer b);
/* this hashes/compares the direct pointer value by following pointers to
* pointers 2 times.
* (**((const void *const*const*) a) == **((const void *const*const*) b)). */
guint nm_ppdirect_hash (gconstpointer p);
gboolean nm_ppdirect_equal (gconstpointer a, gconstpointer b);
/*****************************************************************************/ /*****************************************************************************/
#define NM_HASH_OBFUSCATE_PTR_FMT "%016" G_GINT64_MODIFIER "x" #define NM_HASH_OBFUSCATE_PTR_FMT "%016" G_GINT64_MODIFIER "x"

View File

@@ -635,6 +635,13 @@ NM_G_ERROR_MSG (GError *error)
#define _NM_ENSURE_TYPE_CONST(type, value) ((const type) (value)) #define _NM_ENSURE_TYPE_CONST(type, value) ((const type) (value))
#endif #endif
#if _NM_CC_SUPPORT_GENERIC
#define NM_STRUCT_OFFSET_ENSURE_TYPE(type, container, field) (_Generic ((((container *) NULL)->field), \
type: G_STRUCT_OFFSET (container, field)))
#else
#define NM_STRUCT_OFFSET_ENSURE_TYPE(type, container, field) G_STRUCT_OFFSET (container, field)
#endif
#if _NM_CC_SUPPORT_GENERIC #if _NM_CC_SUPPORT_GENERIC
/* these macros cast (value) to /* these macros cast (value) to
* - "const char **" (for "MC", mutable-const) * - "const char **" (for "MC", mutable-const)
@@ -1261,6 +1268,17 @@ nm_clear_g_cancellable_disconnect (GCancellable *cancellable, gulong *cancellabl
/*****************************************************************************/ /*****************************************************************************/
static inline const char *
nm_dbus_path_not_empty (const char *str)
{
nm_assert (!str || str[0] == '/');
return !str || (str[0] == '/' && str[1] == '\0')
? NULL
: str;
}
/*****************************************************************************/
/* GVariantType is basically a C string. But G_VARIANT_TYPE() is not suitable /* GVariantType is basically a C string. But G_VARIANT_TYPE() is not suitable
* to initialize a static variable (because it evaluates a function check that * to initialize a static variable (because it evaluates a function check that
* the string is valid). Add an alternative macro that does the plain cast. * the string is valid). Add an alternative macro that does the plain cast.

View File

@@ -180,8 +180,14 @@ _nm_ref_string_unref_non_null (NMRefString *rstr)
/* in the fast-path above, we already decremented the ref-count to zero. /* in the fast-path above, we already decremented the ref-count to zero.
* We need recheck that the ref-count is still zero. */ * We need recheck that the ref-count is still zero. */
if (g_atomic_int_get (&rstr0->ref_count) == 0) if (g_atomic_int_get (&rstr0->ref_count) == 0) {
g_hash_table_remove (gl_hash, rstr0); if (!g_hash_table_remove (gl_hash, rstr0))
nm_assert_not_reached ();
} else {
#if NM_MORE_ASSERTS > 5
nm_assert (g_hash_table_lookup (gl_hash, rstr0) == rstr0);
#endif
}
G_UNLOCK (gl_lock); G_UNLOCK (gl_lock);
} }

View File

@@ -684,6 +684,30 @@ _nm_g_slice_free_fcn_define (32)
/*****************************************************************************/ /*****************************************************************************/
static inline void
nm_g_set_error_take (GError **error, GError *error_take)
{
if (!error_take)
g_return_if_reached ();
if (!error) {
g_error_free (error_take);
return;
}
if (*error) {
g_error_free (error_take);
g_return_if_reached ();
}
*error = error_take;
}
#define nm_g_set_error_take_lazy(error, error_take_lazy) \
G_STMT_START { \
GError **_error = (error); \
\
if (_error) \
nm_g_set_error_take (_error, (error_take_lazy)); \
} G_STMT_END
/** /**
* NMUtilsError: * NMUtilsError:
* @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
@@ -901,6 +925,45 @@ nm_g_source_destroy_and_unref (GSource *source)
g_source_unref (source); g_source_unref (source);
} }
NM_AUTO_DEFINE_FCN0 (GSource *, _nm_auto_destroy_and_unref_gsource, nm_g_source_destroy_and_unref);
#define nm_auto_destroy_and_unref_gsource nm_auto(_nm_auto_destroy_and_unref_gsource)
NM_AUTO_DEFINE_FCN0 (GMainContext *, _nm_auto_pop_gmaincontext, g_main_context_pop_thread_default)
#define nm_auto_pop_gmaincontext nm_auto (_nm_auto_pop_gmaincontext)
static inline GMainContext *
nm_g_main_context_push_thread_default (GMainContext *context)
{
/* This function is to work together with nm_auto_pop_gmaincontext. */
if (G_UNLIKELY (!context))
context = g_main_context_default ();
g_main_context_push_thread_default (context);
return context;
}
static inline GMainContext *
nm_g_main_context_push_thread_default_if_necessary (GMainContext *context)
{
GMainContext *cur_context;
cur_context = g_main_context_get_thread_default ();
if (cur_context == context)
return NULL;
if (G_UNLIKELY (!cur_context)) {
cur_context = g_main_context_default ();
if (cur_context == context)
return NULL;
} else if (G_UNLIKELY (!context)) {
context = g_main_context_default ();
if (cur_context == context)
return NULL;
}
g_main_context_push_thread_default (context);
return context;
}
/*****************************************************************************/ /*****************************************************************************/
static inline int static inline int

View File

@@ -67,3 +67,4 @@ void nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo,
GVariant *connection, GVariant *connection,
gboolean verify_connection); gboolean verify_connection);
NMClient *nmtstc_client_new (gboolean allow_iterate_main_context);

View File

@@ -406,3 +406,151 @@ nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo,
g_assert (g_variant_is_of_type (result, G_VARIANT_TYPE ("()"))); g_assert (g_variant_is_of_type (result, G_VARIANT_TYPE ("()")));
g_variant_unref (result); g_variant_unref (result);
} }
/*****************************************************************************/
typedef struct {
GMainLoop *loop;
NMClient *client;
} NMTstcClientNewData;
static void
_nmtstc_client_new_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
NMTstcClientNewData *d = user_data;
gs_free_error GError *error = NULL;
g_assert (!d->client);
d->client = nm_client_new_finish (res,
nmtst_get_rand_bool () ? &error : NULL);
nmtst_assert_success (NM_IS_CLIENT (d->client), error);
g_main_loop_quit (d->loop);
}
static NMClient *
_nmtstc_client_new (gboolean sync)
{
gs_free GError *error = NULL;
NMClient *client;
/* Create a NMClient instance synchronously, and arbitrarily use either
* the sync or async constructor.
*
* Note that the sync and async construct differ in one important aspect:
* the async constructor iterates the current g_main_context_get_thread_default(),
* while the sync constructor does not! Aside from that, both should behave
* pretty much the same way. */
if (sync) {
nm_auto_destroy_and_unref_gsource GSource *source = NULL;
if (nmtst_get_rand_bool ()) {
/* the current main context must not be iterated! */
source = g_idle_source_new ();
g_source_set_callback (source, nmtst_g_source_assert_not_called, NULL, NULL);
g_source_attach (source, g_main_context_get_thread_default ());
}
if (nmtst_get_rand_bool ()) {
gboolean success;
client = g_object_new (NM_TYPE_CLIENT, NULL);
g_assert (NM_IS_CLIENT (client));
success = g_initable_init (G_INITABLE (client),
NULL,
nmtst_get_rand_bool () ? &error : NULL);
nmtst_assert_success (success, error);
} else {
client = nm_client_new (NULL,
nmtst_get_rand_bool () ? &error : NULL);
}
} else {
nm_auto_unref_gmainloop GMainLoop *loop = NULL;
NMTstcClientNewData d = { .loop = NULL, };
loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
d.loop = loop;
nm_client_new_async (NULL,
_nmtstc_client_new_cb,
&d);
g_main_loop_run (loop);
g_assert (NM_IS_CLIENT (d.client));
client = d.client;
}
nmtst_assert_success (NM_IS_CLIENT (client), error);
return client;
}
typedef struct {
GMainLoop *loop;
NMClient *client;
bool sync;
} NewSyncInsideDispatchedData;
static gboolean
_nmtstc_client_new_inside_loop_do (gpointer user_data)
{
NewSyncInsideDispatchedData *d = user_data;
g_assert (d->loop);
g_assert (!d->client);
d->client = nmtstc_client_new (d->sync);
g_main_loop_quit (d->loop);
return G_SOURCE_CONTINUE;
}
static NMClient *
_nmtstc_client_new_inside_loop (gboolean sync)
{
GMainContext *context = g_main_context_get_thread_default ();
nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new (context, FALSE);
NewSyncInsideDispatchedData d = {
.sync = sync,
.loop = loop,
};
nm_auto_destroy_and_unref_gsource GSource *source = NULL;
source = g_idle_source_new ();
g_source_set_callback (source, _nmtstc_client_new_inside_loop_do, &d, NULL);
g_source_attach (source, context);
g_main_loop_run (loop);
g_assert (NM_IS_CLIENT (d.client));
return d.client;
}
NMClient *
nmtstc_client_new (gboolean allow_iterate_main_context)
{
gboolean inside_loop;
gboolean sync;
if (!allow_iterate_main_context) {
sync = TRUE;
inside_loop = FALSE;
} else {
/* The caller allows to iterate the main context. That that point,
* we can both use the synchronous and the asynchronous initialization,
* both should yield the same result. Choose one randomly. */
sync = nmtst_get_rand_bool ();
inside_loop = ((nmtst_get_rand_uint32 () % 3) == 0);
}
if (inside_loop) {
/* Create the client on an idle handler of the current context.
* In practice, it should make no difference, which this check
* tries to prove. */
return _nmtstc_client_new_inside_loop (sync);
}
return _nmtstc_client_new (sync);
}

View File

@@ -1010,6 +1010,34 @@ _nmtst_main_loop_quit_on_notify (GObject *object, GParamSpec *pspec, gpointer us
} }
#define nmtst_main_loop_quit_on_notify ((GCallback) _nmtst_main_loop_quit_on_notify) #define nmtst_main_loop_quit_on_notify ((GCallback) _nmtst_main_loop_quit_on_notify)
static inline gboolean
_nmtst_main_context_iterate_until_timeout (gpointer user_data)
{
gboolean *p_had_pointer = user_data;
g_assert (!*p_had_pointer);
*p_had_pointer = TRUE;
return G_SOURCE_CONTINUE;
}
#define nmtst_main_context_iterate_until(context, timeout_ms, condition) \
G_STMT_START { \
nm_auto_destroy_and_unref_gsource GSource *_source = NULL; \
GMainContext *_context = (context); \
gboolean _had_timeout = FALSE; \
\
_source = g_timeout_source_new (timeout_ms); \
g_source_set_callback (_source, _nmtst_main_context_iterate_until_timeout, &_had_timeout, NULL); \
g_source_attach (_source, _context); \
\
while (TRUE) { \
if (condition) \
break; \
g_main_context_iteration (_context, TRUE); \
g_assert (!_had_timeout && #condition); \
} \
} G_STMT_END
/*****************************************************************************/ /*****************************************************************************/
static inline const char * static inline const char *

View File

@@ -209,7 +209,7 @@ nm_checkpoint_manager_destroy (NMCheckpointManager *self,
g_return_val_if_fail (path && path[0] == '/', FALSE); g_return_val_if_fail (path && path[0] == '/', FALSE);
g_return_val_if_fail (!error || !*error, FALSE); g_return_val_if_fail (!error || !*error, FALSE);
if (nm_streq (path, "/")) { if (!nm_dbus_path_not_empty (path)) {
nm_checkpoint_manager_destroy_all (self); nm_checkpoint_manager_destroy_all (self);
return TRUE; return TRUE;
} }

View File

@@ -1543,7 +1543,7 @@ p2p_props_changed_cb (GDBusProxy *proxy,
if (g_variant_lookup (changed_properties, "Group", "&o", &path)) { if (g_variant_lookup (changed_properties, "Group", "&o", &path)) {
if (priv->group_proxy && g_strcmp0 (path, g_dbus_proxy_get_object_path (priv->group_proxy)) == 0) { if (priv->group_proxy && g_strcmp0 (path, g_dbus_proxy_get_object_path (priv->group_proxy)) == 0) {
/* We already have the proxy, nothing to do. */ /* We already have the proxy, nothing to do. */
} else if (path && g_strcmp0 (path, "/") != 0) { } else if (nm_dbus_path_not_empty (path)) {
if (priv->group_proxy != NULL) { if (priv->group_proxy != NULL) {
_LOGW ("P2P: Unexpected update of the group object path"); _LOGW ("P2P: Unexpected update of the group object path");
priv->group_proxy_acquired = FALSE; priv->group_proxy_acquired = FALSE;

View File

@@ -672,6 +672,7 @@ PRP_DEVICE_UDI = "Udi"
PRP_DEVICE_IFACE = "Interface" PRP_DEVICE_IFACE = "Interface"
PRP_DEVICE_DRIVER = "Driver" PRP_DEVICE_DRIVER = "Driver"
PRP_DEVICE_STATE = "State" PRP_DEVICE_STATE = "State"
PRP_DEVICE_STATE_REASON = "StateReason"
PRP_DEVICE_ACTIVE_CONNECTION = "ActiveConnection" PRP_DEVICE_ACTIVE_CONNECTION = "ActiveConnection"
PRP_DEVICE_IP4_CONFIG = "Ip4Config" PRP_DEVICE_IP4_CONFIG = "Ip4Config"
PRP_DEVICE_IP6_CONFIG = "Ip6Config" PRP_DEVICE_IP6_CONFIG = "Ip6Config"
@@ -700,11 +701,14 @@ class Device(ExportedObj):
self.dhcp4_config = None self.dhcp4_config = None
self.dhcp6_config = None self.dhcp6_config = None
self.prp_state = NM.DeviceState.UNAVAILABLE
props = { props = {
PRP_DEVICE_UDI: "/sys/devices/virtual/%s" % (iface), PRP_DEVICE_UDI: "/sys/devices/virtual/%s" % (iface),
PRP_DEVICE_IFACE: iface, PRP_DEVICE_IFACE: iface,
PRP_DEVICE_DRIVER: "virtual", PRP_DEVICE_DRIVER: "virtual",
PRP_DEVICE_STATE: dbus.UInt32(NM.DeviceState.UNAVAILABLE), PRP_DEVICE_STATE: dbus.UInt32(self.prp_state),
PRP_DEVICE_STATE_REASON: dbus.Struct((dbus.UInt32(self.prp_state), dbus.UInt32(NM.DeviceStateReason.NONE))),
PRP_DEVICE_ACTIVE_CONNECTION: ExportedObj.to_path(None), PRP_DEVICE_ACTIVE_CONNECTION: ExportedObj.to_path(None),
PRP_DEVICE_IP4_CONFIG: ExportedObj.to_path(self.ip4_config), PRP_DEVICE_IP4_CONFIG: ExportedObj.to_path(self.ip4_config),
PRP_DEVICE_IP6_CONFIG: ExportedObj.to_path(self.ip6_config), PRP_DEVICE_IP6_CONFIG: ExportedObj.to_path(self.ip6_config),
@@ -1302,14 +1306,6 @@ class NetworkManager(ExportedObj):
ac = ActiveConnection(device, con_inst, None) ac = ActiveConnection(device, con_inst, None)
self.active_connection_add(ac) self.active_connection_add(ac)
if NmUtil.con_hash_get_id(con_hash) == 'object-creation-failed-test':
# FIXME: this is not the right test, to delete the active-connection
# before returning it. It's the wrong order of what NetworkManager
# would do.
self.active_connection_remove(ac)
return ExportedObj.to_path(ac)
return ExportedObj.to_path(ac) return ExportedObj.to_path(ac)
def active_connection_add(self, ac): def active_connection_add(self, ac):
@@ -1596,6 +1592,9 @@ class Connection(ExportedObj):
@dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='', out_signature='a{sa{sv}}') @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='', out_signature='a{sa{sv}}')
def GetSettings(self): def GetSettings(self):
if hasattr(self, '_remove_next_connection_cb'):
self._remove_next_connection_cb()
raise BusErr.UnknownConnectionException("Connection not found")
if not self.visible: if not self.visible:
raise BusErr.PermissionDeniedException() raise BusErr.PermissionDeniedException()
return self.con_hash return self.con_hash
@@ -1698,11 +1697,21 @@ class Settings(ExportedObj):
self.NewConnection(con_inst.path) self.NewConnection(con_inst.path)
self._dbus_property_set(IFACE_SETTINGS, PRP_SETTINGS_CONNECTIONS, dbus.Array(self.get_connection_paths(), 'o')) self._dbus_property_set(IFACE_SETTINGS, PRP_SETTINGS_CONNECTIONS, dbus.Array(self.get_connection_paths(), 'o'))
gl.manager.devices_available_connections_update()
if self.remove_next_connection: if self.remove_next_connection:
self.remove_next_connection = False self.remove_next_connection = False
def cb():
if hasattr(con_inst, '_remove_next_connection_cb'):
del con_inst._remove_next_connection_cb
self.delete_connection(con_inst) self.delete_connection(con_inst)
return False
gl.manager.devices_available_connections_update() # We will delete the connection right away on an idle handler. However,
# the test races with initializing the connection (calling GetSettings()).
# To avoid the race, we will check in GetSettings() whether the profile
# is about to be deleted, and delete it first.
con_inst._remove_next_connection_cb = cb
GLib.idle_add(cb)
return con_inst.path return con_inst.path