Merge lp:~ubuntu-branches/ubuntu/precise/telepathy-glib/precise-201111092112 into lp:ubuntu/precise/telepathy-glib

Proposed by Ubuntu Package Importer
Status: Rejected
Rejected by: James Westby
Proposed branch: lp:~ubuntu-branches/ubuntu/precise/telepathy-glib/precise-201111092112
Merge into: lp:ubuntu/precise/telepathy-glib
Diff against target: 2803 lines (+2792/-0) (has conflicts)
1 file modified
.pc/ludicrous-timeout-for-lp-buildd.patch/tests/dbus/contact-lists.c (+2792/-0)
Text conflict in .pc/ludicrous-timeout-for-lp-buildd.patch/tests/dbus/contact-lists.c
To merge this branch: bzr merge lp:~ubuntu-branches/ubuntu/precise/telepathy-glib/precise-201111092112
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+81778@code.launchpad.net

Description of the change

The package importer has detected a possible inconsistency between the package history in the archive and the history in bzr. As the archive is authoritative the importer has made lp:ubuntu/precise/telepathy-glib reflect what is in the archive and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/precise/telepathy-glib/precise-201111092112. This merge proposal was created so that an Ubuntu developer can review the situations and perform a merge/upload if necessary. There are three typical cases where this can happen.
  1. Where someone pushes a change to bzr and someone else uploads the package without that change. This is the reason that this check is done by the importer. If this appears to be the case then a merge/upload should be done if the changes that were in bzr are still desirable.
  2. The importer incorrectly detected the above situation when someone made a change in bzr and then uploaded it.
  3. The importer incorrectly detected the above situation when someone just uploaded a package and didn't touch bzr.

If this case doesn't appear to be the first situation then set the status of the merge proposal to "Rejected" and help avoid the problem in future by filing a bug at https://bugs.launchpad.net/udd linking to this merge proposal.

(this is an automatically generated message)

To post a comment you must log in.

Unmerged revisions

70. By Ken VanDine

