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