1 /* A very basic feature test for TpAccount
2 *
3 * Copyright (C) 2009-2012 Collabora Ltd. <http://www.collabora.co.uk/>
4 * Copyright (C) 2009 Nokia Corporation
5 *
6 * Copying and distribution of this file, with or without modification,
7 * are permitted in any medium without royalty provided the copyright
8 * notice and this notice are preserved.
9 */
10
11 #include "config.h"
12
13 #include <telepathy-glib/account.h>
14 #include <telepathy-glib/debug.h>
15 #include <telepathy-glib/defs.h>
16 #include <telepathy-glib/svc-account.h>
17 #include <telepathy-glib/enums.h>
18
19 #include "tests/lib/contacts-conn.h"
20 #include "tests/lib/simple-account.h"
21 #include "tests/lib/util.h"
22
23 #define ACCOUNT_PATH TP_ACCOUNT_OBJECT_PATH_BASE "what/ev/er"
24 #define SUPERSEDED_PATH TP_ACCOUNT_OBJECT_PATH_BASE "super/seded/whatever"
25
26 static void
test_parse_failure(gconstpointer test_data)27 test_parse_failure (gconstpointer test_data)
28 {
29 GError *error = NULL;
30
31 g_assert (!tp_account_parse_object_path (test_data, NULL, NULL, NULL,
32 &error));
33 g_assert (error != NULL);
34 g_error_free (error);
35 }
36
37 typedef struct {
38 const gchar *path;
39 const gchar *cm;
40 const gchar *protocol;
41 const gchar *account_id;
42 } TestParseData;
43
44 static TestParseData *
test_parse_data_new(const gchar * path,const gchar * cm,const gchar * protocol,const gchar * account_id)45 test_parse_data_new (const gchar *path,
46 const gchar *cm,
47 const gchar *protocol,
48 const gchar *account_id)
49 {
50 TestParseData *t = g_slice_new (TestParseData);
51
52 t->path = path;
53 t->cm = cm;
54 t->protocol = protocol;
55 t->account_id = account_id;
56
57 return t;
58 }
59
60 static void
test_parse_success(gconstpointer test_data)61 test_parse_success (gconstpointer test_data)
62 {
63 TestParseData *t = (TestParseData *) test_data;
64 gchar *cm, *protocol, *account_id;
65 GError *error = NULL;
66
67 g_assert (tp_account_parse_object_path (t->path, &cm, &protocol, &account_id,
68 &error));
69 g_assert_no_error (error);
70 g_assert_cmpstr (cm, ==, t->cm);
71 g_assert_cmpstr (protocol, ==, t->protocol);
72 g_assert_cmpstr (account_id, ==, t->account_id);
73
74 g_free (cm);
75 g_free (protocol);
76 g_free (account_id);
77
78 g_slice_free (TestParseData, t);
79 }
80
81 typedef struct {
82 GMainLoop *mainloop;
83 TpDBusDaemon *dbus;
84
85 TpAccount *account;
86 gulong notify_id;
87 /* g_strdup (property name) => GUINT_TO_POINTER (counter) */
88 GHashTable *times_notified;
89 GAsyncResult *result;
90 GError *error /* initialized where needed */;
91
92 /* initialized in prepare_service */
93 TpTestsSimpleAccount *account_service;
94 TpBaseConnection *conn1_service;
95 TpBaseConnection *conn2_service;
96 TpConnection *conn1;
97 TpConnection *conn2;
98 } Test;
99
100 static void
setup(Test * test,gconstpointer data)101 setup (Test *test,
102 gconstpointer data)
103 {
104 test->mainloop = g_main_loop_new (NULL, FALSE);
105 test->dbus = tp_tests_dbus_daemon_dup_or_die ();
106 g_assert (test->dbus != NULL);
107
108 test->account = NULL;
109
110 test->times_notified = g_hash_table_new_full (g_str_hash, g_str_equal,
111 g_free, NULL);
112 }
113
114 static void
setup_service(Test * test,gconstpointer data)115 setup_service (Test *test,
116 gconstpointer data)
117 {
118 setup (test, data);
119
120 tp_dbus_daemon_request_name (test->dbus,
121 TP_ACCOUNT_MANAGER_BUS_NAME, FALSE, &test->error);
122 g_assert_no_error (test->error);
123
124 test->account_service = g_object_new (TP_TESTS_TYPE_SIMPLE_ACCOUNT, NULL);
125 tp_dbus_daemon_register_object (test->dbus, ACCOUNT_PATH,
126 test->account_service);
127
128 tp_tests_create_and_connect_conn (TP_TESTS_TYPE_CONTACTS_CONNECTION,
129 "what@ever", &test->conn1_service, &test->conn1);
130 tp_tests_create_and_connect_conn (TP_TESTS_TYPE_CONTACTS_CONNECTION,
131 "what2@ever", &test->conn2_service, &test->conn2);
132 }
133
134 static guint
test_get_times_notified(Test * test,const gchar * property)135 test_get_times_notified (Test *test,
136 const gchar *property)
137 {
138 return GPOINTER_TO_UINT (g_hash_table_lookup (test->times_notified,
139 property));
140 }
141
142 static void
test_notify_cb(Test * test,GParamSpec * pspec,TpAccount * account)143 test_notify_cb (Test *test,
144 GParamSpec *pspec,
145 TpAccount *account)
146 {
147 guint counter = test_get_times_notified (test, pspec->name);
148
149 g_hash_table_insert (test->times_notified, g_strdup (pspec->name),
150 GUINT_TO_POINTER (++counter));
151 }
152
153 static void
test_set_up_account_notify(Test * test)154 test_set_up_account_notify (Test *test)
155 {
156 g_assert (test->account != NULL);
157
158 g_hash_table_remove_all (test->times_notified);
159
160 if (test->notify_id != 0)
161 {
162 g_signal_handler_disconnect (test->account, test->notify_id);
163 }
164
165 test->notify_id = g_signal_connect_swapped (test->account, "notify",
166 G_CALLBACK (test_notify_cb), test);
167 }
168
169 static void
teardown(Test * test,gconstpointer data)170 teardown (Test *test,
171 gconstpointer data)
172 {
173 if (test->account != NULL)
174 {
175 tp_tests_proxy_run_until_dbus_queue_processed (test->account);
176
177 if (test->notify_id != 0)
178 {
179 g_signal_handler_disconnect (test->account, test->notify_id);
180 }
181
182 g_object_unref (test->account);
183 test->account = NULL;
184 }
185
186 g_hash_table_unref (test->times_notified);
187 test->times_notified = NULL;
188
189 /* make sure any pending calls on the account have happened, so it can die */
190 tp_tests_proxy_run_until_dbus_queue_processed (test->dbus);
191
192 g_object_unref (test->dbus);
193 test->dbus = NULL;
194 g_main_loop_unref (test->mainloop);
195 test->mainloop = NULL;
196
197 g_clear_error (&test->error);
198 tp_clear_object (&test->result);
199 }
200
201 static void
teardown_service(Test * test,gconstpointer data)202 teardown_service (Test *test,
203 gconstpointer data)
204 {
205 tp_dbus_daemon_release_name (test->dbus, TP_ACCOUNT_MANAGER_BUS_NAME,
206 &test->error);
207 g_assert_no_error (test->error);
208
209 tp_dbus_daemon_unregister_object (test->dbus, test->account_service);
210 g_clear_object (&test->account_service);
211
212 tp_tests_connection_assert_disconnect_succeeds (test->conn1);
213 g_clear_object (&test->conn1);
214 g_clear_object (&test->conn1_service);
215
216 tp_tests_connection_assert_disconnect_succeeds (test->conn2);
217 g_clear_object (&test->conn2);
218 g_clear_object (&test->conn2_service);
219
220 teardown (test, data);
221 }
222
223 static void
test_new(Test * test,gconstpointer data G_GNUC_UNUSED)224 test_new (Test *test,
225 gconstpointer data G_GNUC_UNUSED)
226 {
227 test->account = tp_account_new (test->dbus,
228 "/secretly/not/an/object", NULL);
229 g_assert (test->account == NULL);
230
231 test->account = tp_account_new (test->dbus,
232 "not even syntactically valid", NULL);
233 g_assert (test->account == NULL);
234
235 test->account = tp_account_new (test->dbus,
236 "/org/freedesktop/Telepathy/Account/what/ev/er", NULL);
237 g_assert (test->account != NULL);
238 }
239
240 static void
test_setters(Test * test,gconstpointer data G_GNUC_UNUSED)241 test_setters (Test *test,
242 gconstpointer data G_GNUC_UNUSED)
243 {
244 test->account = tp_account_new (test->dbus,
245 "/org/freedesktop/Telepathy/Account/what/ev/er", NULL);
246 g_assert (test->account != NULL);
247
248 tp_account_set_enabled_async (test->account, TRUE, tp_tests_result_ready_cb,
249 &test->result);
250 tp_tests_run_until_result (&test->result);
251 tp_account_set_enabled_finish (test->account, test->result, &test->error);
252 g_assert_error (test->error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED);
253 g_clear_error (&test->error);
254 tp_clear_object (&test->result);
255 }
256
257 static void
test_reconnect(Test * test,gconstpointer data)258 test_reconnect (Test *test,
259 gconstpointer data)
260 {
261 GStrv reconnect_required;
262 const gchar *unset[] = { "unset", NULL };
263
264 test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL);
265 g_assert (test->account != NULL);
266
267 if (!tp_strdiff (data, "vardict"))
268 {
269 tp_account_update_parameters_vardict_async (test->account,
270 g_variant_new_parsed ("{ 'set': <%s> }", "value"), unset,
271 tp_tests_result_ready_cb, &test->result);
272 tp_tests_run_until_result (&test->result);
273 tp_account_update_parameters_vardict_finish (test->account, test->result,
274 &reconnect_required, &test->error);
275 }
276 else
277 {
278 GHashTable *set = tp_asv_new (
279 "set", G_TYPE_STRING, "value",
280 NULL);
281
282 tp_account_update_parameters_async (test->account, set, unset,
283 tp_tests_result_ready_cb, &test->result);
284 tp_tests_run_until_result (&test->result);
285 tp_account_update_parameters_finish (test->account, test->result,
286 &reconnect_required, &test->error);
287
288 g_hash_table_unref (set);
289 }
290
291 g_assert_no_error (test->error);
292 /* check that reconnect_required survives longer than result */
293 tp_clear_object (&test->result);
294
295 g_assert (reconnect_required != NULL);
296 g_assert_cmpstr (reconnect_required[0], ==, "set");
297 g_assert_cmpstr (reconnect_required[1], ==, "unset");
298 g_assert_cmpstr (reconnect_required[2], ==, NULL);
299 g_strfreev (reconnect_required);
300
301 tp_account_reconnect_async (test->account, tp_tests_result_ready_cb,
302 &test->result);
303 tp_tests_run_until_result (&test->result);
304 tp_account_reconnect_finish (test->account, test->result, &test->error);
305 g_assert_error (test->error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED);
306 g_clear_error (&test->error);
307 tp_clear_object (&test->result);
308 }
309
310 static void
account_prepare_cb(GObject * source,GAsyncResult * result,gpointer user_data)311 account_prepare_cb (GObject *source,
312 GAsyncResult *result,
313 gpointer user_data)
314 {
315 Test *test = user_data;
316 GError *error = NULL;
317
318 tp_proxy_prepare_finish (source, result, &error);
319 g_assert_no_error (error);
320
321 g_main_loop_quit (test->mainloop);
322 }
323
324 #define assert_strprop(self, prop, val) \
325 {\
326 gchar *_s; \
327 \
328 g_object_get (self, \
329 prop, &_s, \
330 NULL); \
331 g_assert_cmpstr (_s, ==, val);\
332 g_free (_s); \
333 }
334 #define assert_uintprop(self, prop, val) \
335 {\
336 guint _u; \
337 \
338 g_object_get (self, \
339 prop, &_u, \
340 NULL); \
341 g_assert_cmpuint (_u, ==, val);\
342 }
343 #define assert_boolprop(self, prop, val) \
344 {\
345 gboolean _b; \
346 \
347 g_object_get (self, \
348 prop, &_b, \
349 NULL); \
350 g_assert_cmpint (_b, ==, val);\
351 }
352
353 static void
test_prepare_success(Test * test,gconstpointer data G_GNUC_UNUSED)354 test_prepare_success (Test *test,
355 gconstpointer data G_GNUC_UNUSED)
356 {
357 GQuark account_features[] = { TP_ACCOUNT_FEATURE_CORE, 0 };
358 TpConnectionStatusReason reason;
359 gchar *status = NULL;
360 gchar *message = NULL;
361 const GHashTable *details = GUINT_TO_POINTER (666);
362 GStrv strv;
363 const gchar * const *cstrv;
364 GVariant *variant;
365
366 test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL);
367 g_assert (test->account != NULL);
368
369 tp_proxy_prepare_async (test->account, account_features,
370 account_prepare_cb, test);
371 g_main_loop_run (test->mainloop);
372
373 /* the obvious accessors */
374 g_assert (tp_proxy_is_prepared (test->account, TP_ACCOUNT_FEATURE_CORE));
375 g_assert (tp_account_is_enabled (test->account));
376 assert_boolprop (test->account, "enabled", TRUE);
377 g_assert (tp_account_is_valid (test->account));
378 assert_boolprop (test->account, "valid", TRUE);
379 g_assert_cmpstr (tp_account_get_display_name (test->account), ==,
380 "Fake Account");
381 assert_strprop (test->account, "display-name", "Fake Account");
382 g_assert_cmpstr (tp_account_get_nickname (test->account), ==, "badger");
383 assert_strprop (test->account, "nickname", "badger");
384 g_assert_cmpuint (tp_asv_size (tp_account_get_parameters (test->account)),
385 ==, 0);
386 variant = tp_account_dup_parameters_vardict (test->account);
387 g_assert_cmpstr (g_variant_get_type_string (variant), ==, "a{sv}");
388 g_assert_cmpuint (g_variant_n_children (variant), ==, 0);
389 g_variant_unref (variant);
390 g_assert (!tp_account_get_connect_automatically (test->account));
391 assert_boolprop (test->account, "connect-automatically", FALSE);
392 g_assert (tp_account_get_has_been_online (test->account));
393 assert_boolprop (test->account, "has-been-online", TRUE);
394 g_assert_cmpint (tp_account_get_connection_status (test->account, NULL),
395 ==, TP_CONNECTION_STATUS_CONNECTED);
396 assert_uintprop (test->account, "connection-status",
397 TP_CONNECTION_STATUS_CONNECTED);
398 g_assert_cmpint (tp_account_get_connection_status (test->account, &reason),
399 ==, TP_CONNECTION_STATUS_CONNECTED);
400 g_assert_cmpint (reason, ==, TP_CONNECTION_STATUS_REASON_REQUESTED);
401 assert_uintprop (test->account, "connection-status-reason",
402 TP_CONNECTION_STATUS_REASON_REQUESTED);
403 g_assert_cmpstr (tp_account_get_detailed_error (test->account, NULL), ==,
404 NULL);
405 assert_strprop (test->account, "connection-error", NULL);
406 g_assert_cmpstr (tp_account_get_detailed_error (test->account, &details), ==,
407 NULL);
408 /* this is documented to be untouched */
409 g_assert_cmpuint (GPOINTER_TO_UINT (details), ==, 666);
410
411 /* the CM and protocol come from the object path */
412 g_assert_cmpstr (tp_account_get_cm_name (test->account),
413 ==, "what");
414 assert_strprop (test->account, "cm-name", "what");
415 g_assert_cmpstr (tp_account_get_protocol_name (test->account), ==, "ev");
416 assert_strprop (test->account, "protocol-name", "ev");
417
418 /* the icon name in SimpleAccount is "", so we guess based on the protocol */
419 g_assert_cmpstr (tp_account_get_icon_name (test->account), ==, "im-ev");
420 assert_strprop (test->account, "icon-name", "im-ev");
421
422 /* RequestedPresence */
423 g_assert_cmpint (tp_account_get_requested_presence (test->account, NULL,
424 NULL), ==, TP_CONNECTION_PRESENCE_TYPE_BUSY);
425 assert_uintprop (test->account, "requested-presence-type",
426 TP_CONNECTION_PRESENCE_TYPE_BUSY);
427 g_assert_cmpint (tp_account_get_requested_presence (test->account, &status,
428 NULL), ==, TP_CONNECTION_PRESENCE_TYPE_BUSY);
429 g_assert_cmpstr (status, ==, "requesting");
430 g_free (status);
431 assert_strprop (test->account, "requested-status", "requesting");
432 g_assert_cmpint (tp_account_get_requested_presence (test->account, NULL,
433 &message), ==, TP_CONNECTION_PRESENCE_TYPE_BUSY);
434 g_assert_cmpstr (message, ==, "this is my RequestedPresence");
435 g_free (message);
436 assert_strprop (test->account, "requested-status-message",
437 "this is my RequestedPresence");
438
439 /* CurrentPresence */
440 g_assert_cmpint (tp_account_get_current_presence (test->account, NULL,
441 NULL), ==, TP_CONNECTION_PRESENCE_TYPE_AWAY);
442 assert_uintprop (test->account, "current-presence-type",
443 TP_CONNECTION_PRESENCE_TYPE_AWAY);
444 g_assert_cmpint (tp_account_get_current_presence (test->account, &status,
445 NULL), ==, TP_CONNECTION_PRESENCE_TYPE_AWAY);
446 g_assert_cmpstr (status, ==, "currently-away");
447 g_free (status);
448 assert_strprop (test->account, "current-status", "currently-away");
449 g_assert_cmpint (tp_account_get_current_presence (test->account, NULL,
450 &message), ==, TP_CONNECTION_PRESENCE_TYPE_AWAY);
451 g_assert_cmpstr (message, ==, "this is my CurrentPresence");
452 g_free (message);
453 assert_strprop (test->account, "current-status-message",
454 "this is my CurrentPresence");
455
456 /* AutomaticPresence */
457 g_assert_cmpint (tp_account_get_automatic_presence (test->account, NULL,
458 NULL), ==, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
459 assert_uintprop (test->account, "automatic-presence-type",
460 TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
461 g_assert_cmpint (tp_account_get_automatic_presence (test->account, &status,
462 NULL), ==, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
463 g_assert_cmpstr (status, ==, "automatically-available");
464 g_free (status);
465 assert_strprop (test->account, "automatic-status",
466 "automatically-available");
467 g_assert_cmpint (tp_account_get_automatic_presence (test->account, NULL,
468 &message), ==, TP_CONNECTION_PRESENCE_TYPE_AVAILABLE);
469 g_assert_cmpstr (message, ==, "this is my AutomaticPresence");
470 g_free (message);
471 assert_strprop (test->account, "automatic-status-message",
472 "this is my AutomaticPresence");
473
474 /* NormalizedName */
475 g_assert_cmpstr (tp_account_get_normalized_name (test->account), ==,
476 "bob.mcbadgers@example.com");
477 assert_strprop (test->account, "normalized-name",
478 "bob.mcbadgers@example.com");
479
480 g_object_get (test->account,
481 "supersedes", &strv,
482 NULL);
483 g_assert_cmpstr (strv[0], ==, SUPERSEDED_PATH);
484 g_assert_cmpstr (strv[1], ==, NULL);
485 g_strfreev (strv);
486
487 cstrv = tp_account_get_supersedes (test->account);
488 g_assert_cmpstr (cstrv[0], ==, SUPERSEDED_PATH);
489 g_assert_cmpstr (cstrv[1], ==, NULL);
490 }
491
492 static void
test_storage(Test * test,gconstpointer mode)493 test_storage (Test *test,
494 gconstpointer mode)
495 {
496 GQuark account_features[] = { TP_ACCOUNT_FEATURE_STORAGE, 0 };
497 GValue *gvalue;
498 GVariant *gvariant;
499 GHashTable *info;
500 GError *error = NULL;
501 gboolean found;
502 gint32 i;
503 guint32 u;
504 const gchar *s;
505
506 test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL);
507 g_assert (test->account != NULL);
508
509 if (g_str_equal (mode, "later"))
510 {
511 /* prepare the core feature first */
512 tp_proxy_prepare_async (test->account, NULL, account_prepare_cb, test);
513 g_main_loop_run (test->mainloop);
514
515 /* storage stuff doesn't work yet */
516 g_assert_cmpstr (tp_account_get_storage_provider (test->account), ==,
517 NULL);
518 assert_strprop (test->account, "storage-provider", NULL);
519 g_assert (tp_account_get_storage_identifier (test->account) == NULL);
520 g_object_get (test->account,
521 "storage-identifier", &gvalue,
522 NULL);
523 g_assert (gvalue == NULL);
524 g_assert (tp_account_get_storage_identifier (test->account) == NULL);
525 g_object_get (test->account,
526 "storage-identifier", &gvariant,
527 NULL);
528 g_assert (gvariant == NULL);
529 g_assert_cmpuint (tp_account_get_storage_restrictions (test->account), ==,
530 0);
531 assert_uintprop (test->account, "storage-restrictions", 0);
532 }
533
534 /* prepare the storage feature */
535 tp_proxy_prepare_async (test->account, account_features,
536 account_prepare_cb, test);
537 g_main_loop_run (test->mainloop);
538
539 g_assert_cmpstr (tp_account_get_storage_provider (test->account), ==,
540 "org.freedesktop.Telepathy.glib.test");
541 assert_strprop (test->account, "storage-provider",
542 "org.freedesktop.Telepathy.glib.test");
543
544 g_assert_cmpstr (
545 g_value_get_string (tp_account_get_storage_identifier (test->account)),
546 ==, "unique-identifier");
547 g_object_get (test->account,
548 "storage-identifier", &gvalue,
549 NULL);
550 g_assert_cmpstr (g_value_get_string (gvalue), ==, "unique-identifier");
551 g_boxed_free (G_TYPE_VALUE, gvalue);
552
553 gvariant = tp_account_dup_storage_identifier_variant (test->account);
554 g_assert_cmpstr (g_variant_get_type_string (gvariant), ==, "s");
555 g_assert_cmpstr (g_variant_get_string (gvariant, NULL), ==,
556 "unique-identifier");
557 g_variant_unref (gvariant);
558 g_object_get (test->account,
559 "storage-identifier-variant", &gvariant,
560 NULL);
561 g_assert_cmpstr (g_variant_get_type_string (gvariant), ==, "s");
562 g_assert_cmpstr (g_variant_get_string (gvariant, NULL), ==,
563 "unique-identifier");
564 g_variant_unref (gvariant);
565
566 g_assert_cmpuint (tp_account_get_storage_restrictions (test->account), ==,
567 TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_ENABLED |
568 TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PARAMETERS);
569 assert_uintprop (test->account, "storage-restrictions",
570 TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_ENABLED |
571 TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PARAMETERS);
572
573 /* request the StorageSpecificProperties hash */
574 tp_account_get_storage_specific_information_async (test->account,
575 tp_tests_result_ready_cb, &test->result);
576 tp_tests_run_until_result (&test->result);
577
578 info = tp_account_get_storage_specific_information_finish (
579 test->account, test->result, &error);
580 g_assert_no_error (error);
581
582 g_assert_cmpuint (g_hash_table_size (info), ==, 3);
583
584 g_assert_cmpint (tp_asv_get_int32 (info, "one", NULL), ==, 1);
585 g_assert_cmpuint (tp_asv_get_uint32 (info, "two", NULL), ==, 2);
586 g_assert_cmpstr (tp_asv_get_string (info, "marco"), ==, "polo");
587
588 tp_clear_object (&test->result);
589
590 /* the same, but with 100% more GVariant */
591 tp_account_dup_storage_specific_information_vardict_async (test->account,
592 tp_tests_result_ready_cb, &test->result);
593 tp_tests_run_until_result (&test->result);
594
595 gvariant = tp_account_dup_storage_specific_information_vardict_finish (
596 test->account, test->result, &error);
597 g_assert_no_error (error);
598
599 g_assert_cmpstr (g_variant_get_type_string (gvariant), ==, "a{sv}");
600 found = g_variant_lookup (gvariant, "one", "i", &i);
601 g_assert (found);
602 g_assert_cmpint (i, ==, 1);
603 found = g_variant_lookup (gvariant, "two", "u", &u);
604 g_assert (found);
605 g_assert_cmpint (u, ==, 2);
606 found = g_variant_lookup (gvariant, "marco", "&s", &s);
607 g_assert (found);
608 g_assert_cmpstr (s, ==, "polo");
609 found = g_variant_lookup (gvariant, "barisione", "&s", &s);
610 g_assert (!found);
611
612 g_variant_unref (gvariant);
613 tp_clear_object (&test->result);
614 }
615
616 static void
check_uri_schemes(const gchar * const * schemes)617 check_uri_schemes (const gchar * const * schemes)
618 {
619 g_assert (schemes != NULL);
620 g_assert (tp_strv_contains (schemes, "about"));
621 g_assert (tp_strv_contains (schemes, "telnet"));
622 g_assert (schemes[2] == NULL);
623 }
624
625 static void
notify_cb(GObject * object,GParamSpec * spec,Test * test)626 notify_cb (GObject *object,
627 GParamSpec *spec,
628 Test *test)
629 {
630 g_main_loop_quit (test->mainloop);
631 }
632
633 static void
test_addressing(Test * test,gconstpointer mode)634 test_addressing (Test *test,
635 gconstpointer mode)
636 {
637 GQuark account_features[] = { TP_ACCOUNT_FEATURE_ADDRESSING, 0 };
638 const gchar * const *schemes;
639 GStrv tmp;
640
641 test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL);
642 g_assert (test->account != NULL);
643
644 if (g_str_equal (mode, "later"))
645 {
646 /* prepare the core feature first */
647 tp_proxy_prepare_async (test->account, NULL, account_prepare_cb, test);
648 g_main_loop_run (test->mainloop);
649
650 /* addressing stuff doesn't work yet */
651 g_assert (tp_account_get_uri_schemes (test->account) == NULL);
652 g_assert (!tp_account_associated_with_uri_scheme (test->account,
653 "about"));
654 g_assert (!tp_account_associated_with_uri_scheme (test->account,
655 "telnet"));
656 g_assert (!tp_account_associated_with_uri_scheme (test->account,
657 "xmpp"));
658 }
659
660 /* prepare the addressing feature */
661 tp_proxy_prepare_async (test->account, account_features,
662 account_prepare_cb, test);
663 g_main_loop_run (test->mainloop);
664
665 schemes = tp_account_get_uri_schemes (test->account);
666 check_uri_schemes (schemes);
667
668 g_object_get (test->account,
669 "uri-schemes", &tmp,
670 NULL);
671
672 check_uri_schemes ((const gchar * const *) tmp);
673 g_strfreev (tmp);
674
675 g_assert (tp_account_associated_with_uri_scheme (test->account,
676 "about"));
677 g_assert (tp_account_associated_with_uri_scheme (test->account,
678 "telnet"));
679 g_assert (!tp_account_associated_with_uri_scheme (test->account,
680 "xmpp"));
681
682 g_signal_connect (test->account, "notify::uri-schemes",
683 G_CALLBACK (notify_cb), test);
684
685 tp_tests_simple_account_add_uri_scheme (test->account_service, "xmpp");
686 g_main_loop_run (test->mainloop);
687
688 g_assert (tp_account_associated_with_uri_scheme (test->account,
689 "xmpp"));
690 }
691
692 static void
avatar_changed_cb(TpAccount * account,Test * test)693 avatar_changed_cb (TpAccount *account,
694 Test *test)
695 {
696 g_main_loop_quit (test->mainloop);
697 }
698
699 static void
test_avatar(Test * test,gconstpointer mode)700 test_avatar (Test *test,
701 gconstpointer mode)
702 {
703 const GArray *blob;
704 GError *error = NULL;
705
706 test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL);
707 g_assert (test->account != NULL);
708
709 tp_proxy_prepare_async (test->account, NULL, account_prepare_cb, test);
710 g_main_loop_run (test->mainloop);
711
712 tp_account_get_avatar_async (test->account,
713 tp_tests_result_ready_cb, &test->result);
714 tp_tests_run_until_result (&test->result);
715
716 blob = tp_account_get_avatar_finish (
717 test->account, test->result, &error);
718 g_assert_no_error (error);
719
720 g_assert_cmpuint (blob->len, ==, 4);
721 g_assert_cmpstr (((char *) blob->data), ==, ":-)");
722
723 tp_clear_object (&test->result);
724
725 /* change the avatar */
726 g_signal_connect (test->account, "avatar-changed",
727 G_CALLBACK (avatar_changed_cb), test);
728
729 tp_tests_simple_account_set_avatar (test->account_service, ":-(");
730 g_main_loop_run (test->mainloop);
731
732 tp_account_get_avatar_async (test->account,
733 tp_tests_result_ready_cb, &test->result);
734 tp_tests_run_until_result (&test->result);
735
736 blob = tp_account_get_avatar_finish (
737 test->account, test->result, &error);
738 g_assert_no_error (error);
739
740 g_assert (blob != NULL);
741 g_assert_cmpuint (blob->len, ==, 4);
742 g_assert_cmpstr (((char *) blob->data), ==, ":-(");
743
744 tp_clear_object (&test->result);
745 }
746
747 static void
test_connection(Test * test,gconstpointer data G_GNUC_UNUSED)748 test_connection (Test *test,
749 gconstpointer data G_GNUC_UNUSED)
750 {
751 const gchar *conn1_path = tp_proxy_get_object_path (test->conn1);
752 const gchar *conn2_path = tp_proxy_get_object_path (test->conn2);
753 GQuark account_features[] = { TP_ACCOUNT_FEATURE_CORE, 0 };
754 GHashTable *change = tp_asv_new (NULL, NULL);
755 TpConnection *conn;
756 const GHashTable *details;
757 GVariant *details_v;
758 gboolean found;
759 gchar *s;
760 guint32 u;
761
762 test->account = tp_account_new (test->dbus, ACCOUNT_PATH, NULL);
763 g_assert (test->account != NULL);
764
765 tp_proxy_prepare_async (test->account, account_features,
766 account_prepare_cb, test);
767 g_main_loop_run (test->mainloop);
768
769 g_assert (tp_proxy_is_prepared (test->account, TP_ACCOUNT_FEATURE_CORE));
770
771 /* a connection turns up */
772
773 test_set_up_account_notify (test);
774 tp_asv_set_object_path (change, "Connection", conn1_path);
775 tp_asv_set_uint32 (change, "ConnectionStatus",
776 TP_CONNECTION_STATUS_CONNECTING);
777 tp_asv_set_uint32 (change, "ConnectionStatusReason",
778 TP_CONNECTION_STATUS_REASON_REQUESTED);
779 tp_svc_account_emit_account_property_changed (test->account_service, change);
780 g_hash_table_remove_all (change);
781
782 while (test_get_times_notified (test, "connection") < 1)
783 g_main_context_iteration (NULL, TRUE);
784
785 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1);
786 conn = tp_account_get_connection (test->account);
787 g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn1_path);
788 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1);
789
790 g_assert_cmpstr (tp_account_get_detailed_error (test->account, NULL), ==,
791 TP_ERROR_STR_CANCELLED);
792
793 /* ensure the same connection - no change notification */
794
795 test_set_up_account_notify (test);
796 conn = tp_account_ensure_connection (test->account, conn1_path);
797 g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn1_path);
798 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 0);
799
800 /* a no-op "change" */
801
802 test_set_up_account_notify (test);
803 tp_asv_set_object_path (change, "Connection", conn1_path);
804 tp_asv_set_uint32 (change, "ConnectionStatus",
805 TP_CONNECTION_STATUS_CONNECTING);
806 tp_asv_set_uint32 (change, "ConnectionStatusReason",
807 TP_CONNECTION_STATUS_REASON_REQUESTED);
808 tp_svc_account_emit_account_property_changed (test->account_service, change);
809 g_hash_table_remove_all (change);
810
811 tp_tests_proxy_run_until_dbus_queue_processed (test->account);
812
813 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 0);
814 conn = tp_account_get_connection (test->account);
815 g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn1_path);
816 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 0);
817
818 /* atomically flip from one connection to another (unlikely) */
819
820 test_set_up_account_notify (test);
821 tp_asv_set_object_path (change, "Connection", conn2_path);
822 tp_asv_set_uint32 (change, "ConnectionStatus",
823 TP_CONNECTION_STATUS_CONNECTED);
824 tp_asv_set_uint32 (change, "ConnectionStatusReason",
825 TP_CONNECTION_STATUS_REASON_REQUESTED);
826 tp_svc_account_emit_account_property_changed (test->account_service, change);
827 g_hash_table_remove_all (change);
828
829 while (test_get_times_notified (test, "connection") < 1)
830 g_main_context_iteration (NULL, TRUE);
831
832 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1);
833 conn = tp_account_get_connection (test->account);
834 g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn2_path);
835 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1);
836
837 /* no more connection for you */
838
839 test_set_up_account_notify (test);
840 tp_asv_set_object_path (change, "Connection", "/");
841 tp_asv_set_uint32 (change, "ConnectionStatus",
842 TP_CONNECTION_STATUS_DISCONNECTED);
843 tp_asv_set_uint32 (change, "ConnectionStatusReason",
844 TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR);
845 tp_svc_account_emit_account_property_changed (test->account_service, change);
846 g_hash_table_remove_all (change);
847
848 while (test_get_times_notified (test, "connection") < 1)
849 g_main_context_iteration (NULL, TRUE);
850
851 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1);
852 conn = tp_account_get_connection (test->account);
853 g_assert (conn == NULL);
854
855 g_assert_cmpstr (tp_account_get_detailed_error (test->account, NULL), ==,
856 TP_ERROR_STR_ENCRYPTION_ERROR);
857
858 /* another connection */
859
860 test_set_up_account_notify (test);
861 tp_asv_set_object_path (change, "Connection", conn1_path);
862 tp_asv_set_uint32 (change, "ConnectionStatus",
863 TP_CONNECTION_STATUS_CONNECTING);
864 tp_asv_set_uint32 (change, "ConnectionStatusReason",
865 TP_CONNECTION_STATUS_REASON_REQUESTED);
866 tp_svc_account_emit_account_property_changed (test->account_service, change);
867 g_hash_table_remove_all (change);
868
869 tp_tests_proxy_run_until_dbus_queue_processed (test->account);
870 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1);
871
872 /* lose the connection again */
873
874 test_set_up_account_notify (test);
875 tp_asv_set_object_path (change, "Connection", "/");
876 tp_asv_set_uint32 (change, "ConnectionStatus",
877 TP_CONNECTION_STATUS_DISCONNECTED);
878 tp_asv_set_uint32 (change, "ConnectionStatusReason",
879 TP_CONNECTION_STATUS_REASON_ENCRYPTION_ERROR);
880 tp_asv_set_static_string (change, "ConnectionError",
881 "org.debian.packages.OpenSSL.NotRandomEnough");
882 tp_asv_take_boxed (change, "ConnectionErrorDetails",
883 TP_HASH_TYPE_STRING_VARIANT_MAP,
884 tp_asv_new (
885 "bits-of-entropy", G_TYPE_UINT, 15,
886 "debug-message", G_TYPE_STRING, "shiiiiii-",
887 NULL));
888 tp_svc_account_emit_account_property_changed (test->account_service, change);
889 g_hash_table_remove_all (change);
890
891 tp_tests_proxy_run_until_dbus_queue_processed (test->account);
892 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1);
893 g_assert_cmpuint (test_get_times_notified (test, "connection-error"), ==, 1);
894
895 g_assert_cmpstr (tp_account_get_detailed_error (test->account, &details), ==,
896 "org.debian.packages.OpenSSL.NotRandomEnough");
897 g_assert_cmpuint (tp_asv_size (details), >=, 2);
898 g_assert_cmpstr (tp_asv_get_string (details, "debug-message"), ==,
899 "shiiiiii-");
900 g_assert_cmpuint (tp_asv_get_uint32 (details, "bits-of-entropy", NULL), ==,
901 15);
902
903 s = tp_account_dup_detailed_error_vardict (test->account, &details_v);
904 g_assert_cmpstr (s, ==, "org.debian.packages.OpenSSL.NotRandomEnough");
905 g_free (s);
906 g_assert_cmpuint (g_variant_n_children (details_v), >=, 2);
907 g_assert_cmpstr (g_variant_get_type_string (details_v), ==, "a{sv}");
908 found = g_variant_lookup (details_v, "debug-message", "s", &s);
909 g_assert (found);
910 g_assert_cmpstr (s, ==, "shiiiiii-");
911 g_free (s);
912 found = g_variant_lookup (details_v, "bits-of-entropy", "u", &u);
913 g_assert (found);
914 g_assert_cmpint (u, ==, 15);
915 g_variant_unref (details_v);
916
917 /* staple on a Connection (this is intended for use in e.g. observers,
918 * if they're told about a Connection that the Account hasn't told them
919 * about yet) */
920
921 test_set_up_account_notify (test);
922 conn = tp_account_ensure_connection (test->account, conn1_path);
923 g_assert_cmpstr (tp_proxy_get_object_path (conn), ==, conn1_path);
924 g_assert_cmpuint (test_get_times_notified (test, "connection"), ==, 1);
925
926 g_hash_table_unref (change);
927 }
928
929 int
main(int argc,char ** argv)930 main (int argc,
931 char **argv)
932 {
933 tp_tests_abort_after (10);
934 tp_debug_set_flags ("all");
935
936 g_test_init (&argc, &argv, NULL);
937 g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
938
939 g_test_add_data_func ("/account/parse/spaces",
940 "this is not an object path", test_parse_failure);
941 g_test_add_data_func ("/account/parse/no-prefix",
942 "/this/is/not/an/account/path", test_parse_failure);
943 g_test_add_data_func ("/account/parse/too-few-components",
944 "/org/freedesktop/Telepathy/Account/wrong", test_parse_failure);
945 g_test_add_data_func ("/account/parse/too-many-components",
946 "/org/freedesktop/Telepathy/Account/a/b/c/d", test_parse_failure);
947 g_test_add_data_func ("/account/parse/illegal-components",
948 "/org/freedesktop/Telepathy/Account/1/2/3", test_parse_failure);
949
950 g_test_add_data_func ("/account/parse/legal",
951 test_parse_data_new (
952 TP_ACCOUNT_OBJECT_PATH_BASE "gabble/jabber/badgers",
953 "gabble", "jabber", "badgers"),
954 test_parse_success);
955 g_test_add_data_func ("/account/parse/hyphenated-protocol",
956 test_parse_data_new (
957 TP_ACCOUNT_OBJECT_PATH_BASE "salut/local_xmpp/badgers",
958 "salut", "local-xmpp", "badgers"),
959 test_parse_success);
960 g_test_add_data_func ("/account/parse/wrongly-escaped-protocol",
961 test_parse_data_new (
962 TP_ACCOUNT_OBJECT_PATH_BASE "salut/local_2dxmpp/badgers",
963 "salut", "local-xmpp", "badgers"),
964 test_parse_success);
965 g_test_add_data_func ("/account/parse/wrongly-escaped-corner-case",
966 test_parse_data_new (
967 TP_ACCOUNT_OBJECT_PATH_BASE "salut/local_2d/badgers",
968 "salut", "local-", "badgers"),
969 test_parse_success);
970 g_test_add_data_func ("/account/parse/underscored-account",
971 test_parse_data_new (
972 TP_ACCOUNT_OBJECT_PATH_BASE "haze/msn/_thisseemsunlikely",
973 "haze", "msn", "_thisseemsunlikely"),
974 test_parse_success);
975
976 g_test_add ("/account/new", Test, NULL, setup, test_new, teardown);
977
978 g_test_add ("/account/setters", Test, NULL, setup_service, test_setters,
979 teardown_service);
980
981 g_test_add ("/account/reconnect", Test, NULL, setup_service, test_reconnect,
982 teardown_service);
983 g_test_add ("/account/reconnect", Test, "vardict", setup_service,
984 test_reconnect, teardown_service);
985
986 g_test_add ("/account/prepare/success", Test, NULL, setup_service,
987 test_prepare_success, teardown_service);
988
989 g_test_add ("/account/connection", Test, NULL, setup_service,
990 test_connection, teardown_service);
991
992 g_test_add ("/account/storage", Test, "first", setup_service, test_storage,
993 teardown_service);
994 g_test_add ("/account/storage", Test, "later", setup_service, test_storage,
995 teardown_service);
996
997 g_test_add ("/account/avatar", Test, NULL, setup_service, test_avatar,
998 teardown_service);
999
1000 g_test_add ("/account/addressing", Test, "first", setup_service,
1001 test_addressing, teardown_service);
1002 g_test_add ("/account/addressing", Test, "later", setup_service,
1003 test_addressing, teardown_service);
1004
1005 return tp_tests_run_with_bus ();
1006 }
1007