releasing version 0.16.2-1ubuntu1

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.pc/ludicrous-timeout-for-lp-buildd.patch/tests/dbus/contact-lists.c'
2--- .pc/ludicrous-timeout-for-lp-buildd.patch/tests/dbus/contact-lists.c 2011-11-09 15:08:17 +0000
3+++ .pc/ludicrous-timeout-for-lp-buildd.patch/tests/dbus/contact-lists.c 2011-11-09 21:18:30 +0000
4@@ -1,3 +1,4 @@
5+<<<<<<< TREE
6 /* Feature test for contact lists
7 *
8 * Copyright © 2007-2010 Collabora Ltd. <http://www.collabora.co.uk/>
9@@ -2827,3 +2828,2794 @@
10
11 return g_test_run ();
12 }
13+=======
14+/* Feature test for contact lists
15+ *
16+ * Copyright © 2007-2010 Collabora Ltd. <http://www.collabora.co.uk/>
17+ * Copyright © 2007-2008 Nokia Corporation
18+ *
19+ * Copying and distribution of this file, with or without modification,
20+ * are permitted in any medium without royalty provided the copyright
21+ * notice and this notice are preserved.
22+ */
23+
24+#include <telepathy-glib/connection.h>
25+
26+#include "examples/cm/contactlist/conn.h"
27+#include "tests/lib/util.h"
28+
29+typedef enum {
30+ CONTACTS_CHANGED,
31+ GROUPS_CHANGED,
32+ GROUPS_CREATED,
33+ GROUPS_REMOVED,
34+ GROUP_RENAMED,
35+ BLOCKED_CONTACTS_CHANGED
36+} LogEntryType;
37+
38+typedef struct {
39+ LogEntryType type;
40+ /* ContactsChanged */
41+ GHashTable *contacts_changed;
42+ TpIntset *contacts_removed;
43+ /* GroupsChanged */
44+ GArray *contacts;
45+ /* GroupsChanged, GroupsCreated, GroupRenamed */
46+ GStrv groups_added;
47+ /* GroupsChanged, GroupsRemoved, GroupRenamed */
48+ GStrv groups_removed;
49+ /* BlockedContactsChanged */
50+ GHashTable *blocked_contacts;
51+ GHashTable *unblocked_contacts;
52+} LogEntry;
53+
54+static void
55+log_entry_free (LogEntry *le)
56+{
57+ if (le->contacts_changed != NULL)
58+ g_hash_table_unref (le->contacts_changed);
59+
60+ if (le->contacts_removed != NULL)
61+ tp_intset_destroy (le->contacts_removed);
62+
63+ if (le->contacts != NULL)
64+ g_array_unref (le->contacts);
65+
66+ g_strfreev (le->groups_added);
67+ g_strfreev (le->groups_removed);
68+
69+ if (le->blocked_contacts != NULL)
70+ g_hash_table_unref (le->blocked_contacts);
71+
72+ if (le->unblocked_contacts != NULL)
73+ g_hash_table_unref (le->unblocked_contacts);
74+
75+ g_slice_free (LogEntry, le);
76+}
77+
78+typedef struct {
79+ TpDBusDaemon *dbus;
80+ ExampleContactListConnection *service_conn;
81+ TpBaseConnection *service_conn_as_base;
82+ gchar *conn_name;
83+ gchar *conn_path;
84+ TpConnection *conn;
85+
86+ TpChannel *publish;
87+ TpChannel *subscribe;
88+ TpChannel *stored;
89+ TpChannel *deny;
90+
91+ TpChannel *group;
92+
93+ TpHandleRepoIface *contact_repo;
94+ TpHandle sjoerd;
95+ TpHandle helen;
96+ TpHandle wim;
97+ TpHandle bill;
98+ TpHandle ninja;
99+ TpHandle canceller;
100+
101+ GArray *arr;
102+
103+ /* list of LogEntry */
104+ GPtrArray *log;
105+
106+ GAsyncResult *prepare_result;
107+ GHashTable *contact_attributes;
108+
109+ GMainLoop *main_loop;
110+} Test;
111+
112+static void
113+test_quit_loop (gpointer p)
114+{
115+ Test *test = p;
116+
117+ g_main_loop_quit (test->main_loop);
118+}
119+
120+static void
121+contacts_changed_with_id_cb (TpConnection *connection,
122+ GHashTable *changes,
123+ GHashTable *identifiers,
124+ GHashTable *removals,
125+ gpointer user_data,
126+ GObject *weak_object G_GNUC_UNUSED)
127+{
128+ Test *test = user_data;
129+ LogEntry *le = g_slice_new0 (LogEntry);
130+ GHashTableIter i;
131+ gpointer key, value;
132+
133+ if (g_hash_table_size (changes) > 0)
134+ g_assert_cmpuint (g_hash_table_size (changes), ==,
135+ g_hash_table_size (identifiers));
136+ else
137+ g_assert_cmpuint (g_hash_table_size (removals), >, 0);
138+
139+ le->type = CONTACTS_CHANGED;
140+ le->contacts_changed = g_boxed_copy (TP_HASH_TYPE_CONTACT_SUBSCRIPTION_MAP,
141+ changes);
142+
143+ /* We asserted above that we have as many identifiers as we have changes. */
144+ g_hash_table_iter_init (&i, identifiers);
145+ while (g_hash_table_iter_next (&i, &key, &value))
146+ {
147+ TpHandle handle = GPOINTER_TO_UINT (key);
148+
149+ g_assert_cmpstr (value, ==,
150+ tp_handle_inspect (test->contact_repo, handle));
151+ }
152+
153+ le->contacts_removed = tp_intset_new ();
154+
155+ g_hash_table_iter_init (&i, removals);
156+ while (g_hash_table_iter_next (&i, &key, &value))
157+ {
158+ TpHandle handle = GPOINTER_TO_UINT (key);
159+
160+ g_assert_cmpstr (value, ==,
161+ tp_handle_inspect (test->contact_repo, handle));
162+ tp_intset_add (le->contacts_removed, handle);
163+ }
164+
165+ g_ptr_array_add (test->log, le);
166+}
167+
168+static void
169+contacts_changed_cb (TpConnection *connection,
170+ GHashTable *changes,
171+ const GArray *removals,
172+ gpointer user_data,
173+ GObject *weak_object G_GNUC_UNUSED)
174+{
175+ Test *test = user_data;
176+ LogEntry *le;
177+ GHashTableIter i;
178+ gpointer key, value;
179+ TpIntset *removal_set;
180+
181+ g_assert (g_hash_table_size (changes) > 0 || removals->len > 0);
182+
183+ /* We should have had a ContactsChangedByID signal immediately before this
184+ * signal */
185+ g_assert_cmpuint (test->log->len, >, 0);
186+
187+ le = g_ptr_array_index (test->log, test->log->len - 1);
188+ g_assert_cmpuint (le->type, ==, CONTACTS_CHANGED);
189+
190+ /* The changes should all have been the same as in the previous signal */
191+ g_assert_cmpuint (g_hash_table_size (changes), ==,
192+ g_hash_table_size (le->contacts_changed));
193+
194+ g_hash_table_iter_init (&i, changes);
195+ while (g_hash_table_iter_next (&i, &key, &value))
196+ {
197+ GValueArray *existing = g_hash_table_lookup (le->contacts_changed, key);
198+ GValueArray *emitted = value;
199+ guint existing_sub, existing_pub, emitted_sub, emitted_pub;
200+ const gchar *existing_req, *emitted_req;
201+
202+ g_assert (existing != NULL);
203+
204+ tp_value_array_unpack (existing, 3, &existing_sub, &existing_pub,
205+ &existing_req);
206+ tp_value_array_unpack (emitted, 3, &emitted_sub, &emitted_pub,
207+ &emitted_req);
208+
209+ g_assert_cmpuint (existing_sub, ==, emitted_sub);
210+ g_assert_cmpuint (existing_pub, ==, emitted_pub);
211+ g_assert_cmpstr (existing_req, ==, emitted_req);
212+ }
213+
214+ removal_set = tp_intset_from_array (removals);
215+
216+ if (!tp_intset_is_equal (removal_set, le->contacts_removed))
217+ g_error ("Removals from ContactsChangedById (%s) != "
218+ "Removals from ContactsChanged (%s)",
219+ tp_intset_dump (le->contacts_removed),
220+ tp_intset_dump (removal_set));
221+
222+ tp_intset_destroy (removal_set);
223+}
224+
225+static void
226+groups_changed_cb (TpConnection *connection,
227+ const GArray *contacts,
228+ const gchar **groups_added,
229+ const gchar **groups_removed,
230+ gpointer user_data,
231+ GObject *weak_object G_GNUC_UNUSED)
232+{
233+ Test *test = user_data;
234+ LogEntry *le = g_slice_new0 (LogEntry);
235+
236+ g_assert (contacts->len > 0);
237+ g_assert ((groups_added != NULL && groups_added[0] != NULL) ||
238+ (groups_removed != NULL && groups_removed[0] != NULL));
239+
240+ le->type = GROUPS_CHANGED;
241+ le->contacts = g_array_sized_new (FALSE, FALSE, sizeof (guint),
242+ contacts->len);
243+ g_array_append_vals (le->contacts, contacts->data, contacts->len);
244+ le->groups_added = g_strdupv ((GStrv) groups_added);
245+ le->groups_removed = g_strdupv ((GStrv) groups_removed);
246+
247+ g_ptr_array_add (test->log, le);
248+}
249+
250+static void
251+groups_created_cb (TpConnection *connection,
252+ const gchar **groups_added,
253+ gpointer user_data,
254+ GObject *weak_object G_GNUC_UNUSED)
255+{
256+ Test *test = user_data;
257+ LogEntry *le = g_slice_new0 (LogEntry);
258+
259+ g_assert (groups_added != NULL);
260+ g_assert (groups_added[0] != NULL);
261+
262+ le->type = GROUPS_CREATED;
263+ le->groups_added = g_strdupv ((GStrv) groups_added);
264+
265+ g_ptr_array_add (test->log, le);
266+}
267+
268+static void
269+groups_removed_cb (TpConnection *connection,
270+ const gchar **groups_removed,
271+ gpointer user_data,
272+ GObject *weak_object G_GNUC_UNUSED)
273+{
274+ Test *test = user_data;
275+ LogEntry *le = g_slice_new0 (LogEntry);
276+
277+ g_assert (groups_removed != NULL);
278+ g_assert (groups_removed[0] != NULL);
279+
280+ le->type = GROUPS_REMOVED;
281+ le->groups_removed = g_strdupv ((GStrv) groups_removed);
282+
283+ g_ptr_array_add (test->log, le);
284+}
285+
286+static void
287+group_renamed_cb (TpConnection *connection,
288+ const gchar *old_name,
289+ const gchar *new_name,
290+ gpointer user_data,
291+ GObject *weak_object G_GNUC_UNUSED)
292+{
293+ Test *test = user_data;
294+ LogEntry *le = g_slice_new0 (LogEntry);
295+
296+ le->type = GROUP_RENAMED;
297+ le->groups_added = g_new0 (gchar *, 2);
298+ le->groups_added[0] = g_strdup (new_name);
299+ le->groups_removed = g_new0 (gchar *, 2);
300+ le->groups_removed[0] = g_strdup (old_name);
301+
302+ g_ptr_array_add (test->log, le);
303+}
304+
305+static void
306+blocked_contacts_changed_cb (TpConnection *connection,
307+ GHashTable *blocked_contacts,
308+ GHashTable *unblocked_contacts,
309+ gpointer user_data,
310+ GObject *weak_object G_GNUC_UNUSED)
311+{
312+ Test *test = user_data;
313+ LogEntry *le = g_slice_new0 (LogEntry);
314+
315+ le->type = BLOCKED_CONTACTS_CHANGED;
316+ le->blocked_contacts = g_hash_table_ref (blocked_contacts);
317+ le->unblocked_contacts = g_hash_table_ref (unblocked_contacts);
318+
319+ g_ptr_array_add (test->log, le);
320+}
321+
322+static void
323+maybe_queue_disconnect (TpProxySignalConnection *sc)
324+{
325+ if (sc != NULL)
326+ g_test_queue_destroy (
327+ (GDestroyNotify) tp_proxy_signal_connection_disconnect, sc);
328+}
329+
330+static void
331+setup_pre_connect (
332+ Test *test,
333+ gconstpointer data)
334+{
335+ GError *error = NULL;
336+ const gchar *account;
337+
338+ g_type_init ();
339+ tp_debug_set_flags ("all");
340+ test->dbus = tp_tests_dbus_daemon_dup_or_die ();
341+ test->main_loop = g_main_loop_new (NULL, FALSE);
342+
343+ /* Some tests want 'account' to be an invalid identifier, so that Connect()
344+ * will fail (and the status will change to Disconnected).
345+ */
346+ if (!tp_strdiff (data, "break-account-parameter"))
347+ account = "";
348+ else
349+ account = "me@example.com";
350+
351+ test->service_conn = tp_tests_object_new_static_class (
352+ EXAMPLE_TYPE_CONTACT_LIST_CONNECTION,
353+ "account", account,
354+ "simulation-delay", 0,
355+ "protocol", "example-contact-list",
356+ NULL);
357+ test->service_conn_as_base = TP_BASE_CONNECTION (test->service_conn);
358+ g_assert (test->service_conn != NULL);
359+ g_assert (test->service_conn_as_base != NULL);
360+
361+ g_assert (tp_base_connection_register (test->service_conn_as_base, "example",
362+ &test->conn_name, &test->conn_path, &error));
363+ g_assert_no_error (error);
364+
365+ test->contact_repo = tp_base_connection_get_handles (
366+ test->service_conn_as_base, TP_HANDLE_TYPE_CONTACT);
367+
368+ test->conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
369+ &error);
370+ g_assert (test->conn != NULL);
371+ g_assert_no_error (error);
372+
373+ /* Prepare the connection far enough to know its own interfaces. */
374+ tp_tests_proxy_run_until_prepared (test->conn, NULL);
375+}
376+
377+static void
378+setup (Test *test,
379+ gconstpointer data)
380+{
381+ GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
382+
383+ setup_pre_connect (test, data);
384+
385+ tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL);
386+ tp_tests_proxy_run_until_prepared (test->conn, features);
387+
388+ g_assert (tp_proxy_is_prepared (test->conn, TP_CONNECTION_FEATURE_CORE));
389+ g_assert (tp_proxy_is_prepared (test->conn,
390+ TP_CONNECTION_FEATURE_CONNECTED));
391+
392+ test->log = g_ptr_array_new ();
393+
394+ maybe_queue_disconnect (
395+ tp_cli_connection_interface_contact_list_connect_to_contacts_changed_with_id (
396+ test->conn, contacts_changed_with_id_cb, test, NULL, NULL, NULL));
397+ maybe_queue_disconnect (
398+ tp_cli_connection_interface_contact_list_connect_to_contacts_changed (
399+ test->conn, contacts_changed_cb, test, NULL, NULL, NULL));
400+ maybe_queue_disconnect (
401+ tp_cli_connection_interface_contact_groups_connect_to_groups_changed (
402+ test->conn, groups_changed_cb, test, NULL, NULL, NULL));
403+ maybe_queue_disconnect (
404+ tp_cli_connection_interface_contact_groups_connect_to_groups_created (
405+ test->conn, groups_created_cb, test, NULL, NULL, NULL));
406+ maybe_queue_disconnect (
407+ tp_cli_connection_interface_contact_groups_connect_to_groups_removed (
408+ test->conn, groups_removed_cb, test, NULL, NULL, NULL));
409+ maybe_queue_disconnect (
410+ tp_cli_connection_interface_contact_groups_connect_to_group_renamed (
411+ test->conn, group_renamed_cb, test, NULL, NULL, NULL));
412+ maybe_queue_disconnect (
413+ tp_cli_connection_interface_contact_blocking_connect_to_blocked_contacts_changed (
414+ test->conn, blocked_contacts_changed_cb, test, NULL, NULL, NULL));
415+
416+ test->sjoerd = tp_handle_ensure (test->contact_repo, "sjoerd@example.com",
417+ NULL, NULL);
418+ g_assert (test->sjoerd != 0);
419+ test->helen = tp_handle_ensure (test->contact_repo, "helen@example.com",
420+ NULL, NULL);
421+ g_assert (test->helen != 0);
422+ test->wim = tp_handle_ensure (test->contact_repo, "wim@example.com",
423+ NULL, NULL);
424+ g_assert (test->wim != 0);
425+ test->bill = tp_handle_ensure (test->contact_repo, "bill@example.com",
426+ NULL, NULL);
427+ g_assert (test->bill != 0);
428+ test->ninja = tp_handle_ensure (test->contact_repo, "ninja@example.com",
429+ NULL, NULL);
430+ g_assert (test->ninja != 0);
431+ test->canceller = tp_handle_ensure (test->contact_repo,
432+ "canceller@cancel.example.com", NULL, NULL);
433+ g_assert (test->canceller != 0);
434+
435+ test->arr = g_array_new (FALSE, FALSE, sizeof (TpHandle));
436+}
437+
438+static void
439+test_clear_log (Test *test)
440+{
441+ g_ptr_array_foreach (test->log, (GFunc) log_entry_free, NULL);
442+ g_ptr_array_set_size (test->log, 0);
443+}
444+
445+static void
446+teardown_pre_connect (
447+ Test *test,
448+ gconstpointer data)
449+{
450+ test->service_conn_as_base = NULL;
451+ g_object_unref (test->service_conn);
452+ g_free (test->conn_name);
453+ g_free (test->conn_path);
454+ tp_clear_object (&test->conn);
455+ tp_clear_object (&test->dbus);
456+ tp_clear_pointer (&test->main_loop, g_main_loop_unref);
457+}
458+
459+static void
460+teardown (Test *test,
461+ gconstpointer data)
462+{
463+ TpConnection *conn;
464+ gboolean ok;
465+ GError *error = NULL;
466+
467+ g_array_free (test->arr, TRUE);
468+
469+ test_clear_log (test);
470+ g_ptr_array_free (test->log, TRUE);
471+
472+ tp_handle_unref (test->contact_repo, test->sjoerd);
473+ tp_handle_unref (test->contact_repo, test->helen);
474+ tp_handle_unref (test->contact_repo, test->wim);
475+ tp_handle_unref (test->contact_repo, test->bill);
476+ tp_handle_unref (test->contact_repo, test->ninja);
477+ tp_handle_unref (test->contact_repo, test->canceller);
478+
479+ tp_clear_object (&test->publish);
480+ tp_clear_object (&test->subscribe);
481+ tp_clear_object (&test->stored);
482+ tp_clear_object (&test->group);
483+
484+ /* make a new TpConnection just to disconnect the underlying Connection,
485+ * so we don't leak it */
486+ conn = tp_connection_new (test->dbus, test->conn_name, test->conn_path,
487+ &error);
488+ g_assert (conn != NULL);
489+ g_assert_no_error (error);
490+ ok = tp_cli_connection_run_disconnect (conn, -1, &error, NULL);
491+ g_assert (ok);
492+ g_assert_no_error (error);
493+ g_assert (!tp_connection_run_until_ready (conn, FALSE, &error, NULL));
494+ g_assert_error (error, TP_ERRORS, TP_ERROR_CANCELLED);
495+ g_clear_error (&error);
496+
497+ tp_clear_pointer (&test->contact_attributes, g_hash_table_unref);
498+
499+ teardown_pre_connect (test, data);
500+}
501+
502+static TpChannel *
503+test_ensure_channel (Test *test,
504+ guint channel_type,
505+ const gchar *id)
506+{
507+ GError *error = NULL;
508+ GHashTable *asv, *props;
509+ gchar *path;
510+ TpChannel *ret;
511+
512+ asv = tp_asv_new (
513+ TP_PROP_CHANNEL_CHANNEL_TYPE,
514+ G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_CONTACT_LIST,
515+ TP_PROP_CHANNEL_TARGET_HANDLE_TYPE,
516+ G_TYPE_UINT, channel_type,
517+ TP_PROP_CHANNEL_TARGET_ID,
518+ G_TYPE_STRING, id,
519+ NULL);
520+ tp_cli_connection_interface_requests_run_ensure_channel (test->conn, -1,
521+ asv, NULL, &path, &props, &error, NULL);
522+ g_assert_no_error (error);
523+ ret = tp_channel_new_from_properties (test->conn, path, props,
524+ &error);
525+ g_assert (ret != NULL);
526+ g_assert_no_error (error);
527+ g_free (path);
528+ g_hash_table_unref (props);
529+ g_hash_table_unref (asv);
530+
531+ tp_tests_proxy_run_until_prepared (ret, NULL);
532+ return ret;
533+}
534+
535+static void
536+test_assert_one_contact_changed (Test *test,
537+ guint index,
538+ TpHandle handle,
539+ TpSubscriptionState expected_sub_state,
540+ TpSubscriptionState expected_pub_state,
541+ const gchar *expected_pub_request)
542+{
543+ LogEntry *le;
544+ GValueArray *va;
545+ guint sub_state;
546+ guint pub_state;
547+ const gchar *pub_request;
548+
549+ le = g_ptr_array_index (test->log, index);
550+ g_assert_cmpint (le->type, ==, CONTACTS_CHANGED);
551+
552+ g_assert_cmpuint (g_hash_table_size (le->contacts_changed), ==, 1);
553+ va = g_hash_table_lookup (le->contacts_changed, GUINT_TO_POINTER (handle));
554+ g_assert (va != NULL);
555+ tp_value_array_unpack (va, 3,
556+ &sub_state,
557+ &pub_state,
558+ &pub_request);
559+ g_assert_cmpuint (sub_state, ==, expected_sub_state);
560+ g_assert_cmpuint (pub_state, ==, expected_pub_state);
561+ g_assert_cmpstr (pub_request, ==, expected_pub_request);
562+
563+ g_assert_cmpuint (tp_intset_size (le->contacts_removed), ==, 0);
564+}
565+
566+static void
567+test_assert_one_contact_removed (Test *test,
568+ guint index,
569+ TpHandle handle)
570+{
571+ LogEntry *le;
572+
573+ le = g_ptr_array_index (test->log, index);
574+ g_assert_cmpint (le->type, ==, CONTACTS_CHANGED);
575+
576+ g_assert_cmpuint (g_hash_table_size (le->contacts_changed), ==, 0);
577+ g_assert_cmpuint (tp_intset_size (le->contacts_removed), ==, 1);
578+ g_assert (tp_intset_is_member (le->contacts_removed, handle));
579+}
580+
581+static void
582+test_assert_one_group_joined (Test *test,
583+ guint index,
584+ TpHandle handle,
585+ const gchar *group)
586+{
587+ LogEntry *le;
588+
589+ le = g_ptr_array_index (test->log, index);
590+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
591+ g_assert_cmpuint (le->contacts->len, ==, 1);
592+ g_assert_cmpuint (g_array_index (le->contacts, guint, 0), ==, handle);
593+ g_assert (le->groups_added != NULL);
594+ g_assert_cmpstr (le->groups_added[0], ==, group);
595+ g_assert_cmpstr (le->groups_added[1], ==, NULL);
596+ g_assert (le->groups_removed == NULL || le->groups_removed[0] == NULL);
597+}
598+
599+static void
600+test_assert_one_group_left (Test *test,
601+ guint index,
602+ TpHandle handle,
603+ const gchar *group)
604+{
605+ LogEntry *le;
606+
607+ le = g_ptr_array_index (test->log, index);
608+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
609+ g_assert_cmpuint (le->contacts->len, ==, 1);
610+ g_assert_cmpuint (g_array_index (le->contacts, guint, 0), ==, handle);
611+ g_assert (le->groups_added == NULL || le->groups_added[0] == NULL);
612+ g_assert (le->groups_removed != NULL);
613+ g_assert_cmpstr (le->groups_removed[0], ==, group);
614+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
615+}
616+
617+static void
618+test_assert_one_group_created (Test *test,
619+ guint index,
620+ const gchar *group)
621+{
622+ LogEntry *le;
623+
624+ le = g_ptr_array_index (test->log, index);
625+ g_assert_cmpint (le->type, ==, GROUPS_CREATED);
626+ g_assert (le->groups_added != NULL);
627+ g_assert_cmpstr (le->groups_added[0], ==, group);
628+ g_assert_cmpstr (le->groups_added[1], ==, NULL);
629+}
630+
631+static void
632+test_assert_one_group_removed (Test *test,
633+ guint index,
634+ const gchar *group)
635+{
636+ LogEntry *le;
637+
638+ le = g_ptr_array_index (test->log, index);
639+ g_assert_cmpint (le->type, ==, GROUPS_REMOVED);
640+ g_assert (le->groups_removed != NULL);
641+ g_assert_cmpstr (le->groups_removed[0], ==, group);
642+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
643+}
644+
645+static void
646+test_assert_one_contact_blocked (Test *test,
647+ guint index,
648+ TpHandle handle,
649+ const gchar *id)
650+{
651+ LogEntry *le;
652+
653+ le = g_ptr_array_index (test->log, index);
654+ g_assert_cmpint (le->type, ==, BLOCKED_CONTACTS_CHANGED);
655+
656+ g_assert (le->blocked_contacts != NULL);
657+ g_assert_cmpuint (g_hash_table_size (le->blocked_contacts), ==, 1);
658+ g_assert_cmpstr (g_hash_table_lookup (le->blocked_contacts, GUINT_TO_POINTER (handle)),
659+ ==, id);
660+
661+ g_assert (le->unblocked_contacts != NULL);
662+ g_assert_cmpuint (g_hash_table_size (le->unblocked_contacts), ==, 0);
663+}
664+
665+static void
666+test_assert_one_contact_unblocked (Test *test,
667+ guint index,
668+ TpHandle handle,
669+ const gchar *id)
670+{
671+ LogEntry *le;
672+
673+ le = g_ptr_array_index (test->log, index);
674+ g_assert_cmpint (le->type, ==, BLOCKED_CONTACTS_CHANGED);
675+
676+ g_assert (le->blocked_contacts != NULL);
677+ g_assert_cmpuint (g_hash_table_size (le->blocked_contacts), ==, 0);
678+
679+ g_assert (le->unblocked_contacts != NULL);
680+ g_assert_cmpuint (g_hash_table_size (le->unblocked_contacts), ==, 1);
681+ g_assert_cmpstr (g_hash_table_lookup (le->unblocked_contacts, GUINT_TO_POINTER (handle)),
682+ ==, id);
683+}
684+
685+static void
686+test_nothing (Test *test,
687+ gconstpointer nil G_GNUC_UNUSED)
688+{
689+ /* this is actually a valuable test - it ensures that shutting down the
690+ * CM before the contact list has been retrieved works! */
691+}
692+
693+static void
694+test_initial_channels (Test *test,
695+ gconstpointer nil G_GNUC_UNUSED)
696+{
697+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
698+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST,
699+ "subscribe");
700+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
701+ test->deny = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "deny");
702+
703+ g_assert_cmpuint (
704+ tp_intset_size (tp_channel_group_get_members (test->publish)), ==, 4);
705+ g_assert_cmpuint (
706+ tp_intset_size (tp_channel_group_get_local_pending (test->publish)),
707+ ==, 2);
708+ g_assert_cmpuint (
709+ tp_intset_size (tp_channel_group_get_remote_pending (test->publish)),
710+ ==, 0);
711+ g_assert (tp_intset_is_member (tp_channel_group_get_members (test->publish),
712+ test->sjoerd));
713+ g_assert (tp_intset_is_member (
714+ tp_channel_group_get_local_pending (test->publish),
715+ test->wim));
716+
717+ g_assert_cmpuint (
718+ tp_intset_size (tp_channel_group_get_members (test->subscribe)), ==, 4);
719+ g_assert_cmpuint (
720+ tp_intset_size (tp_channel_group_get_local_pending (test->subscribe)),
721+ ==, 0);
722+ g_assert_cmpuint (
723+ tp_intset_size (tp_channel_group_get_remote_pending (test->subscribe)),
724+ ==, 2);
725+ g_assert (tp_intset_is_member (
726+ tp_channel_group_get_members (test->subscribe),
727+ test->sjoerd));
728+ g_assert (tp_intset_is_member (
729+ tp_channel_group_get_remote_pending (test->subscribe),
730+ test->helen));
731+
732+ g_assert_cmpuint (
733+ tp_intset_size (tp_channel_group_get_members (test->stored)), ==, 8);
734+ g_assert_cmpuint (
735+ tp_intset_size (tp_channel_group_get_local_pending (test->stored)),
736+ ==, 0);
737+ g_assert_cmpuint (
738+ tp_intset_size (tp_channel_group_get_remote_pending (test->stored)),
739+ ==, 0);
740+ g_assert (tp_intset_is_member (tp_channel_group_get_members (test->stored),
741+ test->sjoerd));
742+
743+ g_assert (!tp_intset_is_member (tp_channel_group_get_members (test->publish),
744+ test->ninja));
745+ g_assert (!tp_intset_is_member (tp_channel_group_get_members (
746+ test->subscribe),
747+ test->ninja));
748+ g_assert (!tp_intset_is_member (tp_channel_group_get_members (test->stored),
749+ test->ninja));
750+
751+ g_assert_cmpuint (
752+ tp_intset_size (tp_channel_group_get_members (test->deny)), ==, 2);
753+ g_assert_cmpuint (
754+ tp_intset_size (tp_channel_group_get_local_pending (test->deny)),
755+ ==, 0);
756+ g_assert_cmpuint (
757+ tp_intset_size (tp_channel_group_get_remote_pending (test->deny)),
758+ ==, 0);
759+ g_assert (tp_intset_is_member (tp_channel_group_get_members (test->deny),
760+ test->bill));
761+}
762+
763+static void
764+test_properties (Test *test,
765+ gconstpointer nil G_GNUC_UNUSED)
766+{
767+ GHashTable *asv;
768+ GError *error = NULL;
769+ guint32 blocking_caps;
770+ gboolean valid;
771+
772+ tp_cli_dbus_properties_run_get_all (test->conn, -1,
773+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST, &asv, &error, NULL);
774+ g_assert_no_error (error);
775+ g_assert_cmpuint (g_hash_table_size (asv), >=, 3);
776+ g_assert (tp_asv_get_boolean (asv, "ContactListPersists", NULL));
777+ g_assert (tp_asv_get_boolean (asv, "CanChangeContactList", NULL));
778+ g_assert (tp_asv_get_boolean (asv, "RequestUsesMessage", NULL));
779+ g_hash_table_unref (asv);
780+
781+ tp_cli_dbus_properties_run_get_all (test->conn, -1,
782+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS, &asv, &error, NULL);
783+ g_assert_no_error (error);
784+ g_assert_cmpuint (g_hash_table_size (asv), >=, 3);
785+ g_assert (G_VALUE_HOLDS_BOOLEAN (tp_asv_lookup (asv, "DisjointGroups")));
786+ g_assert (!tp_asv_get_boolean (asv, "DisjointGroups", NULL));
787+ g_assert (G_VALUE_HOLDS_UINT (tp_asv_lookup (asv, "GroupStorage")));
788+ g_assert_cmpuint (tp_asv_get_uint32 (asv, "GroupStorage", NULL), ==,
789+ TP_CONTACT_METADATA_STORAGE_TYPE_ANYONE);
790+ /* Don't assert about the contents yet - we might not have received the
791+ * contact list yet */
792+ g_assert (G_VALUE_HOLDS (tp_asv_lookup (asv, "Groups"), G_TYPE_STRV));
793+ g_hash_table_unref (asv);
794+
795+ /* this has the side-effect of waiting for the contact list to be received */
796+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
797+
798+ tp_cli_dbus_properties_run_get_all (test->conn, -1,
799+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST, &asv, &error, NULL);
800+ g_assert_no_error (error);
801+ g_assert_cmpuint (g_hash_table_size (asv), >=, 3);
802+ g_assert (tp_asv_get_boolean (asv, "ContactListPersists", NULL));
803+ g_assert (tp_asv_get_boolean (asv, "CanChangeContactList", NULL));
804+ g_assert (tp_asv_get_boolean (asv, "RequestUsesMessage", NULL));
805+ g_hash_table_unref (asv);
806+
807+ tp_cli_dbus_properties_run_get_all (test->conn, -1,
808+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS, &asv, &error, NULL);
809+ g_assert_no_error (error);
810+ g_assert_cmpuint (g_hash_table_size (asv), >=, 3);
811+ g_assert (G_VALUE_HOLDS_BOOLEAN (tp_asv_lookup (asv, "DisjointGroups")));
812+ g_assert (G_VALUE_HOLDS_UINT (tp_asv_lookup (asv, "GroupStorage")));
813+ g_assert (tp_asv_get_strv (asv, "Groups") != NULL);
814+ g_assert (tp_strv_contains (tp_asv_get_strv (asv, "Groups"), "Cambridge"));
815+ g_assert (tp_strv_contains (tp_asv_get_strv (asv, "Groups"), "Montreal"));
816+ g_assert (tp_strv_contains (tp_asv_get_strv (asv, "Groups"),
817+ "Francophones"));
818+ g_hash_table_unref (asv);
819+
820+ tp_cli_dbus_properties_run_get_all (test->conn, -1,
821+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING, &asv, &error, NULL);
822+ g_assert_no_error (error);
823+ g_assert_cmpuint (g_hash_table_size (asv), ==, 1);
824+ blocking_caps = tp_asv_get_uint32 (asv, "ContactBlockingCapabilities",
825+ &valid);
826+ g_assert (valid);
827+ g_assert_cmpuint (blocking_caps, ==, 0);
828+ g_hash_table_unref (asv);
829+
830+ g_assert_cmpuint (test->log->len, ==, 0);
831+}
832+
833+static void
834+contact_attrs_cb (TpConnection *conn G_GNUC_UNUSED,
835+ GHashTable *attributes,
836+ const GError *error,
837+ gpointer user_data,
838+ GObject *object G_GNUC_UNUSED)
839+{
840+ Test *test = user_data;
841+
842+ g_assert_no_error ((GError *) error);
843+ tp_clear_pointer (&test->contact_attributes, g_hash_table_unref);
844+ test->contact_attributes = g_boxed_copy (TP_HASH_TYPE_CONTACT_ATTRIBUTES_MAP,
845+ attributes);
846+}
847+
848+static void
849+test_assert_contact_list_attrs (Test *test,
850+ TpHandle handle,
851+ TpSubscriptionState expected_sub_state,
852+ TpSubscriptionState expected_pub_state,
853+ const gchar *expected_pub_request)
854+{
855+ GHashTable *asv;
856+ gboolean valid;
857+
858+ g_assert_cmpuint (g_hash_table_size (test->contact_attributes), >=, 1);
859+ asv = g_hash_table_lookup (test->contact_attributes,
860+ GUINT_TO_POINTER (handle));
861+ g_assert (asv != NULL);
862+ g_assert_cmpuint (tp_asv_get_uint32 (asv,
863+ TP_TOKEN_CONNECTION_INTERFACE_CONTACT_LIST_SUBSCRIBE, &valid), ==,
864+ expected_sub_state);
865+ g_assert (valid);
866+ g_assert_cmpuint (tp_asv_get_uint32 (asv,
867+ TP_TOKEN_CONNECTION_INTERFACE_CONTACT_LIST_PUBLISH, &valid), ==,
868+ expected_pub_state);
869+ g_assert (valid);
870+ g_assert_cmpstr (tp_asv_get_string (asv,
871+ TP_TOKEN_CONNECTION_INTERFACE_CONTACT_LIST_PUBLISH_REQUEST), ==,
872+ expected_pub_request);
873+ g_assert (valid);
874+}
875+
876+/* We simplify here by assuming that contacts are in at most one group,
877+ * which happens to be true for all of these tests. */
878+static void
879+test_assert_contact_groups_attr (Test *test,
880+ TpHandle handle,
881+ const gchar *group)
882+{
883+ GHashTable *asv;
884+ const gchar * const *strv;
885+
886+ g_assert_cmpuint (g_hash_table_size (test->contact_attributes), >=, 1);
887+ asv = g_hash_table_lookup (test->contact_attributes,
888+ GUINT_TO_POINTER (handle));
889+ g_assert (asv != NULL);
890+ tp_asv_dump (asv);
891+ g_assert (tp_asv_lookup (asv,
892+ TP_TOKEN_CONNECTION_INTERFACE_CONTACT_GROUPS_GROUPS) != NULL);
893+ g_assert (G_VALUE_HOLDS (tp_asv_lookup (asv,
894+ TP_TOKEN_CONNECTION_INTERFACE_CONTACT_GROUPS_GROUPS), G_TYPE_STRV));
895+ strv = tp_asv_get_strv (asv,
896+ TP_TOKEN_CONNECTION_INTERFACE_CONTACT_GROUPS_GROUPS);
897+
898+ if (group == NULL)
899+ {
900+ if (strv != NULL)
901+ g_assert_cmpstr (strv[0], ==, NULL);
902+ }
903+ else
904+ {
905+ g_assert (strv != NULL);
906+ g_assert_cmpstr (strv[0], ==, group);
907+ g_assert_cmpstr (strv[1], ==, NULL);
908+ }
909+}
910+
911+static void
912+test_assert_contact_state (Test *test,
913+ TpHandle handle,
914+ TpSubscriptionState expected_sub_state,
915+ TpSubscriptionState expected_pub_state,
916+ const gchar *expected_pub_request,
917+ const gchar *expected_group)
918+{
919+ const gchar * const interfaces[] = {
920+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_LIST,
921+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS,
922+ NULL };
923+
924+ tp_connection_get_contact_attributes (test->conn, -1,
925+ 1, &handle, interfaces, FALSE, contact_attrs_cb,
926+ test, test_quit_loop, NULL);
927+ g_main_loop_run (test->main_loop);
928+
929+ g_assert_cmpuint (g_hash_table_size (test->contact_attributes), ==, 1);
930+ test_assert_contact_list_attrs (test, handle, expected_sub_state,
931+ expected_pub_state, expected_pub_request);
932+ test_assert_contact_groups_attr (test, handle, expected_group);
933+}
934+
935+static void
936+test_contacts (Test *test,
937+ gconstpointer nil G_GNUC_UNUSED)
938+{
939+ /* ensure the contact list has been received */
940+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
941+
942+ test_assert_contact_state (test, test->sjoerd,
943+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, "Cambridge");
944+ test_assert_contact_state (test, test->wim,
945+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_ASK,
946+ "I'm more metal than you!", NULL);
947+ test_assert_contact_state (test, test->helen,
948+ TP_SUBSCRIPTION_STATE_ASK, TP_SUBSCRIPTION_STATE_NO, NULL, "Cambridge");
949+ test_assert_contact_state (test, test->ninja,
950+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
951+ test_assert_contact_state (test, test->bill,
952+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
953+}
954+
955+static void
956+test_contact_list_attrs (Test *test,
957+ gconstpointer nil G_GNUC_UNUSED)
958+{
959+ const gchar * const interfaces[] = {
960+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_GROUPS,
961+ NULL };
962+
963+ tp_connection_get_contact_list_attributes (test->conn, -1,
964+ interfaces, FALSE, contact_attrs_cb, test, test_quit_loop, NULL);
965+ g_main_loop_run (test->main_loop);
966+
967+ test_assert_contact_list_attrs (test, test->sjoerd,
968+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL);
969+ test_assert_contact_list_attrs (test, test->wim,
970+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_ASK,
971+ "I'm more metal than you!");
972+ test_assert_contact_list_attrs (test, test->helen,
973+ TP_SUBSCRIPTION_STATE_ASK, TP_SUBSCRIPTION_STATE_NO, NULL);
974+
975+ test_assert_contact_groups_attr (test, test->sjoerd, "Cambridge");
976+ test_assert_contact_groups_attr (test, test->wim, NULL);
977+ test_assert_contact_groups_attr (test, test->helen, "Cambridge");
978+
979+ /* bill is blocked, but is not on the contact list as such; the ninja isn't
980+ * in the initial state at all */
981+ g_assert (g_hash_table_lookup (test->contact_attributes,
982+ GUINT_TO_POINTER (test->bill)) == NULL);
983+ g_assert (g_hash_table_lookup (test->contact_attributes,
984+ GUINT_TO_POINTER (test->ninja)) == NULL);
985+}
986+
987+static void
988+test_accept_publish_request (Test *test,
989+ gconstpointer mode)
990+{
991+ GError *error = NULL;
992+
993+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
994+
995+ g_assert_cmpuint (
996+ tp_intset_size (tp_channel_group_get_local_pending (test->publish)),
997+ ==, 2);
998+ g_assert (tp_intset_is_member (
999+ tp_channel_group_get_local_pending (test->publish),
1000+ test->wim));
1001+
1002+ g_array_append_val (test->arr, test->wim);
1003+
1004+ if (!tp_strdiff (mode, "old"))
1005+ tp_cli_channel_interface_group_run_add_members (test->publish,
1006+ -1, test->arr, "", &error, NULL);
1007+ else
1008+ tp_cli_connection_interface_contact_list_run_authorize_publication (
1009+ test->conn, -1, test->arr, &error, NULL);
1010+
1011+ g_assert_no_error (error);
1012+
1013+ /* by the time the method returns, we should have had the
1014+ * change-notification, too */
1015+ g_assert_cmpuint (
1016+ tp_intset_size (tp_channel_group_get_local_pending (test->publish)),
1017+ ==, 1);
1018+ g_assert (tp_intset_is_member (
1019+ tp_channel_group_get_members (test->publish),
1020+ test->wim));
1021+ g_assert (!tp_intset_is_member (
1022+ tp_channel_group_get_local_pending (test->publish),
1023+ test->wim));
1024+
1025+ g_assert_cmpuint (test->log->len, ==, 1);
1026+ test_assert_one_contact_changed (test, 0, test->wim, TP_SUBSCRIPTION_STATE_NO,
1027+ TP_SUBSCRIPTION_STATE_YES, "");
1028+ test_assert_contact_state (test, test->wim,
1029+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_YES, NULL, NULL);
1030+}
1031+
1032+static void
1033+test_reject_publish_request (Test *test,
1034+ gconstpointer mode)
1035+{
1036+ GError *error = NULL;
1037+
1038+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1039+
1040+ g_assert (tp_intset_is_member (
1041+ tp_channel_group_get_local_pending (test->publish),
1042+ test->wim));
1043+ g_assert (!tp_intset_is_member (
1044+ tp_channel_group_get_members (test->publish),
1045+ test->wim));
1046+
1047+ g_array_append_val (test->arr, test->wim);
1048+
1049+ if (!tp_strdiff (mode, "old"))
1050+ {
1051+ tp_cli_channel_interface_group_run_remove_members (test->publish,
1052+ -1, test->arr, "", &error, NULL);
1053+ }
1054+ else if (!tp_strdiff (mode, "unpublish"))
1055+ {
1056+ /* directly equivalent, but in practice people won't do this */
1057+ tp_cli_connection_interface_contact_list_run_unpublish (
1058+ test->conn, -1, test->arr, &error, NULL);
1059+ }
1060+ else
1061+ {
1062+ /* this isn't directly equivalent, but in practice it's what people
1063+ * will do */
1064+ tp_cli_connection_interface_contact_list_run_remove_contacts (
1065+ test->conn, -1, test->arr, &error, NULL);
1066+ }
1067+
1068+ g_assert_no_error (error);
1069+
1070+ /* by the time the method returns, we should have had the
1071+ * removal-notification, too */
1072+ g_assert_cmpuint (
1073+ tp_intset_size (tp_channel_group_get_local_pending (test->publish)),
1074+ ==, 1);
1075+ g_assert (!tp_intset_is_member (
1076+ tp_channel_group_get_members (test->publish),
1077+ test->wim));
1078+ g_assert (!tp_intset_is_member (
1079+ tp_channel_group_get_local_pending (test->publish),
1080+ test->wim));
1081+
1082+ g_assert_cmpuint (test->log->len, ==, 1);
1083+
1084+ /* because Wim wasn't really on our contact list, he's removed as a
1085+ * side-effect, even if we only unpublished */
1086+ test_assert_one_contact_removed (test, 0, test->wim);
1087+
1088+ test_assert_contact_state (test, test->wim,
1089+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1090+}
1091+
1092+static void
1093+test_add_to_publish_pre_approve (Test *test,
1094+ gconstpointer mode)
1095+{
1096+ GError *error = NULL;
1097+
1098+ /* Unilaterally adding a member to the publish channel doesn't work, but
1099+ * in the new contact list manager the method "succeeds" anyway, and
1100+ * any subsequent subscription request succeeds instantly. */
1101+
1102+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1103+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1104+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1105+
1106+ g_array_append_val (test->arr, test->ninja);
1107+
1108+ g_assert (!tp_intset_is_member (
1109+ tp_channel_group_get_local_pending (test->publish),
1110+ test->ninja));
1111+
1112+ if (!tp_strdiff (mode, "old"))
1113+ tp_cli_channel_interface_group_run_add_members (test->publish,
1114+ -1, test->arr, "", &error, NULL);
1115+ else
1116+ tp_cli_connection_interface_contact_list_run_authorize_publication (
1117+ test->conn, -1, test->arr, &error, NULL);
1118+
1119+ g_assert_no_error (error);
1120+
1121+ g_assert (!tp_intset_is_member (
1122+ tp_channel_group_get_local_pending (test->publish),
1123+ test->ninja));
1124+
1125+ /* the example CM's fake contacts accept requests that contain "please" */
1126+ if (!tp_strdiff (mode, "old"))
1127+ tp_cli_channel_interface_group_run_add_members (test->subscribe,
1128+ -1, test->arr, "Please may I see your presence?", &error, NULL);
1129+ else
1130+ tp_cli_connection_interface_contact_list_run_request_subscription (
1131+ test->conn, -1, test->arr, "Please may I see your presence?", &error,
1132+ NULL);
1133+
1134+ g_assert_no_error (error);
1135+
1136+ /* by the time the method returns, we should have had the
1137+ * change-notification, too */
1138+ g_assert (tp_intset_is_member (
1139+ tp_channel_group_get_remote_pending (test->subscribe),
1140+ test->ninja));
1141+ g_assert (tp_intset_is_member (
1142+ tp_channel_group_get_members (test->stored),
1143+ test->ninja));
1144+ g_assert (!tp_intset_is_member (
1145+ tp_channel_group_get_remote_pending (test->stored),
1146+ test->ninja));
1147+
1148+ /* after a short delay, the contact accepts our request */
1149+ while (tp_intset_is_member (
1150+ tp_channel_group_get_remote_pending (test->subscribe),
1151+ test->ninja))
1152+ g_main_context_iteration (NULL, TRUE);
1153+
1154+ g_assert (tp_intset_is_member (
1155+ tp_channel_group_get_members (test->subscribe),
1156+ test->ninja));
1157+ g_assert (!tp_intset_is_member (
1158+ tp_channel_group_get_remote_pending (test->subscribe),
1159+ test->ninja));
1160+
1161+ /* the contact also requests our presence after a short delay - we
1162+ * pre-approved, so they go straight to full membership */
1163+ while (!tp_intset_is_member (
1164+ tp_channel_group_get_members (test->publish),
1165+ test->ninja) || test->log->len < 3)
1166+ g_main_context_iteration (NULL, TRUE);
1167+
1168+ g_assert (tp_intset_is_member (
1169+ tp_channel_group_get_members (test->publish),
1170+ test->ninja));
1171+ g_assert (!tp_intset_is_member (
1172+ tp_channel_group_get_local_pending (test->publish),
1173+ test->ninja));
1174+
1175+ g_assert_cmpuint (test->log->len, ==, 3);
1176+ test_assert_one_contact_changed (test, 0, test->ninja, TP_SUBSCRIPTION_STATE_ASK,
1177+ TP_SUBSCRIPTION_STATE_NO, "");
1178+ test_assert_one_contact_changed (test, 1, test->ninja, TP_SUBSCRIPTION_STATE_YES,
1179+ TP_SUBSCRIPTION_STATE_NO, "");
1180+ test_assert_one_contact_changed (test, 2, test->ninja, TP_SUBSCRIPTION_STATE_YES,
1181+ TP_SUBSCRIPTION_STATE_YES, "");
1182+
1183+ test_assert_contact_state (test, test->ninja,
1184+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, NULL);
1185+}
1186+
1187+static void
1188+test_add_to_publish_no_op (Test *test,
1189+ gconstpointer mode)
1190+{
1191+ GError *error = NULL;
1192+
1193+ /* Adding a member to the publish channel when they're already there is
1194+ * valid. */
1195+
1196+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1197+
1198+ g_assert (tp_intset_is_member (
1199+ tp_channel_group_get_members (test->publish),
1200+ test->sjoerd));
1201+
1202+ g_array_append_val (test->arr, test->sjoerd);
1203+
1204+ if (!tp_strdiff (mode, "old"))
1205+ tp_cli_channel_interface_group_run_add_members (test->publish,
1206+ -1, test->arr, "", &error, NULL);
1207+ else
1208+ tp_cli_connection_interface_contact_list_run_authorize_publication (
1209+ test->conn, -1, test->arr, &error, NULL);
1210+
1211+ g_assert_no_error (error);
1212+
1213+ g_assert (tp_intset_is_member (
1214+ tp_channel_group_get_members (test->publish),
1215+ test->sjoerd));
1216+
1217+ g_assert_cmpuint (test->log->len, ==, 0);
1218+ test_assert_contact_state (test, test->sjoerd,
1219+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, "Cambridge");
1220+}
1221+
1222+static void
1223+test_remove_from_publish (Test *test,
1224+ gconstpointer mode)
1225+{
1226+ GError *error = NULL;
1227+
1228+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1229+
1230+ g_assert_cmpuint (
1231+ tp_intset_size (tp_channel_group_get_members (test->publish)),
1232+ ==, 4);
1233+ g_assert (tp_intset_is_member (
1234+ tp_channel_group_get_members (test->publish),
1235+ test->sjoerd));
1236+
1237+ g_array_append_val (test->arr, test->sjoerd);
1238+
1239+ if (!tp_strdiff (mode, "old"))
1240+ tp_cli_channel_interface_group_run_remove_members (test->publish,
1241+ -1, test->arr, "", &error, NULL);
1242+ else
1243+ tp_cli_connection_interface_contact_list_run_unpublish (
1244+ test->conn, -1, test->arr, &error, NULL);
1245+
1246+ g_assert_no_error (error);
1247+
1248+ /* by the time the method returns, we should have had the
1249+ * removal-notification, too */
1250+ g_assert (!tp_intset_is_member (
1251+ tp_channel_group_get_members (test->publish),
1252+ test->sjoerd));
1253+
1254+ /* the contact re-requests our presence after a short delay */
1255+ while (!tp_intset_is_member (
1256+ tp_channel_group_get_local_pending (test->publish),
1257+ test->sjoerd) ||
1258+ test->log->len < 2)
1259+ g_main_context_iteration (NULL, TRUE);
1260+
1261+ g_assert (!tp_intset_is_member (
1262+ tp_channel_group_get_members (test->publish),
1263+ test->sjoerd));
1264+ g_assert (tp_intset_is_member (
1265+ tp_channel_group_get_local_pending (test->publish),
1266+ test->sjoerd));
1267+
1268+ g_assert_cmpuint (test->log->len, ==, 2);
1269+ test_assert_one_contact_changed (test, 0, test->sjoerd,
1270+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_NO, "");
1271+ test_assert_one_contact_changed (test, 1, test->sjoerd,
1272+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1273+ "May I see your presence, please?");
1274+ test_assert_contact_state (test, test->sjoerd,
1275+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1276+ "May I see your presence, please?", "Cambridge");
1277+}
1278+
1279+static void
1280+test_remove_from_publish_no_op (Test *test,
1281+ gconstpointer mode)
1282+{
1283+ GError *error = NULL;
1284+
1285+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1286+
1287+ g_assert_cmpuint (
1288+ tp_intset_size (tp_channel_group_get_members (test->publish)),
1289+ ==, 4);
1290+ g_assert (!tp_intset_is_member (
1291+ tp_channel_group_get_members (test->publish),
1292+ test->ninja));
1293+
1294+ g_array_append_val (test->arr, test->ninja);
1295+
1296+ if (!tp_strdiff (mode, "old"))
1297+ tp_cli_channel_interface_group_run_remove_members (test->publish,
1298+ -1, test->arr, "", &error, NULL);
1299+ else
1300+ tp_cli_connection_interface_contact_list_run_unpublish (
1301+ test->conn, -1, test->arr, &error, NULL);
1302+
1303+ g_assert_no_error (error);
1304+
1305+ g_assert_cmpuint (test->log->len, ==, 0);
1306+ test_assert_contact_state (test, test->ninja,
1307+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1308+}
1309+
1310+static void
1311+test_cancelled_publish_request (Test *test,
1312+ gconstpointer mode)
1313+{
1314+ GError *error = NULL;
1315+
1316+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1317+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1318+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1319+
1320+ g_assert_cmpuint (
1321+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1322+ ==, 4);
1323+ g_assert (!tp_intset_is_member (
1324+ tp_channel_group_get_members (test->subscribe),
1325+ test->canceller));
1326+ g_assert (!tp_intset_is_member (
1327+ tp_channel_group_get_remote_pending (test->subscribe),
1328+ test->canceller));
1329+
1330+ /* the example CM's fake contacts accept requests that contain "please" */
1331+ g_array_append_val (test->arr, test->canceller);
1332+
1333+ tp_cli_connection_interface_contact_list_run_request_subscription (
1334+ test->conn, -1, test->arr, "Please may I see your presence?",
1335+ &error, NULL);
1336+
1337+ /* It starts off the same as test_accept_subscribe_request, but because
1338+ * we're using an identifier with special significance, the contact cancels
1339+ * the request immediately after */
1340+ while (tp_intset_is_member (
1341+ tp_channel_group_get_local_pending (test->publish),
1342+ test->canceller) ||
1343+ test->log->len < 4)
1344+ g_main_context_iteration (NULL, TRUE);
1345+
1346+ g_assert (!tp_intset_is_member (
1347+ tp_channel_group_get_members (test->publish),
1348+ test->canceller));
1349+ g_assert (!tp_intset_is_member (
1350+ tp_channel_group_get_local_pending (test->publish),
1351+ test->canceller));
1352+
1353+ g_assert_cmpuint (test->log->len, ==, 4);
1354+ test_assert_one_contact_changed (test, 0, test->canceller,
1355+ TP_SUBSCRIPTION_STATE_ASK, TP_SUBSCRIPTION_STATE_NO, "");
1356+ test_assert_one_contact_changed (test, 1, test->canceller,
1357+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_NO, "");
1358+ test_assert_one_contact_changed (test, 2, test->canceller,
1359+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1360+ "May I see your presence, please?");
1361+ test_assert_one_contact_changed (test, 3, test->canceller,
1362+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY, "");
1363+ test_assert_contact_state (test, test->canceller,
1364+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY,
1365+ NULL, NULL);
1366+
1367+ test_clear_log (test);
1368+
1369+ /* We can acknowledge the cancellation with Unpublish() or
1370+ * RemoveContacts(). We can't use the old API here, because in the old API,
1371+ * the contact has already vanished from the Group */
1372+ if (!tp_strdiff (mode, "remove-after"))
1373+ tp_cli_connection_interface_contact_list_run_remove_contacts (test->conn,
1374+ -1, test->arr, &error, NULL);
1375+ else
1376+ tp_cli_connection_interface_contact_list_run_unpublish (
1377+ test->conn, -1, test->arr, &error, NULL);
1378+
1379+ while (test->log->len < 1)
1380+ g_main_context_iteration (NULL, TRUE);
1381+
1382+ g_assert_cmpuint (test->log->len, ==, 1);
1383+
1384+ if (!tp_strdiff (mode, "remove-after"))
1385+ test_assert_one_contact_removed (test, 0, test->canceller);
1386+ else
1387+ test_assert_one_contact_changed (test, 0, test->canceller,
1388+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_NO, "");
1389+}
1390+
1391+static void
1392+test_add_to_stored (Test *test,
1393+ gconstpointer mode)
1394+{
1395+ GError *error = NULL;
1396+
1397+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1398+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1399+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST,
1400+ "subscribe");
1401+
1402+ g_assert_cmpuint (
1403+ tp_intset_size (tp_channel_group_get_members (test->stored)),
1404+ ==, 8);
1405+ g_assert (!tp_intset_is_member (
1406+ tp_channel_group_get_members (test->stored),
1407+ test->ninja));
1408+
1409+ g_array_append_val (test->arr, test->ninja);
1410+
1411+ if (!tp_strdiff (mode, "old"))
1412+ {
1413+ tp_cli_channel_interface_group_run_add_members (test->stored,
1414+ -1, test->arr, "", &error, NULL);
1415+ }
1416+ else
1417+ {
1418+ /* there's no specific API for adding contacts to stored (it's not a
1419+ * very useful action in general), but setting an alias has it as a
1420+ * side-effect */
1421+ GHashTable *table = g_hash_table_new (NULL, NULL);
1422+
1423+ g_hash_table_insert (table, GUINT_TO_POINTER (test->ninja),
1424+ "The Wee Ninja");
1425+ tp_cli_connection_interface_aliasing_run_set_aliases (test->conn,
1426+ -1, table, &error, NULL);
1427+ g_hash_table_unref (table);
1428+ }
1429+
1430+ g_assert_no_error (error);
1431+
1432+ /* by the time the method returns, we should have had the
1433+ * change-notification, too */
1434+ g_assert_cmpuint (
1435+ tp_intset_size (tp_channel_group_get_members (test->stored)),
1436+ ==, 9);
1437+ g_assert (tp_intset_is_member (
1438+ tp_channel_group_get_members (test->stored),
1439+ test->ninja));
1440+
1441+ g_assert (!tp_intset_is_member (
1442+ tp_channel_group_get_members (test->subscribe),
1443+ test->ninja));
1444+ g_assert (!tp_intset_is_member (
1445+ tp_channel_group_get_members (test->publish),
1446+ test->ninja));
1447+
1448+ g_assert_cmpuint (test->log->len, ==, 1);
1449+ test_assert_one_contact_changed (test, 0, test->ninja,
1450+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1451+ test_assert_contact_state (test, test->ninja,
1452+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1453+}
1454+
1455+static void
1456+test_add_to_stored_no_op (Test *test,
1457+ gconstpointer mode)
1458+{
1459+ GError *error = NULL;
1460+
1461+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1462+
1463+ g_assert_cmpuint (
1464+ tp_intset_size (tp_channel_group_get_members (test->stored)),
1465+ ==, 8);
1466+ g_assert (tp_intset_is_member (
1467+ tp_channel_group_get_members (test->stored),
1468+ test->sjoerd));
1469+
1470+ g_array_append_val (test->arr, test->sjoerd);
1471+
1472+ if (!tp_strdiff (mode, "old"))
1473+ {
1474+ tp_cli_channel_interface_group_run_add_members (test->stored,
1475+ -1, test->arr, "", &error, NULL);
1476+ }
1477+ else
1478+ {
1479+ /* there's no specific API for adding contacts to stored (it's not a
1480+ * very useful action in general), but setting an alias has it as a
1481+ * side-effect */
1482+ GHashTable *table = g_hash_table_new (NULL, NULL);
1483+
1484+ g_hash_table_insert (table, GUINT_TO_POINTER (test->sjoerd),
1485+ "Sjoerd");
1486+ tp_cli_connection_interface_aliasing_run_set_aliases (test->conn,
1487+ -1, table, &error, NULL);
1488+ g_hash_table_unref (table);
1489+ }
1490+
1491+ g_assert_no_error (error);
1492+
1493+ g_assert_cmpuint (test->log->len, ==, 0);
1494+ test_assert_contact_state (test, test->sjoerd,
1495+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, "Cambridge");
1496+}
1497+
1498+static void
1499+test_remove_from_stored (Test *test,
1500+ gconstpointer mode)
1501+{
1502+ GError *error = NULL;
1503+
1504+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1505+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1506+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST,
1507+ "subscribe");
1508+
1509+ g_assert (tp_intset_is_member (
1510+ tp_channel_group_get_members (test->stored),
1511+ test->sjoerd));
1512+
1513+ g_array_append_val (test->arr, test->sjoerd);
1514+
1515+ if (!tp_strdiff (mode, "old"))
1516+ tp_cli_channel_interface_group_run_remove_members (test->stored,
1517+ -1, test->arr, "", &error, NULL);
1518+ else
1519+ tp_cli_connection_interface_contact_list_run_remove_contacts (test->conn,
1520+ -1, test->arr, &error, NULL);
1521+
1522+ g_assert_no_error (error);
1523+
1524+ /* by the time the method returns, we should have had the
1525+ * removal-notification, too */
1526+ g_assert (!tp_intset_is_member (
1527+ tp_channel_group_get_members (test->stored),
1528+ test->sjoerd));
1529+ g_assert (!tp_intset_is_member (
1530+ tp_channel_group_get_members (test->subscribe),
1531+ test->sjoerd));
1532+ g_assert (!tp_intset_is_member (
1533+ tp_channel_group_get_members (test->publish),
1534+ test->sjoerd));
1535+
1536+ g_assert_cmpuint (test->log->len, ==, 1);
1537+ test_assert_one_contact_removed (test, 0, test->sjoerd);
1538+ test_assert_contact_state (test, test->sjoerd,
1539+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1540+}
1541+
1542+static void
1543+test_remove_from_stored_no_op (Test *test,
1544+ gconstpointer mode)
1545+{
1546+ GError *error = NULL;
1547+
1548+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1549+
1550+ g_assert_cmpuint (
1551+ tp_intset_size (tp_channel_group_get_members (test->stored)),
1552+ ==, 8);
1553+ g_assert (!tp_intset_is_member (
1554+ tp_channel_group_get_members (test->stored),
1555+ test->ninja));
1556+
1557+ g_array_append_val (test->arr, test->ninja);
1558+
1559+ if (!tp_strdiff (mode, "old"))
1560+ tp_cli_channel_interface_group_run_remove_members (test->stored,
1561+ -1, test->arr, "", &error, NULL);
1562+ else
1563+ tp_cli_connection_interface_contact_list_run_remove_contacts (test->conn,
1564+ -1, test->arr, &error, NULL);
1565+
1566+ g_assert_no_error (error);
1567+
1568+ g_assert_cmpuint (test->log->len, ==, 0);
1569+ test_assert_contact_state (test, test->ninja,
1570+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1571+}
1572+
1573+static void
1574+test_accept_subscribe_request (Test *test,
1575+ gconstpointer mode)
1576+{
1577+ GError *error = NULL;
1578+
1579+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1580+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1581+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1582+
1583+ g_assert_cmpuint (
1584+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1585+ ==, 4);
1586+ g_assert (!tp_intset_is_member (
1587+ tp_channel_group_get_members (test->subscribe),
1588+ test->ninja));
1589+ g_assert (!tp_intset_is_member (
1590+ tp_channel_group_get_remote_pending (test->subscribe),
1591+ test->ninja));
1592+
1593+ /* the example CM's fake contacts accept requests that contain "please" */
1594+ g_array_append_val (test->arr, test->ninja);
1595+
1596+ if (!tp_strdiff (mode, "old"))
1597+ tp_cli_channel_interface_group_run_add_members (test->subscribe,
1598+ -1, test->arr, "Please may I see your presence?", &error, NULL);
1599+ else
1600+ tp_cli_connection_interface_contact_list_run_request_subscription (
1601+ test->conn, -1, test->arr, "Please may I see your presence?",
1602+ &error, NULL);
1603+
1604+ g_assert_no_error (error);
1605+
1606+ /* by the time the method returns, we should have had the
1607+ * change-notification, too */
1608+ g_assert (tp_intset_is_member (
1609+ tp_channel_group_get_remote_pending (test->subscribe),
1610+ test->ninja));
1611+ g_assert (tp_intset_is_member (
1612+ tp_channel_group_get_members (test->stored),
1613+ test->ninja));
1614+ g_assert (!tp_intset_is_member (
1615+ tp_channel_group_get_remote_pending (test->stored),
1616+ test->ninja));
1617+
1618+ /* after a short delay, the contact accepts our request */
1619+ while (tp_intset_is_member (
1620+ tp_channel_group_get_remote_pending (test->subscribe),
1621+ test->ninja))
1622+ g_main_context_iteration (NULL, TRUE);
1623+
1624+ g_assert (tp_intset_is_member (
1625+ tp_channel_group_get_members (test->subscribe),
1626+ test->ninja));
1627+ g_assert (!tp_intset_is_member (
1628+ tp_channel_group_get_remote_pending (test->subscribe),
1629+ test->ninja));
1630+
1631+ /* the contact also requests our presence after a short delay */
1632+ while (!tp_intset_is_member (
1633+ tp_channel_group_get_local_pending (test->publish),
1634+ test->ninja) ||
1635+ test->log->len < 3)
1636+ g_main_context_iteration (NULL, TRUE);
1637+
1638+ g_assert (!tp_intset_is_member (
1639+ tp_channel_group_get_members (test->publish),
1640+ test->ninja));
1641+ g_assert (tp_intset_is_member (
1642+ tp_channel_group_get_local_pending (test->publish),
1643+ test->ninja));
1644+
1645+ g_assert_cmpuint (test->log->len, ==, 3);
1646+ test_assert_one_contact_changed (test, 0, test->ninja,
1647+ TP_SUBSCRIPTION_STATE_ASK, TP_SUBSCRIPTION_STATE_NO, "");
1648+ test_assert_one_contact_changed (test, 1, test->ninja,
1649+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_NO, "");
1650+ test_assert_one_contact_changed (test, 2, test->ninja,
1651+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1652+ "May I see your presence, please?");
1653+ test_assert_contact_state (test, test->ninja,
1654+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1655+ "May I see your presence, please?", NULL);
1656+}
1657+
1658+static void
1659+test_reject_subscribe_request (Test *test,
1660+ gconstpointer mode)
1661+{
1662+ GError *error = NULL;
1663+
1664+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1665+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1666+
1667+ g_assert_cmpuint (
1668+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1669+ ==, 4);
1670+ g_assert (!tp_intset_is_member (
1671+ tp_channel_group_get_members (test->subscribe),
1672+ test->ninja));
1673+ g_assert (!tp_intset_is_member (
1674+ tp_channel_group_get_remote_pending (test->subscribe),
1675+ test->ninja));
1676+
1677+ /* the example CM's fake contacts reject requests that don't contain
1678+ * "please" */
1679+ g_array_append_val (test->arr, test->ninja);
1680+
1681+ if (!tp_strdiff (mode, "old"))
1682+ tp_cli_channel_interface_group_run_add_members (test->subscribe,
1683+ -1, test->arr, "I demand to see your presence?", &error, NULL);
1684+ else
1685+ tp_cli_connection_interface_contact_list_run_request_subscription (
1686+ test->conn, -1, test->arr, "I demand to see your presence?",
1687+ &error, NULL);
1688+
1689+ g_assert_no_error (error);
1690+
1691+ /* by the time the method returns, we should have had the
1692+ * change-notification, too */
1693+ g_assert (tp_intset_is_member (
1694+ tp_channel_group_get_remote_pending (test->subscribe),
1695+ test->ninja));
1696+ g_assert (tp_intset_is_member (
1697+ tp_channel_group_get_members (test->stored),
1698+ test->ninja));
1699+ g_assert (!tp_intset_is_member (
1700+ tp_channel_group_get_remote_pending (test->stored),
1701+ test->ninja));
1702+
1703+ /* after a short delay, the contact rejects our request. Say please! */
1704+ while (tp_intset_is_member (
1705+ tp_channel_group_get_remote_pending (test->subscribe),
1706+ test->ninja) ||
1707+ test->log->len < 2)
1708+ g_main_context_iteration (NULL, TRUE);
1709+
1710+ g_assert (!tp_intset_is_member (
1711+ tp_channel_group_get_members (test->subscribe),
1712+ test->ninja));
1713+ g_assert (!tp_intset_is_member (
1714+ tp_channel_group_get_remote_pending (test->subscribe),
1715+ test->ninja));
1716+
1717+ /* the ninja is still on the stored list */
1718+ g_assert (tp_intset_is_member (
1719+ tp_channel_group_get_members (test->stored),
1720+ test->ninja));
1721+ g_assert (!tp_intset_is_member (
1722+ tp_channel_group_get_remote_pending (test->stored),
1723+ test->ninja));
1724+
1725+ g_assert_cmpuint (test->log->len, ==, 2);
1726+ test_assert_one_contact_changed (test, 0, test->ninja,
1727+ TP_SUBSCRIPTION_STATE_ASK, TP_SUBSCRIPTION_STATE_NO, "");
1728+ test_assert_one_contact_changed (test, 1, test->ninja,
1729+ TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY, TP_SUBSCRIPTION_STATE_NO, "");
1730+ test_assert_contact_state (test, test->ninja,
1731+ TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY, TP_SUBSCRIPTION_STATE_NO, NULL,
1732+ NULL);
1733+
1734+ test_clear_log (test);
1735+
1736+ /* We can acknowledge the failure to subscribe with Unsubscribe() or
1737+ * RemoveContacts(). We can't use the old API here, because in the old API,
1738+ * the contact has already vanished from the Group */
1739+ if (!tp_strdiff (mode, "remove-after"))
1740+ tp_cli_connection_interface_contact_list_run_remove_contacts (test->conn,
1741+ -1, test->arr, &error, NULL);
1742+ else
1743+ tp_cli_connection_interface_contact_list_run_unsubscribe (
1744+ test->conn, -1, test->arr, &error, NULL);
1745+
1746+ /* the ninja falls off our subscribe list */
1747+ while (test->log->len < 1)
1748+ g_main_context_iteration (NULL, TRUE);
1749+
1750+ g_assert_cmpuint (test->log->len, ==, 1);
1751+
1752+ if (!tp_strdiff (mode, "remove-after"))
1753+ test_assert_one_contact_removed (test, 0, test->ninja);
1754+ else
1755+ test_assert_one_contact_changed (test, 0, test->ninja,
1756+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1757+}
1758+
1759+static void
1760+test_remove_from_subscribe (Test *test,
1761+ gconstpointer mode)
1762+{
1763+ GError *error = NULL;
1764+
1765+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1766+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1767+
1768+ g_assert_cmpuint (
1769+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1770+ ==, 4);
1771+ g_assert (tp_intset_is_member (
1772+ tp_channel_group_get_members (test->subscribe),
1773+ test->sjoerd));
1774+
1775+ g_array_append_val (test->arr, test->sjoerd);
1776+
1777+ if (!tp_strdiff (mode, "old"))
1778+ tp_cli_channel_interface_group_run_remove_members (test->subscribe,
1779+ -1, test->arr, "", &error, NULL);
1780+ else
1781+ tp_cli_connection_interface_contact_list_run_unsubscribe (
1782+ test->conn, -1, test->arr, &error, NULL);
1783+
1784+ g_assert_no_error (error);
1785+
1786+ /* by the time the method returns, we should have had the
1787+ * removal-notification, too */
1788+ g_assert (!tp_intset_is_member (
1789+ tp_channel_group_get_members (test->subscribe),
1790+ test->sjoerd));
1791+ g_assert (tp_intset_is_member (
1792+ tp_channel_group_get_members (test->stored),
1793+ test->sjoerd));
1794+
1795+ g_assert_cmpuint (test->log->len, ==, 1);
1796+ test_assert_one_contact_changed (test, 0, test->sjoerd,
1797+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_YES, "");
1798+ test_assert_contact_state (test, test->sjoerd,
1799+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_YES, NULL, "Cambridge");
1800+}
1801+
1802+static void
1803+test_remove_from_subscribe_pending (Test *test,
1804+ gconstpointer mode)
1805+{
1806+ GError *error = NULL;
1807+
1808+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1809+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1810+
1811+ g_assert_cmpuint (
1812+ tp_intset_size (tp_channel_group_get_remote_pending (test->subscribe)),
1813+ ==, 2);
1814+ g_assert (tp_intset_is_member (
1815+ tp_channel_group_get_remote_pending (test->subscribe),
1816+ test->helen));
1817+
1818+ g_array_append_val (test->arr, test->helen);
1819+
1820+ if (!tp_strdiff (mode, "old"))
1821+ tp_cli_channel_interface_group_run_remove_members (test->subscribe,
1822+ -1, test->arr, "", &error, NULL);
1823+ else
1824+ tp_cli_connection_interface_contact_list_run_unsubscribe (
1825+ test->conn, -1, test->arr, &error, NULL);
1826+
1827+ g_assert_no_error (error);
1828+
1829+ /* by the time the method returns, we should have had the
1830+ * removal-notification, too */
1831+ g_assert (!tp_intset_is_member (
1832+ tp_channel_group_get_members (test->subscribe),
1833+ test->helen));
1834+ g_assert (!tp_intset_is_member (
1835+ tp_channel_group_get_remote_pending (test->subscribe),
1836+ test->helen));
1837+ g_assert (tp_intset_is_member (
1838+ tp_channel_group_get_members (test->stored),
1839+ test->helen));
1840+
1841+ g_assert_cmpuint (test->log->len, ==, 1);
1842+ test_assert_one_contact_changed (test, 0, test->helen,
1843+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1844+ test_assert_contact_state (test, test->helen,
1845+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, "Cambridge");
1846+}
1847+
1848+static void
1849+test_remove_from_subscribe_no_op (Test *test,
1850+ gconstpointer mode)
1851+{
1852+ GError *error = NULL;
1853+
1854+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1855+
1856+ g_assert_cmpuint (
1857+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1858+ ==, 4);
1859+ g_assert (!tp_intset_is_member (
1860+ tp_channel_group_get_members (test->subscribe),
1861+ test->ninja));
1862+
1863+ g_array_append_val (test->arr, test->ninja);
1864+
1865+ if (!tp_strdiff (mode, "old"))
1866+ tp_cli_channel_interface_group_run_remove_members (test->subscribe,
1867+ -1, test->arr, "", &error, NULL);
1868+ else
1869+ tp_cli_connection_interface_contact_list_run_unsubscribe (
1870+ test->conn, -1, test->arr, &error, NULL);
1871+
1872+ g_assert_no_error (error);
1873+
1874+ g_assert_cmpuint (test->log->len, ==, 0);
1875+ test_assert_contact_state (test, test->ninja,
1876+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1877+}
1878+
1879+static void
1880+test_add_to_group (Test *test,
1881+ gconstpointer mode)
1882+{
1883+ GError *error = NULL;
1884+ LogEntry *le;
1885+ guint i;
1886+
1887+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
1888+ "Cambridge");
1889+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1890+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1891+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST,
1892+ "subscribe");
1893+
1894+ g_assert_cmpuint (
1895+ tp_intset_size (tp_channel_group_get_members (test->group)),
1896+ ==, 4);
1897+ g_assert (!tp_intset_is_member (
1898+ tp_channel_group_get_members (test->group),
1899+ test->ninja));
1900+
1901+ g_array_append_val (test->arr, test->ninja);
1902+
1903+ if (!tp_strdiff (mode, "old"))
1904+ tp_cli_channel_interface_group_run_add_members (test->group,
1905+ -1, test->arr, "", &error, NULL);
1906+ else
1907+ tp_cli_connection_interface_contact_groups_run_add_to_group (test->conn,
1908+ -1, "Cambridge", test->arr, &error, NULL);
1909+
1910+ g_assert_no_error (error);
1911+
1912+ /* by the time the method returns, we should have had the
1913+ * change-notification, too */
1914+ g_assert_cmpuint (
1915+ tp_intset_size (tp_channel_group_get_members (test->group)),
1916+ ==, 5);
1917+ g_assert (tp_intset_is_member (
1918+ tp_channel_group_get_members (test->group),
1919+ test->ninja));
1920+
1921+ g_assert (tp_intset_is_member (
1922+ tp_channel_group_get_members (test->stored),
1923+ test->ninja));
1924+ g_assert (!tp_intset_is_member (
1925+ tp_channel_group_get_members (test->subscribe),
1926+ test->ninja));
1927+ g_assert (!tp_intset_is_member (
1928+ tp_channel_group_get_members (test->publish),
1929+ test->ninja));
1930+
1931+ g_assert_cmpuint (test->log->len, ==, 2);
1932+
1933+ le = g_ptr_array_index (test->log, 0);
1934+
1935+ if (le->type == CONTACTS_CHANGED)
1936+ {
1937+ test_assert_one_contact_changed (test, 0, test->ninja,
1938+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1939+ i = 1;
1940+ }
1941+ else
1942+ {
1943+ test_assert_one_contact_changed (test, 1, test->ninja,
1944+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1945+ i = 0;
1946+ }
1947+
1948+ /* either way, the i'th entry is now the GroupsChanged signal */
1949+ test_assert_one_group_joined (test, i, test->ninja, "Cambridge");
1950+
1951+ test_assert_contact_state (test, test->ninja,
1952+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, "Cambridge");
1953+}
1954+
1955+static void
1956+test_add_to_group_no_op (Test *test,
1957+ gconstpointer mode)
1958+{
1959+ GError *error = NULL;
1960+
1961+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
1962+ "Cambridge");
1963+
1964+ g_assert (tp_intset_is_member (
1965+ tp_channel_group_get_members (test->group),
1966+ test->sjoerd));
1967+
1968+ g_array_append_val (test->arr, test->sjoerd);
1969+
1970+ if (!tp_strdiff (mode, "old"))
1971+ tp_cli_channel_interface_group_run_add_members (test->group,
1972+ -1, test->arr, "", &error, NULL);
1973+ else
1974+ tp_cli_connection_interface_contact_groups_run_add_to_group (test->conn,
1975+ -1, "Cambridge", test->arr, &error, NULL);
1976+
1977+ g_assert_no_error (error);
1978+
1979+ g_assert_cmpuint (test->log->len, ==, 0);
1980+ test_assert_contact_state (test, test->sjoerd,
1981+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, "Cambridge");
1982+}
1983+
1984+static void
1985+test_remove_from_group (Test *test,
1986+ gconstpointer mode)
1987+{
1988+ GError *error = NULL;
1989+
1990+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
1991+ "Cambridge");
1992+
1993+ g_assert (tp_intset_is_member (
1994+ tp_channel_group_get_members (test->group),
1995+ test->sjoerd));
1996+
1997+ g_array_append_val (test->arr, test->sjoerd);
1998+
1999+ if (!tp_strdiff (mode, "old"))
2000+ tp_cli_channel_interface_group_run_remove_members (test->group,
2001+ -1, test->arr, "", &error, NULL);
2002+ else
2003+ tp_cli_connection_interface_contact_groups_run_remove_from_group (
2004+ test->conn, -1, "Cambridge", test->arr, &error, NULL);
2005+
2006+ g_assert_no_error (error);
2007+
2008+ /* by the time the method returns, we should have had the
2009+ * removal-notification, too */
2010+ g_assert (!tp_intset_is_member (
2011+ tp_channel_group_get_members (test->group),
2012+ test->sjoerd));
2013+
2014+ g_assert_cmpuint (test->log->len, ==, 1);
2015+ test_assert_one_group_left (test, 0, test->sjoerd, "Cambridge");
2016+ test_assert_contact_state (test, test->sjoerd,
2017+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, NULL);
2018+}
2019+
2020+static void
2021+test_remove_from_group_no_op (Test *test,
2022+ gconstpointer mode)
2023+{
2024+ GError *error = NULL;
2025+
2026+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2027+ "Cambridge");
2028+
2029+ g_assert (!tp_intset_is_member (
2030+ tp_channel_group_get_members (test->group),
2031+ test->ninja));
2032+
2033+ g_array_append_val (test->arr, test->ninja);
2034+
2035+ if (!tp_strdiff (mode, "old"))
2036+ tp_cli_channel_interface_group_run_remove_members (test->group,
2037+ -1, test->arr, "", &error, NULL);
2038+ else
2039+ tp_cli_connection_interface_contact_groups_run_remove_from_group (
2040+ test->conn, -1, "Cambridge", test->arr, &error, NULL);
2041+
2042+ g_assert_no_error (error);
2043+
2044+ g_assert_cmpuint (test->log->len, ==, 0);
2045+ test_assert_contact_state (test, test->ninja,
2046+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2047+}
2048+
2049+static void
2050+test_remove_group (Test *test,
2051+ gconstpointer mode)
2052+{
2053+ GError *error = NULL;
2054+
2055+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2056+ "Cambridge");
2057+
2058+ g_assert (!tp_intset_is_empty (
2059+ tp_channel_group_get_members (test->group)));
2060+
2061+ if (!tp_strdiff (mode, "old"))
2062+ {
2063+ /* The old API can't remove non-empty groups... */
2064+ tp_cli_channel_run_close (test->group, -1, &error, NULL);
2065+ g_assert_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE);
2066+
2067+ g_assert_cmpuint (test->log->len, ==, 0);
2068+ }
2069+ else
2070+ {
2071+ /* ... but the new API can */
2072+ LogEntry *le;
2073+
2074+ tp_cli_connection_interface_contact_groups_run_remove_group (test->conn,
2075+ -1, "Cambridge", &error, NULL);
2076+ g_assert_no_error (error);
2077+
2078+ g_assert (tp_proxy_get_invalidated (test->group) != NULL);
2079+ g_assert_cmpuint (test->log->len, ==, 2);
2080+ test_assert_one_group_removed (test, 0, "Cambridge");
2081+
2082+ le = g_ptr_array_index (test->log, 1);
2083+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
2084+ g_assert_cmpuint (le->contacts->len, ==, 4);
2085+ g_assert (le->groups_added == NULL || le->groups_added[0] == NULL);
2086+ g_assert (le->groups_removed != NULL);
2087+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2088+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2089+ }
2090+}
2091+
2092+static void
2093+test_remove_group_empty (Test *test,
2094+ gconstpointer mode)
2095+{
2096+ GError *error = NULL;
2097+
2098+ g_assert_cmpuint (test->log->len, ==, 0);
2099+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2100+ "people who understand const in C");
2101+
2102+ g_assert_cmpuint (test->log->len, ==, 1);
2103+ test_assert_one_group_created (test, 0, "people who understand const in C");
2104+
2105+ g_assert (tp_intset_is_empty (
2106+ tp_channel_group_get_members (test->group)));
2107+
2108+ tp_cli_channel_run_close (test->group, -1, &error, NULL);
2109+ g_assert_no_error (error);
2110+
2111+ g_assert_cmpuint (test->log->len, ==, 2);
2112+ test_assert_one_group_removed (test, 1, "people who understand const in C");
2113+}
2114+
2115+static void
2116+test_set_contact_groups (Test *test,
2117+ gconstpointer nil G_GNUC_UNUSED)
2118+{
2119+ GError *error = NULL;
2120+ LogEntry *le;
2121+ const gchar *montreal_strv[] = { "Montreal", NULL };
2122+
2123+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2124+ "Cambridge");
2125+
2126+ g_assert_cmpuint (
2127+ tp_intset_size (tp_channel_group_get_members (test->group)),
2128+ ==, 4);
2129+ g_assert (tp_intset_is_member (
2130+ tp_channel_group_get_members (test->group),
2131+ test->sjoerd));
2132+
2133+ g_array_append_val (test->arr, test->sjoerd);
2134+ g_array_append_val (test->arr, test->wim);
2135+
2136+ tp_cli_connection_interface_contact_groups_run_set_contact_groups (
2137+ test->conn, -1, test->sjoerd, montreal_strv, &error, NULL);
2138+
2139+ g_assert_no_error (error);
2140+
2141+ /* by the time the method returns, we should have had the
2142+ * change-notification, too */
2143+ g_assert_cmpuint (
2144+ tp_intset_size (tp_channel_group_get_members (test->group)),
2145+ ==, 3);
2146+ g_assert (!tp_intset_is_member (
2147+ tp_channel_group_get_members (test->group),
2148+ test->sjoerd));
2149+
2150+ g_assert_cmpuint (test->log->len, ==, 1);
2151+
2152+ le = g_ptr_array_index (test->log, 0);
2153+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
2154+ g_assert_cmpuint (le->contacts->len, ==, 1);
2155+ g_assert_cmpuint (g_array_index (le->contacts, guint, 0), ==, test->sjoerd);
2156+ g_assert (le->groups_added != NULL);
2157+ g_assert_cmpstr (le->groups_added[0], ==, "Montreal");
2158+ g_assert_cmpstr (le->groups_added[1], ==, NULL);
2159+ g_assert (le->groups_removed != NULL);
2160+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2161+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2162+}
2163+
2164+static void
2165+test_set_contact_groups_no_op (Test *test,
2166+ gconstpointer nil G_GNUC_UNUSED)
2167+{
2168+ GError *error = NULL;
2169+ const gchar *cambridge_strv[] = { "Cambridge", NULL };
2170+
2171+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2172+ "Cambridge");
2173+
2174+ g_assert_cmpuint (
2175+ tp_intset_size (tp_channel_group_get_members (test->group)),
2176+ ==, 4);
2177+ g_assert (tp_intset_is_member (
2178+ tp_channel_group_get_members (test->group),
2179+ test->sjoerd));
2180+
2181+ g_array_append_val (test->arr, test->sjoerd);
2182+ g_array_append_val (test->arr, test->wim);
2183+
2184+ tp_cli_connection_interface_contact_groups_run_set_contact_groups (
2185+ test->conn, -1, test->sjoerd, cambridge_strv, &error, NULL);
2186+
2187+ g_assert_no_error (error);
2188+
2189+ g_assert_cmpuint (
2190+ tp_intset_size (tp_channel_group_get_members (test->group)),
2191+ ==, 4);
2192+ g_assert (tp_intset_is_member (
2193+ tp_channel_group_get_members (test->group),
2194+ test->sjoerd));
2195+
2196+ g_assert_cmpuint (test->log->len, ==, 0);
2197+}
2198+
2199+static void
2200+test_set_group_members (Test *test,
2201+ gconstpointer nil G_GNUC_UNUSED)
2202+{
2203+ GError *error = NULL;
2204+ LogEntry *le;
2205+
2206+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2207+ "Cambridge");
2208+
2209+ g_assert_cmpuint (
2210+ tp_intset_size (tp_channel_group_get_members (test->group)),
2211+ ==, 4);
2212+ g_assert (tp_intset_is_member (
2213+ tp_channel_group_get_members (test->group),
2214+ test->sjoerd));
2215+ g_assert (tp_intset_is_member (
2216+ tp_channel_group_get_members (test->group),
2217+ test->helen));
2218+ g_assert (!tp_intset_is_member (
2219+ tp_channel_group_get_members (test->group),
2220+ test->wim));
2221+
2222+ g_array_append_val (test->arr, test->sjoerd);
2223+ g_array_append_val (test->arr, test->wim);
2224+
2225+ tp_cli_connection_interface_contact_groups_run_set_group_members (test->conn,
2226+ -1, "Cambridge", test->arr, &error, NULL);
2227+
2228+ g_assert_no_error (error);
2229+
2230+ /* by the time the method returns, we should have had the
2231+ * change-notification, too */
2232+ g_assert_cmpuint (
2233+ tp_intset_size (tp_channel_group_get_members (test->group)),
2234+ ==, 2);
2235+ g_assert (tp_intset_is_member (
2236+ tp_channel_group_get_members (test->group),
2237+ test->wim));
2238+ g_assert (tp_intset_is_member (
2239+ tp_channel_group_get_members (test->group),
2240+ test->sjoerd));
2241+ g_assert (!tp_intset_is_member (
2242+ tp_channel_group_get_members (test->group),
2243+ test->helen));
2244+
2245+ g_assert_cmpuint (test->log->len, ==, 2);
2246+
2247+ /* Wim was added */
2248+ test_assert_one_group_joined (test, 0, test->wim, "Cambridge");
2249+
2250+ /* The three other members, other than Sjoerd, left */
2251+ le = g_ptr_array_index (test->log, 1);
2252+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
2253+ g_assert_cmpuint (le->contacts->len, ==, 3);
2254+ g_assert (le->groups_added == NULL || le->groups_added[0] == NULL);
2255+ g_assert (le->groups_removed != NULL);
2256+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2257+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2258+}
2259+
2260+static void
2261+test_rename_group (Test *test,
2262+ gconstpointer nil G_GNUC_UNUSED)
2263+{
2264+ LogEntry *le;
2265+ GError *error = NULL;
2266+
2267+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2268+ "Cambridge");
2269+
2270+ g_assert_cmpuint (
2271+ tp_intset_size (tp_channel_group_get_members (test->group)),
2272+ ==, 4);
2273+
2274+ tp_cli_connection_interface_contact_groups_run_rename_group (test->conn,
2275+ -1, "Cambridge", "Grantabrugge", &error, NULL);
2276+ g_assert_no_error (error);
2277+
2278+ g_assert (tp_proxy_get_invalidated (test->group) != NULL);
2279+ g_assert_cmpuint (test->log->len, ==, 4);
2280+
2281+ le = g_ptr_array_index (test->log, 0);
2282+ g_assert_cmpint (le->type, ==, GROUP_RENAMED);
2283+ g_assert (le->groups_added != NULL);
2284+ g_assert_cmpstr (le->groups_added[0], ==, "Grantabrugge");
2285+ g_assert_cmpstr (le->groups_added[1], ==, NULL);
2286+ g_assert (le->groups_removed != NULL);
2287+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2288+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2289+
2290+ test_assert_one_group_created (test, 1, "Grantabrugge");
2291+
2292+ test_assert_one_group_removed (test, 2, "Cambridge");
2293+
2294+ le = g_ptr_array_index (test->log, 3);
2295+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
2296+ g_assert_cmpuint (le->contacts->len, ==, 4);
2297+ g_assert (le->groups_added != NULL);
2298+ g_assert_cmpstr (le->groups_added[0], ==, "Grantabrugge");
2299+ g_assert_cmpstr (le->groups_added[1], ==, NULL);
2300+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2301+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2302+}
2303+
2304+static void
2305+test_rename_group_overwrite (Test *test,
2306+ gconstpointer nil G_GNUC_UNUSED)
2307+{
2308+ GError *error = NULL;
2309+
2310+ tp_cli_connection_interface_contact_groups_run_rename_group (test->conn,
2311+ -1, "Cambridge", "Montreal", &error, NULL);
2312+ g_assert_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE);
2313+ g_assert_cmpuint (test->log->len, ==, 0);
2314+ g_clear_error (&error);
2315+}
2316+
2317+static void
2318+test_rename_group_absent (Test *test,
2319+ gconstpointer nil G_GNUC_UNUSED)
2320+{
2321+ GError *error = NULL;
2322+
2323+ tp_cli_connection_interface_contact_groups_run_rename_group (test->conn,
2324+ -1, "Badgers", "Mushrooms", &error, NULL);
2325+ g_assert_error (error, TP_ERRORS, TP_ERROR_DOES_NOT_EXIST);
2326+ g_assert_cmpuint (test->log->len, ==, 0);
2327+ g_clear_error (&error);
2328+}
2329+
2330+/* Signature of a function which does something with test->arr */
2331+typedef void (*ManipulateContactsFunc) (
2332+ Test *test,
2333+ GError **error);
2334+
2335+static void
2336+block_contacts (Test *test,
2337+ ManipulateContactsFunc func)
2338+{
2339+ GError *error = NULL;
2340+
2341+ test->deny = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "deny");
2342+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
2343+
2344+ g_assert_cmpuint (
2345+ tp_intset_size (tp_channel_group_get_members (test->deny)),
2346+ ==, 2);
2347+ g_assert (!tp_intset_is_member (
2348+ tp_channel_group_get_members (test->deny),
2349+ test->ninja));
2350+
2351+ g_array_append_val (test->arr, test->ninja);
2352+ func (test, &error);
2353+ g_assert_no_error (error);
2354+
2355+ /* by the time the method returns, we should have had the
2356+ * change-notification, on both the deny channel and the ContactBlocking
2357+ * connection interface */
2358+ g_assert_cmpuint (
2359+ tp_intset_size (tp_channel_group_get_members (test->deny)),
2360+ ==, 3);
2361+ g_assert (tp_intset_is_member (
2362+ tp_channel_group_get_members (test->deny),
2363+ test->ninja));
2364+
2365+ g_assert (!tp_intset_is_member (
2366+ tp_channel_group_get_members (test->stored),
2367+ test->ninja));
2368+ test_assert_contact_state (test, test->ninja,
2369+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2370+
2371+ g_assert_cmpuint (test->log->len, ==, 1);
2372+ test_assert_one_contact_blocked (test, 0, test->ninja,
2373+ tp_handle_inspect (test->contact_repo, test->ninja));
2374+}
2375+
2376+static void
2377+block_contacts_no_op (Test *test,
2378+ ManipulateContactsFunc func)
2379+{
2380+ GError *error = NULL;
2381+
2382+ test->deny = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "deny");
2383+
2384+ g_assert (tp_intset_is_member (
2385+ tp_channel_group_get_members (test->deny),
2386+ test->bill));
2387+
2388+ g_array_append_val (test->arr, test->bill);
2389+ func (test, &error);
2390+ g_assert_no_error (error);
2391+
2392+ g_assert (tp_intset_is_member (
2393+ tp_channel_group_get_members (test->deny),
2394+ test->bill));
2395+ test_assert_contact_state (test, test->bill,
2396+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2397+
2398+ /* We shouldn't emit spurious empty BlockedContactsChanged signals. */
2399+ g_assert_cmpuint (test->log->len, ==, 0);
2400+}
2401+
2402+static void
2403+unblock_contacts (Test *test,
2404+ ManipulateContactsFunc func)
2405+{
2406+ GError *error = NULL;
2407+
2408+ test->deny = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "deny");
2409+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
2410+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST,
2411+ "subscribe");
2412+
2413+ g_assert (tp_intset_is_member (
2414+ tp_channel_group_get_members (test->deny),
2415+ test->bill));
2416+
2417+ g_array_append_val (test->arr, test->bill);
2418+ func (test, &error);
2419+ g_assert_no_error (error);
2420+
2421+ /* by the time the method returns, we should have had the
2422+ * removal-notification, too */
2423+ g_assert (!tp_intset_is_member (
2424+ tp_channel_group_get_members (test->deny),
2425+ test->bill));
2426+ test_assert_contact_state (test, test->bill,
2427+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2428+
2429+ g_assert_cmpuint (test->log->len, ==, 1);
2430+ test_assert_one_contact_unblocked (test, 0, test->bill,
2431+ tp_handle_inspect (test->contact_repo, test->bill));
2432+}
2433+
2434+static void
2435+unblock_contacts_no_op (Test *test,
2436+ ManipulateContactsFunc func)
2437+{
2438+ GError *error = NULL;
2439+
2440+ test->deny = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "deny");
2441+
2442+ g_assert (!tp_intset_is_member (
2443+ tp_channel_group_get_members (test->deny),
2444+ test->ninja));
2445+
2446+ g_array_append_val (test->arr, test->ninja);
2447+ func (test, &error);
2448+ g_assert_no_error (error);
2449+ g_assert (!tp_intset_is_member (
2450+ tp_channel_group_get_members (test->deny),
2451+ test->ninja));
2452+ test_assert_contact_state (test, test->ninja,
2453+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2454+
2455+ /* We shouldn't emit spurious empty BlockedContactsChanged signals. */
2456+ g_assert_cmpuint (test->log->len, ==, 0);
2457+}
2458+
2459+static void
2460+add_to_deny (Test *test,
2461+ GError **error)
2462+{
2463+ tp_cli_channel_interface_group_run_add_members (test->deny,
2464+ -1, test->arr, "", error, NULL);
2465+}
2466+
2467+static void
2468+test_add_to_deny (Test *test,
2469+ gconstpointer nil G_GNUC_UNUSED)
2470+{
2471+ block_contacts (test, add_to_deny);
2472+}
2473+
2474+static void
2475+test_add_to_deny_no_op (Test *test,
2476+ gconstpointer nil G_GNUC_UNUSED)
2477+{
2478+ block_contacts_no_op (test, add_to_deny);
2479+}
2480+
2481+static void
2482+remove_from_deny (Test *test,
2483+ GError **error)
2484+{
2485+ tp_cli_channel_interface_group_run_remove_members (test->deny,
2486+ -1, test->arr, "", error, NULL);
2487+}
2488+
2489+static void
2490+test_remove_from_deny (Test *test,
2491+ gconstpointer nil G_GNUC_UNUSED)
2492+{
2493+ unblock_contacts (test, remove_from_deny);
2494+}
2495+
2496+static void
2497+test_remove_from_deny_no_op (Test *test,
2498+ gconstpointer nil G_GNUC_UNUSED)
2499+{
2500+ unblock_contacts_no_op (test, remove_from_deny);
2501+}
2502+
2503+static void
2504+test_request_blocked_contacts (Test *test,
2505+ gconstpointer nil G_GNUC_UNUSED)
2506+{
2507+ GHashTable *blocked_contacts;
2508+ GError *error = NULL;
2509+
2510+ tp_cli_connection_interface_contact_blocking_run_request_blocked_contacts (
2511+ test->conn, -1, &blocked_contacts, &error, NULL);
2512+ g_assert_no_error (error);
2513+ g_assert (blocked_contacts != NULL);
2514+
2515+ /* Both Bill and the shadowy Steve are blocked; Steve does not appear in this
2516+ * test, as he is in poor health.
2517+ */
2518+ g_assert_cmpuint (g_hash_table_size (blocked_contacts), ==, 2);
2519+ g_assert_cmpstr (tp_handle_inspect (test->contact_repo, test->bill), ==,
2520+ g_hash_table_lookup (blocked_contacts, GUINT_TO_POINTER (test->bill)));
2521+ g_hash_table_unref (blocked_contacts);
2522+}
2523+
2524+static void
2525+request_blocked_contacts_succeeded_cb (
2526+ TpConnection *conn,
2527+ GHashTable *blocked_contacts,
2528+ const GError *error,
2529+ gpointer user_data,
2530+ GObject *weak_object)
2531+{
2532+ g_assert_no_error (error);
2533+
2534+ /* As above. */
2535+ g_assert_cmpuint (g_hash_table_size (blocked_contacts), ==, 2);
2536+}
2537+
2538+static void
2539+test_request_blocked_contacts_pre_connect (Test *test,
2540+ gconstpointer nil G_GNUC_UNUSED)
2541+{
2542+ gboolean ok;
2543+
2544+ /* This verifies that calling RequestBlockedContacts()
2545+ * before Connect(), when Connect() ultimately succeeds, returns correctly.
2546+ */
2547+ tp_cli_connection_interface_contact_blocking_call_request_blocked_contacts (
2548+ test->conn, -1, request_blocked_contacts_succeeded_cb,
2549+ test, test_quit_loop, NULL);
2550+ tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL);
2551+ g_main_loop_run (test->main_loop);
2552+
2553+ ok = tp_cli_connection_run_disconnect (test->conn, -1, NULL, NULL);
2554+ g_assert (ok);
2555+}
2556+
2557+static void
2558+request_blocked_contacts_failed_cb (
2559+ TpConnection *conn,
2560+ GHashTable *blocked_contacts,
2561+ const GError *error,
2562+ gpointer user_data,
2563+ GObject *weak_object)
2564+{
2565+ g_assert_error (error, TP_ERRORS, TP_ERROR_DISCONNECTED);
2566+}
2567+
2568+static void
2569+test_request_blocked_contacts_connect_failed (Test *test,
2570+ gconstpointer nil G_GNUC_UNUSED)
2571+{
2572+ /* This verifies that calling RequestBlockedContacts() (twice, no less)
2573+ * before Connect(), when Connect() ultimately fails, returns an appropriate
2574+ * error.
2575+ */
2576+ tp_cli_connection_interface_contact_blocking_call_request_blocked_contacts (
2577+ test->conn, -1, request_blocked_contacts_failed_cb,
2578+ test, test_quit_loop, NULL);
2579+ tp_cli_connection_interface_contact_blocking_call_request_blocked_contacts (
2580+ test->conn, -1, request_blocked_contacts_failed_cb,
2581+ test, test_quit_loop, NULL);
2582+
2583+ /* We expect calling Connect() to fail because the handle was invalid, but
2584+ * don't wait around for it.
2585+ */
2586+ tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL);
2587+ /* Spin the mainloop twice, once for each outstanding call. */
2588+ g_main_loop_run (test->main_loop);
2589+ g_main_loop_run (test->main_loop);
2590+}
2591+
2592+static void
2593+call_block_contacts (Test *test,
2594+ GError **error)
2595+{
2596+ tp_cli_connection_interface_contact_blocking_run_block_contacts (test->conn,
2597+ -1, test->arr, FALSE, error, NULL);
2598+}
2599+
2600+static void
2601+test_block_contacts (Test *test,
2602+ gconstpointer nil G_GNUC_UNUSED)
2603+{
2604+ block_contacts (test, call_block_contacts);
2605+}
2606+
2607+static void
2608+test_block_contacts_no_op (Test *test,
2609+ gconstpointer nil G_GNUC_UNUSED)
2610+{
2611+ block_contacts_no_op (test, call_block_contacts);
2612+}
2613+
2614+static void
2615+call_unblock_contacts (Test *test,
2616+ GError **error)
2617+{
2618+ tp_cli_connection_interface_contact_blocking_run_unblock_contacts (
2619+ test->conn, -1, test->arr, error, NULL);
2620+}
2621+
2622+static void
2623+test_unblock_contacts (Test *test,
2624+ gconstpointer nil G_GNUC_UNUSED)
2625+{
2626+ unblock_contacts (test, call_unblock_contacts);
2627+}
2628+
2629+static void
2630+test_unblock_contacts_no_op (Test *test,
2631+ gconstpointer nil G_GNUC_UNUSED)
2632+{
2633+ unblock_contacts_no_op (test, call_unblock_contacts);
2634+}
2635+
2636+int
2637+main (int argc,
2638+ char **argv)
2639+{
2640+ g_type_init ();
2641+ tp_tests_abort_after (30);
2642+ tp_debug_set_flags ("all");
2643+
2644+ g_test_init (&argc, &argv, NULL);
2645+
2646+ g_test_add ("/contact-lists/nothing",
2647+ Test, NULL, setup, test_nothing, teardown);
2648+
2649+ g_test_add ("/contact-lists/initial-channels",
2650+ Test, NULL, setup, test_initial_channels, teardown);
2651+ g_test_add ("/contact-lists/properties",
2652+ Test, NULL, setup, test_properties, teardown);
2653+ g_test_add ("/contact-lists/contacts",
2654+ Test, NULL, setup, test_contacts, teardown);
2655+ g_test_add ("/contact-lists/contact-list-attrs",
2656+ Test, NULL, setup, test_contact_list_attrs, teardown);
2657+
2658+ g_test_add ("/contact-lists/accept-publish-request",
2659+ Test, NULL, setup, test_accept_publish_request, teardown);
2660+ g_test_add ("/contact-lists/reject-publish-request",
2661+ Test, NULL, setup, test_reject_publish_request, teardown);
2662+ g_test_add ("/contact-lists/reject-publish-request/unpublish",
2663+ Test, "unpublish", setup, test_reject_publish_request, teardown);
2664+ g_test_add ("/contact-lists/add-to-publish/pre-approve",
2665+ Test, NULL, setup, test_add_to_publish_pre_approve, teardown);
2666+ g_test_add ("/contact-lists/add-to-publish/no-op",
2667+ Test, NULL, setup, test_add_to_publish_no_op, teardown);
2668+ g_test_add ("/contact-lists/remove-from-publish",
2669+ Test, NULL, setup, test_remove_from_publish, teardown);
2670+ g_test_add ("/contact-lists/remove-from-publish/no-op",
2671+ Test, NULL, setup, test_remove_from_publish_no_op, teardown);
2672+
2673+ g_test_add ("/contact-lists/accept-publish-request/old",
2674+ Test, "old", setup, test_accept_publish_request, teardown);
2675+ g_test_add ("/contact-lists/reject-publish-request/old",
2676+ Test, "old", setup, test_reject_publish_request, teardown);
2677+ g_test_add ("/contact-lists/add-to-publish/pre-approve/old",
2678+ Test, "old", setup, test_add_to_publish_pre_approve, teardown);
2679+ g_test_add ("/contact-lists/add-to-publish/no-op/old",
2680+ Test, "old", setup, test_add_to_publish_no_op, teardown);
2681+ g_test_add ("/contact-lists/remove-from-publish/old",
2682+ Test, "old", setup, test_remove_from_publish, teardown);
2683+ g_test_add ("/contact-lists/remove-from-publish/no-op/old",
2684+ Test, "old", setup, test_remove_from_publish_no_op, teardown);
2685+
2686+ g_test_add ("/contact-lists/cancelled-publish-request",
2687+ Test, NULL, setup, test_cancelled_publish_request, teardown);
2688+ g_test_add ("/contact-lists/cancelled-publish-request",
2689+ Test, "remove-after", setup, test_cancelled_publish_request, teardown);
2690+
2691+ g_test_add ("/contact-lists/add-to-stored",
2692+ Test, NULL, setup, test_add_to_stored, teardown);
2693+ g_test_add ("/contact-lists/add-to-stored/no-op",
2694+ Test, NULL, setup, test_add_to_stored_no_op, teardown);
2695+ g_test_add ("/contact-lists/remove-from-stored",
2696+ Test, NULL, setup, test_remove_from_stored, teardown);
2697+ g_test_add ("/contact-lists/remove-from-stored/no-op",
2698+ Test, NULL, setup, test_remove_from_stored_no_op, teardown);
2699+
2700+ g_test_add ("/contact-lists/add-to-stored/old",
2701+ Test, "old", setup, test_add_to_stored, teardown);
2702+ g_test_add ("/contact-lists/add-to-stored/no-op/old",
2703+ Test, "old", setup, test_add_to_stored_no_op, teardown);
2704+ g_test_add ("/contact-lists/remove-from-stored/old",
2705+ Test, "old", setup, test_remove_from_stored, teardown);
2706+ g_test_add ("/contact-lists/remove-from-stored/no-op/old",
2707+ Test, "old", setup, test_remove_from_stored_no_op, teardown);
2708+
2709+ g_test_add ("/contact-lists/accept-subscribe-request",
2710+ Test, NULL, setup, test_accept_subscribe_request, teardown);
2711+ g_test_add ("/contact-lists/reject-subscribe-request",
2712+ Test, NULL, setup, test_reject_subscribe_request, teardown);
2713+ g_test_add ("/contact-lists/remove-from-subscribe",
2714+ Test, NULL, setup, test_remove_from_subscribe, teardown);
2715+ g_test_add ("/contact-lists/remove-from-subscribe/pending",
2716+ Test, NULL, setup, test_remove_from_subscribe_pending, teardown);
2717+ g_test_add ("/contact-lists/remove-from-subscribe/no-op",
2718+ Test, NULL, setup, test_remove_from_subscribe_no_op, teardown);
2719+
2720+ g_test_add ("/contact-lists/accept-subscribe-request/old",
2721+ Test, "old", setup, test_accept_subscribe_request, teardown);
2722+ g_test_add ("/contact-lists/reject-subscribe-request/old",
2723+ Test, "old", setup, test_reject_subscribe_request, teardown);
2724+ g_test_add ("/contact-lists/remove-from-subscribe/old",
2725+ Test, "old", setup, test_remove_from_subscribe, teardown);
2726+ g_test_add ("/contact-lists/remove-from-subscribe/pending/old",
2727+ Test, "old", setup, test_remove_from_subscribe_pending, teardown);
2728+ g_test_add ("/contact-lists/remove-from-subscribe/no-op/old",
2729+ Test, "old", setup, test_remove_from_subscribe_no_op, teardown);
2730+
2731+ g_test_add ("/contact-lists/reject-subscribe-request/remove-after",
2732+ Test, "remove-after", setup, test_reject_subscribe_request, teardown);
2733+
2734+ g_test_add ("/contact-lists/add-to-group",
2735+ Test, NULL, setup, test_add_to_group, teardown);
2736+ g_test_add ("/contact-lists/add-to-group/no-op",
2737+ Test, NULL, setup, test_add_to_group_no_op, teardown);
2738+ g_test_add ("/contact-lists/remove-from-group",
2739+ Test, NULL, setup, test_remove_from_group, teardown);
2740+ g_test_add ("/contact-lists/remove-from-group/no-op",
2741+ Test, NULL, setup, test_remove_from_group_no_op, teardown);
2742+ g_test_add ("/contact-lists/remove-group",
2743+ Test, NULL, setup, test_remove_group, teardown);
2744+ g_test_add ("/contact-lists/remove-group/empty",
2745+ Test, NULL, setup, test_remove_group_empty, teardown);
2746+
2747+ g_test_add ("/contact-lists/add-to-group/old",
2748+ Test, "old", setup, test_add_to_group, teardown);
2749+ g_test_add ("/contact-lists/add-to-group/no-op/old",
2750+ Test, "old", setup, test_add_to_group_no_op, teardown);
2751+ g_test_add ("/contact-lists/remove-from-group/old",
2752+ Test, "old", setup, test_remove_from_group, teardown);
2753+ g_test_add ("/contact-lists/remove-from-group/no-op/old",
2754+ Test, "old", setup, test_remove_from_group_no_op, teardown);
2755+ g_test_add ("/contact-lists/remove-group/old",
2756+ Test, "old", setup, test_remove_group, teardown);
2757+ g_test_add ("/contact-lists/remove-group/empty/old",
2758+ Test, "old", setup, test_remove_group_empty, teardown);
2759+
2760+ g_test_add ("/contact-lists/set_contact_groups",
2761+ Test, NULL, setup, test_set_contact_groups, teardown);
2762+ g_test_add ("/contact-lists/set_contact_groups/no-op",
2763+ Test, NULL, setup, test_set_contact_groups_no_op, teardown);
2764+ g_test_add ("/contact-lists/set_group_members",
2765+ Test, NULL, setup, test_set_group_members, teardown);
2766+
2767+ g_test_add ("/contact-lists/rename_group",
2768+ Test, NULL, setup, test_rename_group, teardown);
2769+ g_test_add ("/contact-lists/rename_group/absent",
2770+ Test, NULL, setup, test_rename_group_absent, teardown);
2771+ g_test_add ("/contact-lists/rename_group/overwrite",
2772+ Test, NULL, setup, test_rename_group_overwrite, teardown);
2773+
2774+ g_test_add ("/contact-lists/add-to-deny",
2775+ Test, NULL, setup, test_add_to_deny, teardown);
2776+ g_test_add ("/contact-lists/add-to-deny/no-op",
2777+ Test, NULL, setup, test_add_to_deny_no_op, teardown);
2778+ g_test_add ("/contact-lists/remove-from-deny",
2779+ Test, NULL, setup, test_remove_from_deny, teardown);
2780+ g_test_add ("/contact-lists/remove-from-deny/no-op",
2781+ Test, NULL, setup, test_remove_from_deny_no_op, teardown);
2782+
2783+ g_test_add ("/contact-lists/request-blocked-contacts",
2784+ Test, NULL, setup, test_request_blocked_contacts, teardown);
2785+ g_test_add ("/contact-lists/request-blocked-contacts-before-connect",
2786+ Test, NULL, setup_pre_connect,
2787+ test_request_blocked_contacts_pre_connect, teardown_pre_connect);
2788+ g_test_add ("/contact-lists/request-blocked-contacts-connect-failed",
2789+ Test, "break-account-parameter", setup_pre_connect,
2790+ test_request_blocked_contacts_connect_failed,
2791+ teardown_pre_connect);
2792+ g_test_add ("/contact-lists/block-contacts",
2793+ Test, NULL, setup, test_block_contacts, teardown);
2794+ g_test_add ("/contact-lists/block-contacts/no-op",
2795+ Test, NULL, setup, test_block_contacts_no_op, teardown);
2796+ g_test_add ("/contact-lists/unblock-contacts",
2797+ Test, NULL, setup, test_unblock_contacts, teardown);
2798+ g_test_add ("/contact-lists/unblock-contacts/no-op",
2799+ Test, NULL, setup, test_unblock_contacts_no_op, teardown);
2800+
2801+ return g_test_run ();
2802+}
2803+>>>>>>> MERGE-SOURCE

Subscribers

People subscribed via source and target branches

to all changes: