tests: fix libnm-util testcase on 32-bit platforms
[NetworkManager.git] / libnm-util / 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 ANY 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 (C) 2008 - 2011 Red Hat, Inc.
19  *
20  */
21
22 #include <glib.h>
23 #include <dbus/dbus-glib.h>
24 #include <string.h>
25 #include <netinet/ether.h>
26 #include <linux/if_infiniband.h>
27
28 #include "nm-test-helpers.h"
29 #include <nm-utils.h>
30
31 #include "nm-setting-connection.h"
32 #include "nm-setting-vpn.h"
33 #include "nm-setting-gsm.h"
34 #include "nm-setting-cdma.h"
35 #include "nm-setting-wired.h"
36 #include "nm-setting-wireless-security.h"
37 #include "nm-setting-ip6-config.h"
38 #include "nm-setting-ip4-config.h"
39 #include "nm-setting-pppoe.h"
40 #include "nm-setting-serial.h"
41 #include "nm-dbus-glib-types.h"
42
43 static void
44 vpn_check_func (const char *key, const char *value, gpointer user_data)
45 {
46         const char *test = user_data;
47
48         if (!strcmp (key, "foobar1")) {
49                 ASSERT (strcmp (value, "blahblah1") == 0,
50                                 test, "unexpected vpn item '%s' / '%s'", key, value);
51                 return;
52         }
53
54         if (!strcmp (key, "foobar2")) {
55                 ASSERT (strcmp (value, "blahblah2") == 0,
56                                 test, "unexpected vpn item '%s' / '%s'", key, value);
57                 return;
58         }
59
60         if (!strcmp (key, "foobar3")) {
61                 ASSERT (strcmp (value, "blahblah3") == 0,
62                                 test, "unexpected vpn item '%s' / '%s'", key, value);
63                 return;
64         }
65
66         if (!strcmp (key, "foobar4")) {
67                 ASSERT (strcmp (value, "blahblah4") == 0,
68                                 test, "unexpected vpn item '%s' / '%s'", key, value);
69                 return;
70         }
71
72         ASSERT (FALSE, test, "unexpected vpn item '%s'", key);
73 }
74
75 static void
76 vpn_check_empty_func (const char *key, const char *value, gpointer user_data)
77 {
78         const char *test = user_data;
79
80         /* We don't expect any values */
81         ASSERT (FALSE, test, "unexpected vpn item '%s'", key);
82 }
83
84 static void
85 test_setting_vpn_items (void)
86 {
87         NMSettingVPN *s_vpn;
88
89         s_vpn = (NMSettingVPN *) nm_setting_vpn_new ();
90         ASSERT (s_vpn != NULL,
91                 "vpn-items",
92                 "error creating vpn setting");
93
94         nm_setting_vpn_add_data_item (s_vpn, "foobar1", "blahblah1");
95         nm_setting_vpn_add_data_item (s_vpn, "foobar2", "blahblah2");
96         nm_setting_vpn_add_data_item (s_vpn, "foobar3", "blahblah3");
97         nm_setting_vpn_add_data_item (s_vpn, "foobar4", "blahblah4");
98
99         /* Ensure that added values are all present */
100         nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_func, "vpn-data");
101         nm_setting_vpn_remove_data_item (s_vpn, "foobar1");
102         nm_setting_vpn_remove_data_item (s_vpn, "foobar2");
103         nm_setting_vpn_remove_data_item (s_vpn, "foobar3");
104         nm_setting_vpn_remove_data_item (s_vpn, "foobar4");
105
106         nm_setting_vpn_add_secret (s_vpn, "foobar1", "blahblah1");
107         nm_setting_vpn_add_secret (s_vpn, "foobar2", "blahblah2");
108         nm_setting_vpn_add_secret (s_vpn, "foobar3", "blahblah3");
109         nm_setting_vpn_add_secret (s_vpn, "foobar4", "blahblah4");
110
111         /* Ensure that added values are all present */
112         nm_setting_vpn_foreach_secret (s_vpn, vpn_check_func, "vpn-secrets");
113         nm_setting_vpn_remove_secret (s_vpn, "foobar1");
114         nm_setting_vpn_remove_secret (s_vpn, "foobar2");
115         nm_setting_vpn_remove_secret (s_vpn, "foobar3");
116         nm_setting_vpn_remove_secret (s_vpn, "foobar4");
117
118         /* Try to add some blank values and make sure they are rejected */
119         nm_setting_vpn_add_data_item (s_vpn, NULL, NULL);
120         nm_setting_vpn_add_data_item (s_vpn, "", "");
121         nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL);
122         nm_setting_vpn_add_data_item (s_vpn, "foobar1", "");
123         nm_setting_vpn_add_data_item (s_vpn, NULL, "blahblah1");
124         nm_setting_vpn_add_data_item (s_vpn, "", "blahblah1");
125
126         nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_empty_func, "vpn-data-empty");
127
128         /* Try to add some blank secrets and make sure they are rejected */
129         nm_setting_vpn_add_secret (s_vpn, NULL, NULL);
130         nm_setting_vpn_add_secret (s_vpn, "", "");
131         nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL);
132         nm_setting_vpn_add_secret (s_vpn, "foobar1", "");
133         nm_setting_vpn_add_secret (s_vpn, NULL, "blahblah1");
134         nm_setting_vpn_add_secret (s_vpn, "", "blahblah1");
135
136         nm_setting_vpn_foreach_secret (s_vpn, vpn_check_empty_func, "vpn-secrets-empty");
137
138         g_object_unref (s_vpn);
139 }
140
141 static void
142 test_setting_vpn_update_secrets (void)
143 {
144         NMConnection *connection;
145         NMSettingVPN *s_vpn;
146         GHashTable *settings, *vpn, *secrets;
147         GValue val = { 0 };
148         gboolean success;
149         GError *error = NULL;
150         const char *tmp;
151         const char *key1 = "foobar";
152         const char *key2 = "blahblah";
153         const char *val1 = "value1";
154         const char *val2 = "value2";
155
156         connection = nm_connection_new ();
157         ASSERT (connection != NULL,
158                 "vpn-update-secrets",
159                 "error creating connection");
160
161         s_vpn = (NMSettingVPN *) nm_setting_vpn_new ();
162         ASSERT (s_vpn != NULL,
163                 "vpn-update-secrets",
164                 "error creating vpn setting");
165         nm_connection_add_setting (connection, NM_SETTING (s_vpn));
166
167         settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_hash_table_destroy);
168         vpn = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_value_unset);
169         g_hash_table_insert (settings, NM_SETTING_VPN_SETTING_NAME, vpn);
170
171         secrets = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
172         g_value_init (&val, DBUS_TYPE_G_MAP_OF_STRING);
173         g_value_take_boxed (&val, secrets);
174         g_hash_table_insert (vpn, NM_SETTING_VPN_SECRETS, &val);
175
176         /* Add some secrets */
177         g_hash_table_insert (secrets, (char *) key1, (char *) val1);
178         g_hash_table_insert (secrets, (char *) key2, (char *) val2);
179
180         success = nm_connection_update_secrets (connection, NM_SETTING_VPN_SETTING_NAME, settings, &error);
181         ASSERT (success == TRUE,
182                 "vpn-update-secrets", "failed to update VPN secrets: %s", error->message);
183
184         /* Read the secrets back out */
185         tmp = nm_setting_vpn_get_secret (s_vpn, key1);
186         ASSERT (tmp != NULL,
187                 "vpn-update-secrets", "unexpected failure getting key #1");
188         ASSERT (strcmp (tmp, val1) == 0,
189                 "vpn-update-secrets", "unexpected key #1 value");
190
191         tmp = nm_setting_vpn_get_secret (s_vpn, key2);
192         ASSERT (tmp != NULL,
193                 "vpn-update-secrets", "unexpected failure getting key #2");
194         ASSERT (strcmp (tmp, val2) == 0,
195                 "vpn-update-secrets", "unexpected key #2 value");
196
197         g_object_unref (connection);
198 }
199
200 #define TO_DEL_NUM 50
201 typedef struct {
202         NMSettingVPN *s_vpn;
203         char *to_del[TO_DEL_NUM];
204         guint called;
205 } IterInfo;
206
207 static void
208 del_iter_func (const char *key, const char *value, gpointer user_data)
209 {
210         IterInfo *info = user_data;
211         int i;
212
213         /* Record how many times this function gets called; it should get called
214          * exactly as many times as there are keys in the hash table, regardless
215          * of what keys we delete from the table.
216          */
217         info->called++;
218
219         /* During the iteration, remove a bunch of stuff from the table */
220         if (info->called == 1) {
221                 for (i = 0; i < TO_DEL_NUM; i++)
222                         nm_setting_vpn_remove_data_item (info->s_vpn, info->to_del[i]);
223         }
224 }
225
226 static void
227 test_setting_vpn_modify_during_foreach (void)
228 {
229         NMSettingVPN *s_vpn;
230         IterInfo info;
231         char *key, *val;
232         int i, u = 0;
233
234         s_vpn = (NMSettingVPN *) nm_setting_vpn_new ();
235         g_assert (s_vpn);
236
237         for (i = 0; i < TO_DEL_NUM * 2; i++) {
238                 key = g_strdup_printf ("adsfasdfadf%d", i);
239                 val = g_strdup_printf ("42263236236awt%d", i);
240                 nm_setting_vpn_add_data_item (s_vpn, key, val);
241
242                 /* Cache some keys to delete */
243                 if (i % 2)
244                         info.to_del[u++] = g_strdup (key);
245
246                 g_free (key);
247                 g_free (val);
248         }
249
250         /* Iterate over current table keys */
251         info.s_vpn = s_vpn;
252         info.called = 0;
253         nm_setting_vpn_foreach_data_item (s_vpn, del_iter_func, &info);
254
255         /* Make sure all the things we removed during iteration are really gone */
256         for (i = 0; i < TO_DEL_NUM; i++) {
257                 g_assert_cmpstr (nm_setting_vpn_get_data_item (s_vpn, info.to_del[i]), ==, NULL);
258                 g_free (info.to_del[i]);
259         }
260
261         /* And make sure the foreach callback was called the same number of times
262          * as there were keys in the table at the beginning of the foreach.
263          */
264         g_assert_cmpint (info.called, ==, TO_DEL_NUM * 2);
265
266         g_object_unref (s_vpn);
267 }
268
269 #define OLD_DBUS_TYPE_G_IP6_ADDRESS (dbus_g_type_get_struct ("GValueArray", DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UINT, G_TYPE_INVALID))
270 #define OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS (dbus_g_type_get_collection ("GPtrArray", OLD_DBUS_TYPE_G_IP6_ADDRESS))
271
272 /* Test that setting the IPv6 setting's 'addresses' property using the old
273  * IPv6 address format still works, i.e. that the GValue transformation function
274  * from old->new is working correctly.
275  */
276 static void
277 test_setting_ip6_config_old_address_array (void)
278 {
279         NMSettingIP6Config *s_ip6;
280         GPtrArray *addresses, *read_addresses;
281         GValueArray *array, *read_array;
282         GValue element = {0, }, written_value = {0, }, read_value = {0, };
283         GByteArray *ba;
284         const guint8 addr[16] = { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
285                                   0x11, 0x22, 0x33, 0x44, 0x66, 0x77, 0x88, 0x99 };
286         const guint8 gw[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
288         guint32 prefix = 56;
289         GValue *read_addr, *read_prefix, *read_gw;
290
291         s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
292         ASSERT (s_ip6 != NULL,
293                 "ip6-old-addr", "error creating IP6 setting");
294
295         g_value_init (&written_value, OLD_DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS);
296
297         addresses = g_ptr_array_new ();
298         array = g_value_array_new (3);
299
300         /* IP address */
301         g_value_init (&element, DBUS_TYPE_G_UCHAR_ARRAY);
302         ba = g_byte_array_new ();
303         g_byte_array_append (ba, &addr[0], sizeof (addr));
304         g_value_take_boxed (&element, ba);
305         g_value_array_append (array, &element);
306         g_value_unset (&element);
307
308         /* Prefix */
309         g_value_init (&element, G_TYPE_UINT);
310         g_value_set_uint (&element, prefix);
311         g_value_array_append (array, &element);
312         g_value_unset (&element);
313
314         g_ptr_array_add (addresses, array);
315         g_value_set_boxed (&written_value, addresses);
316
317         /* Set the address array on the object */
318         g_object_set_property (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_ADDRESSES, &written_value);
319
320         /* Get it back so we can compare it */
321         g_value_init (&read_value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS);
322         g_object_get_property (G_OBJECT (s_ip6), NM_SETTING_IP6_CONFIG_ADDRESSES, &read_value);
323
324         ASSERT (G_VALUE_HOLDS (&read_value, DBUS_TYPE_G_ARRAY_OF_IP6_ADDRESS),
325                 "ip6-old-addr", "wrong addresses property value type '%s'",
326                 G_VALUE_TYPE_NAME (&read_value));
327
328         read_addresses = (GPtrArray *) g_value_get_boxed (&read_value);
329         ASSERT (read_addresses != NULL,
330                 "ip6-old-addr", "missing addresses on readback");
331         ASSERT (read_addresses->len == 1,
332                 "ip6-old-addr", "expected one address on readback");
333
334         read_array = (GValueArray *) g_ptr_array_index (read_addresses, 0);
335
336         read_addr = g_value_array_get_nth (read_array, 0);
337         ba = g_value_get_boxed (read_addr);
338         ASSERT (ba->len == sizeof (addr),
339                 "ip6-old-addr", "unexpected address item length %d", ba->len);
340         ASSERT (memcmp (ba->data, &addr[0], sizeof (addr)) == 0,
341                 "ip6-old-addr", "unexpected failure comparing addresses");
342
343         read_prefix = g_value_array_get_nth (read_array, 1);
344         ASSERT (g_value_get_uint (read_prefix) == prefix,
345                 "ip6-old-addr", "unexpected failure comparing prefix");
346
347         /* Ensure the gateway is all zeros, which is how the 2-item to 3-item
348          * conversion happens.
349          */
350         read_gw = g_value_array_get_nth (read_array, 2);
351         ba = g_value_get_boxed (read_gw);
352         ASSERT (ba->len == sizeof (gw),
353                 "ip6-old-addr", "unexpected gateway item length %d", ba->len);
354         ASSERT (memcmp (ba->data, &gw[0], sizeof (gw)) == 0,
355                 "ip6-old-addr", "unexpected failure comparing gateways");
356
357         g_value_unset (&written_value);
358         g_value_unset (&read_value);
359         g_object_unref (s_ip6);
360 }
361
362 static void
363 test_setting_gsm_apn_spaces (void)
364 {
365         NMSettingGsm *s_gsm;
366         const char *tmp;
367
368         s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
369         ASSERT (s_gsm != NULL,
370                 "gsm-apn-spaces",
371                 "error creating GSM setting");
372
373         /* Trailing space */
374         g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar ", NULL);
375         tmp = nm_setting_gsm_get_apn (s_gsm);
376         ASSERT (tmp != NULL,
377                 "gsm-apn-spaces", "empty APN");
378         ASSERT (strcmp (tmp, "foobar") == 0,
379                 "gsm-apn-spaces", "unexpected APN");
380
381         /* Leading space */
382         g_object_set (s_gsm, NM_SETTING_GSM_APN, " foobar", NULL);
383         tmp = nm_setting_gsm_get_apn (s_gsm);
384         ASSERT (tmp != NULL,
385                 "gsm-apn-spaces", "empty APN");
386         ASSERT (strcmp (tmp, "foobar") == 0,
387                 "gsm-apn-spaces", "unexpected APN");
388 }
389
390 static void
391 test_setting_gsm_apn_bad_chars (void)
392 {
393         NMSettingGsm *s_gsm;
394
395         s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
396         ASSERT (s_gsm != NULL,
397                 "gsm-apn-bad-chars",
398                 "error creating GSM setting");
399
400         g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL);
401
402         /* Make sure a valid APN works */
403         g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar123.-baz", NULL);
404         ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == TRUE,
405                 "gsm-apn-bad-chars", "unexpectedly invalid GSM setting");
406
407         /* Random invalid chars */
408         g_object_set (s_gsm, NM_SETTING_GSM_APN, "@#%$@#%@#%", NULL);
409         ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == FALSE,
410                 "gsm-apn-bad-chars", "unexpectedly valid GSM setting");
411
412         /* Spaces */
413         g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar baz", NULL);
414         ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == FALSE,
415                 "gsm-apn-bad-chars", "unexpectedly valid GSM setting");
416
417         /* 0 characters long */
418         g_object_set (s_gsm, NM_SETTING_GSM_APN, "", NULL);
419         ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == FALSE,
420                 "gsm-apn-bad-chars", "unexpectedly valid GSM setting");
421
422         /* 65-character long */
423         g_object_set (s_gsm, NM_SETTING_GSM_APN, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl1", NULL);
424         ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == FALSE,
425                 "gsm-apn-bad-chars", "unexpectedly valid GSM setting");
426 }
427
428 static void
429 test_setting_gsm_apn_underscore (void)
430 {
431         NMSettingGsm *s_gsm;
432         GError *error = NULL;
433         gboolean success;
434
435         s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
436         g_assert (s_gsm);
437
438         g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL);
439
440         /* 65-character long */
441         g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar_baz", NULL);
442         success = nm_setting_verify (NM_SETTING (s_gsm), NULL, &error);
443         g_assert_no_error (error);
444         g_assert (success == TRUE);
445 }
446
447 static void
448 test_setting_gsm_without_number (void)
449 {
450         NMSettingGsm *s_gsm;
451         GError *error = NULL;
452         gboolean success;
453
454         s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
455         g_assert (s_gsm);
456
457         g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, NULL, NULL);
458         success = nm_setting_verify (NM_SETTING (s_gsm), NULL, &error);
459         g_assert_no_error (error);
460         g_assert (success == TRUE);
461
462         g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "", NULL);
463         success = nm_setting_verify (NM_SETTING (s_gsm), NULL, &error);
464         g_assert_error (error, NM_SETTING_GSM_ERROR, NM_SETTING_GSM_ERROR_INVALID_PROPERTY);
465 }
466
467 static NMSettingWirelessSecurity *
468 make_test_wsec_setting (const char *detail)
469 {
470         NMSettingWirelessSecurity *s_wsec;
471
472         s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
473         ASSERT (s_wsec != NULL, detail, "error creating setting");
474
475         g_object_set (s_wsec,
476                       NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
477                       NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, "foobarbaz",
478                       NM_SETTING_WIRELESS_SECURITY_PSK, "random psk",
479                       NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, "aaaaaaaaaa",
480                       NULL);
481
482         return s_wsec;
483 }
484
485 static void
486 test_setting_to_hash_all (void)
487 {
488         NMSettingWirelessSecurity *s_wsec;
489         GHashTable *hash;
490
491         s_wsec = make_test_wsec_setting ("setting-to-hash-all");
492
493         hash = nm_setting_to_hash (NM_SETTING (s_wsec), NM_SETTING_HASH_FLAG_ALL);
494
495         /* Make sure all keys are there */
496         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT),
497                 "setting-to-hash-all", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
498         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME),
499                 "setting-to-hash-all", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
500         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_PSK),
501                 "setting-to-hash-all", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_PSK);
502         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0),
503                 "setting-to-hash-all", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
504
505         g_hash_table_destroy (hash);
506         g_object_unref (s_wsec);
507 }
508
509 static void
510 test_setting_to_hash_no_secrets (void)
511 {
512         NMSettingWirelessSecurity *s_wsec;
513         GHashTable *hash;
514
515         s_wsec = make_test_wsec_setting ("setting-to-hash-no-secrets");
516
517         hash = nm_setting_to_hash (NM_SETTING (s_wsec), NM_SETTING_HASH_FLAG_NO_SECRETS);
518
519         /* Make sure non-secret keys are there */
520         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT),
521                 "setting-to-hash-no-secrets", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
522         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME),
523                 "setting-to-hash-no-secrets", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
524
525         /* Make sure secrets are not there */
526         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_PSK) == NULL,
527                 "setting-to-hash-no-secrets", "unexpectedly present " NM_SETTING_WIRELESS_SECURITY_PSK);
528         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0) == NULL,
529                 "setting-to-hash-no-secrets", "unexpectedly present " NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
530
531         g_hash_table_destroy (hash);
532         g_object_unref (s_wsec);
533 }
534
535 static void
536 test_setting_to_hash_only_secrets (void)
537 {
538         NMSettingWirelessSecurity *s_wsec;
539         GHashTable *hash;
540
541         s_wsec = make_test_wsec_setting ("setting-to-hash-only-secrets");
542
543         hash = nm_setting_to_hash (NM_SETTING (s_wsec), NM_SETTING_HASH_FLAG_ONLY_SECRETS);
544
545         /* Make sure non-secret keys are there */
546         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT) == NULL,
547                 "setting-to-hash-only-secrets", "unexpectedly present " NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
548         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME) == NULL,
549                 "setting-to-hash-only-secrets", "unexpectedly present " NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
550
551         /* Make sure secrets are not there */
552         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_PSK),
553                 "setting-to-hash-only-secrets", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_PSK);
554         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0),
555                 "setting-to-hash-only-secrets", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
556
557         g_hash_table_destroy (hash);
558         g_object_unref (s_wsec);
559 }
560
561 static void
562 test_connection_to_hash_setting_name (void)
563 {
564         NMConnection *connection;
565         NMSettingWirelessSecurity *s_wsec;
566         GHashTable *hash;
567
568         connection = nm_connection_new ();
569         s_wsec = make_test_wsec_setting ("connection-to-hash-setting-name");
570         nm_connection_add_setting (connection, NM_SETTING (s_wsec));
571
572         hash = nm_connection_to_hash (connection, NM_SETTING_HASH_FLAG_ALL);
573
574         /* Make sure the keys of the first level hash are setting names, not
575          * the GType name of the setting objects.
576          */
577         ASSERT (g_hash_table_lookup (hash, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) != NULL,
578                 "connection-to-hash-setting-name", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
579
580         g_hash_table_destroy (hash);
581         g_object_unref (connection);
582 }
583
584 static void
585 check_permission (NMSettingConnection *s_con,
586                   guint32 idx,
587                   const char *expected_uname,
588                   const char *tag)
589 {
590         gboolean success;
591         const char *ptype = NULL, *pitem = NULL, *detail = NULL;
592
593         success = nm_setting_connection_get_permission (s_con, 0, &ptype, &pitem, &detail);
594         ASSERT (success == TRUE, tag, "unexpected failure getting added permission");
595
596         /* Permission type */
597         ASSERT (ptype != NULL, tag, "unexpected failure getting permission type");
598         ASSERT (strcmp (ptype, "user") == 0, tag, "retrieved unexpected permission type");
599
600         /* Permission item */
601         ASSERT (pitem != NULL, tag, "unexpected failure getting permission item");
602         ASSERT (strcmp (pitem, expected_uname) == 0, tag, "retrieved unexpected permission item");
603
604         ASSERT (detail == NULL, tag, "unexpected success getting permission detail");
605 }
606
607 #define TEST_UNAME "asdfasfasdf"
608
609 static void
610 test_setting_connection_permissions_helpers (void)
611 {
612         NMSettingConnection *s_con;
613         gboolean success;
614         char buf[9] = { 0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00 };
615         GSList *list = NULL;
616         const char *expected_perm = "user:" TEST_UNAME ":";
617
618         s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
619
620         /* Ensure a bad [type] is rejected */
621         success = nm_setting_connection_add_permission (s_con, "foobar", "blah", NULL);
622         ASSERT (success == FALSE,
623                 "setting-connection-permissions-helpers", "unexpected success adding bad permission type #1");
624
625         /* Ensure a bad [type] is rejected */
626         success = nm_setting_connection_add_permission (s_con, NULL, "blah", NULL);
627         ASSERT (success == FALSE,
628                 "setting-connection-permissions-helpers", "unexpected success adding bad permission type #2");
629
630         /* Ensure a bad [item] is rejected */
631         success = nm_setting_connection_add_permission (s_con, "user", NULL, NULL);
632         ASSERT (success == FALSE,
633                 "setting-connection-permissions-helpers", "unexpected success adding bad permission item #1");
634
635         /* Ensure a bad [item] is rejected */
636         success = nm_setting_connection_add_permission (s_con, "user", "", NULL);
637         ASSERT (success == FALSE,
638                 "setting-connection-permissions-helpers", "unexpected success adding bad permission item #2");
639
640         /* Ensure an [item] with ':' is rejected */
641         success = nm_setting_connection_add_permission (s_con, "user", "ad:asdf", NULL);
642         ASSERT (success == FALSE,
643                 "setting-connection-permissions-helpers", "unexpected success adding bad permission item #3");
644
645         /* Ensure a non-UTF-8 [item] is rejected */
646         success = nm_setting_connection_add_permission (s_con, "user", buf, NULL);
647         ASSERT (success == FALSE,
648                 "setting-connection-permissions-helpers", "unexpected success adding bad permission item #4");
649
650         /* Ensure a non-NULL [detail] is rejected */
651         success = nm_setting_connection_add_permission (s_con, "user", "dafasdf", "asdf");
652         ASSERT (success == FALSE,
653                 "setting-connection-permissions-helpers", "unexpected success adding bad detail");
654
655         /* Ensure a valid call results in success */
656         success = nm_setting_connection_add_permission (s_con, "user", TEST_UNAME, NULL);
657         ASSERT (success == TRUE,
658                 "setting-connection-permissions-helpers", "unexpected failure adding valid user permisson");
659
660         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 1,
661                 "setting-connection-permissions-helpers", "unexpected failure getting number of permissions");
662
663         check_permission (s_con, 0, TEST_UNAME, "setting-connection-permissions-helpers");
664
665         /* Check the actual GObject property just to be paranoid */
666         g_object_get (G_OBJECT (s_con), NM_SETTING_CONNECTION_PERMISSIONS, &list, NULL);
667         ASSERT (list != NULL,
668                 "setting-connection-permissions-helpers", "unexpected failure getting permissions list");
669         ASSERT (g_slist_length (list) == 1,
670                 "setting-connection-permissions-helpers", "unexpected failure getting number of permissions in list");
671         ASSERT (strcmp (list->data, expected_perm) == 0,
672                 "setting-connection-permissions-helpers", "unexpected permission property data");
673
674         /* Now remove that permission and ensure we have 0 permissions */
675         nm_setting_connection_remove_permission (s_con, 0);
676         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
677                 "setting-connection-permissions-helpers", "unexpected failure removing permission");
678
679         g_object_unref (s_con);
680 }
681
682 static void
683 add_permission_property (NMSettingConnection *s_con,
684                          const char *ptype,
685                          const char *pitem,
686                          int pitem_len,
687                          const char *detail)
688 {
689         GString *str;
690         GSList *list = NULL;
691
692         str = g_string_sized_new (50);
693         if (ptype)
694                 g_string_append (str, ptype);
695         g_string_append_c (str, ':');
696
697         if (pitem) {
698                 if (pitem_len >= 0)
699                         g_string_append_len (str, pitem, pitem_len);
700                 else
701                         g_string_append (str, pitem);
702         }
703
704         g_string_append_c (str, ':');
705
706         if (detail)
707                 g_string_append (str, detail);
708
709         list = g_slist_append (list, str->str);
710         g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_PERMISSIONS, list, NULL);
711
712         g_string_free (str, TRUE);
713         g_slist_free (list);
714 }
715
716 static void
717 test_setting_connection_permissions_property (void)
718 {
719         NMSettingConnection *s_con;
720         gboolean success;
721         char buf[9] = { 0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00 };
722
723         s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
724
725         /* Ensure a bad [type] is rejected */
726         add_permission_property (s_con, "foobar", "blah", -1, NULL);
727         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
728                 "setting-connection-permissions-property", "unexpected success adding bad permission type #1");
729
730         /* Ensure a bad [type] is rejected */
731         add_permission_property (s_con, NULL, "blah", -1, NULL);
732         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
733                 "setting-connection-permissions-property", "unexpected success adding bad permission type #2");
734
735         /* Ensure a bad [item] is rejected */
736         add_permission_property (s_con, "user", NULL, -1, NULL);
737         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
738                 "setting-connection-permissions-property", "unexpected success adding bad permission item #1");
739
740         /* Ensure a bad [item] is rejected */
741         add_permission_property (s_con, "user", "", -1, NULL);
742         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
743                 "setting-connection-permissions-property", "unexpected success adding bad permission item #2");
744
745         /* Ensure an [item] with ':' in the middle is rejected */
746         add_permission_property (s_con, "user", "ad:asdf", -1, NULL);
747         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
748                 "setting-connection-permissions-property", "unexpected success adding bad permission item #3");
749
750         /* Ensure an [item] with ':' at the end is rejected */
751         add_permission_property (s_con, "user", "adasdfaf:", -1, NULL);
752         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
753                 "setting-connection-permissions-property", "unexpected success adding bad permission item #4");
754
755         /* Ensure a non-UTF-8 [item] is rejected */
756         add_permission_property (s_con, "user", buf, (int) sizeof (buf), NULL);
757         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
758                 "setting-connection-permissions-property", "unexpected success adding bad permission item #5");
759
760         /* Ensure a non-NULL [detail] is rejected */
761         add_permission_property (s_con, "user", "dafasdf", -1, "asdf");
762         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
763                 "setting-connection-permissions-property", "unexpected success adding bad detail");
764
765         /* Ensure a valid call results in success */
766         success = nm_setting_connection_add_permission (s_con, "user", TEST_UNAME, NULL);
767         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 1,
768                 "setting-connection-permissions-property", "unexpected failure adding valid user permisson");
769
770         check_permission (s_con, 0, TEST_UNAME, "setting-connection-permissions-property");
771
772         /* Now remove that permission and ensure we have 0 permissions */
773         nm_setting_connection_remove_permission (s_con, 0);
774         ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
775                 "setting-connection-permissions-property", "unexpected failure removing permission");
776
777         g_object_unref (s_con);
778 }
779
780 static NMConnection *
781 new_test_connection (void)
782 {
783         NMConnection *connection;
784         NMSetting *setting;
785         char *uuid;
786         guint64 timestamp = time (NULL);
787
788         connection = nm_connection_new ();
789
790         setting = nm_setting_connection_new ();
791         uuid = nm_utils_uuid_generate ();
792         g_object_set (G_OBJECT (setting),
793                       NM_SETTING_CONNECTION_ID, "foobar",
794                       NM_SETTING_CONNECTION_UUID, uuid,
795                       NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
796                       NM_SETTING_CONNECTION_TIMESTAMP, timestamp,
797                       NULL);
798         g_free (uuid);
799         nm_connection_add_setting (connection, setting);
800
801         setting = nm_setting_wired_new ();
802         g_object_set (G_OBJECT (setting),
803                       NM_SETTING_WIRED_MTU, 1592,
804                       NULL);
805         nm_connection_add_setting (connection, setting);
806
807         setting = nm_setting_ip4_config_new ();
808         g_object_set (G_OBJECT (setting),
809                       NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
810                       NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, "eyeofthetiger",
811                       NULL);
812         nm_connection_add_setting (connection, setting);
813
814         return connection;
815 }
816
817 typedef struct {
818         const char *key_name;
819         guint32 result;
820 } DiffKey;
821
822 typedef struct {
823         const char *name;
824         DiffKey keys[30];
825 } DiffSetting;
826
827 #define ARRAY_LEN(a)  (sizeof (a) / sizeof (a[0]))
828
829 static void
830 ensure_diffs (GHashTable *diffs, const DiffSetting *check, gsize n_check)
831 {
832         guint i;
833
834         g_assert (g_hash_table_size (diffs) == n_check);
835
836         /* Loop through the settings */
837         for (i = 0; i < n_check; i++) {
838                 GHashTable *setting_hash;
839                 guint z = 0;
840
841                 setting_hash = g_hash_table_lookup (diffs, check[i].name);
842                 g_assert (setting_hash);
843
844                 /* Get the number of keys to check */
845                 while (check[i].keys[z].key_name)
846                         z++;
847                 g_assert (g_hash_table_size (setting_hash) == z);
848
849                 /* Now compare the actual keys */
850                 for (z = 0; check[i].keys[z].key_name; z++) {
851                         NMSettingDiffResult result;
852
853                         result = GPOINTER_TO_UINT (g_hash_table_lookup (setting_hash, check[i].keys[z].key_name));
854                         g_assert (result == check[i].keys[z].result);
855                 }
856         }
857 }
858
859 static void
860 test_connection_diff_a_only (void)
861 {
862         NMConnection *connection;
863         GHashTable *out_diffs = NULL;
864         gboolean same;
865         const DiffSetting settings[] = {
866                 { NM_SETTING_CONNECTION_SETTING_NAME, {
867                         { NM_SETTING_CONNECTION_ID,          NM_SETTING_DIFF_RESULT_IN_A },
868                         { NM_SETTING_CONNECTION_UUID,        NM_SETTING_DIFF_RESULT_IN_A },
869                         { NM_SETTING_CONNECTION_TYPE,        NM_SETTING_DIFF_RESULT_IN_A },
870                         { NM_SETTING_CONNECTION_TIMESTAMP,   NM_SETTING_DIFF_RESULT_IN_A },
871                         { NM_SETTING_CONNECTION_AUTOCONNECT, NM_SETTING_DIFF_RESULT_IN_A },
872                         { NM_SETTING_CONNECTION_READ_ONLY,   NM_SETTING_DIFF_RESULT_IN_A },
873                         { NM_SETTING_CONNECTION_PERMISSIONS, NM_SETTING_DIFF_RESULT_IN_A },
874                         { NM_SETTING_CONNECTION_ZONE,        NM_SETTING_DIFF_RESULT_IN_A },
875                         { NM_SETTING_CONNECTION_MASTER,      NM_SETTING_DIFF_RESULT_IN_A },
876                         { NM_SETTING_CONNECTION_SLAVE_TYPE,  NM_SETTING_DIFF_RESULT_IN_A },
877                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }
878                 } },
879                 { NM_SETTING_WIRED_SETTING_NAME, {
880                         { NM_SETTING_WIRED_PORT,                  NM_SETTING_DIFF_RESULT_IN_A },
881                         { NM_SETTING_WIRED_SPEED,                 NM_SETTING_DIFF_RESULT_IN_A },
882                         { NM_SETTING_WIRED_DUPLEX,                NM_SETTING_DIFF_RESULT_IN_A },
883                         { NM_SETTING_WIRED_AUTO_NEGOTIATE,        NM_SETTING_DIFF_RESULT_IN_A },
884                         { NM_SETTING_WIRED_MAC_ADDRESS,           NM_SETTING_DIFF_RESULT_IN_A },
885                         { NM_SETTING_WIRED_CLONED_MAC_ADDRESS,    NM_SETTING_DIFF_RESULT_IN_A },
886                         { NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, NM_SETTING_DIFF_RESULT_IN_A },
887                         { NM_SETTING_WIRED_MTU,                   NM_SETTING_DIFF_RESULT_IN_A },
888                         { NM_SETTING_WIRED_S390_SUBCHANNELS,      NM_SETTING_DIFF_RESULT_IN_A },
889                         { NM_SETTING_WIRED_S390_NETTYPE,          NM_SETTING_DIFF_RESULT_IN_A },
890                         { NM_SETTING_WIRED_S390_OPTIONS,          NM_SETTING_DIFF_RESULT_IN_A },
891                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
892                 } },
893                 { NM_SETTING_IP4_CONFIG_SETTING_NAME, {
894                         { NM_SETTING_IP4_CONFIG_METHOD,             NM_SETTING_DIFF_RESULT_IN_A },
895                         { NM_SETTING_IP4_CONFIG_DNS,                NM_SETTING_DIFF_RESULT_IN_A },
896                         { NM_SETTING_IP4_CONFIG_DNS_SEARCH,         NM_SETTING_DIFF_RESULT_IN_A },
897                         { NM_SETTING_IP4_CONFIG_ADDRESSES,          NM_SETTING_DIFF_RESULT_IN_A },
898                         { NM_SETTING_IP4_CONFIG_ROUTES,             NM_SETTING_DIFF_RESULT_IN_A },
899                         { NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
900                         { NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS,    NM_SETTING_DIFF_RESULT_IN_A },
901                         { NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID,     NM_SETTING_DIFF_RESULT_IN_A },
902                         { NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A },
903                         { NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME,      NM_SETTING_DIFF_RESULT_IN_A },
904                         { NM_SETTING_IP4_CONFIG_NEVER_DEFAULT,      NM_SETTING_DIFF_RESULT_IN_A },
905                         { NM_SETTING_IP4_CONFIG_MAY_FAIL,           NM_SETTING_DIFF_RESULT_IN_A },
906                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
907                 } },
908         };
909
910         connection = new_test_connection ();
911
912         same = nm_connection_diff (connection, NULL, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
913         g_assert (same == FALSE);
914         g_assert (out_diffs != NULL);
915         g_assert (g_hash_table_size (out_diffs) > 0);
916
917         ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
918
919         g_object_unref (connection);
920 }
921
922 static void
923 test_connection_diff_same (void)
924 {
925         NMConnection *a, *b;
926         GHashTable *out_diffs = NULL;
927         gboolean same;
928
929         a = new_test_connection ();
930         b = nm_connection_duplicate (a);
931
932         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
933         g_assert (same == TRUE);
934         g_assert (out_diffs == NULL);
935         g_object_unref (a);
936         g_object_unref (b);
937 }
938
939 static void
940 test_connection_diff_different (void)
941 {
942         NMConnection *a, *b;
943         GHashTable *out_diffs = NULL;
944         NMSettingIP4Config *s_ip4;
945         gboolean same;
946         const DiffSetting settings[] = {
947                 { NM_SETTING_IP4_CONFIG_SETTING_NAME, {
948                         { NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B },
949                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
950                 } },
951         };
952
953         a = new_test_connection ();
954         b = nm_connection_duplicate (a);
955         s_ip4 = nm_connection_get_setting_ip4_config (a);
956         g_assert (s_ip4);
957         g_object_set (G_OBJECT (s_ip4),
958                       NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
959                       NULL);
960
961         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
962         g_assert (same == FALSE);
963         g_assert (out_diffs != NULL);
964         g_assert (g_hash_table_size (out_diffs) > 0);
965
966         ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
967
968         g_object_unref (a);
969         g_object_unref (b);
970 }
971
972 static void
973 test_connection_diff_no_secrets (void)
974 {
975         NMConnection *a, *b;
976         GHashTable *out_diffs = NULL;
977         NMSetting *s_pppoe;
978         gboolean same;
979         const DiffSetting settings[] = {
980                 { NM_SETTING_PPPOE_SETTING_NAME, {
981                         { NM_SETTING_PPPOE_PASSWORD, NM_SETTING_DIFF_RESULT_IN_B },
982                         { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
983                 } },
984         };
985
986         a = new_test_connection ();
987         s_pppoe = nm_setting_pppoe_new ();
988         g_object_set (G_OBJECT (s_pppoe),
989                       NM_SETTING_PPPOE_USERNAME, "thomas",
990                       NULL);
991         nm_connection_add_setting (a, s_pppoe);
992
993         b = nm_connection_duplicate (a);
994
995         /* Add a secret to B */
996         s_pppoe = NM_SETTING (nm_connection_get_setting_pppoe (b));
997         g_assert (s_pppoe);
998         g_object_set (G_OBJECT (s_pppoe),
999                       NM_SETTING_PPPOE_PASSWORD, "secretpassword",
1000                       NULL);
1001
1002         /* Make sure the diff returns no results as secrets are ignored */
1003         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &out_diffs);
1004         g_assert (same == TRUE);
1005         g_assert (out_diffs == NULL);
1006
1007         /* Now make sure the diff returns results if secrets are not ignored */
1008         same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
1009         g_assert (same == FALSE);
1010         g_assert (out_diffs != NULL);
1011         g_assert (g_hash_table_size (out_diffs) > 0);
1012
1013         ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
1014
1015         g_object_unref (a);
1016         g_object_unref (b);
1017 }
1018
1019 static void
1020 add_generic_settings (NMConnection *connection, const char *ctype)
1021 {
1022         NMSetting *setting;
1023         char *uuid;
1024
1025         uuid = nm_utils_uuid_generate ();
1026
1027         setting = nm_setting_connection_new ();
1028         g_object_set (setting,
1029                       NM_SETTING_CONNECTION_ID, "asdfasdfadf",
1030                       NM_SETTING_CONNECTION_TYPE, ctype,
1031                       NM_SETTING_CONNECTION_UUID, uuid,
1032                       NULL);
1033         nm_connection_add_setting (connection, setting);
1034
1035         g_free (uuid);
1036
1037         setting = nm_setting_ip4_config_new ();
1038         g_object_set (setting, NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
1039         nm_connection_add_setting (connection, setting);
1040
1041         setting = nm_setting_ip6_config_new ();
1042         g_object_set (setting, NM_SETTING_IP6_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
1043         nm_connection_add_setting (connection, setting);
1044 }
1045
1046 static void
1047 test_connection_good_base_types (void)
1048 {
1049         NMConnection *connection;
1050         NMSetting *setting;
1051         gboolean success;
1052         GError *error = NULL;
1053         GByteArray *array;
1054         const guint8 bdaddr[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
1055
1056         /* Try a basic wired connection */
1057         connection = nm_connection_new ();
1058         add_generic_settings (connection, NM_SETTING_WIRED_SETTING_NAME);
1059         setting = nm_setting_wired_new ();
1060         nm_connection_add_setting (connection, setting);
1061
1062         success = nm_connection_verify (connection, &error);
1063         g_assert_no_error (error);
1064         g_assert (success);
1065         g_object_unref (connection);
1066
1067         /* Try a wired PPPoE connection */
1068         connection = nm_connection_new ();
1069         add_generic_settings (connection, NM_SETTING_PPPOE_SETTING_NAME);
1070         setting = nm_setting_pppoe_new ();
1071         g_object_set (setting, NM_SETTING_PPPOE_USERNAME, "bob smith", NULL);
1072         nm_connection_add_setting (connection, setting);
1073
1074         success = nm_connection_verify (connection, &error);
1075         g_assert_no_error (error);
1076         g_assert (success);
1077         g_object_unref (connection);
1078
1079         /* Wifi connection */
1080         connection = nm_connection_new ();
1081         add_generic_settings (connection, NM_SETTING_WIRELESS_SETTING_NAME);
1082
1083         setting = nm_setting_wireless_new ();
1084         array = g_byte_array_new ();
1085         g_byte_array_append (array, (const guint8 *) "1234567", 7);
1086         g_object_set (setting,
1087                       NM_SETTING_WIRELESS_SSID, array,
1088                       NM_SETTING_WIRELESS_MODE, "infrastructure",
1089                       NULL);
1090         g_byte_array_free (array, TRUE);
1091         nm_connection_add_setting (connection, setting);
1092
1093         success = nm_connection_verify (connection, &error);
1094         g_assert_no_error (error);
1095         g_assert (success);
1096         g_object_unref (connection);
1097
1098         /* Bluetooth connection */
1099         connection = nm_connection_new ();
1100         add_generic_settings (connection, NM_SETTING_BLUETOOTH_SETTING_NAME);
1101
1102         setting = nm_setting_bluetooth_new ();
1103         array = g_byte_array_new ();
1104         g_byte_array_append (array, bdaddr, sizeof (bdaddr));
1105         g_object_set (setting,
1106                       NM_SETTING_BLUETOOTH_BDADDR, array,
1107                       NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
1108                       NULL);
1109         g_byte_array_free (array, TRUE);
1110         nm_connection_add_setting (connection, setting);
1111
1112         success = nm_connection_verify (connection, &error);
1113         g_assert_no_error (error);
1114         g_assert (success);
1115         g_object_unref (connection);
1116
1117         /* WiMAX connection */
1118         connection = nm_connection_new ();
1119         add_generic_settings (connection, NM_SETTING_WIMAX_SETTING_NAME);
1120         setting = nm_setting_wimax_new ();
1121         g_object_set (setting, NM_SETTING_WIMAX_NETWORK_NAME, "CLEAR", NULL);
1122         nm_connection_add_setting (connection, setting);
1123
1124         success = nm_connection_verify (connection, &error);
1125         g_assert_no_error (error);
1126         g_assert (success);
1127         g_object_unref (connection);
1128
1129         /* GSM connection */
1130         connection = nm_connection_new ();
1131         add_generic_settings (connection, NM_SETTING_GSM_SETTING_NAME);
1132
1133         setting = nm_setting_gsm_new ();
1134         g_object_set (setting,
1135                       NM_SETTING_GSM_NUMBER, "*99#",
1136                       NM_SETTING_GSM_APN, "metered.billing.sucks",
1137                       NULL);
1138         nm_connection_add_setting (connection, setting);
1139
1140         /* CDMA connection */
1141         connection = nm_connection_new ();
1142         add_generic_settings (connection, NM_SETTING_CDMA_SETTING_NAME);
1143
1144         setting = nm_setting_cdma_new ();
1145         g_object_set (setting,
1146                       NM_SETTING_CDMA_NUMBER, "#777",
1147                       NM_SETTING_CDMA_USERNAME, "foobar@vzw.com",
1148                       NULL);
1149         nm_connection_add_setting (connection, setting);
1150
1151         success = nm_connection_verify (connection, &error);
1152         g_assert_no_error (error);
1153         g_assert (success);
1154         g_object_unref (connection);
1155 }
1156
1157 static void
1158 test_connection_bad_base_types (void)
1159 {
1160         NMConnection *connection;
1161         NMSetting *setting;
1162         gboolean success;
1163         GError *error = NULL;
1164
1165         /* Test various non-base connection types to make sure they are rejected;
1166          * using a fake 'wired' connection so the rest of it verifies
1167          */
1168
1169         /* Connection setting */
1170         connection = nm_connection_new ();
1171         add_generic_settings (connection, NM_SETTING_CONNECTION_SETTING_NAME);
1172         setting = nm_setting_wired_new ();
1173         nm_connection_add_setting (connection, setting);
1174
1175         success = nm_connection_verify (connection, &error);
1176         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
1177         g_assert (success == FALSE);
1178         g_object_unref (connection);
1179         g_clear_error (&error);
1180
1181         /* PPP setting */
1182         connection = nm_connection_new ();
1183         add_generic_settings (connection, NM_SETTING_PPP_SETTING_NAME);
1184         setting = nm_setting_wired_new ();
1185         nm_connection_add_setting (connection, setting);
1186         setting = nm_setting_ppp_new ();
1187         nm_connection_add_setting (connection, setting);
1188
1189         success = nm_connection_verify (connection, &error);
1190         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
1191         g_assert (success == FALSE);
1192         g_object_unref (connection);
1193         g_clear_error (&error);
1194
1195         /* Serial setting */
1196         connection = nm_connection_new ();
1197         add_generic_settings (connection, NM_SETTING_SERIAL_SETTING_NAME);
1198         setting = nm_setting_wired_new ();
1199         nm_connection_add_setting (connection, setting);
1200         setting = nm_setting_serial_new ();
1201         nm_connection_add_setting (connection, setting);
1202
1203         success = nm_connection_verify (connection, &error);
1204         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
1205         g_assert (success == FALSE);
1206         g_object_unref (connection);
1207         g_clear_error (&error);
1208
1209         /* IP4 setting */
1210         connection = nm_connection_new ();
1211         add_generic_settings (connection, NM_SETTING_IP4_CONFIG_SETTING_NAME);
1212         setting = nm_setting_wired_new ();
1213         nm_connection_add_setting (connection, setting);
1214
1215         success = nm_connection_verify (connection, &error);
1216         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
1217         g_assert (success == FALSE);
1218         g_object_unref (connection);
1219         g_clear_error (&error);
1220
1221         /* IP6 setting */
1222         connection = nm_connection_new ();
1223         add_generic_settings (connection, NM_SETTING_IP6_CONFIG_SETTING_NAME);
1224         setting = nm_setting_wired_new ();
1225         nm_connection_add_setting (connection, setting);
1226
1227         success = nm_connection_verify (connection, &error);
1228         g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_CONNECTION_TYPE_INVALID);
1229         g_assert (success == FALSE);
1230         g_object_unref (connection);
1231         g_clear_error (&error);
1232 }
1233
1234 static void
1235 test_setting_compare_id (void)
1236 {
1237         NMSetting *old, *new;
1238         gboolean success;
1239
1240         old = nm_setting_connection_new ();
1241         g_object_set (old,
1242                       NM_SETTING_CONNECTION_ID, "really awesome cool connection",
1243                       NM_SETTING_CONNECTION_UUID, "fbbd59d5-acab-4e30-8f86-258d272617e7",
1244                       NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
1245                       NULL);
1246
1247         new = nm_setting_duplicate (old);
1248         g_object_set (new, NM_SETTING_CONNECTION_ID, "some different connection id", NULL);
1249
1250         /* First make sure they are different */
1251         success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
1252         g_assert (success == FALSE);
1253
1254         success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_IGNORE_ID);
1255         g_assert (success);
1256 }
1257
1258 static void
1259 test_setting_compare_secrets (NMSettingSecretFlags secret_flags,
1260                               NMSettingCompareFlags comp_flags,
1261                               gboolean remove_secret)
1262 {
1263         NMSetting *old, *new;
1264         gboolean success;
1265
1266         /* Make sure that a connection with transient/unsaved secrets compares
1267          * successfully to the same connection without those secrets.
1268          */
1269
1270         old = nm_setting_wireless_security_new ();
1271         g_object_set (old,
1272                       NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
1273                       NM_SETTING_WIRELESS_SECURITY_PSK, "really cool psk",
1274                       NULL);
1275         nm_setting_set_secret_flags (old, NM_SETTING_WIRELESS_SECURITY_PSK, secret_flags, NULL);
1276
1277         /* Clear the PSK from the duplicated setting */
1278         new = nm_setting_duplicate (old);
1279         if (remove_secret) {
1280                 g_object_set (new, NM_SETTING_WIRELESS_SECURITY_PSK, NULL, NULL);
1281
1282                 success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
1283                 g_assert (success == FALSE);
1284         }
1285
1286         success = nm_setting_compare (old, new, comp_flags);
1287         g_assert (success);
1288 }
1289
1290 static void
1291 test_setting_compare_vpn_secrets (NMSettingSecretFlags secret_flags,
1292                                   NMSettingCompareFlags comp_flags,
1293                                   gboolean remove_secret)
1294 {
1295         NMSetting *old, *new;
1296         gboolean success;
1297
1298         /* Make sure that a connection with transient/unsaved secrets compares
1299          * successfully to the same connection without those secrets.
1300          */
1301
1302         old = nm_setting_vpn_new ();
1303         nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "foobarbaz", "really secret password");
1304         nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "asdfasdfasdf", "really adfasdfasdfasdf");
1305         nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "0123456778", "abcdefghijklmnpqrstuvqxyz");
1306         nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "borkbork", "yet another really secret password");
1307         nm_setting_set_secret_flags (old, "borkbork", secret_flags, NULL);
1308
1309         /* Clear "borkbork" from the duplicated setting */
1310         new = nm_setting_duplicate (old);
1311         if (remove_secret) {
1312                 nm_setting_vpn_remove_secret (NM_SETTING_VPN (new), "borkbork");
1313
1314                 /* First make sure they are different */
1315                 success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
1316                 g_assert (success == FALSE);
1317         }
1318
1319         success = nm_setting_compare (old, new, comp_flags);
1320         g_assert (success);
1321 }
1322
1323 static void
1324 test_hwaddr_aton_ether_normal (void)
1325 {
1326         guint8 buf[100];
1327         guint8 expected[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
1328
1329         g_assert (nm_utils_hwaddr_aton ("00:11:22:33:44:55", ARPHRD_ETHER, buf) != NULL);
1330         g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
1331 }
1332
1333 static void
1334 test_hwaddr_aton_ib_normal (void)
1335 {
1336         guint8 buf[100];
1337         const char *source = "00:11:22:33:44:55:66:77:88:99:01:12:23:34:45:56:67:78:89:90";
1338         guint8 expected[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
1339                 0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
1340                 0x90 };
1341
1342         g_assert (nm_utils_hwaddr_aton (source, ARPHRD_INFINIBAND, buf) != NULL);
1343         g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
1344 }
1345
1346 static void
1347 test_hwaddr_aton_no_leading_zeros (void)
1348 {
1349         guint8 buf[100];
1350         guint8 expected[ETH_ALEN] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05 };
1351
1352         g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:44:5", ARPHRD_ETHER, buf) != NULL);
1353         g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
1354 }
1355
1356 static void
1357 test_hwaddr_aton_malformed (void)
1358 {
1359         guint8 buf[100];
1360
1361         g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:a@%%", ARPHRD_ETHER, buf) == NULL);
1362 }
1363
1364 int main (int argc, char **argv)
1365 {
1366         GError *error = NULL;
1367         char *base;
1368
1369         g_type_init ();
1370
1371         if (!nm_utils_init (&error))
1372                 FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);
1373
1374         /* The tests */
1375         test_setting_vpn_items ();
1376         test_setting_vpn_update_secrets ();
1377         test_setting_vpn_modify_during_foreach ();
1378         test_setting_ip6_config_old_address_array ();
1379         test_setting_gsm_apn_spaces ();
1380         test_setting_gsm_apn_bad_chars ();
1381         test_setting_gsm_apn_underscore ();
1382         test_setting_gsm_without_number ();
1383         test_setting_to_hash_all ();
1384         test_setting_to_hash_no_secrets ();
1385         test_setting_to_hash_only_secrets ();
1386         test_setting_compare_id ();
1387         test_setting_compare_secrets (NM_SETTING_SECRET_FLAG_AGENT_OWNED, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, TRUE);
1388         test_setting_compare_secrets (NM_SETTING_SECRET_FLAG_NOT_SAVED, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, TRUE);
1389         test_setting_compare_secrets (NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, TRUE);
1390         test_setting_compare_secrets (NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_EXACT, FALSE);
1391         test_setting_compare_vpn_secrets (NM_SETTING_SECRET_FLAG_AGENT_OWNED, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, TRUE);
1392         test_setting_compare_vpn_secrets (NM_SETTING_SECRET_FLAG_NOT_SAVED, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, TRUE);
1393         test_setting_compare_vpn_secrets (NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, TRUE);
1394         test_setting_compare_vpn_secrets (NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_EXACT, FALSE);
1395
1396         test_connection_to_hash_setting_name ();
1397         test_setting_connection_permissions_helpers ();
1398         test_setting_connection_permissions_property ();
1399         test_connection_diff_a_only ();
1400         test_connection_diff_same ();
1401         test_connection_diff_different ();
1402         test_connection_diff_no_secrets ();
1403         test_connection_good_base_types ();
1404         test_connection_bad_base_types ();
1405
1406         test_hwaddr_aton_ether_normal ();
1407         test_hwaddr_aton_ib_normal ();
1408         test_hwaddr_aton_no_leading_zeros ();
1409         test_hwaddr_aton_malformed ();
1410
1411         base = g_path_get_basename (argv[0]);
1412         fprintf (stdout, "%s: SUCCESS\n", base);
1413         g_free (base);
1414         return 0;
1415 }
1416