device: renew dhcp leases on awake for software devices
[NetworkManager.git] / shared / nm-test-utils-impl.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16  *
17  * Copyright 2010 - 2015 Red Hat, Inc.
18  *
19  */
20
21 #include "nm-default.h"
22
23 #include <string.h>
24
25 #include "NetworkManager.h"
26 #include "nm-dbus-compat.h"
27
28 #if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
29 #include "nm-dbus-glib-types.h"
30 #endif
31
32 #include "nm-test-libnm-utils.h"
33
34 /*****************************************************************************/
35
36 static gboolean
37 name_exists (GDBusConnection *c, const char *name)
38 {
39         GVariant *reply;
40         gboolean exists = FALSE;
41
42         reply = g_dbus_connection_call_sync (c,
43                                              DBUS_SERVICE_DBUS,
44                                              DBUS_PATH_DBUS,
45                                              DBUS_INTERFACE_DBUS,
46                                              "GetNameOwner",
47                                              g_variant_new ("(s)", name),
48                                              NULL,
49                                              G_DBUS_CALL_FLAGS_NO_AUTO_START,
50                                              -1,
51                                              NULL,
52                                              NULL);
53         if (reply != NULL) {
54                 exists = TRUE;
55                 g_variant_unref (reply);
56         }
57
58         return exists;
59 }
60
61 #if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
62
63 static DBusGProxy *
64 _libdbus_create_proxy_test (DBusGConnection *bus)
65 {
66         DBusGProxy *proxy;
67
68         proxy = dbus_g_proxy_new_for_name (bus,
69                                            NM_DBUS_SERVICE,
70                                            NM_DBUS_PATH,
71                                            "org.freedesktop.NetworkManager.LibnmGlibTest");
72         g_assert (proxy);
73
74         dbus_g_proxy_set_default_timeout (proxy, G_MAXINT);
75
76         return proxy;
77 }
78
79 #endif
80
81 NMTstcServiceInfo *
82 nmtstc_service_init (void)
83 {
84         NMTstcServiceInfo *info;
85         const char *args[2] = { TEST_NM_SERVICE, NULL };
86         GError *error = NULL;
87         int i;
88
89         info = g_malloc0 (sizeof (*info));
90
91         info->bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL,  &error);
92         g_assert_no_error (error);
93
94         /* Spawn the test service. info->keepalive_fd will be a pipe to the service's
95          * stdin; if it closes, the service will exit immediately. We use this to
96          * make sure the service exits if the test program crashes.
97          */
98         g_spawn_async_with_pipes (NULL, (char **) args, NULL, 0, NULL, NULL,
99                                   &info->pid, &info->keepalive_fd, NULL, NULL, &error);
100         g_assert_no_error (error);
101
102         /* Wait until the service is registered on the bus */
103         for (i = 1000; i > 0; i--) {
104                 if (name_exists (info->bus, "org.freedesktop.NetworkManager"))
105                         break;
106                 g_usleep (G_USEC_PER_SEC / 50);
107         }
108         g_assert (i > 0);
109
110         /* Grab a proxy to our fake NM service to trigger tests */
111         info->proxy = g_dbus_proxy_new_sync (info->bus,
112                                              G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
113                                              G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
114                                              G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
115                                              NULL,
116                                              NM_DBUS_SERVICE,
117                                              NM_DBUS_PATH,
118                                              "org.freedesktop.NetworkManager.LibnmGlibTest",
119                                              NULL, &error);
120         g_assert_no_error (error);
121
122 #if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
123         info->libdbus.bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
124         g_assert_no_error (error);
125         g_assert (info->libdbus.bus);
126 #endif
127         return info;
128 }
129
130 void
131 nmtstc_service_cleanup (NMTstcServiceInfo *info)
132 {
133         int i;
134
135         g_object_unref (info->proxy);
136         kill (info->pid, SIGTERM);
137
138         /* Wait until the bus notices the service is gone */
139         for (i = 100; i > 0; i--) {
140                 if (!name_exists (info->bus, "org.freedesktop.NetworkManager"))
141                         break;
142                 g_usleep (G_USEC_PER_SEC / 50);
143         }
144         g_assert (i > 0);
145
146         g_object_unref (info->bus);
147         close (info->keepalive_fd);
148
149 #if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
150         g_clear_pointer (&info->libdbus.bus, dbus_g_connection_unref);
151 #endif
152
153         memset (info, 0, sizeof (*info));
154         g_free (info);
155 }
156
157 #if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB)
158
159 typedef struct {
160         GMainLoop *loop;
161         const char *ifname;
162         char *path;
163         NMDevice *device;
164 } AddDeviceInfo;
165
166 static void
167 device_added_cb (NMClient *client,
168                  NMDevice *device,
169                  gpointer user_data)
170 {
171         AddDeviceInfo *info = user_data;
172
173         g_assert (device);
174         g_assert_cmpstr (nm_object_get_path (NM_OBJECT (device)), ==, info->path);
175         g_assert_cmpstr (nm_device_get_iface (device), ==, info->ifname);
176
177         info->device = device;
178         g_main_loop_quit (info->loop);
179 }
180
181 static gboolean
182 timeout (gpointer user_data)
183 {
184         g_assert_not_reached ();
185         return G_SOURCE_REMOVE;
186 }
187
188 static GVariant *
189 call_add_wired_device (GDBusProxy *proxy, const char *ifname, const char *hwaddr,
190                        const char **subchannels, GError **error)
191 {
192         const char *empty[] = { NULL };
193
194         if (!hwaddr)
195                 hwaddr = "/";
196         if (!subchannels)
197                 subchannels = empty;
198
199         return g_dbus_proxy_call_sync (proxy,
200                                        "AddWiredDevice",
201                                        g_variant_new ("(ss^as)", ifname, hwaddr, subchannels),
202                                        G_DBUS_CALL_FLAGS_NO_AUTO_START,
203                                        3000,
204                                        NULL,
205                                        error);
206 }
207
208 static GVariant *
209 call_add_device (GDBusProxy *proxy, const char *method, const char *ifname, GError **error)
210 {
211         return g_dbus_proxy_call_sync (proxy,
212                                        method,
213                                        g_variant_new ("(s)", ifname),
214                                        G_DBUS_CALL_FLAGS_NO_AUTO_START,
215                                        3000,
216                                        NULL,
217                                        error);
218 }
219
220 static NMDevice *
221 add_device_common (NMTstcServiceInfo *sinfo, NMClient *client,
222                    const char *method, const char *ifname,
223                    const char *hwaddr, const char **subchannels)
224 {
225         AddDeviceInfo info;
226         GError *error = NULL;
227         GVariant *ret;
228         guint timeout_id;
229
230         if (g_strcmp0 (method, "AddWiredDevice") == 0)
231                 ret = call_add_wired_device (sinfo->proxy, ifname, hwaddr, subchannels, &error);
232         else
233                 ret = call_add_device (sinfo->proxy, method, ifname, &error);
234
235         g_assert_no_error (error);
236         g_assert (ret);
237         g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)");
238         g_variant_get (ret, "(o)", &info.path);
239         g_variant_unref (ret);
240
241         /* Wait for libnm to find the device */
242         info.ifname = ifname;
243         info.loop = g_main_loop_new (NULL, FALSE);
244         g_signal_connect (client, "device-added",
245                           G_CALLBACK (device_added_cb), &info);
246         timeout_id = g_timeout_add_seconds (5, timeout, NULL);
247         g_main_loop_run (info.loop);
248
249         g_source_remove (timeout_id);
250         g_signal_handlers_disconnect_by_func (client, device_added_cb, &info);
251         g_free (info.path);
252         g_main_loop_unref (info.loop);
253
254         return info.device;
255 }
256
257 NMDevice *
258 nmtstc_service_add_device (NMTstcServiceInfo *sinfo, NMClient *client,
259                            const char *method, const char *ifname)
260 {
261         return add_device_common (sinfo, client, method, ifname, NULL, NULL);
262 }
263
264 NMDevice *
265 nmtstc_service_add_wired_device (NMTstcServiceInfo *sinfo, NMClient *client,
266                                  const char *ifname, const char *hwaddr,
267                                  const char **subchannels)
268 {
269         return add_device_common (sinfo, client, "AddWiredDevice", ifname, hwaddr, subchannels);
270 }
271
272 #endif /* NM_NETWORKMANAGER_COMPILATION_LIB */
273
274 void
275 nmtstc_service_add_connection (NMTstcServiceInfo *sinfo,
276                                NMConnection *connection,
277                                gboolean verify_connection,
278                                char **out_path)
279 {
280 #if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
281         gs_unref_hashtable GHashTable *new_settings = NULL;
282         gboolean success;
283         gs_free_error GError *error = NULL;
284         gs_free char *path = NULL;
285         gs_unref_object DBusGProxy *proxy = NULL;
286
287         g_assert (sinfo);
288         g_assert (NM_IS_CONNECTION (connection));
289
290         new_settings = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL);
291
292         proxy = _libdbus_create_proxy_test (sinfo->libdbus.bus);
293
294         success = dbus_g_proxy_call (proxy,
295                                      "AddConnection",
296                                      &error,
297                                      DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, new_settings,
298                                      G_TYPE_BOOLEAN, verify_connection,
299                                      G_TYPE_INVALID,
300                                      DBUS_TYPE_G_OBJECT_PATH, &path,
301                                      G_TYPE_INVALID);
302         g_assert_no_error (error);
303         g_assert (success);
304
305         g_assert (path && *path);
306
307         if (out_path)
308                 *out_path = g_strdup (path);
309 #else
310         nmtstc_service_add_connection_variant (sinfo,
311                                                nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL),
312                                                verify_connection,
313                                                out_path);
314 #endif
315 }
316
317 void
318 nmtstc_service_add_connection_variant (NMTstcServiceInfo *sinfo,
319                                        GVariant *connection,
320                                        gboolean verify_connection,
321                                        char **out_path)
322 {
323         GVariant *result;
324         GError *error = NULL;
325
326         g_assert (sinfo);
327         g_assert (G_IS_DBUS_PROXY (sinfo->proxy));
328         g_assert (g_variant_is_of_type (connection, G_VARIANT_TYPE ("a{sa{sv}}")));
329
330         result = g_dbus_proxy_call_sync (sinfo->proxy,
331                                          "AddConnection",
332                                          g_variant_new ("(vb)", connection, verify_connection),
333                                          G_DBUS_CALL_FLAGS_NO_AUTO_START,
334                                          3000,
335                                          NULL,
336                                          &error);
337         g_assert_no_error (error);
338         g_assert (g_variant_is_of_type (result, G_VARIANT_TYPE ("(o)")));
339         if (out_path)
340                 g_variant_get (result, "(o)", out_path);
341         g_variant_unref (result);
342 }
343
344 void
345 nmtstc_service_update_connection (NMTstcServiceInfo *sinfo,
346                                   const char *path,
347                                   NMConnection *connection,
348                                   gboolean verify_connection)
349 {
350         if (!path)
351                 path = nm_connection_get_path (connection);
352         g_assert (path);
353
354 #if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
355         {
356                 gs_unref_hashtable GHashTable *new_settings = NULL;
357                 gboolean success;
358                 gs_free_error GError *error = NULL;
359                 gs_unref_object DBusGProxy *proxy = NULL;
360
361                 g_assert (sinfo);
362                 g_assert (NM_IS_CONNECTION (connection));
363
364                 new_settings = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL);
365
366                 proxy = _libdbus_create_proxy_test (sinfo->libdbus.bus);
367
368                 success = dbus_g_proxy_call (proxy,
369                                              "UpdateConnection",
370                                              &error,
371                                              DBUS_TYPE_G_OBJECT_PATH, path,
372                                              DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, new_settings,
373                                              G_TYPE_BOOLEAN, verify_connection,
374                                              G_TYPE_INVALID,
375                                              G_TYPE_INVALID);
376                 g_assert_no_error (error);
377                 g_assert (success);
378         }
379 #else
380         nmtstc_service_update_connection_variant (sinfo,
381                                                   path,
382                                                   nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL),
383                                                   verify_connection);
384 #endif
385 }
386
387 void
388 nmtstc_service_update_connection_variant (NMTstcServiceInfo *sinfo,
389                                           const char *path,
390                                           GVariant *connection,
391                                           gboolean verify_connection)
392 {
393         GVariant *result;
394         GError *error = NULL;
395
396         g_assert (sinfo);
397         g_assert (G_IS_DBUS_PROXY (sinfo->proxy));
398         g_assert (g_variant_is_of_type (connection, G_VARIANT_TYPE ("a{sa{sv}}")));
399         g_assert (path && path[0] == '/');
400
401         result = g_dbus_proxy_call_sync (sinfo->proxy,
402                                          "UpdateConnection",
403                                          g_variant_new ("(ovb)", path, connection, verify_connection),
404                                          G_DBUS_CALL_FLAGS_NO_AUTO_START,
405                                          3000,
406                                          NULL,
407                                          &error);
408         g_assert_no_error (error);
409         g_assert (g_variant_is_of_type (result, G_VARIANT_TYPE ("()")));
410         g_variant_unref (result);
411 }
412
413 /*****************************************************************************/
414
415 #if ((NETWORKMANAGER_COMPILATION) == NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY)
416
417 NMClient *
418 nmtstc_nm_client_new (void)
419 {
420         NMClient *client;
421         DBusGConnection *bus;
422         GError *error = NULL;
423         gboolean success;
424
425         bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
426         g_assert_no_error (error);
427         g_assert (bus);
428
429         client = g_object_new (NM_TYPE_CLIENT,
430                                NM_OBJECT_DBUS_CONNECTION, bus,
431                                NM_OBJECT_DBUS_PATH, NM_DBUS_PATH,
432                                NULL);
433         g_assert (client != NULL);
434
435         dbus_g_connection_unref (bus);
436
437         success = g_initable_init (G_INITABLE (client), NULL, &error);
438         g_assert_no_error (error);
439         g_assert (success == TRUE);
440
441         return client;
442 }
443
444 NMRemoteSettings *
445 nmtstc_nm_remote_settings_new (void)
446 {
447         NMRemoteSettings *settings;
448         DBusGConnection *bus;
449         GError *error = NULL;
450
451         bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
452         g_assert_no_error (error);
453         g_assert (bus);
454
455         settings = nm_remote_settings_new (bus);
456         g_assert (settings);
457
458         dbus_g_connection_unref (bus);
459
460         return settings;
461 }
462
463 #endif /* NM_NETWORKMANAGER_COMPILATION_LIB_LEGACY */
464
465 /*****************************************************************************/