libnm-glib: allow non-verifiable NMRemoteConnection in libnm-glib
[NetworkManager.git] / libnm-glib / tests / test-nm-client.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 - 2014 Red Hat, Inc.
18  *
19  */
20
21 #include "nm-default.h"
22
23 #include <dbus/dbus.h>
24 #include <dbus/dbus-glib.h>
25 #include <dbus/dbus-glib-lowlevel.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <signal.h>
29
30 #include "nm-client.h"
31 #include "nm-device-wifi.h"
32 #include "nm-device-ethernet.h"
33 #include "nm-device-wimax.h"
34 #include "nm-connection.h"
35 #include "nm-setting.h"
36
37 #include "nm-test-libnm-utils.h"
38
39 static GMainLoop *loop = NULL;
40 static NMTstcServiceInfo *sinfo;
41
42 /*******************************************************************/
43
44 static gboolean
45 loop_quit (gpointer user_data)
46 {
47         g_main_loop_quit ((GMainLoop *) user_data);
48         return G_SOURCE_REMOVE;
49 }
50
51 static gboolean
52 add_device (const char *method, const char *ifname, char **out_path)
53 {
54         GError *error = NULL;
55         GVariant *ret;
56
57         ret = g_dbus_proxy_call_sync (sinfo->proxy,
58                                       method,
59                                       g_variant_new ("(s)", ifname),
60                                       G_DBUS_CALL_FLAGS_NO_AUTO_START,
61                                       3000,
62                                       NULL,
63                                       &error);
64         g_assert_no_error (error);
65         g_assert (ret);
66         g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)");
67         if (out_path)
68                 g_variant_get (ret, "(o)", out_path);
69         g_variant_unref (ret);
70         return TRUE;
71 }
72
73 static gboolean
74 add_wired_device (const char *method, const char *ifname, char **out_path)
75 {
76         const char *empty[] = { NULL };
77         GError *error = NULL;
78         GVariant *ret;
79
80         ret = g_dbus_proxy_call_sync (sinfo->proxy,
81                                       method,
82                                       g_variant_new ("(ss^as)", ifname, "/", empty),
83                                       G_DBUS_CALL_FLAGS_NO_AUTO_START,
84                                       3000,
85                                       NULL,
86                                       &error);
87         g_assert_no_error (error);
88         g_assert (ret);
89         g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)");
90         if (out_path)
91                 g_variant_get (ret, "(o)", out_path);
92         g_variant_unref (ret);
93         return TRUE;
94 }
95
96 /*******************************************************************/
97
98 typedef struct {
99         GMainLoop *loop;
100         gboolean signaled;
101         gboolean notified;
102         guint quit_count;
103         guint quit_id;
104 } DeviceAddedInfo;
105
106 static void
107 device_add_check_quit (DeviceAddedInfo *info)
108 {
109         info->quit_count--;
110         if (info->quit_count == 0) {
111                 g_source_remove (info->quit_id);
112                 info->quit_id = 0;
113                 g_main_loop_quit (info->loop);
114         }
115 }
116
117 static void
118 device_added_cb (NMClient *c,
119                  NMDevice *device,
120                  DeviceAddedInfo *info)
121 {
122         g_assert (device);
123         g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
124         info->signaled = TRUE;
125         device_add_check_quit (info);
126 }
127
128 static void
129 devices_notify_cb (NMClient *c,
130                    GParamSpec *pspec,
131                    DeviceAddedInfo *info)
132 {
133         const GPtrArray *devices;
134         NMDevice *device;
135
136         devices = nm_client_get_devices (c);
137         g_assert (devices);
138         g_assert_cmpint (devices->len, ==, 1);
139
140         device = g_ptr_array_index (devices, 0);
141         g_assert (device);
142         g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
143
144         info->notified = TRUE;
145
146         device_add_check_quit (info);
147 }
148
149 static void
150 test_device_added (void)
151 {
152         NMClient *client;
153         const GPtrArray *devices;
154         NMDevice *device;
155         DeviceAddedInfo info = { loop, FALSE, FALSE, 0, 0 };
156
157         sinfo = nmtstc_service_init ();
158         client = nmtstc_nm_client_new ();
159
160         devices = nm_client_get_devices (client);
161         g_assert (devices == NULL);
162
163         /* Tell the test service to add a new device */
164         add_wired_device ("AddWiredDevice", "eth0", NULL);
165
166         g_signal_connect (client,
167                           "device-added",
168                           (GCallback) device_added_cb,
169                           &info);
170         info.quit_count++;
171
172         g_signal_connect (client,
173                           "notify::devices",
174                           (GCallback) devices_notify_cb,
175                           &info);
176         info.quit_count++;
177
178         /* Wait for libnm-glib to find the device */
179         info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
180         g_main_loop_run (loop);
181
182         g_assert (info.signaled);
183         g_assert (info.notified);
184
185         g_signal_handlers_disconnect_by_func (client, device_added_cb, &info);
186         g_signal_handlers_disconnect_by_func (client, devices_notify_cb, &info);
187
188         devices = nm_client_get_devices (client);
189         g_assert (devices);
190         g_assert_cmpint (devices->len, ==, 1);
191
192         device = g_ptr_array_index (devices, 0);
193         g_assert (device);
194         g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
195
196         g_object_unref (client);
197         g_clear_pointer (&sinfo, nmtstc_service_cleanup);
198 }
199
200 /*******************************************************************/
201
202 static const char *expected_bssid = "66:55:44:33:22:11";
203
204 typedef struct {
205         GMainLoop *loop;
206         gboolean found;
207         char *ap_path;
208         gboolean signaled;
209         gboolean notified;
210         guint quit_id;
211         guint quit_count;
212 } WifiApInfo;
213
214 static void
215 wifi_check_quit (WifiApInfo *info)
216 {
217         info->quit_count--;
218         if (info->quit_count == 0) {
219                 g_source_remove (info->quit_id);
220                 info->quit_id = 0;
221                 g_main_loop_quit (info->loop);
222         }
223 }
224
225 static void
226 wifi_device_added_cb (NMClient *c,
227                       NMDevice *device,
228                       WifiApInfo *info)
229 {
230         g_assert_cmpstr (nm_device_get_iface (device), ==, "wlan0");
231         info->found = TRUE;
232         wifi_check_quit (info);
233 }
234
235 static void
236 got_ap_path (WifiApInfo *info, const char *path)
237 {
238         if (info->ap_path)
239                 g_assert_cmpstr (info->ap_path, ==, path);
240         else
241                 info->ap_path = g_strdup (path);
242 }
243
244 static void
245 wifi_ap_added_cb (NMDeviceWifi *w,
246                   NMAccessPoint *ap,
247                   WifiApInfo *info)
248 {
249         g_assert (ap);
250         g_assert_cmpstr (nm_access_point_get_bssid (ap), ==, expected_bssid);
251         got_ap_path (info, nm_object_get_path (NM_OBJECT (ap)));
252
253         info->signaled = TRUE;
254         wifi_check_quit (info);
255 }
256
257 static void
258 wifi_ap_add_notify_cb (NMDeviceWifi *w,
259                        GParamSpec *pspec,
260                        WifiApInfo *info)
261 {
262         const GPtrArray *aps;
263         NMAccessPoint *ap;
264
265         aps = nm_device_wifi_get_access_points (w);
266         g_assert (aps);
267         g_assert_cmpint (aps->len, ==, 1);
268
269         ap = g_ptr_array_index (aps, 0);
270         g_assert (ap);
271         g_assert_cmpstr (nm_access_point_get_bssid (ap), ==, "66:55:44:33:22:11");
272         got_ap_path (info, nm_object_get_path (NM_OBJECT (ap)));
273
274         info->notified = TRUE;
275         wifi_check_quit (info);
276 }
277
278 static void
279 wifi_ap_removed_cb (NMDeviceWifi *w,
280                     NMAccessPoint *ap,
281                     WifiApInfo *info)
282 {
283         g_assert (ap);
284         g_assert_cmpstr (info->ap_path, ==, nm_object_get_path (NM_OBJECT (ap)));
285
286         info->signaled = TRUE;
287         wifi_check_quit (info);
288 }
289
290 static void
291 wifi_ap_remove_notify_cb (NMDeviceWifi *w,
292                           GParamSpec *pspec,
293                           WifiApInfo *info)
294 {
295         const GPtrArray *aps;
296
297         aps = nm_device_wifi_get_access_points (w);
298         g_assert (aps == NULL);
299
300         info->notified = TRUE;
301         wifi_check_quit (info);
302 }
303
304 static void
305 test_wifi_ap_added_removed (void)
306 {
307         NMClient *client;
308         NMDeviceWifi *wifi;
309         WifiApInfo info = { loop, FALSE, FALSE, 0, 0 };
310         GVariant *ret;
311         GError *error = NULL;
312         char *expected_path = NULL;
313
314         sinfo = nmtstc_service_init ();
315         client = nmtstc_nm_client_new ();
316
317         /*************************************/
318         /* Add the wifi device */
319         add_device ("AddWifiDevice", "wlan0", NULL);
320
321         g_signal_connect (client,
322                           "device-added",
323                           (GCallback) wifi_device_added_cb,
324                           &info);
325         info.quit_count = 1;
326
327         /* Wait for libnm-glib to find the device */
328         info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
329         g_main_loop_run (loop);
330
331         g_assert (info.found);
332         g_signal_handlers_disconnect_by_func (client, wifi_device_added_cb, &info);
333
334         wifi = (NMDeviceWifi *) nm_client_get_device_by_iface (client, "wlan0");
335         g_assert (NM_IS_DEVICE_WIFI (wifi));
336
337         /*************************************/
338         /* Add the wifi device */
339         info.signaled =  FALSE;
340         info.notified = FALSE;
341         info.quit_id = 0;
342
343         ret = g_dbus_proxy_call_sync (sinfo->proxy,
344                                       "AddWifiAp",
345                                       g_variant_new ("(sss)", "wlan0", "test-ap", expected_bssid),
346                                       G_DBUS_CALL_FLAGS_NO_AUTO_START,
347                                       3000,
348                                       NULL,
349                                       &error);
350         g_assert_no_error (error);
351         g_assert (ret);
352         g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)");
353         g_variant_get (ret, "(o)", &expected_path);
354         g_variant_unref (ret);
355
356         g_signal_connect (wifi,
357                           "access-point-added",
358                           (GCallback) wifi_ap_added_cb,
359                           &info);
360         info.quit_count = 1;
361
362         g_signal_connect (wifi,
363                           "notify::access-points",
364                           (GCallback) wifi_ap_add_notify_cb,
365                           &info);
366         info.quit_count++;
367
368         /* Wait for libnm-glib to find the AP */
369         info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
370         g_main_loop_run (loop);
371
372         g_assert (info.signaled);
373         g_assert (info.notified);
374         g_assert (info.ap_path);
375         g_assert_cmpstr (info.ap_path, ==, expected_path);
376         g_signal_handlers_disconnect_by_func (wifi, wifi_ap_added_cb, &info);
377         g_signal_handlers_disconnect_by_func (wifi, wifi_ap_add_notify_cb, &info);
378
379         /*************************************/
380         /* Remove the wifi device */
381         info.signaled =  FALSE;
382         info.notified = FALSE;
383         info.quit_id = 0;
384
385         ret = g_dbus_proxy_call_sync (sinfo->proxy,
386                                       "RemoveWifiAp",
387                                       g_variant_new ("(so)", "wlan0", expected_path),
388                                       G_DBUS_CALL_FLAGS_NO_AUTO_START,
389                                       3000,
390                                       NULL,
391                                       &error);
392         g_assert_no_error (error);
393         g_clear_pointer (&ret, g_variant_unref);
394
395         g_signal_connect (wifi,
396                           "access-point-removed",
397                           (GCallback) wifi_ap_removed_cb,
398                           &info);
399         info.quit_count = 1;
400
401         g_signal_connect (wifi,
402                           "notify::access-points",
403                           (GCallback) wifi_ap_remove_notify_cb,
404                           &info);
405         info.quit_count++;
406
407         /* Wait for libnm-glib to find the AP */
408         info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
409         g_main_loop_run (loop);
410
411         g_assert (info.signaled);
412         g_assert (info.notified);
413         g_signal_handlers_disconnect_by_func (wifi, wifi_ap_removed_cb, &info);
414         g_signal_handlers_disconnect_by_func (wifi, wifi_ap_remove_notify_cb, &info);
415
416         g_free (info.ap_path);
417         g_free (expected_path);
418
419         g_object_unref (client);
420         g_clear_pointer (&sinfo, nmtstc_service_cleanup);
421 }
422
423 /*******************************************************************/
424
425 static const char *expected_nsp_name = "Clear";
426
427 typedef struct {
428         GMainLoop *loop;
429         gboolean found;
430         char *nsp_path;
431         gboolean signaled;
432         gboolean notified;
433         guint quit_id;
434         guint quit_count;
435 } WimaxNspInfo;
436
437 static void
438 wimax_check_quit (WimaxNspInfo *info)
439 {
440         info->quit_count--;
441         if (info->quit_count == 0) {
442                 g_source_remove (info->quit_id);
443                 info->quit_id = 0;
444                 g_main_loop_quit (info->loop);
445         }
446 }
447
448 static void
449 wimax_device_added_cb (NMClient *c,
450                        NMDevice *device,
451                        WimaxNspInfo *info)
452 {
453         g_assert_cmpstr (nm_device_get_iface (device), ==, "wmx0");
454         info->found = TRUE;
455         wimax_check_quit (info);
456 }
457
458 static void
459 got_nsp_path (WimaxNspInfo *info, const char *path)
460 {
461         if (info->nsp_path)
462                 g_assert_cmpstr (info->nsp_path, ==, path);
463         else
464                 info->nsp_path = g_strdup (path);
465 }
466
467 static void
468 wimax_nsp_added_cb (NMDeviceWimax *w,
469                     NMWimaxNsp *nsp,
470                     WimaxNspInfo *info)
471 {
472         g_assert (nsp);
473         g_assert_cmpstr (nm_wimax_nsp_get_name (nsp), ==, expected_nsp_name);
474         got_nsp_path (info, nm_object_get_path (NM_OBJECT (nsp)));
475
476         info->signaled = TRUE;
477         wimax_check_quit (info);
478 }
479
480 static void
481 wimax_nsp_add_notify_cb (NMDeviceWimax *w,
482                          GParamSpec *pspec,
483                          WimaxNspInfo *info)
484 {
485         const GPtrArray *nsps;
486         NMWimaxNsp *nsp;
487
488         nsps = nm_device_wimax_get_nsps (w);
489         g_assert (nsps);
490         g_assert_cmpint (nsps->len, ==, 1);
491
492         nsp = g_ptr_array_index (nsps, 0);
493         g_assert (nsp);
494         g_assert_cmpstr (nm_wimax_nsp_get_name (nsp), ==, expected_nsp_name);
495         got_nsp_path (info, nm_object_get_path (NM_OBJECT (nsp)));
496
497         info->notified = TRUE;
498         wimax_check_quit (info);
499 }
500
501 static void
502 wimax_nsp_removed_cb (NMDeviceWimax *w,
503                       NMWimaxNsp *nsp,
504                       WimaxNspInfo *info)
505 {
506         g_assert (nsp);
507         g_assert_cmpstr (info->nsp_path, ==, nm_object_get_path (NM_OBJECT (nsp)));
508
509         info->signaled = TRUE;
510         wimax_check_quit (info);
511 }
512
513 static void
514 wimax_nsp_remove_notify_cb (NMDeviceWimax *w,
515                             GParamSpec *pspec,
516                             WimaxNspInfo *info)
517 {
518         const GPtrArray *nsps;
519
520         nsps = nm_device_wimax_get_nsps (w);
521         g_assert (nsps == NULL);
522
523         info->notified = TRUE;
524         wimax_check_quit (info);
525 }
526
527 static void
528 test_wimax_nsp_added_removed (void)
529 {
530         NMClient *client;
531         NMDeviceWimax *wimax;
532         WimaxNspInfo info = { loop, FALSE, FALSE, 0, 0 };
533         GVariant *ret;
534         GError *error = NULL;
535         char *expected_path = NULL;
536
537         sinfo = nmtstc_service_init ();
538         client = nmtstc_nm_client_new ();
539
540         /*************************************/
541         /* Add the wimax device */
542         add_device ("AddWimaxDevice", "wmx0", NULL);
543
544         g_signal_connect (client,
545                           "device-added",
546                           (GCallback) wimax_device_added_cb,
547                           &info);
548         info.quit_count = 1;
549
550         /* Wait for libnm-glib to find the device */
551         info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
552         g_main_loop_run (loop);
553
554         g_assert (info.found);
555         g_signal_handlers_disconnect_by_func (client, wimax_device_added_cb, &info);
556
557         wimax = (NMDeviceWimax *) nm_client_get_device_by_iface (client, "wmx0");
558         g_assert (NM_IS_DEVICE_WIMAX (wimax));
559
560         /*************************************/
561         /* Add the wimax NSP */
562         info.signaled =  FALSE;
563         info.notified = FALSE;
564         info.quit_id = 0;
565
566         ret = g_dbus_proxy_call_sync (sinfo->proxy,
567                                       "AddWimaxNsp",
568                                       g_variant_new ("(ss)", "wmx0", expected_nsp_name),
569                                       G_DBUS_CALL_FLAGS_NO_AUTO_START,
570                                       3000,
571                                       NULL,
572                                       &error);
573         g_assert_no_error (error);
574         g_assert (ret);
575         g_assert_cmpstr (g_variant_get_type_string (ret), ==, "(o)");
576         g_variant_get (ret, "(o)", &expected_path);
577         g_variant_unref (ret);
578
579         g_signal_connect (wimax,
580                           "nsp-added",
581                           (GCallback) wimax_nsp_added_cb,
582                           &info);
583         info.quit_count = 1;
584
585         g_signal_connect (wimax,
586                           "notify::nsps",
587                           (GCallback) wimax_nsp_add_notify_cb,
588                           &info);
589         info.quit_count++;
590
591         /* Wait for libnm-glib to find the AP */
592         info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
593         g_main_loop_run (loop);
594
595         g_assert (info.signaled);
596         g_assert (info.notified);
597         g_assert (info.nsp_path);
598         g_assert_cmpstr (info.nsp_path, ==, expected_path);
599         g_signal_handlers_disconnect_by_func (wimax, wimax_nsp_added_cb, &info);
600         g_signal_handlers_disconnect_by_func (wimax, wimax_nsp_add_notify_cb, &info);
601
602         /*************************************/
603         /* Remove the wimax NSP */
604         info.signaled =  FALSE;
605         info.notified = FALSE;
606         info.quit_id = 0;
607
608         ret = g_dbus_proxy_call_sync (sinfo->proxy,
609                                       "RemoveWimaxNsp",
610                                       g_variant_new ("(so)", "wmx0", expected_path),
611                                       G_DBUS_CALL_FLAGS_NO_AUTO_START,
612                                       3000,
613                                       NULL,
614                                       &error);
615         g_assert_no_error (error);
616         g_clear_pointer (&ret, g_variant_unref);
617
618         g_signal_connect (wimax,
619                           "nsp-removed",
620                           (GCallback) wimax_nsp_removed_cb,
621                           &info);
622         info.quit_count = 1;
623
624         g_signal_connect (wimax,
625                           "notify::nsps",
626                           (GCallback) wimax_nsp_remove_notify_cb,
627                           &info);
628         info.quit_count++;
629
630         /* Wait for libnm-glib to find the AP */
631         info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
632         g_main_loop_run (loop);
633
634         g_assert (info.signaled);
635         g_assert (info.notified);
636         g_signal_handlers_disconnect_by_func (wimax, wimax_nsp_removed_cb, &info);
637         g_signal_handlers_disconnect_by_func (wimax, wimax_nsp_remove_notify_cb, &info);
638
639         g_free (info.nsp_path);
640         g_free (expected_path);
641
642         g_object_unref (client);
643         g_clear_pointer (&sinfo, nmtstc_service_cleanup);
644 }
645
646 /*******************************************************************/
647
648 typedef struct {
649         GMainLoop *loop;
650         gboolean signaled;
651         gboolean notified;
652         guint quit_count;
653         guint quit_id;
654 } DaInfo;
655
656 static void
657 da_check_quit (DaInfo *info)
658 {
659         g_assert (info->quit_count > 0);
660         info->quit_count--;
661         if (info->quit_count == 0) {
662                 g_source_remove (info->quit_id);
663                 info->quit_id = 0;
664                 g_main_loop_quit (info->loop);
665         }
666 }
667
668 static void
669 da_device_added_cb (NMClient *c,
670                     NMDevice *device,
671                     DaInfo *info)
672 {
673         da_check_quit (info);
674 }
675
676 static void
677 da_device_removed_cb (NMClient *c,
678                       NMDevice *device,
679                       DaInfo *info)
680 {
681         g_assert_cmpstr (nm_device_get_iface (device), ==, "eth0");
682         info->signaled = TRUE;
683         da_check_quit (info);
684 }
685
686 static void
687 da_devices_notify_cb (NMClient *c,
688                       GParamSpec *pspec,
689                       DaInfo *info)
690 {
691         const GPtrArray *devices;
692         NMDevice *device;
693         guint i;
694         const char *iface;
695
696         devices = nm_client_get_devices (c);
697         g_assert (devices);
698         g_assert_cmpint (devices->len, ==, 2);
699
700         for (i = 0; i < devices->len; i++) {
701                 device = g_ptr_array_index (devices, i);
702                 iface = nm_device_get_iface (device);
703
704                 g_assert (!strcmp (iface, "wlan0") || !strcmp (iface, "eth1"));
705         }
706
707         info->notified = TRUE;
708         da_check_quit (info);
709 }
710
711 static void
712 test_devices_array (void)
713 {
714         NMClient *client;
715         DaInfo info = { loop };
716         char *paths[3] = { NULL, NULL, NULL };
717         NMDevice *device;
718         const GPtrArray *devices;
719         GError *error = NULL;
720         GVariant *ret;
721
722         sinfo = nmtstc_service_init ();
723         client = nmtstc_nm_client_new ();
724
725         /*************************************/
726         /* Add some devices */
727         add_device ("AddWifiDevice", "wlan0", &paths[0]);
728         add_wired_device ("AddWiredDevice", "eth0", &paths[1]);
729         add_wired_device ("AddWiredDevice", "eth1", &paths[2]);
730         info.quit_count = 3;
731
732         g_signal_connect (client,
733                           "device-added",
734                           (GCallback) da_device_added_cb,
735                           &info);
736
737         /* Wait for libnm-glib to find the device */
738         info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
739         g_main_loop_run (loop);
740
741         g_assert_cmpint (info.quit_count, ==, 0);
742         g_signal_handlers_disconnect_by_func (client, da_device_added_cb, &info);
743
744         /* Ensure the devices now exist */
745         devices = nm_client_get_devices (client);
746         g_assert (devices);
747         g_assert_cmpint (devices->len, ==, 3);
748
749         device = nm_client_get_device_by_iface (client, "wlan0");
750         g_assert (NM_IS_DEVICE_WIFI (device));
751
752         device = nm_client_get_device_by_iface (client, "eth0");
753         g_assert (NM_IS_DEVICE_ETHERNET (device));
754
755         device = nm_client_get_device_by_iface (client, "eth1");
756         g_assert (NM_IS_DEVICE_ETHERNET (device));
757
758         /********************************/
759         /* Now remove the device in the middle */
760         ret = g_dbus_proxy_call_sync (sinfo->proxy,
761                                       "RemoveDevice",
762                                       g_variant_new ("(o)", paths[1]),
763                                       G_DBUS_CALL_FLAGS_NO_AUTO_START,
764                                       3000,
765                                       NULL,
766                                       &error);
767         g_assert_no_error (error);
768         g_assert (ret);
769         g_variant_unref (ret);
770
771         g_signal_connect (client,
772                           "device-removed",
773                           (GCallback) da_device_removed_cb,
774                           &info);
775
776         g_signal_connect (client,
777                           "notify::devices",
778                           (GCallback) da_devices_notify_cb,
779                           &info);
780         info.quit_count = 2;
781
782         /* Wait for libnm-glib to find the device */
783         info.quit_id = g_timeout_add_seconds (5, loop_quit, loop);
784         g_main_loop_run (loop);
785
786         g_assert_cmpint (info.quit_count, ==, 0);
787         g_signal_handlers_disconnect_by_func (client, da_device_removed_cb, &info);
788         g_signal_handlers_disconnect_by_func (client, da_devices_notify_cb, &info);
789
790         /* Ensure only two are left */
791         devices = nm_client_get_devices (client);
792         g_assert (devices);
793         g_assert_cmpint (devices->len, ==, 2);
794
795         device = nm_client_get_device_by_iface (client, "wlan0");
796         g_assert (NM_IS_DEVICE_WIFI (device));
797
798         device = nm_client_get_device_by_iface (client, "eth1");
799         g_assert (NM_IS_DEVICE_ETHERNET (device));
800
801         g_free (paths[0]);
802         g_free (paths[1]);
803         g_free (paths[2]);
804
805         g_object_unref (client);
806         g_clear_pointer (&sinfo, nmtstc_service_cleanup);
807 }
808
809 static void
810 manager_running_changed (GObject *client,
811                          GParamSpec *pspec,
812                          gpointer user_data)
813 {
814         int *running_changed = user_data;
815
816         (*running_changed)++;
817         g_main_loop_quit (loop);
818 }
819
820 static void
821 test_client_manager_running (void)
822 {
823         NMClient *client1, *client2;
824         guint quit_id;
825         int running_changed = 0;
826         GError *error = NULL;
827
828         client1 = nmtstc_nm_client_new ();
829
830         g_assert (!nm_client_get_manager_running (client1));
831         g_assert_cmpstr (nm_client_get_version (client1), ==, NULL);
832
833         g_assert (!nm_client_networking_get_enabled (client1));
834         /* This will have no effect, but it shouldn't cause any warnings either. */
835         nm_client_networking_set_enabled (client1, TRUE);
836         g_assert (!nm_client_networking_get_enabled (client1));
837
838         /* OTOH, this should result in an error */
839         nm_client_set_logging (client1, "DEFAULT", "INFO", &error);
840         g_assert_error (error, NM_CLIENT_ERROR, NM_CLIENT_ERROR_MANAGER_NOT_RUNNING);
841         g_clear_error (&error);
842
843         /* Now start the test service. */
844         sinfo = nmtstc_service_init ();
845         client2 = nmtstc_nm_client_new ();
846
847         /* client2 should know that NM is running, but the previously-created
848          * client1 hasn't gotten the news yet.
849          */
850         g_assert (!nm_client_get_manager_running (client1));
851         g_assert (nm_client_get_manager_running (client2));
852
853         g_signal_connect (client1, "notify::" NM_CLIENT_MANAGER_RUNNING,
854                           G_CALLBACK (manager_running_changed), &running_changed);
855         quit_id = g_timeout_add_seconds (5, loop_quit, loop);
856         g_main_loop_run (loop);
857         g_assert_cmpint (running_changed, ==, 1);
858         g_assert (nm_client_get_manager_running (client1));
859         g_source_remove (quit_id);
860
861         /* And kill it */
862         g_clear_pointer (&sinfo, nmtstc_service_cleanup);
863
864         g_assert (nm_client_get_manager_running (client1));
865
866         quit_id = g_timeout_add_seconds (5, loop_quit, loop);
867         g_main_loop_run (loop);
868         g_assert_cmpint (running_changed, ==, 2);
869         g_assert (!nm_client_get_manager_running (client1));
870         g_source_remove (quit_id);
871
872         g_object_unref (client1);
873         g_object_unref (client2);
874 }
875
876 /*******************************************************************/
877
878 static GPtrArray *
879 _slist_to_array (GPtrArray **connections, GSList *list)
880 {
881         GPtrArray *array;
882         const GSList *iter;
883
884         if (!*connections)
885                 *connections = array = g_ptr_array_new ();
886         else {
887                 array = *connections;
888                 g_ptr_array_set_size (array, 0);
889         }
890         for (iter = list; iter; iter = iter->next)
891                 g_ptr_array_add (array, iter->data);
892         g_slist_free (list);
893         return array;
894 }
895
896 static gboolean
897 _test_connection_invalid_find_connections (gpointer element, gpointer needle, gpointer user_data)
898 {
899         NMRemoteConnection *con = NM_REMOTE_CONNECTION (element);
900         const char *path = needle;
901
902         g_assert (NM_IS_REMOTE_CONNECTION (con));
903         g_assert (path && *path);
904
905         return strcmp (path, nm_connection_get_path ((NMConnection *) con)) == 0;
906 }
907
908 #define ASSERT_IDX(i) \
909         g_assert_cmpint (idx[i], >=, 0); \
910         g_assert (path##i && *path##i); \
911         g_assert (NM_IS_REMOTE_CONNECTION (connections->pdata[idx[i]])); \
912         g_assert_cmpstr (nm_connection_get_path (connections->pdata[idx[i]]), ==, path##i);
913
914 static void
915 test_connection_invalid (void)
916 {
917         NMTSTC_SERVICE_INFO_SETUP (my_sinfo)
918         gs_unref_object NMConnection *connection = NULL;
919         NMSettingConnection *s_con;
920         gs_unref_object NMRemoteSettings *settings = NULL;
921         gs_unref_ptrarray GPtrArray *connections = NULL;
922         gs_free char *path0 = NULL;
923         gs_free char *path1 = NULL;
924         gs_free char *path2 = NULL;
925         gs_free char *uuid2 = NULL;
926         gsize n_found;
927         gssize idx[3];
928
929         /**************************************************************************
930          * Add two connection before starting libnm. One valid, one invalid.
931          *************************************************************************/
932
933         connection = nmtst_create_minimal_connection ("test-connection-invalid-0", NULL, NM_SETTING_WIRED_SETTING_NAME, &s_con);
934         nmtst_connection_normalize (connection);
935         g_object_set (s_con,
936                       NM_SETTING_CONNECTION_UUID, nmtst_uuid_generate (),
937                       NULL);
938         nmtstc_service_add_connection (my_sinfo,
939                                        connection,
940                                        TRUE,
941                                        &path0);
942
943         nm_connection_remove_setting (connection, NM_TYPE_SETTING_WIRED);
944         g_object_set (s_con,
945                       NM_SETTING_CONNECTION_ID, "test-connection-invalid-1",
946                       NM_SETTING_CONNECTION_TYPE, "invalid-type-1",
947                       NM_SETTING_CONNECTION_UUID, nmtst_uuid_generate (),
948                       NULL);
949         nmtstc_service_add_connection (my_sinfo,
950                                        connection,
951                                        FALSE,
952                                        &path1);
953
954         nmtst_main_loop_run (loop, 100);
955
956         settings = nmtstc_nm_remote_settings_new ();
957
958         nmtst_main_loop_run (loop, 100);
959
960         _slist_to_array (&connections, nm_remote_settings_list_connections (settings));
961
962         g_assert_cmpint (connections->len, ==, 2);
963         n_found = nmtst_find_all_indexes (connections->pdata,
964                                           connections->len,
965                                           (gpointer *) ((const char *[]) { path0, path1 }),
966                                           2,
967                                           _test_connection_invalid_find_connections,
968                                           NULL,
969                                           idx);
970         g_assert_cmpint (n_found, ==, 2);
971         ASSERT_IDX (0);
972         ASSERT_IDX (1);
973         nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]);
974         nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0);
975
976         /**************************************************************************
977          * After having the client up and running, add another invalid connection
978          *************************************************************************/
979
980         g_object_set (s_con,
981                       NM_SETTING_CONNECTION_ID, "test-connection-invalid-2",
982                       NM_SETTING_CONNECTION_TYPE, "invalid-type-2",
983                       NM_SETTING_CONNECTION_UUID, (uuid2 = g_strdup (nmtst_uuid_generate ())),
984                       NULL);
985         nmtstc_service_add_connection (my_sinfo,
986                                        connection,
987                                        FALSE,
988                                        &path2);
989
990         nmtst_main_loop_run (loop, 100);
991
992         _slist_to_array (&connections, nm_remote_settings_list_connections (settings));
993
994         g_assert_cmpint (connections->len, ==, 3);
995         n_found = nmtst_find_all_indexes (connections->pdata,
996                                           connections->len,
997                                           (gpointer *) ((const char *[]) { path0, path1, path2 }),
998                                           3,
999                                           _test_connection_invalid_find_connections,
1000                                           NULL,
1001                                           idx);
1002         g_assert_cmpint (n_found, ==, 3);
1003         ASSERT_IDX (0);
1004         ASSERT_IDX (1);
1005         ASSERT_IDX (2);
1006         nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]);
1007         nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0);
1008         nmtst_assert_connection_unnormalizable (connections->pdata[idx[2]], 0, 0);
1009
1010         /**************************************************************************
1011          * Modify the invalid connection. Connection disappears
1012          *************************************************************************/
1013
1014         g_object_set (s_con,
1015                       NM_SETTING_CONNECTION_ID, "test-connection-invalid-2x",
1016                       NULL);
1017         nmtstc_service_update_connection (my_sinfo,
1018                                           path2,
1019                                           connection,
1020                                           FALSE);
1021
1022         nmtst_main_loop_run (loop, 100);
1023
1024         _slist_to_array (&connections, nm_remote_settings_list_connections (settings));
1025
1026         g_assert_cmpint (connections->len, ==, 3);
1027         n_found = nmtst_find_all_indexes (connections->pdata,
1028                                           connections->len,
1029                                           (gpointer *) ((const char *[]) { path0, path1, path2 }),
1030                                           3,
1031                                           _test_connection_invalid_find_connections,
1032                                           NULL,
1033                                           idx);
1034         g_assert_cmpint (n_found, ==, 3);
1035         ASSERT_IDX (0);
1036         ASSERT_IDX (1);
1037         ASSERT_IDX (2);
1038         nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]);
1039         nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0);
1040         nmtst_assert_connection_unnormalizable (connections->pdata[idx[2]], 0, 0);
1041
1042         /**************************************************************************
1043          * Modify the invalid connection again. Note that the connection stays
1044          * invisible (although it exists, and is valid).
1045          *************************************************************************/
1046
1047         g_clear_object (&connection);
1048         connection = nmtst_create_minimal_connection ("test-connection-invalid-2", NULL, NM_SETTING_WIRED_SETTING_NAME, &s_con);
1049         nmtst_connection_normalize (connection);
1050         g_object_set (s_con,
1051                       NM_SETTING_CONNECTION_ID, "test-connection-invalid-2z",
1052                       NM_SETTING_CONNECTION_TYPE, "802-3-ethernet",
1053                       NM_SETTING_CONNECTION_UUID, uuid2,
1054                       NULL);
1055
1056         nmtstc_service_update_connection (my_sinfo,
1057                                           path2,
1058                                           connection,
1059                                           FALSE);
1060
1061         nmtst_main_loop_run (loop, 100);
1062
1063         _slist_to_array (&connections, nm_remote_settings_list_connections (settings));
1064
1065         g_assert_cmpint (connections->len, ==, 3);
1066         n_found = nmtst_find_all_indexes (connections->pdata,
1067                                           connections->len,
1068                                           (gpointer *) ((const char *[]) { path0, path1, path2 }),
1069                                           3,
1070                                           _test_connection_invalid_find_connections,
1071                                           NULL,
1072                                           idx);
1073         g_assert_cmpint (n_found, ==, 3);
1074         ASSERT_IDX (0);
1075         ASSERT_IDX (1);
1076         ASSERT_IDX (2);
1077         nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]);
1078         nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0);
1079         nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[2]]);
1080
1081
1082         /**************************************************************************
1083          * Modify the invalid connection and make it valid
1084          *************************************************************************/
1085
1086         g_clear_object (&connection);
1087         connection = nmtst_create_minimal_connection ("test-connection-invalid-1", NULL, NM_SETTING_WIRED_SETTING_NAME, &s_con);
1088         nmtst_connection_normalize (connection);
1089         g_object_set (s_con,
1090                       NM_SETTING_CONNECTION_ID, "test-connection-invalid-1x",
1091                       NM_SETTING_CONNECTION_TYPE, "802-3-ethernet",
1092                       NM_SETTING_CONNECTION_UUID, nm_connection_get_uuid (connections->pdata[idx[1]]),
1093                       NULL);
1094
1095         nmtstc_service_update_connection (my_sinfo,
1096                                           path1,
1097                                           connection,
1098                                           FALSE);
1099
1100         nmtst_main_loop_run (loop, 100);
1101
1102         _slist_to_array (&connections, nm_remote_settings_list_connections (settings));
1103
1104         g_assert_cmpint (connections->len, ==, 3);
1105         n_found = nmtst_find_all_indexes (connections->pdata,
1106                                           connections->len,
1107                                           (gpointer *) ((const char *[]) { path0, path1, path2 }),
1108                                           3,
1109                                           _test_connection_invalid_find_connections,
1110                                           NULL,
1111                                           idx);
1112         g_assert_cmpint (n_found, ==, 3);
1113         ASSERT_IDX (0);
1114         ASSERT_IDX (1);
1115         ASSERT_IDX (2);
1116         nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]);
1117         nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[1]]);
1118         nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[2]]);
1119         g_assert_cmpstr ("test-connection-invalid-1x", ==, nm_connection_get_id (connections->pdata[idx[1]]));
1120
1121 #undef ASSERT_IDX
1122 }
1123
1124 /*******************************************************************/
1125
1126 NMTST_DEFINE ();
1127
1128 int
1129 main (int argc, char **argv)
1130 {
1131         nmtst_init (&argc, &argv, TRUE);
1132
1133         loop = g_main_loop_new (NULL, FALSE);
1134
1135         g_test_add_func ("/libnm-glib/device-added", test_device_added);
1136         g_test_add_func ("/libnm-glib/wifi-ap-added-removed", test_wifi_ap_added_removed);
1137         g_test_add_func ("/libnm-glib/wimax-nsp-added-removed", test_wimax_nsp_added_removed);
1138         g_test_add_func ("/libnm-glib/devices-array", test_devices_array);
1139         g_test_add_func ("/libnm-glib/client-manager-running", test_client_manager_running);
1140         g_test_add_func ("/libnm/connection/invalid", test_connection_invalid);
1141
1142         return g_test_run ();
1143 }
1144