Merge lp:~ubuntu-branches/ubuntu/precise/telepathy-glib/precise-201111172307 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-201111172307
Merge into: lp:ubuntu/precise/telepathy-glib
Diff against target: 2843 lines (+2832/-0) (has conflicts)
1 file modified
.pc/ludicrous-timeout-for-lp-buildd.patch/tests/dbus/contact-lists.c (+2832/-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-201111172307
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+82610@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-201111172307. 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

74. By Ken VanDine

releasing version 0.17.1-0ubuntu1

73. By Ken VanDine

* debian/control
  - bump build depends for gobject-introspection to >= 1.30
* debian/libtelepathy-glib0.symbols
  - added new symbols

72. By Ken VanDine

New upstream release.

71. By Ken VanDine

merged

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-17 16:02:36 +0000
3+++ .pc/ludicrous-timeout-for-lp-buildd.patch/tests/dbus/contact-lists.c 2011-11-17 23:14:36 +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@@ -2828,3 +2829,2834 @@
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_assert_contact_blocking_attrs (Test *test,
989+ TpHandle handle,
990+ gboolean expected_blocked)
991+{
992+ GHashTable *asv;
993+ gboolean blocked, valid;
994+
995+ g_assert_cmpuint (g_hash_table_size (test->contact_attributes), >=, 1);
996+ asv = g_hash_table_lookup (test->contact_attributes,
997+ GUINT_TO_POINTER (handle));
998+ g_assert (asv != NULL);
999+ tp_asv_dump (asv);
1000+
1001+ blocked = tp_asv_get_boolean (asv,
1002+ TP_TOKEN_CONNECTION_INTERFACE_CONTACT_BLOCKING_BLOCKED, &valid);
1003+ g_assert (valid);
1004+ g_assert (blocked == expected_blocked);
1005+}
1006+
1007+static void
1008+test_contact_blocking_attrs (Test *test,
1009+ gconstpointer nil G_GNUC_UNUSED)
1010+{
1011+ const gchar * const interfaces[] = {
1012+ TP_IFACE_CONNECTION_INTERFACE_CONTACT_BLOCKING,
1013+ NULL };
1014+ TpHandle handles[] = { test->sjoerd, test->bill };
1015+
1016+ tp_connection_get_contact_attributes (test->conn, -1,
1017+ G_N_ELEMENTS (handles), handles,
1018+ interfaces, FALSE, contact_attrs_cb, test, test_quit_loop, NULL);
1019+ g_main_loop_run (test->main_loop);
1020+
1021+ test_assert_contact_blocking_attrs (test, test->sjoerd, FALSE);
1022+ test_assert_contact_blocking_attrs (test, test->bill, TRUE);
1023+}
1024+
1025+static void
1026+test_accept_publish_request (Test *test,
1027+ gconstpointer mode)
1028+{
1029+ GError *error = NULL;
1030+
1031+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1032+
1033+ g_assert_cmpuint (
1034+ tp_intset_size (tp_channel_group_get_local_pending (test->publish)),
1035+ ==, 2);
1036+ g_assert (tp_intset_is_member (
1037+ tp_channel_group_get_local_pending (test->publish),
1038+ test->wim));
1039+
1040+ g_array_append_val (test->arr, test->wim);
1041+
1042+ if (!tp_strdiff (mode, "old"))
1043+ tp_cli_channel_interface_group_run_add_members (test->publish,
1044+ -1, test->arr, "", &error, NULL);
1045+ else
1046+ tp_cli_connection_interface_contact_list_run_authorize_publication (
1047+ test->conn, -1, test->arr, &error, NULL);
1048+
1049+ g_assert_no_error (error);
1050+
1051+ /* by the time the method returns, we should have had the
1052+ * change-notification, too */
1053+ g_assert_cmpuint (
1054+ tp_intset_size (tp_channel_group_get_local_pending (test->publish)),
1055+ ==, 1);
1056+ g_assert (tp_intset_is_member (
1057+ tp_channel_group_get_members (test->publish),
1058+ test->wim));
1059+ g_assert (!tp_intset_is_member (
1060+ tp_channel_group_get_local_pending (test->publish),
1061+ test->wim));
1062+
1063+ g_assert_cmpuint (test->log->len, ==, 1);
1064+ test_assert_one_contact_changed (test, 0, test->wim, TP_SUBSCRIPTION_STATE_NO,
1065+ TP_SUBSCRIPTION_STATE_YES, "");
1066+ test_assert_contact_state (test, test->wim,
1067+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_YES, NULL, NULL);
1068+}
1069+
1070+static void
1071+test_reject_publish_request (Test *test,
1072+ gconstpointer mode)
1073+{
1074+ GError *error = NULL;
1075+
1076+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1077+
1078+ g_assert (tp_intset_is_member (
1079+ tp_channel_group_get_local_pending (test->publish),
1080+ test->wim));
1081+ g_assert (!tp_intset_is_member (
1082+ tp_channel_group_get_members (test->publish),
1083+ test->wim));
1084+
1085+ g_array_append_val (test->arr, test->wim);
1086+
1087+ if (!tp_strdiff (mode, "old"))
1088+ {
1089+ tp_cli_channel_interface_group_run_remove_members (test->publish,
1090+ -1, test->arr, "", &error, NULL);
1091+ }
1092+ else if (!tp_strdiff (mode, "unpublish"))
1093+ {
1094+ /* directly equivalent, but in practice people won't do this */
1095+ tp_cli_connection_interface_contact_list_run_unpublish (
1096+ test->conn, -1, test->arr, &error, NULL);
1097+ }
1098+ else
1099+ {
1100+ /* this isn't directly equivalent, but in practice it's what people
1101+ * will do */
1102+ tp_cli_connection_interface_contact_list_run_remove_contacts (
1103+ test->conn, -1, test->arr, &error, NULL);
1104+ }
1105+
1106+ g_assert_no_error (error);
1107+
1108+ /* by the time the method returns, we should have had the
1109+ * removal-notification, too */
1110+ g_assert_cmpuint (
1111+ tp_intset_size (tp_channel_group_get_local_pending (test->publish)),
1112+ ==, 1);
1113+ g_assert (!tp_intset_is_member (
1114+ tp_channel_group_get_members (test->publish),
1115+ test->wim));
1116+ g_assert (!tp_intset_is_member (
1117+ tp_channel_group_get_local_pending (test->publish),
1118+ test->wim));
1119+
1120+ g_assert_cmpuint (test->log->len, ==, 1);
1121+
1122+ /* because Wim wasn't really on our contact list, he's removed as a
1123+ * side-effect, even if we only unpublished */
1124+ test_assert_one_contact_removed (test, 0, test->wim);
1125+
1126+ test_assert_contact_state (test, test->wim,
1127+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1128+}
1129+
1130+static void
1131+test_add_to_publish_pre_approve (Test *test,
1132+ gconstpointer mode)
1133+{
1134+ GError *error = NULL;
1135+
1136+ /* Unilaterally adding a member to the publish channel doesn't work, but
1137+ * in the new contact list manager the method "succeeds" anyway, and
1138+ * any subsequent subscription request succeeds instantly. */
1139+
1140+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1141+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1142+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1143+
1144+ g_array_append_val (test->arr, test->ninja);
1145+
1146+ g_assert (!tp_intset_is_member (
1147+ tp_channel_group_get_local_pending (test->publish),
1148+ test->ninja));
1149+
1150+ if (!tp_strdiff (mode, "old"))
1151+ tp_cli_channel_interface_group_run_add_members (test->publish,
1152+ -1, test->arr, "", &error, NULL);
1153+ else
1154+ tp_cli_connection_interface_contact_list_run_authorize_publication (
1155+ test->conn, -1, test->arr, &error, NULL);
1156+
1157+ g_assert_no_error (error);
1158+
1159+ g_assert (!tp_intset_is_member (
1160+ tp_channel_group_get_local_pending (test->publish),
1161+ test->ninja));
1162+
1163+ /* the example CM's fake contacts accept requests that contain "please" */
1164+ if (!tp_strdiff (mode, "old"))
1165+ tp_cli_channel_interface_group_run_add_members (test->subscribe,
1166+ -1, test->arr, "Please may I see your presence?", &error, NULL);
1167+ else
1168+ tp_cli_connection_interface_contact_list_run_request_subscription (
1169+ test->conn, -1, test->arr, "Please may I see your presence?", &error,
1170+ NULL);
1171+
1172+ g_assert_no_error (error);
1173+
1174+ /* by the time the method returns, we should have had the
1175+ * change-notification, too */
1176+ g_assert (tp_intset_is_member (
1177+ tp_channel_group_get_remote_pending (test->subscribe),
1178+ test->ninja));
1179+ g_assert (tp_intset_is_member (
1180+ tp_channel_group_get_members (test->stored),
1181+ test->ninja));
1182+ g_assert (!tp_intset_is_member (
1183+ tp_channel_group_get_remote_pending (test->stored),
1184+ test->ninja));
1185+
1186+ /* after a short delay, the contact accepts our request */
1187+ while (tp_intset_is_member (
1188+ tp_channel_group_get_remote_pending (test->subscribe),
1189+ test->ninja))
1190+ g_main_context_iteration (NULL, TRUE);
1191+
1192+ g_assert (tp_intset_is_member (
1193+ tp_channel_group_get_members (test->subscribe),
1194+ test->ninja));
1195+ g_assert (!tp_intset_is_member (
1196+ tp_channel_group_get_remote_pending (test->subscribe),
1197+ test->ninja));
1198+
1199+ /* the contact also requests our presence after a short delay - we
1200+ * pre-approved, so they go straight to full membership */
1201+ while (!tp_intset_is_member (
1202+ tp_channel_group_get_members (test->publish),
1203+ test->ninja) || test->log->len < 3)
1204+ g_main_context_iteration (NULL, TRUE);
1205+
1206+ g_assert (tp_intset_is_member (
1207+ tp_channel_group_get_members (test->publish),
1208+ test->ninja));
1209+ g_assert (!tp_intset_is_member (
1210+ tp_channel_group_get_local_pending (test->publish),
1211+ test->ninja));
1212+
1213+ g_assert_cmpuint (test->log->len, ==, 3);
1214+ test_assert_one_contact_changed (test, 0, test->ninja, TP_SUBSCRIPTION_STATE_ASK,
1215+ TP_SUBSCRIPTION_STATE_NO, "");
1216+ test_assert_one_contact_changed (test, 1, test->ninja, TP_SUBSCRIPTION_STATE_YES,
1217+ TP_SUBSCRIPTION_STATE_NO, "");
1218+ test_assert_one_contact_changed (test, 2, test->ninja, TP_SUBSCRIPTION_STATE_YES,
1219+ TP_SUBSCRIPTION_STATE_YES, "");
1220+
1221+ test_assert_contact_state (test, test->ninja,
1222+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, NULL);
1223+}
1224+
1225+static void
1226+test_add_to_publish_no_op (Test *test,
1227+ gconstpointer mode)
1228+{
1229+ GError *error = NULL;
1230+
1231+ /* Adding a member to the publish channel when they're already there is
1232+ * valid. */
1233+
1234+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1235+
1236+ g_assert (tp_intset_is_member (
1237+ tp_channel_group_get_members (test->publish),
1238+ test->sjoerd));
1239+
1240+ g_array_append_val (test->arr, test->sjoerd);
1241+
1242+ if (!tp_strdiff (mode, "old"))
1243+ tp_cli_channel_interface_group_run_add_members (test->publish,
1244+ -1, test->arr, "", &error, NULL);
1245+ else
1246+ tp_cli_connection_interface_contact_list_run_authorize_publication (
1247+ test->conn, -1, test->arr, &error, NULL);
1248+
1249+ g_assert_no_error (error);
1250+
1251+ g_assert (tp_intset_is_member (
1252+ tp_channel_group_get_members (test->publish),
1253+ test->sjoerd));
1254+
1255+ g_assert_cmpuint (test->log->len, ==, 0);
1256+ test_assert_contact_state (test, test->sjoerd,
1257+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, "Cambridge");
1258+}
1259+
1260+static void
1261+test_remove_from_publish (Test *test,
1262+ gconstpointer mode)
1263+{
1264+ GError *error = NULL;
1265+
1266+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1267+
1268+ g_assert_cmpuint (
1269+ tp_intset_size (tp_channel_group_get_members (test->publish)),
1270+ ==, 4);
1271+ g_assert (tp_intset_is_member (
1272+ tp_channel_group_get_members (test->publish),
1273+ test->sjoerd));
1274+
1275+ g_array_append_val (test->arr, test->sjoerd);
1276+
1277+ if (!tp_strdiff (mode, "old"))
1278+ tp_cli_channel_interface_group_run_remove_members (test->publish,
1279+ -1, test->arr, "", &error, NULL);
1280+ else
1281+ tp_cli_connection_interface_contact_list_run_unpublish (
1282+ test->conn, -1, test->arr, &error, NULL);
1283+
1284+ g_assert_no_error (error);
1285+
1286+ /* by the time the method returns, we should have had the
1287+ * removal-notification, too */
1288+ g_assert (!tp_intset_is_member (
1289+ tp_channel_group_get_members (test->publish),
1290+ test->sjoerd));
1291+
1292+ /* the contact re-requests our presence after a short delay */
1293+ while (!tp_intset_is_member (
1294+ tp_channel_group_get_local_pending (test->publish),
1295+ test->sjoerd) ||
1296+ test->log->len < 2)
1297+ g_main_context_iteration (NULL, TRUE);
1298+
1299+ g_assert (!tp_intset_is_member (
1300+ tp_channel_group_get_members (test->publish),
1301+ test->sjoerd));
1302+ g_assert (tp_intset_is_member (
1303+ tp_channel_group_get_local_pending (test->publish),
1304+ test->sjoerd));
1305+
1306+ g_assert_cmpuint (test->log->len, ==, 2);
1307+ test_assert_one_contact_changed (test, 0, test->sjoerd,
1308+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_NO, "");
1309+ test_assert_one_contact_changed (test, 1, test->sjoerd,
1310+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1311+ "May I see your presence, please?");
1312+ test_assert_contact_state (test, test->sjoerd,
1313+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1314+ "May I see your presence, please?", "Cambridge");
1315+}
1316+
1317+static void
1318+test_remove_from_publish_no_op (Test *test,
1319+ gconstpointer mode)
1320+{
1321+ GError *error = NULL;
1322+
1323+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1324+
1325+ g_assert_cmpuint (
1326+ tp_intset_size (tp_channel_group_get_members (test->publish)),
1327+ ==, 4);
1328+ g_assert (!tp_intset_is_member (
1329+ tp_channel_group_get_members (test->publish),
1330+ test->ninja));
1331+
1332+ g_array_append_val (test->arr, test->ninja);
1333+
1334+ if (!tp_strdiff (mode, "old"))
1335+ tp_cli_channel_interface_group_run_remove_members (test->publish,
1336+ -1, test->arr, "", &error, NULL);
1337+ else
1338+ tp_cli_connection_interface_contact_list_run_unpublish (
1339+ test->conn, -1, test->arr, &error, NULL);
1340+
1341+ g_assert_no_error (error);
1342+
1343+ g_assert_cmpuint (test->log->len, ==, 0);
1344+ test_assert_contact_state (test, test->ninja,
1345+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1346+}
1347+
1348+static void
1349+test_cancelled_publish_request (Test *test,
1350+ gconstpointer mode)
1351+{
1352+ GError *error = NULL;
1353+
1354+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1355+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1356+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1357+
1358+ g_assert_cmpuint (
1359+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1360+ ==, 4);
1361+ g_assert (!tp_intset_is_member (
1362+ tp_channel_group_get_members (test->subscribe),
1363+ test->canceller));
1364+ g_assert (!tp_intset_is_member (
1365+ tp_channel_group_get_remote_pending (test->subscribe),
1366+ test->canceller));
1367+
1368+ /* the example CM's fake contacts accept requests that contain "please" */
1369+ g_array_append_val (test->arr, test->canceller);
1370+
1371+ tp_cli_connection_interface_contact_list_run_request_subscription (
1372+ test->conn, -1, test->arr, "Please may I see your presence?",
1373+ &error, NULL);
1374+
1375+ /* It starts off the same as test_accept_subscribe_request, but because
1376+ * we're using an identifier with special significance, the contact cancels
1377+ * the request immediately after */
1378+ while (tp_intset_is_member (
1379+ tp_channel_group_get_local_pending (test->publish),
1380+ test->canceller) ||
1381+ test->log->len < 4)
1382+ g_main_context_iteration (NULL, TRUE);
1383+
1384+ g_assert (!tp_intset_is_member (
1385+ tp_channel_group_get_members (test->publish),
1386+ test->canceller));
1387+ g_assert (!tp_intset_is_member (
1388+ tp_channel_group_get_local_pending (test->publish),
1389+ test->canceller));
1390+
1391+ g_assert_cmpuint (test->log->len, ==, 4);
1392+ test_assert_one_contact_changed (test, 0, test->canceller,
1393+ TP_SUBSCRIPTION_STATE_ASK, TP_SUBSCRIPTION_STATE_NO, "");
1394+ test_assert_one_contact_changed (test, 1, test->canceller,
1395+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_NO, "");
1396+ test_assert_one_contact_changed (test, 2, test->canceller,
1397+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1398+ "May I see your presence, please?");
1399+ test_assert_one_contact_changed (test, 3, test->canceller,
1400+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY, "");
1401+ test_assert_contact_state (test, test->canceller,
1402+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY,
1403+ NULL, NULL);
1404+
1405+ test_clear_log (test);
1406+
1407+ /* We can acknowledge the cancellation with Unpublish() or
1408+ * RemoveContacts(). We can't use the old API here, because in the old API,
1409+ * the contact has already vanished from the Group */
1410+ if (!tp_strdiff (mode, "remove-after"))
1411+ tp_cli_connection_interface_contact_list_run_remove_contacts (test->conn,
1412+ -1, test->arr, &error, NULL);
1413+ else
1414+ tp_cli_connection_interface_contact_list_run_unpublish (
1415+ test->conn, -1, test->arr, &error, NULL);
1416+
1417+ while (test->log->len < 1)
1418+ g_main_context_iteration (NULL, TRUE);
1419+
1420+ g_assert_cmpuint (test->log->len, ==, 1);
1421+
1422+ if (!tp_strdiff (mode, "remove-after"))
1423+ test_assert_one_contact_removed (test, 0, test->canceller);
1424+ else
1425+ test_assert_one_contact_changed (test, 0, test->canceller,
1426+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_NO, "");
1427+}
1428+
1429+static void
1430+test_add_to_stored (Test *test,
1431+ gconstpointer mode)
1432+{
1433+ GError *error = NULL;
1434+
1435+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1436+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1437+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST,
1438+ "subscribe");
1439+
1440+ g_assert_cmpuint (
1441+ tp_intset_size (tp_channel_group_get_members (test->stored)),
1442+ ==, 8);
1443+ g_assert (!tp_intset_is_member (
1444+ tp_channel_group_get_members (test->stored),
1445+ test->ninja));
1446+
1447+ g_array_append_val (test->arr, test->ninja);
1448+
1449+ if (!tp_strdiff (mode, "old"))
1450+ {
1451+ tp_cli_channel_interface_group_run_add_members (test->stored,
1452+ -1, test->arr, "", &error, NULL);
1453+ }
1454+ else
1455+ {
1456+ /* there's no specific API for adding contacts to stored (it's not a
1457+ * very useful action in general), but setting an alias has it as a
1458+ * side-effect */
1459+ GHashTable *table = g_hash_table_new (NULL, NULL);
1460+
1461+ g_hash_table_insert (table, GUINT_TO_POINTER (test->ninja),
1462+ "The Wee Ninja");
1463+ tp_cli_connection_interface_aliasing_run_set_aliases (test->conn,
1464+ -1, table, &error, NULL);
1465+ g_hash_table_unref (table);
1466+ }
1467+
1468+ g_assert_no_error (error);
1469+
1470+ /* by the time the method returns, we should have had the
1471+ * change-notification, too */
1472+ g_assert_cmpuint (
1473+ tp_intset_size (tp_channel_group_get_members (test->stored)),
1474+ ==, 9);
1475+ g_assert (tp_intset_is_member (
1476+ tp_channel_group_get_members (test->stored),
1477+ test->ninja));
1478+
1479+ g_assert (!tp_intset_is_member (
1480+ tp_channel_group_get_members (test->subscribe),
1481+ test->ninja));
1482+ g_assert (!tp_intset_is_member (
1483+ tp_channel_group_get_members (test->publish),
1484+ test->ninja));
1485+
1486+ g_assert_cmpuint (test->log->len, ==, 1);
1487+ test_assert_one_contact_changed (test, 0, test->ninja,
1488+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1489+ test_assert_contact_state (test, test->ninja,
1490+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1491+}
1492+
1493+static void
1494+test_add_to_stored_no_op (Test *test,
1495+ gconstpointer mode)
1496+{
1497+ GError *error = NULL;
1498+
1499+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1500+
1501+ g_assert_cmpuint (
1502+ tp_intset_size (tp_channel_group_get_members (test->stored)),
1503+ ==, 8);
1504+ g_assert (tp_intset_is_member (
1505+ tp_channel_group_get_members (test->stored),
1506+ test->sjoerd));
1507+
1508+ g_array_append_val (test->arr, test->sjoerd);
1509+
1510+ if (!tp_strdiff (mode, "old"))
1511+ {
1512+ tp_cli_channel_interface_group_run_add_members (test->stored,
1513+ -1, test->arr, "", &error, NULL);
1514+ }
1515+ else
1516+ {
1517+ /* there's no specific API for adding contacts to stored (it's not a
1518+ * very useful action in general), but setting an alias has it as a
1519+ * side-effect */
1520+ GHashTable *table = g_hash_table_new (NULL, NULL);
1521+
1522+ g_hash_table_insert (table, GUINT_TO_POINTER (test->sjoerd),
1523+ "Sjoerd");
1524+ tp_cli_connection_interface_aliasing_run_set_aliases (test->conn,
1525+ -1, table, &error, NULL);
1526+ g_hash_table_unref (table);
1527+ }
1528+
1529+ g_assert_no_error (error);
1530+
1531+ g_assert_cmpuint (test->log->len, ==, 0);
1532+ test_assert_contact_state (test, test->sjoerd,
1533+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, "Cambridge");
1534+}
1535+
1536+static void
1537+test_remove_from_stored (Test *test,
1538+ gconstpointer mode)
1539+{
1540+ GError *error = NULL;
1541+
1542+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1543+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1544+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST,
1545+ "subscribe");
1546+
1547+ g_assert (tp_intset_is_member (
1548+ tp_channel_group_get_members (test->stored),
1549+ test->sjoerd));
1550+
1551+ g_array_append_val (test->arr, test->sjoerd);
1552+
1553+ if (!tp_strdiff (mode, "old"))
1554+ tp_cli_channel_interface_group_run_remove_members (test->stored,
1555+ -1, test->arr, "", &error, NULL);
1556+ else
1557+ tp_cli_connection_interface_contact_list_run_remove_contacts (test->conn,
1558+ -1, test->arr, &error, NULL);
1559+
1560+ g_assert_no_error (error);
1561+
1562+ /* by the time the method returns, we should have had the
1563+ * removal-notification, too */
1564+ g_assert (!tp_intset_is_member (
1565+ tp_channel_group_get_members (test->stored),
1566+ test->sjoerd));
1567+ g_assert (!tp_intset_is_member (
1568+ tp_channel_group_get_members (test->subscribe),
1569+ test->sjoerd));
1570+ g_assert (!tp_intset_is_member (
1571+ tp_channel_group_get_members (test->publish),
1572+ test->sjoerd));
1573+
1574+ g_assert_cmpuint (test->log->len, ==, 1);
1575+ test_assert_one_contact_removed (test, 0, test->sjoerd);
1576+ test_assert_contact_state (test, test->sjoerd,
1577+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1578+}
1579+
1580+static void
1581+test_remove_from_stored_no_op (Test *test,
1582+ gconstpointer mode)
1583+{
1584+ GError *error = NULL;
1585+
1586+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1587+
1588+ g_assert_cmpuint (
1589+ tp_intset_size (tp_channel_group_get_members (test->stored)),
1590+ ==, 8);
1591+ g_assert (!tp_intset_is_member (
1592+ tp_channel_group_get_members (test->stored),
1593+ test->ninja));
1594+
1595+ g_array_append_val (test->arr, test->ninja);
1596+
1597+ if (!tp_strdiff (mode, "old"))
1598+ tp_cli_channel_interface_group_run_remove_members (test->stored,
1599+ -1, test->arr, "", &error, NULL);
1600+ else
1601+ tp_cli_connection_interface_contact_list_run_remove_contacts (test->conn,
1602+ -1, test->arr, &error, NULL);
1603+
1604+ g_assert_no_error (error);
1605+
1606+ g_assert_cmpuint (test->log->len, ==, 0);
1607+ test_assert_contact_state (test, test->ninja,
1608+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1609+}
1610+
1611+static void
1612+test_accept_subscribe_request (Test *test,
1613+ gconstpointer mode)
1614+{
1615+ GError *error = NULL;
1616+
1617+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1618+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1619+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1620+
1621+ g_assert_cmpuint (
1622+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1623+ ==, 4);
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 example CM's fake contacts accept requests that contain "please" */
1632+ g_array_append_val (test->arr, test->ninja);
1633+
1634+ if (!tp_strdiff (mode, "old"))
1635+ tp_cli_channel_interface_group_run_add_members (test->subscribe,
1636+ -1, test->arr, "Please may I see your presence?", &error, NULL);
1637+ else
1638+ tp_cli_connection_interface_contact_list_run_request_subscription (
1639+ test->conn, -1, test->arr, "Please may I see your presence?",
1640+ &error, NULL);
1641+
1642+ g_assert_no_error (error);
1643+
1644+ /* by the time the method returns, we should have had the
1645+ * change-notification, too */
1646+ g_assert (tp_intset_is_member (
1647+ tp_channel_group_get_remote_pending (test->subscribe),
1648+ test->ninja));
1649+ g_assert (tp_intset_is_member (
1650+ tp_channel_group_get_members (test->stored),
1651+ test->ninja));
1652+ g_assert (!tp_intset_is_member (
1653+ tp_channel_group_get_remote_pending (test->stored),
1654+ test->ninja));
1655+
1656+ /* after a short delay, the contact accepts our request */
1657+ while (tp_intset_is_member (
1658+ tp_channel_group_get_remote_pending (test->subscribe),
1659+ test->ninja))
1660+ g_main_context_iteration (NULL, TRUE);
1661+
1662+ g_assert (tp_intset_is_member (
1663+ tp_channel_group_get_members (test->subscribe),
1664+ test->ninja));
1665+ g_assert (!tp_intset_is_member (
1666+ tp_channel_group_get_remote_pending (test->subscribe),
1667+ test->ninja));
1668+
1669+ /* the contact also requests our presence after a short delay */
1670+ while (!tp_intset_is_member (
1671+ tp_channel_group_get_local_pending (test->publish),
1672+ test->ninja) ||
1673+ test->log->len < 3)
1674+ g_main_context_iteration (NULL, TRUE);
1675+
1676+ g_assert (!tp_intset_is_member (
1677+ tp_channel_group_get_members (test->publish),
1678+ test->ninja));
1679+ g_assert (tp_intset_is_member (
1680+ tp_channel_group_get_local_pending (test->publish),
1681+ test->ninja));
1682+
1683+ g_assert_cmpuint (test->log->len, ==, 3);
1684+ test_assert_one_contact_changed (test, 0, test->ninja,
1685+ TP_SUBSCRIPTION_STATE_ASK, TP_SUBSCRIPTION_STATE_NO, "");
1686+ test_assert_one_contact_changed (test, 1, test->ninja,
1687+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_NO, "");
1688+ test_assert_one_contact_changed (test, 2, test->ninja,
1689+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1690+ "May I see your presence, please?");
1691+ test_assert_contact_state (test, test->ninja,
1692+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_ASK,
1693+ "May I see your presence, please?", NULL);
1694+}
1695+
1696+static void
1697+test_reject_subscribe_request (Test *test,
1698+ gconstpointer mode)
1699+{
1700+ GError *error = NULL;
1701+
1702+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1703+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1704+
1705+ g_assert_cmpuint (
1706+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1707+ ==, 4);
1708+ g_assert (!tp_intset_is_member (
1709+ tp_channel_group_get_members (test->subscribe),
1710+ test->ninja));
1711+ g_assert (!tp_intset_is_member (
1712+ tp_channel_group_get_remote_pending (test->subscribe),
1713+ test->ninja));
1714+
1715+ /* the example CM's fake contacts reject requests that don't contain
1716+ * "please" */
1717+ g_array_append_val (test->arr, test->ninja);
1718+
1719+ if (!tp_strdiff (mode, "old"))
1720+ tp_cli_channel_interface_group_run_add_members (test->subscribe,
1721+ -1, test->arr, "I demand to see your presence?", &error, NULL);
1722+ else
1723+ tp_cli_connection_interface_contact_list_run_request_subscription (
1724+ test->conn, -1, test->arr, "I demand to see your presence?",
1725+ &error, NULL);
1726+
1727+ g_assert_no_error (error);
1728+
1729+ /* by the time the method returns, we should have had the
1730+ * change-notification, too */
1731+ g_assert (tp_intset_is_member (
1732+ tp_channel_group_get_remote_pending (test->subscribe),
1733+ test->ninja));
1734+ g_assert (tp_intset_is_member (
1735+ tp_channel_group_get_members (test->stored),
1736+ test->ninja));
1737+ g_assert (!tp_intset_is_member (
1738+ tp_channel_group_get_remote_pending (test->stored),
1739+ test->ninja));
1740+
1741+ /* after a short delay, the contact rejects our request. Say please! */
1742+ while (tp_intset_is_member (
1743+ tp_channel_group_get_remote_pending (test->subscribe),
1744+ test->ninja) ||
1745+ test->log->len < 2)
1746+ g_main_context_iteration (NULL, TRUE);
1747+
1748+ g_assert (!tp_intset_is_member (
1749+ tp_channel_group_get_members (test->subscribe),
1750+ test->ninja));
1751+ g_assert (!tp_intset_is_member (
1752+ tp_channel_group_get_remote_pending (test->subscribe),
1753+ test->ninja));
1754+
1755+ /* the ninja is still on the stored list */
1756+ g_assert (tp_intset_is_member (
1757+ tp_channel_group_get_members (test->stored),
1758+ test->ninja));
1759+ g_assert (!tp_intset_is_member (
1760+ tp_channel_group_get_remote_pending (test->stored),
1761+ test->ninja));
1762+
1763+ g_assert_cmpuint (test->log->len, ==, 2);
1764+ test_assert_one_contact_changed (test, 0, test->ninja,
1765+ TP_SUBSCRIPTION_STATE_ASK, TP_SUBSCRIPTION_STATE_NO, "");
1766+ test_assert_one_contact_changed (test, 1, test->ninja,
1767+ TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY, TP_SUBSCRIPTION_STATE_NO, "");
1768+ test_assert_contact_state (test, test->ninja,
1769+ TP_SUBSCRIPTION_STATE_REMOVED_REMOTELY, TP_SUBSCRIPTION_STATE_NO, NULL,
1770+ NULL);
1771+
1772+ test_clear_log (test);
1773+
1774+ /* We can acknowledge the failure to subscribe with Unsubscribe() or
1775+ * RemoveContacts(). We can't use the old API here, because in the old API,
1776+ * the contact has already vanished from the Group */
1777+ if (!tp_strdiff (mode, "remove-after"))
1778+ tp_cli_connection_interface_contact_list_run_remove_contacts (test->conn,
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+ /* the ninja falls off our subscribe list */
1785+ while (test->log->len < 1)
1786+ g_main_context_iteration (NULL, TRUE);
1787+
1788+ g_assert_cmpuint (test->log->len, ==, 1);
1789+
1790+ if (!tp_strdiff (mode, "remove-after"))
1791+ test_assert_one_contact_removed (test, 0, test->ninja);
1792+ else
1793+ test_assert_one_contact_changed (test, 0, test->ninja,
1794+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1795+}
1796+
1797+static void
1798+test_remove_from_subscribe (Test *test,
1799+ gconstpointer mode)
1800+{
1801+ GError *error = NULL;
1802+
1803+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1804+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1805+
1806+ g_assert_cmpuint (
1807+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1808+ ==, 4);
1809+ g_assert (tp_intset_is_member (
1810+ tp_channel_group_get_members (test->subscribe),
1811+ test->sjoerd));
1812+
1813+ g_array_append_val (test->arr, test->sjoerd);
1814+
1815+ if (!tp_strdiff (mode, "old"))
1816+ tp_cli_channel_interface_group_run_remove_members (test->subscribe,
1817+ -1, test->arr, "", &error, NULL);
1818+ else
1819+ tp_cli_connection_interface_contact_list_run_unsubscribe (
1820+ test->conn, -1, test->arr, &error, NULL);
1821+
1822+ g_assert_no_error (error);
1823+
1824+ /* by the time the method returns, we should have had the
1825+ * removal-notification, too */
1826+ g_assert (!tp_intset_is_member (
1827+ tp_channel_group_get_members (test->subscribe),
1828+ test->sjoerd));
1829+ g_assert (tp_intset_is_member (
1830+ tp_channel_group_get_members (test->stored),
1831+ test->sjoerd));
1832+
1833+ g_assert_cmpuint (test->log->len, ==, 1);
1834+ test_assert_one_contact_changed (test, 0, test->sjoerd,
1835+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_YES, "");
1836+ test_assert_contact_state (test, test->sjoerd,
1837+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_YES, NULL, "Cambridge");
1838+}
1839+
1840+static void
1841+test_remove_from_subscribe_pending (Test *test,
1842+ gconstpointer mode)
1843+{
1844+ GError *error = NULL;
1845+
1846+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1847+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1848+
1849+ g_assert_cmpuint (
1850+ tp_intset_size (tp_channel_group_get_remote_pending (test->subscribe)),
1851+ ==, 2);
1852+ g_assert (tp_intset_is_member (
1853+ tp_channel_group_get_remote_pending (test->subscribe),
1854+ test->helen));
1855+
1856+ g_array_append_val (test->arr, test->helen);
1857+
1858+ if (!tp_strdiff (mode, "old"))
1859+ tp_cli_channel_interface_group_run_remove_members (test->subscribe,
1860+ -1, test->arr, "", &error, NULL);
1861+ else
1862+ tp_cli_connection_interface_contact_list_run_unsubscribe (
1863+ test->conn, -1, test->arr, &error, NULL);
1864+
1865+ g_assert_no_error (error);
1866+
1867+ /* by the time the method returns, we should have had the
1868+ * removal-notification, too */
1869+ g_assert (!tp_intset_is_member (
1870+ tp_channel_group_get_members (test->subscribe),
1871+ test->helen));
1872+ g_assert (!tp_intset_is_member (
1873+ tp_channel_group_get_remote_pending (test->subscribe),
1874+ test->helen));
1875+ g_assert (tp_intset_is_member (
1876+ tp_channel_group_get_members (test->stored),
1877+ test->helen));
1878+
1879+ g_assert_cmpuint (test->log->len, ==, 1);
1880+ test_assert_one_contact_changed (test, 0, test->helen,
1881+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1882+ test_assert_contact_state (test, test->helen,
1883+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, "Cambridge");
1884+}
1885+
1886+static void
1887+test_remove_from_subscribe_no_op (Test *test,
1888+ gconstpointer mode)
1889+{
1890+ GError *error = NULL;
1891+
1892+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "subscribe");
1893+
1894+ g_assert_cmpuint (
1895+ tp_intset_size (tp_channel_group_get_members (test->subscribe)),
1896+ ==, 4);
1897+ g_assert (!tp_intset_is_member (
1898+ tp_channel_group_get_members (test->subscribe),
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_remove_members (test->subscribe,
1905+ -1, test->arr, "", &error, NULL);
1906+ else
1907+ tp_cli_connection_interface_contact_list_run_unsubscribe (
1908+ test->conn, -1, test->arr, &error, NULL);
1909+
1910+ g_assert_no_error (error);
1911+
1912+ g_assert_cmpuint (test->log->len, ==, 0);
1913+ test_assert_contact_state (test, test->ninja,
1914+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
1915+}
1916+
1917+static void
1918+test_add_to_group (Test *test,
1919+ gconstpointer mode)
1920+{
1921+ GError *error = NULL;
1922+ LogEntry *le;
1923+ guint i;
1924+
1925+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
1926+ "Cambridge");
1927+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
1928+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
1929+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST,
1930+ "subscribe");
1931+
1932+ g_assert_cmpuint (
1933+ tp_intset_size (tp_channel_group_get_members (test->group)),
1934+ ==, 4);
1935+ g_assert (!tp_intset_is_member (
1936+ tp_channel_group_get_members (test->group),
1937+ test->ninja));
1938+
1939+ g_array_append_val (test->arr, test->ninja);
1940+
1941+ if (!tp_strdiff (mode, "old"))
1942+ tp_cli_channel_interface_group_run_add_members (test->group,
1943+ -1, test->arr, "", &error, NULL);
1944+ else
1945+ tp_cli_connection_interface_contact_groups_run_add_to_group (test->conn,
1946+ -1, "Cambridge", test->arr, &error, NULL);
1947+
1948+ g_assert_no_error (error);
1949+
1950+ /* by the time the method returns, we should have had the
1951+ * change-notification, too */
1952+ g_assert_cmpuint (
1953+ tp_intset_size (tp_channel_group_get_members (test->group)),
1954+ ==, 5);
1955+ g_assert (tp_intset_is_member (
1956+ tp_channel_group_get_members (test->group),
1957+ test->ninja));
1958+
1959+ g_assert (tp_intset_is_member (
1960+ tp_channel_group_get_members (test->stored),
1961+ test->ninja));
1962+ g_assert (!tp_intset_is_member (
1963+ tp_channel_group_get_members (test->subscribe),
1964+ test->ninja));
1965+ g_assert (!tp_intset_is_member (
1966+ tp_channel_group_get_members (test->publish),
1967+ test->ninja));
1968+
1969+ g_assert_cmpuint (test->log->len, ==, 2);
1970+
1971+ le = g_ptr_array_index (test->log, 0);
1972+
1973+ if (le->type == CONTACTS_CHANGED)
1974+ {
1975+ test_assert_one_contact_changed (test, 0, test->ninja,
1976+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1977+ i = 1;
1978+ }
1979+ else
1980+ {
1981+ test_assert_one_contact_changed (test, 1, test->ninja,
1982+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, "");
1983+ i = 0;
1984+ }
1985+
1986+ /* either way, the i'th entry is now the GroupsChanged signal */
1987+ test_assert_one_group_joined (test, i, test->ninja, "Cambridge");
1988+
1989+ test_assert_contact_state (test, test->ninja,
1990+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, "Cambridge");
1991+}
1992+
1993+static void
1994+test_add_to_group_no_op (Test *test,
1995+ gconstpointer mode)
1996+{
1997+ GError *error = NULL;
1998+
1999+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2000+ "Cambridge");
2001+
2002+ g_assert (tp_intset_is_member (
2003+ tp_channel_group_get_members (test->group),
2004+ test->sjoerd));
2005+
2006+ g_array_append_val (test->arr, test->sjoerd);
2007+
2008+ if (!tp_strdiff (mode, "old"))
2009+ tp_cli_channel_interface_group_run_add_members (test->group,
2010+ -1, test->arr, "", &error, NULL);
2011+ else
2012+ tp_cli_connection_interface_contact_groups_run_add_to_group (test->conn,
2013+ -1, "Cambridge", test->arr, &error, NULL);
2014+
2015+ g_assert_no_error (error);
2016+
2017+ g_assert_cmpuint (test->log->len, ==, 0);
2018+ test_assert_contact_state (test, test->sjoerd,
2019+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, "Cambridge");
2020+}
2021+
2022+static void
2023+test_remove_from_group (Test *test,
2024+ gconstpointer mode)
2025+{
2026+ GError *error = NULL;
2027+
2028+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2029+ "Cambridge");
2030+
2031+ g_assert (tp_intset_is_member (
2032+ tp_channel_group_get_members (test->group),
2033+ test->sjoerd));
2034+
2035+ g_array_append_val (test->arr, test->sjoerd);
2036+
2037+ if (!tp_strdiff (mode, "old"))
2038+ tp_cli_channel_interface_group_run_remove_members (test->group,
2039+ -1, test->arr, "", &error, NULL);
2040+ else
2041+ tp_cli_connection_interface_contact_groups_run_remove_from_group (
2042+ test->conn, -1, "Cambridge", test->arr, &error, NULL);
2043+
2044+ g_assert_no_error (error);
2045+
2046+ /* by the time the method returns, we should have had the
2047+ * removal-notification, too */
2048+ g_assert (!tp_intset_is_member (
2049+ tp_channel_group_get_members (test->group),
2050+ test->sjoerd));
2051+
2052+ g_assert_cmpuint (test->log->len, ==, 1);
2053+ test_assert_one_group_left (test, 0, test->sjoerd, "Cambridge");
2054+ test_assert_contact_state (test, test->sjoerd,
2055+ TP_SUBSCRIPTION_STATE_YES, TP_SUBSCRIPTION_STATE_YES, NULL, NULL);
2056+}
2057+
2058+static void
2059+test_remove_from_group_no_op (Test *test,
2060+ gconstpointer mode)
2061+{
2062+ GError *error = NULL;
2063+
2064+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2065+ "Cambridge");
2066+
2067+ g_assert (!tp_intset_is_member (
2068+ tp_channel_group_get_members (test->group),
2069+ test->ninja));
2070+
2071+ g_array_append_val (test->arr, test->ninja);
2072+
2073+ if (!tp_strdiff (mode, "old"))
2074+ tp_cli_channel_interface_group_run_remove_members (test->group,
2075+ -1, test->arr, "", &error, NULL);
2076+ else
2077+ tp_cli_connection_interface_contact_groups_run_remove_from_group (
2078+ test->conn, -1, "Cambridge", test->arr, &error, NULL);
2079+
2080+ g_assert_no_error (error);
2081+
2082+ g_assert_cmpuint (test->log->len, ==, 0);
2083+ test_assert_contact_state (test, test->ninja,
2084+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2085+}
2086+
2087+static void
2088+test_remove_group (Test *test,
2089+ gconstpointer mode)
2090+{
2091+ GError *error = NULL;
2092+
2093+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2094+ "Cambridge");
2095+
2096+ g_assert (!tp_intset_is_empty (
2097+ tp_channel_group_get_members (test->group)));
2098+
2099+ if (!tp_strdiff (mode, "old"))
2100+ {
2101+ /* The old API can't remove non-empty groups... */
2102+ tp_cli_channel_run_close (test->group, -1, &error, NULL);
2103+ g_assert_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE);
2104+
2105+ g_assert_cmpuint (test->log->len, ==, 0);
2106+ }
2107+ else
2108+ {
2109+ /* ... but the new API can */
2110+ LogEntry *le;
2111+
2112+ tp_cli_connection_interface_contact_groups_run_remove_group (test->conn,
2113+ -1, "Cambridge", &error, NULL);
2114+ g_assert_no_error (error);
2115+
2116+ g_assert (tp_proxy_get_invalidated (test->group) != NULL);
2117+ g_assert_cmpuint (test->log->len, ==, 2);
2118+ test_assert_one_group_removed (test, 0, "Cambridge");
2119+
2120+ le = g_ptr_array_index (test->log, 1);
2121+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
2122+ g_assert_cmpuint (le->contacts->len, ==, 4);
2123+ g_assert (le->groups_added == NULL || le->groups_added[0] == NULL);
2124+ g_assert (le->groups_removed != NULL);
2125+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2126+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2127+ }
2128+}
2129+
2130+static void
2131+test_remove_group_empty (Test *test,
2132+ gconstpointer mode)
2133+{
2134+ GError *error = NULL;
2135+
2136+ g_assert_cmpuint (test->log->len, ==, 0);
2137+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2138+ "people who understand const in C");
2139+
2140+ g_assert_cmpuint (test->log->len, ==, 1);
2141+ test_assert_one_group_created (test, 0, "people who understand const in C");
2142+
2143+ g_assert (tp_intset_is_empty (
2144+ tp_channel_group_get_members (test->group)));
2145+
2146+ tp_cli_channel_run_close (test->group, -1, &error, NULL);
2147+ g_assert_no_error (error);
2148+
2149+ g_assert_cmpuint (test->log->len, ==, 2);
2150+ test_assert_one_group_removed (test, 1, "people who understand const in C");
2151+}
2152+
2153+static void
2154+test_set_contact_groups (Test *test,
2155+ gconstpointer nil G_GNUC_UNUSED)
2156+{
2157+ GError *error = NULL;
2158+ LogEntry *le;
2159+ const gchar *montreal_strv[] = { "Montreal", NULL };
2160+
2161+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2162+ "Cambridge");
2163+
2164+ g_assert_cmpuint (
2165+ tp_intset_size (tp_channel_group_get_members (test->group)),
2166+ ==, 4);
2167+ g_assert (tp_intset_is_member (
2168+ tp_channel_group_get_members (test->group),
2169+ test->sjoerd));
2170+
2171+ g_array_append_val (test->arr, test->sjoerd);
2172+ g_array_append_val (test->arr, test->wim);
2173+
2174+ tp_cli_connection_interface_contact_groups_run_set_contact_groups (
2175+ test->conn, -1, test->sjoerd, montreal_strv, &error, NULL);
2176+
2177+ g_assert_no_error (error);
2178+
2179+ /* by the time the method returns, we should have had the
2180+ * change-notification, too */
2181+ g_assert_cmpuint (
2182+ tp_intset_size (tp_channel_group_get_members (test->group)),
2183+ ==, 3);
2184+ g_assert (!tp_intset_is_member (
2185+ tp_channel_group_get_members (test->group),
2186+ test->sjoerd));
2187+
2188+ g_assert_cmpuint (test->log->len, ==, 1);
2189+
2190+ le = g_ptr_array_index (test->log, 0);
2191+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
2192+ g_assert_cmpuint (le->contacts->len, ==, 1);
2193+ g_assert_cmpuint (g_array_index (le->contacts, guint, 0), ==, test->sjoerd);
2194+ g_assert (le->groups_added != NULL);
2195+ g_assert_cmpstr (le->groups_added[0], ==, "Montreal");
2196+ g_assert_cmpstr (le->groups_added[1], ==, NULL);
2197+ g_assert (le->groups_removed != NULL);
2198+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2199+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2200+}
2201+
2202+static void
2203+test_set_contact_groups_no_op (Test *test,
2204+ gconstpointer nil G_GNUC_UNUSED)
2205+{
2206+ GError *error = NULL;
2207+ const gchar *cambridge_strv[] = { "Cambridge", NULL };
2208+
2209+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2210+ "Cambridge");
2211+
2212+ g_assert_cmpuint (
2213+ tp_intset_size (tp_channel_group_get_members (test->group)),
2214+ ==, 4);
2215+ g_assert (tp_intset_is_member (
2216+ tp_channel_group_get_members (test->group),
2217+ test->sjoerd));
2218+
2219+ g_array_append_val (test->arr, test->sjoerd);
2220+ g_array_append_val (test->arr, test->wim);
2221+
2222+ tp_cli_connection_interface_contact_groups_run_set_contact_groups (
2223+ test->conn, -1, test->sjoerd, cambridge_strv, &error, NULL);
2224+
2225+ g_assert_no_error (error);
2226+
2227+ g_assert_cmpuint (
2228+ tp_intset_size (tp_channel_group_get_members (test->group)),
2229+ ==, 4);
2230+ g_assert (tp_intset_is_member (
2231+ tp_channel_group_get_members (test->group),
2232+ test->sjoerd));
2233+
2234+ g_assert_cmpuint (test->log->len, ==, 0);
2235+}
2236+
2237+static void
2238+test_set_group_members (Test *test,
2239+ gconstpointer nil G_GNUC_UNUSED)
2240+{
2241+ GError *error = NULL;
2242+ LogEntry *le;
2243+
2244+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2245+ "Cambridge");
2246+
2247+ g_assert_cmpuint (
2248+ tp_intset_size (tp_channel_group_get_members (test->group)),
2249+ ==, 4);
2250+ g_assert (tp_intset_is_member (
2251+ tp_channel_group_get_members (test->group),
2252+ test->sjoerd));
2253+ g_assert (tp_intset_is_member (
2254+ tp_channel_group_get_members (test->group),
2255+ test->helen));
2256+ g_assert (!tp_intset_is_member (
2257+ tp_channel_group_get_members (test->group),
2258+ test->wim));
2259+
2260+ g_array_append_val (test->arr, test->sjoerd);
2261+ g_array_append_val (test->arr, test->wim);
2262+
2263+ tp_cli_connection_interface_contact_groups_run_set_group_members (test->conn,
2264+ -1, "Cambridge", test->arr, &error, NULL);
2265+
2266+ g_assert_no_error (error);
2267+
2268+ /* by the time the method returns, we should have had the
2269+ * change-notification, too */
2270+ g_assert_cmpuint (
2271+ tp_intset_size (tp_channel_group_get_members (test->group)),
2272+ ==, 2);
2273+ g_assert (tp_intset_is_member (
2274+ tp_channel_group_get_members (test->group),
2275+ test->wim));
2276+ g_assert (tp_intset_is_member (
2277+ tp_channel_group_get_members (test->group),
2278+ test->sjoerd));
2279+ g_assert (!tp_intset_is_member (
2280+ tp_channel_group_get_members (test->group),
2281+ test->helen));
2282+
2283+ g_assert_cmpuint (test->log->len, ==, 2);
2284+
2285+ /* Wim was added */
2286+ test_assert_one_group_joined (test, 0, test->wim, "Cambridge");
2287+
2288+ /* The three other members, other than Sjoerd, left */
2289+ le = g_ptr_array_index (test->log, 1);
2290+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
2291+ g_assert_cmpuint (le->contacts->len, ==, 3);
2292+ g_assert (le->groups_added == NULL || le->groups_added[0] == NULL);
2293+ g_assert (le->groups_removed != NULL);
2294+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2295+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2296+}
2297+
2298+static void
2299+test_rename_group (Test *test,
2300+ gconstpointer nil G_GNUC_UNUSED)
2301+{
2302+ LogEntry *le;
2303+ GError *error = NULL;
2304+
2305+ test->group = test_ensure_channel (test, TP_HANDLE_TYPE_GROUP,
2306+ "Cambridge");
2307+
2308+ g_assert_cmpuint (
2309+ tp_intset_size (tp_channel_group_get_members (test->group)),
2310+ ==, 4);
2311+
2312+ tp_cli_connection_interface_contact_groups_run_rename_group (test->conn,
2313+ -1, "Cambridge", "Grantabrugge", &error, NULL);
2314+ g_assert_no_error (error);
2315+
2316+ g_assert (tp_proxy_get_invalidated (test->group) != NULL);
2317+ g_assert_cmpuint (test->log->len, ==, 4);
2318+
2319+ le = g_ptr_array_index (test->log, 0);
2320+ g_assert_cmpint (le->type, ==, GROUP_RENAMED);
2321+ g_assert (le->groups_added != NULL);
2322+ g_assert_cmpstr (le->groups_added[0], ==, "Grantabrugge");
2323+ g_assert_cmpstr (le->groups_added[1], ==, NULL);
2324+ g_assert (le->groups_removed != NULL);
2325+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2326+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2327+
2328+ test_assert_one_group_created (test, 1, "Grantabrugge");
2329+
2330+ test_assert_one_group_removed (test, 2, "Cambridge");
2331+
2332+ le = g_ptr_array_index (test->log, 3);
2333+ g_assert_cmpint (le->type, ==, GROUPS_CHANGED);
2334+ g_assert_cmpuint (le->contacts->len, ==, 4);
2335+ g_assert (le->groups_added != NULL);
2336+ g_assert_cmpstr (le->groups_added[0], ==, "Grantabrugge");
2337+ g_assert_cmpstr (le->groups_added[1], ==, NULL);
2338+ g_assert_cmpstr (le->groups_removed[0], ==, "Cambridge");
2339+ g_assert_cmpstr (le->groups_removed[1], ==, NULL);
2340+}
2341+
2342+static void
2343+test_rename_group_overwrite (Test *test,
2344+ gconstpointer nil G_GNUC_UNUSED)
2345+{
2346+ GError *error = NULL;
2347+
2348+ tp_cli_connection_interface_contact_groups_run_rename_group (test->conn,
2349+ -1, "Cambridge", "Montreal", &error, NULL);
2350+ g_assert_error (error, TP_ERRORS, TP_ERROR_NOT_AVAILABLE);
2351+ g_assert_cmpuint (test->log->len, ==, 0);
2352+ g_clear_error (&error);
2353+}
2354+
2355+static void
2356+test_rename_group_absent (Test *test,
2357+ gconstpointer nil G_GNUC_UNUSED)
2358+{
2359+ GError *error = NULL;
2360+
2361+ tp_cli_connection_interface_contact_groups_run_rename_group (test->conn,
2362+ -1, "Badgers", "Mushrooms", &error, NULL);
2363+ g_assert_error (error, TP_ERRORS, TP_ERROR_DOES_NOT_EXIST);
2364+ g_assert_cmpuint (test->log->len, ==, 0);
2365+ g_clear_error (&error);
2366+}
2367+
2368+/* Signature of a function which does something with test->arr */
2369+typedef void (*ManipulateContactsFunc) (
2370+ Test *test,
2371+ GError **error);
2372+
2373+static void
2374+block_contacts (Test *test,
2375+ ManipulateContactsFunc func)
2376+{
2377+ GError *error = NULL;
2378+
2379+ test->deny = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "deny");
2380+ test->stored = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "stored");
2381+
2382+ g_assert_cmpuint (
2383+ tp_intset_size (tp_channel_group_get_members (test->deny)),
2384+ ==, 2);
2385+ g_assert (!tp_intset_is_member (
2386+ tp_channel_group_get_members (test->deny),
2387+ test->ninja));
2388+
2389+ g_array_append_val (test->arr, test->ninja);
2390+ func (test, &error);
2391+ g_assert_no_error (error);
2392+
2393+ /* by the time the method returns, we should have had the
2394+ * change-notification, on both the deny channel and the ContactBlocking
2395+ * connection interface */
2396+ g_assert_cmpuint (
2397+ tp_intset_size (tp_channel_group_get_members (test->deny)),
2398+ ==, 3);
2399+ g_assert (tp_intset_is_member (
2400+ tp_channel_group_get_members (test->deny),
2401+ test->ninja));
2402+
2403+ g_assert (!tp_intset_is_member (
2404+ tp_channel_group_get_members (test->stored),
2405+ test->ninja));
2406+ test_assert_contact_state (test, test->ninja,
2407+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2408+
2409+ g_assert_cmpuint (test->log->len, ==, 1);
2410+ test_assert_one_contact_blocked (test, 0, test->ninja,
2411+ tp_handle_inspect (test->contact_repo, test->ninja));
2412+}
2413+
2414+static void
2415+block_contacts_no_op (Test *test,
2416+ ManipulateContactsFunc func)
2417+{
2418+ GError *error = NULL;
2419+
2420+ test->deny = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "deny");
2421+
2422+ g_assert (tp_intset_is_member (
2423+ tp_channel_group_get_members (test->deny),
2424+ test->bill));
2425+
2426+ g_array_append_val (test->arr, test->bill);
2427+ func (test, &error);
2428+ g_assert_no_error (error);
2429+
2430+ g_assert (tp_intset_is_member (
2431+ tp_channel_group_get_members (test->deny),
2432+ test->bill));
2433+ test_assert_contact_state (test, test->bill,
2434+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2435+
2436+ /* We shouldn't emit spurious empty BlockedContactsChanged signals. */
2437+ g_assert_cmpuint (test->log->len, ==, 0);
2438+}
2439+
2440+static void
2441+unblock_contacts (Test *test,
2442+ ManipulateContactsFunc func)
2443+{
2444+ GError *error = NULL;
2445+
2446+ test->deny = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "deny");
2447+ test->publish = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "publish");
2448+ test->subscribe = test_ensure_channel (test, TP_HANDLE_TYPE_LIST,
2449+ "subscribe");
2450+
2451+ g_assert (tp_intset_is_member (
2452+ tp_channel_group_get_members (test->deny),
2453+ test->bill));
2454+
2455+ g_array_append_val (test->arr, test->bill);
2456+ func (test, &error);
2457+ g_assert_no_error (error);
2458+
2459+ /* by the time the method returns, we should have had the
2460+ * removal-notification, too */
2461+ g_assert (!tp_intset_is_member (
2462+ tp_channel_group_get_members (test->deny),
2463+ test->bill));
2464+ test_assert_contact_state (test, test->bill,
2465+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2466+
2467+ g_assert_cmpuint (test->log->len, ==, 1);
2468+ test_assert_one_contact_unblocked (test, 0, test->bill,
2469+ tp_handle_inspect (test->contact_repo, test->bill));
2470+}
2471+
2472+static void
2473+unblock_contacts_no_op (Test *test,
2474+ ManipulateContactsFunc func)
2475+{
2476+ GError *error = NULL;
2477+
2478+ test->deny = test_ensure_channel (test, TP_HANDLE_TYPE_LIST, "deny");
2479+
2480+ g_assert (!tp_intset_is_member (
2481+ tp_channel_group_get_members (test->deny),
2482+ test->ninja));
2483+
2484+ g_array_append_val (test->arr, test->ninja);
2485+ func (test, &error);
2486+ g_assert_no_error (error);
2487+ g_assert (!tp_intset_is_member (
2488+ tp_channel_group_get_members (test->deny),
2489+ test->ninja));
2490+ test_assert_contact_state (test, test->ninja,
2491+ TP_SUBSCRIPTION_STATE_NO, TP_SUBSCRIPTION_STATE_NO, NULL, NULL);
2492+
2493+ /* We shouldn't emit spurious empty BlockedContactsChanged signals. */
2494+ g_assert_cmpuint (test->log->len, ==, 0);
2495+}
2496+
2497+static void
2498+add_to_deny (Test *test,
2499+ GError **error)
2500+{
2501+ tp_cli_channel_interface_group_run_add_members (test->deny,
2502+ -1, test->arr, "", error, NULL);
2503+}
2504+
2505+static void
2506+test_add_to_deny (Test *test,
2507+ gconstpointer nil G_GNUC_UNUSED)
2508+{
2509+ block_contacts (test, add_to_deny);
2510+}
2511+
2512+static void
2513+test_add_to_deny_no_op (Test *test,
2514+ gconstpointer nil G_GNUC_UNUSED)
2515+{
2516+ block_contacts_no_op (test, add_to_deny);
2517+}
2518+
2519+static void
2520+remove_from_deny (Test *test,
2521+ GError **error)
2522+{
2523+ tp_cli_channel_interface_group_run_remove_members (test->deny,
2524+ -1, test->arr, "", error, NULL);
2525+}
2526+
2527+static void
2528+test_remove_from_deny (Test *test,
2529+ gconstpointer nil G_GNUC_UNUSED)
2530+{
2531+ unblock_contacts (test, remove_from_deny);
2532+}
2533+
2534+static void
2535+test_remove_from_deny_no_op (Test *test,
2536+ gconstpointer nil G_GNUC_UNUSED)
2537+{
2538+ unblock_contacts_no_op (test, remove_from_deny);
2539+}
2540+
2541+static void
2542+test_request_blocked_contacts (Test *test,
2543+ gconstpointer nil G_GNUC_UNUSED)
2544+{
2545+ GHashTable *blocked_contacts;
2546+ GError *error = NULL;
2547+
2548+ tp_cli_connection_interface_contact_blocking_run_request_blocked_contacts (
2549+ test->conn, -1, &blocked_contacts, &error, NULL);
2550+ g_assert_no_error (error);
2551+ g_assert (blocked_contacts != NULL);
2552+
2553+ /* Both Bill and the shadowy Steve are blocked; Steve does not appear in this
2554+ * test, as he is in poor health.
2555+ */
2556+ g_assert_cmpuint (g_hash_table_size (blocked_contacts), ==, 2);
2557+ g_assert_cmpstr (tp_handle_inspect (test->contact_repo, test->bill), ==,
2558+ g_hash_table_lookup (blocked_contacts, GUINT_TO_POINTER (test->bill)));
2559+ g_hash_table_unref (blocked_contacts);
2560+}
2561+
2562+static void
2563+request_blocked_contacts_succeeded_cb (
2564+ TpConnection *conn,
2565+ GHashTable *blocked_contacts,
2566+ const GError *error,
2567+ gpointer user_data,
2568+ GObject *weak_object)
2569+{
2570+ g_assert_no_error (error);
2571+
2572+ /* As above. */
2573+ g_assert_cmpuint (g_hash_table_size (blocked_contacts), ==, 2);
2574+}
2575+
2576+static void
2577+test_request_blocked_contacts_pre_connect (Test *test,
2578+ gconstpointer nil G_GNUC_UNUSED)
2579+{
2580+ gboolean ok;
2581+
2582+ /* This verifies that calling RequestBlockedContacts()
2583+ * before Connect(), when Connect() ultimately succeeds, returns correctly.
2584+ */
2585+ tp_cli_connection_interface_contact_blocking_call_request_blocked_contacts (
2586+ test->conn, -1, request_blocked_contacts_succeeded_cb,
2587+ test, test_quit_loop, NULL);
2588+ tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL);
2589+ g_main_loop_run (test->main_loop);
2590+
2591+ ok = tp_cli_connection_run_disconnect (test->conn, -1, NULL, NULL);
2592+ g_assert (ok);
2593+}
2594+
2595+static void
2596+request_blocked_contacts_failed_cb (
2597+ TpConnection *conn,
2598+ GHashTable *blocked_contacts,
2599+ const GError *error,
2600+ gpointer user_data,
2601+ GObject *weak_object)
2602+{
2603+ g_assert_error (error, TP_ERRORS, TP_ERROR_DISCONNECTED);
2604+}
2605+
2606+static void
2607+test_request_blocked_contacts_connect_failed (Test *test,
2608+ gconstpointer nil G_GNUC_UNUSED)
2609+{
2610+ /* This verifies that calling RequestBlockedContacts() (twice, no less)
2611+ * before Connect(), when Connect() ultimately fails, returns an appropriate
2612+ * error.
2613+ */
2614+ tp_cli_connection_interface_contact_blocking_call_request_blocked_contacts (
2615+ test->conn, -1, request_blocked_contacts_failed_cb,
2616+ test, test_quit_loop, NULL);
2617+ tp_cli_connection_interface_contact_blocking_call_request_blocked_contacts (
2618+ test->conn, -1, request_blocked_contacts_failed_cb,
2619+ test, test_quit_loop, NULL);
2620+
2621+ /* We expect calling Connect() to fail because the handle was invalid, but
2622+ * don't wait around for it.
2623+ */
2624+ tp_cli_connection_call_connect (test->conn, -1, NULL, NULL, NULL, NULL);
2625+ /* Spin the mainloop twice, once for each outstanding call. */
2626+ g_main_loop_run (test->main_loop);
2627+ g_main_loop_run (test->main_loop);
2628+}
2629+
2630+static void
2631+call_block_contacts (Test *test,
2632+ GError **error)
2633+{
2634+ tp_cli_connection_interface_contact_blocking_run_block_contacts (test->conn,
2635+ -1, test->arr, FALSE, error, NULL);
2636+}
2637+
2638+static void
2639+test_block_contacts (Test *test,
2640+ gconstpointer nil G_GNUC_UNUSED)
2641+{
2642+ block_contacts (test, call_block_contacts);
2643+}
2644+
2645+static void
2646+test_block_contacts_no_op (Test *test,
2647+ gconstpointer nil G_GNUC_UNUSED)
2648+{
2649+ block_contacts_no_op (test, call_block_contacts);
2650+}
2651+
2652+static void
2653+call_unblock_contacts (Test *test,
2654+ GError **error)
2655+{
2656+ tp_cli_connection_interface_contact_blocking_run_unblock_contacts (
2657+ test->conn, -1, test->arr, error, NULL);
2658+}
2659+
2660+static void
2661+test_unblock_contacts (Test *test,
2662+ gconstpointer nil G_GNUC_UNUSED)
2663+{
2664+ unblock_contacts (test, call_unblock_contacts);
2665+}
2666+
2667+static void
2668+test_unblock_contacts_no_op (Test *test,
2669+ gconstpointer nil G_GNUC_UNUSED)
2670+{
2671+ unblock_contacts_no_op (test, call_unblock_contacts);
2672+}
2673+
2674+int
2675+main (int argc,
2676+ char **argv)
2677+{
2678+ g_type_init ();
2679+ tp_tests_abort_after (30);
2680+ tp_debug_set_flags ("all");
2681+
2682+ g_test_init (&argc, &argv, NULL);
2683+
2684+ g_test_add ("/contact-lists/nothing",
2685+ Test, NULL, setup, test_nothing, teardown);
2686+
2687+ g_test_add ("/contact-lists/initial-channels",
2688+ Test, NULL, setup, test_initial_channels, teardown);
2689+ g_test_add ("/contact-lists/properties",
2690+ Test, NULL, setup, test_properties, teardown);
2691+ g_test_add ("/contact-lists/contacts",
2692+ Test, NULL, setup, test_contacts, teardown);
2693+ g_test_add ("/contact-lists/contact-list-attrs",
2694+ Test, NULL, setup, test_contact_list_attrs, teardown);
2695+ g_test_add ("/contact-lists/contact-blocking-attrs",
2696+ Test, NULL, setup, test_contact_blocking_attrs, teardown);
2697+
2698+ g_test_add ("/contact-lists/accept-publish-request",
2699+ Test, NULL, setup, test_accept_publish_request, teardown);
2700+ g_test_add ("/contact-lists/reject-publish-request",
2701+ Test, NULL, setup, test_reject_publish_request, teardown);
2702+ g_test_add ("/contact-lists/reject-publish-request/unpublish",
2703+ Test, "unpublish", setup, test_reject_publish_request, teardown);
2704+ g_test_add ("/contact-lists/add-to-publish/pre-approve",
2705+ Test, NULL, setup, test_add_to_publish_pre_approve, teardown);
2706+ g_test_add ("/contact-lists/add-to-publish/no-op",
2707+ Test, NULL, setup, test_add_to_publish_no_op, teardown);
2708+ g_test_add ("/contact-lists/remove-from-publish",
2709+ Test, NULL, setup, test_remove_from_publish, teardown);
2710+ g_test_add ("/contact-lists/remove-from-publish/no-op",
2711+ Test, NULL, setup, test_remove_from_publish_no_op, teardown);
2712+
2713+ g_test_add ("/contact-lists/accept-publish-request/old",
2714+ Test, "old", setup, test_accept_publish_request, teardown);
2715+ g_test_add ("/contact-lists/reject-publish-request/old",
2716+ Test, "old", setup, test_reject_publish_request, teardown);
2717+ g_test_add ("/contact-lists/add-to-publish/pre-approve/old",
2718+ Test, "old", setup, test_add_to_publish_pre_approve, teardown);
2719+ g_test_add ("/contact-lists/add-to-publish/no-op/old",
2720+ Test, "old", setup, test_add_to_publish_no_op, teardown);
2721+ g_test_add ("/contact-lists/remove-from-publish/old",
2722+ Test, "old", setup, test_remove_from_publish, teardown);
2723+ g_test_add ("/contact-lists/remove-from-publish/no-op/old",
2724+ Test, "old", setup, test_remove_from_publish_no_op, teardown);
2725+
2726+ g_test_add ("/contact-lists/cancelled-publish-request",
2727+ Test, NULL, setup, test_cancelled_publish_request, teardown);
2728+ g_test_add ("/contact-lists/cancelled-publish-request",
2729+ Test, "remove-after", setup, test_cancelled_publish_request, teardown);
2730+
2731+ g_test_add ("/contact-lists/add-to-stored",
2732+ Test, NULL, setup, test_add_to_stored, teardown);
2733+ g_test_add ("/contact-lists/add-to-stored/no-op",
2734+ Test, NULL, setup, test_add_to_stored_no_op, teardown);
2735+ g_test_add ("/contact-lists/remove-from-stored",
2736+ Test, NULL, setup, test_remove_from_stored, teardown);
2737+ g_test_add ("/contact-lists/remove-from-stored/no-op",
2738+ Test, NULL, setup, test_remove_from_stored_no_op, teardown);
2739+
2740+ g_test_add ("/contact-lists/add-to-stored/old",
2741+ Test, "old", setup, test_add_to_stored, teardown);
2742+ g_test_add ("/contact-lists/add-to-stored/no-op/old",
2743+ Test, "old", setup, test_add_to_stored_no_op, teardown);
2744+ g_test_add ("/contact-lists/remove-from-stored/old",
2745+ Test, "old", setup, test_remove_from_stored, teardown);
2746+ g_test_add ("/contact-lists/remove-from-stored/no-op/old",
2747+ Test, "old", setup, test_remove_from_stored_no_op, teardown);
2748+
2749+ g_test_add ("/contact-lists/accept-subscribe-request",
2750+ Test, NULL, setup, test_accept_subscribe_request, teardown);
2751+ g_test_add ("/contact-lists/reject-subscribe-request",
2752+ Test, NULL, setup, test_reject_subscribe_request, teardown);
2753+ g_test_add ("/contact-lists/remove-from-subscribe",
2754+ Test, NULL, setup, test_remove_from_subscribe, teardown);
2755+ g_test_add ("/contact-lists/remove-from-subscribe/pending",
2756+ Test, NULL, setup, test_remove_from_subscribe_pending, teardown);
2757+ g_test_add ("/contact-lists/remove-from-subscribe/no-op",
2758+ Test, NULL, setup, test_remove_from_subscribe_no_op, teardown);
2759+
2760+ g_test_add ("/contact-lists/accept-subscribe-request/old",
2761+ Test, "old", setup, test_accept_subscribe_request, teardown);
2762+ g_test_add ("/contact-lists/reject-subscribe-request/old",
2763+ Test, "old", setup, test_reject_subscribe_request, teardown);
2764+ g_test_add ("/contact-lists/remove-from-subscribe/old",
2765+ Test, "old", setup, test_remove_from_subscribe, teardown);
2766+ g_test_add ("/contact-lists/remove-from-subscribe/pending/old",
2767+ Test, "old", setup, test_remove_from_subscribe_pending, teardown);
2768+ g_test_add ("/contact-lists/remove-from-subscribe/no-op/old",
2769+ Test, "old", setup, test_remove_from_subscribe_no_op, teardown);
2770+
2771+ g_test_add ("/contact-lists/reject-subscribe-request/remove-after",
2772+ Test, "remove-after", setup, test_reject_subscribe_request, teardown);
2773+
2774+ g_test_add ("/contact-lists/add-to-group",
2775+ Test, NULL, setup, test_add_to_group, teardown);
2776+ g_test_add ("/contact-lists/add-to-group/no-op",
2777+ Test, NULL, setup, test_add_to_group_no_op, teardown);
2778+ g_test_add ("/contact-lists/remove-from-group",
2779+ Test, NULL, setup, test_remove_from_group, teardown);
2780+ g_test_add ("/contact-lists/remove-from-group/no-op",
2781+ Test, NULL, setup, test_remove_from_group_no_op, teardown);
2782+ g_test_add ("/contact-lists/remove-group",
2783+ Test, NULL, setup, test_remove_group, teardown);
2784+ g_test_add ("/contact-lists/remove-group/empty",
2785+ Test, NULL, setup, test_remove_group_empty, teardown);
2786+
2787+ g_test_add ("/contact-lists/add-to-group/old",
2788+ Test, "old", setup, test_add_to_group, teardown);
2789+ g_test_add ("/contact-lists/add-to-group/no-op/old",
2790+ Test, "old", setup, test_add_to_group_no_op, teardown);
2791+ g_test_add ("/contact-lists/remove-from-group/old",
2792+ Test, "old", setup, test_remove_from_group, teardown);
2793+ g_test_add ("/contact-lists/remove-from-group/no-op/old",
2794+ Test, "old", setup, test_remove_from_group_no_op, teardown);
2795+ g_test_add ("/contact-lists/remove-group/old",
2796+ Test, "old", setup, test_remove_group, teardown);
2797+ g_test_add ("/contact-lists/remove-group/empty/old",
2798+ Test, "old", setup, test_remove_group_empty, teardown);
2799+
2800+ g_test_add ("/contact-lists/set_contact_groups",
2801+ Test, NULL, setup, test_set_contact_groups, teardown);
2802+ g_test_add ("/contact-lists/set_contact_groups/no-op",
2803+ Test, NULL, setup, test_set_contact_groups_no_op, teardown);
2804+ g_test_add ("/contact-lists/set_group_members",
2805+ Test, NULL, setup, test_set_group_members, teardown);
2806+
2807+ g_test_add ("/contact-lists/rename_group",
2808+ Test, NULL, setup, test_rename_group, teardown);
2809+ g_test_add ("/contact-lists/rename_group/absent",
2810+ Test, NULL, setup, test_rename_group_absent, teardown);
2811+ g_test_add ("/contact-lists/rename_group/overwrite",
2812+ Test, NULL, setup, test_rename_group_overwrite, teardown);
2813+
2814+ g_test_add ("/contact-lists/add-to-deny",
2815+ Test, NULL, setup, test_add_to_deny, teardown);
2816+ g_test_add ("/contact-lists/add-to-deny/no-op",
2817+ Test, NULL, setup, test_add_to_deny_no_op, teardown);
2818+ g_test_add ("/contact-lists/remove-from-deny",
2819+ Test, NULL, setup, test_remove_from_deny, teardown);
2820+ g_test_add ("/contact-lists/remove-from-deny/no-op",
2821+ Test, NULL, setup, test_remove_from_deny_no_op, teardown);
2822+
2823+ g_test_add ("/contact-lists/request-blocked-contacts",
2824+ Test, NULL, setup, test_request_blocked_contacts, teardown);
2825+ g_test_add ("/contact-lists/request-blocked-contacts-before-connect",
2826+ Test, NULL, setup_pre_connect,
2827+ test_request_blocked_contacts_pre_connect, teardown_pre_connect);
2828+ g_test_add ("/contact-lists/request-blocked-contacts-connect-failed",
2829+ Test, "break-account-parameter", setup_pre_connect,
2830+ test_request_blocked_contacts_connect_failed,
2831+ teardown_pre_connect);
2832+ g_test_add ("/contact-lists/block-contacts",
2833+ Test, NULL, setup, test_block_contacts, teardown);
2834+ g_test_add ("/contact-lists/block-contacts/no-op",
2835+ Test, NULL, setup, test_block_contacts_no_op, teardown);
2836+ g_test_add ("/contact-lists/unblock-contacts",
2837+ Test, NULL, setup, test_unblock_contacts, teardown);
2838+ g_test_add ("/contact-lists/unblock-contacts/no-op",
2839+ Test, NULL, setup, test_unblock_contacts_no_op, teardown);
2840+
2841+ return g_test_run ();
2842+}
2843+>>>>>>> MERGE-SOURCE

Subscribers

People subscribed via source and target branches

to all changes: