libnm-core/tests: refactor call to nm_simple_connection_new_from_dbus()
[NetworkManager.git] / libnm-core / tests / test-general.c
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT SC WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * Copyright 2008 - 2011 Red Hat, Inc.
19  *
20  */
21
22 #define NM_GLIB_COMPAT_H_TEST
23
24 #include "nm-default.h"
25
26 #include <string.h>
27
28 #include "nm-utils.h"
29 #include "nm-setting-private.h"
30 #include "nm-utils.h"
31 #include "nm-utils-private.h"
32 #include "nm-core-internal.h"
33 #include "nm-core-tests-enum-types.h"
34
35 #include "nm-setting-8021x.h"
36 #include "nm-setting-adsl.h"
37 #include "nm-setting-bluetooth.h"
38 #include "nm-setting-bond.h"
39 #include "nm-setting-bridge.h"
40 #include "nm-setting-bridge-port.h"
41 #include "nm-setting-cdma.h"
42 #include "nm-setting-connection.h"
43 #include "nm-setting-generic.h"
44 #include "nm-setting-gsm.h"
45 #include "nm-setting-infiniband.h"
46 #include "nm-setting-ip4-config.h"
47 #include "nm-setting-ip6-config.h"
48 #include "nm-setting-olpc-mesh.h"
49 #include "nm-setting-ppp.h"
50 #include "nm-setting-pppoe.h"
51 #include "nm-setting-serial.h"
52 #include "nm-setting-team.h"
53 #include "nm-setting-team-port.h"
54 #include "nm-setting-vlan.h"
55 #include "nm-setting-vpn.h"
56 #include "nm-setting-wimax.h"
57 #include "nm-setting-wired.h"
58 #include "nm-setting-wireless.h"
59 #include "nm-setting-wireless-security.h"
60 #include "nm-simple-connection.h"
61 #include "nm-keyfile-internal.h"
62
63 #include "test-general-enums.h"
64
65 #include "nm-test-utils.h"
66
67 /* When passing a "bool" typed argument to a variadic function that
68  * expects a gboolean, the compiler will promote the integer type
69  * to have at least size (int). That way:
70  *   g_object_set (obj, PROP_BOOL, bool_val, NULL);
71  * will just work correctly. */
72 G_STATIC_ASSERT (sizeof (gboolean) == sizeof (int));
73 G_STATIC_ASSERT (sizeof (bool) <= sizeof (int));
74
75 /*****************************************************************************/
76
77 static NMConnection *
78 _connection_new_from_dbus (GVariant *dict, GError **error)
79 {
80         return _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, error);
81 }
82
83 static void
84 vpn_check_func (const char *key, const char *value, gpointer user_data)
85 {
86         if (!strcmp (key, "foobar1")) {
87                 g_assert_cmpstr (value, ==, "blahblah1");
88                 return;
89         }
90
91         if (!strcmp (key, "foobar2")) {
92                 g_assert_cmpstr (value, ==, "blahblah2");
93                 return;
94         }
95
96         if (!strcmp (key, "foobar3")) {
97                 g_assert_cmpstr (value, ==, "blahblah3");
98                 return;
99         }
100
101         if (!strcmp (key, "foobar4")) {
102                 g_assert_cmpstr (value, ==, "blahblah4");
103                 return;
104         }
105
106         g_assert_not_reached ();
107 }
108
109 static void
110 vpn_check_empty_func (const char *key, const char *value, gpointer user_data)
111 {
112         g_assert_not_reached ();
113 }
114
115 static void
116 test_setting_vpn_items (void)
117 {
118         gs_unref_object NMSettingVpn *s_vpn = NULL;
119
120         s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
121         g_assert (s_vpn);
122
123         nm_setting_vpn_add_data_item (s_vpn, "foobar1", "blahblah1");
124         nm_setting_vpn_add_data_item (s_vpn, "foobar2", "blahblah2");
125         nm_setting_vpn_add_data_item (s_vpn, "foobar3", "blahblah3");
126         nm_setting_vpn_add_data_item (s_vpn, "foobar4", "blahblah4");
127
128         /* Ensure that added values are all present */
129         nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_func, NULL);
130         nm_setting_vpn_remove_data_item (s_vpn, "foobar1");
131         nm_setting_vpn_remove_data_item (s_vpn, "foobar2");
132         nm_setting_vpn_remove_data_item (s_vpn, "foobar3");
133         nm_setting_vpn_remove_data_item (s_vpn, "foobar4");
134
135         nm_setting_vpn_add_secret (s_vpn, "foobar1", "blahblah1");
136         nm_setting_vpn_add_secret (s_vpn, "foobar2", "blahblah2");
137         nm_setting_vpn_add_secret (s_vpn, "foobar3", "blahblah3");
138         nm_setting_vpn_add_secret (s_vpn, "foobar4", "blahblah4");
139
140         /* Ensure that added values are all present */
141         nm_setting_vpn_foreach_secret (s_vpn, vpn_check_func, NULL);
142         nm_setting_vpn_remove_secret (s_vpn, "foobar1");
143         nm_setting_vpn_remove_secret (s_vpn, "foobar2");
144         nm_setting_vpn_remove_secret (s_vpn, "foobar3");
145         nm_setting_vpn_remove_secret (s_vpn, "foobar4");
146
147         /* Try to add some blank values and make sure they are rejected */
148         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
149         nm_setting_vpn_add_data_item (s_vpn, NULL, NULL);
150         g_test_assert_expected_messages ();
151
152         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
153         nm_setting_vpn_add_data_item (s_vpn, "", "");
154         g_test_assert_expected_messages ();
155
156         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*item != NULL*");
157         nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL);
158         g_test_assert_expected_messages ();
159
160         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (item) > 0*");
161         nm_setting_vpn_add_data_item (s_vpn, "foobar1", "");
162         g_test_assert_expected_messages ();
163
164         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
165         nm_setting_vpn_add_data_item (s_vpn, NULL, "blahblah1");
166         g_test_assert_expected_messages ();
167
168         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
169         nm_setting_vpn_add_data_item (s_vpn, "", "blahblah1");
170         g_test_assert_expected_messages ();
171
172         nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_empty_func, NULL);
173
174         /* Try to add some blank secrets and make sure they are rejected */
175         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
176         nm_setting_vpn_add_secret (s_vpn, NULL, NULL);
177         g_test_assert_expected_messages ();
178
179         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
180         nm_setting_vpn_add_secret (s_vpn, "", "");
181         g_test_assert_expected_messages ();
182
183         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*secret != NULL*");
184         nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL);
185         g_test_assert_expected_messages ();
186
187         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (secret) > 0*");
188         nm_setting_vpn_add_secret (s_vpn, "foobar1", "");
189         g_test_assert_expected_messages ();
190
191         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
192         nm_setting_vpn_add_secret (s_vpn, NULL, "blahblah1");
193         g_test_assert_expected_messages ();
194
195         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
196         nm_setting_vpn_add_secret (s_vpn, "", "blahblah1");
197         g_test_assert_expected_messages ();
198
199         nm_setting_vpn_foreach_secret (s_vpn, vpn_check_empty_func, NULL);
200 }
201
202 static void
203 test_setting_vpn_update_secrets (void)
204 {
205         NMConnection *connection;
206         NMSettingVpn *s_vpn;
207         GVariantBuilder settings_builder, vpn_builder, secrets_builder;
208         GVariant *settings;
209         gboolean success;
210         GError *error = NULL;
211         const char *tmp;
212         const char *key1 = "foobar";
213         const char *key2 = "blahblah";
214         const char *val1 = "value1";
215         const char *val2 = "value2";
216
217         connection = nm_simple_connection_new ();
218         s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
219         nm_connection_add_setting (connection, NM_SETTING (s_vpn));
220
221         g_variant_builder_init (&settings_builder, NM_VARIANT_TYPE_CONNECTION);
222         g_variant_builder_init (&vpn_builder, NM_VARIANT_TYPE_SETTING);
223         g_variant_builder_init (&secrets_builder, G_VARIANT_TYPE ("a{ss}"));
224
225         g_variant_builder_add (&secrets_builder, "{ss}", key1, val1);
226         g_variant_builder_add (&secrets_builder, "{ss}", key2, val2);
227
228         g_variant_builder_add (&vpn_builder, "{sv}",
229                                NM_SETTING_VPN_SECRETS,
230                                g_variant_builder_end (&secrets_builder));
231         g_variant_builder_add (&settings_builder, "{sa{sv}}",
232                                NM_SETTING_VPN_SETTING_NAME,
233                                &vpn_builder);
234         settings = g_variant_builder_end (&settings_builder);
235
236         success = nm_connection_update_secrets (connection, NM_SETTING_VPN_SETTING_NAME, settings, &error);
237         g_assert_no_error (error);
238         g_assert (success);
239
240         /* Read the secrets back out */
241         tmp = nm_setting_vpn_get_secret (s_vpn, key1);
242         g_assert (tmp);
243         g_assert_cmpstr (tmp, ==, val1);
244
245         tmp = nm_setting_vpn_get_secret (s_vpn, key2);
246         g_assert (tmp);
247         g_assert_cmpstr (tmp, ==, val2);
248
249         g_variant_unref (settings);
250         g_object_unref (connection);
251 }
252
253 #define TO_DEL_NUM 50
254 typedef struct {
255         NMSettingVpn *s_vpn;
256         char *to_del[TO_DEL_NUM];
257         guint called;
258 } IterInfo;
259
260 static void
261 del_iter_func (const char *key, const char *value, gpointer user_data)
262 {
263         IterInfo *info = user_data;
264         int i;
265
266         /* Record how many times this function gets called; it should get called
267          * exactly as many times as there are keys in the hash table, regardless
268          * of what keys we delete from the table.
269          */
270         info->called++;
271
272         /* During the iteration, remove a bunch of stuff from the table */
273         if (info->called == 1) {
274                 for (i = 0; i < TO_DEL_NUM; i++)
275                         nm_setting_vpn_remove_data_item (info->s_vpn, info->to_del[i]);
276         }
277 }
278
279 static void
280 test_setting_vpn_modify_during_foreach (void)
281 {
282         NMSettingVpn *s_vpn;
283         IterInfo info;
284         char *key, *val;
285         int i, u = 0;
286
287         s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
288         g_assert (s_vpn);
289
290         for (i = 0; i < TO_DEL_NUM * 2; i++) {
291                 key = g_strdup_printf ("adsfasdfadf%d", i);
292                 val = g_strdup_printf ("42263236236awt%d", i);
293                 nm_setting_vpn_add_data_item (s_vpn, key, val);
294
295                 /* Cache some keys to delete */
296                 if (i % 2)
297                         info.to_del[u++] = g_strdup (key);
298
299                 g_free (key);
300                 g_free (val);
301         }
302
303         /* Iterate over current table keys */
304         info.s_vpn = s_vpn;
305         info.called = 0;
306         nm_setting_vpn_foreach_data_item (s_vpn, del_iter_func, &info);
307
308         /* Make sure all the things we removed during iteration are really gone */
309         for (i = 0; i < TO_DEL_NUM; i++) {
310                 g_assert_cmpstr (nm_setting_vpn_get_data_item (s_vpn, info.to_del[i]), ==, NULL);
311                 g_free (info.to_del[i]);
312         }
313
314         /* And make sure the foreach callback was called the same number of times
315          * as there were keys in the table at the beginning of the foreach.
316          */
317         g_assert_cmpint (info.called, ==, TO_DEL_NUM * 2);
318
319         g_object_unref (s_vpn);
320 }
321
322 static void
323 test_setting_ip4_config_labels (void)
324 {
325         NMSettingIPConfig *s_ip4;
326         NMIPAddress *addr;
327         GVariant *label;
328         GPtrArray *addrs;
329         char **labels;
330         NMConnection *conn;
331         GVariant *dict, *dict2, *setting_dict, *value;
332         GError *error = NULL;
333
334         s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
335         g_object_set (G_OBJECT (s_ip4),
336                       NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
337                       NULL);
338
339         /* addr 1 */
340         addr = nm_ip_address_new (AF_INET, "1.2.3.4", 24, &error);
341         g_assert_no_error (error);
342
343         nm_setting_ip_config_add_address (s_ip4, addr);
344         nm_ip_address_unref (addr);
345         nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
346
347         addr = nm_setting_ip_config_get_address (s_ip4, 0);
348         label = nm_ip_address_get_attribute (addr, "label");
349         g_assert (label == NULL);
350
351         /* The 'address-labels' property should be omitted from the serialization if
352          * there are no non-NULL labels.
353          */
354         conn = nmtst_create_minimal_connection ("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
355         nm_connection_add_setting (conn, nm_setting_duplicate (NM_SETTING (s_ip4)));
356         dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
357         g_object_unref (conn);
358
359         setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
360         g_assert (setting_dict != NULL);
361
362         value = g_variant_lookup_value (setting_dict, "address-labels", NULL);
363         g_assert (value == NULL);
364
365         g_variant_unref (setting_dict);
366         g_variant_unref (dict);
367
368         /* Now back to constructing the original s_ip4... */
369
370         /* addr 2 */
371         addr = nm_ip_address_new (AF_INET, "2.3.4.5", 24, &error);
372         g_assert_no_error (error);
373         nm_ip_address_set_attribute (addr, "label", g_variant_new_string ("eth0:1"));
374
375         nm_setting_ip_config_add_address (s_ip4, addr);
376         nm_ip_address_unref (addr);
377         nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
378
379         addr = nm_setting_ip_config_get_address (s_ip4, 1);
380         label = nm_ip_address_get_attribute (addr, "label");
381         g_assert (label != NULL);
382         g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
383
384         /* addr 3 */
385         addr = nm_ip_address_new (AF_INET, "3.4.5.6", 24, &error);
386         g_assert_no_error (error);
387         nm_ip_address_set_attribute (addr, "label", NULL);
388
389         nm_setting_ip_config_add_address (s_ip4, addr);
390         nm_ip_address_unref (addr);
391         nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
392
393         addr = nm_setting_ip_config_get_address (s_ip4, 2);
394         label = nm_ip_address_get_attribute (addr, "label");
395         g_assert (label == NULL);
396
397         /* Remove addr 1 and re-verify remaining addresses */
398         nm_setting_ip_config_remove_address (s_ip4, 0);
399         nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
400
401         addr = nm_setting_ip_config_get_address (s_ip4, 0);
402         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
403         label = nm_ip_address_get_attribute (addr, "label");
404         g_assert (label != NULL);
405         g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
406
407         addr = nm_setting_ip_config_get_address (s_ip4, 1);
408         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
409         label = nm_ip_address_get_attribute (addr, "label");
410         g_assert (label == NULL);
411
412         /* If we serialize as the daemon, the labels should appear in the D-Bus
413          * serialization under both 'address-labels' and 'address-data'.
414          */
415         conn = nmtst_create_minimal_connection ("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
416         nm_connection_add_setting (conn, NM_SETTING (s_ip4));
417         _nm_utils_is_manager_process = TRUE;
418         dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
419         _nm_utils_is_manager_process = FALSE;
420         g_object_unref (conn);
421
422         setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
423         g_assert (setting_dict != NULL);
424
425         value = g_variant_lookup_value (setting_dict, "address-labels", G_VARIANT_TYPE_STRING_ARRAY);
426         g_assert (value != NULL);
427         g_variant_get (value, "^as", &labels);
428         g_assert_cmpint (g_strv_length (labels), ==, 2);
429         g_assert_cmpstr (labels[0], ==, "eth0:1");
430         g_assert_cmpstr (labels[1], ==, "");
431         g_variant_unref (value);
432         g_strfreev (labels);
433
434         value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
435         addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
436         g_variant_unref (value);
437         g_assert (addrs != NULL);
438         g_assert_cmpint (addrs->len, ==, 2);
439         addr = addrs->pdata[0];
440         label = nm_ip_address_get_attribute (addr, "label");
441         g_assert (label != NULL);
442         g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
443         addr = addrs->pdata[1];
444         label = nm_ip_address_get_attribute (addr, "label");
445         g_assert (label == NULL);
446         g_ptr_array_unref (addrs);
447
448         g_variant_unref (setting_dict);
449
450         /* We should be able to deserialize the labels from either 'address-labels'
451          * or 'address-data'.
452          */
453         dict2 = g_variant_ref (dict);
454
455         NMTST_VARIANT_EDITOR (dict,
456                               NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
457                                                            "address-data");
458                               );
459         conn = _connection_new_from_dbus (dict, &error);
460         g_assert_no_error (error);
461         g_variant_unref (dict);
462
463         s_ip4 = nm_connection_get_setting_ip4_config (conn);
464
465         addr = nm_setting_ip_config_get_address (s_ip4, 0);
466         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
467         label = nm_ip_address_get_attribute (addr, "label");
468         g_assert (label != NULL);
469         g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
470
471         addr = nm_setting_ip_config_get_address (s_ip4, 1);
472         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
473         label = nm_ip_address_get_attribute (addr, "label");
474         g_assert (label == NULL);
475
476         g_object_unref (conn);
477
478         NMTST_VARIANT_EDITOR (dict2,
479                               NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
480                                                            "address-labels");
481                               );
482         conn = _connection_new_from_dbus (dict2, &error);
483         g_assert_no_error (error);
484         g_variant_unref (dict2);
485
486         s_ip4 = nm_connection_get_setting_ip4_config (conn);
487
488         addr = nm_setting_ip_config_get_address (s_ip4, 0);
489         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
490         label = nm_ip_address_get_attribute (addr, "label");
491         g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
492
493         addr = nm_setting_ip_config_get_address (s_ip4, 1);
494         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
495         label = nm_ip_address_get_attribute (addr, "label");
496         g_assert (label == NULL);
497
498         /* Test explicit property assignment */
499         g_object_get (G_OBJECT (s_ip4),
500                       NM_SETTING_IP_CONFIG_ADDRESSES, &addrs,
501                       NULL);
502
503         nm_setting_ip_config_clear_addresses (s_ip4);
504         g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 0);
505
506         g_object_set (G_OBJECT (s_ip4),
507                       NM_SETTING_IP_CONFIG_ADDRESSES, addrs,
508                       NULL);
509         g_ptr_array_unref (addrs);
510         nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
511         g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 2);
512
513         addr = nm_setting_ip_config_get_address (s_ip4, 0);
514         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
515         label = nm_ip_address_get_attribute (addr, "label");
516         g_assert (label != NULL);
517         g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
518
519         addr = nm_setting_ip_config_get_address (s_ip4, 1);
520         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
521         label = nm_ip_address_get_attribute (addr, "label");
522         g_assert (label == NULL);
523
524         g_object_unref (conn);
525 }
526
527 static void
528 test_setting_ip4_config_address_data (void)
529 {
530         NMSettingIPConfig *s_ip4;
531         NMIPAddress *addr;
532         GPtrArray *addrs;
533         NMConnection *conn;
534         GVariant *dict, *setting_dict, *value;
535         GError *error = NULL;
536
537         s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
538         g_object_set (G_OBJECT (s_ip4),
539                       NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
540                       NULL);
541
542         /* addr 1 */
543         addr = nm_ip_address_new (AF_INET, "1.2.3.4", 24, &error);
544         g_assert_no_error (error);
545         nm_ip_address_set_attribute (addr, "one", g_variant_new_string ("foo"));
546         nm_ip_address_set_attribute (addr, "two", g_variant_new_int32 (42));
547
548         nm_setting_ip_config_add_address (s_ip4, addr);
549         nm_ip_address_unref (addr);
550         nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
551
552         /* addr 2 */
553         addr = nm_ip_address_new (AF_INET, "2.3.4.5", 24, &error);
554         g_assert_no_error (error);
555
556         nm_setting_ip_config_add_address (s_ip4, addr);
557         nm_ip_address_unref (addr);
558         nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
559
560         /* The client-side D-Bus serialization should include the attributes in
561          * "address-data", and should not have an "addresses" property.
562          */
563         conn = nmtst_create_minimal_connection ("address-data test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
564         nm_connection_add_setting (conn, NM_SETTING (s_ip4));
565         dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
566
567         setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
568         g_assert (setting_dict != NULL);
569
570         value = g_variant_lookup_value (setting_dict, "addresses", NULL);
571         g_assert (value == NULL);
572
573         value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
574         addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
575         g_variant_unref (value);
576         g_assert (addrs != NULL);
577         g_assert_cmpint (addrs->len, ==, 2);
578
579         addr = addrs->pdata[0];
580         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.2.3.4");
581         value = nm_ip_address_get_attribute (addr, "one");
582         g_assert (value != NULL);
583         g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "foo");
584         value = nm_ip_address_get_attribute (addr, "two");
585         g_assert (value != NULL);
586         g_assert_cmpint (g_variant_get_int32 (value), ==, 42);
587
588         g_ptr_array_unref (addrs);
589         g_variant_unref (setting_dict);
590         g_variant_unref (dict);
591
592         /* The daemon-side serialization should include both 'addresses' and 'address-data' */
593         _nm_utils_is_manager_process = TRUE;
594         dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
595         _nm_utils_is_manager_process = FALSE;
596
597         setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
598         g_assert (setting_dict != NULL);
599
600         value = g_variant_lookup_value (setting_dict, "addresses", G_VARIANT_TYPE ("aau"));
601         g_assert (value != NULL);
602         g_variant_unref (value);
603
604         value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
605         g_assert (value != NULL);
606         g_variant_unref (value);
607
608         g_variant_unref (setting_dict);
609         g_object_unref (conn);
610
611         /* When we reserialize that dictionary as a client, 'address-data' will be preferred. */
612         conn = _connection_new_from_dbus (dict, &error);
613         g_assert_no_error (error);
614
615         s_ip4 = nm_connection_get_setting_ip4_config (conn);
616
617         addr = nm_setting_ip_config_get_address (s_ip4, 0);
618         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.2.3.4");
619         value = nm_ip_address_get_attribute (addr, "one");
620         g_assert (value != NULL);
621         g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "foo");
622         value = nm_ip_address_get_attribute (addr, "two");
623         g_assert (value != NULL);
624         g_assert_cmpint (g_variant_get_int32 (value), ==, 42);
625
626         /* But on the server side, 'addresses' will have precedence. */
627         _nm_utils_is_manager_process = TRUE;
628         conn = _connection_new_from_dbus (dict, &error);
629         _nm_utils_is_manager_process = FALSE;
630         g_assert_no_error (error);
631         g_variant_unref (dict);
632
633         s_ip4 = nm_connection_get_setting_ip4_config (conn);
634
635         addr = nm_setting_ip_config_get_address (s_ip4, 0);
636         g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.2.3.4");
637         value = nm_ip_address_get_attribute (addr, "one");
638         g_assert (value == NULL);
639         value = nm_ip_address_get_attribute (addr, "two");
640         g_assert (value == NULL);
641
642         g_object_unref (conn);
643 }
644
645 static void
646 test_setting_gsm_apn_spaces (void)
647 {
648         gs_unref_object NMSettingGsm *s_gsm = NULL;
649         const char *tmp;
650
651         s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
652         g_assert (s_gsm);
653
654         /* Trailing space */
655         g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar ", NULL);
656         tmp = nm_setting_gsm_get_apn (s_gsm);
657         g_assert_cmpstr (tmp, ==, "foobar");
658
659         /* Leading space */
660         g_object_set (s_gsm, NM_SETTING_GSM_APN, " foobar", NULL);
661         tmp = nm_setting_gsm_get_apn (s_gsm);
662         g_assert_cmpstr (tmp, ==, "foobar");
663 }
664
665 static void
666 test_setting_gsm_apn_bad_chars (void)
667 {
668         gs_unref_object NMSettingGsm *s_gsm = NULL;
669
670         s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
671         g_assert (s_gsm);
672
673         g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL);
674
675         /* Make sure a valid APN works */
676         g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar123.-baz", NULL);
677         g_assert (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
678
679         /* Random invalid chars */
680         g_object_set (s_gsm, NM_SETTING_GSM_APN, "@#%$@#%@#%", NULL);
681         g_assert (!nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
682
683         /* Spaces */
684         g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar baz", NULL);
685         g_assert (!nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
686
687         /* 0 characters long */
688         g_object_set (s_gsm, NM_SETTING_GSM_APN, "", NULL);
689         g_assert (!nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
690
691         /* 65-character long */
692         g_object_set (s_gsm, NM_SETTING_GSM_APN, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl1", NULL);
693         g_assert (!nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL));
694 }
695
696 static void
697 test_setting_gsm_apn_underscore (void)
698 {
699         gs_unref_object NMSettingGsm *s_gsm = NULL;
700
701         s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
702         g_assert (s_gsm);
703
704         g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL);
705
706         /* 65-character long */
707         g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar_baz", NULL);
708         nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
709 }
710
711 static void
712 test_setting_gsm_without_number (void)
713 {
714         gs_unref_object NMSettingGsm *s_gsm = NULL;
715
716         s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
717         g_assert (s_gsm);
718
719         g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, NULL, NULL);
720         nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
721
722         g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "", NULL);
723         nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
724                                            NM_CONNECTION_ERROR_INVALID_PROPERTY);
725 }
726
727 static void
728 test_setting_gsm_sim_operator_id (void)
729 {
730         gs_unref_object NMSettingGsm *s_gsm = NULL;
731
732         s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
733         g_assert (s_gsm);
734
735         /* Valid */
736         g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "12345", NULL);
737         nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
738
739         g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "123456", NULL);
740         nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
741
742         /* Invalid */
743         g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "", NULL);
744         nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
745                                            NM_CONNECTION_ERROR_INVALID_PROPERTY);
746
747         g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "     ", NULL);
748         nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
749                                            NM_CONNECTION_ERROR_INVALID_PROPERTY);
750
751         g_object_set (s_gsm, NM_SETTING_GSM_SIM_OPERATOR_ID, "abcdef", NULL);
752         nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
753                                            NM_CONNECTION_ERROR_INVALID_PROPERTY);
754 }
755
756 static NMSettingWirelessSecurity *
757 make_test_wsec_setting (const char *detail)
758 {
759         NMSettingWirelessSecurity *s_wsec;
760
761         s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
762         g_assert (s_wsec);
763
764         g_object_set (s_wsec,
765                       NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
766                       NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, "foobarbaz",
767                       NM_SETTING_WIRELESS_SECURITY_PSK, "random psk",
768                       NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED,
769                       NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, "aaaaaaaaaa",
770                       NULL);
771         return s_wsec;
772 }
773
774 static gboolean
775 _variant_contains (GVariant *vardict, const char *key)
776 {
777         gs_unref_variant GVariant *value = NULL;
778
779         value = g_variant_lookup_value (vardict, key, NULL);
780         return !!value;
781 }
782
783 static void
784 test_setting_to_dbus_all (void)
785 {
786         NMSettingWirelessSecurity *s_wsec;
787         GVariant *dict;
788
789         s_wsec = make_test_wsec_setting ("setting-to-dbus-all");
790
791         dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL);
792
793         /* Make sure all keys are there */
794         g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT));
795         g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME));
796         g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_PSK));
797         g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0));
798
799         g_variant_unref (dict);
800         g_object_unref (s_wsec);
801 }
802
803 static void
804 test_setting_to_dbus_no_secrets (void)
805 {
806         NMSettingWirelessSecurity *s_wsec;
807         GVariant *dict;
808
809         s_wsec = make_test_wsec_setting ("setting-to-dbus-no-secrets");
810
811         dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_NO_SECRETS);
812
813         /* Make sure non-secret keys are there */
814         g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT));
815         g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME));
816
817         /* Make sure secrets are not there */
818         g_assert (!_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_PSK));
819         g_assert (!_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0));
820
821         g_variant_unref (dict);
822         g_object_unref (s_wsec);
823 }
824
825 static void
826 test_setting_to_dbus_only_secrets (void)
827 {
828         NMSettingWirelessSecurity *s_wsec;
829         GVariant *dict;
830
831         s_wsec = make_test_wsec_setting ("setting-to-dbus-only-secrets");
832
833         dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ONLY_SECRETS);
834
835         /* Make sure non-secret keys are not there */
836         g_assert (!_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT));
837         g_assert (!_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME));
838
839         /* Make sure secrets are there */
840         g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_PSK));
841         g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0));
842
843         g_variant_unref (dict);
844         g_object_unref (s_wsec);
845 }
846
847 static void
848 test_setting_to_dbus_transform (void)
849 {
850         NMSetting *s_wired;
851         GVariant *dict, *val;
852         const char *test_mac_address = "11:22:33:44:55:66";
853         const guint8 *dbus_mac_address;
854         guint8 cmp_mac_address[ETH_ALEN];
855         gsize len;
856
857         s_wired = nm_setting_wired_new ();
858         g_object_set (s_wired,
859                       NM_SETTING_WIRED_MAC_ADDRESS, test_mac_address,
860                       NULL);
861
862         g_assert_cmpstr (nm_setting_wired_get_mac_address (NM_SETTING_WIRED (s_wired)), ==, test_mac_address);
863
864         dict = _nm_setting_to_dbus (s_wired, NULL, NM_CONNECTION_SERIALIZE_ALL);
865         g_assert (dict != NULL);
866
867         val = g_variant_lookup_value (dict, NM_SETTING_WIRED_MAC_ADDRESS, G_VARIANT_TYPE_BYTESTRING);
868         g_assert (val != NULL);
869
870         dbus_mac_address = g_variant_get_fixed_array (val, &len, 1);
871         g_assert_cmpint (len, ==, ETH_ALEN);
872
873         nm_utils_hwaddr_aton (test_mac_address, cmp_mac_address, ETH_ALEN);
874         g_assert (memcmp (dbus_mac_address, cmp_mac_address, ETH_ALEN) == 0);
875
876         g_variant_unref (val);
877         g_variant_unref (dict);
878         g_object_unref (s_wired);
879 }
880
881 static void
882 test_setting_to_dbus_enum (void)
883 {
884         NMSetting *s_ip6, *s_wsec, *s_serial;
885         GVariant *dict, *val;
886
887         /* enum */
888         s_ip6 = nm_setting_ip6_config_new ();
889         g_object_set (s_ip6,
890                       NM_SETTING_IP6_CONFIG_IP6_PRIVACY, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
891                       NULL);
892
893         dict = _nm_setting_to_dbus (s_ip6, NULL, NM_CONNECTION_SERIALIZE_ALL);
894         g_assert (dict != NULL);
895
896         val = g_variant_lookup_value (dict, NM_SETTING_IP6_CONFIG_IP6_PRIVACY, G_VARIANT_TYPE_INT32);
897         g_assert (val != NULL);
898         g_assert_cmpint (g_variant_get_int32 (val), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
899         g_variant_unref (val);
900
901         g_variant_unref (dict);
902         g_object_unref (s_ip6);
903
904         /* flags (and a transformed enum) */
905         s_wsec = nm_setting_wireless_security_new ();
906         g_object_set (s_wsec,
907                       NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, NM_WEP_KEY_TYPE_KEY,
908                       NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
909                                                                    NM_SETTING_SECRET_FLAG_NOT_SAVED),
910                       NULL);
911
912         dict = _nm_setting_to_dbus (s_wsec, NULL, NM_CONNECTION_SERIALIZE_ALL);
913         g_assert (dict != NULL);
914
915         val = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, G_VARIANT_TYPE_UINT32);
916         g_assert (val != NULL);
917         g_assert_cmpint (g_variant_get_uint32 (val), ==, NM_WEP_KEY_TYPE_KEY);
918         g_variant_unref (val);
919
920         val = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, G_VARIANT_TYPE_UINT32);
921         g_assert (val != NULL);
922         g_assert_cmpint (g_variant_get_uint32 (val), ==, (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
923                                                           NM_SETTING_SECRET_FLAG_NOT_SAVED));
924         g_variant_unref (val);
925
926         g_variant_unref (dict);
927         g_object_unref (s_wsec);
928
929         /* another transformed enum */
930         s_serial = nm_setting_serial_new ();
931         g_object_set (s_serial,
932                       NM_SETTING_SERIAL_PARITY, NM_SETTING_SERIAL_PARITY_ODD,
933                       NULL);
934
935         dict = _nm_setting_to_dbus (s_serial, NULL, NM_CONNECTION_SERIALIZE_ALL);
936         g_assert (dict != NULL);
937
938         val = g_variant_lookup_value (dict, NM_SETTING_SERIAL_PARITY, G_VARIANT_TYPE_BYTE);
939         g_assert (val != NULL);
940         g_assert_cmpint (g_variant_get_byte (val), ==, 'o');
941         g_variant_unref (val);
942
943         g_variant_unref (dict);
944         g_object_unref (s_serial);
945 }
946
947 static void
948 test_connection_to_dbus_setting_name (void)
949 {
950         NMConnection *connection;
951         NMSettingWirelessSecurity *s_wsec;
952         GVariant *dict;
953
954         connection = nm_simple_connection_new ();
955         s_wsec = make_test_wsec_setting ("connection-to-dbus-setting-name");
956         nm_connection_add_setting (connection, NM_SETTING (s_wsec));
957
958         dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
959
960         /* Make sure the keys of the first level dict are setting names, not
961          * the GType name of the setting objects.
962          */
963         g_assert (_variant_contains (dict, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME));
964
965         g_variant_unref (dict);
966         g_object_unref (connection);
967 }
968
969 static void
970 test_connection_to_dbus_deprecated_props (void)
971 {
972         NMConnection *connection;
973         NMSetting *s_wireless;
974         GBytes *ssid;
975         NMSettingWirelessSecurity *s_wsec;
976         GVariant *dict, *wireless_dict, *sec_val;
977
978         connection = nmtst_create_minimal_connection ("test-connection-to-dbus-deprecated-props",
979                                                       NULL,
980                                                       NM_SETTING_WIRELESS_SETTING_NAME,
981                                                       NULL);
982
983         s_wireless = nm_setting_wireless_new ();
984         ssid = g_bytes_new ("1234567", 7);
985         g_object_set (s_wireless,
986                       NM_SETTING_WIRELESS_SSID, ssid,
987                       NULL);
988         g_bytes_unref (ssid);
989         nm_connection_add_setting (connection, s_wireless);
990
991         /* Serialization should not have an 802-11-wireless.security property */
992         dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
993         g_assert (dict != NULL);
994
995         wireless_dict = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
996         g_assert (wireless_dict != NULL);
997
998         sec_val = g_variant_lookup_value (wireless_dict, "security", NULL);
999         g_assert (sec_val == NULL);
1000
1001         g_variant_unref (wireless_dict);
1002         g_variant_unref (dict);
1003
1004         /* Now add an NMSettingWirelessSecurity and try again */
1005         s_wsec = make_test_wsec_setting ("test-connection-to-dbus-deprecated-props");
1006         nm_connection_add_setting (connection, NM_SETTING (s_wsec));
1007
1008         dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
1009         g_assert (dict != NULL);
1010
1011         wireless_dict = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
1012         g_assert (wireless_dict != NULL);
1013
1014         sec_val = g_variant_lookup_value (wireless_dict, "security", NULL);
1015         g_assert (g_variant_is_of_type (sec_val, G_VARIANT_TYPE_STRING));
1016         g_assert_cmpstr (g_variant_get_string (sec_val, NULL), ==, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
1017
1018         g_variant_unref (sec_val);
1019         g_variant_unref (wireless_dict);
1020         g_variant_unref (dict);
1021         g_object_unref (connection);
1022 }
1023
1024 static void
1025 test_setting_new_from_dbus (void)
1026 {
1027         NMSettingWirelessSecurity *s_wsec;
1028         GVariant *dict;
1029
1030         s_wsec = make_test_wsec_setting ("setting-new-from-dbus");
1031         dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL);
1032         g_object_unref (s_wsec);
1033
1034         s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, NULL);
1035         g_variant_unref (dict);
1036
1037         g_assert (s_wsec);
1038         g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk");
1039         g_assert_cmpstr (nm_setting_wireless_security_get_leap_username (s_wsec), ==, "foobarbaz");
1040         g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "random psk");
1041         g_object_unref (s_wsec);
1042 }
1043
1044 static void
1045 test_setting_new_from_dbus_transform (void)
1046 {
1047         NMSetting *s_wired;
1048         GVariant *dict;
1049         GVariantBuilder builder;
1050         const char *test_mac_address = "11:22:33:44:55:66";
1051         guint8 dbus_mac_address[ETH_ALEN];
1052         GError *error = NULL;
1053
1054         nm_utils_hwaddr_aton (test_mac_address, dbus_mac_address, ETH_ALEN);
1055
1056         g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
1057         g_variant_builder_add (&builder, "{sv}",
1058                                NM_SETTING_WIRED_MAC_ADDRESS,
1059                                g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
1060                                                           dbus_mac_address, ETH_ALEN, 1));
1061         dict = g_variant_builder_end (&builder);
1062
1063         s_wired = _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRED, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error);
1064         g_assert_no_error (error);
1065
1066         g_assert_cmpstr (nm_setting_wired_get_mac_address (NM_SETTING_WIRED (s_wired)), ==, test_mac_address);
1067
1068         g_variant_unref (dict);
1069         g_object_unref (s_wired);
1070 }
1071
1072 static void
1073 test_setting_new_from_dbus_enum (void)
1074 {
1075         NMSettingIP6Config *s_ip6;
1076         NMSettingWirelessSecurity *s_wsec;
1077         NMSettingSerial *s_serial;
1078         GVariant *dict;
1079         GVariantBuilder builder;
1080         GError *error = NULL;
1081
1082         /* enum */
1083         g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
1084         g_variant_builder_add (&builder, "{sv}",
1085                                NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
1086                                g_variant_new_int32 (NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
1087         dict = g_variant_builder_end (&builder);
1088
1089         s_ip6 = (NMSettingIP6Config *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_IP6_CONFIG, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error);
1090         g_assert_no_error (error);
1091
1092         g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (s_ip6), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
1093
1094         g_variant_unref (dict);
1095         g_object_unref (s_ip6);
1096
1097         /* flags (and a transformed enum) */
1098         g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
1099         g_variant_builder_add (&builder, "{sv}",
1100                                NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
1101                                g_variant_new_uint32 (NM_WEP_KEY_TYPE_KEY));
1102         g_variant_builder_add (&builder, "{sv}",
1103                                NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS,
1104                                g_variant_new_uint32 (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
1105                                                      NM_SETTING_SECRET_FLAG_NOT_SAVED));
1106         dict = g_variant_builder_end (&builder);
1107
1108         s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error);
1109         g_assert_no_error (error);
1110
1111         g_assert_cmpint (nm_setting_wireless_security_get_wep_key_type (s_wsec), ==, NM_WEP_KEY_TYPE_KEY);
1112         g_assert_cmpint (nm_setting_wireless_security_get_wep_key_flags (s_wsec), ==, (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
1113                                                                                        NM_SETTING_SECRET_FLAG_NOT_SAVED));
1114
1115         g_variant_unref (dict);
1116         g_object_unref (s_wsec);
1117
1118         /* another transformed enum */
1119         g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
1120         g_variant_builder_add (&builder, "{sv}",
1121                                NM_SETTING_SERIAL_PARITY,
1122                                g_variant_new_byte ('E'));
1123         dict = g_variant_builder_end (&builder);
1124
1125         s_serial = (NMSettingSerial *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_SERIAL, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error);
1126         g_assert_no_error (error);
1127
1128         g_assert_cmpint (nm_setting_serial_get_parity (s_serial), ==, NM_SETTING_SERIAL_PARITY_EVEN);
1129
1130         g_variant_unref (dict);
1131         g_object_unref (s_serial);
1132 }
1133
1134 static void
1135 test_setting_new_from_dbus_bad (void)
1136 {
1137         NMSetting *setting;
1138         NMConnection *conn;
1139         GBytes *ssid;
1140         GPtrArray *addrs;
1141         GVariant *orig_dict, *dict;
1142         GError *error = NULL;
1143
1144         /* We want to test:
1145          * - ordinary scalar properties
1146          * - string properties
1147          * - GBytes-valued properties (which are handled specially by set_property_from_dbus())
1148          * - enum/flags-valued properties
1149          * - overridden properties
1150          * - transformed properties
1151          *
1152          * No single setting class has examples of all of these, so we need two settings.
1153          */
1154
1155         conn = nm_simple_connection_new ();
1156
1157         setting = nm_setting_connection_new ();
1158         g_object_set (setting,
1159                       NM_SETTING_CONNECTION_ID, "test",
1160                       NM_SETTING_CONNECTION_UUID, "83c5a841-1759-4cdb-bfce-8d4087956497",
1161                       NULL);
1162         nm_connection_add_setting (conn, setting);
1163
1164         setting = nm_setting_wireless_new ();
1165         ssid = g_bytes_new ("my-ssid", 7);
1166         g_object_set (setting,
1167                       /* scalar */
1168                       NM_SETTING_WIRELESS_RATE, 100,
1169                       /* string */
1170                       NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
1171                       /* GBytes */
1172                       NM_SETTING_WIRELESS_SSID, ssid,
1173                       /* transformed */
1174                       NM_SETTING_WIRELESS_BSSID, "00:11:22:33:44:55",
1175                       NULL);
1176         g_bytes_unref (ssid);
1177         nm_connection_add_setting (conn, setting);
1178
1179         setting = nm_setting_ip6_config_new ();
1180         addrs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
1181         g_ptr_array_add (addrs, nm_ip_address_new (AF_INET6, "1234::5678", 64, NULL));
1182         g_object_set (setting,
1183                       /* enum */
1184                       NM_SETTING_IP6_CONFIG_IP6_PRIVACY, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR,
1185                       /* overridden */
1186                       NM_SETTING_IP_CONFIG_ADDRESSES, addrs,
1187                       /* (needed in order to verify()) */
1188                       NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
1189                       NULL);
1190         g_ptr_array_unref (addrs);
1191         nm_connection_add_setting (conn, setting);
1192
1193         orig_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
1194         g_object_unref (conn);
1195
1196         /* sanity-check */
1197         conn = _connection_new_from_dbus (orig_dict, &error);
1198         g_assert_no_error (error);
1199         g_assert (conn);
1200         g_object_unref (conn);
1201
1202         /* Compatible mismatches */
1203
1204         dict = g_variant_ref (orig_dict);
1205         NMTST_VARIANT_EDITOR (dict,
1206                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
1207                                                              NM_SETTING_WIRELESS_RATE,
1208                                                              "i", 10);
1209                               );
1210         conn = _connection_new_from_dbus (dict, &error);
1211         g_assert (conn);
1212         g_assert_no_error (error);
1213         setting = nm_connection_get_setting (conn, NM_TYPE_SETTING_WIRELESS);
1214         g_assert (setting);
1215         g_assert_cmpint (nm_setting_wireless_get_rate (NM_SETTING_WIRELESS (setting)), ==, 10);
1216         g_object_unref (conn);
1217         g_variant_unref (dict);
1218
1219         dict = g_variant_ref (orig_dict);
1220         NMTST_VARIANT_EDITOR (dict,
1221                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
1222                                                              NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
1223                                                              "i", NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
1224                               );
1225         conn = _connection_new_from_dbus (dict, &error);
1226         g_assert (conn);
1227         g_assert_no_error (error);
1228         setting = nm_connection_get_setting (conn, NM_TYPE_SETTING_IP6_CONFIG);
1229         g_assert (setting);
1230         g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (setting)), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
1231         g_object_unref (conn);
1232         g_variant_unref (dict);
1233
1234         /* Incompatible mismatches */
1235
1236         dict = g_variant_ref (orig_dict);
1237         NMTST_VARIANT_EDITOR (dict,
1238                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
1239                                                              NM_SETTING_WIRELESS_RATE,
1240                                                              "s", "ten");
1241                               );
1242         conn = _connection_new_from_dbus (dict, &error);
1243         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
1244         g_assert (g_str_has_prefix (error->message, "802-11-wireless.rate:"));
1245         g_clear_error (&error);
1246         g_variant_unref (dict);
1247
1248         dict = g_variant_ref (orig_dict);
1249         NMTST_VARIANT_EDITOR (dict,
1250                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
1251                                                              NM_SETTING_WIRELESS_MODE,
1252                                                              "b", FALSE);
1253                               );
1254         conn = _connection_new_from_dbus (dict, &error);
1255         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
1256         g_assert (g_str_has_prefix (error->message, "802-11-wireless.mode:"));
1257         g_clear_error (&error);
1258         g_variant_unref (dict);
1259
1260         dict = g_variant_ref (orig_dict);
1261         NMTST_VARIANT_EDITOR (dict,
1262                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
1263                                                              NM_SETTING_WIRELESS_SSID,
1264                                                              "s", "fred");
1265                               );
1266         conn = _connection_new_from_dbus (dict, &error);
1267         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
1268         g_assert (g_str_has_prefix (error->message, "802-11-wireless.ssid:"));
1269         g_clear_error (&error);
1270         g_variant_unref (dict);
1271
1272         dict = g_variant_ref (orig_dict);
1273         NMTST_VARIANT_EDITOR (dict,
1274                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME,
1275                                                              NM_SETTING_WIRELESS_BSSID,
1276                                                              "i", 42);
1277                               );
1278         conn = _connection_new_from_dbus (dict, &error);
1279         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
1280         g_assert (g_str_has_prefix (error->message, "802-11-wireless.bssid:"));
1281         g_clear_error (&error);
1282         g_variant_unref (dict);
1283
1284         dict = g_variant_ref (orig_dict);
1285         NMTST_VARIANT_EDITOR (dict,
1286                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
1287                                                              NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
1288                                                              "s", "private");
1289                               );
1290         conn = _connection_new_from_dbus (dict, &error);
1291         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
1292         g_assert (g_str_has_prefix (error->message, "ipv6.ip6-privacy:"));
1293         g_clear_error (&error);
1294         g_variant_unref (dict);
1295
1296         dict = g_variant_ref (orig_dict);
1297         NMTST_VARIANT_EDITOR (dict,
1298                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
1299                                                              NM_SETTING_IP_CONFIG_ADDRESSES,
1300                                                              "s", "1234::5678");
1301                               );
1302         conn = _connection_new_from_dbus (dict, &error);
1303         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
1304         g_assert (g_str_has_prefix (error->message, "ipv6.addresses:"));
1305         g_clear_error (&error);
1306         g_variant_unref (dict);
1307
1308         g_variant_unref (orig_dict);
1309 }
1310
1311 static NMConnection *
1312 new_test_connection (void)
1313 {
1314         NMConnection *connection;
1315         NMSetting *setting;
1316         char *uuid;
1317         guint64 timestamp = time (NULL);
1318
1319         connection = nm_simple_connection_new ();
1320
1321         setting = nm_setting_connection_new ();
1322         uuid = nm_utils_uuid_generate ();
1323         g_object_set (G_OBJECT (setting),
1324                       NM_SETTING_CONNECTION_ID, "foobar",
1325                       NM_SETTING_CONNECTION_UUID, uuid,
1326                       NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
1327                       NM_SETTING_CONNECTION_TIMESTAMP, timestamp,
1328                       NULL);
1329         g_free (uuid);
1330         nm_connection_add_setting (connection, setting);
1331
1332         setting = nm_setting_wired_new ();
1333         g_object_set (G_OBJECT (setting),
1334                       NM_SETTING_WIRED_MTU, 1592,
1335                       NULL);
1336         nm_connection_add_setting (connection, setting);
1337
1338         setting = nm_setting_ip4_config_new ();
1339         g_object_set (G_OBJECT (setting),
1340                       NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
1341                       NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, "eyeofthetiger",
1342                       NULL);
1343         nm_connection_add_setting (connection, setting);
1344
1345         return connection;
1346 }
1347
1348 static GVariant *
1349 new_connection_dict (char **out_uuid,
1350                      const char **out_expected_id,
1351                      const char **out_expected_ip6_method)
1352 {
1353         GVariantBuilder conn_builder, setting_builder;
1354
1355         g_variant_builder_init (&conn_builder, NM_VARIANT_TYPE_CONNECTION);
1356
1357         *out_uuid = nm_utils_uuid_generate ();
1358         *out_expected_id = "My happy connection";
1359         *out_expected_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
1360
1361         /* Connection setting */
1362         g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
1363         g_variant_builder_add (&setting_builder, "{sv}",
1364                                NM_SETTING_NAME,
1365                                g_variant_new_string (NM_SETTING_CONNECTION_SETTING_NAME));
1366         g_variant_builder_add (&setting_builder, "{sv}",
1367                                NM_SETTING_CONNECTION_ID,
1368                                g_variant_new_string (*out_expected_id));
1369         g_variant_builder_add (&setting_builder, "{sv}",
1370                                NM_SETTING_CONNECTION_UUID,
1371                                g_variant_new_string (*out_uuid));
1372         g_variant_builder_add (&setting_builder, "{sv}",
1373                                NM_SETTING_CONNECTION_TYPE,
1374                                g_variant_new_string (NM_SETTING_WIRED_SETTING_NAME));
1375
1376         g_variant_builder_add (&conn_builder, "{sa{sv}}",
1377                                NM_SETTING_CONNECTION_SETTING_NAME,
1378                                &setting_builder);
1379
1380         /* Wired setting */
1381         g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
1382         g_variant_builder_add (&conn_builder, "{sa{sv}}",
1383                                NM_SETTING_WIRED_SETTING_NAME,
1384                                &setting_builder);
1385
1386         /* IP6 */
1387         g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
1388         g_variant_builder_add (&setting_builder, "{sv}",
1389                                NM_SETTING_IP_CONFIG_METHOD,
1390                                g_variant_new_string (*out_expected_ip6_method));
1391         g_variant_builder_add (&conn_builder, "{sa{sv}}",
1392                                NM_SETTING_IP6_CONFIG_SETTING_NAME,
1393                                &setting_builder);
1394
1395         return g_variant_builder_end (&conn_builder);
1396 }
1397
1398 static void
1399 test_connection_replace_settings (void)
1400 {
1401         NMConnection *connection;
1402         GVariant *new_settings;
1403         GError *error = NULL;
1404         gboolean success;
1405         NMSettingConnection *s_con;
1406         NMSettingIPConfig *s_ip6;
1407         char *uuid = NULL;
1408         const char *expected_id = NULL, *expected_method = NULL;
1409
1410         connection = new_test_connection ();
1411
1412         new_settings = new_connection_dict (&uuid, &expected_id, &expected_method);
1413         g_assert (new_settings);
1414
1415         /* Replace settings and test */
1416         success = nm_connection_replace_settings (connection, new_settings, &error);
1417         g_assert_no_error (error);
1418         g_assert (success);
1419
1420         s_con = nm_connection_get_setting_connection (connection);
1421         g_assert (s_con);
1422         g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
1423         g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
1424
1425         g_assert (nm_connection_get_setting_wired (connection));
1426         g_assert (!nm_connection_get_setting_ip4_config (connection));
1427
1428         s_ip6 = nm_connection_get_setting_ip6_config (connection);
1429         g_assert (s_ip6);
1430         g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, expected_method);
1431
1432         g_free (uuid);
1433         g_variant_unref (new_settings);
1434         g_object_unref (connection);
1435 }
1436
1437 static void
1438 test_connection_replace_settings_from_connection (void)
1439 {
1440         NMConnection *connection, *replacement;
1441         NMSettingConnection *s_con;
1442         NMSetting *setting;
1443         GBytes *ssid;
1444         char *uuid = NULL;
1445         const char *expected_id = "Awesome connection";
1446
1447         connection = new_test_connection ();
1448         g_assert (connection);
1449
1450         replacement = nm_simple_connection_new ();
1451         g_assert (replacement);
1452
1453         /* New connection setting */
1454         setting = nm_setting_connection_new ();
1455         g_assert (setting);
1456
1457         uuid = nm_utils_uuid_generate ();
1458         g_object_set (setting,
1459                       NM_SETTING_CONNECTION_ID, expected_id,
1460                       NM_SETTING_CONNECTION_UUID, uuid,
1461                       NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
1462                       NULL);
1463         nm_connection_add_setting (replacement, setting);
1464
1465         /* New wifi setting */
1466         setting = nm_setting_wireless_new ();
1467         g_assert (setting);
1468
1469         ssid = g_bytes_new ("1234567", 7);
1470         g_object_set (setting,
1471                       NM_SETTING_WIRELESS_SSID, ssid,
1472                       NM_SETTING_WIRELESS_MODE, "infrastructure",
1473                       NULL);
1474         g_bytes_unref (ssid);
1475         nm_connection_add_setting (replacement, setting);
1476
1477         /* Replace settings and test */
1478         nm_connection_replace_settings_from_connection (connection, replacement);
1479
1480         s_con = nm_connection_get_setting_connection (connection);
1481         g_assert (s_con);
1482         g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
1483         g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
1484
1485         g_assert (!nm_connection_get_setting_wired (connection));
1486         g_assert (!nm_connection_get_setting_ip6_config (connection));
1487         g_assert (nm_connection_get_setting_wireless (connection));
1488
1489         g_free (uuid);
1490         g_object_unref (replacement);
1491         g_object_unref (connection);
1492 }
1493
1494 static void
1495 test_connection_replace_settings_bad (void)
1496 {
1497         NMConnection *connection, *new_connection;
1498         GVariant *new_settings;
1499         GVariantBuilder builder, setting_builder;
1500         GError *error = NULL;
1501         gboolean success;
1502         NMSettingConnection *s_con;
1503
1504         new_connection = new_test_connection ();
1505         g_assert (nm_connection_verify (new_connection, NULL));
1506         s_con = nm_connection_get_setting_connection (new_connection);
1507         g_object_set (s_con,
1508                       NM_SETTING_CONNECTION_UUID, NULL,
1509                       NM_SETTING_CONNECTION_ID, "bad-connection",
1510                       NULL);
1511         g_assert (!nm_connection_verify (new_connection, NULL));
1512
1513         /* nm_connection_replace_settings_from_connection() should succeed */
1514         connection = new_test_connection ();
1515         nm_connection_replace_settings_from_connection (connection, new_connection);
1516         g_assert_cmpstr (nm_connection_get_id (connection), ==, "bad-connection");
1517         g_assert (!nm_connection_verify (connection, NULL));
1518         g_object_unref (connection);
1519
1520         /* nm_connection_replace_settings() should succeed */
1521         new_settings = nm_connection_to_dbus (new_connection, NM_CONNECTION_SERIALIZE_ALL);
1522         g_assert (new_settings != NULL);
1523
1524         connection = new_test_connection ();
1525         success = nm_connection_replace_settings (connection, new_settings, &error);
1526         g_assert_no_error (error);
1527         g_assert (success);
1528
1529         g_assert_cmpstr (nm_connection_get_id (connection), ==, "bad-connection");
1530         g_assert (!nm_connection_verify (connection, NULL));
1531         g_object_unref (connection);
1532         g_variant_unref (new_settings);
1533
1534         /* But given an invalid dict, it should fail */
1535         g_variant_builder_init (&builder, NM_VARIANT_TYPE_CONNECTION);
1536         g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
1537         g_variant_builder_add (&builder, "{sa{sv}}",
1538                                "ip-over-avian-carrier",
1539                                &setting_builder);
1540         new_settings = g_variant_builder_end (&builder);
1541
1542         connection = new_test_connection ();
1543         success = nm_connection_replace_settings (connection, new_settings, &error);
1544         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING);
1545         g_clear_error (&error);
1546         g_assert (!success);
1547
1548         g_assert (nm_connection_verify (connection, NULL));
1549         g_object_unref (connection);
1550
1551         g_variant_unref (new_settings);
1552         g_object_unref (new_connection);
1553 }
1554
1555 static void
1556 test_connection_new_from_dbus (void)
1557 {
1558         NMConnection *connection;
1559         GVariant *new_settings;
1560         GError *error = NULL;
1561         NMSettingConnection *s_con;
1562         NMSettingIPConfig *s_ip6;
1563         char *uuid = NULL;
1564         const char *expected_id = NULL, *expected_method = NULL;
1565
1566         new_settings = new_connection_dict (&uuid, &expected_id, &expected_method);
1567         g_assert (new_settings);
1568
1569         /* Replace settings and test */
1570         connection = _connection_new_from_dbus (new_settings, &error);
1571         g_assert_no_error (error);
1572         g_assert (connection);
1573
1574         s_con = nm_connection_get_setting_connection (connection);
1575         g_assert (s_con);
1576         g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
1577         g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
1578
1579         g_assert (nm_connection_get_setting_wired (connection));
1580         g_assert (nm_connection_get_setting_ip4_config (connection));
1581
1582         s_ip6 = nm_connection_get_setting_ip6_config (connection);
1583         g_assert (s_ip6);
1584         g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, expected_method);
1585
1586         g_free (uuid);
1587         g_variant_unref (new_settings);
1588         g_object_unref (connection);
1589 }
1590
1591 static void
1592 check_permission (NMSettingConnection *s_con,
1593                   guint32 idx,
1594                   const char *expected_uname)
1595 {
1596         gboolean success;
1597         const char *ptype = NULL, *pitem = NULL, *detail = NULL;
1598
1599         success = nm_setting_connection_get_permission (s_con, 0, &ptype, &pitem, &detail);
1600         g_assert (success);
1601
1602         g_assert_cmpstr (ptype, ==, "user");
1603
1604         g_assert (pitem);
1605         g_assert_cmpstr (pitem, ==, expected_uname);
1606
1607         g_assert (!detail);
1608 }
1609
1610 #define TEST_UNAME "asdfasfasdf"
1611
1612 static void
1613 test_setting_connection_permissions_helpers (void)
1614 {
1615         NMSettingConnection *s_con;
1616         gboolean success;
1617         char buf[9] = { 0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00 };
1618         char **perms;
1619         const char *expected_perm = "user:" TEST_UNAME ":";
1620
1621         s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
1622
1623         /* Ensure a bad [type] is rejected */
1624         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strcmp (ptype, \"user\") == 0*");
1625         success = nm_setting_connection_add_permission (s_con, "foobar", "blah", NULL);
1626         g_test_assert_expected_messages ();
1627         g_assert (!success);
1628
1629         /* Ensure a bad [type] is rejected */
1630         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*ptype*");
1631         success = nm_setting_connection_add_permission (s_con, NULL, "blah", NULL);
1632         g_test_assert_expected_messages ();
1633         g_assert (!success);
1634
1635         /* Ensure a bad [item] is rejected */
1636         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*uname*");
1637         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
1638         success = nm_setting_connection_add_permission (s_con, "user", NULL, NULL);
1639         g_test_assert_expected_messages ();
1640         g_assert (!success);
1641
1642         /* Ensure a bad [item] is rejected */
1643         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*uname[0] != '\\0'*");
1644         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
1645         success = nm_setting_connection_add_permission (s_con, "user", "", NULL);
1646         g_test_assert_expected_messages ();
1647         g_assert (!success);
1648
1649         /* Ensure an [item] with ':' is rejected */
1650         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strchr (uname, ':')*");
1651         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
1652         success = nm_setting_connection_add_permission (s_con, "user", "ad:asdf", NULL);
1653         g_test_assert_expected_messages ();
1654         g_assert (!success);
1655
1656         /* Ensure a non-UTF-8 [item] is rejected */
1657         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*g_utf8_validate (uname, -1, NULL)*");
1658         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
1659         success = nm_setting_connection_add_permission (s_con, "user", buf, NULL);
1660         g_test_assert_expected_messages ();
1661         g_assert (!success);
1662
1663         /* Ensure a non-NULL [detail] is rejected */
1664         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*detail == NULL*");
1665         success = nm_setting_connection_add_permission (s_con, "user", "dafasdf", "asdf");
1666         g_test_assert_expected_messages ();
1667         g_assert (!success);
1668
1669         /* Ensure a valid call results in success */
1670         success = nm_setting_connection_add_permission (s_con, "user", TEST_UNAME, NULL);
1671         g_assert (success);
1672
1673         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 1);
1674
1675         check_permission (s_con, 0, TEST_UNAME);
1676
1677         /* Check the actual GObject property just to be paranoid */
1678         g_object_get (G_OBJECT (s_con), NM_SETTING_CONNECTION_PERMISSIONS, &perms, NULL);
1679         g_assert (perms);
1680         g_assert_cmpint (g_strv_length (perms), ==, 1);
1681         g_assert_cmpstr (perms[0], ==, expected_perm);
1682         g_strfreev (perms);
1683
1684         /* Now remove that permission and ensure we have 0 permissions */
1685         nm_setting_connection_remove_permission (s_con, 0);
1686         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1687
1688         g_object_unref (s_con);
1689 }
1690
1691 static void
1692 add_permission_property (NMSettingConnection *s_con,
1693                          const char *ptype,
1694                          const char *pitem,
1695                          int pitem_len,
1696                          const char *detail)
1697 {
1698         GString *str;
1699         char *perms[2];
1700
1701         str = g_string_sized_new (50);
1702         if (ptype)
1703                 g_string_append (str, ptype);
1704         g_string_append_c (str, ':');
1705
1706         if (pitem) {
1707                 if (pitem_len >= 0)
1708                         g_string_append_len (str, pitem, pitem_len);
1709                 else
1710                         g_string_append (str, pitem);
1711         }
1712
1713         g_string_append_c (str, ':');
1714
1715         if (detail)
1716                 g_string_append (str, detail);
1717
1718         perms[0] = str->str;
1719         perms[1] = NULL;
1720         g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_PERMISSIONS, perms, NULL);
1721
1722         g_string_free (str, TRUE);
1723 }
1724
1725 static void
1726 test_setting_connection_permissions_property (void)
1727 {
1728         NMSettingConnection *s_con;
1729         gboolean success;
1730         char buf[9] = { 0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00 };
1731
1732         s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
1733
1734         /* Ensure a bad [type] is rejected */
1735         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0*");
1736         add_permission_property (s_con, "foobar", "blah", -1, NULL);
1737         g_test_assert_expected_messages ();
1738         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1739
1740         /* Ensure a bad [type] is rejected */
1741         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0*");
1742         add_permission_property (s_con, NULL, "blah", -1, NULL);
1743         g_test_assert_expected_messages ();
1744         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1745
1746         /* Ensure a bad [item] is rejected */
1747         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*last_colon > str*");
1748         add_permission_property (s_con, "user", NULL, -1, NULL);
1749         g_test_assert_expected_messages ();
1750         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1751
1752         /* Ensure a bad [item] is rejected */
1753         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*last_colon > str*");
1754         add_permission_property (s_con, "user", "", -1, NULL);
1755         g_test_assert_expected_messages ();
1756         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1757
1758         /* Ensure an [item] with ':' in the middle is rejected */
1759         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*str[i] != ':'*");
1760         add_permission_property (s_con, "user", "ad:asdf", -1, NULL);
1761         g_test_assert_expected_messages ();
1762         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1763
1764         /* Ensure an [item] with ':' at the end is rejected */
1765         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*str[i] != ':'*");
1766         add_permission_property (s_con, "user", "adasdfaf:", -1, NULL);
1767         g_test_assert_expected_messages ();
1768         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1769
1770         /* Ensure a non-UTF-8 [item] is rejected */
1771         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*g_utf8_validate (str, -1, NULL)*");
1772         add_permission_property (s_con, "user", buf, (int) sizeof (buf), NULL);
1773         g_test_assert_expected_messages ();
1774         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1775
1776         /* Ensure a non-NULL [detail] is rejected */
1777         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*(last_colon + 1) == '\\0'*");
1778         add_permission_property (s_con, "user", "dafasdf", -1, "asdf");
1779         g_test_assert_expected_messages ();
1780         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1781
1782         /* Ensure a valid call results in success */
1783         success = nm_setting_connection_add_permission (s_con, "user", TEST_UNAME, NULL);
1784         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 1);
1785
1786         check_permission (s_con, 0, TEST_UNAME);
1787
1788         /* Now remove that permission and ensure we have 0 permissions */
1789         nm_setting_connection_remove_permission (s_con, 0);
1790         g_assert_cmpint (nm_setting_connection_get_num_permissions (s_con), ==, 0);
1791
1792         g_object_unref (s_con);
1793 }
1794
1795 static void
1796 test_connection_compare_same (void)
1797 {
1798         NMConnection *a, *b;
1799
1800         a = new_test_connection ();
1801         b = nm_simple_connection_new_clone (a);
1802         g_assert (nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
1803         g_object_unref (a);
1804         g_object_unref (b);
1805 }
1806
1807 static void
1808 test_connection_compare_key_only_in_a (void)
1809 {
1810         NMConnection *a, *b;
1811         NMSettingConnection *s_con;
1812
1813         a = new_test_connection ();
1814         b = nm_simple_connection_new_clone (a);
1815         s_con = (NMSettingConnection *) nm_connection_get_setting (b, NM_TYPE_SETTING_CONNECTION);
1816         g_assert (s_con);
1817         g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL);
1818
1819         g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
1820         g_object_unref (a);
1821         g_object_unref (b);
1822 }
1823
1824 static void
1825 test_connection_compare_setting_only_in_a (void)
1826 {
1827         NMConnection *a, *b;
1828
1829         a = new_test_connection ();
1830         b = nm_simple_connection_new_clone (a);
1831         nm_connection_remove_setting (b, NM_TYPE_SETTING_IP4_CONFIG);
1832         g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
1833         g_object_unref (a);
1834         g_object_unref (b);
1835 }
1836
1837 static void
1838 test_connection_compare_key_only_in_b (void)
1839 {
1840         NMConnection *a, *b;
1841         NMSettingConnection *s_con;
1842
1843         a = new_test_connection ();
1844         b = nm_simple_connection_new_clone (a);
1845         s_con = (NMSettingConnection *) nm_connection_get_setting (b, NM_TYPE_SETTING_CONNECTION);
1846         g_assert (s_con);
1847         g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL);
1848
1849         g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
1850         g_object_unref (a);
1851         g_object_unref (b);
1852 }
1853
1854 static void
1855 test_connection_compare_setting_only_in_b (void)
1856 {
1857         NMConnection *a, *b;
1858
1859         a = new_test_connection ();
1860         b = nm_simple_connection_new_clone (a);
1861         nm_connection_remove_setting (a, NM_TYPE_SETTING_IP4_CONFIG);
1862         g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
1863         g_object_unref (a);
1864         g_object_unref (b);
1865 }
1866
1867 typedef struct {
1868         const char *key_name;
1869         guint32 result;
1870 } DiffKey;
1871
1872 typedef struct {
1873         const char *name;
1874         DiffKey keys[30];
1875 } DiffSetting;
1876
1877 #define ARRAY_LEN(a)  (sizeof (a) / sizeof (a[0]))
1878
1879 static void
1880 ensure_diffs (GHashTable *diffs, const DiffSetting *check, gsize n_check)
1881 {
1882         guint i;
1883
1884         g_assert (g_hash_table_size (diffs) == n_check);
1885
1886         /* Loop through the settings */
1887         for (i = 0; i < n_check; i++) {
1888                 GHashTable *setting_hash;
1889                 guint z = 0;
1890
1891                 setting_hash = g_hash_table_lookup (diffs, check[i].name);
1892                 g_assert (setting_hash);
1893
1894                 /* Get the number of keys to check */
1895                 while (check[i].keys[z].key_name)
1896                         z++;
1897                 g_assert (g_hash_table_size (setting_hash) == z);
1898
1899                 /* Now compare the actual keys */
1900                 for (z = 0; check[i].keys[z].key_name; z++) {
1901                         NMSettingDiffResult result;
1902
1903                         result = GPOINTER_TO_UINT (g_hash_table_lookup (setting_hash, check[i].keys[z].key_name));
1904                         g_assert (result == check[i].keys[z].result);
1905                 }
1906         }
1907 }
1908
1909 static void
1910 test_connection_diff_a_only (void)
1911 {
1912         NMConnection *connection;
1913         GHashTable *out_diffs = NULL;
1914         gboolean same;
1915         const DiffSetting settings[] = {
1916                 { NM_SETTING_CONNECTION_SETTING_NAME, {
1917                         { NM_SETTING_CONNECTION_ID,                   NM_SETTING_DIFF_RESULT_IN_A },
1918                         { NM_SETTING_CONNECTION_UUID,                 NM_SETTING_DIFF_RESULT_IN_A },
1919                         { NM_SETTING_CONNECTION_INTERFACE_NAME,       NM_SETTING_DIFF_RESULT_IN_A },
1920                         { NM_SETTING_CONNECTION_TYPE,                 NM_SETTING_DIFF_RESULT_IN_A },
1921                         { NM_SETTING_CONNECTION_TIMESTAMP,            NM_SETTING_DIFF_RESULT_IN_A },
1922                         { NM_SETTING_CONNECTION_AUTOCONNECT,          NM_SETTING_DIFF_RESULT_IN_A },
1923                         { NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A },
1924                         { NM_SETTING_CONNECTION_READ_ONLY,            NM_SETTING_DIFF_RESULT_IN_A },
1925                         { NM_SETTING_CONNECTION_PERMISSIONS,          NM_SETTING_DIFF_RESULT_IN_A },
1926                         { NM_SETTING_CONNECTION_ZONE,                 NM_SETTING_DIFF_RESULT_IN_A },
1927                         { NM_SETTING_CONNECTION_MASTER,               NM_SETTING_DIFF_RESULT_IN_A },
1928                         { NM_SETTING_CONNECTION_SLAVE_TYPE,           NM_SETTING_DIFF_RESULT_IN_A },
1929                         { NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES,   NM_SETTING_DIFF_RESULT_IN_A },
1930                         { NM_SETTING_CONNECTION_SECONDARIES,          NM_SETTING_DIFF_RESULT_IN_A },
1931                         { NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A },
1932                         { NM_SETTING_CONNECTION_METERED,              NM_SETTING_DIFF_RESULT_IN_A },
1933                         { NM_SETTING_CONNECTION_LLDP,                 NM_SETTING_DIFF_RESULT_IN_A },
1934                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }
1935                 } },
1936                 { NM_SETTING_WIRED_SETTING_NAME, {
1937                         { NM_SETTING_WIRED_PORT,                  NM_SETTING_DIFF_RESULT_IN_A },
1938                         { NM_SETTING_WIRED_SPEED,                 NM_SETTING_DIFF_RESULT_IN_A },
1939                         { NM_SETTING_WIRED_DUPLEX,                NM_SETTING_DIFF_RESULT_IN_A },
1940                         { NM_SETTING_WIRED_AUTO_NEGOTIATE,        NM_SETTING_DIFF_RESULT_IN_A },
1941                         { NM_SETTING_WIRED_MAC_ADDRESS,           NM_SETTING_DIFF_RESULT_IN_A },
1942                         { NM_SETTING_WIRED_CLONED_MAC_ADDRESS,    NM_SETTING_DIFF_RESULT_IN_A },
1943                         { NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, NM_SETTING_DIFF_RESULT_IN_A },
1944                         { NM_SETTING_WIRED_MTU,                   NM_SETTING_DIFF_RESULT_IN_A },
1945                         { NM_SETTING_WIRED_S390_SUBCHANNELS,      NM_SETTING_DIFF_RESULT_IN_A },
1946                         { NM_SETTING_WIRED_S390_NETTYPE,          NM_SETTING_DIFF_RESULT_IN_A },
1947                         { NM_SETTING_WIRED_S390_OPTIONS,          NM_SETTING_DIFF_RESULT_IN_A },
1948                         { NM_SETTING_WIRED_WAKE_ON_LAN,           NM_SETTING_DIFF_RESULT_IN_A },
1949                         { NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD,  NM_SETTING_DIFF_RESULT_IN_A },
1950                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
1951                 } },
1952                 { NM_SETTING_IP4_CONFIG_SETTING_NAME, {
1953                         { NM_SETTING_IP_CONFIG_METHOD,             NM_SETTING_DIFF_RESULT_IN_A },
1954                         { NM_SETTING_IP_CONFIG_DNS,                NM_SETTING_DIFF_RESULT_IN_A },
1955                         { NM_SETTING_IP_CONFIG_DNS_SEARCH,         NM_SETTING_DIFF_RESULT_IN_A },
1956                         { NM_SETTING_IP_CONFIG_DNS_OPTIONS,        NM_SETTING_DIFF_RESULT_IN_A },
1957                         { NM_SETTING_IP_CONFIG_ADDRESSES,          NM_SETTING_DIFF_RESULT_IN_A },
1958                         { NM_SETTING_IP_CONFIG_GATEWAY,            NM_SETTING_DIFF_RESULT_IN_A },
1959                         { NM_SETTING_IP_CONFIG_ROUTES,             NM_SETTING_DIFF_RESULT_IN_A },
1960                         { NM_SETTING_IP_CONFIG_ROUTE_METRIC,       NM_SETTING_DIFF_RESULT_IN_A },
1961                         { NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
1962                         { NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS,    NM_SETTING_DIFF_RESULT_IN_A },
1963                         { NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID,    NM_SETTING_DIFF_RESULT_IN_A },
1964                         { NM_SETTING_IP_CONFIG_DHCP_TIMEOUT,       NM_SETTING_DIFF_RESULT_IN_A },
1965                         { NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A },
1966                         { NM_SETTING_IP_CONFIG_DHCP_HOSTNAME,      NM_SETTING_DIFF_RESULT_IN_A },
1967                         { NM_SETTING_IP4_CONFIG_DHCP_FQDN,         NM_SETTING_DIFF_RESULT_IN_A },
1968                         { NM_SETTING_IP_CONFIG_NEVER_DEFAULT,      NM_SETTING_DIFF_RESULT_IN_A },
1969                         { NM_SETTING_IP_CONFIG_MAY_FAIL,           NM_SETTING_DIFF_RESULT_IN_A },
1970                         { NM_SETTING_IP_CONFIG_DAD_TIMEOUT,        NM_SETTING_DIFF_RESULT_IN_A },
1971                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
1972                 } },
1973         };
1974
1975         connection = new_test_connection ();
1976
1977         same = nm_connection_diff (connection, NULL, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
1978         g_assert (same == FALSE);
1979         g_assert (out_diffs != NULL);
1980         g_assert (g_hash_table_size (out_diffs) > 0);
1981
1982         ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
1983
1984         g_hash_table_destroy (out_diffs);
1985         g_object_unref (connection);
1986 }
1987
1988 static void
1989 test_connection_diff_same (void)
1990 {
1991         NMConnection *a, *b;
1992         GHashTable *out_diffs = NULL;
1993         gboolean same;
1994
1995         a = new_test_connection ();
1996         b = nm_simple_connection_new_clone (a);
1997
1998         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
1999         g_assert (same == TRUE);
2000         g_assert (out_diffs == NULL);
2001         g_object_unref (a);
2002         g_object_unref (b);
2003 }
2004
2005 static void
2006 test_connection_diff_different (void)
2007 {
2008         NMConnection *a, *b;
2009         GHashTable *out_diffs = NULL;
2010         NMSettingIPConfig *s_ip4;
2011         gboolean same;
2012         const DiffSetting settings[] = {
2013                 { NM_SETTING_IP4_CONFIG_SETTING_NAME, {
2014                         { NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B },
2015                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
2016                 } },
2017         };
2018
2019         a = new_test_connection ();
2020         b = nm_simple_connection_new_clone (a);
2021         s_ip4 = nm_connection_get_setting_ip4_config (a);
2022         g_assert (s_ip4);
2023         g_object_set (G_OBJECT (s_ip4),
2024                       NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
2025                       NULL);
2026
2027         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
2028         g_assert (same == FALSE);
2029         g_assert (out_diffs != NULL);
2030         g_assert (g_hash_table_size (out_diffs) > 0);
2031
2032         ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
2033
2034         g_hash_table_destroy (out_diffs);
2035         g_object_unref (a);
2036         g_object_unref (b);
2037 }
2038
2039 static void
2040 test_connection_diff_no_secrets (void)
2041 {
2042         NMConnection *a, *b;
2043         GHashTable *out_diffs = NULL;
2044         NMSetting *s_pppoe;
2045         gboolean same;
2046         const DiffSetting settings[] = {
2047                 { NM_SETTING_PPPOE_SETTING_NAME, {
2048                         { NM_SETTING_PPPOE_PASSWORD, NM_SETTING_DIFF_RESULT_IN_B },
2049                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
2050                 } },
2051         };
2052
2053         a = new_test_connection ();
2054         s_pppoe = nm_setting_pppoe_new ();
2055         g_object_set (G_OBJECT (s_pppoe),
2056                       NM_SETTING_PPPOE_USERNAME, "thomas",
2057                       NULL);
2058         nm_connection_add_setting (a, s_pppoe);
2059
2060         b = nm_simple_connection_new_clone (a);
2061
2062         /* Add a secret to B */
2063         s_pppoe = NM_SETTING (nm_connection_get_setting_pppoe (b));
2064         g_assert (s_pppoe);
2065         g_object_set (G_OBJECT (s_pppoe),
2066                       NM_SETTING_PPPOE_PASSWORD, "secretpassword",
2067                       NULL);
2068
2069         /* Make sure the diff returns no results as secrets are ignored */
2070         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &out_diffs);
2071         g_assert (same == TRUE);
2072         g_assert (out_diffs == NULL);
2073
2074         /* Now make sure the diff returns results if secrets are not ignored */
2075         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
2076         g_assert (same == FALSE);
2077         g_assert (out_diffs != NULL);
2078         g_assert (g_hash_table_size (out_diffs) > 0);
2079
2080         ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
2081
2082         g_hash_table_destroy (out_diffs);
2083         g_object_unref (a);
2084         g_object_unref (b);
2085 }
2086
2087 static void
2088 test_connection_diff_inferrable (void)
2089 {
2090         NMConnection *a, *b;
2091         GHashTable *out_diffs = NULL;
2092         gboolean same;
2093         NMSettingConnection *s_con;
2094         NMSettingWired *s_wired;
2095         NMSettingIPConfig *s_ip4;
2096         char *uuid;
2097         const DiffSetting settings[] = {
2098                 { NM_SETTING_CONNECTION_SETTING_NAME, {
2099                         { NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A },
2100                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
2101                 } },
2102         };
2103
2104         a = new_test_connection ();
2105         b = nm_simple_connection_new_clone (a);
2106
2107         /* Change the UUID, wired MTU, and set ignore-auto-dns */
2108         s_con = nm_connection_get_setting_connection (a);
2109         g_assert (s_con);
2110         uuid = nm_utils_uuid_generate ();
2111         g_object_set (G_OBJECT (s_con),
2112                       NM_SETTING_CONNECTION_UUID, uuid,
2113                       NM_SETTING_CONNECTION_ID, "really neat connection",
2114                       NULL);
2115         g_free (uuid);
2116
2117         s_wired = nm_connection_get_setting_wired (a);
2118         g_assert (s_wired);
2119         g_object_set (G_OBJECT (s_wired), NM_SETTING_WIRED_MTU, 300, NULL);
2120
2121         s_ip4 = nm_connection_get_setting_ip4_config (a);
2122         g_assert (s_ip4);
2123         g_object_set (G_OBJECT (s_ip4), NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, TRUE, NULL);
2124
2125         /* Make sure the diff returns no results as secrets are ignored */
2126         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs);
2127         g_assert (same == TRUE);
2128         g_assert (out_diffs == NULL);
2129
2130         /* And change a INFERRABLE property to ensure that it shows up in the diff results */
2131         g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, "usb0", NULL);
2132
2133         /* Make sure the diff returns no results as secrets are ignored */
2134         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs);
2135         g_assert (same == FALSE);
2136         g_assert (out_diffs != NULL);
2137         g_assert (g_hash_table_size (out_diffs) > 0);
2138
2139         ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
2140
2141         g_hash_table_destroy (out_diffs);
2142         g_object_unref (a);
2143         g_object_unref (b);
2144 }
2145
2146 static void
2147 add_generic_settings (NMConnection *connection, const char *ctype)
2148 {
2149         NMSetting *setting;
2150         char *uuid;
2151
2152         uuid = nm_utils_uuid_generate ();
2153
2154         setting = nm_setting_connection_new ();
2155         g_object_set (setting,
2156                       NM_SETTING_CONNECTION_ID, "asdfasdfadf",
2157                       NM_SETTING_CONNECTION_TYPE, ctype,
2158                       NM_SETTING_CONNECTION_UUID, uuid,
2159                       NULL);
2160         nm_connection_add_setting (connection, setting);
2161
2162         g_free (uuid);
2163
2164         setting = nm_setting_ip4_config_new ();
2165         g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
2166         nm_connection_add_setting (connection, setting);
2167
2168         setting = nm_setting_ip6_config_new ();
2169         g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
2170         nm_connection_add_setting (connection, setting);
2171 }
2172
2173 static void
2174 test_connection_good_base_types (void)
2175 {
2176         NMConnection *connection;
2177         NMSetting *setting;
2178         gboolean success;
2179         GError *error = NULL;
2180         GBytes *ssid;
2181         const char *bdaddr = "11:22:33:44:55:66";
2182
2183         /* Try a basic wired connection */
2184         connection = nm_simple_connection_new ();
2185         add_generic_settings (connection, NM_SETTING_WIRED_SETTING_NAME);
2186         setting = nm_setting_wired_new ();
2187         nm_connection_add_setting (connection, setting);
2188
2189         success = nm_connection_verify (connection, &error);
2190         g_assert_no_error (error);
2191         g_assert (success);
2192         g_object_unref (connection);
2193
2194         /* Try a wired PPPoE connection */
2195         connection = nm_simple_connection_new ();
2196         add_generic_settings (connection, NM_SETTING_PPPOE_SETTING_NAME);
2197         setting = nm_setting_pppoe_new ();
2198         g_object_set (setting, NM_SETTING_PPPOE_USERNAME, "bob smith", NULL);
2199         nm_connection_add_setting (connection, setting);
2200
2201         success = nm_connection_verify (connection, &error);
2202         g_assert_no_error (error);
2203         g_assert (success);
2204         g_object_unref (connection);
2205
2206         /* Wifi connection */
2207         connection = nm_simple_connection_new ();
2208         add_generic_settings (connection, NM_SETTING_WIRELESS_SETTING_NAME);
2209
2210         setting = nm_setting_wireless_new ();
2211         ssid = g_bytes_new ("1234567", 7);
2212         g_object_set (setting,
2213                       NM_SETTING_WIRELESS_SSID, ssid,
2214                       NM_SETTING_WIRELESS_MODE, "infrastructure",
2215                       NULL);
2216         g_bytes_unref (ssid);
2217         nm_connection_add_setting (connection, setting);
2218
2219         success = nm_connection_verify (connection, &error);
2220         g_assert_no_error (error);
2221         g_assert (success);
2222         g_object_unref (connection);
2223
2224         /* Bluetooth connection */
2225         connection = nm_simple_connection_new ();
2226         add_generic_settings (connection, NM_SETTING_BLUETOOTH_SETTING_NAME);
2227
2228         setting = nm_setting_bluetooth_new ();
2229         g_object_set (setting,
2230                       NM_SETTING_BLUETOOTH_BDADDR, bdaddr,
2231                       NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
2232                       NULL);
2233         nm_connection_add_setting (connection, setting);
2234
2235         success = nm_connection_verify (connection, &error);
2236         g_assert_no_error (error);
2237         g_assert (success);
2238         g_object_unref (connection);
2239
2240         /* WiMAX connection */
2241         connection = nm_simple_connection_new ();
2242         add_generic_settings (connection, NM_SETTING_WIMAX_SETTING_NAME);
2243         setting = nm_setting_wimax_new ();
2244         g_object_set (setting, NM_SETTING_WIMAX_NETWORK_NAME, "CLEAR", NULL);
2245         nm_connection_add_setting (connection, setting);
2246
2247         success = nm_connection_verify (connection, &error);
2248         g_assert_no_error (error);
2249         g_assert (success);
2250         g_object_unref (connection);
2251
2252         /* GSM connection */
2253         connection = nm_simple_connection_new ();
2254         add_generic_settings (connection, NM_SETTING_GSM_SETTING_NAME);
2255
2256         setting = nm_setting_gsm_new ();
2257         g_object_set (setting,
2258                       NM_SETTING_GSM_NUMBER, "*99#",
2259                       NM_SETTING_GSM_APN, "metered.billing.sucks",
2260                       NULL);
2261         nm_connection_add_setting (connection, setting);
2262
2263         /* CDMA connection */
2264         connection = nm_simple_connection_new ();
2265         add_generic_settings (connection, NM_SETTING_CDMA_SETTING_NAME);
2266
2267         setting = nm_setting_cdma_new ();
2268         g_object_set (setting,
2269                       NM_SETTING_CDMA_NUMBER, "#777",
2270                       NM_SETTING_CDMA_USERNAME, "foobar@vzw.com",
2271                       NULL);
2272         nm_connection_add_setting (connection, setting);
2273
2274         success = nm_connection_verify (connection, &error);
2275         g_assert_no_error (error);
2276         g_assert (success);
2277         g_object_unref (connection);
2278 }
2279
2280 static void
2281 test_connection_bad_base_types (void)
2282 {
2283         NMConnection *connection;
2284         NMSetting *setting;
2285         gboolean success;
2286         GError *error = NULL;
2287
2288         /* Test various non-base connection types to make sure they are rejected;
2289          * using a fake 'wired' connection so the rest of it verifies
2290          */
2291
2292         /* Connection setting */
2293         connection = nm_simple_connection_new ();
2294         add_generic_settings (connection, NM_SETTING_CONNECTION_SETTING_NAME);
2295         setting = nm_setting_wired_new ();
2296         nm_connection_add_setting (connection, setting);
2297
2298         success = nm_connection_verify (connection, &error);
2299         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
2300         g_assert (g_str_has_prefix (error->message, "connection.type: "));
2301         g_assert (success == FALSE);
2302         g_object_unref (connection);
2303         g_clear_error (&error);
2304
2305         /* PPP setting */
2306         connection = nm_simple_connection_new ();
2307         add_generic_settings (connection, NM_SETTING_PPP_SETTING_NAME);
2308         setting = nm_setting_wired_new ();
2309         nm_connection_add_setting (connection, setting);
2310         setting = nm_setting_ppp_new ();
2311         nm_connection_add_setting (connection, setting);
2312
2313         success = nm_connection_verify (connection, &error);
2314         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
2315         g_assert (g_str_has_prefix (error->message, "connection.type: "));
2316         g_assert (success == FALSE);
2317         g_object_unref (connection);
2318         g_clear_error (&error);
2319
2320         /* Serial setting */
2321         connection = nm_simple_connection_new ();
2322         add_generic_settings (connection, NM_SETTING_SERIAL_SETTING_NAME);
2323         setting = nm_setting_wired_new ();
2324         nm_connection_add_setting (connection, setting);
2325         setting = nm_setting_serial_new ();
2326         nm_connection_add_setting (connection, setting);
2327
2328         success = nm_connection_verify (connection, &error);
2329         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
2330         g_assert (g_str_has_prefix (error->message, "connection.type: "));
2331         g_assert (success == FALSE);
2332         g_object_unref (connection);
2333         g_clear_error (&error);
2334
2335         /* IP4 setting */
2336         connection = nm_simple_connection_new ();
2337         add_generic_settings (connection, NM_SETTING_IP4_CONFIG_SETTING_NAME);
2338         setting = nm_setting_wired_new ();
2339         nm_connection_add_setting (connection, setting);
2340
2341         success = nm_connection_verify (connection, &error);
2342         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
2343         g_assert (g_str_has_prefix (error->message, "connection.type: "));
2344         g_assert (success == FALSE);
2345         g_object_unref (connection);
2346         g_clear_error (&error);
2347
2348         /* IP6 setting */
2349         connection = nm_simple_connection_new ();
2350         add_generic_settings (connection, NM_SETTING_IP6_CONFIG_SETTING_NAME);
2351         setting = nm_setting_wired_new ();
2352         nm_connection_add_setting (connection, setting);
2353
2354         success = nm_connection_verify (connection, &error);
2355         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
2356         g_assert (g_str_has_prefix (error->message, "connection.type: "));
2357         g_assert (success == FALSE);
2358         g_object_unref (connection);
2359         g_clear_error (&error);
2360 }
2361
2362 static void
2363 test_setting_compare_id (void)
2364 {
2365         gs_unref_object NMSetting *old = NULL, *new = NULL;
2366         gboolean success;
2367
2368         old = nm_setting_connection_new ();
2369         g_object_set (old,
2370                       NM_SETTING_CONNECTION_ID, "really awesome cool connection",
2371                       NM_SETTING_CONNECTION_UUID, "fbbd59d5-acab-4e30-8f86-258d272617e7",
2372                       NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
2373                       NULL);
2374
2375         new = nm_setting_duplicate (old);
2376         g_object_set (new, NM_SETTING_CONNECTION_ID, "some different connection id", NULL);
2377
2378         /* First make sure they are different */
2379         success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
2380         g_assert (success == FALSE);
2381
2382         success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_IGNORE_ID);
2383         g_assert (success);
2384 }
2385
2386 static void
2387 test_setting_compare_timestamp (void)
2388 {
2389         gs_unref_object NMSetting *old = NULL, *new = NULL;
2390         gboolean success;
2391
2392         old = nm_setting_connection_new ();
2393         g_object_set (old,
2394                       NM_SETTING_CONNECTION_ID, "ignore timestamp connection",
2395                       NM_SETTING_CONNECTION_UUID, "b047a198-0e0a-4f0e-a653-eea09bb35e40",
2396                       NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
2397                       NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 1234567890,
2398                       NULL);
2399
2400         new = nm_setting_duplicate (old);
2401         g_object_set (new, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 1416316539, NULL);
2402
2403         /* First make sure they are different */
2404         success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
2405         g_assert (success == FALSE);
2406
2407         success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP);
2408         g_assert (success);
2409 }
2410
2411 typedef struct {
2412         NMSettingSecretFlags secret_flags;
2413         NMSettingCompareFlags comp_flags;
2414         gboolean remove_secret;
2415 } TestDataCompareSecrets;
2416
2417 static TestDataCompareSecrets *
2418 test_data_compare_secrets_new (NMSettingSecretFlags secret_flags,
2419                                NMSettingCompareFlags comp_flags,
2420                                gboolean remove_secret)
2421 {
2422         TestDataCompareSecrets *data = g_new0 (TestDataCompareSecrets, 1);
2423
2424         data->secret_flags = secret_flags;
2425         data->comp_flags = comp_flags;
2426         data->remove_secret = remove_secret;
2427         return data;
2428 }
2429
2430 static void
2431 test_setting_compare_secrets (gconstpointer test_data)
2432 {
2433         const TestDataCompareSecrets *data = test_data;
2434         gs_unref_object NMSetting *old = NULL, *new = NULL;
2435         gboolean success;
2436
2437         /* Make sure that a connection with transient/unsaved secrets compares
2438          * successfully to the same connection without those secrets.
2439          */
2440
2441         old = nm_setting_wireless_security_new ();
2442         g_object_set (old,
2443                       NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
2444                       NM_SETTING_WIRELESS_SECURITY_PSK, "really cool psk",
2445                       NULL);
2446         nm_setting_set_secret_flags (old, NM_SETTING_WIRELESS_SECURITY_PSK, data->secret_flags, NULL);
2447
2448         /* Clear the PSK from the duplicated setting */
2449         new = nm_setting_duplicate (old);
2450         if (data->remove_secret) {
2451                 g_object_set (new, NM_SETTING_WIRELESS_SECURITY_PSK, NULL, NULL);
2452
2453                 success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
2454                 g_assert (success == FALSE);
2455         }
2456
2457         success = nm_setting_compare (old, new, data->comp_flags);
2458         g_assert (success);
2459 }
2460
2461 static void
2462 test_setting_compare_vpn_secrets (gconstpointer test_data)
2463 {
2464         const TestDataCompareSecrets *data = test_data;
2465         gs_unref_object NMSetting *old = NULL, *new = NULL;
2466         gboolean success;
2467
2468         /* Make sure that a connection with transient/unsaved secrets compares
2469          * successfully to the same connection without those secrets.
2470          */
2471
2472         old = nm_setting_vpn_new ();
2473         nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "foobarbaz", "really secret password");
2474         nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "asdfasdfasdf", "really adfasdfasdfasdf");
2475         nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "0123456778", "abcdefghijklmnpqrstuvqxyz");
2476         nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "borkbork", "yet another really secret password");
2477         nm_setting_set_secret_flags (old, "borkbork", data->secret_flags, NULL);
2478
2479         /* Clear "borkbork" from the duplicated setting */
2480         new = nm_setting_duplicate (old);
2481         if (data->remove_secret) {
2482                 nm_setting_vpn_remove_secret (NM_SETTING_VPN (new), "borkbork");
2483
2484                 /* First make sure they are different */
2485                 success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
2486                 g_assert (success == FALSE);
2487         }
2488
2489         success = nm_setting_compare (old, new, data->comp_flags);
2490         g_assert (success);
2491 }
2492
2493 static void
2494 test_hwaddr_aton_ether_normal (void)
2495 {
2496         guint8 buf[100];
2497         guint8 expected[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
2498
2499         g_assert (nm_utils_hwaddr_aton ("00:11:22:33:44:55", buf, ETH_ALEN) != NULL);
2500         g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
2501 }
2502
2503 static void
2504 test_hwaddr_aton_ib_normal (void)
2505 {
2506         guint8 buf[100];
2507         const char *source = "00:11:22:33:44:55:66:77:88:99:01:12:23:34:45:56:67:78:89:90";
2508         guint8 expected[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
2509                 0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
2510                 0x90 };
2511
2512         g_assert (nm_utils_hwaddr_aton (source, buf, INFINIBAND_ALEN) != NULL);
2513         g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
2514 }
2515
2516 static void
2517 test_hwaddr_aton_no_leading_zeros (void)
2518 {
2519         guint8 buf[100];
2520         guint8 expected[ETH_ALEN] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05 };
2521
2522         g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:44:5", buf, ETH_ALEN) != NULL);
2523         g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
2524 }
2525
2526 static void
2527 test_hwaddr_aton_malformed (void)
2528 {
2529         guint8 buf[100];
2530
2531         g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:a@%%", buf, ETH_ALEN) == NULL);
2532 }
2533
2534 static void
2535 test_hwaddr_equal (void)
2536 {
2537         const char *string = "00:1a:2b:03:44:05";
2538         const char *upper_string = "00:1A:2B:03:44:05";
2539         const char *bad_string = "0:1a:2b:3:44:5";
2540         const guint8 binary[ETH_ALEN] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05 };
2541         const char *other_string = "1a:2b:03:44:05:00";
2542         const guint8 other_binary[ETH_ALEN] = { 0x1A, 0x2B, 0x03, 0x44, 0x05, 0x00 };
2543         const char *long_string = "00:1a:2b:03:44:05:06:07";
2544         const guint8 long_binary[8] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05, 0x06, 0x07 };
2545         const char *null_string = "00:00:00:00:00:00";
2546         const guint8 null_binary[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
2547
2548         g_assert (nm_utils_hwaddr_matches (string, -1, string, -1));
2549         g_assert (nm_utils_hwaddr_matches (string, -1, upper_string, -1));
2550         g_assert (nm_utils_hwaddr_matches (string, -1, bad_string, -1));
2551         g_assert (nm_utils_hwaddr_matches (string, -1, binary, sizeof (binary)));
2552         g_assert (!nm_utils_hwaddr_matches (string, -1, other_string, -1));
2553         g_assert (!nm_utils_hwaddr_matches (string, -1, other_binary, sizeof (other_binary)));
2554         g_assert (!nm_utils_hwaddr_matches (string, -1, long_string, -1));
2555         g_assert (!nm_utils_hwaddr_matches (string, -1, long_binary, sizeof (long_binary)));
2556         g_assert (!nm_utils_hwaddr_matches (string, -1, null_string, -1));
2557         g_assert (!nm_utils_hwaddr_matches (string, -1, null_binary, sizeof (null_binary)));
2558         g_assert (!nm_utils_hwaddr_matches (string, -1, NULL, ETH_ALEN));
2559
2560         g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), string, -1));
2561         g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), upper_string, -1));
2562         g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), bad_string, -1));
2563         g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), binary, sizeof (binary)));
2564         g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), other_string, -1));
2565         g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), other_binary, sizeof (other_binary)));
2566         g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), long_string, -1));
2567         g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), long_binary, sizeof (long_binary)));
2568         g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), null_string, -1));
2569         g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), null_binary, sizeof (null_binary)));
2570         g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), NULL, ETH_ALEN));
2571
2572         g_assert (!nm_utils_hwaddr_matches (null_string, -1, string, -1));
2573         g_assert (!nm_utils_hwaddr_matches (null_string, -1, upper_string, -1));
2574         g_assert (!nm_utils_hwaddr_matches (null_string, -1, bad_string, -1));
2575         g_assert (!nm_utils_hwaddr_matches (null_string, -1, binary, sizeof (binary)));
2576         g_assert (!nm_utils_hwaddr_matches (null_string, -1, other_string, -1));
2577         g_assert (!nm_utils_hwaddr_matches (null_string, -1, other_binary, sizeof (other_binary)));
2578         g_assert (!nm_utils_hwaddr_matches (null_string, -1, long_string, -1));
2579         g_assert (!nm_utils_hwaddr_matches (null_string, -1, long_binary, sizeof (long_binary)));
2580         g_assert (nm_utils_hwaddr_matches (null_string, -1, null_string, -1));
2581         g_assert (nm_utils_hwaddr_matches (null_string, -1, null_binary, sizeof (null_binary)));
2582         g_assert (nm_utils_hwaddr_matches (null_string, -1, NULL, ETH_ALEN));
2583
2584         g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), string, -1));
2585         g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), upper_string, -1));
2586         g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), bad_string, -1));
2587         g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), binary, sizeof (binary)));
2588         g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), other_string, -1));
2589         g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), other_binary, sizeof (other_binary)));
2590         g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), long_string, -1));
2591         g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), long_binary, sizeof (long_binary)));
2592         g_assert (nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), null_string, -1));
2593         g_assert (nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), null_binary, sizeof (null_binary)));
2594         g_assert (nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), NULL, ETH_ALEN));
2595 }
2596
2597 static void
2598 test_hwaddr_canonical (void)
2599 {
2600         const char *string = "00:1A:2B:03:44:05";
2601         const char *lower_string = "00:1a:2b:03:44:05";
2602         const char *short_string = "0:1a:2b:3:44:5";
2603         const char *hyphen_string = "00-1a-2b-03-44-05";
2604         const char *invalid_string = "00:1A:2B";
2605         char *canonical;
2606
2607         canonical = nm_utils_hwaddr_canonical (string, ETH_ALEN);
2608         g_assert_cmpstr (canonical, ==, string);
2609         g_free (canonical);
2610
2611         canonical = nm_utils_hwaddr_canonical (lower_string, ETH_ALEN);
2612         g_assert_cmpstr (canonical, ==, string);
2613         g_free (canonical);
2614
2615         canonical = nm_utils_hwaddr_canonical (short_string, ETH_ALEN);
2616         g_assert_cmpstr (canonical, ==, string);
2617         g_free (canonical);
2618
2619         canonical = nm_utils_hwaddr_canonical (hyphen_string, ETH_ALEN);
2620         g_assert_cmpstr (canonical, ==, string);
2621         g_free (canonical);
2622
2623         canonical = nm_utils_hwaddr_canonical (invalid_string, ETH_ALEN);
2624         g_assert_cmpstr (canonical, ==, NULL);
2625
2626         canonical = nm_utils_hwaddr_canonical (invalid_string, -1);
2627         g_assert_cmpstr (canonical, ==, invalid_string);
2628         g_free (canonical);
2629 }
2630
2631 static void
2632 test_connection_changed_cb (NMConnection *connection, gboolean *data)
2633 {
2634         *data = TRUE;
2635 }
2636
2637 static void
2638 test_ip4_prefix_to_netmask (void)
2639 {
2640         int i;
2641
2642         for (i = 0; i<=32; i++) {
2643                 guint32 netmask = nm_utils_ip4_prefix_to_netmask (i);
2644                 int plen = nm_utils_ip4_netmask_to_prefix (netmask);
2645
2646                 g_assert_cmpint (i, ==, plen);
2647                 {
2648                         guint32 msk = 0x80000000;
2649                         guint32 netmask2 = 0;
2650                         guint32 prefix = i;
2651                         while (prefix > 0) {
2652                                 netmask2 |= msk;
2653                                 msk >>= 1;
2654                                 prefix--;
2655                         }
2656                         g_assert_cmpint (netmask, ==, (guint32) htonl (netmask2));
2657                 }
2658         }
2659 }
2660
2661 static void
2662 test_ip4_netmask_to_prefix (void)
2663 {
2664         int i, j;
2665
2666         GRand *rand = g_rand_new ();
2667
2668         g_rand_set_seed (rand, 1);
2669
2670         for (i = 2; i<=32; i++) {
2671                 guint32 netmask = nm_utils_ip4_prefix_to_netmask (i);
2672                 guint32 netmask_lowest_bit = netmask & ~nm_utils_ip4_prefix_to_netmask (i-1);
2673
2674                 g_assert_cmpint (i, ==, nm_utils_ip4_netmask_to_prefix (netmask));
2675
2676                 for (j = 0; j < 2*i; j++) {
2677                         guint32 r = g_rand_int (rand);
2678                         guint32 netmask_holey;
2679                         guint32 prefix_holey;
2680
2681                         netmask_holey = (netmask & r) | netmask_lowest_bit;
2682
2683                         if (netmask_holey == netmask)
2684                                 continue;
2685
2686                         /* create an invalid netmask with holes and check that the function
2687                          * returns the longest prefix. */
2688                         prefix_holey = nm_utils_ip4_netmask_to_prefix (netmask_holey);
2689
2690                         g_assert_cmpint (i, ==, prefix_holey);
2691                 }
2692         }
2693
2694         g_rand_free (rand);
2695 }
2696
2697 #define ASSERT_CHANGED(statement) \
2698 G_STMT_START { \
2699         changed = FALSE; \
2700         statement; \
2701         g_assert (changed); \
2702 } G_STMT_END
2703
2704 #define ASSERT_UNCHANGED(statement) \
2705 G_STMT_START { \
2706         changed = FALSE; \
2707         statement; \
2708         g_assert (!changed); \
2709 } G_STMT_END
2710
2711 static void
2712 test_connection_changed_signal (void)
2713 {
2714         NMConnection *connection;
2715         gboolean changed = FALSE;
2716
2717         connection = new_test_connection ();
2718         g_signal_connect (connection,
2719                           NM_CONNECTION_CHANGED,
2720                           (GCallback) test_connection_changed_cb,
2721                           &changed);
2722
2723         /* Add new setting */
2724         ASSERT_CHANGED (nm_connection_add_setting (connection, nm_setting_vlan_new ()));
2725
2726         /* Remove existing setting */
2727         ASSERT_CHANGED (nm_connection_remove_setting (connection, NM_TYPE_SETTING_VLAN));
2728
2729         /* Remove non-existing setting */
2730         ASSERT_UNCHANGED (nm_connection_remove_setting (connection, NM_TYPE_SETTING_VLAN));
2731
2732         g_object_unref (connection);
2733 }
2734
2735 static void
2736 test_setting_connection_changed_signal (void)
2737 {
2738         NMConnection *connection;
2739         gboolean changed = FALSE;
2740         NMSettingConnection *s_con;
2741         gs_free char *uuid = NULL;
2742
2743         connection = nm_simple_connection_new ();
2744         g_signal_connect (connection,
2745                           NM_CONNECTION_CHANGED,
2746                           (GCallback) test_connection_changed_cb,
2747                           &changed);
2748
2749         s_con = (NMSettingConnection *) nm_setting_connection_new ();
2750         nm_connection_add_setting (connection, NM_SETTING (s_con));
2751
2752         ASSERT_CHANGED (g_object_set (s_con, NM_SETTING_CONNECTION_ID, "adfadfasdfaf", NULL));
2753
2754         ASSERT_CHANGED (nm_setting_connection_add_permission (s_con, "user", "billsmith", NULL));
2755         ASSERT_CHANGED (nm_setting_connection_remove_permission (s_con, 0));
2756
2757         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*iter != NULL*");
2758         ASSERT_UNCHANGED (nm_setting_connection_remove_permission (s_con, 1));
2759         g_test_assert_expected_messages ();
2760
2761         uuid = nm_utils_uuid_generate ();
2762         ASSERT_CHANGED (nm_setting_connection_add_secondary (s_con, uuid));
2763         ASSERT_CHANGED (nm_setting_connection_remove_secondary (s_con, 0));
2764
2765         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
2766         ASSERT_UNCHANGED (nm_setting_connection_remove_secondary (s_con, 1));
2767         g_test_assert_expected_messages ();
2768
2769         g_object_unref (connection);
2770 }
2771
2772 static void
2773 test_setting_bond_changed_signal (void)
2774 {
2775         NMConnection *connection;
2776         gboolean changed = FALSE;
2777         NMSettingBond *s_bond;
2778
2779         connection = nm_simple_connection_new ();
2780         g_signal_connect (connection,
2781                           NM_CONNECTION_CHANGED,
2782                           (GCallback) test_connection_changed_cb,
2783                           &changed);
2784
2785         s_bond = (NMSettingBond *) nm_setting_bond_new ();
2786         nm_connection_add_setting (connection, NM_SETTING (s_bond));
2787
2788         ASSERT_CHANGED (nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10"));
2789         ASSERT_CHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY));
2790         ASSERT_UNCHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY));
2791
2792         g_object_unref (connection);
2793 }
2794
2795 static void
2796 test_setting_ip4_changed_signal (void)
2797 {
2798         NMConnection *connection;
2799         gboolean changed = FALSE;
2800         NMSettingIPConfig *s_ip4;
2801         NMIPAddress *addr;
2802         NMIPRoute *route;
2803         GError *error = NULL;
2804
2805         connection = nm_simple_connection_new ();
2806         g_signal_connect (connection,
2807                           NM_CONNECTION_CHANGED,
2808                           (GCallback) test_connection_changed_cb,
2809                           &changed);
2810
2811         s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
2812         nm_connection_add_setting (connection, NM_SETTING (s_ip4));
2813
2814         ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip4, "11.22.0.0"));
2815         ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip4, 0));
2816
2817         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns->len*");
2818         ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip4, 1));
2819         g_test_assert_expected_messages ();
2820
2821         nm_setting_ip_config_add_dns (s_ip4, "33.44.0.0");
2822         ASSERT_CHANGED (nm_setting_ip_config_clear_dns (s_ip4));
2823
2824         ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com"));
2825         ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 0));
2826
2827         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns_search->len*");
2828         ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 1));
2829         g_test_assert_expected_messages ();
2830
2831         ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com"));
2832         ASSERT_CHANGED (nm_setting_ip_config_clear_dns_searches (s_ip4));
2833
2834         addr = nm_ip_address_new (AF_INET, "22.33.0.0", 24, &error);
2835         g_assert_no_error (error);
2836         ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip4, addr));
2837         ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip4, 0));
2838
2839         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->addresses->len*");
2840         ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip4, 1));
2841         g_test_assert_expected_messages ();
2842
2843         nm_setting_ip_config_add_address (s_ip4, addr);
2844         ASSERT_CHANGED (nm_setting_ip_config_clear_addresses (s_ip4));
2845
2846         route = nm_ip_route_new (AF_INET, "22.33.0.0", 24, NULL, 0, &error);
2847         g_assert_no_error (error);
2848
2849         ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip4, route));
2850         ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip4, 0));
2851
2852         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->routes->len*");
2853         ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip4, 1));
2854         g_test_assert_expected_messages ();
2855
2856         nm_setting_ip_config_add_route (s_ip4, route);
2857         ASSERT_CHANGED (nm_setting_ip_config_clear_routes (s_ip4));
2858
2859         ASSERT_CHANGED (nm_setting_ip_config_add_dns_option (s_ip4, "debug"));
2860         ASSERT_CHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 0));
2861
2862         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns_options->len*");
2863         ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_option (s_ip4, 1));
2864         g_test_assert_expected_messages ();
2865
2866         nm_ip_address_unref (addr);
2867         nm_ip_route_unref (route);
2868         g_object_unref (connection);
2869 }
2870
2871 static void
2872 test_setting_ip6_changed_signal (void)
2873 {
2874         NMConnection *connection;
2875         gboolean changed = FALSE;
2876         NMSettingIPConfig *s_ip6;
2877         NMIPAddress *addr;
2878         NMIPRoute *route;
2879         GError *error = NULL;
2880
2881         connection = nm_simple_connection_new ();
2882         g_signal_connect (connection,
2883                           NM_CONNECTION_CHANGED,
2884                           (GCallback) test_connection_changed_cb,
2885                           &changed);
2886
2887         s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
2888         nm_connection_add_setting (connection, NM_SETTING (s_ip6));
2889
2890         ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip6, "1:2:3::4:5:6"));
2891         ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip6, 0));
2892
2893         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns->len*");
2894         ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip6, 1));
2895         g_test_assert_expected_messages ();
2896
2897         nm_setting_ip_config_add_dns (s_ip6, "1:2:3::4:5:6");
2898         ASSERT_CHANGED (nm_setting_ip_config_clear_dns (s_ip6));
2899
2900         ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com"));
2901         ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 0));
2902
2903         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->dns_search->len*");
2904         ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 1));
2905         g_test_assert_expected_messages ();
2906
2907         nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com");
2908         ASSERT_CHANGED (nm_setting_ip_config_clear_dns_searches (s_ip6));
2909
2910         addr = nm_ip_address_new (AF_INET6, "1:2:3::4:5:6", 64, &error);
2911         g_assert_no_error (error);
2912
2913         ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip6, addr));
2914         ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip6, 0));
2915
2916         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->addresses->len*");
2917         ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip6, 1));
2918         g_test_assert_expected_messages ();
2919
2920         nm_setting_ip_config_add_address (s_ip6, addr);
2921         ASSERT_CHANGED (nm_setting_ip_config_clear_addresses (s_ip6));
2922
2923         route = nm_ip_route_new (AF_INET6, "1:2:3::4:5:6", 128, NULL, 0, &error);
2924         g_assert_no_error (error);
2925
2926         ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip6, route));
2927         ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip6, 0));
2928
2929         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < priv->routes->len*");
2930         ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip6, 1));
2931         g_test_assert_expected_messages ();
2932
2933         nm_setting_ip_config_add_route (s_ip6, route);
2934         ASSERT_CHANGED (nm_setting_ip_config_clear_routes (s_ip6));
2935
2936         nm_ip_address_unref (addr);
2937         nm_ip_route_unref (route);
2938         g_object_unref (connection);
2939 }
2940
2941 static void
2942 test_setting_vlan_changed_signal (void)
2943 {
2944         NMConnection *connection;
2945         gboolean changed = FALSE;
2946         NMSettingVlan *s_vlan;
2947
2948         connection = nm_simple_connection_new ();
2949         g_signal_connect (connection,
2950                           NM_CONNECTION_CHANGED,
2951                           (GCallback) test_connection_changed_cb,
2952                           &changed);
2953
2954         s_vlan = (NMSettingVlan *) nm_setting_vlan_new ();
2955         nm_connection_add_setting (connection, NM_SETTING (s_vlan));
2956
2957         ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1, 3));
2958         ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 0));
2959         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < g_slist_length (list)*");
2960         ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1));
2961         g_test_assert_expected_messages ();
2962         ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_INGRESS_MAP, "1:3"));
2963         ASSERT_CHANGED (nm_setting_vlan_clear_priorities (s_vlan, NM_VLAN_INGRESS_MAP));
2964
2965         ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1, 3));
2966         ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 0));
2967         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < g_slist_length (list)*");
2968         ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1));
2969         g_test_assert_expected_messages ();
2970         ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_EGRESS_MAP, "1:3"));
2971         ASSERT_CHANGED (nm_setting_vlan_clear_priorities (s_vlan, NM_VLAN_EGRESS_MAP));
2972
2973         g_object_unref (connection);
2974 }
2975
2976 static void
2977 test_setting_vpn_changed_signal (void)
2978 {
2979         NMConnection *connection;
2980         gboolean changed = FALSE;
2981         NMSettingVpn *s_vpn;
2982
2983         connection = nm_simple_connection_new ();
2984         g_signal_connect (connection,
2985                           NM_CONNECTION_CHANGED,
2986                           (GCallback) test_connection_changed_cb,
2987                           &changed);
2988
2989         s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
2990         nm_connection_add_setting (connection, NM_SETTING (s_vpn));
2991
2992         ASSERT_CHANGED (nm_setting_vpn_add_data_item (s_vpn, "foobar", "baz"));
2993         ASSERT_CHANGED (nm_setting_vpn_remove_data_item (s_vpn, "foobar"));
2994         ASSERT_UNCHANGED (nm_setting_vpn_remove_data_item (s_vpn, "not added"));
2995
2996         ASSERT_CHANGED (nm_setting_vpn_add_secret (s_vpn, "foobar", "baz"));
2997         ASSERT_CHANGED (nm_setting_vpn_remove_secret (s_vpn, "foobar"));
2998         ASSERT_UNCHANGED (nm_setting_vpn_remove_secret (s_vpn, "not added"));
2999
3000         g_object_unref (connection);
3001 }
3002
3003 static void
3004 test_setting_wired_changed_signal (void)
3005 {
3006         NMConnection *connection;
3007         gboolean changed = FALSE;
3008         NMSettingWired *s_wired;
3009
3010         connection = nm_simple_connection_new ();
3011         g_signal_connect (connection,
3012                           NM_CONNECTION_CHANGED,
3013                           (GCallback) test_connection_changed_cb,
3014                           &changed);
3015
3016         s_wired = (NMSettingWired *) nm_setting_wired_new ();
3017         nm_connection_add_setting (connection, NM_SETTING (s_wired));
3018
3019         ASSERT_CHANGED (nm_setting_wired_add_s390_option (s_wired, "portno", "1"));
3020         ASSERT_CHANGED (nm_setting_wired_remove_s390_option (s_wired, "portno"));
3021         ASSERT_UNCHANGED (nm_setting_wired_remove_s390_option (s_wired, "layer2"));
3022
3023         g_object_unref (connection);
3024 }
3025
3026 static void
3027 test_setting_wireless_changed_signal (void)
3028 {
3029         NMConnection *connection;
3030         gboolean changed = FALSE;
3031         NMSettingWireless *s_wifi;
3032
3033         connection = nm_simple_connection_new ();
3034         g_signal_connect (connection,
3035                           NM_CONNECTION_CHANGED,
3036                           (GCallback) test_connection_changed_cb,
3037                           &changed);
3038
3039         s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
3040         nm_connection_add_setting (connection, NM_SETTING (s_wifi));
3041
3042         ASSERT_CHANGED (nm_setting_wireless_add_seen_bssid (s_wifi, "00:11:22:33:44:55"));
3043
3044         g_object_unref (connection);
3045 }
3046
3047 static void
3048 test_setting_wireless_security_changed_signal (void)
3049 {
3050         NMConnection *connection;
3051         gboolean changed = FALSE;
3052         NMSettingWirelessSecurity *s_wsec;
3053
3054         connection = nm_simple_connection_new ();
3055         g_signal_connect (connection,
3056                           NM_CONNECTION_CHANGED,
3057                           (GCallback) test_connection_changed_cb,
3058                           &changed);
3059
3060         s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
3061         nm_connection_add_setting (connection, NM_SETTING (s_wsec));
3062
3063         /* Protos */
3064         ASSERT_CHANGED (nm_setting_wireless_security_add_proto (s_wsec, "wpa"));
3065         ASSERT_CHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 0));
3066         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
3067         ASSERT_UNCHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 1));
3068         g_test_assert_expected_messages ();
3069
3070         nm_setting_wireless_security_add_proto (s_wsec, "wep");
3071         ASSERT_CHANGED (nm_setting_wireless_security_clear_protos (s_wsec));
3072
3073         /* Pairwise ciphers */
3074         ASSERT_CHANGED (nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"));
3075         ASSERT_CHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 0));
3076         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
3077         ASSERT_UNCHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 1));
3078         g_test_assert_expected_messages ();
3079
3080         nm_setting_wireless_security_add_pairwise (s_wsec, "tkip");
3081         ASSERT_CHANGED (nm_setting_wireless_security_clear_pairwise (s_wsec));
3082
3083         /* Group ciphers */
3084         ASSERT_CHANGED (nm_setting_wireless_security_add_group (s_wsec, "ccmp"));
3085         ASSERT_CHANGED (nm_setting_wireless_security_remove_group (s_wsec, 0));
3086         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
3087         ASSERT_UNCHANGED (nm_setting_wireless_security_remove_group (s_wsec, 1));
3088         g_test_assert_expected_messages ();
3089
3090         nm_setting_wireless_security_add_group (s_wsec, "tkip");
3091         ASSERT_CHANGED (nm_setting_wireless_security_clear_groups (s_wsec));
3092
3093         /* WEP key secret flags */
3094         ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key0", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
3095         ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key1", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
3096         ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key2", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
3097         ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key3", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
3098
3099         g_object_unref (connection);
3100 }
3101
3102 static void
3103 test_setting_802_1x_changed_signal (void)
3104 {
3105         NMConnection *connection;
3106         gboolean changed = FALSE;
3107         NMSetting8021x *s_8021x;
3108
3109         connection = nm_simple_connection_new ();
3110         g_signal_connect (connection,
3111                           NM_CONNECTION_CHANGED,
3112                           (GCallback) test_connection_changed_cb,
3113                           &changed);
3114
3115         s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
3116         nm_connection_add_setting (connection, NM_SETTING (s_8021x));
3117
3118         /* EAP methods */
3119         ASSERT_CHANGED (nm_setting_802_1x_add_eap_method (s_8021x, "tls"));
3120         ASSERT_CHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 0));
3121         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
3122         ASSERT_UNCHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 1));
3123         g_test_assert_expected_messages ();
3124
3125         nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
3126         ASSERT_CHANGED (nm_setting_802_1x_clear_eap_methods (s_8021x));
3127
3128         /* alternate subject matches */
3129         ASSERT_CHANGED (nm_setting_802_1x_add_altsubject_match (s_8021x, "EMAIL:server@example.com"));
3130         ASSERT_CHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 0));
3131         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
3132         ASSERT_UNCHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 1));
3133         g_test_assert_expected_messages ();
3134
3135         nm_setting_802_1x_add_altsubject_match (s_8021x, "EMAIL:server@example.com");
3136         ASSERT_CHANGED (nm_setting_802_1x_clear_altsubject_matches (s_8021x));
3137
3138         /* phase2 alternate subject matches */
3139         ASSERT_CHANGED (nm_setting_802_1x_add_phase2_altsubject_match (s_8021x, "EMAIL:server@example.com"));
3140         ASSERT_CHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 0));
3141         g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
3142         ASSERT_UNCHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 1));
3143         g_test_assert_expected_messages ();
3144
3145         nm_setting_802_1x_add_phase2_altsubject_match (s_8021x, "EMAIL:server@example.com");
3146         ASSERT_CHANGED (nm_setting_802_1x_clear_phase2_altsubject_matches (s_8021x));
3147
3148         g_object_unref (connection);
3149 }
3150
3151 static void
3152 test_setting_old_uuid (void)
3153 {
3154         gs_unref_object NMSetting *setting = NULL;
3155
3156         /* NetworkManager-0.9.4.0 generated 40-character UUIDs with no dashes,
3157          * like this one. Test that we maintain compatibility. */
3158         const char *uuid = "f43bec2cdd60e5da381ebb1eb1fa39f3cc52660c";
3159
3160         setting = nm_setting_connection_new ();
3161         g_object_set (G_OBJECT (setting),
3162                       NM_SETTING_CONNECTION_ID, "uuidtest",
3163                       NM_SETTING_CONNECTION_UUID, uuid,
3164                       NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
3165                       NULL);
3166
3167         nmtst_assert_setting_verifies (NM_SETTING (setting));
3168 }
3169
3170 /******************************************************************************/
3171
3172 static void
3173 test_connection_normalize_uuid (void)
3174 {
3175         gs_unref_object NMConnection *con = NULL;
3176
3177         con = nmtst_create_minimal_connection ("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
3178
3179         nmtst_assert_connection_verifies_and_normalizable (con);
3180
3181         g_object_set (nm_connection_get_setting_connection (con),
3182                       NM_SETTING_CONNECTION_UUID, NULL,
3183                       NULL);
3184         nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
3185 }
3186
3187 /******************************************************************************/
3188
3189 /*
3190  * Test normalization of interface-name
3191  */
3192 static void
3193 test_connection_normalize_virtual_iface_name (void)
3194 {
3195         NMConnection *con = NULL;
3196         NMSettingConnection *s_con;
3197         NMSettingVlan *s_vlan;
3198         GVariant *connection_dict, *setting_dict, *var;
3199         GError *error = NULL;
3200         const char *IFACE_NAME = "iface";
3201         const char *IFACE_VIRT = "iface-X";
3202
3203         con = nmtst_create_minimal_connection ("test1",
3204                                                "22001632-bbb4-4616-b277-363dce3dfb5b",
3205                                                NM_SETTING_VLAN_SETTING_NAME,
3206                                                &s_con);
3207
3208         nm_connection_add_setting (con,
3209             g_object_new (NM_TYPE_SETTING_IP4_CONFIG,
3210                           NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
3211                           NULL));
3212
3213         nm_connection_add_setting (con,
3214             g_object_new (NM_TYPE_SETTING_IP6_CONFIG,
3215                           NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
3216                           NULL));
3217
3218         s_vlan = nm_connection_get_setting_vlan (con);
3219
3220         g_object_set (G_OBJECT (s_vlan),
3221                       NM_SETTING_VLAN_PARENT, "eth0",
3222                       NULL);
3223
3224         g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, IFACE_NAME, NULL);
3225
3226         g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_NAME);
3227
3228         connection_dict = nm_connection_to_dbus (con, NM_CONNECTION_SERIALIZE_ALL);
3229         g_object_unref (con);
3230
3231         /* Serialized form should include vlan.interface-name as well. */
3232         setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_VLAN_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
3233         g_assert (setting_dict != NULL);
3234         var = g_variant_lookup_value (setting_dict, "interface-name", NULL);
3235         g_assert (var != NULL);
3236         g_assert (g_variant_is_of_type (var, G_VARIANT_TYPE_STRING));
3237         g_assert_cmpstr (g_variant_get_string (var, NULL), ==, IFACE_NAME);
3238
3239         g_variant_unref (setting_dict);
3240         g_variant_unref (var);
3241
3242         /* If vlan.interface-name is invalid, deserialization will fail. */
3243         NMTST_VARIANT_EDITOR (connection_dict,
3244                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_VLAN_SETTING_NAME,
3245                                                              "interface-name",
3246                                                              "s",
3247                                                              ":::this-is-not-a-valid-interface-name:::");
3248                               );
3249
3250         con = _connection_new_from_dbus (connection_dict, &error);
3251         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
3252         g_clear_error (&error);
3253
3254         /* If vlan.interface-name is valid, but doesn't match, it will be ignored. */
3255         NMTST_VARIANT_EDITOR (connection_dict,
3256                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_VLAN_SETTING_NAME,
3257                                                              "interface-name",
3258                                                              "s",
3259                                                              IFACE_VIRT);
3260                               );
3261
3262         con = _connection_new_from_dbus (connection_dict, &error);
3263         g_assert_no_error (error);
3264
3265         g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_NAME);
3266         s_con = nm_connection_get_setting_connection (con);
3267         g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, IFACE_NAME);
3268         g_object_unref (con);
3269
3270         /* But removing connection.interface-name should result in vlan.connection-name
3271          * being "promoted".
3272          */
3273         NMTST_VARIANT_EDITOR (connection_dict,
3274                               NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_CONNECTION_SETTING_NAME,
3275                                                            NM_SETTING_CONNECTION_INTERFACE_NAME);
3276                               );
3277
3278         con = _connection_new_from_dbus (connection_dict, &error);
3279         g_assert_no_error (error);
3280
3281         g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_VIRT);
3282         s_con = nm_connection_get_setting_connection (con);
3283         g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, IFACE_VIRT);
3284         g_object_unref (con);
3285
3286         g_variant_unref (connection_dict);
3287 }
3288
3289 static void
3290 _test_connection_normalize_type_normalizable_setting (const char *type,
3291                                                       void (*prepare_normalizable_fcn) (NMConnection *con))
3292 {
3293         NMSettingConnection *s_con;
3294         NMSetting *s_base;
3295         GType base_type;
3296         gs_unref_object NMConnection *con = NULL;
3297         gs_free char *id = g_strdup_printf ("%s[%s]", G_STRFUNC, type);
3298
3299         base_type = nm_setting_lookup_type (type);
3300         g_assert (base_type != G_TYPE_INVALID);
3301         g_assert (_nm_setting_type_is_base_type (base_type));
3302
3303         con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con);
3304
3305         nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
3306
3307         g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NULL);
3308
3309         if (prepare_normalizable_fcn)
3310                 prepare_normalizable_fcn (con);
3311
3312         g_assert (!nm_connection_get_setting_by_name (con, type));
3313         nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
3314         nmtst_connection_normalize (con);
3315
3316         s_base = nm_connection_get_setting_by_name (con, type);
3317         g_assert (s_base);
3318         g_assert (G_OBJECT_TYPE (s_base) == base_type);
3319 }
3320
3321 static void
3322 _test_connection_normalize_type_unnormalizable_setting (const char *type)
3323 {
3324         NMSettingConnection *s_con;
3325         GType base_type;
3326         gs_unref_object NMConnection *con = NULL;
3327         gs_free char *id = g_strdup_printf ("%s[%s]", G_STRFUNC, type);
3328
3329         base_type = nm_setting_lookup_type (type);
3330         g_assert (base_type != G_TYPE_INVALID);
3331         g_assert (_nm_setting_type_is_base_type (base_type));
3332
3333         con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con);
3334
3335         nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
3336
3337         g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NULL);
3338
3339         nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
3340 }
3341
3342 static void
3343 _test_connection_normalize_type_normalizable_type (const char *type,
3344                                                    NMSetting *(*add_setting_fcn) (NMConnection *con))
3345 {
3346         NMSettingConnection *s_con;
3347         NMSetting *s_base;
3348         GType base_type;
3349         gs_unref_object NMConnection *con = NULL;
3350         gs_free char *id = g_strdup_printf ("%s[%s]", G_STRFUNC, type);
3351
3352         base_type = nm_setting_lookup_type (type);
3353         g_assert (base_type != G_TYPE_INVALID);
3354         g_assert (_nm_setting_type_is_base_type (base_type));
3355
3356         con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con);
3357
3358         nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
3359
3360         if (add_setting_fcn)
3361                 s_base = add_setting_fcn (con);
3362         else {
3363                 s_base = NM_SETTING (g_object_new (base_type, NULL));
3364                 nm_connection_add_setting (con, s_base);
3365         }
3366
3367         g_assert (!nm_connection_get_connection_type (con));
3368         g_assert (nm_connection_get_setting_by_name (con, type) == s_base);
3369
3370         nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
3371         nmtst_connection_normalize (con);
3372
3373         g_assert_cmpstr (nm_connection_get_connection_type (con), ==, type);
3374         g_assert (nm_connection_get_setting_by_name (con, type) == s_base);
3375 }
3376
3377 static NMSetting *
3378 _add_setting_fcn_adsl (NMConnection *con)
3379 {
3380         NMSetting *setting;
3381
3382         setting = g_object_new (NM_TYPE_SETTING_ADSL,
3383                                 NM_SETTING_ADSL_USERNAME, "test-user",
3384                                 NM_SETTING_ADSL_PROTOCOL, NM_SETTING_ADSL_PROTOCOL_PPPOA,
3385                                 NM_SETTING_ADSL_ENCAPSULATION, NM_SETTING_ADSL_ENCAPSULATION_VCMUX,
3386                                 NULL);
3387
3388         nm_connection_add_setting (con, setting);
3389         return setting;
3390 }
3391
3392 static NMSetting *
3393 _add_setting_fcn_bluetooth (NMConnection *con)
3394 {
3395         NMSetting *setting;
3396
3397         setting = g_object_new (NM_TYPE_SETTING_BLUETOOTH,
3398                                 NM_SETTING_BLUETOOTH_BDADDR, "11:22:33:44:55:66",
3399                                 NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
3400                                 NULL);
3401
3402         nm_connection_add_setting (con, setting);
3403         return setting;
3404 }
3405
3406 static NMSetting *
3407 _add_setting_fcn_bond (NMConnection *con)
3408 {
3409         NMSetting *setting;
3410         NMSettingConnection *s_con;
3411
3412         setting = g_object_new (NM_TYPE_SETTING_BOND, NULL);
3413
3414         nm_connection_add_setting (con, setting);
3415
3416         s_con = nm_connection_get_setting_connection (con);
3417
3418         g_object_set (s_con,
3419                       NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bond",
3420                       NULL);
3421
3422         return setting;
3423 }
3424
3425 static NMSetting *
3426 _add_setting_fcn_bridge (NMConnection *con)
3427 {
3428         NMSetting *setting;
3429         NMSettingConnection *s_con;
3430
3431         setting = g_object_new (NM_TYPE_SETTING_BRIDGE, NULL);
3432
3433         nm_connection_add_setting (con, setting);
3434
3435         s_con = nm_connection_get_setting_connection (con);
3436
3437         g_object_set (s_con,
3438                       NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bridge",
3439                       NULL);
3440
3441         return setting;
3442 }
3443
3444 static NMSetting *
3445 _add_setting_fcn_cdma (NMConnection *con)
3446 {
3447         NMSetting *setting;
3448
3449         setting = g_object_new (NM_TYPE_SETTING_CDMA,
3450                                 NM_SETTING_CDMA_NUMBER, "test-number",
3451                                 NULL);
3452
3453         nm_connection_add_setting (con, setting);
3454         return setting;
3455 }
3456
3457 static NMSetting *
3458 _add_setting_fcn_infiniband (NMConnection *con)
3459 {
3460         NMSetting *setting;
3461
3462         setting = g_object_new (NM_TYPE_SETTING_INFINIBAND,
3463                                 NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
3464                                 NULL);
3465
3466         nm_connection_add_setting (con, setting);
3467         return setting;
3468 }
3469
3470 static NMSetting *
3471 _add_setting_fcn_olpc_mesh (NMConnection *con)
3472 {
3473         NMSetting *setting;
3474         const char *ssid_data = "ssid-test";
3475         GBytes *ssid;
3476
3477         ssid = g_bytes_new (ssid_data, strlen (ssid_data));
3478         setting = g_object_new (NM_TYPE_SETTING_OLPC_MESH,
3479                                 NM_SETTING_OLPC_MESH_SSID, ssid,
3480                                 NM_SETTING_OLPC_MESH_CHANNEL, 1,
3481                                 NULL);
3482         g_bytes_unref (ssid);
3483
3484         nm_connection_add_setting (con, setting);
3485         return setting;
3486 }
3487
3488 static NMSetting *
3489 _add_setting_fcn_team (NMConnection *con)
3490 {
3491         NMSetting *setting;
3492         NMSettingConnection *s_con;
3493
3494         setting = g_object_new (NM_TYPE_SETTING_TEAM, NULL);
3495
3496         nm_connection_add_setting (con, setting);
3497
3498         s_con = nm_connection_get_setting_connection (con);
3499
3500         g_object_set (s_con,
3501                       NM_SETTING_CONNECTION_INTERFACE_NAME, "test-team",
3502                       NULL);
3503
3504         return setting;
3505 }
3506
3507 static NMSetting *
3508 _add_setting_fcn_vlan (NMConnection *con)
3509 {
3510         NMSetting *setting;
3511
3512         setting = g_object_new (NM_TYPE_SETTING_VLAN,
3513                                 NM_SETTING_VLAN_PARENT, "test-parent",
3514                                 NULL);
3515
3516         nm_connection_add_setting (con, setting);
3517         return setting;
3518 }
3519
3520 static NMSetting *
3521 _add_setting_fcn_vpn (NMConnection *con)
3522 {
3523         NMSetting *setting;
3524
3525         setting = g_object_new (NM_TYPE_SETTING_VPN,
3526                                 NM_SETTING_VPN_SERVICE_TYPE, "test-vpn-service-type",
3527                                 NULL);
3528
3529         nm_connection_add_setting (con, setting);
3530         return setting;
3531 }
3532
3533 static NMSetting *
3534 _add_setting_fcn_wimax (NMConnection *con)
3535 {
3536         NMSetting *setting;
3537
3538         setting = g_object_new (NM_TYPE_SETTING_WIMAX,
3539                                 NM_SETTING_WIMAX_NETWORK_NAME, "test-network",
3540                                 NULL);
3541
3542         nm_connection_add_setting (con, setting);
3543         return setting;
3544 }
3545
3546 static NMSetting *
3547 _add_setting_fcn_wireless (NMConnection *con)
3548 {
3549         NMSetting *setting;
3550         const char *ssid_data = "ssid-test";
3551         GBytes *ssid;
3552
3553         ssid = g_bytes_new (ssid_data, strlen (ssid_data));
3554         setting = g_object_new (NM_TYPE_SETTING_WIRELESS,
3555                                 NM_SETTING_WIRELESS_SSID, ssid,
3556                                 NULL);
3557         g_bytes_unref (ssid);
3558
3559         nm_connection_add_setting (con, setting);
3560         return setting;
3561 }
3562
3563 static void
3564 _prepare_normalizable_fcn_vlan (NMConnection *con)
3565 {
3566         nm_connection_add_setting (con, g_object_new (NM_TYPE_SETTING_WIRED,
3567                                                       NM_SETTING_WIRED_MAC_ADDRESS, "11:22:33:44:55:66",
3568                                                       NULL));
3569 }
3570
3571 static void
3572 test_connection_normalize_type (void)
3573 {
3574         guint i;
3575         struct {
3576                 const char *type;
3577                 gboolean normalizable;
3578                 NMSetting *(*add_setting_fcn) (NMConnection *con);
3579                 void (*prepare_normalizable_fcn) (NMConnection *con);
3580         } types[] = {
3581                 { NM_SETTING_GENERIC_SETTING_NAME, TRUE },
3582                 { NM_SETTING_GSM_SETTING_NAME, TRUE },
3583                 { NM_SETTING_WIRED_SETTING_NAME, TRUE },
3584                 { NM_SETTING_VLAN_SETTING_NAME, TRUE, _add_setting_fcn_vlan, _prepare_normalizable_fcn_vlan },
3585
3586                 { NM_SETTING_ADSL_SETTING_NAME, FALSE, _add_setting_fcn_adsl },
3587                 { NM_SETTING_BLUETOOTH_SETTING_NAME, FALSE, _add_setting_fcn_bluetooth },
3588                 { NM_SETTING_BOND_SETTING_NAME, FALSE, _add_setting_fcn_bond },
3589                 { NM_SETTING_BRIDGE_SETTING_NAME, FALSE, _add_setting_fcn_bridge },
3590                 { NM_SETTING_CDMA_SETTING_NAME, FALSE, _add_setting_fcn_cdma },
3591                 { NM_SETTING_INFINIBAND_SETTING_NAME, FALSE, _add_setting_fcn_infiniband },
3592                 { NM_SETTING_OLPC_MESH_SETTING_NAME, FALSE, _add_setting_fcn_olpc_mesh },
3593                 { NM_SETTING_TEAM_SETTING_NAME, FALSE, _add_setting_fcn_team },
3594                 { NM_SETTING_VLAN_SETTING_NAME, FALSE, _add_setting_fcn_vlan },
3595                 { NM_SETTING_VPN_SETTING_NAME, FALSE, _add_setting_fcn_vpn },
3596                 { NM_SETTING_WIMAX_SETTING_NAME, FALSE, _add_setting_fcn_wimax },
3597                 { NM_SETTING_WIRELESS_SETTING_NAME, FALSE, _add_setting_fcn_wireless },
3598                 { 0 },
3599         };
3600
3601         for (i = 0; types[i].type; i++) {
3602                 const char *type = types[i].type;
3603
3604                 if (types[i].normalizable)
3605                         _test_connection_normalize_type_normalizable_setting (type, types[i].prepare_normalizable_fcn);
3606                 else
3607                         _test_connection_normalize_type_unnormalizable_setting (type);
3608                 _test_connection_normalize_type_normalizable_type (type, types[i].add_setting_fcn);
3609         }
3610 }
3611
3612 static void
3613 test_connection_normalize_slave_type_1 (void)
3614 {
3615         gs_unref_object NMConnection *con = NULL;
3616         NMSettingConnection *s_con;
3617
3618         con = nmtst_create_minimal_connection ("test_connection_normalize_slave_type_1",
3619                                                "cc4cd5df-45dc-483e-b291-6b76c2338ecb",
3620                                                NM_SETTING_WIRED_SETTING_NAME, &s_con);
3621
3622         g_object_set (s_con,
3623                       NM_SETTING_CONNECTION_MASTER, "master0",
3624                       NM_SETTING_CONNECTION_SLAVE_TYPE, "invalid-type",
3625                       NULL);
3626
3627         nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
3628         g_assert (!nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
3629
3630         g_object_set (s_con,
3631                       NM_SETTING_CONNECTION_SLAVE_TYPE, "bridge",
3632                       NULL);
3633
3634         g_assert (!nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
3635         nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
3636         nmtst_connection_normalize (con);
3637         g_assert (nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
3638         g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
3639 }
3640
3641 static void
3642 test_connection_normalize_slave_type_2 (void)
3643 {
3644         gs_unref_object NMConnection *con = NULL;
3645         NMSettingConnection *s_con;
3646
3647         con = nmtst_create_minimal_connection ("test_connection_normalize_slave_type_2",
3648                                                "40bea008-ca72-439a-946b-e65f827656f9",
3649                                                NM_SETTING_WIRED_SETTING_NAME, &s_con);
3650
3651         g_object_set (s_con,
3652                       NM_SETTING_CONNECTION_MASTER, "master0",
3653                       NM_SETTING_CONNECTION_SLAVE_TYPE, "invalid-type",
3654                       NULL);
3655
3656         nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
3657         g_assert (!nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
3658
3659         g_object_set (s_con,
3660                       NM_SETTING_CONNECTION_SLAVE_TYPE, NULL,
3661                       NULL);
3662         nm_connection_add_setting (con, nm_setting_bridge_port_new ());
3663
3664         g_assert (nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
3665         g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NULL);
3666         nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
3667         nmtst_connection_normalize (con);
3668         g_assert (nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
3669         g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
3670 }
3671
3672 static void
3673 test_connection_normalize_infiniband_mtu (void)
3674 {
3675         gs_unref_object NMConnection *con = NULL;
3676         NMSettingInfiniband *s_infini;
3677
3678         con = nmtst_create_minimal_connection ("test_connection_normalize_infiniband_mtu", NULL,
3679                                                NM_SETTING_INFINIBAND_SETTING_NAME, NULL);
3680
3681         s_infini = nm_connection_get_setting_infiniband (con);
3682         g_object_set (s_infini,
3683                       NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
3684                       NULL);
3685         nmtst_assert_connection_verifies_and_normalizable (con);
3686
3687         g_object_set (s_infini,
3688                       NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
3689                       NM_SETTING_INFINIBAND_MTU, (guint) 2044,
3690                       NULL);
3691         nmtst_assert_connection_verifies_and_normalizable (con);
3692         nmtst_connection_normalize (con);
3693         g_assert_cmpint (2044, ==, nm_setting_infiniband_get_mtu (s_infini));
3694
3695         g_object_set (s_infini,
3696                       NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
3697                       NM_SETTING_INFINIBAND_MTU, (guint) 2045,
3698                       NULL);
3699         nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
3700         nmtst_connection_normalize (con);
3701         g_assert_cmpint (2044, ==, nm_setting_infiniband_get_mtu (s_infini));
3702
3703         g_object_set (s_infini,
3704                       NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
3705                       NM_SETTING_INFINIBAND_MTU, (guint) 65520,
3706                       NULL);
3707         nmtst_assert_connection_verifies_without_normalization (con);
3708         g_assert_cmpint (65520, ==, nm_setting_infiniband_get_mtu (s_infini));
3709
3710         g_object_set (s_infini,
3711                       NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
3712                       NM_SETTING_INFINIBAND_MTU, (guint) 65521,
3713                       NULL);
3714         nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
3715         nmtst_connection_normalize (con);
3716         g_assert_cmpint (65520, ==, nm_setting_infiniband_get_mtu (s_infini));
3717 }
3718
3719 static void
3720 test_setting_ip4_gateway (void)
3721 {
3722         NMConnection *conn;
3723         NMSettingIPConfig *s_ip4;
3724         NMIPAddress *addr;
3725         GVariant *conn_dict, *ip4_dict, *value;
3726         GVariantIter iter;
3727         GVariant *addr_var;
3728         guint32 addr_vals_0[] = { htonl (0xc0a8010a), 0x00000018, htonl (0x00000000) };
3729         guint32 addr_vals_1[] = { htonl (0xc0a8010b), 0x00000018, htonl (0xc0a80101) };
3730         GVariantBuilder addrs_builder;
3731         GError *error = NULL;
3732
3733         g_assert_cmpstr (nm_utils_inet4_ntop (addr_vals_0[0], NULL), ==, "192.168.1.10");
3734
3735         /* When serializing on the daemon side, ipv4.gateway is copied to the first
3736          * entry of ipv4.addresses
3737          */
3738         conn = nmtst_create_minimal_connection ("test_setting_ip4_gateway", NULL,
3739                                                 NM_SETTING_WIRED_SETTING_NAME, NULL);
3740         s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
3741         g_object_set (s_ip4,
3742                       NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
3743                       NM_SETTING_IP_CONFIG_GATEWAY, "192.168.1.1",
3744                       NULL);
3745         nm_connection_add_setting (conn, NM_SETTING (s_ip4));
3746
3747         addr = nm_ip_address_new (AF_INET, "192.168.1.10", 24, &error);
3748         g_assert_no_error (error);
3749         nm_setting_ip_config_add_address (s_ip4, addr);
3750         nm_ip_address_unref (addr);
3751
3752         _nm_utils_is_manager_process = TRUE;
3753         conn_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
3754         _nm_utils_is_manager_process = FALSE;
3755         g_object_unref (conn);
3756
3757         ip4_dict = g_variant_lookup_value (conn_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
3758         g_assert (ip4_dict != NULL);
3759
3760         value = g_variant_lookup_value (ip4_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING);
3761         g_assert (value != NULL);
3762         g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "192.168.1.1");
3763         g_variant_unref (value);
3764
3765         value = g_variant_lookup_value (ip4_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE ("aau"));
3766         g_assert (value != NULL);
3767
3768         g_variant_iter_init (&iter, value);
3769         while (g_variant_iter_next (&iter, "@au", &addr_var)) {
3770                 const guint32 *addr_array;
3771                 gsize length;
3772
3773                 addr_array = g_variant_get_fixed_array (addr_var, &length, sizeof (guint32));
3774                 g_assert_cmpint (length, ==, 3);
3775                 g_assert_cmpstr (nm_utils_inet4_ntop (addr_array[2], NULL), ==, "192.168.1.1");
3776                 g_variant_unref (addr_var);
3777         }
3778         g_variant_unref (value);
3779
3780         g_variant_unref (ip4_dict);
3781
3782         /* When deserializing an old-style connection, the first non-0 gateway in
3783          * ipv4.addresses is copied to :gateway.
3784          */
3785         NMTST_VARIANT_EDITOR (conn_dict,
3786                               NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
3787                                                            NM_SETTING_IP_CONFIG_GATEWAY);
3788                               NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
3789                                                            "address-data");
3790                               );
3791
3792         conn = _connection_new_from_dbus (conn_dict, &error);
3793         g_assert_no_error (error);
3794
3795         s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn);
3796         g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1");
3797
3798         g_object_unref (conn);
3799
3800         /* Try again with the gateway in the second address. */
3801         g_variant_builder_init (&addrs_builder, G_VARIANT_TYPE ("aau"));
3802         g_variant_builder_add (&addrs_builder, "@au",
3803                                g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
3804                                                           addr_vals_0, 3, 4));
3805         g_variant_builder_add (&addrs_builder, "@au",
3806                                g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
3807                                                           addr_vals_1, 3, 4));
3808
3809         NMTST_VARIANT_EDITOR (conn_dict,
3810                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
3811                                                              "addresses", "aau", &addrs_builder);
3812                               );
3813
3814         conn = _connection_new_from_dbus (conn_dict, &error);
3815         g_assert_no_error (error);
3816         g_variant_unref (conn_dict);
3817
3818         s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn);
3819         g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1");
3820
3821         g_object_unref (conn);
3822 }
3823
3824 static void
3825 test_setting_ip6_gateway (void)
3826 {
3827         NMConnection *conn;
3828         NMSettingIPConfig *s_ip6;
3829         NMIPAddress *addr;
3830         GVariant *conn_dict, *ip6_dict, *value;
3831         GVariantIter iter;
3832         GVariant *gateway_var;
3833         GVariantBuilder addrs_builder;
3834         guint8 addr_bytes_0[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3835                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a };
3836         guint8 addr_bytes_1[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3837                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b };
3838         guint8 gateway_bytes_1[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3839                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
3840         GError *error = NULL;
3841
3842         /* When serializing on the daemon side, ipv6.gateway is copied to the first
3843          * entry of ipv6.addresses
3844          */
3845         conn = nmtst_create_minimal_connection ("test_setting_ip6_gateway", NULL,
3846                                                 NM_SETTING_WIRED_SETTING_NAME, NULL);
3847         s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
3848         g_object_set (s_ip6,
3849                       NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
3850                       NM_SETTING_IP_CONFIG_GATEWAY, "abcd::1",
3851                       NULL);
3852         nm_connection_add_setting (conn, NM_SETTING (s_ip6));
3853
3854         addr = nm_ip_address_new (AF_INET6, "abcd::10", 64, &error);
3855         g_assert_no_error (error);
3856         nm_setting_ip_config_add_address (s_ip6, addr);
3857         nm_ip_address_unref (addr);
3858
3859         _nm_utils_is_manager_process = TRUE;
3860         conn_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
3861         _nm_utils_is_manager_process = FALSE;
3862         g_object_unref (conn);
3863
3864         ip6_dict = g_variant_lookup_value (conn_dict, NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
3865         g_assert (ip6_dict != NULL);
3866
3867         value = g_variant_lookup_value (ip6_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING);
3868         g_assert (value != NULL);
3869         g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "abcd::1");
3870         g_variant_unref (value);
3871
3872         value = g_variant_lookup_value (ip6_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE ("a(ayuay)"));
3873         g_assert (value != NULL);
3874
3875         g_variant_iter_init (&iter, value);
3876         while (g_variant_iter_next (&iter, "(@ayu@ay)", NULL, NULL, &gateway_var)) {
3877                 const guint8 *gateway_bytes;
3878                 gsize length;
3879
3880                 gateway_bytes = g_variant_get_fixed_array (gateway_var, &length, 1);
3881                 g_assert_cmpint (length, ==, 16);
3882                 g_assert_cmpstr (nm_utils_inet6_ntop ((struct in6_addr *) gateway_bytes, NULL), ==, "abcd::1");
3883                 g_variant_unref (gateway_var);
3884         }
3885         g_variant_unref (value);
3886
3887         g_variant_unref (ip6_dict);
3888
3889         /* When deserializing an old-style connection, the first non-0 gateway in
3890          * ipv6.addresses is copied to :gateway.
3891          */
3892         NMTST_VARIANT_EDITOR (conn_dict,
3893                               NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
3894                                                            NM_SETTING_IP_CONFIG_GATEWAY);
3895                               NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
3896                                                            "address-data");
3897                               );
3898
3899         conn = _connection_new_from_dbus (conn_dict, &error);
3900         g_assert_no_error (error);
3901
3902         s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn);
3903         g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd::1");
3904
3905         g_object_unref (conn);
3906
3907         /* Try again with the gateway in the second address. */
3908         g_variant_builder_init (&addrs_builder, G_VARIANT_TYPE ("a(ayuay)"));
3909         g_variant_builder_add (&addrs_builder, "(@ayu@ay)",
3910                                g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
3911                                                           addr_bytes_0, 16, 1),
3912                                64,
3913                                g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
3914                                                           &in6addr_any, 16, 1));
3915         g_variant_builder_add (&addrs_builder, "(@ayu@ay)",
3916                                g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
3917                                                           addr_bytes_1, 16, 1),
3918                                64,
3919                                g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
3920                                                           gateway_bytes_1, 16, 1));
3921
3922         NMTST_VARIANT_EDITOR (conn_dict,
3923                               NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
3924                                                              "addresses", "a(ayuay)", &addrs_builder);
3925                               );
3926
3927         conn = _connection_new_from_dbus (conn_dict, &error);
3928         g_assert_no_error (error);
3929         g_variant_unref (conn_dict);
3930
3931         s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn);
3932         g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd::1");
3933
3934         g_object_unref (conn);
3935 }
3936
3937 typedef struct {
3938         const char *str;
3939         const guint8 expected[20];
3940         const guint expected_len;
3941 } HexItem;
3942
3943 static void
3944 test_setting_compare_default_strv (void)
3945 {
3946         gs_unref_object NMConnection *c1 = NULL, *c2 = NULL;
3947         char **strv;
3948         NMSettingIPConfig *s_ip2, *s_ip1;
3949         gboolean compare;
3950         GHashTable *out_settings = NULL;
3951
3952         c1 = nmtst_create_minimal_connection ("test_compare_default_strv", NULL,
3953                                               NM_SETTING_WIRED_SETTING_NAME, NULL);
3954         nmtst_assert_connection_verifies_and_normalizable (c1);
3955         nmtst_connection_normalize (c1);
3956
3957         c2 = nm_simple_connection_new_clone (c1);
3958         nmtst_assert_connection_verifies_without_normalization (c2);
3959
3960         nmtst_assert_connection_equals (c1, FALSE, c2, FALSE);
3961
3962         s_ip1 = nm_connection_get_setting_ip4_config (c1);
3963         s_ip2 = nm_connection_get_setting_ip4_config (c2);
3964
3965         nm_setting_ip_config_clear_dns_options (s_ip2, FALSE);
3966         g_object_get (G_OBJECT (s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL);
3967         g_assert (!strv);
3968         nmtst_assert_connection_equals (c1, FALSE, c2, FALSE);
3969
3970         nm_setting_ip_config_clear_dns_options (s_ip2, TRUE);
3971         g_object_get (G_OBJECT (s_ip2), NM_SETTING_IP_CONFIG_DNS_OPTIONS, &strv, NULL);
3972         g_assert (strv && !strv[0]);
3973         g_strfreev (strv);
3974
3975         compare = nm_setting_diff ((NMSetting *) s_ip1, (NMSetting *) s_ip2, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, &out_settings);
3976         g_assert (!compare);
3977         g_assert (out_settings);
3978         g_assert (g_hash_table_contains (out_settings, NM_SETTING_IP_CONFIG_DNS_OPTIONS));
3979         g_hash_table_unref (out_settings);
3980         out_settings = NULL;
3981
3982         compare = nm_connection_diff (c1, c2, NM_SETTING_COMPARE_FLAG_EXACT, &out_settings);
3983         g_assert (!compare);
3984         g_assert (out_settings);
3985         g_hash_table_unref (out_settings);
3986         out_settings = NULL;
3987 }
3988
3989 static void
3990 test_hexstr2bin (void)
3991 {
3992         static const HexItem items[] = {
3993                 { "aaBBCCddDD10496a",     { 0xaa, 0xbb, 0xcc, 0xdd, 0xdd, 0x10, 0x49, 0x6a }, 8 },
3994                 { "aa:bb:cc:dd:10:49:6a", { 0xaa, 0xbb, 0xcc, 0xdd, 0x10, 0x49, 0x6a },       7 },
3995                 { "0xccddeeff",           { 0xcc, 0xdd, 0xee, 0xff },                         4 },
3996                 { "1:2:66:77:80",         { 0x01, 0x02, 0x66, 0x77, 0x80 },                   5 },
3997                 { "e",                    { 0x0e },                                           1 },
3998                 { "aabb1199:" },
3999                 { ":aabb1199" },
4000                 { "aabb$$dd" },
4001                 { "aab:ccc:ddd" },
4002                 { "aab::ccc:ddd" },
4003         };
4004         GBytes *b;
4005         guint i;
4006
4007         for (i = 0; i < G_N_ELEMENTS (items); i++) {
4008                 b = nm_utils_hexstr2bin (items[i].str);
4009                 if (items[i].expected_len) {
4010                         g_assert (b);
4011                         g_assert_cmpint (g_bytes_get_size (b), ==, items[i].expected_len);
4012                         g_assert (memcmp (g_bytes_get_data (b, NULL), items[i].expected, g_bytes_get_size (b)) == 0);
4013                         g_bytes_unref (b);
4014                 } else
4015                         g_assert (b == NULL);
4016         }
4017 }
4018
4019 /******************************************************************************/
4020
4021 #define UUID_NIL        "00000000-0000-0000-0000-000000000000"
4022 #define UUID_NS_DNS     "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
4023
4024 static void
4025 _test_uuid (int uuid_type, const char *expected_uuid, const char *str, gssize slen, gpointer type_args)
4026 {
4027         gs_free char *uuid_test = NULL;
4028
4029         uuid_test = nm_utils_uuid_generate_from_string (str, slen, uuid_type, type_args);
4030
4031         g_assert (uuid_test);
4032         g_assert (nm_utils_is_uuid (uuid_test));
4033
4034         if (strcmp (uuid_test, expected_uuid)) {
4035                 g_error ("UUID test failed: type=%d; text=%s, len=%lld, uuid=%s, expected=%s", uuid_type,
4036                          str, (long long) slen, uuid_test, expected_uuid);
4037         }
4038
4039         if (slen < 0) {
4040                 /* also test that passing slen==-1 yields the same result as passing strlen(str). */
4041                 _test_uuid (uuid_type, expected_uuid, str, strlen (str), type_args);
4042         } else if (str && slen == 0) {
4043                 /* also test if we accept NULL for slen==0 */
4044                 _test_uuid (uuid_type, expected_uuid, NULL, 0, type_args);
4045         }
4046
4047         if (uuid_type == NM_UTILS_UUID_TYPE_VARIANT3 && !type_args) {
4048                 /* For NM_UTILS_UUID_TYPE_VARIANT3, a missing @type_args is equal to UUID_NIL */
4049                 _test_uuid (uuid_type, expected_uuid, str, slen, UUID_NIL);
4050         }
4051 }
4052
4053 static void
4054 test_nm_utils_uuid_generate_from_string (void)
4055 {
4056         _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "d41d8cd9-8f00-b204-e980-0998ecf8427e", "", -1, NULL);
4057         _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "0cc175b9-c0f1-b6a8-31c3-99e269772661", "a", -1, NULL);
4058         _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "098f6bcd-4621-d373-cade-4e832627b4f6", "test", -1, NULL);
4059         _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "70350f60-27bc-e371-3f6b-76473084309b", "a\0b", 3, NULL);
4060         _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "59c0547b-7fe2-1c15-2cce-e328e8bf6742", "/etc/NetworkManager/system-connections/em1", -1, NULL);
4061
4062         _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "4ae71336-e44b-39bf-b9d2-752e234818a5", "", -1, NULL);
4063         _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "0531103a-d8fc-3dd4-b972-d98e4750994e", "a", -1, NULL);
4064         _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "96e17d7a-ac89-38cf-95e1-bf5098da34e1", "test", -1, NULL);
4065         _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "8156568e-4ae6-3f34-a93e-18e2c6cbbf78", "a\0b", 3, NULL);
4066
4067         _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "c87ee674-4ddc-3efe-a74e-dfe25da5d7b3", "", -1, UUID_NS_DNS);
4068         _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "4c104dd0-4821-30d5-9ce3-0e7a1f8b7c0d", "a", -1, UUID_NS_DNS);
4069         _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "45a113ac-c7f2-30b0-90a5-a399ab912716", "test", -1, UUID_NS_DNS);
4070         _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "002a0ada-f547-375a-bab5-896a11d1927e", "a\0b", 3, UUID_NS_DNS);
4071 }
4072
4073 /*******************************************/
4074
4075 static void
4076 __test_uuid (const char *expected_uuid, const char *str, gssize slen, char *uuid_test)
4077 {
4078         g_assert (uuid_test);
4079         g_assert (nm_utils_is_uuid (uuid_test));
4080
4081         if (strcmp (uuid_test, expected_uuid)) {
4082                 g_error ("UUID test failed (1): text=%s, len=%lld, expected=%s, uuid_test=%s",
4083                          str, (long long) slen, expected_uuid, uuid_test);
4084         }
4085         g_free (uuid_test);
4086
4087         uuid_test = nm_utils_uuid_generate_from_string (str, slen, NM_UTILS_UUID_TYPE_VARIANT3, NM_UTILS_UUID_NS);
4088
4089         g_assert (uuid_test);
4090         g_assert (nm_utils_is_uuid (uuid_test));
4091
4092         if (strcmp (uuid_test, expected_uuid)) {
4093                 g_error ("UUID test failed (2): text=%s; len=%lld, expected=%s, uuid2=%s",
4094                          str, (long long) slen, expected_uuid, uuid_test);
4095         }
4096         g_free (uuid_test);
4097 }
4098
4099 #define _test_uuid(expected_uuid, str, strlen, ...) __test_uuid (expected_uuid, str, strlen, _nm_utils_uuid_generate_from_strings(__VA_ARGS__, NULL))
4100
4101 static void
4102 test_nm_utils_uuid_generate_from_strings (void)
4103 {
4104         _test_uuid ("b07c334a-399b-32de-8d50-58e4e08f98e3", "",         0, NULL);
4105         _test_uuid ("b8a426cb-bcb5-30a3-bd8f-6786fea72df9", "\0",       1, "");
4106         _test_uuid ("12a4a982-7aae-39e1-951e-41aeb1250959", "a\0",      2, "a");
4107         _test_uuid ("69e22c7e-f89f-3a43-b239-1cb52ed8db69", "aa\0",     3, "aa");
4108         _test_uuid ("59829fd3-5ad5-3d90-a7b0-4911747e4088", "\0\0",     2, "",   "");
4109         _test_uuid ("01ad0e06-6c50-3384-8d86-ddab81421425", "a\0\0",    3, "a",  "");
4110         _test_uuid ("e1ed8647-9ed3-3ec8-8c6d-e8204524d71d", "aa\0\0",   4, "aa", "");
4111         _test_uuid ("fb1c7cd6-275c-3489-9382-83b900da8af0", "\0a\0",    3, "",   "a");
4112         _test_uuid ("5d79494e-c4ba-31a6-80a2-d6016ccd7e17", "a\0a\0",   4, "a",  "a");
4113         _test_uuid ("fd698d86-1b60-3ebe-855f-7aada9950a8d", "aa\0a\0",  5, "aa", "a");
4114         _test_uuid ("8c573b48-0f01-30ba-bb94-c5f59f4fe517", "\0aa\0",   4, "",   "aa");
4115         _test_uuid ("2bdd3d46-eb83-3c53-a41b-a724d04b5544", "a\0aa\0",  5, "a",  "aa");
4116         _test_uuid ("13d4b780-07c1-3ba7-b449-81c4844ef039", "aa\0aa\0", 6, "aa", "aa");
4117         _test_uuid ("dd265bf7-c05a-3037-9939-b9629858a477", "a\0b\0",   4, "a",  "b");
4118 }
4119
4120 /******************************************************************************/
4121
4122 static void
4123 test_nm_utils_ascii_str_to_int64_check (const char *str, guint base, gint64 min,
4124                                         gint64 max, gint64 fallback, int exp_errno,
4125                                         gint64 exp_val)
4126 {
4127         gint64 v;
4128
4129         errno = 1;
4130         v = _nm_utils_ascii_str_to_int64 (str, base, min, max, fallback);
4131         g_assert_cmpint (errno, ==, exp_errno);
4132         g_assert_cmpint (v, ==, exp_val);
4133 }
4134
4135 static void
4136 test_nm_utils_ascii_str_to_int64_do (const char *str, guint base, gint64 min,
4137                                      gint64 max, gint64 fallback, int exp_errno,
4138                                      gint64 exp_val)
4139 {
4140         const char *sign = "";
4141         const char *val;
4142         static const char *whitespaces[] = {
4143                 "",
4144                 " ",
4145                 "\r\n\t",
4146                 " \r\n\t ",
4147                 " \r\n\t \t\r\n\t",
4148                 NULL,
4149         };
4150         static const char *nulls[] = {
4151                 "",
4152                 "0",
4153                 "00",
4154                 "0000",
4155                 "0000000000000000",
4156                 "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
4157                 "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
4158                 NULL,
4159         };
4160         const char **ws_pre, **ws_post, **null;
4161         guint i;
4162
4163         if (str == NULL || exp_errno != 0) {
4164                 test_nm_utils_ascii_str_to_int64_check (str, base, min, max, fallback, exp_errno, exp_val);
4165                 return;
4166         }
4167
4168         if (strncmp (str, "-", 1) == 0)
4169                 sign = "-";
4170
4171         val = str + strlen (sign);
4172
4173         for (ws_pre = whitespaces; *ws_pre; ws_pre++) {
4174                 for (ws_post = whitespaces; *ws_post; ws_post++) {
4175                         for (null = nulls; *null; null++) {
4176                                 for (i = 0; ; i++) {
4177                                         char *s;
4178                                         const char *str_base = "";
4179
4180                                         if (base == 16) {
4181                                                 if (i == 1)
4182                                                         str_base = "0x";
4183                                                 else if (i > 1)
4184                                                         break;
4185                                         } else if (base == 8) {
4186                                                 if (i == 1)
4187                                                         str_base = "0";
4188                                                 else if (i > 1)
4189                                                         break;
4190                                         } else if (base == 0) {
4191                                                 if (i > 0)
4192                                                         break;
4193                                                 /* with base==0, a leading zero would be interpreted as octal. Only test without *null */
4194                                                 if ((*null)[0])
4195                                                         break;
4196                                         } else {
4197                                                 if (i > 0)
4198                                                         break;
4199                                         }
4200
4201                                         s = g_strdup_printf ("%s%s%s%s%s%s", *ws_pre, sign, str_base, *null, val, *ws_post);
4202
4203                                         test_nm_utils_ascii_str_to_int64_check (s, base, min, max, fallback, exp_errno, exp_val);
4204                                         g_free (s);
4205                                 }
4206                         }
4207                 }
4208         }
4209 }
4210
4211 static void
4212 test_nm_utils_ascii_str_to_int64 (void)
4213 {
4214         test_nm_utils_ascii_str_to_int64_do (NULL, 10, 0, 10000, -1, EINVAL, -1);
4215         test_nm_utils_ascii_str_to_int64_do ("", 10, 0, 10000, -1, EINVAL, -1);
4216         test_nm_utils_ascii_str_to_int64_do ("1x", 10, 0, 10000, -1, EINVAL, -1);
4217         test_nm_utils_ascii_str_to_int64_do ("4711", 10, 0, 10000, -1, 0, 4711);
4218         test_nm_utils_ascii_str_to_int64_do ("10000", 10, 0, 10000, -1, 0, 10000);
4219         test_nm_utils_ascii_str_to_int64_do ("10001", 10, 0, 10000, -1, ERANGE, -1);
4220         test_nm_utils_ascii_str_to_int64_do ("FF", 16, 0, 10000, -1, 0, 255);
4221         test_nm_utils_ascii_str_to_int64_do ("FF", 10, 0, 10000, -2, EINVAL, -2);
4222         test_nm_utils_ascii_str_to_int64_do ("9223372036854775807", 10, 0, G_MAXINT64, -2, 0, G_MAXINT64);
4223         test_nm_utils_ascii_str_to_int64_do ("7FFFFFFFFFFFFFFF", 16, 0, G_MAXINT64, -2, 0, G_MAXINT64);
4224         test_nm_utils_ascii_str_to_int64_do ("9223372036854775808", 10, 0, G_MAXINT64, -2, ERANGE, -2);
4225         test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64, 0, -2, 0, G_MININT64);
4226         test_nm_utils_ascii_str_to_int64_do ("-9223372036854775808", 10, G_MININT64+1, 0, -2, ERANGE, -2);
4227         test_nm_utils_ascii_str_to_int64_do ("-9223372036854775809", 10, G_MININT64, 0, -2, ERANGE, -2);
4228         test_nm_utils_ascii_str_to_int64_do ("1.0", 10, 1, 1, -1, EINVAL, -1);
4229         test_nm_utils_ascii_str_to_int64_do ("1x0", 16, -10, 10, -100, EINVAL, -100);
4230         test_nm_utils_ascii_str_to_int64_do ("0", 16, -10, 10, -100, 0, 0);
4231         test_nm_utils_ascii_str_to_int64_do ("10001111", 2, -1000, 1000, -100000, 0, 0x8F);
4232         test_nm_utils_ascii_str_to_int64_do ("-10001111", 2, -1000, 1000, -100000, 0, -0x8F);
4233         test_nm_utils_ascii_str_to_int64_do ("1111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7F);
4234         test_nm_utils_ascii_str_to_int64_do ("111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFF);
4235         test_nm_utils_ascii_str_to_int64_do ("11111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFF);
4236         test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111", 2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
4237         test_nm_utils_ascii_str_to_int64_do ("100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0,  0x4000000000000000);
4238         test_nm_utils_ascii_str_to_int64_do ("1000000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, ERANGE, -1);
4239         test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000", 2, G_MININT64, G_MAXINT64, -1, 0,  -0x4000000000000000);
4240         test_nm_utils_ascii_str_to_int64_do ("111111111111111111111111111111111111111111111111111111111111111",  2, G_MININT64, G_MAXINT64, -1, 0, 0x7FFFFFFFFFFFFFFF);
4241         test_nm_utils_ascii_str_to_int64_do ("-100000000000000000000000000000000000000000000000000000000000000",  2, G_MININT64, G_MAXINT64, -1, 0,  -0x4000000000000000);
4242         test_nm_utils_ascii_str_to_int64_do ("0x70",  10, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
4243         test_nm_utils_ascii_str_to_int64_do ("4711",  0, G_MININT64, G_MAXINT64, -1, 0, 4711);
4244         test_nm_utils_ascii_str_to_int64_do ("04711",  0, G_MININT64, G_MAXINT64, -1, 0, 04711);
4245         test_nm_utils_ascii_str_to_int64_do ("0x4711",  0, G_MININT64, G_MAXINT64, -1, 0, 0x4711);
4246         test_nm_utils_ascii_str_to_int64_do ("080",  0, G_MININT64, G_MAXINT64, -1, EINVAL, -1);
4247         test_nm_utils_ascii_str_to_int64_do ("070",  0, G_MININT64, G_MAXINT64, -1, 0, 7*8);
4248         test_nm_utils_ascii_str_to_int64_do ("0x70",  0, G_MININT64, G_MAXINT64, -1, 0, 0x70);
4249 }
4250
4251 /******************************************************************************/
4252
4253 static void
4254 test_nm_utils_strstrdictkey (void)
4255 {
4256 #define _VALUES_STATIC(_v1, _v2) { .v1 = _v1, .v2 = _v2, .v_static = _nm_utils_strstrdictkey_static (_v1, _v2), }
4257         const struct {
4258                 const char *v1;
4259                 const char *v2;
4260                 NMUtilsStrStrDictKey *v_static;
4261         } *val1, *val2, values[] = {
4262                 { NULL, NULL },
4263                 { "", NULL },
4264                 { NULL, "" },
4265                 { "a", NULL },
4266                 { NULL, "a" },
4267                 _VALUES_STATIC ("", ""),
4268                 _VALUES_STATIC ("a", ""),
4269                 _VALUES_STATIC ("", "a"),
4270                 _VALUES_STATIC ("a", "b"),
4271         };
4272         guint i, j;
4273
4274         for (i = 0; i < G_N_ELEMENTS (values); i++) {
4275                 gs_free NMUtilsStrStrDictKey *key1 = NULL;
4276
4277                 val1 = &values[i];
4278
4279                 key1 = _nm_utils_strstrdictkey_create (val1->v1, val1->v2);
4280                 if (val1->v_static) {
4281                         g_assert (_nm_utils_strstrdictkey_equal (key1, val1->v_static));
4282                         g_assert (_nm_utils_strstrdictkey_equal (val1->v_static, key1));
4283                         g_assert_cmpint (_nm_utils_strstrdictkey_hash (key1), ==, _nm_utils_strstrdictkey_hash (val1->v_static));
4284                 }
4285
4286                 for (j = 0; j < G_N_ELEMENTS (values); j++) {
4287                         gs_free NMUtilsStrStrDictKey *key2 = NULL;
4288
4289                         val2 = &values[j];
4290                         key2 = _nm_utils_strstrdictkey_create (val2->v1, val2->v2);
4291                         if (i != j) {
4292                                 g_assert (!_nm_utils_strstrdictkey_equal (key1, key2));
4293                                 g_assert (!_nm_utils_strstrdictkey_equal (key2, key1));
4294                         }
4295                 }
4296         }
4297 }
4298
4299 /******************************************************************************/
4300
4301 static void
4302 test_nm_utils_dns_option_validate_do (char *option, gboolean ipv6, const NMUtilsDNSOptionDesc *descs,
4303                                       gboolean exp_result, char *exp_name, gboolean exp_value)
4304 {
4305         char *name;
4306         long value = 0;
4307         gboolean result;
4308
4309         result = _nm_utils_dns_option_validate (option, &name, &value, ipv6, descs);
4310
4311         g_assert (result == exp_result);
4312         g_assert_cmpstr (name, ==, exp_name);
4313         g_assert (value == exp_value);
4314
4315         g_free (name);
4316 }
4317
4318 static const NMUtilsDNSOptionDesc opt_descs[] = {
4319         /* name                   num      ipv6 */
4320         { "opt1",                 FALSE,   FALSE },
4321         { "opt2",                 TRUE,    FALSE },
4322         { "opt3",                 FALSE,   TRUE  },
4323         { "opt4",                 TRUE,    TRUE  },
4324         { NULL,                   FALSE,   FALSE }
4325 };
4326
4327 static void
4328 test_nm_utils_dns_option_validate (void)
4329 {
4330         /*                                    opt            ipv6    descs        result name       value */
4331         test_nm_utils_dns_option_validate_do ("",            FALSE,  NULL,        FALSE, NULL,      -1);
4332         test_nm_utils_dns_option_validate_do (":",           FALSE,  NULL,        FALSE, NULL,      -1);
4333         test_nm_utils_dns_option_validate_do (":1",          FALSE,  NULL,        FALSE, NULL,      -1);
4334         test_nm_utils_dns_option_validate_do (":val",        FALSE,  NULL,        FALSE, NULL,      -1);
4335         test_nm_utils_dns_option_validate_do ("opt",         FALSE,  NULL,        TRUE,  "opt",     -1);
4336         test_nm_utils_dns_option_validate_do ("opt:",        FALSE,  NULL,        FALSE, NULL,      -1);
4337         test_nm_utils_dns_option_validate_do ("opt:12",      FALSE,  NULL,        TRUE,  "opt",     12);
4338         test_nm_utils_dns_option_validate_do ("opt:12 ",     FALSE,  NULL,        FALSE, NULL,      -1);
4339         test_nm_utils_dns_option_validate_do ("opt:val",     FALSE,  NULL,        FALSE, NULL,      -1);
4340         test_nm_utils_dns_option_validate_do ("opt:2val",    FALSE,  NULL,        FALSE, NULL,      -1);
4341         test_nm_utils_dns_option_validate_do ("opt:2:3",     FALSE,  NULL,        FALSE, NULL,      -1);
4342         test_nm_utils_dns_option_validate_do ("opt-6",       FALSE,  NULL,        TRUE,  "opt-6",   -1);
4343
4344         test_nm_utils_dns_option_validate_do ("opt1",        FALSE,  opt_descs,   TRUE,  "opt1",    -1);
4345         test_nm_utils_dns_option_validate_do ("opt1",        TRUE,   opt_descs,   TRUE,  "opt1",    -1);
4346         test_nm_utils_dns_option_validate_do ("opt1:3",      FALSE,  opt_descs,   FALSE,  NULL,     -1);
4347
4348         test_nm_utils_dns_option_validate_do ("opt2",        FALSE,  opt_descs,   FALSE, NULL,      -1);
4349         test_nm_utils_dns_option_validate_do ("opt2:5",      FALSE,  opt_descs,   TRUE,  "opt2",    5);
4350
4351         test_nm_utils_dns_option_validate_do ("opt3",        FALSE,  opt_descs,   FALSE, NULL,      -1);
4352         test_nm_utils_dns_option_validate_do ("opt3",        TRUE,   opt_descs,   TRUE,  "opt3",    -1);
4353
4354         test_nm_utils_dns_option_validate_do ("opt4",        FALSE,  opt_descs,   FALSE, NULL,      -1);
4355         test_nm_utils_dns_option_validate_do ("opt4",        TRUE,   opt_descs,   FALSE, NULL,      -1);
4356         test_nm_utils_dns_option_validate_do ("opt4:40",     FALSE,  opt_descs,   FALSE, NULL,      -1);
4357         test_nm_utils_dns_option_validate_do ("opt4:40",     TRUE,   opt_descs,   TRUE,  "opt4",    40);
4358 }
4359
4360 static void
4361 test_nm_utils_dns_option_find_idx (void)
4362 {
4363         GPtrArray *options;
4364
4365         options = g_ptr_array_new ();
4366
4367         g_ptr_array_add (options, "debug");
4368         g_ptr_array_add (options, "timeout:5");
4369         g_ptr_array_add (options, "edns0");
4370
4371         g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "debug"),      ==, 0);
4372         g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "debug:1"),    ==, 0);
4373         g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "timeout"),    ==, 1);
4374         g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "timeout:5"),  ==, 1);
4375         g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "timeout:2"),  ==, 1);
4376         g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "edns0"),      ==, 2);
4377         g_assert_cmpint (_nm_utils_dns_option_find_idx (options, "rotate"),     ==, -1);
4378         g_assert_cmpint (_nm_utils_dns_option_find_idx (options, ""),           ==, -1);
4379
4380         g_ptr_array_free (options, TRUE);
4381 }
4382
4383 /******************************************************************************/
4384
4385 enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED {
4386         _DUMMY_1 = -1,
4387 };
4388
4389 enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED {
4390         _DUMMY_2,
4391 };
4392
4393 enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64 {
4394         _DUMMY_3 = (1LL << 40),
4395 };
4396
4397 enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64 {
4398         _DUMMY_4a = -1,
4399         _DUMMY_4b = (1LL << 40),
4400 };
4401
4402 #define test_nm_utils_is_power_of_two_do(type, x, expect) \
4403         G_STMT_START { \
4404                 typeof (x) x1 = (x); \
4405                 type x2 = (type) x1; \
4406                 \
4407                 if (((typeof (x1)) x2) == x1 && (x2 > 0 || x2 == 0)) { \
4408                         /* x2 equals @x, and is positive. Compare to @expect */ \
4409                         g_assert_cmpint (expect, ==, nm_utils_is_power_of_two (x2)); \
4410                 } else if (!(x2 > 0) && !(x2 == 0)) { \
4411                         /* a (signed) negative value is always FALSE. */ \
4412                         g_assert_cmpint (FALSE, ==, nm_utils_is_power_of_two (x2));\
4413                 } \
4414                 g_assert_cmpint (expect, ==, nm_utils_is_power_of_two (x1)); \
4415         } G_STMT_END
4416
4417 static void
4418 test_nm_utils_is_power_of_two (void)
4419 {
4420         guint64 xyes, xno;
4421         gint i, j;
4422         GRand *rand = nmtst_get_rand ();
4423         int numbits;
4424
4425         for (i = -1; i < 64; i++) {
4426
4427                 /* find a (positive) x which is a power of two. */
4428                 if (i == -1)
4429                         xyes = 0;
4430                 else {
4431                         xyes = (1LL << i);
4432                         g_assert (xyes != 0);
4433                 }
4434
4435                 xno = xyes;
4436                 if (xyes != 0) {
4437 again:
4438                         /* Find another @xno, that is not a power of two. Do that,
4439                          * by randomly setting bits. */
4440                         numbits = g_rand_int_range (rand, 1, 65);
4441                         while (xno != ~((guint64) 0) && numbits > 0) {
4442                                 guint64 v = (1LL << g_rand_int_range (rand, 0, 64));
4443
4444                                 if ((xno | v) != xno) {
4445                                         xno |= v;
4446                                         --numbits;
4447                                 }
4448                         }
4449                         if (xno == xyes)
4450                                 goto again;
4451                 }
4452
4453                 for (j = 0; j < 2; j++) {
4454                         gboolean expect = j == 0;
4455                         guint64 x = expect ? xyes : xno;
4456
4457                         if (!expect && xno == 0)
4458                                 continue;
4459
4460                         /* check if @x is as @expect, when casted to a certain data type. */
4461                         test_nm_utils_is_power_of_two_do (gint8, x, expect);
4462                         test_nm_utils_is_power_of_two_do (guint8, x, expect);
4463                         test_nm_utils_is_power_of_two_do (gint16, x, expect);
4464                         test_nm_utils_is_power_of_two_do (guint16, x, expect);
4465                         test_nm_utils_is_power_of_two_do (gint32, x, expect);
4466                         test_nm_utils_is_power_of_two_do (guint32, x, expect);
4467                         test_nm_utils_is_power_of_two_do (gint64, x, expect);
4468                         test_nm_utils_is_power_of_two_do (guint64, x, expect);
4469                         test_nm_utils_is_power_of_two_do (char, x, expect);
4470                         test_nm_utils_is_power_of_two_do (unsigned char, x, expect);
4471                         test_nm_utils_is_power_of_two_do (signed char, x, expect);
4472                         test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED, x, expect);
4473                         test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED, x, expect);
4474                         test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_SIGNED_64, x, expect);
4475                         test_nm_utils_is_power_of_two_do (enum TEST_IS_POWER_OF_TWP_ENUM_UNSIGNED_64, x, expect);
4476                 }
4477         }
4478 }
4479
4480 /******************************************************************************/
4481
4482 static void
4483 test_g_ptr_array_insert (void)
4484 {
4485         /* this test only makes sense on a recent glib, where we compare our compat
4486          * with the original implementation. */
4487 #if GLIB_CHECK_VERSION(2, 40, 0)
4488         gs_unref_ptrarray GPtrArray *arr1 = g_ptr_array_new ();
4489         gs_unref_ptrarray GPtrArray *arr2 = g_ptr_array_new ();
4490         GRand *rand = nmtst_get_rand ();
4491         guint i;
4492
4493         for (i = 0; i < 560; i++) {
4494                 gint32 idx = g_rand_int_range (rand, -1, arr1->len + 1);
4495
4496                 g_ptr_array_insert (arr1, idx, GINT_TO_POINTER (i));
4497                 _nm_g_ptr_array_insert (arr2, idx, GINT_TO_POINTER (i));
4498
4499                 g_assert_cmpint (arr1->len, ==, arr2->len);
4500                 g_assert (memcmp (arr1->pdata, arr2->pdata, arr1->len * sizeof (gpointer)) == 0);
4501         }
4502 #endif
4503 }
4504
4505 /******************************************************************************/
4506
4507 static void
4508 test_g_hash_table_get_keys_as_array (void)
4509 {
4510         GHashTable *table = g_hash_table_new (g_str_hash, g_str_equal);
4511         guint length = 0;
4512         char **keys;
4513
4514         g_hash_table_insert (table, "one",   "1");
4515         g_hash_table_insert (table, "two",   "2");
4516         g_hash_table_insert (table, "three", "3");
4517
4518         keys = (char **) _nm_g_hash_table_get_keys_as_array (table, &length);
4519         g_assert (keys);
4520         g_assert_cmpuint (length, ==, 3);
4521
4522         g_assert (   !strcmp (keys[0], "one")
4523                   || !strcmp (keys[1], "one")
4524                   || !strcmp (keys[2], "one"));
4525
4526         g_assert (   !strcmp (keys[0], "two")
4527                   || !strcmp (keys[1], "two")
4528                   || !strcmp (keys[2], "two"));
4529
4530         g_assert (   !strcmp (keys[0], "three")
4531                   || !strcmp (keys[1], "three")
4532                   || !strcmp (keys[2], "three"));
4533
4534         g_assert (!keys[3]);
4535
4536         g_free (keys);
4537         g_hash_table_unref (table);
4538 }
4539
4540 /******************************************************************************/
4541
4542 static int
4543 _test_find_binary_search_cmp (gconstpointer a, gconstpointer b, gpointer dummy)
4544 {
4545         int ia, ib;
4546
4547         ia = GPOINTER_TO_INT (a);
4548         ib = GPOINTER_TO_INT (b);
4549
4550         if (ia == ib)
4551                 return 0;
4552         if (ia < ib)
4553                 return -1;
4554         return 1;
4555 }
4556
4557 static void
4558 _test_find_binary_search_do (const int *array, gsize len)
4559 {
4560         gsize i;
4561         gssize idx;
4562         gs_free gpointer *parray = g_new (gpointer, len);
4563         const int needle = 0;
4564         gpointer pneedle = GINT_TO_POINTER (needle);
4565         gssize expected_result;
4566
4567         for (i = 0; i < len; i++)
4568                 parray[i] = GINT_TO_POINTER (array[i]);
4569
4570         expected_result = _nm_utils_ptrarray_find_first (parray, len, pneedle);
4571
4572         idx = _nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL);
4573         if (expected_result >= 0)
4574                 g_assert_cmpint (expected_result, ==, idx);
4575         else {
4576                 gssize idx2 = ~idx;
4577                 g_assert_cmpint (idx, <, 0);
4578
4579                 g_assert (idx2 >= 0);
4580                 g_assert (idx2 <= len);
4581                 g_assert (idx2 - 1 < 0 || _test_find_binary_search_cmp (parray[idx2 - 1], pneedle, NULL) < 0);
4582                 g_assert (idx2 >= len || _test_find_binary_search_cmp (parray[idx2], pneedle, NULL) > 0);
4583         }
4584         for (i = 0; i < len; i++) {
4585                 int cmp;
4586
4587                 cmp = _test_find_binary_search_cmp (parray[i], pneedle, NULL);
4588                 if (cmp == 0) {
4589                         g_assert (pneedle == parray[i]);
4590                         g_assert (idx >= 0);
4591                         g_assert (i == idx);
4592                 } else {
4593                         g_assert (pneedle != parray[i]);
4594                         if (cmp < 0) {
4595                                 if (idx < 0)
4596                                         g_assert (i < ~idx);
4597                                 else
4598                                         g_assert (i < idx);
4599                         } else {
4600                                 if (idx < 0)
4601                                         g_assert (i >= ~idx);
4602                                 else
4603                                         g_assert (i >= idx);
4604                         }
4605                 }
4606         }
4607 }
4608 #define test_find_binary_search_do(...) \
4609         G_STMT_START { \
4610                 const int _array[] = { __VA_ARGS__ } ; \
4611                 _test_find_binary_search_do (_array, G_N_ELEMENTS (_array)); \
4612         } G_STMT_END
4613
4614 static void
4615 test_nm_utils_ptrarray_find_binary_search (void)
4616 {
4617 #define _NOT(idx) (~ ((gssize) (idx)))
4618         test_find_binary_search_do (            0);
4619         test_find_binary_search_do (        -1, 0);
4620         test_find_binary_search_do (    -2, -1, 0);
4621         test_find_binary_search_do (-3, -2, -1, 0);
4622         test_find_binary_search_do (            0, 1);
4623         test_find_binary_search_do (            0, 1, 2);
4624         test_find_binary_search_do (        -1, 0, 1, 2);
4625         test_find_binary_search_do (    -2, -1, 0, 1, 2);
4626         test_find_binary_search_do (-3, -2, -1, 0, 1, 2);
4627         test_find_binary_search_do (-3, -2, -1, 0, 1, 2);
4628         test_find_binary_search_do (-3, -2, -1, 0, 1, 2, 3);
4629         test_find_binary_search_do (-3, -2, -1, 0, 1, 2, 3, 4);
4630
4631         test_find_binary_search_do (        -1);
4632         test_find_binary_search_do (    -2, -1);
4633         test_find_binary_search_do (-3, -2, -1);
4634         test_find_binary_search_do (            1);
4635         test_find_binary_search_do (            1, 2);
4636         test_find_binary_search_do (        -1, 1, 2);
4637         test_find_binary_search_do (    -2, -1, 1, 2);
4638         test_find_binary_search_do (-3, -2, -1, 1, 2);
4639         test_find_binary_search_do (-3, -2, -1, 1, 2);
4640         test_find_binary_search_do (-3, -2, -1, 1, 2, 3);
4641         test_find_binary_search_do (-3, -2, -1, 1, 2, 3, 4);
4642 }
4643
4644 /******************************************************************************/
4645 static void
4646 test_nm_utils_enum_from_str_do (GType type, const char *str,
4647                                 gboolean exp_result, int exp_flags,
4648                                 const char *exp_err_token)
4649 {
4650         int flags = 1;
4651         char *err_token = NULL;
4652         gboolean result;
4653
4654         result = nm_utils_enum_from_str (type, str, &flags, &err_token);
4655
4656         g_assert (result == exp_result);
4657         g_assert_cmpint (flags, ==, exp_flags);
4658         g_assert_cmpstr (err_token, ==, exp_err_token);
4659
4660         g_free (err_token);
4661 }
4662
4663 static void
4664 test_nm_utils_enum_to_str_do (GType type, int flags, const char *exp_str)
4665 {
4666         char *str;
4667
4668         str = nm_utils_enum_to_str (type, flags);
4669         g_assert_cmpstr (str, ==, exp_str);
4670         g_free (str);
4671 }
4672
4673 static void
4674 test_nm_utils_enum_get_values_do (GType type, int from, int to, const char *exp_str)
4675 {
4676         const char **strv;
4677         char *str;
4678
4679         strv = nm_utils_enum_get_values (type, from, to);
4680         g_assert (strv);
4681         str = g_strjoinv (",", (char **) strv);
4682         g_assert_cmpstr (str, ==, exp_str);
4683         g_free (str);
4684         g_free (strv);
4685 }
4686
4687
4688 static void test_nm_utils_enum (void)
4689 {
4690         GType bool_enum = nm_test_general_bool_enum_get_type();
4691         GType meta_flags = nm_test_general_meta_flags_get_type();
4692         GType color_flags = nm_test_general_color_flags_get_type();
4693
4694         test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, "yes");
4695         test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN, "unknown");
4696         test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_INVALID, NULL);
4697
4698         test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "");
4699         test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz");
4700         test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_FOO |
4701                                                   NM_TEST_GENERAL_META_FLAGS_BAR |
4702                                                   NM_TEST_GENERAL_META_FLAGS_BAZ, "foo, bar, baz");
4703
4704         test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED, "red");
4705         test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_WHITE, "");
4706         test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED |
4707                                                    NM_TEST_GENERAL_COLOR_FLAGS_GREEN, "red, green");
4708
4709         test_nm_utils_enum_from_str_do (bool_enum, "", FALSE, 0, NULL);
4710         test_nm_utils_enum_from_str_do (bool_enum, " ", FALSE, 0, NULL);
4711         test_nm_utils_enum_from_str_do (bool_enum, "invalid", FALSE, 0, NULL);
4712         test_nm_utils_enum_from_str_do (bool_enum, "yes", TRUE, NM_TEST_GENERAL_BOOL_ENUM_YES, NULL);
4713         test_nm_utils_enum_from_str_do (bool_enum, "no", TRUE, NM_TEST_GENERAL_BOOL_ENUM_NO, NULL);
4714         test_nm_utils_enum_from_str_do (bool_enum, "yes,no", FALSE, 0, NULL);
4715
4716         test_nm_utils_enum_from_str_do (meta_flags, "", TRUE, 0, NULL);
4717         test_nm_utils_enum_from_str_do (meta_flags, " ", TRUE, 0, NULL);
4718         test_nm_utils_enum_from_str_do (meta_flags, "foo", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO, NULL);
4719         test_nm_utils_enum_from_str_do (meta_flags, "foo,baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
4720                                                                      NM_TEST_GENERAL_META_FLAGS_BAZ, NULL);
4721         test_nm_utils_enum_from_str_do (meta_flags, "foo, baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
4722                                                                       NM_TEST_GENERAL_META_FLAGS_BAZ, NULL);
4723         test_nm_utils_enum_from_str_do (meta_flags, "foo,,bar", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
4724                                                                       NM_TEST_GENERAL_META_FLAGS_BAR, NULL);
4725         test_nm_utils_enum_from_str_do (meta_flags, "foo,baz,quux,bar", FALSE, 0, "quux");
4726
4727         test_nm_utils_enum_from_str_do (color_flags, "green", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_GREEN, NULL);
4728         test_nm_utils_enum_from_str_do (color_flags, "blue,red", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_BLUE |
4729                                                                        NM_TEST_GENERAL_COLOR_FLAGS_RED, NULL);
4730         test_nm_utils_enum_from_str_do (color_flags, "blue,white", FALSE, 0, "white");
4731
4732         test_nm_utils_enum_get_values_do (bool_enum, 0, G_MAXINT, "no,yes,maybe,unknown");
4733         test_nm_utils_enum_get_values_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES,
4734                                           NM_TEST_GENERAL_BOOL_ENUM_MAYBE, "yes,maybe");
4735         test_nm_utils_enum_get_values_do (meta_flags, 0, G_MAXINT, "none,foo,bar,baz");
4736         test_nm_utils_enum_get_values_do (color_flags, 0, G_MAXINT, "blue,red,green");
4737 }
4738
4739 /******************************************************************************/
4740
4741 static int
4742 _test_nm_in_set_get (int *call_counter, gboolean allow_called, int value)
4743 {
4744         g_assert (call_counter);
4745         *call_counter += 1;
4746         if (!allow_called)
4747                 g_assert_not_reached ();
4748         return value;
4749 }
4750
4751 static void
4752 _test_nm_in_set_assert (int *call_counter, int expected)
4753 {
4754         g_assert (call_counter);
4755         g_assert_cmpint (expected, ==, *call_counter);
4756         *call_counter = 0;
4757 }
4758
4759 static void
4760 test_nm_in_set (void)
4761 {
4762         int call_counter = 0;
4763
4764 #define G(x) _test_nm_in_set_get (&call_counter, TRUE,  x)
4765 #define N(x) _test_nm_in_set_get (&call_counter, FALSE,  x)
4766 #define _ASSERT(expected, expr) \
4767         G_STMT_START { \
4768                 _test_nm_in_set_assert (&call_counter, 0); \
4769                 g_assert (expr); \
4770                 _test_nm_in_set_assert (&call_counter, (expected)); \
4771         } G_STMT_END
4772         _ASSERT (1, !NM_IN_SET (-1, G( 1)));
4773         _ASSERT (1,  NM_IN_SET (-1, G(-1)));
4774
4775         _ASSERT (2, !NM_IN_SET (-1, G( 1), G( 2)));
4776         _ASSERT (1,  NM_IN_SET (-1, G(-1), N( 2)));
4777         _ASSERT (2,  NM_IN_SET (-1, G( 1), G(-1)));
4778         _ASSERT (1,  NM_IN_SET (-1, G(-1), N(-1)));
4779
4780         _ASSERT (3, !NM_IN_SET (-1, G( 1), G( 2), G( 3)));
4781         _ASSERT (1,  NM_IN_SET (-1, G(-1), N( 2), N( 3)));
4782         _ASSERT (2,  NM_IN_SET (-1, G( 1), G(-1), N( 3)));
4783         _ASSERT (3,  NM_IN_SET (-1, G( 1), G( 2), G(-1)));
4784         _ASSERT (2,  NM_IN_SET (-1, G( 1), G(-1), N(-1)));
4785         _ASSERT (1,  NM_IN_SET (-1, G(-1), N( 2), N(-1)));
4786         _ASSERT (1,  NM_IN_SET (-1, G(-1), N(-1), N( 3)));
4787         _ASSERT (1,  NM_IN_SET (-1, G(-1), N(-1), N(-1)));
4788
4789         _ASSERT (4, !NM_IN_SET (-1, G( 1), G( 2), G( 3), G( 4)));
4790         _ASSERT (1,  NM_IN_SET (-1, G(-1), N( 2), N( 3), N( 4)));
4791         _ASSERT (2,  NM_IN_SET (-1, G( 1), G(-1), N( 3), N( 4)));
4792         _ASSERT (3,  NM_IN_SET (-1, G( 1), G( 2), G(-1), N( 4)));
4793         _ASSERT (4,  NM_IN_SET (-1, G( 1), G( 2), G( 3), G(-1)));
4794
4795         _ASSERT (4,  NM_IN_SET (-1, G( 1), G( 2), G( 3), G(-1), G( 5)));
4796         _ASSERT (5,  NM_IN_SET (-1, G( 1), G( 2), G( 3), G( 4), G(-1)));
4797         _ASSERT (6,  NM_IN_SET (-1, G( 1), G( 2), G( 3), G( 4), G( 5), G( -1)));
4798
4799         _ASSERT (1, !NM_IN_SET_SE (-1, G( 1)));
4800         _ASSERT (1,  NM_IN_SET_SE (-1, G(-1)));
4801
4802         _ASSERT (2, !NM_IN_SET_SE (-1, G( 1), G( 2)));
4803         _ASSERT (2,  NM_IN_SET_SE (-1, G(-1), G( 2)));
4804         _ASSERT (2,  NM_IN_SET_SE (-1, G( 1), G(-1)));
4805         _ASSERT (2,  NM_IN_SET_SE (-1, G(-1), G(-1)));
4806
4807         _ASSERT (3, !NM_IN_SET_SE (-1, G( 1), G( 2), G( 3)));
4808         _ASSERT (3,  NM_IN_SET_SE (-1, G(-1), G( 2), G( 3)));
4809         _ASSERT (3,  NM_IN_SET_SE (-1, G( 1), G(-1), G( 3)));
4810         _ASSERT (3,  NM_IN_SET_SE (-1, G( 1), G( 2), G(-1)));
4811         _ASSERT (3,  NM_IN_SET_SE (-1, G( 1), G(-1), G(-1)));
4812         _ASSERT (3,  NM_IN_SET_SE (-1, G(-1), G( 2), G(-1)));
4813         _ASSERT (3,  NM_IN_SET_SE (-1, G(-1), G(-1), G( 3)));
4814         _ASSERT (3,  NM_IN_SET_SE (-1, G(-1), G(-1), G(-1)));
4815
4816         _ASSERT (4, !NM_IN_SET_SE (-1, G( 1), G( 2), G( 3), G( 4)));
4817         _ASSERT (4,  NM_IN_SET_SE (-1, G(-1), G( 2), G( 3), G( 4)));
4818         _ASSERT (4,  NM_IN_SET_SE (-1, G( 1), G(-1), G( 3), G( 4)));
4819         _ASSERT (4,  NM_IN_SET_SE (-1, G( 1), G( 2), G(-1), G( 4)));
4820         _ASSERT (4,  NM_IN_SET_SE (-1, G( 1), G( 2), G( 3), G(-1)));
4821
4822         _ASSERT (5,  NM_IN_SET_SE (-1, G( 1), G( 2), G( 3), G(-1), G( 5)));
4823         _ASSERT (6,  NM_IN_SET_SE (-1, G( 1), G( 2), G( 3), G( 4), G( 5), G(-1)));
4824 #undef G
4825 #undef N
4826 #undef _ASSERT
4827 }
4828
4829 /******************************************************************************/
4830
4831 static const char *
4832 _test_nm_in_set_getstr (int *call_counter, gboolean allow_called, const char *value)
4833 {
4834         g_assert (call_counter);
4835         *call_counter += 1;
4836         if (!allow_called)
4837                 g_assert_not_reached ();
4838         return value;
4839 }
4840
4841 static void
4842 test_nm_in_strset (void)
4843 {
4844         int call_counter = 0;
4845
4846 #define G(x) _test_nm_in_set_getstr (&call_counter, TRUE,  x)
4847 #define N(x) _test_nm_in_set_getstr (&call_counter, FALSE,  x)
4848 #define _ASSERT(expected, expr) \
4849         G_STMT_START { \
4850                 _test_nm_in_set_assert (&call_counter, 0); \
4851                 g_assert (expr); \
4852                 _test_nm_in_set_assert (&call_counter, (expected)); \
4853         } G_STMT_END
4854         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL)));
4855         _ASSERT (1, !NM_IN_STRSET ("a",  G(NULL)));
4856         _ASSERT (1, !NM_IN_STRSET (NULL, G("a")));
4857
4858         _ASSERT (1,  NM_IN_STRSET_SE (NULL, G(NULL)));
4859         _ASSERT (1, !NM_IN_STRSET_SE ("a",  G(NULL)));
4860         _ASSERT (1, !NM_IN_STRSET_SE (NULL, G("a")));
4861
4862         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N(NULL)));
4863         _ASSERT (2, !NM_IN_STRSET ("a",  G(NULL), G(NULL)));
4864         _ASSERT (2,  NM_IN_STRSET (NULL, G("a"),  G(NULL)));
4865         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N("a")));
4866         _ASSERT (2,  NM_IN_STRSET ("a",  G(NULL), G("a")));
4867         _ASSERT (2, !NM_IN_STRSET (NULL, G("a"),  G("a")));
4868         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N("b")));
4869         _ASSERT (2, !NM_IN_STRSET ("a",  G(NULL), G("b")));
4870         _ASSERT (2, !NM_IN_STRSET (NULL, G("a"),  G("b")));
4871
4872         _ASSERT (2,  NM_IN_STRSET_SE (NULL, G(NULL), G(NULL)));
4873         _ASSERT (2, !NM_IN_STRSET_SE ("a",  G(NULL), G(NULL)));
4874         _ASSERT (2,  NM_IN_STRSET_SE (NULL, G("a"),  G(NULL)));
4875         _ASSERT (2,  NM_IN_STRSET_SE (NULL, G(NULL), G("a")));
4876         _ASSERT (2,  NM_IN_STRSET_SE ("a",  G(NULL), G("a")));
4877         _ASSERT (2, !NM_IN_STRSET_SE (NULL, G("a"),  G("a")));
4878         _ASSERT (2,  NM_IN_STRSET_SE (NULL, G(NULL), G("b")));
4879         _ASSERT (2, !NM_IN_STRSET_SE ("a",  G(NULL), G("b")));
4880         _ASSERT (2, !NM_IN_STRSET_SE (NULL, G("a"),  G("b")));
4881
4882         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N(NULL), N(NULL)));
4883         _ASSERT (3, !NM_IN_STRSET ("a",  G(NULL), G(NULL), G(NULL)));
4884         _ASSERT (2,  NM_IN_STRSET (NULL, G("a"),  G(NULL), N(NULL)));
4885         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N("a"),  N(NULL)));
4886         _ASSERT (2,  NM_IN_STRSET ("a",  G(NULL), G("a"),  N(NULL)));
4887         _ASSERT (3,  NM_IN_STRSET (NULL, G("a"),  G("a"),  G(NULL)));
4888         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N("b"),  N(NULL)));
4889         _ASSERT (3, !NM_IN_STRSET ("a",  G(NULL), G("b"),  G(NULL)));
4890         _ASSERT (3,  NM_IN_STRSET (NULL, G("a"),  G("b"),  G(NULL)));
4891         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N(NULL), N("a")));
4892         _ASSERT (3,  NM_IN_STRSET ("a",  G(NULL), G(NULL), G("a")));
4893         _ASSERT (2,  NM_IN_STRSET (NULL, G("a"),  G(NULL), N("a")));
4894         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N("a"),  N("a")));
4895         _ASSERT (2,  NM_IN_STRSET ("a",  G(NULL), G("a"),  N("a")));
4896         _ASSERT (3, !NM_IN_STRSET (NULL, G("a"),  G("a"),  G("a")));
4897         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N("b"),  N("a")));
4898         _ASSERT (3,  NM_IN_STRSET ("a",  G(NULL), G("b"),  G("a")));
4899         _ASSERT (3, !NM_IN_STRSET (NULL, G("a"),  G("b"),  G("a")));
4900         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N(NULL), N("b")));
4901         _ASSERT (3, !NM_IN_STRSET ("a",  G(NULL), G(NULL), G("b")));
4902         _ASSERT (2,  NM_IN_STRSET (NULL, G("a"),  G(NULL), N("b")));
4903         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N("a"),  N("b")));
4904         _ASSERT (2,  NM_IN_STRSET ("a",  G(NULL), G("a"),  N("b")));
4905         _ASSERT (3, !NM_IN_STRSET (NULL, G("a"),  G("a"),  G("b")));
4906         _ASSERT (1,  NM_IN_STRSET (NULL, G(NULL), N("b"),  N("b")));
4907         _ASSERT (3, !NM_IN_STRSET ("a",  G(NULL), G("b"),  G("b")));
4908         _ASSERT (3, !NM_IN_STRSET (NULL, G("a"),  G("b"),  G("b")));
4909
4910         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G(NULL), G(NULL), G(NULL)));
4911         _ASSERT (3, !NM_IN_STRSET_SE ("a",  G(NULL), G(NULL), G(NULL)));
4912         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G("a"),  G(NULL), G(NULL)));
4913         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G(NULL), G("a"),  G(NULL)));
4914         _ASSERT (3,  NM_IN_STRSET_SE ("a",  G(NULL), G("a"),  G(NULL)));
4915         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G("a"),  G("a"),  G(NULL)));
4916         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G(NULL), G("b"),  G(NULL)));
4917         _ASSERT (3, !NM_IN_STRSET_SE ("a",  G(NULL), G("b"),  G(NULL)));
4918         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G("a"),  G("b"),  G(NULL)));
4919         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G(NULL), G(NULL), G("a")));
4920         _ASSERT (3,  NM_IN_STRSET_SE ("a",  G(NULL), G(NULL), G("a")));
4921         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G("a"),  G(NULL), G("a")));
4922         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G(NULL), G("a"),  G("a")));
4923         _ASSERT (3,  NM_IN_STRSET_SE ("a",  G(NULL), G("a"),  G("a")));
4924         _ASSERT (3, !NM_IN_STRSET_SE (NULL, G("a"),  G("a"),  G("a")));
4925         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G(NULL), G("b"),  G("a")));
4926         _ASSERT (3,  NM_IN_STRSET_SE ("a",  G(NULL), G("b"),  G("a")));
4927         _ASSERT (3, !NM_IN_STRSET_SE (NULL, G("a"),  G("b"),  G("a")));
4928         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G(NULL), G(NULL), G("b")));
4929         _ASSERT (3, !NM_IN_STRSET_SE ("a",  G(NULL), G(NULL), G("b")));
4930         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G("a"),  G(NULL), G("b")));
4931         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G(NULL), G("a"),  G("b")));
4932         _ASSERT (3,  NM_IN_STRSET_SE ("a",  G(NULL), G("a"),  G("b")));
4933         _ASSERT (3, !NM_IN_STRSET_SE (NULL, G("a"),  G("a"),  G("b")));
4934         _ASSERT (3,  NM_IN_STRSET_SE (NULL, G(NULL), G("b"),  G("b")));
4935         _ASSERT (3, !NM_IN_STRSET_SE ("a",  G(NULL), G("b"),  G("b")));
4936         _ASSERT (3, !NM_IN_STRSET_SE (NULL, G("a"),  G("b"),  G("b")));
4937
4938
4939         _ASSERT (3,  NM_IN_STRSET ("a",  G(NULL), G("b"),  G("a"),  N("a")));
4940         _ASSERT (4,  NM_IN_STRSET ("a",  G(NULL), G("b"),  G("c"),  G("a")));
4941         _ASSERT (4, !NM_IN_STRSET ("a",  G(NULL), G("b"),  G("c"),  G("d")));
4942
4943         _ASSERT (4,  NM_IN_STRSET ("a",  G(NULL), G("b"),  G("c"),  G("a"),  N("a")));
4944         _ASSERT (5,  NM_IN_STRSET ("a",  G(NULL), G("b"),  G("c"),  G("d"),  G("a")));
4945         _ASSERT (5, !NM_IN_STRSET ("a",  G(NULL), G("b"),  G("c"),  G("d"),  G("e")));
4946
4947         _ASSERT (5,  NM_IN_STRSET ("a",  G(NULL), G("b"),  G("c"),  G("d"),  G("a"),  N("a")));
4948         _ASSERT (6,  NM_IN_STRSET ("a",  G(NULL), G("b"),  G("c"),  G("d"),  G("e"),  G("a")));
4949         _ASSERT (6, !NM_IN_STRSET ("a",  G(NULL), G("b"),  G("c"),  G("d"),  G("e"),  G("f")));
4950 #undef G
4951 #undef N
4952 #undef _ASSERT
4953 }
4954
4955 /******************************************************************************/
4956
4957 NMTST_DEFINE ();
4958
4959 int main (int argc, char **argv)
4960 {
4961         nmtst_init (&argc, &argv, TRUE);
4962
4963         /* The tests */
4964         g_test_add_func ("/core/general/test_nm_in_set", test_nm_in_set);
4965         g_test_add_func ("/core/general/test_nm_in_strset", test_nm_in_strset);
4966         g_test_add_func ("/core/general/test_setting_vpn_items", test_setting_vpn_items);
4967         g_test_add_func ("/core/general/test_setting_vpn_update_secrets", test_setting_vpn_update_secrets);
4968         g_test_add_func ("/core/general/test_setting_vpn_modify_during_foreach", test_setting_vpn_modify_during_foreach);
4969         g_test_add_func ("/core/general/test_setting_ip4_config_labels", test_setting_ip4_config_labels);
4970         g_test_add_func ("/core/general/test_setting_ip4_config_address_data", test_setting_ip4_config_address_data);
4971         g_test_add_func ("/core/general/test_setting_gsm_apn_spaces", test_setting_gsm_apn_spaces);
4972         g_test_add_func ("/core/general/test_setting_gsm_apn_bad_chars", test_setting_gsm_apn_bad_chars);
4973         g_test_add_func ("/core/general/test_setting_gsm_apn_underscore", test_setting_gsm_apn_underscore);
4974         g_test_add_func ("/core/general/test_setting_gsm_without_number", test_setting_gsm_without_number);
4975         g_test_add_func ("/core/general/test_setting_gsm_sim_operator_id", test_setting_gsm_sim_operator_id);
4976         g_test_add_func ("/core/general/test_setting_to_dbus_all", test_setting_to_dbus_all);
4977         g_test_add_func ("/core/general/test_setting_to_dbus_no_secrets", test_setting_to_dbus_no_secrets);
4978         g_test_add_func ("/core/general/test_setting_to_dbus_only_secrets", test_setting_to_dbus_only_secrets);
4979         g_test_add_func ("/core/general/test_setting_to_dbus_transform", test_setting_to_dbus_transform);
4980         g_test_add_func ("/core/general/test_setting_to_dbus_enum", test_setting_to_dbus_enum);
4981         g_test_add_func ("/core/general/test_setting_compare_id", test_setting_compare_id);
4982         g_test_add_func ("/core/general/test_setting_compare_timestamp", test_setting_compare_timestamp);
4983 #define ADD_FUNC(name, func, secret_flags, comp_flags, remove_secret) \
4984         g_test_add_data_func_full ("/core/general/" G_STRINGIFY (func) "_" name, \
4985                                    test_data_compare_secrets_new (secret_flags, comp_flags, remove_secret), \
4986                                    func, g_free)
4987         ADD_FUNC ("agent_owned", test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_AGENT_OWNED, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, TRUE);
4988         ADD_FUNC ("not_saved", test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_NOT_SAVED, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, TRUE);
4989         ADD_FUNC ("secrets", test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, TRUE);
4990         ADD_FUNC ("exact", test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_EXACT, FALSE);
4991         ADD_FUNC ("agent_owned", test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_AGENT_OWNED, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, TRUE);
4992         ADD_FUNC ("not_saved", test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_NOT_SAVED, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, TRUE);
4993         ADD_FUNC ("secrets", test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, TRUE);
4994         ADD_FUNC ("exact", test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_EXACT, FALSE);
4995         g_test_add_func ("/core/general/test_setting_old_uuid", test_setting_old_uuid);
4996
4997         g_test_add_func ("/core/general/test_connection_to_dbus_setting_name", test_connection_to_dbus_setting_name);
4998         g_test_add_func ("/core/general/test_connection_to_dbus_deprecated_props", test_connection_to_dbus_deprecated_props);
4999         g_test_add_func ("/core/general/test_setting_new_from_dbus", test_setting_new_from_dbus);
5000         g_test_add_func ("/core/general/test_setting_new_from_dbus_transform", test_setting_new_from_dbus_transform);
5001         g_test_add_func ("/core/general/test_setting_new_from_dbus_enum", test_setting_new_from_dbus_enum);
5002         g_test_add_func ("/core/general/test_setting_new_from_dbus_bad", test_setting_new_from_dbus_bad);
5003         g_test_add_func ("/core/general/test_connection_replace_settings", test_connection_replace_settings);
5004         g_test_add_func ("/core/general/test_connection_replace_settings_from_connection", test_connection_replace_settings_from_connection);
5005         g_test_add_func ("/core/general/test_connection_replace_settings_bad", test_connection_replace_settings_bad);
5006         g_test_add_func ("/core/general/test_connection_new_from_dbus", test_connection_new_from_dbus);
5007         g_test_add_func ("/core/general/test_connection_normalize_virtual_iface_name", test_connection_normalize_virtual_iface_name);
5008         g_test_add_func ("/core/general/test_connection_normalize_uuid", test_connection_normalize_uuid);
5009         g_test_add_func ("/core/general/test_connection_normalize_type", test_connection_normalize_type);
5010         g_test_add_func ("/core/general/test_connection_normalize_slave_type_1", test_connection_normalize_slave_type_1);
5011         g_test_add_func ("/core/general/test_connection_normalize_slave_type_2", test_connection_normalize_slave_type_2);
5012         g_test_add_func ("/core/general/test_connection_normalize_infiniband_mtu", test_connection_normalize_infiniband_mtu);
5013
5014         g_test_add_func ("/core/general/test_setting_connection_permissions_helpers", test_setting_connection_permissions_helpers);
5015         g_test_add_func ("/core/general/test_setting_connection_permissions_property", test_setting_connection_permissions_property);
5016
5017         g_test_add_func ("/core/general/test_connection_compare_same", test_connection_compare_same);
5018         g_test_add_func ("/core/general/test_connection_compare_key_only_in_a", test_connection_compare_key_only_in_a);
5019         g_test_add_func ("/core/general/test_connection_compare_setting_only_in_a", test_connection_compare_setting_only_in_a);
5020         g_test_add_func ("/core/general/test_connection_compare_key_only_in_b", test_connection_compare_key_only_in_b);
5021         g_test_add_func ("/core/general/test_connection_compare_setting_only_in_b", test_connection_compare_setting_only_in_b);
5022
5023         g_test_add_func ("/core/general/test_connection_diff_a_only", test_connection_diff_a_only);
5024         g_test_add_func ("/core/general/test_connection_diff_same", test_connection_diff_same);
5025         g_test_add_func ("/core/general/test_connection_diff_different", test_connection_diff_different);
5026         g_test_add_func ("/core/general/test_connection_diff_no_secrets", test_connection_diff_no_secrets);
5027         g_test_add_func ("/core/general/test_connection_diff_inferrable", test_connection_diff_inferrable);
5028         g_test_add_func ("/core/general/test_connection_good_base_types", test_connection_good_base_types);
5029         g_test_add_func ("/core/general/test_connection_bad_base_types", test_connection_bad_base_types);
5030
5031         g_test_add_func ("/core/general/test_hwaddr_aton_ether_normal", test_hwaddr_aton_ether_normal);
5032         g_test_add_func ("/core/general/test_hwaddr_aton_ib_normal", test_hwaddr_aton_ib_normal);
5033         g_test_add_func ("/core/general/test_hwaddr_aton_no_leading_zeros", test_hwaddr_aton_no_leading_zeros);
5034         g_test_add_func ("/core/general/test_hwaddr_aton_malformed", test_hwaddr_aton_malformed);
5035         g_test_add_func ("/core/general/test_hwaddr_equal", test_hwaddr_equal);
5036         g_test_add_func ("/core/general/test_hwaddr_canonical", test_hwaddr_canonical);
5037
5038         g_test_add_func ("/core/general/test_ip4_prefix_to_netmask", test_ip4_prefix_to_netmask);
5039         g_test_add_func ("/core/general/test_ip4_netmask_to_prefix", test_ip4_netmask_to_prefix);
5040
5041         g_test_add_func ("/core/general/test_connection_changed_signal", test_connection_changed_signal);
5042         g_test_add_func ("/core/general/test_setting_connection_changed_signal", test_setting_connection_changed_signal);
5043         g_test_add_func ("/core/general/test_setting_bond_changed_signal", test_setting_bond_changed_signal);
5044         g_test_add_func ("/core/general/test_setting_ip4_changed_signal", test_setting_ip4_changed_signal);
5045         g_test_add_func ("/core/general/test_setting_ip6_changed_signal", test_setting_ip6_changed_signal);
5046         g_test_add_func ("/core/general/test_setting_vlan_changed_signal", test_setting_vlan_changed_signal);
5047         g_test_add_func ("/core/general/test_setting_vpn_changed_signal", test_setting_vpn_changed_signal);
5048         g_test_add_func ("/core/general/test_setting_wired_changed_signal", test_setting_wired_changed_signal);
5049         g_test_add_func ("/core/general/test_setting_wireless_changed_signal", test_setting_wireless_changed_signal);
5050         g_test_add_func ("/core/general/test_setting_wireless_security_changed_signal", test_setting_wireless_security_changed_signal);
5051         g_test_add_func ("/core/general/test_setting_802_1x_changed_signal", test_setting_802_1x_changed_signal);
5052         g_test_add_func ("/core/general/test_setting_ip4_gateway", test_setting_ip4_gateway);
5053         g_test_add_func ("/core/general/test_setting_ip6_gateway", test_setting_ip6_gateway);
5054         g_test_add_func ("/core/general/test_setting_compare_default_strv", test_setting_compare_default_strv);
5055
5056         g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin);
5057         g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string);
5058         g_test_add_func ("/core/general/_nm_utils_uuid_generate_from_strings", test_nm_utils_uuid_generate_from_strings);
5059
5060         g_test_add_func ("/core/general/_nm_utils_ascii_str_to_int64", test_nm_utils_ascii_str_to_int64);
5061         g_test_add_func ("/core/general/nm_utils_is_power_of_two", test_nm_utils_is_power_of_two);
5062         g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert);
5063         g_test_add_func ("/core/general/_glib_compat_g_hash_table_get_keys_as_array", test_g_hash_table_get_keys_as_array);
5064         g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
5065         g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey);
5066
5067         g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate);
5068         g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx);
5069
5070         g_test_add_func ("/core/general/test_nm_utils_enum", test_nm_utils_enum);
5071
5072         return g_test_run ();
5073 }
5074