From 60f0246a6a76ba8259ee7005ee55a66fc029d41a Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Wed, 25 Sep 2013 10:00:54 +0200 Subject: [PATCH 11/15] tests/lib: sync with tp-glib master Add room-list-chan.c as it's used by simple-conn. https://bugs.freedesktop.org/show_bug.cgi?id=69797 --- tests/lib/Makefile.am | 4 +- tests/lib/room-list-chan.c | 253 +++++++++++++++++++++++++++++++++ tests/lib/room-list-chan.h | 50 +++++++ tests/lib/simple-conn.c | 172 ++++++++++++++++++++--- tests/lib/simple-conn.h | 5 + tests/lib/textchan-null.c | 15 +- tests/lib/util.c | 340 ++++++++++++++++++++++++++++++++++++--------- tests/lib/util.h | 36 ++++- 8 files changed, 777 insertions(+), 98 deletions(-) create mode 100644 tests/lib/room-list-chan.c create mode 100644 tests/lib/room-list-chan.h diff --git a/tests/lib/Makefile.am b/tests/lib/Makefile.am index e0b7940..faae79a 100644 --- a/tests/lib/Makefile.am +++ b/tests/lib/Makefile.am @@ -3,6 +3,8 @@ noinst_LTLIBRARIES = libtp-logger-tests.la libtp_logger_tests_la_SOURCES = \ contacts-conn.c \ contacts-conn.h \ + room-list-chan.c \ + room-list-chan.h \ simple-account.c \ simple-account.h \ simple-account-manager.c \ @@ -23,4 +25,4 @@ AM_CFLAGS = \ $(TPL_CFLAGS)\ $(NULL) -libtp_logger_tests_la_LIBADD = $(TPL_LIBS) \ No newline at end of file +libtp_logger_tests_la_LIBADD = $(TPL_LIBS) diff --git a/tests/lib/room-list-chan.c b/tests/lib/room-list-chan.c new file mode 100644 index 0000000..49ed291 --- /dev/null +++ b/tests/lib/room-list-chan.c @@ -0,0 +1,253 @@ + +#include "config.h" + +#include "room-list-chan.h" + +#include +#include +#include + +static void room_list_iface_init (gpointer iface, + gpointer data); + +G_DEFINE_TYPE_WITH_CODE (TpTestsRoomListChan, tp_tests_room_list_chan, TP_TYPE_BASE_CHANNEL, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_ROOM_LIST, room_list_iface_init)) + +enum { + PROP_SERVER = 1, + LAST_PROPERTY, +}; + +/* +enum { + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; +*/ + +struct _TpTestsRoomListChanPriv { + gchar *server; + gboolean listing; +}; + +static void +tp_tests_room_list_chan_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + TpTestsRoomListChan *self = TP_TESTS_ROOM_LIST_CHAN (object); + + switch (property_id) + { + case PROP_SERVER: + g_value_set_string (value, self->priv->server); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +tp_tests_room_list_chan_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + TpTestsRoomListChan *self = TP_TESTS_ROOM_LIST_CHAN (object); + + switch (property_id) + { + case PROP_SERVER: + g_assert (self->priv->server == NULL); /* construct only */ + self->priv->server = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +tp_tests_room_list_chan_constructed (GObject *object) +{ + TpTestsRoomListChan *self = TP_TESTS_ROOM_LIST_CHAN (object); + void (*chain_up) (GObject *) = + ((GObjectClass *) tp_tests_room_list_chan_parent_class)->constructed; + + if (chain_up != NULL) + chain_up (object); + + tp_base_channel_register (TP_BASE_CHANNEL (self)); +} + +static void +tp_tests_room_list_chan_finalize (GObject *object) +{ + TpTestsRoomListChan *self = TP_TESTS_ROOM_LIST_CHAN (object); + void (*chain_up) (GObject *) = + ((GObjectClass *) tp_tests_room_list_chan_parent_class)->finalize; + + g_free (self->priv->server); + + if (chain_up != NULL) + chain_up (object); +} + +static void +fill_immutable_properties (TpBaseChannel *chan, + GHashTable *properties) +{ + TpBaseChannelClass *klass = TP_BASE_CHANNEL_CLASS ( + tp_tests_room_list_chan_parent_class); + + klass->fill_immutable_properties (chan, properties); + + tp_dbus_properties_mixin_fill_properties_hash ( + G_OBJECT (chan), properties, + TP_IFACE_CHANNEL_TYPE_ROOM_LIST, "Server", + NULL); +} + +static void +room_list_chan_close (TpBaseChannel *channel) +{ + tp_base_channel_destroyed (channel); +} + +static void +tp_tests_room_list_chan_class_init ( + TpTestsRoomListChanClass *klass) +{ + GObjectClass *oclass = G_OBJECT_CLASS (klass); + TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (klass); + GParamSpec *spec; + static TpDBusPropertiesMixinPropImpl room_list_props[] = { + { "Server", "server", NULL, }, + { NULL } + }; + + oclass->get_property = tp_tests_room_list_chan_get_property; + oclass->set_property = tp_tests_room_list_chan_set_property; + oclass->constructed = tp_tests_room_list_chan_constructed; + oclass->finalize = tp_tests_room_list_chan_finalize; + + base_class->channel_type = TP_IFACE_CHANNEL_TYPE_ROOM_LIST; + base_class->target_handle_type = TP_HANDLE_TYPE_NONE; + base_class->fill_immutable_properties = fill_immutable_properties; + base_class->close = room_list_chan_close; + + spec = g_param_spec_string ("server", "server", + "Server", + "", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (oclass, PROP_SERVER, spec); + + tp_dbus_properties_mixin_implement_interface (oclass, + TP_IFACE_QUARK_CHANNEL_TYPE_ROOM_LIST, + tp_dbus_properties_mixin_getter_gobject_properties, NULL, + room_list_props); + + g_type_class_add_private (klass, sizeof (TpTestsRoomListChanPriv)); +} + +static void +tp_tests_room_list_chan_init (TpTestsRoomListChan *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + TP_TESTS_TYPE_ROOM_LIST_CHAN, TpTestsRoomListChanPriv); +} + +static void +add_room (GPtrArray *rooms) +{ + GHashTable *hash; + + hash = tp_asv_new ( + "handle-name", G_TYPE_STRING, "the handle name", + "name", G_TYPE_STRING, "the name", + "description", G_TYPE_STRING, "the description", + "subject", G_TYPE_STRING, "the subject", + "members", G_TYPE_UINT, 10, + "password", G_TYPE_BOOLEAN, TRUE, + "invite-only", G_TYPE_BOOLEAN, TRUE, + "room-id", G_TYPE_STRING, "the room id", + "server", G_TYPE_STRING, "the server", + NULL); + + g_ptr_array_add (rooms, tp_value_array_build (3, + G_TYPE_UINT, 0, + G_TYPE_STRING, TP_IFACE_CHANNEL_TYPE_TEXT, + TP_HASH_TYPE_STRING_VARIANT_MAP, hash, + G_TYPE_INVALID)); + + g_hash_table_unref (hash); +} + +static gboolean +find_rooms (gpointer data) +{ + TpTestsRoomListChan *self = TP_TESTS_ROOM_LIST_CHAN (data); + GPtrArray *rooms; + + rooms = g_ptr_array_new_with_free_func ((GDestroyNotify) g_value_array_free); + + /* Find 2 rooms */ + add_room (rooms); + add_room (rooms); + tp_svc_channel_type_room_list_emit_got_rooms (self, rooms); + g_ptr_array_set_size (rooms, 0); + + /* Find 1 room */ + add_room (rooms); + tp_svc_channel_type_room_list_emit_got_rooms (self, rooms); + g_ptr_array_unref (rooms); + + return FALSE; +} + +static void +room_list_list_rooms (TpSvcChannelTypeRoomList *chan, + DBusGMethodInvocation *context) +{ + TpTestsRoomListChan *self = TP_TESTS_ROOM_LIST_CHAN (chan); + + if (self->priv->listing) + { + GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + "Already listing" }; + + dbus_g_method_return_error (context, &error); + return; + } + + if (!tp_strdiff (self->priv->server, "ListRoomsFail")) + { + GError error = { TP_ERROR, TP_ERROR_SERVICE_CONFUSED, + "Computer says no" }; + + dbus_g_method_return_error (context, &error); + return; + } + + self->priv->listing = TRUE; + tp_svc_channel_type_room_list_emit_listing_rooms (self, TRUE); + + g_idle_add (find_rooms, self); + + tp_svc_channel_type_room_list_return_from_list_rooms (context); +} + +static void +room_list_iface_init (gpointer iface, + gpointer data) +{ + TpSvcChannelTypeRoomListClass *klass = iface; + +#define IMPLEMENT(x) \ + tp_svc_channel_type_room_list_implement_##x (klass, room_list_##x) + IMPLEMENT(list_rooms); +#undef IMPLEMENT +} diff --git a/tests/lib/room-list-chan.h b/tests/lib/room-list-chan.h new file mode 100644 index 0000000..b41be27 --- /dev/null +++ b/tests/lib/room-list-chan.h @@ -0,0 +1,50 @@ + +#ifndef __TP_TESTS_ROOM_LIST_CHAN_H__ +#define __TP_TESTS_ROOM_LIST_CHAN_H__ + +#include +#include + +G_BEGIN_DECLS + +typedef struct _TpTestsRoomListChan TpTestsRoomListChan; +typedef struct _TpTestsRoomListChanClass TpTestsRoomListChanClass; +typedef struct _TpTestsRoomListChanPriv TpTestsRoomListChanPriv; + +struct _TpTestsRoomListChanClass { + TpBaseChannelClass parent_class; + TpDBusPropertiesMixinClass dbus_properties_class; +}; + +struct _TpTestsRoomListChan { + TpBaseChannel parent; + TpTestsRoomListChanPriv *priv; +}; + +GType tp_tests_room_list_chan_get_type (void); + +/* TYPE MACROS */ +#define TP_TESTS_TYPE_ROOM_LIST_CHAN \ + (tp_tests_room_list_chan_get_type ()) +#define TP_TESTS_ROOM_LIST_CHAN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + TP_TESTS_TYPE_ROOM_LIST_CHAN, \ + TpTestsRoomListChan)) +#define TP_TESTS_ROOM_LIST_CHAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + TP_TESTS_TYPE_ROOM_LIST_CHAN, \ + TpTestsRoomListChanClass)) +#define TP_TESTS_IS_ROOM_LIST_CHAN(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + TP_TESTS_TYPE_ROOM_LIST_CHAN)) +#define TP_TESTS_IS_ROOM_LIST_CHAN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), \ + TP_TESTS_TYPE_ROOM_LIST_CHAN)) +#define TP_TESTS_ROOM_LIST_CHAN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TP_TESTS_TYPE_ROOM_LIST_CHAN, \ + TpTestsRoomListChanClass)) + +G_END_DECLS + +#endif /* #ifndef __TP_TESTS_ROOM_LIST_CHAN_H__*/ diff --git a/tests/lib/simple-conn.c b/tests/lib/simple-conn.c index 11cc7f5..c78e127 100644 --- a/tests/lib/simple-conn.c +++ b/tests/lib/simple-conn.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -25,12 +26,15 @@ #include #include "textchan-null.h" +#include "room-list-chan.h" #include "util.h" +static void props_iface_init (TpSvcDBusPropertiesClass *); static void conn_iface_init (TpSvcConnectionClass *); G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleConnection, tp_tests_simple_connection, TP_TYPE_BASE_CONNECTION, + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES, props_iface_init); G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION, conn_iface_init)) /* type definition stuff */ @@ -38,12 +42,15 @@ G_DEFINE_TYPE_WITH_CODE (TpTestsSimpleConnection, tp_tests_simple_connection, enum { PROP_ACCOUNT = 1, + PROP_BREAK_PROPS = 2, + PROP_DBUS_STATUS = 3, N_PROPS }; enum { SIGNAL_GOT_SELF_HANDLE, + SIGNAL_GOT_ALL, N_SIGNALS }; @@ -54,9 +61,11 @@ struct _TpTestsSimpleConnectionPrivate gchar *account; guint connect_source; guint disconnect_source; + gboolean break_fastpath_props; /* TpHandle => reffed TpTestsTextChannelNull */ - GHashTable *channels; + GHashTable *text_channels; + TpTestsRoomListChan *room_list_chan; GError *get_self_handle_error /* initially NULL */ ; }; @@ -67,7 +76,7 @@ tp_tests_simple_connection_init (TpTestsSimpleConnection *self) self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TESTS_TYPE_SIMPLE_CONNECTION, TpTestsSimpleConnectionPrivate); - self->priv->channels = g_hash_table_new_full (NULL, NULL, NULL, + self->priv->text_channels = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref); } @@ -83,6 +92,21 @@ get_property (GObject *object, case PROP_ACCOUNT: g_value_set_string (value, self->priv->account); break; + case PROP_BREAK_PROPS: + g_value_set_boolean (value, self->priv->break_fastpath_props); + break; + case PROP_DBUS_STATUS: + if (self->priv->break_fastpath_props) + { + g_debug ("returning broken value for Connection.Status"); + g_value_set_uint (value, 0xdeadbeefU); + } + else + { + g_value_set_uint (value, + tp_base_connection_get_status (TP_BASE_CONNECTION (self))); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); } @@ -101,6 +125,9 @@ set_property (GObject *object, g_free (self->priv->account); self->priv->account = g_utf8_strdown (g_value_get_string (value), -1); break; + case PROP_BREAK_PROPS: + self->priv->break_fastpath_props = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, spec); } @@ -111,7 +138,8 @@ dispose (GObject *object) { TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (object); - g_hash_table_unref (self->priv->channels); + g_hash_table_unref (self->priv->text_channels); + g_clear_object (&self->priv->room_list_chan); G_OBJECT_CLASS (tp_tests_simple_connection_parent_class)->dispose (object); } @@ -170,7 +198,7 @@ tp_tests_simple_normalize_contact (TpHandleRepoIface *repo, static void create_handle_repos (TpBaseConnection *conn, - TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES]) + TpHandleRepoIface *repos[TP_NUM_HANDLE_TYPES]) { repos[TP_HANDLE_TYPE_CONTACT] = tp_dynamic_handle_repo_new (TP_HANDLE_TYPE_CONTACT, tp_tests_simple_normalize_contact, NULL); @@ -199,11 +227,13 @@ pretend_connected (gpointer data) TpBaseConnection *conn = (TpBaseConnection *) self; TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (conn, TP_HANDLE_TYPE_CONTACT); + TpHandle self_handle; - conn->self_handle = tp_handle_ensure (contact_repo, self->priv->account, + self_handle = tp_handle_ensure (contact_repo, self->priv->account, NULL, NULL); + tp_base_connection_set_self_handle (conn, self_handle); - if (conn->status == TP_CONNECTION_STATUS_CONNECTING) + if (tp_base_connection_get_status (conn) == TP_CONNECTION_STATUS_CONNECTING) { tp_base_connection_change_status (conn, TP_CONNECTION_STATUS_CONNECTED, TP_CONNECTION_STATUS_REASON_REQUESTED); @@ -237,7 +267,8 @@ pretend_disconnected (gpointer data) TpTestsSimpleConnection *self = TP_TESTS_SIMPLE_CONNECTION (data); /* We are disconnected, all our channels are invalidated */ - g_hash_table_remove_all (self->priv->channels); + g_hash_table_remove_all (self->priv->text_channels); + g_clear_object (&self->priv->room_list_chan); tp_base_connection_finish_shutdown (TP_BASE_CONNECTION (data)); self->priv->disconnect_source = 0; @@ -257,6 +288,19 @@ shut_down (TpBaseConnection *conn) conn); } +static GPtrArray * +get_interfaces_always_present (TpBaseConnection *base) +{ + GPtrArray *interfaces; + + interfaces = TP_BASE_CONNECTION_CLASS ( + tp_tests_simple_connection_parent_class)->get_interfaces_always_present (base); + + g_ptr_array_add (interfaces, TP_IFACE_CONNECTION_INTERFACE_REQUESTS); + + return interfaces; +} + static void tp_tests_simple_connection_class_init (TpTestsSimpleConnectionClass *klass) { @@ -264,8 +308,6 @@ tp_tests_simple_connection_class_init (TpTestsSimpleConnectionClass *klass) (TpBaseConnectionClass *) klass; GObjectClass *object_class = (GObjectClass *) klass; GParamSpec *param_spec; - static const gchar *interfaces_always_present[] = { - TP_IFACE_CONNECTION_INTERFACE_REQUESTS, NULL }; object_class->get_property = get_property; object_class->set_property = set_property; @@ -279,20 +321,39 @@ tp_tests_simple_connection_class_init (TpTestsSimpleConnectionClass *klass) base_class->start_connecting = start_connecting; base_class->shut_down = shut_down; - base_class->interfaces_always_present = interfaces_always_present; + base_class->get_interfaces_always_present = get_interfaces_always_present; param_spec = g_param_spec_string ("account", "Account name", "The username of this user", NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | - G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec); + param_spec = g_param_spec_boolean ("break-0192-properties", + "Break 0.19.2 properties", + "Break Connection D-Bus properties introduced in spec 0.19.2", FALSE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_BREAK_PROPS, param_spec); + + param_spec = g_param_spec_uint ("dbus-status", + "Connection.Status", + "The connection status as visible on D-Bus (overridden so can break it)", + TP_CONNECTION_STATUS_CONNECTED, G_MAXUINT, + TP_CONNECTION_STATUS_DISCONNECTED, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_DBUS_STATUS, param_spec); + signals[SIGNAL_GOT_SELF_HANDLE] = g_signal_new ("got-self-handle", G_OBJECT_CLASS_TYPE (klass), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, 0, - NULL, NULL, - g_cclosure_marshal_VOID__VOID, + NULL, NULL, NULL, + G_TYPE_NONE, 0); + + signals[SIGNAL_GOT_ALL] = g_signal_new ("got-all", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + 0, + NULL, NULL, NULL, G_TYPE_NONE, 0); } @@ -309,7 +370,6 @@ tp_tests_simple_connection_set_identifier (TpTestsSimpleConnection *self, g_return_if_fail (handle != 0); tp_base_connection_set_self_handle (conn, handle); - tp_handle_unref (contact_repo, handle); } TpTestsSimpleConnection * @@ -342,7 +402,8 @@ tp_tests_simple_connection_ensure_text_chan (TpTestsSimpleConnection *self, handle = tp_handle_ensure (contact_repo, target_id, NULL, NULL); - chan = g_hash_table_lookup (self->priv->channels, GUINT_TO_POINTER (handle)); + chan = g_hash_table_lookup (self->priv->text_channels, + GUINT_TO_POINTER (handle)); if (chan != NULL) { /* Channel already exist, reuse it */ @@ -350,8 +411,8 @@ tp_tests_simple_connection_ensure_text_chan (TpTestsSimpleConnection *self, } else { - chan_path = g_strdup_printf ("%s/Channel%u", base_conn->object_path, - count++); + chan_path = g_strdup_printf ("%s/Channel%u", + tp_base_connection_get_object_path (base_conn), count++); chan = TP_TESTS_TEXT_CHANNEL_NULL ( tp_tests_object_new_static_class ( @@ -361,18 +422,61 @@ tp_tests_simple_connection_ensure_text_chan (TpTestsSimpleConnection *self, "handle", handle, NULL)); - g_hash_table_insert (self->priv->channels, GUINT_TO_POINTER (handle), + g_hash_table_insert (self->priv->text_channels, GUINT_TO_POINTER (handle), chan); } - tp_handle_unref (contact_repo, handle); - if (props != NULL) *props = tp_tests_text_channel_get_props (chan); return chan_path; } +static void +room_list_chan_closed_cb (TpBaseChannel *channel, + TpTestsSimpleConnection *self) +{ + g_clear_object (&self->priv->room_list_chan); +} + +gchar * +tp_tests_simple_connection_ensure_room_list_chan (TpTestsSimpleConnection *self, + const gchar *server, + GHashTable **props) +{ + gchar *chan_path; + TpBaseConnection *base_conn = (TpBaseConnection *) self; + + if (self->priv->room_list_chan != NULL) + { + /* Channel already exist, reuse it */ + g_object_get (self->priv->room_list_chan, + "object-path", &chan_path, NULL); + } + else + { + chan_path = g_strdup_printf ("%s/RoomListChannel", + tp_base_connection_get_object_path (base_conn)); + + self->priv->room_list_chan = TP_TESTS_ROOM_LIST_CHAN ( + tp_tests_object_new_static_class ( + TP_TESTS_TYPE_ROOM_LIST_CHAN, + "connection", self, + "object-path", chan_path, + "server", server ? server : "", + NULL)); + + g_signal_connect (self->priv->room_list_chan, "closed", + G_CALLBACK (room_list_chan_closed_cb), self); + } + + if (props != NULL) + g_object_get (self->priv->room_list_chan, + "channel-properties", props, NULL); + + return chan_path; +} + void tp_tests_simple_connection_set_get_self_handle_error ( TpTestsSimpleConnection *self, @@ -401,7 +505,8 @@ get_self_handle (TpSvcConnection *iface, return; } - tp_svc_connection_return_from_get_self_handle (context, base->self_handle); + tp_svc_connection_return_from_get_self_handle (context, + tp_base_connection_get_self_handle (base)); g_signal_emit (self, signals[SIGNAL_GOT_SELF_HANDLE], 0); } @@ -413,3 +518,26 @@ conn_iface_init (TpSvcConnectionClass *iface) IMPLEMENT(,get_self_handle); #undef IMPLEMENT } + +static void +get_all (TpSvcDBusProperties *iface, + const gchar *interface_name, + DBusGMethodInvocation *context) +{ + GHashTable *values = tp_dbus_properties_mixin_dup_all (G_OBJECT (iface), + interface_name); + + tp_svc_dbus_properties_return_from_get_all (context, values); + g_hash_table_unref (values); + g_signal_emit (iface, signals[SIGNAL_GOT_ALL], + g_quark_from_string (interface_name)); +} + +static void +props_iface_init (TpSvcDBusPropertiesClass *iface) +{ +#define IMPLEMENT(x) \ + tp_svc_dbus_properties_implement_##x (iface, x) + IMPLEMENT (get_all); +#undef IMPLEMENT +} diff --git a/tests/lib/simple-conn.h b/tests/lib/simple-conn.h index 6322f4b..837400b 100644 --- a/tests/lib/simple-conn.h +++ b/tests/lib/simple-conn.h @@ -72,6 +72,11 @@ void tp_tests_simple_connection_set_get_self_handle_error ( gint code, const gchar *message); +gchar * tp_tests_simple_connection_ensure_room_list_chan ( + TpTestsSimpleConnection *self, + const gchar *server, + GHashTable **props); + G_END_DECLS #endif /* #ifndef __TP_TESTS_SIMPLE_CONN_H__ */ diff --git a/tests/lib/textchan-null.c b/tests/lib/textchan-null.c index 01efb4f..bbeb0c7 100644 --- a/tests/lib/textchan-null.c +++ b/tests/lib/textchan-null.c @@ -21,6 +21,10 @@ #include #include +/* This is for text-mixin unit tests, others should be using ExampleEcho2Channel + * which uses newer TpMessageMixin */ +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + static void text_iface_init (gpointer iface, gpointer data); static void channel_iface_init (gpointer iface, gpointer data); @@ -150,7 +154,8 @@ get_property (GObject *object, g_value_set_boolean (value, TRUE); break; case PROP_INITIATOR_HANDLE: - g_value_set_uint (value, self->priv->conn->self_handle); + g_value_set_uint (value, tp_base_connection_get_self_handle ( + self->priv->conn)); break; case PROP_INITIATOR_ID: { @@ -158,7 +163,8 @@ get_property (GObject *object, self->priv->conn, TP_HANDLE_TYPE_CONTACT); g_value_set_string (value, - tp_handle_inspect (contact_repo, self->priv->conn->self_handle)); + tp_handle_inspect (contact_repo, + tp_base_connection_get_self_handle (self->priv->conn))); } break; case PROP_INTERFACES: @@ -273,8 +279,7 @@ tp_tests_text_channel_null_class_init (TpTestsTextChannelNullClass *klass) param_spec = g_param_spec_object ("connection", "TpBaseConnection object", "Connection object that owns this channel", TP_TYPE_BASE_CONNECTION, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | - G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB); + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_CONNECTION, param_spec); param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces", @@ -570,3 +575,5 @@ tp_tests_text_channel_get_props (TpTestsTextChannelNull *self) g_strfreev (interfaces); return props; } + +G_GNUC_END_IGNORE_DEPRECATIONS diff --git a/tests/lib/util.c b/tests/lib/util.c index b58227e..1e8c402 100644 --- a/tests/lib/util.c +++ b/tests/lib/util.c @@ -12,11 +12,21 @@ #include "util.h" +#include + +#include +#include #include + #ifdef G_OS_UNIX # include /* for alarm() */ #endif +#ifdef HAVE_GIO_UNIX +#include +#include +#endif + void tp_tests_proxy_run_until_prepared (gpointer proxy, const GQuark *features) @@ -105,50 +115,6 @@ tp_tests_proxy_run_until_dbus_queue_processed (gpointer proxy) g_main_loop_unref (loop); } -typedef struct { - GMainLoop *loop; - TpHandle handle; -} HandleRequestResult; - -static void -handles_requested_cb (TpConnection *connection G_GNUC_UNUSED, - TpHandleType handle_type G_GNUC_UNUSED, - guint n_handles, - const TpHandle *handles, - const gchar * const *ids G_GNUC_UNUSED, - const GError *error, - gpointer user_data, - GObject *weak_object G_GNUC_UNUSED) -{ - HandleRequestResult *result = user_data; - - g_assert_no_error ((GError *) error); - g_assert_cmpuint (n_handles, ==, 1); - result->handle = handles[0]; -} - -static void -handle_request_result_finish (gpointer r) -{ - HandleRequestResult *result = r; - - g_main_loop_quit (result->loop); -} - -TpHandle -tp_tests_connection_run_request_contact_handle (TpConnection *connection, - const gchar *id) -{ - HandleRequestResult result = { g_main_loop_new (NULL, FALSE), 0 }; - const gchar * const ids[] = { id, NULL }; - - tp_connection_request_handles (connection, -1, TP_HANDLE_TYPE_CONTACT, ids, - handles_requested_cb, &result, handle_request_result_finish, NULL); - g_main_loop_run (result.loop); - g_main_loop_unref (result.loop); - return result.handle; -} - void _test_assert_empty_strv (const char *file, int line, @@ -211,41 +177,43 @@ _tp_tests_assert_strv_equals (const char *file, } void -tp_tests_copy_dir (const gchar *from_dir, const gchar *to_dir) +_tp_tests_assert_bytes_equal (const gchar *file, int line, + GBytes *actual, gconstpointer expected_data, + gsize expected_length) { - gchar *command; - - // If destination directory exist erase it - command = g_strdup_printf ("rm -rf %s", to_dir); - g_assert (system (command) == 0); - g_free (command); - - command = g_strdup_printf ("cp -r %s %s", from_dir, to_dir); - g_assert (system (command) == 0); - g_free (command); - - // In distcheck mode the files and directory are read-only, fix that - command = g_strdup_printf ("chmod -R +w %s", to_dir); - g_assert (system (command) == 0); - g_free (command); + if (expected_length != g_bytes_get_size (actual)) + { + g_error ("%s:%d: assertion failed: expected %"G_GSIZE_FORMAT + " bytes, got %"G_GSIZE_FORMAT, + file, line, expected_length, g_bytes_get_size (actual)); + } + else if (memcmp (g_bytes_get_data (actual, NULL), + expected_data, expected_length) != 0) + { + g_error ( + "%s:%d: assertion failed: expected data didn't match the actual data", + file, line); + } } void -tp_tests_create_and_connect_conn (GType conn_type, +tp_tests_create_conn (GType conn_type, const gchar *account, + gboolean connect, TpBaseConnection **service_conn, TpConnection **client_conn) { TpDBusDaemon *dbus; + TpSimpleClientFactory *factory; gchar *name; gchar *conn_path; GError *error = NULL; - GQuark conn_features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 }; g_assert (service_conn != NULL); g_assert (client_conn != NULL); dbus = tp_tests_dbus_daemon_dup_or_die (); + factory = (TpSimpleClientFactory *) tp_automatic_client_factory_new (dbus); *service_conn = tp_tests_object_new_static_class ( conn_type, @@ -258,18 +226,33 @@ tp_tests_create_and_connect_conn (GType conn_type, &name, &conn_path, &error)); g_assert_no_error (error); - *client_conn = tp_connection_new (dbus, name, conn_path, - &error); + *client_conn = tp_simple_client_factory_ensure_connection (factory, + conn_path, NULL, &error); g_assert (*client_conn != NULL); g_assert_no_error (error); - tp_cli_connection_call_connect (*client_conn, -1, NULL, NULL, NULL, NULL); - tp_tests_proxy_run_until_prepared (*client_conn, conn_features); + if (connect) + { + GQuark conn_features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 }; + + tp_cli_connection_call_connect (*client_conn, -1, NULL, NULL, NULL, NULL); + tp_tests_proxy_run_until_prepared (*client_conn, conn_features); + } g_free (name); g_free (conn_path); g_object_unref (dbus); + g_object_unref (factory); +} + +void +tp_tests_create_and_connect_conn (GType conn_type, + const gchar *account, + TpBaseConnection **service_conn, + TpConnection **client_conn) +{ + tp_tests_create_conn (conn_type, account, TRUE, service_conn, client_conn); } /* This object exists solely so that tests/tests.supp can ignore "leaked" @@ -300,7 +283,27 @@ time_out (gpointer nil G_GNUC_UNUSED) void tp_tests_abort_after (guint sec) { - if (g_getenv ("TP_TESTS_NO_TIMEOUT") != NULL) + gboolean debugger = FALSE; + gchar *contents; + + if (g_file_get_contents ("/proc/self/status", &contents, NULL, NULL)) + { +/* http://www.youtube.com/watch?v=SXmv8quf_xM */ +#define TRACER_T "\nTracerPid:\t" + gchar *line = strstr (contents, TRACER_T); + + if (line != NULL) + { + gchar *value = line + strlen (TRACER_T); + + if (value[0] != '0' || value[1] != '\n') + debugger = TRUE; + } + + g_free (contents); + } + + if (g_getenv ("TP_TESTS_NO_TIMEOUT") != NULL || debugger) return; g_timeout_add_seconds (sec, time_out, NULL); @@ -312,3 +315,206 @@ tp_tests_abort_after (guint sec) alarm (sec + 2); #endif } + +void +tp_tests_init (int *argc, + char ***argv) +{ + g_type_init (); + tp_tests_abort_after (10); + tp_debug_set_flags ("all"); + + g_test_init (argc, argv, NULL); +} + +void +_tp_destroy_socket_control_list (gpointer data) +{ + GArray *tab = data; + g_array_unref (tab); +} + +GValue * +_tp_create_local_socket (TpSocketAddressType address_type, + TpSocketAccessControl access_control, + GSocketService **service, + gchar **unix_address, + gchar **unix_tmpdir, + GError **error) +{ + gboolean success; + GSocketAddress *address, *effective_address; + GValue *address_gvalue; + + g_assert (service != NULL); + g_assert (unix_address != NULL); + + switch (access_control) + { + case TP_SOCKET_ACCESS_CONTROL_LOCALHOST: + case TP_SOCKET_ACCESS_CONTROL_CREDENTIALS: + case TP_SOCKET_ACCESS_CONTROL_PORT: + break; + + default: + g_assert_not_reached (); + } + + switch (address_type) + { +#ifdef HAVE_GIO_UNIX + case TP_SOCKET_ADDRESS_TYPE_UNIX: + { + GError *e = NULL; + gchar *dir = g_dir_make_tmp ("tp-glib-tests.XXXXXX", &e); + gchar *name; + + g_assert_no_error (e); + + name = g_build_filename (dir, "s", NULL); + address = g_unix_socket_address_new (name); + g_free (name); + + if (unix_tmpdir != NULL) + *unix_tmpdir = dir; + else + g_free (dir); + break; + } +#endif + + case TP_SOCKET_ADDRESS_TYPE_IPV4: + case TP_SOCKET_ADDRESS_TYPE_IPV6: + { + GInetAddress *localhost; + + localhost = g_inet_address_new_loopback ( + address_type == TP_SOCKET_ADDRESS_TYPE_IPV4 ? + G_SOCKET_FAMILY_IPV4 : G_SOCKET_FAMILY_IPV6); + address = g_inet_socket_address_new (localhost, 0); + + g_object_unref (localhost); + break; + } + + default: + g_assert_not_reached (); + } + + *service = g_socket_service_new (); + + success = g_socket_listener_add_address ( + G_SOCKET_LISTENER (*service), + address, G_SOCKET_TYPE_STREAM, + G_SOCKET_PROTOCOL_DEFAULT, + NULL, &effective_address, NULL); + g_assert (success); + + switch (address_type) + { +#ifdef HAVE_GIO_UNIX + case TP_SOCKET_ADDRESS_TYPE_UNIX: + *unix_address = g_strdup (g_unix_socket_address_get_path ( + G_UNIX_SOCKET_ADDRESS (effective_address))); + address_gvalue = tp_g_value_slice_new_bytes ( + g_unix_socket_address_get_path_len ( + G_UNIX_SOCKET_ADDRESS (effective_address)), + g_unix_socket_address_get_path ( + G_UNIX_SOCKET_ADDRESS (effective_address))); + break; +#endif + + case TP_SOCKET_ADDRESS_TYPE_IPV4: + case TP_SOCKET_ADDRESS_TYPE_IPV6: + *unix_address = NULL; + + address_gvalue = tp_g_value_slice_new_take_boxed ( + TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4, + dbus_g_type_specialized_construct ( + TP_STRUCT_TYPE_SOCKET_ADDRESS_IPV4)); + + dbus_g_type_struct_set (address_gvalue, + 0, address_type == TP_SOCKET_ADDRESS_TYPE_IPV4 ? + "127.0.0.1" : "::1", + 1, g_inet_socket_address_get_port ( + G_INET_SOCKET_ADDRESS (effective_address)), + G_MAXUINT); + break; + + default: + g_assert_not_reached (); + } + + g_object_unref (address); + g_object_unref (effective_address); + return address_gvalue; +} + +void +tp_tests_connection_assert_disconnect_succeeds (TpConnection *connection) +{ + GAsyncResult *result = NULL; + GError *error = NULL; + gboolean ok; + + tp_connection_disconnect_async (connection, tp_tests_result_ready_cb, + &result); + tp_tests_run_until_result (&result); + ok = tp_connection_disconnect_finish (connection, result, &error); + g_assert_no_error (error); + g_assert (ok); + g_object_unref (result); +} + +static void +one_contact_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + TpConnection *connection = (TpConnection *) object; + TpContact **contact_loc = user_data; + GError *error = NULL; + + *contact_loc = tp_connection_dup_contact_by_id_finish (connection, result, + &error); + + g_assert_no_error (error); + g_assert (TP_IS_CONTACT (*contact_loc)); +} + +TpContact * +tp_tests_connection_run_until_contact_by_id (TpConnection *connection, + const gchar *id, + guint n_features, + const TpContactFeature *features) +{ + TpContact *contact = NULL; + + tp_connection_dup_contact_by_id_async (connection, id, n_features, features, + one_contact_cb, &contact); + + while (contact == NULL) + g_main_context_iteration (NULL, TRUE); + + return contact; +} + +void +tp_tests_copy_dir (const gchar *from_dir, const gchar *to_dir) +{ + gchar *command; + + // If destination directory exist erase it + command = g_strdup_printf ("rm -rf %s", to_dir); + g_assert (system (command) == 0); + g_free (command); + + command = g_strdup_printf ("cp -r %s %s", from_dir, to_dir); + g_assert (system (command) == 0); + g_free (command); + + // In distcheck mode the files and directory are read-only, fix that + command = g_strdup_printf ("chmod -R +w %s", to_dir); + g_assert (system (command) == 0); + g_free (command); +} diff --git a/tests/lib/util.h b/tests/lib/util.h index ba96c7b..42c9489 100644 --- a/tests/lib/util.h +++ b/tests/lib/util.h @@ -18,10 +18,6 @@ TpDBusDaemon *tp_tests_dbus_daemon_dup_or_die (void); void tp_tests_proxy_run_until_dbus_queue_processed (gpointer proxy); -TpHandle tp_tests_connection_run_request_contact_handle ( - TpConnection *connection, - const gchar *id); - void tp_tests_proxy_run_until_prepared (gpointer proxy, const GQuark *features); gboolean tp_tests_proxy_run_until_prepared_or_failed (gpointer proxy, @@ -40,6 +36,18 @@ void _tp_tests_assert_strv_equals (const char *file, int line, const char *actual_desc, gconstpointer actual_strv, const char *expected_desc, gconstpointer expected_strv); +#define tp_tests_assert_bytes_equals(actual, expected, expected_length) \ + _tp_tests_assert_bytes_equal (__FILE__, __LINE__, \ + actual, expected, expected_length) +void _tp_tests_assert_bytes_equal (const gchar *file, int line, + GBytes *actual, gconstpointer expected_data, gsize expected_length); + +void tp_tests_create_conn (GType conn_type, + const gchar *account, + gboolean connect, + TpBaseConnection **service_conn, + TpConnection **client_conn); + void tp_tests_create_and_connect_conn (GType conn_type, const gchar *account, TpBaseConnection **service_conn, @@ -54,6 +62,26 @@ void tp_tests_result_ready_cb (GObject *object, void tp_tests_abort_after (guint sec); +void tp_tests_init (int *argc, + char ***argv); + +GValue *_tp_create_local_socket (TpSocketAddressType address_type, + TpSocketAccessControl access_control, + GSocketService **service, + gchar **unix_address, + gchar **unix_tmpdir, + GError **error); + +void _tp_destroy_socket_control_list (gpointer data); + +void tp_tests_connection_assert_disconnect_succeeds (TpConnection *connection); + +TpContact *tp_tests_connection_run_until_contact_by_id ( + TpConnection *connection, + const gchar *id, + guint n_features, + const TpContactFeature *features); + void tp_tests_copy_dir (const gchar *from_dir, const gchar *to_dir); #endif /* #ifndef __TP_TESTS_LIB_UTIL_H__ */ -- 1.8.3.1