summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-11-07 13:23:01 +0100
committerThomas Haller <thaller@redhat.com>2019-11-07 13:23:01 +0100
commitb4e62ca73be32afff995de0f1dd5c003f04ce44d (patch)
treef265d326cc8362bdabd85298d2f699ce5770f614
parent4a870c57f52d7f0447c5a11145dca3d46ca57a5c (diff)
parente96bc190d60a574f6a02abe2b9efdcf44558310f (diff)
downloadNetworkManager-b4e62ca73be32afff995de0f1dd5c003f04ce44d.tar.gz
libnm: merge branch 'th/libnm-no-dbus-codegen-3'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/324
-rw-r--r--clients/cli/general.c5
-rwxr-xr-xclients/tests/test-client.py66
-rw-r--r--libnm/nm-client.c35
-rw-r--r--libnm/nm-client.h3
-rw-r--r--libnm/nm-device.c7
-rw-r--r--libnm/nm-device.h2
-rw-r--r--libnm/nm-libnm-utils.c94
-rw-r--r--libnm/nm-libnm-utils.h11
-rw-r--r--libnm/nm-manager.c53
-rw-r--r--libnm/tests/test-nm-client.c302
-rw-r--r--libnm/tests/test-remote-settings-client.c207
-rw-r--r--libnm/tests/test-secret-agent.c5
-rw-r--r--shared/nm-glib-aux/nm-hash-utils.c31
-rw-r--r--shared/nm-glib-aux/nm-hash-utils.h10
-rw-r--r--shared/nm-glib-aux/nm-macros-internal.h18
-rw-r--r--shared/nm-glib-aux/nm-ref-string.c10
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.h63
-rw-r--r--shared/nm-test-libnm-utils.h1
-rw-r--r--shared/nm-test-utils-impl.c148
-rw-r--r--shared/nm-utils/nm-test-utils.h28
-rw-r--r--src/nm-checkpoint-manager.c2
-rw-r--r--src/supplicant/nm-supplicant-interface.c2
-rwxr-xr-xtools/test-networkmanager-service.py33
23 files changed, 681 insertions, 455 deletions
diff --git a/clients/cli/general.c b/clients/cli/general.c
index e246d2828d..123cc5b4fc 100644
--- a/clients/cli/general.c
+++ b/clients/cli/general.c
@@ -600,6 +600,9 @@ permission_changed (NMClient *client,
if (got_permissions (nmc)) {
/* Defer the printing, so that we have a chance to process the other
* permission-changed signals. */
+ g_signal_handlers_disconnect_by_func (nmc->client,
+ G_CALLBACK (permission_changed),
+ nmc);
g_idle_remove_by_data (nmc);
g_idle_add (print_permissions, nmc);
}
@@ -616,7 +619,7 @@ show_nm_permissions (NmCli *nmc)
/* The client didn't get the permissions reply yet. Subscribe to changes. */
g_signal_connect (nmc->client, NM_CLIENT_PERMISSION_CHANGED,
- G_CALLBACK (permission_changed), nmc);
+ G_CALLBACK (permission_changed), nmc);
if (nmc->timeout == -1)
nmc->timeout = 10;
diff --git a/clients/tests/test-client.py b/clients/tests/test-client.py
index af26756def..10739239b8 100755
--- a/clients/tests/test-client.py
+++ b/clients/tests/test-client.py
@@ -91,11 +91,13 @@ import itertools
import subprocess
import shlex
import re
+import fcntl
import dbus
import time
import random
import dbus.service
import dbus.mainloop.glib
+import io
###############################################################################
@@ -173,26 +175,52 @@ class Util:
@staticmethod
def popen_wait(p, timeout = 0):
- if Util.python_has_version(3, 3):
- if timeout == 0:
- return p.poll()
- try:
- return p.wait(timeout)
- except subprocess.TimeoutExpired:
- return None
+ (res, b_stdout, b_stderr) = Util.popen_wait_read(p, timeout = timeout, read_std_pipes = False)
+ return res
+
+ @staticmethod
+ def popen_wait_read(p, timeout = 0, read_std_pipes = True):
start = NM.utils_get_timestamp_msec()
delay = 0.0005
+ b_stdout = b''
+ b_stderr = b''
+ res = None
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:
- return p.returncode
+ res = p.returncode
+ break
if timeout == 0:
- return None
+ break
assert(timeout > 0)
remaining = timeout - ((NM.utils_get_timestamp_msec() - start) / 1000.0)
if remaining <= 0:
- return None
+ break
delay = min(delay * 2, remaining, 0.05)
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
def random_job(jobs):
@@ -459,10 +487,14 @@ class AsyncProcess():
def start(self):
if not hasattr(self, '_p'):
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,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
env = self._env)
+ Util.buffer_set_nonblock(self._p.stdout)
+ Util.buffer_set_nonblock(self._p.stderr)
def _timeout_remaining_time(self):
# note that we call this during poll() and wait_and_complete().
@@ -476,7 +508,11 @@ class AsyncProcess():
def poll(self, timeout = 0):
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 \
and self._timeout_remaining_time() <= 0:
raise Exception("process is still running after timeout: %s" % (' '.join(self._args)))
@@ -488,11 +524,16 @@ class AsyncProcess():
p = self._p
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())
p.stdout.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:
print(stdout)
print(stderr)
@@ -670,6 +711,7 @@ class TestNmcli(NmTestBase):
env['TERM'] = 'linux'
env['ASAN_OPTIONS'] = 'detect_leaks=0'
env['XDG_CONFIG_HOME'] = PathConfiguration.srcdir()
+ env['NM_TEST_CALLING_NUM'] = str(calling_num)
if fatal_warnings is _DEFAULT_ARG or fatal_warnings:
env['G_DEBUG'] = 'fatal-warnings'
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
index 0d84923e28..56367eedc1 100644
--- a/libnm/nm-client.c
+++ b/libnm/nm-client.c
@@ -511,16 +511,15 @@ nm_client_wwan_hardware_get_enabled (NMClient *client)
* Determines whether WiMAX is enabled.
*
* Returns: %TRUE if WiMAX is enabled
+ *
+ * Deprecated: 1.22 This function always returns FALSE because WiMax is no longer supported
**/
gboolean
nm_client_wimax_get_enabled (NMClient *client)
{
g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
- if (!nm_client_get_nm_running (client))
- return FALSE;
-
- return nm_manager_wimax_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
+ return FALSE;
}
/**
@@ -529,16 +528,13 @@ nm_client_wimax_get_enabled (NMClient *client)
* @enabled: %TRUE to enable WiMAX
*
* Enables or disables WiMAX devices.
+ *
+ * Deprecated: 1.22 This function does nothing because WiMax is no longer supported
**/
void
nm_client_wimax_set_enabled (NMClient *client, gboolean enabled)
{
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.
*
* Returns: %TRUE if the WiMAX hardware is enabled
+ *
+ * Deprecated: 1.22 This function always returns FALSE because WiMax is no longer supported
**/
gboolean
nm_client_wimax_hardware_get_enabled (NMClient *client)
{
g_return_val_if_fail (NM_IS_CLIENT (client), FALSE);
- if (!nm_client_get_nm_running (client))
- return FALSE;
-
- return nm_manager_wimax_hardware_get_enabled (NM_CLIENT_GET_PRIVATE (client)->manager);
+ return FALSE;
}
/**
@@ -3540,13 +3535,10 @@ get_property (GObject *object, guint prop_id,
g_value_set_boolean (value, FALSE);
break;
case PROP_WIMAX_ENABLED:
- g_value_set_boolean (value, nm_client_wimax_get_enabled (self));
+ g_value_set_boolean (value, FALSE);
break;
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;
case PROP_ACTIVE_CONNECTIONS:
g_value_take_boxed (value, _nm_utils_copy_object_array (nm_client_get_active_connections (self)));
@@ -3643,11 +3635,12 @@ set_property (GObject *object, guint prop_id,
case PROP_NETWORKING_ENABLED:
case PROP_WIRELESS_ENABLED:
case PROP_WWAN_ENABLED:
- case PROP_WIMAX_ENABLED:
case PROP_CONNECTIVITY_CHECK_ENABLED:
if (priv->manager)
g_object_set_property (G_OBJECT (priv->manager), pspec->name, value);
break;
+ case PROP_WIMAX_ENABLED:
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -4015,7 +4008,7 @@ nm_client_class_init (NMClientClass *client_class)
*
* 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] =
g_param_spec_boolean (NM_CLIENT_WIMAX_ENABLED, "", "",
@@ -4027,6 +4020,8 @@ nm_client_class_init (NMClientClass *client_class)
* NMClient:wimax-hardware-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] =
g_param_spec_boolean (NM_CLIENT_WIMAX_HARDWARE_ENABLED, "", "",
diff --git a/libnm/nm-client.h b/libnm/nm-client.h
index f1822c5ea3..41481f11f7 100644
--- a/libnm/nm-client.h
+++ b/libnm/nm-client.h
@@ -245,11 +245,14 @@ void nm_client_wwan_set_enabled (NMClient *client, gboolean enabled);
gboolean nm_client_wwan_hardware_get_enabled (NMClient *client);
+NM_DEPRECATED_IN_1_22
gboolean nm_client_wimax_get_enabled (NMClient *client);
+NM_DEPRECATED_IN_1_22
_NM_DEPRECATED_SYNC_METHOD
void nm_client_wimax_set_enabled (NMClient *client, gboolean enabled);
+NM_DEPRECATED_IN_1_22
gboolean nm_client_wimax_hardware_get_enabled (NMClient *client);
NM_AVAILABLE_IN_1_10
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
index 96698967b9..8344f2a037 100644
--- a/libnm/nm-device.c
+++ b/libnm/nm-device.c
@@ -1066,6 +1066,10 @@ nm_device_get_managed (NMDevice *device)
* Since: 1.2
*
* 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
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.
*
* 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
nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect)
diff --git a/libnm/nm-device.h b/libnm/nm-device.h
index ede606d8e9..bc8aad63df 100644
--- a/libnm/nm-device.h
+++ b/libnm/nm-device.h
@@ -77,11 +77,13 @@ NMDeviceCapabilities nm_device_get_capabilities (NMDevice *device);
gboolean nm_device_get_managed (NMDevice *device);
NM_AVAILABLE_IN_1_2
+NM_DEPRECATED_IN_1_22
_NM_DEPRECATED_SYNC_METHOD
void nm_device_set_managed (NMDevice *device, gboolean managed);
gboolean nm_device_get_autoconnect (NMDevice *device);
+NM_DEPRECATED_IN_1_22
_NM_DEPRECATED_SYNC_METHOD
void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect);
diff --git a/libnm/nm-libnm-utils.c b/libnm/nm-libnm-utils.c
index 7d34d2fd41..5638d0eae0 100644
--- a/libnm/nm-libnm-utils.c
+++ b/libnm/nm-libnm-utils.c
@@ -8,6 +8,9 @@
#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;
@@ -43,6 +46,7 @@ _nml_dbus_log (NMLDBusLogLevel level,
gs_free char *msg = NULL;
va_list args;
const char *prefix = "";
+ gint64 ts;
/* 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
@@ -84,7 +88,13 @@ _nml_dbus_log (NMLDBusLogLevel level,
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;
}
+
+/*****************************************************************************/
+
+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;
+}
diff --git a/libnm/nm-libnm-utils.h b/libnm/nm-libnm-utils.h
index 39b86aac64..484c00396f 100644
--- a/libnm/nm-libnm-utils.h
+++ b/libnm/nm-libnm-utils.h
@@ -8,6 +8,7 @@
#include "nm-types.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 {
_NML_DBUS_LOG_LEVEL_INITIALIZED = 0x01,
@@ -124,9 +131,7 @@ _nml_coerce_property_object_path (NMRefString *path)
{
if (!path)
return NULL;
- if (nm_streq (path->str, "/"))
- return NULL;
- return path->str;
+ return nm_dbus_path_not_empty (path->str);
}
static inline const char *const*
diff --git a/libnm/nm-manager.c b/libnm/nm-manager.c
index 872c9fa8b9..b88aba098e 100644
--- a/libnm/nm-manager.c
+++ b/libnm/nm-manager.c
@@ -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
update_permissions (NMManager *self, GVariant *permissions)
{
diff --git a/libnm/tests/test-nm-client.c b/libnm/tests/test-nm-client.c
index f97aa56077..c6b26a21ab 100644
--- a/libnm/tests/test-nm-client.c
+++ b/libnm/tests/test-nm-client.c
@@ -10,8 +10,9 @@
#include "nm-test-libnm-utils.h"
-static GMainLoop *loop = NULL;
-static NMTstcServiceInfo *sinfo;
+static struct {
+ 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
devices_notify_cb (NMClient *c,
GParamSpec *pspec,
@@ -109,7 +48,8 @@ devices_notify_cb (NMClient *c,
static void
test_device_added (void)
{
- NMClient *client;
+ nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
+ gs_unref_object NMClient *client = NULL;
const GPtrArray *devices;
NMDevice *device;
gboolean notified = FALSE;
@@ -119,8 +59,7 @@ test_device_added (void)
if (!nmtstc_service_available (sinfo))
return;
- client = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ client = nmtstc_client_new (TRUE);
devices = nm_client_get_devices (client);
g_assert (devices->len == 0);
@@ -151,9 +90,6 @@ test_device_added (void)
nm_device_delete (device, NULL, &error);
g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_SOFTWARE);
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;
NMDevice *device;
+ g_assert_cmpstr (pspec->name, ==, "devices");
+
devices = nm_client_get_devices (c);
g_assert (devices);
g_assert_cmpint (devices->len, ==, 1);
@@ -205,18 +143,17 @@ devices_sai_notify_cb (NMClient *c,
static 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;
NMDevice *device;
guint result = 0;
- GError *error = NULL;
sinfo = nmtstc_service_init ();
if (!nmtstc_service_available (sinfo))
return;
- client = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ client = nmtstc_client_new (TRUE);
devices = nm_client_get_devices (client);
g_assert (devices->len == 0);
@@ -253,9 +190,6 @@ test_device_added_signal_after_init (void)
device = g_ptr_array_index (devices, 0);
g_assert (device);
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
test_wifi_ap_added_removed (void)
{
- NMClient *client;
+ nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
+ gs_unref_object NMClient *client = NULL;
NMDeviceWifi *wifi;
- WifiApInfo info = { loop, FALSE, FALSE, 0, 0 };
+ WifiApInfo info = { gl.loop, FALSE, FALSE, 0, 0 };
GVariant *ret;
GError *error = NULL;
- char *expected_path = NULL;
+ gs_free char *expected_path = NULL;
sinfo = nmtstc_service_init ();
if (!nmtstc_service_available (sinfo))
return;
- client = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ client = nmtstc_client_new (TRUE);
/*************************************/
/* Add the wifi device */
@@ -406,8 +340,8 @@ test_wifi_ap_added_removed (void)
info.quit_count++;
/* Wait for libnm to find the AP */
- info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
- g_main_loop_run (loop);
+ info.quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
+ g_main_loop_run (gl.loop);
g_assert (info.signaled);
g_assert (info.notified);
@@ -445,8 +379,8 @@ test_wifi_ap_added_removed (void)
info.quit_count++;
/* Wait for libnm to find the AP */
- info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
- g_main_loop_run (loop);
+ info.quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
+ g_main_loop_run (gl.loop);
g_assert (info.signaled);
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_free (info.ap_path);
- g_free (expected_path);
-
- g_object_unref (client);
- g_clear_pointer (&sinfo, nmtstc_service_cleanup);
}
/*****************************************************************************/
@@ -517,25 +447,11 @@ da_devices_notify_cb (NMClient *c,
}
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
test_devices_array (void)
{
- NMClient *client = NULL;
- DaInfo info = { loop };
+ nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
+ gs_unref_object NMClient *client = NULL;
+ DaInfo info = { gl.loop };
NMDevice *wlan0, *eth0, *eth1, *device;
const GPtrArray *devices;
GError *error = NULL;
@@ -545,10 +461,7 @@ test_devices_array (void)
if (!nmtstc_service_available (sinfo))
return;
- /* Make sure that we test the async codepath in at least one test... */
- nm_client_new_async (NULL, new_client_cb, &client);
- g_main_loop_run (loop);
- g_assert (client != NULL);
+ client = nmtstc_client_new (TRUE);
/*************************************/
/* Add some devices */
@@ -598,8 +511,8 @@ test_devices_array (void)
info.quit_count = 2;
/* Wait for libnm to notice the changes */
- info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
- g_main_loop_run (loop);
+ info.quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
+ g_main_loop_run (gl.loop);
g_assert_cmpint (info.quit_count, ==, 0);
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");
g_assert (NM_IS_DEVICE_ETHERNET (device));
g_assert (device == eth1);
-
- g_object_unref (client);
- g_clear_pointer (&sinfo, nmtstc_service_cleanup);
}
static void
@@ -630,20 +540,20 @@ nm_running_changed (GObject *client,
int *running_changed = user_data;
(*running_changed)++;
- g_main_loop_quit (loop);
+ g_main_loop_quit (gl.loop);
}
static void
test_client_nm_running (void)
{
+ nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
gs_unref_object NMClient *client1 = NULL;
gs_unref_object NMClient *client2 = NULL;
guint quit_id;
int running_changed = 0;
GError *error = NULL;
- client1 = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ client1 = nmtstc_client_new (TRUE);
g_assert (!nm_client_get_nm_running (client1));
g_assert_cmpstr (nm_client_get_version (client1), ==, NULL);
@@ -663,8 +573,7 @@ test_client_nm_running (void)
if (!nmtstc_service_available (sinfo))
return;
- client2 = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ client2 = nmtstc_client_new (FALSE);
/* client2 should know that NM is running, but the previously-created
* 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_CALLBACK (nm_running_changed), &running_changed);
- quit_id = g_timeout_add_seconds (5, loop_quit, loop);
- g_main_loop_run (loop);
+ quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
+ g_main_loop_run (gl.loop);
g_assert_cmpint (running_changed, ==, 1);
g_assert (nm_client_get_nm_running (client1));
g_source_remove (quit_id);
@@ -685,8 +594,8 @@ test_client_nm_running (void)
g_assert (nm_client_get_nm_running (client1));
- quit_id = g_timeout_add_seconds (5, loop_quit, loop);
- g_main_loop_run (loop);
+ quit_id = g_timeout_add_seconds (5, loop_quit, gl.loop);
+ g_main_loop_run (gl.loop);
g_assert_cmpint (running_changed, ==, 2);
g_assert (!nm_client_get_nm_running (client1));
g_source_remove (quit_id);
@@ -697,6 +606,9 @@ typedef struct {
NMActiveConnection *ac;
int remaining;
+
+ NMDevice *device;
+ gulong ac_signal_id;
} TestACInfo;
static void
@@ -786,18 +698,17 @@ device_ac_changed_cb (GObject *device,
static void
test_active_connections (void)
{
- NMClient *client;
+ nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
+ gs_unref_object NMClient *client = NULL;
NMDevice *device;
NMConnection *conn;
- TestACInfo info = { loop, NULL, 0 };
- GError *error = NULL;
+ TestACInfo info = { gl.loop, NULL, 0 };
sinfo = nmtstc_service_init ();
if (!nmtstc_service_available (sinfo))
return;
- client = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ client = nmtstc_client_new (TRUE);
/* Tell the test service to add a new device */
device = nmtstc_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
@@ -814,30 +725,25 @@ test_active_connections (void)
/* Two signals plus activate_cb */
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 (device, device_ac_changed_cb, &info);
g_assert (info.ac != NULL);
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
* AC and the Device in a newly-created client.
*/
- client = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ client = nmtstc_client_new (TRUE);
assert_ac_and_device (client);
- g_object_unref (client);
+ g_clear_object (&client);
- client = NULL;
- nm_client_new_async (NULL, new_client_cb, &client);
- g_main_loop_run (loop);
+ client = nmtstc_client_new (TRUE);
assert_ac_and_device (client);
- g_object_unref (client);
-
- g_clear_pointer (&sinfo, nmtstc_service_cleanup);
+ g_clear_object (&client);
}
static void
@@ -865,9 +771,12 @@ client_devices_changed_cb (GObject *client,
g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0.1");
if (!nm_device_get_active_connection (device)) {
+ g_assert (info->ac_signal_id == 0);
info->remaining++;
- g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION,
- G_CALLBACK (device_ac_changed_cb), info);
+ 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);
}
info->remaining--;
@@ -916,20 +825,19 @@ activate_cb (GObject *object,
static void
test_activate_virtual (void)
{
- NMClient *client;
+ nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
+ gs_unref_object NMClient *client = NULL;
NMConnection *conn;
NMSettingConnection *s_con;
NMSettingVlan *s_vlan;
- TestACInfo info = { loop, NULL, 0 };
- TestConnectionInfo conn_info = { loop, NULL };
- GError *error = NULL;
+ TestACInfo info = { gl.loop, NULL, 0 };
+ TestConnectionInfo conn_info = { gl.loop, NULL };
sinfo = nmtstc_service_init ();
if (!nmtstc_service_available (sinfo))
return;
- client = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ client = nmtstc_client_new (TRUE);
nmtstc_service_add_device (sinfo, client, "AddWiredDevice", "eth0");
@@ -945,7 +853,7 @@ test_activate_virtual (void)
nm_client_add_connection_async (client, conn, TRUE,
NULL, add_connection_cb, &conn_info);
- g_main_loop_run (loop);
+ g_main_loop_run (gl.loop);
g_object_unref (conn);
conn = NM_CONNECTION (conn_info.remote);
@@ -965,72 +873,27 @@ test_activate_virtual (void)
*/
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_devices_changed_cb, &info);
g_assert (info.ac != NULL);
+ g_clear_object (&info.ac);
- g_object_unref (info.ac);
- g_object_unref (client);
-
- 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);
+ if (info.device) {
+ g_object_remove_weak_pointer (G_OBJECT (info.device), (gpointer *) &info.device);
+ nm_clear_g_signal_handler (info.device, &info.ac_signal_id);
+ }
}
static void
test_device_connection_compatibility (void)
{
- NMClient *client;
- NMDevice *device1, *device2;
- NMConnection *conn;
+ nmtstc_auto_service_cleanup NMTstcServiceInfo *sinfo = NULL;
+ gs_unref_object NMClient *client = NULL;
+ gs_unref_object NMConnection *conn = NULL;
+ NMDevice *device1;
+ NMDevice *device2;
NMSettingWired *s_wired;
GError *error = 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))
return;
- client = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ client = nmtstc_client_new (TRUE);
/* Create two devices */
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);
g_assert_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION);
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,
&path2);
- client = nmtst_get_rand_bool ()
- ? _nm_client_new_sync ()
- : _nm_client_new_sync_inside_dispatched ();
+ client = nmtstc_client_new (TRUE);
connections = nm_client_get_connections (client);
g_assert (connections);
@@ -1216,7 +1071,7 @@ test_connection_invalid (void)
FALSE,
&path3);
- nmtst_main_loop_run (loop, 1000);
+ nmtst_main_loop_run (gl.loop, 1000);
connections = nm_client_get_connections (client);
g_assert (connections);
@@ -1252,7 +1107,7 @@ test_connection_invalid (void)
variant,
FALSE);
- nmtst_main_loop_run (loop, 100);
+ nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client);
g_assert (connections);
@@ -1290,7 +1145,7 @@ test_connection_invalid (void)
variant,
FALSE);
- nmtst_main_loop_run (loop, 100);
+ nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client);
g_assert (connections);
@@ -1325,7 +1180,7 @@ test_connection_invalid (void)
connection,
FALSE);
- nmtst_main_loop_run (loop, 100);
+ nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client);
g_assert (connections);
@@ -1367,7 +1222,7 @@ test_connection_invalid (void)
connection,
FALSE);
- nmtst_main_loop_run (loop, 100);
+ nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client);
g_assert (connections);
@@ -1409,7 +1264,7 @@ test_connection_invalid (void)
connection,
FALSE);
- nmtst_main_loop_run (loop, 100);
+ nmtst_main_loop_run (gl.loop, 100);
connections = nm_client_get_connections (client);
g_assert (connections);
@@ -1448,7 +1303,7 @@ main (int argc, char **argv)
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-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/active-connections", test_active_connections);
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/connection/invalid", test_connection_invalid);
diff --git a/libnm/tests/test-remote-settings-client.c b/libnm/tests/test-remote-settings-client.c
index 7017808972..8483eca838 100644
--- a/libnm/tests/test-remote-settings-client.c
+++ b/libnm/tests/test-remote-settings-client.c
@@ -8,12 +8,16 @@
#include <sys/types.h>
#include <signal.h>
+#include "nm-glib-aux/nm-time-utils.h"
+
#include "nm-test-libnm-utils.h"
-static NMTstcServiceInfo *sinfo;
-static NMClient *client = NULL;
-GDBusConnection *bus = NULL;
-NMRemoteConnection *remote = NULL;
+static struct {
+ NMTstcServiceInfo *sinfo;
+ NMClient *client;
+ GDBusConnection *bus;
+ NMRemoteConnection *remote;
+} gl = { };
/*****************************************************************************/
@@ -25,17 +29,17 @@ add_cb (GObject *s,
gboolean *done = user_data;
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);
*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
* want the weak pointer to be cleared as soon as @client drops its own ref.
* So drop ours.
*/
- g_object_unref (remote);
+ g_object_unref (gl.remote);
}
#define TEST_CON_ID "blahblahblah"
@@ -44,32 +48,27 @@ static void
test_add_connection (void)
{
NMConnection *connection;
- time_t start, now;
gboolean done = FALSE;
- if (!nmtstc_service_available (sinfo))
+ if (!nmtstc_service_available (gl.sinfo))
return;
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,
TRUE,
NULL,
add_cb,
&done);
- start = time (NULL);
- do {
- now = time (NULL);
- g_main_context_iteration (NULL, FALSE);
- } while ((done == FALSE) && (now - start < 5));
- g_assert (done == TRUE);
- g_assert (remote != NULL);
+ nmtst_main_context_iterate_until (NULL, 5000, done);
+
+ g_assert (gl.remote != NULL);
/* Make sure the connection is the same as what we added */
g_assert (nm_connection_compare (connection,
- NM_CONNECTION (remote),
+ NM_CONNECTION (gl.remote),
NM_SETTING_COMPARE_FLAG_EXACT) == TRUE);
g_object_unref (connection);
}
@@ -99,7 +98,7 @@ visible_changed_cb (GObject *object, GParamSpec *pspec, gboolean *done)
static void
connection_removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done)
{
- if (connection == remote)
+ if (connection == gl.remote)
*done = TRUE;
}
@@ -116,7 +115,6 @@ invis_has_settings_cb (NMSetting *setting,
static void
test_make_invisible (void)
{
- time_t start, now;
const GPtrArray *conns;
int i;
GDBusProxy *proxy;
@@ -124,17 +122,17 @@ test_make_invisible (void)
gboolean has_settings = FALSE;
char *path;
- if (!nmtstc_service_available (sinfo))
+ if (!nmtstc_service_available (gl.sinfo))
return;
- g_assert (remote != NULL);
+ g_assert (gl.remote != NULL);
/* 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 (client, "connection-removed", G_CALLBACK (connection_removed_cb), &connection_removed);
+ g_signal_connect (gl.remote, "notify::" NM_REMOTE_CONNECTION_VISIBLE, G_CALLBACK (visible_changed_cb), &visible_changed);
+ g_signal_connect (gl.client, "connection-removed", G_CALLBACK (connection_removed_cb), &connection_removed);
- path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote)));
- proxy = g_dbus_proxy_new_sync (bus,
+ path = g_strdup (nm_connection_get_path (NM_CONNECTION (gl.remote)));
+ proxy = g_dbus_proxy_new_sync (gl.bus,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
NM_DBUS_SERVICE,
@@ -153,29 +151,23 @@ test_make_invisible (void)
set_visible_cb, NULL);
/* Wait for the connection to be removed */
- start = time (NULL);
- 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);
+ nmtst_main_context_iterate_until (NULL, 5000, visible_changed && connection_removed);
- g_signal_handlers_disconnect_by_func (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.remote, G_CALLBACK (visible_changed_cb), &visible_changed);
+ g_signal_handlers_disconnect_by_func (gl.client, G_CALLBACK (connection_removed_cb), &connection_removed);
/* 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++) {
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);
}
/* And ensure the invisible connection no longer has any settings */
- g_assert (remote);
- nm_connection_for_each_setting_value (NM_CONNECTION (remote),
+ g_assert (gl.remote);
+ nm_connection_for_each_setting_value (NM_CONNECTION (gl.remote),
invis_has_settings_cb,
&has_settings);
g_assert (has_settings == FALSE);
@@ -197,7 +189,6 @@ vis_new_connection_cb (NMClient *foo,
static void
test_make_visible (void)
{
- time_t start, now;
const GPtrArray *conns;
int i;
GDBusProxy *proxy;
@@ -205,17 +196,17 @@ test_make_visible (void)
char *path;
NMRemoteConnection *new = NULL;
- if (!nmtstc_service_available (sinfo))
+ if (!nmtstc_service_available (gl.sinfo))
return;
- g_assert (remote != NULL);
+ g_assert (gl.remote != NULL);
/* 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);
- path = g_strdup (nm_connection_get_path (NM_CONNECTION (remote)));
- proxy = g_dbus_proxy_new_sync (bus,
+ path = g_strdup (nm_connection_get_path (NM_CONNECTION (gl.remote)));
+ proxy = g_dbus_proxy_new_sync (gl.bus,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
NM_DBUS_SERVICE,
@@ -234,24 +225,19 @@ test_make_visible (void)
set_visible_cb, NULL);
/* Wait for the settings service to announce the connection again */
- start = time (NULL);
- do {
- now = time (NULL);
- g_main_context_iteration (NULL, FALSE);
- } while ((new == NULL) && (now - start < 5));
+ nmtst_main_context_iterate_until (NULL, 5000, new);
/* Ensure the new connection is the same as the one we made visible again */
- g_assert (new);
- g_assert (new == remote);
+ g_assert (new == gl.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 */
- conns = nm_client_get_connections (client);
+ conns = nm_client_get_connections (gl.client);
for (i = 0; i < conns->len; 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 (TEST_CON_ID, ==, nm_connection_get_id (candidate));
found = TRUE;
@@ -282,7 +268,7 @@ deleted_cb (GObject *proxy,
static void
removed_cb (NMClient *s, NMRemoteConnection *connection, gboolean *done)
{
- if (connection == remote)
+ if (connection == gl.remote)
*done = TRUE;
}
@@ -290,27 +276,26 @@ static void
test_remove_connection (void)
{
NMRemoteConnection *connection;
- time_t start, now;
const GPtrArray *conns;
int i;
GDBusProxy *proxy;
gboolean done = FALSE;
char *path;
- if (!nmtstc_service_available (sinfo))
+ if (!nmtstc_service_available (gl.sinfo))
return;
/* Find a connection to delete */
- conns = nm_client_get_connections (client);
+ conns = nm_client_get_connections (gl.client);
g_assert_cmpint (conns->len, >, 0);
connection = NM_REMOTE_CONNECTION (conns->pdata[0]);
g_assert (connection);
- g_assert (remote == connection);
+ g_assert (gl.remote == 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,
NULL,
NM_DBUS_SERVICE,
@@ -328,18 +313,10 @@ test_remove_connection (void)
NULL,
deleted_cb, NULL);
- start = time (NULL);
- 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);
+ nmtst_main_context_iterate_until (NULL, 5000, done && !gl.remote);
/* 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++) {
NMConnection *candidate = NM_CONNECTION (conns->pdata[i]);
@@ -364,7 +341,7 @@ add_remove_cb (GObject *s,
gboolean *done = user_data;
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 (connection == NULL);
@@ -374,43 +351,34 @@ add_remove_cb (GObject *s,
static void
test_add_remove_connection (void)
{
- GVariant *ret;
+ gs_unref_variant GVariant *ret = NULL;
GError *error = NULL;
- NMConnection *connection;
- time_t start, now;
+ gs_unref_object NMConnection *connection = NULL;
gboolean done = FALSE;
- if (!nmtstc_service_available (sinfo))
+ if (!nmtstc_service_available (gl.sinfo))
return;
/* This will cause the test server to immediately delete the connection
* after creating it.
*/
- ret = g_dbus_proxy_call_sync (sinfo->proxy,
+ ret = g_dbus_proxy_call_sync (gl.sinfo->proxy,
"AutoRemoveNextConnection",
NULL,
G_DBUS_CALL_FLAGS_NONE, -1,
NULL,
&error);
- g_assert_no_error (error);
- g_variant_unref (ret);
+ nmtst_assert_success (ret, error);
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,
TRUE,
NULL,
add_remove_cb,
&done);
- start = time (NULL);
- do {
- now = time (NULL);
- g_main_context_iteration (NULL, FALSE);
- } while ((done == FALSE) && (now - start < 5));
- g_assert (done == TRUE);
-
- g_object_unref (connection);
+ nmtst_main_context_iterate_until (NULL, 5000, done);
}
/*****************************************************************************/
@@ -423,7 +391,7 @@ add_bad_cb (GObject *s,
gboolean *done = user_data;
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);
*done = TRUE;
@@ -432,31 +400,25 @@ add_bad_cb (GObject *s,
static void
test_add_bad_connection (void)
{
- NMConnection *connection;
- time_t start, now;
+ gs_unref_object NMConnection *connection = NULL;
gboolean done = FALSE;
- if (!nmtstc_service_available (sinfo))
+ if (!nmtstc_service_available (gl.sinfo))
return;
/* The test daemon doesn't support bond connections */
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,
TRUE,
NULL,
add_bad_cb,
&done);
- g_object_unref (connection);
+ g_clear_object (&connection);
- start = time (NULL);
- do {
- now = time (NULL);
- g_main_context_iteration (NULL, FALSE);
- } while ((done == FALSE) && (now - start < 5));
- g_assert (done == TRUE);
- g_assert (remote == NULL);
+ nmtst_main_context_iterate_until (NULL, 5000, done);
+ g_assert (gl.remote == NULL);
}
/*****************************************************************************/
@@ -469,7 +431,7 @@ save_hostname_cb (GObject *s,
gboolean *done = user_data;
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);
*done = TRUE;
@@ -478,27 +440,30 @@ save_hostname_cb (GObject *s,
static void
test_save_hostname (void)
{
- time_t start, now;
+ gint64 until_ts;
gboolean done = FALSE;
GError *error = NULL;
- if (!nmtstc_service_available (sinfo))
+ if (!nmtstc_service_available (gl.sinfo))
return;
/* 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_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);
- do {
- now = time (NULL);
+ until_ts = nm_utils_get_monotonic_timestamp_ms () + 5000;
+ while (TRUE) {
g_main_context_iteration (NULL, FALSE);
- } while ((done == FALSE) && (now - start < 5));
- g_assert (done == TRUE);
- g_assert (remote == NULL);
+ if (done)
+ break;
+ 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);
- bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
- g_assert_no_error (error);
+ gl.bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+ nmtst_assert_success (gl.bus, error);
- sinfo = nmtstc_service_init ();
+ gl.sinfo = nmtstc_service_init ();
- client = nm_client_new (NULL, &error);
- g_assert_no_error (error);
- g_assert (client != NULL);
+ gl.client = nmtstc_client_new (TRUE);
/* FIXME: these tests assume that they get run in order, but g_test_run()
* does not actually guarantee that!
@@ -537,9 +500,9 @@ main (int argc, char **argv)
ret = g_test_run ();
- nmtstc_service_cleanup (sinfo);
- g_object_unref (client);
- g_object_unref (bus);
+ nm_clear_pointer (&gl.sinfo, nmtstc_service_cleanup);
+ g_clear_object (&gl.client);
+ g_clear_object (&gl.bus);
return ret;
}
diff --git a/libnm/tests/test-secret-agent.c b/libnm/tests/test-secret-agent.c
index bb822a0a0e..fef6071df9 100644
--- a/libnm/tests/test-secret-agent.c
+++ b/libnm/tests/test-secret-agent.c
@@ -234,8 +234,9 @@ test_setup (TestSecretAgentData *sadata, gconstpointer test_data)
if (!sadata->sinfo)
return;
- sadata->client = nm_client_new (NULL, &error);
- g_assert_no_error (error);
+ g_assert (g_main_context_get_thread_default () == NULL);
+
+ sadata->client = nmtstc_client_new (TRUE);
sadata->loop = g_main_loop_new (NULL, FALSE);
sadata->timeout_id = g_timeout_add_seconds (5, timeout_assert, NULL);
diff --git a/shared/nm-glib-aux/nm-hash-utils.c b/shared/nm-glib-aux/nm-hash-utils.c
index 8fef015f8b..a821259815 100644
--- a/shared/nm-glib-aux/nm-hash-utils.c
+++ b/shared/nm-glib-aux/nm-hash-utils.c
@@ -206,3 +206,34 @@ nm_pdirect_equal (gconstpointer a, gconstpointer b)
&& 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;
+}
diff --git a/shared/nm-glib-aux/nm-hash-utils.h b/shared/nm-glib-aux/nm-hash-utils.h
index 2e7b35183f..c95cc6db91 100644
--- a/shared/nm-glib-aux/nm-hash-utils.h
+++ b/shared/nm-glib-aux/nm-hash-utils.h
@@ -279,12 +279,20 @@ gboolean nm_pstr_equal (gconstpointer a, gconstpointer b);
/*****************************************************************************/
/* 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);
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"
diff --git a/shared/nm-glib-aux/nm-macros-internal.h b/shared/nm-glib-aux/nm-macros-internal.h
index 52441cf144..81b56b583e 100644
--- a/shared/nm-glib-aux/nm-macros-internal.h
+++ b/shared/nm-glib-aux/nm-macros-internal.h
@@ -636,6 +636,13 @@ NM_G_ERROR_MSG (GError *error)
#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
/* these macros cast (value) to
* - "const char **" (for "MC", mutable-const)
* - "const char *const*" (for "CC", const-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
* 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.
diff --git a/shared/nm-glib-aux/nm-ref-string.c b/shared/nm-glib-aux/nm-ref-string.c
index f128d55832..0a0b0d3a41 100644
--- a/shared/nm-glib-aux/nm-ref-string.c
+++ b/shared/nm-glib-aux/nm-ref-string.c
@@ -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.
* We need recheck that the ref-count is still zero. */
- if (g_atomic_int_get (&rstr0->ref_count) == 0)
- g_hash_table_remove (gl_hash, rstr0);
+ if (g_atomic_int_get (&rstr0->ref_count) == 0) {
+ 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);
}
diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h
index c027769aa2..5f1edcb219 100644
--- a/shared/nm-glib-aux/nm-shared-utils.h
+++ b/shared/nm-glib-aux/nm-shared-utils.h
@@ -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:
* @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
@@ -901,6 +925,45 @@ nm_g_source_destroy_and_unref (GSource *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
diff --git a/shared/nm-test-libnm-utils.h b/shared/nm-test-libnm-utils.h
index 76e2a2158c..63e3b4c72c 100644
--- a/shared/nm-test-libnm-utils.h
+++ b/shared/nm-test-libnm-utils.h
@@ -67,3 +67,4 @@ void nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo,
GVariant *connection,
gboolean verify_connection);
+NMClient *nmtstc_client_new (gboolean allow_iterate_main_context);
diff --git a/shared/nm-test-utils-impl.c b/shared/nm-test-utils-impl.c
index 39f0a08325..bbe74a9656 100644
--- a/shared/nm-test-utils-impl.c
+++ b/shared/nm-test-utils-impl.c
@@ -406,3 +406,151 @@ nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo,
g_assert (g_variant_is_of_type (result, G_VARIANT_TYPE ("()")));
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);
+}
diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h
index d4b9578ad1..f0ea11790d 100644
--- a/shared/nm-utils/nm-test-utils.h
+++ b/shared/nm-utils/nm-test-utils.h
@@ -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)
+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 *
diff --git a/src/nm-checkpoint-manager.c b/src/nm-checkpoint-manager.c
index ded623b3aa..8cc8e609e5 100644
--- a/src/nm-checkpoint-manager.c
+++ b/src/nm-checkpoint-manager.c
@@ -209,7 +209,7 @@ nm_checkpoint_manager_destroy (NMCheckpointManager *self,
g_return_val_if_fail (path && path[0] == '/', 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);
return TRUE;
}
diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c
index a5e94df60b..6ef2931129 100644
--- a/src/supplicant/nm-supplicant-interface.c
+++ b/src/supplicant/nm-supplicant-interface.c
@@ -1543,7 +1543,7 @@ p2p_props_changed_cb (GDBusProxy *proxy,
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) {
/* 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) {
_LOGW ("P2P: Unexpected update of the group object path");
priv->group_proxy_acquired = FALSE;
diff --git a/tools/test-networkmanager-service.py b/tools/test-networkmanager-service.py
index 19d4baef2c..03ed7bde52 100755
--- a/tools/test-networkmanager-service.py
+++ b/tools/test-networkmanager-service.py
@@ -672,6 +672,7 @@ PRP_DEVICE_UDI = "Udi"
PRP_DEVICE_IFACE = "Interface"
PRP_DEVICE_DRIVER = "Driver"
PRP_DEVICE_STATE = "State"
+PRP_DEVICE_STATE_REASON = "StateReason"
PRP_DEVICE_ACTIVE_CONNECTION = "ActiveConnection"
PRP_DEVICE_IP4_CONFIG = "Ip4Config"
PRP_DEVICE_IP6_CONFIG = "Ip6Config"
@@ -700,11 +701,14 @@ class Device(ExportedObj):
self.dhcp4_config = None
self.dhcp6_config = None
+ self.prp_state = NM.DeviceState.UNAVAILABLE
+
props = {
PRP_DEVICE_UDI: "/sys/devices/virtual/%s" % (iface),
PRP_DEVICE_IFACE: iface,
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_IP4_CONFIG: ExportedObj.to_path(self.ip4_config),
PRP_DEVICE_IP6_CONFIG: ExportedObj.to_path(self.ip6_config),
@@ -1302,14 +1306,6 @@ class NetworkManager(ExportedObj):
ac = ActiveConnection(device, con_inst, None)
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)
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}}')
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:
raise BusErr.PermissionDeniedException()
return self.con_hash
@@ -1698,11 +1697,21 @@ class Settings(ExportedObj):
self.NewConnection(con_inst.path)
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:
self.remove_next_connection = False
- self.delete_connection(con_inst)
-
- gl.manager.devices_available_connections_update()
+ def cb():
+ if hasattr(con_inst, '_remove_next_connection_cb'):
+ del con_inst._remove_next_connection_cb
+ self.delete_connection(con_inst)
+ return False
+ # 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