diff options
36 files changed, 764 insertions, 349 deletions
@@ -4,6 +4,7 @@ /INSTALL aclocal.m4 autom4te.cache +/build-aux config.guess config.cache config.h diff --git a/configure.ac b/configure.ac index 6f3c451..f1cb1f9 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_PREREQ([2.59]) +AC_PREREQ([2.60]) # Making releases: # set the new version number: @@ -25,17 +25,18 @@ AC_INIT([telepathy-idle], [idle_version], [https://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=idle]) AC_CONFIG_MACRO_DIR([m4]) +AC_CONFIG_AUX_DIR([build-aux]) # Enable silent build rules by default, requires at least # Automake-1.11. Disable by either passing --disable-silent-rules to # configure or passing V=1 to make m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -AM_INIT_AUTOMAKE([1.9 -Wno-portability]) +AM_INIT_AUTOMAKE([1.9 -Wno-portability subdir-objects]) AM_PROG_LIBTOOL AM_CONFIG_HEADER(config.h) -AM_PROG_MKDIR_P +AC_PROG_MKDIR_P dnl check for tools AC_PROG_CC @@ -78,9 +79,8 @@ AC_SUBST([ERROR_CFLAGS]) # these aren't really error flags but they serve a similar purpose for us - # making the toolchain stricter -if test "x$enable_fatal_warnings" = xyes; then - TP_ADD_LINKER_FLAG([ERROR_LDFLAGS], [-Wl,--no-copy-dt-needed-entries]) -fi +AS_IF([test "x$enable_fatal_warnings" = xyes], + [TP_ADD_LINKER_FLAG([ERROR_LDFLAGS], [-Wl,--no-copy-dt-needed-entries])]) AC_HEADER_STDC([]) AC_C_INLINE @@ -95,30 +95,30 @@ PKG_CHECK_MODULES([DBUS], [dbus-1 >= 0.51, dbus-glib-1 >= 0.51]) AC_DEFINE([TP_SEAL_ENABLE], [], [Prevent to use sealed variables]) AC_DEFINE([TP_DISABLE_SINGLE_INCLUDE], [], [Disable single header include]) -AC_DEFINE(TP_VERSION_MIN_REQUIRED, TP_VERSION_0_22, [Ignore post 0.22 deprecations]) -AC_DEFINE(TP_VERSION_MAX_ALLOWED, TP_VERSION_0_22, [Prevent post 0.22 APIs]) -PKG_CHECK_MODULES([TELEPATHY], [telepathy-glib >= 0.21]) +AC_DEFINE(TP_VERSION_MIN_REQUIRED, TP_VERSION_0_24, [Ignore post 0.24 deprecations]) +AC_DEFINE(TP_VERSION_MAX_ALLOWED, TP_VERSION_0_24, [Prevent post 0.24 APIs]) +PKG_CHECK_MODULES([TELEPATHY], [telepathy-glib >= 0.23.0]) dnl Check for code generation tools XSLTPROC= AC_CHECK_PROGS([XSLTPROC], [xsltproc]) -if test -z "$XSLTPROC"; then - AC_MSG_ERROR([xsltproc (from the libxslt source package) is required]) -fi +AS_IF([test -z "$XSLTPROC"], + [AC_MSG_ERROR([xsltproc (from the libxslt source package) is required])]) AM_PATH_PYTHON([2.3]) dnl check for a version of python that can run the twisted tests AC_MSG_CHECKING([for Python with Twisted and IRC protocol support]) for TEST_PYTHON in python2.5 python2.6 python; do - if $TEST_PYTHON -c "from sys import version_info; import dbus, dbus.mainloop.glib; raise SystemExit(version_info < (2, 5, 0, 'final', 0))" >/dev/null 2>&1; then - if $TEST_PYTHON -c "import twisted.words.protocols.irc, twisted.internet.reactor" >/dev/null 2>&1; then - AM_CONDITIONAL([WANT_TWISTED_TESTS], true) + AS_IF([$TEST_PYTHON -c "from sys import version_info; import dbus, dbus.mainloop.glib; raise SystemExit(version_info < (2, 5, 0, 'final', 0))" >/dev/null 2>&1], + [ + AS_IF([$TEST_PYTHON -c "import twisted.words.protocols.irc, twisted.internet.reactor" >/dev/null 2>&1], + [ + AM_CONDITIONAL([WANT_TWISTED_TESTS], [true]) break - else - TEST_PYTHON=no - fi - fi + ], + [TEST_PYTHON=no]) + ]) done AC_MSG_RESULT([$TEST_PYTHON]) AC_SUBST(TEST_PYTHON) diff --git a/extensions/Connection_Interface_IRC_Command1.xml b/extensions/Connection_Interface_IRC_Command1.xml new file mode 100644 index 0000000..1de5396 --- /dev/null +++ b/extensions/Connection_Interface_IRC_Command1.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" ?> +<node name="/Connection_Interface_IRC_Command1" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> + <tp:copyright> Copyright (C) 2013 Collabora Limited </tp:copyright> + <tp:license xmlns="http://www.w3.org/1999/xhtml"> + <p>This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version.</p> + +<p>This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details.</p> + +<p>You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> + </tp:license> + <interface name="org.freedesktop.Telepathy.Connection.Interface.IRCCommand1" + tp:causes-havoc='not well-tested'> + <tp:requires interface="org.freedesktop.Telepathy.Connection"/> + <method name="Send" tp:name-for-bindings="Send"> + <arg direction="in" name="Command" type="s"> + <tp:docstring> + The command followed by its arguments. + </tp:docstring> + </arg> + <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> + <p>Send an arbitrary IRC command to the server.</p> + <p>For example, an IRC client receiving <code>/bip blreset</code> from + the user might call this method with <code>BIP blreset</code> as + argument which will send <code>BIP blreset</code> to the server.</p> + <p>The command is supplied in UTF-8 (because strings on D-Bus are + always UTF-8). It is transcoded into the connection's configured + character set, if different, before sending to the server.</p> + </tp:docstring> + <tp:possible-errors> + <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> + <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/> + <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"> + <tp:docstring> + The connection manager MAY raise this error for commands that + have a more appropriate D-Bus API. + </tp:docstring> + </tp:error> + </tp:possible-errors> + </method> + <tp:docstring> + An interface to send arbitrary IRC commands to the server. + </tp:docstring> + </interface> +</node> +<!-- vim:set sw=2 sts=2 et ft=xml: --> diff --git a/extensions/Connection_Interface_Renaming.xml b/extensions/Connection_Interface_Renaming.xml deleted file mode 100644 index d08b748..0000000 --- a/extensions/Connection_Interface_Renaming.xml +++ /dev/null @@ -1,98 +0,0 @@ -<?xml version="1.0" ?> -<node name="/Connection_Interface_Renaming" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"> - <tp:copyright> Copyright (C) 2005, 2006 Collabora Limited </tp:copyright> - <tp:copyright> Copyright (C) 2005, 2006 Nokia Corporation </tp:copyright> - <tp:copyright> Copyright (C) 2006 INdT </tp:copyright> - <tp:license xmlns="http://www.w3.org/1999/xhtml"> - <p>This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version.</p> - -<p>This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details.</p> - -<p>You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</p> - </tp:license> - <interface name="org.freedesktop.Telepathy.Connection.Interface.Renaming" - tp:causes-havoc='not well-tested'> - <tp:requires interface="org.freedesktop.Telepathy.Connection"/> - <signal name="Renamed" tp:name-for-bindings="Renamed"> - <arg name="Original" type="u" tp:type="Contact_Handle"> - <tp:docstring> - The handle of the original identifier - </tp:docstring> - </arg> - <arg name="New" type="u" tp:type="Contact_Handle"> - <tp:docstring> - The handle of the new identifier - </tp:docstring> - </arg> - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - <p>Emitted when the unique identifier of a contact on the server - changes.</p> - - <p>Any channels associated with the contact's original handle will - continue to be to that handle, and so are no longer useful (unless - the contact renames back, or another contact connects with that - unique ID). Clients may open a similar channel associated with the - new handle to continue communicating with the contact.</p> - - <p>For example, if a GUI client associates text - channels with chat windows, it should detach the old channel - from the chat window, closing it, and associate a channel to the - new handle with the same window.</p> - - <p>If the contact's old handle is in any of the member lists of - a channel which has the groups interface, it will be removed from - the channel and the new handle will be added. The resulting - <tp:dbus-ref - namespace="org.freedesktop.Telepathy.Channel.Interface.Group">MembersChanged</tp:dbus-ref> - signal must be emitted <em>after</em> the - <tp:member-ref>Renamed</tp:member-ref> signal; the reason should be - RENAMED. - </p> - - <p>The handles may be either general-purpose or channel-specific. - If the original handle is general-purpose, the new handle must be - general-purpose; if the original handle is channel-specific, the - new handle must be channel-specific in the same channel. - </p> - </tp:docstring> - </signal> - <method name="RequestRename" tp:name-for-bindings="Request_Rename"> - <arg direction="in" name="Identifier" type="s"> - <tp:docstring> - The desired identifier - </tp:docstring> - </arg> - <tp:docstring xmlns="http://www.w3.org/1999/xhtml"> - <p>Request that the user's own identifier is changed on the server. - If successful, a <tp:member-ref>Renamed</tp:member-ref> signal will - be emitted for the current "self handle" as returned by <tp:dbus-ref - namespace="org.freedesktop.Telepathy.Connection">GetSelfHandle</tp:dbus-ref>.</p> - <p>It is protocol-dependent how the identifier that's actually - used will be derived from the supplied identifier; some sort of - normalization might take place.</p> - </tp:docstring> - <tp:possible-errors> - <tp:error name="org.freedesktop.Telepathy.Error.Disconnected"/> - <tp:error name="org.freedesktop.Telepathy.Error.NetworkError"/> - <tp:error name="org.freedesktop.Telepathy.Error.NotAvailable"/> - <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument"/> - <tp:error name="org.freedesktop.Telepathy.Error.PermissionDenied"/> - </tp:possible-errors> - </method> - <tp:docstring> - An interface on connections to support protocols where the unique - identifiers of contacts can change. Because handles are immutable, - this is represented by a pair of handles, that representing the - old name, and that representing the new one. - </tp:docstring> - </interface> -</node> -<!-- vim:set sw=2 sts=2 et ft=xml: --> diff --git a/extensions/Makefile.am b/extensions/Makefile.am index bb837da..b4d67f8 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -2,7 +2,8 @@ tools_dir = $(top_srcdir)/tools EXTRA_DIST = \ all.xml \ - Connection_Interface_Renaming.xml + Connection_Interface_IRC_Command1.xml \ + $(NULL) noinst_LTLIBRARIES = libidle-extensions.la @@ -32,7 +33,7 @@ DROP_NAMESPACE = sed -e 's@xmlns:tp="http://telepathy\.freedesktop\.org/wiki/Dbu XSLTPROCFLAGS = --nonet --novalid _gen/all.xml: all.xml $(wildcard $(srcdir)/*.xml) - @$(mkdir_p) _gen + @$(MKDIR_P) _gen $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) \ --xinclude $(tools_dir)/identity.xsl \ $< > $@ @@ -49,7 +50,7 @@ _gen/svc.c: _gen/all.xml \ $(tools_dir)/glib-ginterface-gen.py $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-ginterface-gen.py \ --filename=_gen/svc --signal-marshal-prefix=_idle_ext \ - --include='<telepathy-glib/dbus.h>' \ + --include='<telepathy-glib/telepathy-glib.h>' \ --not-implemented-func='tp_dbus_g_method_return_not_implemented' \ --allow-unstable \ $< Idle_Svc_ diff --git a/extensions/all.xml b/extensions/all.xml index 3ed5d93..6b76837 100644 --- a/extensions/all.xml +++ b/extensions/all.xml @@ -22,7 +22,7 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA</p> </tp:license> -<xi:include href="Connection_Interface_Renaming.xml"/> +<xi:include href="Connection_Interface_IRC_Command1.xml"/> <tp:generic-types> <tp:external-type name="Contact_Handle" type="u" diff --git a/extensions/meson.build b/extensions/meson.build index 3600c3c..388820d 100644 --- a/extensions/meson.build +++ b/extensions/meson.build @@ -1,6 +1,6 @@ xmls = files( 'all.xml', - 'Connection_Interface_Renaming.xml', + 'Connection_Interface_IRC_Command1.xml', ) subdir('_gen') diff --git a/src/idle-connection.c b/src/idle-connection.c index 8614d52..9ee8840 100644 --- a/src/idle-connection.c +++ b/src/idle-connection.c @@ -27,6 +27,7 @@ #include <time.h> #include <dbus/dbus-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #define IDLE_DEBUG_FLAG IDLE_DEBUG_CONNECTION #include "idle-contact-info.h" @@ -40,7 +41,7 @@ #include "idle-server-connection.h" #include "server-tls-manager.h" -#include "extensions/extensions.h" /* Renaming */ +#include "extensions/extensions.h" /* IRCCommand */ #define DEFAULT_KEEPALIVE_INTERVAL 30 /* sec */ #define MISSED_KEEPALIVES_BEFORE_DISCONNECTING 3 @@ -64,12 +65,14 @@ static void _free_alias_pair(gpointer data, gpointer user_data) static void _aliasing_iface_init(gpointer, gpointer); static void _renaming_iface_init(gpointer, gpointer); +static void irc_command_iface_init(gpointer, gpointer); G_DEFINE_TYPE_WITH_CODE(IdleConnection, idle_connection, TP_TYPE_BASE_CONNECTION, G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING, _aliasing_iface_init); G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACT_INFO, idle_contact_info_iface_init); - G_IMPLEMENT_INTERFACE(IDLE_TYPE_SVC_CONNECTION_INTERFACE_RENAMING, _renaming_iface_init); + G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_RENAMING, _renaming_iface_init); G_IMPLEMENT_INTERFACE(TP_TYPE_SVC_CONNECTION_INTERFACE_CONTACTS, tp_contacts_mixin_iface_init); + G_IMPLEMENT_INTERFACE(IDLE_TYPE_SVC_CONNECTION_INTERFACE_IRC_COMMAND1, irc_command_iface_init); ); typedef struct _IdleOutputPendingMsg IdleOutputPendingMsg; @@ -449,7 +452,7 @@ static void idle_connection_finalize (GObject *object) { static const gchar * interfaces_always_present[] = { TP_IFACE_CONNECTION_INTERFACE_ALIASING, TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, - IDLE_IFACE_CONNECTION_INTERFACE_RENAMING, + TP_IFACE_CONNECTION_INTERFACE_RENAMING, TP_IFACE_CONNECTION_INTERFACE_REQUESTS, TP_IFACE_CONNECTION_INTERFACE_CONTACTS, NULL}; @@ -489,7 +492,6 @@ static void idle_connection_class_init(IdleConnectionClass *klass) { parent_class->create_handle_repos = _iface_create_handle_repos; parent_class->get_unique_connection_name = _iface_get_unique_connection_name; - parent_class->create_channel_factories = NULL; parent_class->create_channel_managers = _iface_create_channel_managers; parent_class->connecting = NULL; parent_class->connected = NULL; @@ -566,7 +568,7 @@ static GPtrArray *_iface_create_channel_managers(TpBaseConnection *base) { } static void _iface_create_handle_repos(TpBaseConnection *self, TpHandleRepoIface **repos) { - for (int i = 0; i < NUM_TP_HANDLE_TYPES; i++) + for (int i = 0; i < TP_NUM_HANDLE_TYPES; i++) repos[i] = NULL; idle_handle_repos_init(repos); @@ -1085,7 +1087,7 @@ static IdleParserHandlerResult _nick_handler(IdleParser *parser, IdleParserMessa tp_base_connection_set_self_handle(TP_BASE_CONNECTION(conn), new_handle); } - idle_svc_connection_interface_renaming_emit_renamed(IDLE_SVC_CONNECTION_INTERFACE_RENAMING(conn), old_handle, new_handle); + tp_svc_connection_interface_renaming_emit_renamed(conn, old_handle, new_handle); idle_connection_emit_queued_aliases_changed(conn); @@ -1433,11 +1435,15 @@ static gboolean _send_rename_request(IdleConnection *obj, const gchar *nick, DBu return TRUE; } -static void idle_connection_request_rename(IdleSvcConnectionInterfaceRenaming *iface, const gchar *nick, DBusGMethodInvocation *context) { +static void +idle_connection_request_rename (TpSvcConnectionInterfaceRenaming *iface, + const gchar *nick, + DBusGMethodInvocation *context) +{ IdleConnection *conn = IDLE_CONNECTION(iface); if (_send_rename_request(conn, nick, context)) - idle_svc_connection_interface_renaming_return_from_request_rename(context); + tp_svc_connection_interface_renaming_return_from_request_rename(context); } static void idle_connection_set_aliases(TpSvcConnectionInterfaceAliasing *iface, GHashTable *aliases, DBusGMethodInvocation *context) { @@ -1563,11 +1569,86 @@ static void _aliasing_iface_init(gpointer g_iface, gpointer iface_data) { } static void _renaming_iface_init(gpointer g_iface, gpointer iface_data) { - IdleSvcConnectionInterfaceRenamingClass *klass = (IdleSvcConnectionInterfaceRenamingClass *) g_iface; + TpSvcConnectionInterfaceRenamingClass *klass = g_iface; -#define IMPLEMENT(x) idle_svc_connection_interface_renaming_implement_##x (\ +#define IMPLEMENT(x) tp_svc_connection_interface_renaming_implement_##x (\ klass, idle_connection_##x) IMPLEMENT(request_rename); #undef IMPLEMENT } +typedef struct +{ + const gchar *command; + const gchar *error_msg; +} IrcCommandCheck; + +static const IrcCommandCheck commands[] = { + { "INVITE", "Use the Group API on room channels" }, + { "JOIN", "Use the Group API on room channels" }, + { "KICK", "Use the Group API on room channels" }, + { "PART", "Use the Group API on room channels" }, + { "PRIVMSG", "Use text channels" }, + { "QUIT", "Disconnect the connection" }, + { "TOPIC", "Use the Subject API on room channels" }, + { NULL, NULL } +}; + +/* Return FALSE and set @error if @command is not meant to be used with + * IRC_Command.Send() as we have proper Telepathy API for it. */ +static gboolean +check_irc_command (IdleConnection *self, + const gchar *full_command, + GError **error) +{ + gchar **splitted; + guint i; + + splitted = g_strsplit (full_command, " ", 0); + + for (i = 0; commands[i].command != NULL; i++) + { + if (g_ascii_strcasecmp (splitted[0], commands[i].command) == 0) + { + g_set_error_literal (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT, + commands[i].error_msg); + + g_strfreev (splitted); + return FALSE; + } + } + + g_strfreev (splitted); + return TRUE; +} + +static void +idle_connection_irc_command_send (IdleSvcConnectionInterfaceIRCCommand1 *iface, + const gchar *command, + DBusGMethodInvocation *context) +{ + IdleConnection *self = IDLE_CONNECTION(iface); + GError *error = NULL; + + if (!check_irc_command (self, command, &error)) + { + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + + _send_with_priority (self, command, SERVER_CMD_NORMAL_PRIORITY); + + dbus_g_method_return (context); +} + +static void irc_command_iface_init(gpointer g_iface, + gpointer iface_data) +{ + IdleSvcConnectionInterfaceIRCCommand1Class *klass = g_iface; + +#define IMPLEMENT(x) idle_svc_connection_interface_irc_command1_implement_##x (\ + klass, idle_connection_irc_command_##x) + IMPLEMENT(send); +#undef IMPLEMENT +} diff --git a/src/idle-contact-info.c b/src/idle-contact-info.c index b056510..07cd9a9 100644 --- a/src/idle-contact-info.c +++ b/src/idle-contact-info.c @@ -20,6 +20,8 @@ #include "config.h" #include "idle-contact-info.h" +#include <telepathy-glib/telepathy-glib-dbus.h> + #define IDLE_DEBUG_FLAG IDLE_DEBUG_CONNECTION #include "idle-debug.h" #include "idle-muc-channel.h" diff --git a/src/idle-im-channel.c b/src/idle-im-channel.c index 04773d5..1449a9c 100644 --- a/src/idle-im-channel.c +++ b/src/idle-im-channel.c @@ -23,6 +23,7 @@ #include "idle-im-channel.h" #include <dbus/dbus-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #define IDLE_DEBUG_FLAG IDLE_DEBUG_IM #include "idle-connection.h" diff --git a/src/idle-im-manager.c b/src/idle-im-manager.c index ab15713..914306b 100644 --- a/src/idle-im-manager.c +++ b/src/idle-im-manager.c @@ -23,6 +23,7 @@ #include "idle-im-manager.h" #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #define IDLE_DEBUG_FLAG IDLE_DEBUG_IM #include "idle-connection.h" diff --git a/src/idle-muc-channel.c b/src/idle-muc-channel.c index bc864bf..c335efa 100644 --- a/src/idle-muc-channel.c +++ b/src/idle-muc-channel.c @@ -30,6 +30,7 @@ #include <dbus/dbus-glib.h> #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #define IDLE_DEBUG_FLAG IDLE_DEBUG_MUC #include "idle-connection.h" @@ -817,11 +818,7 @@ void idle_muc_channel_namereply(IdleMUCChannel *chan, GValueArray *args) { for (guint i = 1; (i + 1) < args->n_values; i += 2) { TpHandle handle = g_value_get_uint(g_value_array_get_nth(args, i)); -#if GLIB_CHECK_VERSION(2, 31, 0) gchar modechar = g_value_get_schar(g_value_array_get_nth(args, i + 1)); -#else - gchar modechar = g_value_get_char(g_value_array_get_nth(args, i + 1)); -#endif if (handle == tp_base_connection_get_self_handle (base_conn)) { guint remove = MODE_FLAG_OPERATOR_PRIVILEGE | MODE_FLAG_VOICE_PRIVILEGE | MODE_FLAG_HALFOP_PRIVILEGE; diff --git a/src/idle-muc-manager.c b/src/idle-muc-manager.c index b5909f0..28e4fc3 100644 --- a/src/idle-muc-manager.c +++ b/src/idle-muc-manager.c @@ -25,6 +25,7 @@ #include <time.h> #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #define IDLE_DEBUG_FLAG IDLE_DEBUG_MUC #include "idle-connection.h" diff --git a/src/idle-parser.c b/src/idle-parser.c index b0cab94..ec454ec 100644 --- a/src/idle-parser.c +++ b/src/idle-parser.c @@ -563,11 +563,7 @@ static gboolean _parse_atom(IdleParser *parser, GValueArray *arr, char atom, con if (atom == 'C') { g_value_init(&val, G_TYPE_CHAR); -#if GLIB_CHECK_VERSION(2, 31, 0) g_value_set_schar(&val, modechar); -#else - g_value_set_char(&val, modechar); -#endif g_value_array_append(arr, &val); g_value_unset(&val); diff --git a/src/idle-roomlist-channel.c b/src/idle-roomlist-channel.c index 183e696..9fa15d2 100644 --- a/src/idle-roomlist-channel.c +++ b/src/idle-roomlist-channel.c @@ -26,6 +26,7 @@ #include <time.h> #include <dbus/dbus-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #define IDLE_DEBUG_FLAG IDLE_DEBUG_ROOMLIST #include "idle-connection.h" diff --git a/src/idle-roomlist-manager.c b/src/idle-roomlist-manager.c index 1ce4652..970529b 100644 --- a/src/idle-roomlist-manager.c +++ b/src/idle-roomlist-manager.c @@ -24,6 +24,7 @@ #include "idle-roomlist-manager.h" #include <telepathy-glib/telepathy-glib.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #define IDLE_DEBUG_FLAG IDLE_DEBUG_ROOMLIST #include "idle-connection.h" diff --git a/src/idle-text.c b/src/idle-text.c index dbda8b0..cce38c8 100644 --- a/src/idle-text.c +++ b/src/idle-text.c @@ -179,7 +179,7 @@ void idle_text_send(GObject *obj, TpMessage *message, TpMessageSendingFlags flag if (!result) INVALID_ARGUMENT ("message-type must be a 32-bit unsigned integer"); - if (type >= NUM_TP_CHANNEL_TEXT_MESSAGE_TYPES) + if (type >= TP_NUM_CHANNEL_TEXT_MESSAGE_TYPES) INVALID_ARGUMENT ("invalid message type: %u", type); n_parts = tp_message_count_parts (message); diff --git a/src/protocol.c b/src/protocol.c index b6ba690..8e5a2cc 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -23,6 +23,7 @@ #include <dbus/dbus-glib.h> #include <dbus/dbus-protocol.h> +#include <telepathy-glib/telepathy-glib-dbus.h> #include "idle-connection.h" #include "idle-handles.h" diff --git a/src/tls-certificate.c b/src/tls-certificate.c index 467d13e..3d71be1 100644 --- a/src/tls-certificate.c +++ b/src/tls-certificate.c @@ -216,7 +216,7 @@ idle_tls_certificate_class_init (IdleTLSCertificateClass *klass) pspec = g_param_spec_uint ("state", "State of this certificate", "The state of this TLS certificate.", - 0, NUM_TP_TLS_CERTIFICATE_STATES - 1, + 0, TP_NUM_TLS_CERTIFICATE_STATES - 1, TP_TLS_CERTIFICATE_STATE_PENDING, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_property (oclass, PROP_STATE, pspec); diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am index 732f98d..1e16f95 100644 --- a/tests/twisted/Makefile.am +++ b/tests/twisted/Makefile.am @@ -23,6 +23,7 @@ TWISTED_TESTS = \ channels/muc-destroy.py \ channels/room-list-channel.py \ channels/room-list-multiple.py \ + irc-command.py \ messages/accept-invalid-nicks.py \ messages/contactinfo-request.py \ messages/messages-iface.py \ diff --git a/tests/twisted/channels/join-muc-channel-bouncer.py b/tests/twisted/channels/join-muc-channel-bouncer.py index e2e85fb..11f84d5 100644 --- a/tests/twisted/channels/join-muc-channel-bouncer.py +++ b/tests/twisted/channels/join-muc-channel-bouncer.py @@ -10,7 +10,6 @@ from servicetest import ( from constants import * def test_join_bouncer(q, conn, stream, room): - room_handles = conn.RequestHandles(HT_ROOM, [room]) stream.sendJoin(room) new_channels = EventPattern('dbus-signal', signal='NewChannels') @@ -20,19 +19,11 @@ def test_join_bouncer(q, conn, stream, room): assertEquals(1, len(channel_details)) path, props = channel_details[0] assertEquals(HT_ROOM, props[TARGET_HANDLE_TYPE]) - assertEquals(room_handles[0], props[TARGET_HANDLE]) assertEquals(CHANNEL_TYPE_TEXT, props[CHANNEL_TYPE]) - new_channel = EventPattern('dbus-signal', signal='NewChannel') - event = q.expect_many(new_channel)[0] - q.forbid_events([new_channel]) - assertEquals(CHANNEL_TYPE_TEXT, event.args[1]) - assertEquals(HT_ROOM, event.args[2]) - assertEquals(room_handles[0], event.args[3]) - q.expect('dbus-signal', signal='MembersChanged') - q.unforbid_events([new_channels, new_channel]) + q.unforbid_events([new_channels]) return path def test(q, bus, conn, stream): @@ -46,7 +37,7 @@ def test(q, bus, conn, stream): CHANNEL_NAME = "#idletest" - self_handle = conn.GetSelfHandle() + self_handle = conn.Get(CONN, 'SelfHandle', dbus_interface=PROPERTIES_IFACE) # The bouncer initiates a JOIN. path = test_join_bouncer(q, conn, stream, CHANNEL_NAME) diff --git a/tests/twisted/channels/join-muc-channel.py b/tests/twisted/channels/join-muc-channel.py index 2ea9d28..19f3fc6 100644 --- a/tests/twisted/channels/join-muc-channel.py +++ b/tests/twisted/channels/join-muc-channel.py @@ -16,10 +16,13 @@ def test(q, bus, conn, stream): q.expect('dbus-signal', signal='SelfHandleChanged', args=[1]) q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) - room_handles = conn.RequestHandles(HT_ROOM, ['#idletest']) - call_async(q, conn, 'RequestChannel', CHANNEL_TYPE_TEXT, HT_ROOM, room_handles[0], True) + call_async(q, conn.Requests, 'CreateChannel', + { CHANNEL_TYPE: CHANNEL_TYPE_TEXT, + TARGET_HANDLE_TYPE: HT_ROOM, + TARGET_ID: '#idletest' }) + q.expect('stream-JOIN') - event = q.expect('dbus-return', method='RequestChannel') + event = q.expect('dbus-return', method='CreateChannel') obj_path = event.value[0] pattern = EventPattern('dbus-signal', signal='NewChannels') @@ -30,17 +33,8 @@ def test(q, bus, conn, stream): path, props = channel_details[0] assert path == obj_path assert props[TARGET_HANDLE_TYPE] == HT_ROOM - assert props[TARGET_HANDLE] == room_handles[0] assert props[CHANNEL_TYPE] == CHANNEL_TYPE_TEXT - pattern = EventPattern('dbus-signal', signal='NewChannel') - event = q.expect_many(pattern)[0] - q.forbid_events([pattern]) - assert event.args[0] == obj_path - assert event.args[1] == CHANNEL_TYPE_TEXT - assert event.args[2] == HT_ROOM - assert event.args[3] == room_handles[0] - q.expect('dbus-signal', signal='MembersChanged') call_async(q, conn, 'Disconnect') q.expect_many( diff --git a/tests/twisted/channels/muc-channel-topic.py b/tests/twisted/channels/muc-channel-topic.py index 58accb1..ec3b438 100644 --- a/tests/twisted/channels/muc-channel-topic.py +++ b/tests/twisted/channels/muc-channel-topic.py @@ -68,7 +68,7 @@ def test(q, bus, conn, stream): q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) - alice_handle, bob_handle = conn.RequestHandles(HT_CONTACT, ['alice', 'bob']) + alice_handle, bob_handle = conn.get_contact_handles_sync(['alice', 'bob']) call_async(q, conn.Requests, 'CreateChannel', { CHANNEL_TYPE: CHANNEL_TYPE_TEXT, diff --git a/tests/twisted/channels/requests-create.py b/tests/twisted/channels/requests-create.py index e3adb64..957560e 100644 --- a/tests/twisted/channels/requests-create.py +++ b/tests/twisted/channels/requests-create.py @@ -15,14 +15,12 @@ def test(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[0,1]) - ifs = conn.GetInterfaces() + props = conn.GetAll(cs.CONN, dbus_interface=cs.PROPERTIES_IFACE) - assert cs.CONN_IFACE_REQUESTS in ifs + assertContains(cs.CONN_IFACE_REQUESTS, props['Interfaces']) nick = 'foo' - call_async(q, conn, 'RequestHandles', cs.HT_CONTACT, [nick]) - event = q.expect('dbus-return', method='RequestHandles') - foo_handle = event.value[0][0] + foo_handle = conn.get_contact_handle_sync(nick) properties = conn.GetAll(cs.CONN_IFACE_REQUESTS, dbus_interface=cs.PROPERTIES_IFACE) @@ -41,9 +39,8 @@ def test(q, bus, conn, stream): } call_async(q, requestotron, 'CreateChannel', request) - ret, old_sig, new_sig = q.expect_many( + ret, new_sig = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), - EventPattern('dbus-signal', signal='NewChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) @@ -54,15 +51,9 @@ def test(q, bus, conn, stream): assert emitted_props[cs.TARGET_HANDLE] == foo_handle assert emitted_props[cs.TARGET_ID] == nick assert emitted_props[cs.REQUESTED] - assert emitted_props[cs.INITIATOR_HANDLE] == conn.GetSelfHandle() + assert emitted_props[cs.INITIATOR_HANDLE] == props['SelfHandle'] assert emitted_props[cs.INITIATOR_ID] == stream.nick - assert old_sig.args[0] == ret.value[0] - assert old_sig.args[1] == cs.CHANNEL_TYPE_TEXT - assert old_sig.args[2] == cs.HT_CONTACT - assert old_sig.args[3] == foo_handle - assert old_sig.args[4] == True # suppress handler - assert len(new_sig.args) == 1 assert len(new_sig.args[0]) == 1 # one channel assert len(new_sig.args[0][0]) == 2 # two struct members diff --git a/tests/twisted/channels/requests-muc.py b/tests/twisted/channels/requests-muc.py index b54091c..7286ab1 100644 --- a/tests/twisted/channels/requests-muc.py +++ b/tests/twisted/channels/requests-muc.py @@ -55,7 +55,7 @@ def test(q, bus, conn, stream, use_room=False): q.expect('dbus-signal', signal='SelfHandleChanged') q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) - self_handle = conn.GetSelfHandle() + self_handle = conn.Get(cs.CONN, 'SelfHandle', dbus_interface=cs.PROPERTIES_IFACE) request = build_request(conn, '#idletest', use_room) call_async(q, conn.Requests, 'CreateChannel', request) @@ -95,12 +95,10 @@ def test(q, bus, conn, stream, use_room=False): assert props[cs.TARGET_ID] == '#idletest' assertEquals('#idletest', props[cs.ROOM_NAME]) assertEquals('', props[cs.ROOM_SERVER]) - assert props[cs.TARGET_HANDLE] == \ - conn.RequestHandles(cs.HT_ROOM, ['#idletest'])[0] assert props[cs.REQUESTED] assert props[cs.INITIATOR_HANDLE] == self_handle assert props[cs.INITIATOR_ID] == \ - conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0] + conn.inspect_contacts_sync([self_handle])[0] ec_yours, ec_path, ec_props = ec.value assert not ec_yours diff --git a/tests/twisted/channels/room-list-channel.py b/tests/twisted/channels/room-list-channel.py index 0907f54..43ed783 100644 --- a/tests/twisted/channels/room-list-channel.py +++ b/tests/twisted/channels/room-list-channel.py @@ -65,7 +65,7 @@ def test(q, bus, conn, stream): predicate=looks_like_a_room_list) chan = bus.get_object(conn.bus_name, path) - list_chan = dbus.Interface(chan, tp_name_prefix + '.Channel.Type.RoomList') + list_chan = dbus.Interface(chan, cs.CHANNEL_TYPE_ROOM_LIST) list_chan.ListRooms(); q.expect('dbus-signal', signal='GotRooms', predicate=lambda x:check_rooms(x.args[0])) diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py index eae149b..e21bc13 100644 --- a/tests/twisted/constants.py +++ b/tests/twisted/constants.py @@ -1,10 +1,34 @@ +# Copyright (C) 2009 Nokia Corporation +# Copyright (C) 2009-2013 Collabora Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + """ Some handy constants for other tests to share and enjoy. """ -from dbus import PROPERTIES_IFACE +from dbus import PROPERTIES_IFACE, INTROSPECTABLE_IFACE + +PREFIX = "org.freedesktop.Telepathy" +PATH_PREFIX = '/' + PREFIX.replace('.', '/') + +tp_name_prefix = PREFIX +tp_path_prefix = PATH_PREFIX -CM = "org.freedesktop.Telepathy.ConnectionManager" +CM = PREFIX + ".ConnectionManager" HT_NONE = 0 HT_CONTACT = 1 @@ -12,40 +36,42 @@ HT_ROOM = 2 HT_LIST = 3 HT_GROUP = 4 -CHANNEL = "org.freedesktop.Telepathy.Channel" +CHANNEL = PREFIX + ".Channel" CHANNEL_IFACE_CALL_STATE = CHANNEL + ".Interface.CallState" CHANNEL_IFACE_CHAT_STATE = CHANNEL + '.Interface.ChatState' CHANNEL_IFACE_DESTROYABLE = CHANNEL + ".Interface.Destroyable" +CHANNEL_IFACE_DTMF = CHANNEL + ".Interface.DTMF" CHANNEL_IFACE_GROUP = CHANNEL + ".Interface.Group" CHANNEL_IFACE_HOLD = CHANNEL + ".Interface.Hold" CHANNEL_IFACE_MEDIA_SIGNALLING = CHANNEL + ".Interface.MediaSignalling" CHANNEL_IFACE_MESSAGES = CHANNEL + ".Interface.Messages" CHANNEL_IFACE_PASSWORD = CHANNEL + ".Interface.Password" CHANNEL_IFACE_TUBE = CHANNEL + ".Interface.Tube" -CHANNEL_IFACE_SASL_AUTH = CHANNEL + ".Interface.SaslAuthentication.DRAFT" +CHANNEL_IFACE_SASL_AUTH = CHANNEL + ".Interface.SASLAuthentication" CHANNEL_IFACE_CONFERENCE = CHANNEL + '.Interface.Conference' CHANNEL_IFACE_ROOM = CHANNEL + '.Interface.Room2' CHANNEL_IFACE_ROOM_CONFIG = CHANNEL + '.Interface.RoomConfig1' CHANNEL_IFACE_SUBJECT = CHANNEL + '.Interface.Subject2' +CHANNEL_IFACE_FILE_TRANSFER_METADATA = CHANNEL + '.Interface.FileTransfer.Metadata' +CHANNEL_IFACE_SMS = CHANNEL + '.Interface.SMS' -CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call.DRAFT" +CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call1" CHANNEL_TYPE_CONTACT_LIST = CHANNEL + ".Type.ContactList" CHANNEL_TYPE_CONTACT_SEARCH = CHANNEL + ".Type.ContactSearch" CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text" CHANNEL_TYPE_TUBES = CHANNEL + ".Type.Tubes" CHANNEL_TYPE_STREAM_TUBE = CHANNEL + ".Type.StreamTube" CHANNEL_TYPE_DBUS_TUBE = CHANNEL + ".Type.DBusTube" -CHANNEL_TYPE_STREAMED_MEDIA = CHANNEL + ".Type.StreamedMedia" CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text" CHANNEL_TYPE_FILE_TRANSFER = CHANNEL + ".Type.FileTransfer" CHANNEL_TYPE_ROOM_LIST = CHANNEL + ".Type.RoomList" CHANNEL_TYPE_SERVER_AUTHENTICATION = \ - CHANNEL + ".Type.ServerAuthentication.DRAFT" + CHANNEL + ".Type.ServerAuthentication" CHANNEL_TYPE_SERVER_TLS_CONNECTION = \ CHANNEL + ".Type.ServerTLSConnection" -TP_AWKWARD_PROPERTIES = "org.freedesktop.Telepathy.Properties" +TP_AWKWARD_PROPERTIES = PREFIX + ".Properties" PROPERTY_FLAG_READ = 1 PROPERTY_FLAG_WRITE = 2 PROPERTY_FLAGS_RW = PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE @@ -59,53 +85,105 @@ INITIATOR_HANDLE = CHANNEL + '.InitiatorHandle' INITIATOR_ID = CHANNEL + '.InitiatorID' INTERFACES = CHANNEL + '.Interfaces' -ROOM_NAME = CHANNEL_IFACE_ROOM + '.RoomName' -ROOM_SERVER = CHANNEL_IFACE_ROOM + '.Server' - -INITIAL_AUDIO = CHANNEL_TYPE_STREAMED_MEDIA + '.InitialAudio' -INITIAL_VIDEO = CHANNEL_TYPE_STREAMED_MEDIA + '.InitialVideo' -IMMUTABLE_STREAMS = CHANNEL_TYPE_STREAMED_MEDIA + '.ImmutableStreams' - +CALL_CONTENTS = CHANNEL_TYPE_CALL + '.Contents' +CALL_CALL_STATE_DETAILS = CHANNEL_TYPE_CALL + '.CallStateDetails' +CALL_CALL_STATE = CHANNEL_TYPE_CALL + '.CallState' +CALL_CALL_FLAGS = CHANNEL_TYPE_CALL + '.CallFlags' +CALL_CALL_STATE_REASON = CHANNEL_TYPE_CALL + '.CallStateReason' +CALL_HARDWARE_STREAMING = CHANNEL_TYPE_CALL + '.HardwareStreaming' +CALL_CALL_MEMBERS = CHANNEL_TYPE_CALL + '.CallMembers' +CALL_MEMBER_IDENTIFIERS = CHANNEL_TYPE_CALL + '.MemberIdentifiers' +CALL_INITIAL_TRANSPORT = CHANNEL_TYPE_CALL + '.InitialTransport' CALL_INITIAL_AUDIO = CHANNEL_TYPE_CALL + '.InitialAudio' +CALL_INITIAL_AUDIO_NAME = CHANNEL_TYPE_CALL + '.InitialAudioName' CALL_INITIAL_VIDEO = CHANNEL_TYPE_CALL + '.InitialVideo' +CALL_INITIAL_VIDEO_NAME = CHANNEL_TYPE_CALL + '.InitialVideoName' CALL_MUTABLE_CONTENTS = CHANNEL_TYPE_CALL + '.MutableContents' -CALL_CONTENT = 'org.freedesktop.Telepathy.Call.Content.DRAFT' -CALL_CONTENT_IFACE_MEDIA = \ - 'org.freedesktop.Telepathy.Call.Content.Interface.Media.DRAFT' +CALL_CONTENT = PREFIX + '.Call1.Content' +CALL_CONTENT_IFACE_MEDIA = CALL_CONTENT + '.Interface.Media' +CALL_CONTENT_IFACE_DTMF = CALL_CONTENT + '.Interface.DTMF' -CALL_CONTENT_CODECOFFER = \ - 'org.freedesktop.Telepathy.Call.Content.CodecOffer.DRAFT' +CALL_CONTENT_MEDIA_DESCRIPTION = CALL_CONTENT + '.MediaDescription' -CALL_STREAM = 'org.freedesktop.Telepathy.Call.Stream.DRAFT' -CALL_STREAM_IFACE_MEDIA = \ - 'org.freedesktop.Telepathy.Call.Stream.Interface.Media.DRAFT' +CALL_STREAM = PREFIX + '.Call1.Stream' +CALL_STREAM_IFACE_MEDIA = CALL_STREAM + '.Interface.Media' -CALL_STREAM_ENDPOINT = 'org.freedesktop.Telepathy.Call.Stream.Endpoint.DRAFT' +CALL_STREAM_ENDPOINT = CALL_STREAM + '.Endpoint' CALL_MEDIA_TYPE_AUDIO = 0 CALL_MEDIA_TYPE_VIDEO = 1 -CALL_STREAM_TRANSPORT_RAW_UDP = 0 -CALL_STREAM_TRANSPORT_ICE = 1 -CALL_STREAM_TRANSPORT_GOOGLE = 2 +CALL_CONTENT_PACKETIZATION_RTP = 0 +CALL_CONTENT_PACKETIZATION_RAW = 1 +CALL_CONTENT_PACKETIZATION_MSN_WEBCAM = 2 + +CALL_STREAM_TRANSPORT_UNKNOWN = 0 +CALL_STREAM_TRANSPORT_RAW_UDP = 1 +CALL_STREAM_TRANSPORT_ICE = 2 +CALL_STREAM_TRANSPORT_GTALK_P2P = 3 +CALL_STREAM_TRANSPORT_WLM_2009 = 4 +CALL_STREAM_TRANSPORT_SHM = 5 +CALL_STREAM_TRANSPORT_MULTICAST = 6 CALL_STATE_UNKNOWN = 0 CALL_STATE_PENDING_INITIATOR = 1 -CALL_STATE_PENDING_RECEIVER = 2 -CALL_STATE_ACCEPTED = 3 -CALL_STATE_ENDED = 4 +CALL_STATE_INITIALISING = 2 +CALL_STATE_INITIALISED = 3 +CALL_STATE_ACCEPTED = 4 +CALL_STATE_ACTIVE = 5 +CALL_STATE_ENDED = 6 + +CALL_FLAG_LOCALLY_HELD = 1 +CALL_FLAG_LOCALLY_RINGING = 2 +CALL_FLAG_LOCALLY_QUEUED = 4 +CALL_FLAG_FORWARDED = 8 +CALL_FLAG_CLEARING = 16 CALL_MEMBER_FLAG_RINGING = 1 CALL_MEMBER_FLAG_HELD = 2 CALL_DISPOSITION_NONE = 0 -CALL_DISPOSITION_EARLY_MEDIA = 1 -CALL_DISPOSITION_INITIAL = 2 +CALL_DISPOSITION_INITIAL = 1 CALL_SENDING_STATE_NONE = 0 CALL_SENDING_STATE_PENDING_SEND = 1 CALL_SENDING_STATE_SENDING = 2 +CALL_SENDING_STATE_PENDING_STOP_SENDING = 3 + +CALL_STREAM_FLOW_STATE_STOPPED = 0 +CALL_STREAM_FLOW_STATE_PENDING_START = 1 +CALL_STREAM_FLOW_STATE_PENDING_STOP = 2 +CALL_STREAM_FLOW_STATE_STARTED = 3 + +CALL_STREAM_ENDPOINT_STATE_CONNECTING = 0 +CALL_STREAM_ENDPOINT_STATE_PROVISIONALLY_CONNECTED = 1 +CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED = 2 +CALL_STREAM_ENDPOINT_STATE_EXHAUSTED_CANDIDATES = 3 +CALL_STREAM_ENDPOINT_STATE_FAILED = 4 + +CALL_STREAM_CANDIDATE_TYPE_HOST = 1 +CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE = 2 +CALL_STREAM_CANDIDATE_TYPE_RELAY = 4 + +CALL_STATE_CHANGE_REASON_UNKNOWN = 0 +CALL_STATE_CHANGE_REASON_PROGRESS_MADE = 1 +CALL_STATE_CHANGE_REASON_USER_REQUESTED = 2 +CALL_STATE_CHANGE_REASON_FORWARDED = 3 +CALL_STATE_CHANGE_REASON_REJECTED = 4 +CALL_STATE_CHANGE_REASON_NO_ANSWER = 5 +CALL_STATE_CHANGE_REASON_INVALID_CONTACT = 6 +CALL_STATE_CHANGE_REASON_PERMISSION_DENIED = 7 +CALL_STATE_CHANGE_REASON_BUSY = 8 +CALL_STATE_CHANGE_REASON_INTERNAL_ERROR = 9 +CALL_STATE_CHANGE_REASON_SERVICE_ERROR = 10 +CALL_STATE_CHANGE_REASON_NETWORK_ERROR = 11 +CALL_STATE_CHANGE_REASON_MEDIA_ERROR = 12 +CALL_STATE_CHANGE_REASON_CONNECTIVITY_ERROR = 13 + +CALL_STREAM_COMPONENT_UNKNOWN = 0 +CALL_STREAM_COMPONENT_DATA = 1 +CALL_STREAM_COMPONENT_CONTROL = 2 SUBSCRIPTION_STATE_UNKNOWN = 0 SUBSCRIPTION_STATE_NO = 1 @@ -118,7 +196,7 @@ CONTACT_LIST_STATE_WAITING = 1 CONTACT_LIST_STATE_FAILURE = 2 CONTACT_LIST_STATE_SUCCESS = 3 -CONN = "org.freedesktop.Telepathy.Connection" +CONN = PREFIX + ".Connection" CONN_IFACE_AVATARS = CONN + '.Interface.Avatars' CONN_IFACE_ALIASING = CONN + '.Interface.Aliasing' CONN_IFACE_CAPS = CONN + '.Interface.Capabilities' @@ -126,19 +204,36 @@ CONN_IFACE_CONTACTS = CONN + '.Interface.Contacts' CONN_IFACE_CONTACT_CAPS = CONN + '.Interface.ContactCapabilities' CONN_IFACE_CONTACT_INFO = CONN + ".Interface.ContactInfo" CONN_IFACE_PRESENCE = CONN + '.Interface.Presence' +CONN_IFACE_RENAMING = CONN + '.Interface.Renaming' +CONN_IFACE_SIDECARS1 = CONN + '.Interface.Sidecars1' CONN_IFACE_SIMPLE_PRESENCE = CONN + '.Interface.SimplePresence' CONN_IFACE_REQUESTS = CONN + '.Interface.Requests' CONN_IFACE_LOCATION = CONN + '.Interface.Location' CONN_IFACE_GABBLE_DECLOAK = CONN + '.Interface.Gabble.Decloak' -CONN_IFACE_MAIL_NOTIFICATION = CONN + '.Interface.MailNotification.DRAFT' +CONN_IFACE_MAIL_NOTIFICATION = CONN + '.Interface.MailNotification' CONN_IFACE_CONTACT_LIST = CONN + '.Interface.ContactList' CONN_IFACE_CONTACT_GROUPS = CONN + '.Interface.ContactGroups' - +CONN_IFACE_CLIENT_TYPES = CONN + '.Interface.ClientTypes' +CONN_IFACE_POWER_SAVING = CONN + '.Interface.PowerSaving' +CONN_IFACE_CONTACT_BLOCKING = CONN + '.Interface.ContactBlocking' +CONN_IFACE_ADDRESSING = CONN + '.Interface.Addressing1' +CONN_IFACE_SERVICE_POINT = CONN + '.Interface.ServicePoint' + +ATTR_ALIAS = CONN_IFACE_ALIASING + '/alias' +ATTR_AVATAR_TOKEN = CONN_IFACE_AVATARS + '/token' +ATTR_CLIENT_TYPES = CONN_IFACE_CLIENT_TYPES + '/client-types' ATTR_CONTACT_CAPABILITIES = CONN_IFACE_CONTACT_CAPS + '/capabilities' +ATTR_CONTACT_ID = CONN + '/contact-id' +ATTR_CONTACT_INFO = CONN_IFACE_CONTACT_INFO + '/info' +ATTR_GROUPS = CONN_IFACE_CONTACT_GROUPS + '/groups' +ATTR_LOCATION = CONN_IFACE_LOCATION + '/location' +ATTR_PRESENCE = CONN_IFACE_SIMPLE_PRESENCE + '/presence' +ATTR_PUBLISH = CONN_IFACE_CONTACT_LIST + '/publish' +ATTR_SUBSCRIBE = CONN_IFACE_CONTACT_LIST + '/subscribe' -STREAM_HANDLER = 'org.freedesktop.Telepathy.Media.StreamHandler' +STREAM_HANDLER = PREFIX + '.Media.StreamHandler' -ERROR = 'org.freedesktop.Telepathy.Error' +ERROR = PREFIX + '.Error' INVALID_ARGUMENT = ERROR + '.InvalidArgument' NOT_IMPLEMENTED = ERROR + '.NotImplemented' NOT_AVAILABLE = ERROR + '.NotAvailable' @@ -149,9 +244,9 @@ CONNECTION_REFUSED = ERROR + '.ConnectionRefused' CONNECTION_FAILED = ERROR + '.ConnectionFailed' CONNECTION_LOST = ERROR + '.ConnectionLost' CANCELLED = ERROR + '.Cancelled' +NOT_YOURS = ERROR + '.NotYours' DISCONNECTED = ERROR + '.Disconnected' REGISTRATION_EXISTS = ERROR + '.RegistrationExists' -SERVICE_BUSY = ERROR + '.ServiceBusy' AUTHENTICATION_FAILED = ERROR + '.AuthenticationFailed' CONNECTION_REPLACED = ERROR + '.ConnectionReplaced' ALREADY_CONNECTED = ERROR + '.AlreadyConnected' @@ -159,8 +254,14 @@ NETWORK_ERROR = ERROR + '.NetworkError' NOT_YET = ERROR + '.NotYet' INVALID_HANDLE = ERROR + '.InvalidHandle' CERT_UNTRUSTED = ERROR + '.Cert.Untrusted' +SERVICE_BUSY = ERROR + '.ServiceBusy' +SERVICE_CONFUSED = ERROR + '.ServiceConfused' +SOFTWARE_UPGRADE_REQUIRED = ERROR + '.SoftwareUpgradeRequired' -UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod' +BANNED = ERROR + '.Channel.Banned' + +DBUS_ERROR_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod' +DBUS_ERROR_NO_REPLY = 'org.freedesktop.DBus.Error.NoReply' TUBE_PARAMETERS = CHANNEL_IFACE_TUBE + '.Parameters' TUBE_STATE = CHANNEL_IFACE_TUBE + '.State' @@ -192,6 +293,13 @@ TUBE_CHANNEL_STATE_NOT_OFFERED = 3 MEDIA_STREAM_TYPE_AUDIO = 0 MEDIA_STREAM_TYPE_VIDEO = 1 +MEDIA_STREAM_BASE_PROTO_UDP = 0 +MEDIA_STREAM_BASE_PROTO_TCP = 1 + +MEDIA_STREAM_TRANSPORT_TYPE_LOCAL = 0 +MEDIA_STREAM_TRANSPORT_TYPE_DERIVED = 1 +MEDIA_STREAM_TRANSPORT_TYPE_RELAY = 2 + SOCKET_ADDRESS_TYPE_UNIX = 0 SOCKET_ADDRESS_TYPE_ABSTRACT_UNIX = 1 SOCKET_ADDRESS_TYPE_IPV4 = 2 @@ -260,7 +368,10 @@ FT_DATE = CHANNEL_TYPE_FILE_TRANSFER + '.Date' FT_AVAILABLE_SOCKET_TYPES = CHANNEL_TYPE_FILE_TRANSFER + '.AvailableSocketTypes' FT_TRANSFERRED_BYTES = CHANNEL_TYPE_FILE_TRANSFER + '.TransferredBytes' FT_INITIAL_OFFSET = CHANNEL_TYPE_FILE_TRANSFER + '.InitialOffset' -FT_FILE_COLLECTION = CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE.FileCollection' +FT_FILE_COLLECTION = CHANNEL_TYPE_FILE_TRANSFER + '.FileCollection' +FT_URI = CHANNEL_TYPE_FILE_TRANSFER + '.URI' +FT_SERVICE_NAME = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.ServiceName' +FT_METADATA = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.Metadata' GF_CAN_ADD = 1 GF_CAN_REMOVE = 2 @@ -298,11 +409,6 @@ HSR_NONE = 0 HSR_REQUESTED = 1 HSR_RESOURCE_NOT_AVAILABLE = 2 -CALL_STATE_RINGING = 1 -CALL_STATE_QUEUED = 2 -CALL_STATE_HELD = 4 -CALL_STATE_FORWARDED = 8 - CONN_STATUS_CONNECTED = 0 CONN_STATUS_CONNECTING = 1 CONN_STATUS_DISCONNECTED = 2 @@ -339,8 +445,9 @@ MEDIA_CAP_GTALKP2P = 8 MEDIA_CAP_ICEUDP = 16 MEDIA_CAP_IMMUTABLE_STREAMS = 32 -CLIENT = 'org.freedesktop.Telepathy.Client' +CLIENT = PREFIX + '.Client' +PRESENCE_UNSET = 0 PRESENCE_OFFLINE = 1 PRESENCE_AVAILABLE = 2 PRESENCE_AWAY = 3 @@ -352,11 +459,8 @@ PRESENCE_ERROR = 8 CONTACT_INFO_FLAG_CAN_SET = 1 CONTACT_INFO_FLAG_PUSH = 2 -CONTACT_INFO_FIELD_FLAG_PARAMETERS_MANDATORY = 1 - -# Channel_Type_ServerAuthentication -AUTH_TYPE_SASL = 0 -AUTH_TYPE_CAPTCHA = 1 +CONTACT_INFO_FIELD_FLAG_PARAMETERS_EXACT = 1 +CONTACT_INFO_FIELD_FLAG_OVERWRITTEN_BY_NICKNAME = 2 # Channel_Interface_SaslAuthentication SASL_STATUS_NOT_STARTED = 0 @@ -371,12 +475,20 @@ SASL_ABORT_REASON_INVALID_CHALLENGE = 0 SASL_ABORT_REASON_USER_ABORT = 1 AUTH_METHOD = CHANNEL_TYPE_SERVER_AUTHENTICATION + ".AuthenticationMethod" -AUTH_INFO = CHANNEL_TYPE_SERVER_AUTHENTICATION + ".AuthenticationInformation" SASL_AVAILABLE_MECHANISMS = CHANNEL_IFACE_SASL_AUTH + ".AvailableMechanisms" +SASL_STATUS = CHANNEL_IFACE_SASL_AUTH + ".SASLStatus" +SASL_ERROR = CHANNEL_IFACE_SASL_AUTH + ".SASLError" +SASL_ERROR_DETAILS = CHANNEL_IFACE_SASL_AUTH + ".SASLErrorDetails" +SASL_CONTEXT = CHANNEL_IFACE_SASL_AUTH + ".SASLContext" +SASL_AUTHORIZATION_IDENTITY = CHANNEL_IFACE_SASL_AUTH + ".AuthorizationIdentity" +SASL_DEFAULT_REALM = CHANNEL_IFACE_SASL_AUTH + ".DefaultRealm" +SASL_DEFAULT_USERNAME = CHANNEL_IFACE_SASL_AUTH + ".DefaultUsername" # Channel_Type_ServerTLSConnection TLS_CERT_PATH = CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".ServerCertificate" TLS_HOSTNAME = CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".Hostname" +TLS_REFERENCE_IDENTITIES = \ + CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".ReferenceIdentities" # Connection.Interface.Location @@ -390,14 +502,32 @@ MT_NOTICE = 2 MT_AUTO_REPLY = 3 MT_DELIVERY_REPORT = 4 -PROTOCOL = 'org.freedesktop.Telepathy.Protocol' +class MessageFlag(object): + TRUNCATED = 1 + NON_TEXT_CONTENT = 2 + SCROLLBACK = 4 + RESCUED = 8 + +class SendError(object): + UNKNOWN = 0 + OFFLINE = 1 + INVALID_CONTACT = 2 + PERMISSION_DENIED = 3 + TOO_LONG = 4 + NOT_IMPLEMENTED = 5 + +PROTOCOL = PREFIX + '.Protocol' +PROTOCOL_IFACE_PRESENCES = PROTOCOL + '.Interface.Presence' +PROTOCOL_IFACE_ADDRESSING = PROTOCOL + '.Interface.Addressing' +PROTOCOL_IFACE_AVATARS = PROTOCOL + '.Interface.Avatars' + PARAM_REQUIRED = 1 PARAM_REGISTER = 2 PARAM_HAS_DEFAULT = 4 PARAM_SECRET = 8 PARAM_DBUS_PROPERTY = 16 -AUTHENTICATION = 'org.freedesktop.Telepathy.Authentication' +AUTHENTICATION = PREFIX + '.Authentication' AUTH_TLS_CERT = AUTHENTICATION + ".TLSCertificate" TLS_CERT_STATE_PENDING = 0 @@ -409,6 +539,10 @@ TLS_REJECT_REASON_UNTRUSTED = 1 # Channel.Interface.Messages +MESSAGE_PART_SUPPORT_FLAGS = CHANNEL_IFACE_MESSAGES + '.MessagePartSupportFlags' +DELIVERY_REPORTING_SUPPORT = CHANNEL_IFACE_MESSAGES + '.DeliveryReportingSupport' +SUPPORTED_CONTENT_TYPES = CHANNEL_IFACE_MESSAGES + '.SupportedContentTypes' + MSG_SENDING_FLAGS_REPORT_DELIVERY = 1 MSG_SENDING_FLAGS_REPORT_READ = 2 MSG_SENDING_FLAGS_REPORT_DELETED = 4 @@ -417,3 +551,86 @@ DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_FAILURES = 1 DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_SUCCESSES = 2 DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_READ = 4 DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_DELETED = 8 + +DELIVERY_STATUS_UNKNOWN = 0 +DELIVERY_STATUS_DELIVERED = 1 +DELIVERY_STATUS_TEMPORARILY_FAILED = 2 +DELIVERY_STATUS_PERMANENTLY_FAILED = 3 +DELIVERY_STATUS_ACCEPTED = 4 +DELIVERY_STATUS_READ = 5 +DELIVERY_STATUS_DELETED = 6 + +MEDIA_STREAM_ERROR_UNKNOWN = 0 +MEDIA_STREAM_ERROR_EOS = 1 +MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED = 2 +MEDIA_STREAM_ERROR_CONNECTION_FAILED = 3 +MEDIA_STREAM_ERROR_NETWORK_ERROR = 4 +MEDIA_STREAM_ERROR_NO_CODECS = 5 +MEDIA_STREAM_ERROR_INVALID_CM_BEHAVIOR = 6 +MEDIA_STREAM_ERROR_MEDIA_ERROR = 7 + +PASSWORD_FLAG_PROVIDE = 8 + +# Channel.Interface.Room +ROOM_NAME = CHANNEL_IFACE_ROOM + '.RoomName' +ROOM_SERVER = CHANNEL_IFACE_ROOM + '.Server' + +# Channel.Interface.Subject +SUBJECT = CHANNEL_IFACE_ROOM + '.Subject' +SUBJECT_PRESENT = 1 +SUBJECT_CAN_SET = 2 + +DEBUG_IFACE = PREFIX + '.Debug' +DEBUG_PATH = PATH_PREFIX + '/debug' + +SERVICE_POINT_TYPE_NONE = 0 +SERVICE_POINT_TYPE_EMERGENCY = 1 +SERVICE_POINT_TYPE_COUNSELING = 2 + +CLIENT = PREFIX + '.Client' +CLIENT_PATH = PATH_PREFIX + '/Client' +OBSERVER = PREFIX + '.Client.Observer' +APPROVER = PREFIX + '.Client.Approver' +HANDLER = PREFIX + '.Client.Handler' +CLIENT_IFACE_REQUESTS = CLIENT + '.Interface.Requests' + +ACCOUNT = PREFIX + '.Account' +ACCOUNT_IFACE_AVATAR = ACCOUNT + '.Interface.Avatar' +ACCOUNT_IFACE_ADDRESSING = ACCOUNT + '.Interface.Addressing' +ACCOUNT_IFACE_HIDDEN = ACCOUNT + '.Interface.Hidden.DRAFT1' +ACCOUNT_IFACE_NOKIA_CONDITIONS = 'com.nokia.Account.Interface.Conditions' +ACCOUNT_PATH_PREFIX = PATH_PREFIX + '/Account/' + +AM = PREFIX + '.AccountManager' +AM_IFACE_HIDDEN = AM + '.Interface.Hidden.DRAFT1' +AM_PATH = PATH_PREFIX + '/AccountManager' + +CR = PREFIX + '.ChannelRequest' +CDO = PREFIX + '.ChannelDispatchOperation' + +CD = PREFIX + '.ChannelDispatcher' +CD_IFACE_MESSAGES1 = PREFIX + '.ChannelDispatcher.Interface.Messages1' +CD_IFACE_OP_LIST = PREFIX + '.ChannelDispatcher.Interface.OperationList' +CD_PATH = PATH_PREFIX + '/ChannelDispatcher' +CD_REDISPATCH = CD + '.Interface.Redispatch.DRAFT' + +MC = PREFIX + '.MissionControl5' +MC_PATH = PATH_PREFIX + '/MissionControl5' + +DTMF_CURRENTLY_SENDING_TONES = CHANNEL_IFACE_DTMF + '.CurrentlySendingTones' +DTMF_INITIAL_TONES = CHANNEL_IFACE_DTMF + '.InitialTones' +DTMF_DEFERRED_TONES = CHANNEL_IFACE_DTMF + '.DeferredTones' + +TESTDOT = PREFIX + ".Test." +TESTSLASH = PATH_PREFIX + "/Test/" + +TEST_DBUS_ACCOUNT_SERVICE = TESTDOT + "DBusAccountService" +TEST_DBUS_ACCOUNT_SERVICE_PATH = TESTSLASH + "DBusAccountService" +TEST_DBUS_ACCOUNT_SERVICE_IFACE = TEST_DBUS_ACCOUNT_SERVICE + +TEST_DBUS_ACCOUNT_PLUGIN_PATH = TESTSLASH + "DBusAccountPlugin" +TEST_DBUS_ACCOUNT_PLUGIN_IFACE = TESTDOT + "DBusAccountPlugin" + +# Channel.Interface.SMS +SMS_FLASH = CHANNEL_IFACE_SMS + '.Flash' +SMS_CHANNEL = CHANNEL_IFACE_SMS + '.SMSChannel' diff --git a/tests/twisted/contacts.py b/tests/twisted/contacts.py index 1e83f35..8df602e 100644 --- a/tests/twisted/contacts.py +++ b/tests/twisted/contacts.py @@ -18,8 +18,7 @@ def test(q, bus, conn, stream): assertContains(cs.CONN_IFACE_ALIASING, attr_ifaces) assertContains(cs.CONN_IFACE_CONTACT_INFO, attr_ifaces) - brillana, miriam = conn.RequestHandles(cs.HT_CONTACT, - ["brillana", "miriam"]) + brillana, miriam = conn.get_contact_handles_sync(["brillana", "miriam"]) # First up, check that contact-id is always present attrs = conn.Contacts.GetContactAttributes([brillana], [], True) diff --git a/tests/twisted/idletest.py b/tests/twisted/idletest.py index bf080e4..6d9d1e1 100644 --- a/tests/twisted/idletest.py +++ b/tests/twisted/idletest.py @@ -7,6 +7,7 @@ import os import sys import dbus import servicetest +from servicetest import (unwrap, Event) import twisted from twisted.words.protocols import irc from twisted.internet import reactor, ssl @@ -238,6 +239,22 @@ def exec_test_deferred (funs, params, protocol=None, timeout=None): # conn = make_connection(bus, queue.append, params) (server, port) = start_server(queue.append, protocol=protocol) + bus.add_signal_receiver( + lambda *args, **kw: + queue.append( + Event('dbus-signal', + path=unwrap(kw['path']), + signal=kw['member'], args=list(map(unwrap, args)), + interface=kw['interface'])), + None, # signal name + None, # interface + None, + path_keyword='path', + member_keyword='member', + interface_keyword='interface', + byte_arrays=True + ) + error = None try: diff --git a/tests/twisted/irc-command.py b/tests/twisted/irc-command.py new file mode 100644 index 0000000..6ec27da --- /dev/null +++ b/tests/twisted/irc-command.py @@ -0,0 +1,31 @@ +""" +Test Messages interface implementation +""" + +from idletest import exec_test +from servicetest import call_async +import constants as cs +import dbus + +def test(q, bus, conn, stream): + conn.Connect() + q.expect('dbus-signal', signal='StatusChanged', + args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) + + irc_cmd = dbus.Interface(conn, cs.CONN + '.Interface.IRCCommand1') + + call_async(q, irc_cmd, 'Send', 'badger mushroom snake') + + q.expect('stream-BADGER', data=['mushroom', 'snake']) + + q.expect('dbus-return', method='Send') + + # We are not supposed to use this API to send messages + call_async(q, irc_cmd, 'Send', 'PRIVMSG badger :oh hi') + + q.expect('dbus-error', method='Send', name=cs.INVALID_ARGUMENT) + + call_async(q, conn, 'Disconnect') + +if __name__ == '__main__': + exec_test(test) diff --git a/tests/twisted/meson.build b/tests/twisted/meson.build index 8fcf290..a7e9b28 100644 --- a/tests/twisted/meson.build +++ b/tests/twisted/meson.build @@ -23,6 +23,7 @@ twisted_tests = [ 'channels/muc-destroy.py', 'channels/room-list-channel.py', 'channels/room-list-multiple.py', + 'irc-command.py', 'messages/accept-invalid-nicks.py', 'messages/contactinfo-request.py', 'messages/messages-iface.py', diff --git a/tests/twisted/messages/contactinfo-request.py b/tests/twisted/messages/contactinfo-request.py index cd524a0..d181dca 100644 --- a/tests/twisted/messages/contactinfo-request.py +++ b/tests/twisted/messages/contactinfo-request.py @@ -41,12 +41,15 @@ def test(q, bus, conn, stream): args=[1]) q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) - self_handle = conn.GetSelfHandle() + self_handle = conn.Get(CONN, 'SelfHandle', dbus_interface=PROPERTIES_IFACE) - room_handles = conn.RequestHandles(HT_ROOM, CHANNEL_NAMES) - for room_handle in room_handles: - call_async(q, conn, 'RequestChannel', CHANNEL_TYPE_TEXT, HT_ROOM, room_handle, True) - q.expect('dbus-return', method='RequestChannel') + for name in CHANNEL_NAMES: + call_async(q, conn.Requests, 'CreateChannel', + { CHANNEL_TYPE: CHANNEL_TYPE_TEXT, + TARGET_HANDLE_TYPE: HT_ROOM, + TARGET_ID: name }) + + q.expect('dbus-return', method='CreateChannel') q.expect('dbus-signal', signal='NewChannels') contact_info = dbus.Interface(conn, CONN_IFACE_CONTACT_INFO) diff --git a/tests/twisted/messages/long-message-split.py b/tests/twisted/messages/long-message-split.py index 88c11aa..fc8ce87 100644 --- a/tests/twisted/messages/long-message-split.py +++ b/tests/twisted/messages/long-message-split.py @@ -35,11 +35,12 @@ def test(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) CHANNEL_NAME = '#idletest' - room_handles = conn.RequestHandles(HT_ROOM, [CHANNEL_NAME]) - call_async(q, conn, 'RequestChannel', CHANNEL_TYPE_TEXT, HT_ROOM, - room_handles[0], True) + call_async(q, conn.Requests, 'CreateChannel', + { CHANNEL_TYPE: CHANNEL_TYPE_TEXT, + TARGET_HANDLE_TYPE: HT_ROOM, + TARGET_ID: CHANNEL_NAME }) - ret = q.expect('dbus-return', method='RequestChannel') + ret = q.expect('dbus-return', method='CreateChannel') q.expect('dbus-signal', signal='MembersChanged') chan = bus.get_object(conn.bus_name, ret.value[0]) diff --git a/tests/twisted/messages/message-order.py b/tests/twisted/messages/message-order.py index 545c183..d307e29 100644 --- a/tests/twisted/messages/message-order.py +++ b/tests/twisted/messages/message-order.py @@ -14,11 +14,12 @@ def test(q, bus, conn, stream): conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) CHANNEL_NAME = '#idletest' - room_handles = conn.RequestHandles(HT_ROOM, [CHANNEL_NAME]) - call_async(q, conn, 'RequestChannel', CHANNEL_TYPE_TEXT, HT_ROOM, - room_handles[0], True) + call_async(q, conn.Requests, 'CreateChannel', + { CHANNEL_TYPE: CHANNEL_TYPE_TEXT, + TARGET_HANDLE_TYPE: HT_ROOM, + TARGET_ID: CHANNEL_NAME }) - ret = q.expect('dbus-return', method='RequestChannel') + ret = q.expect('dbus-return', method='CreateChannel') q.expect('dbus-signal', signal='MembersChanged') chan = bus.get_object(conn.bus_name, ret.value[0]) diff --git a/tests/twisted/messages/room-contact-mixup.py b/tests/twisted/messages/room-contact-mixup.py index 2c0ab8c..e53b454 100644 --- a/tests/twisted/messages/room-contact-mixup.py +++ b/tests/twisted/messages/room-contact-mixup.py @@ -25,11 +25,13 @@ def test(q, bus, conn, stream): q.expect('dbus-signal', signal='StatusChanged', args=[0, 1]) # join a chat room with the same name as our nick - room_handles = conn.RequestHandles(HT_ROOM, [CHANNEL]) - call_async(q, conn, 'RequestChannel', CHANNEL_TYPE_TEXT, HT_ROOM, - room_handles[0], True) + call_async(q, conn.Requests,'CreateChannel', + { CHANNEL_TYPE: CHANNEL_TYPE_TEXT, + TARGET_HANDLE_TYPE: HT_ROOM, + TARGET_ID: CHANNEL }) + # wait for the join to finish - ret = q.expect('dbus-return', method='RequestChannel') + ret = q.expect('dbus-return', method='CreateChannel') muc_path = ret.value chan = bus.get_object(conn.bus_name, ret.value[0]) group_text_chan = dbus.Interface(chan, CHANNEL_TYPE_TEXT) diff --git a/tests/twisted/servicetest.py b/tests/twisted/servicetest.py index f4b50c9..24a606b 100644 --- a/tests/twisted/servicetest.py +++ b/tests/twisted/servicetest.py @@ -7,6 +7,8 @@ from twisted.internet import gireactor from twisted.internet.protocol import Protocol, Factory, ClientFactory gireactor.install() import sys +import time +import os import pprint import unittest @@ -19,18 +21,41 @@ from twisted.internet import reactor import constants as cs -tp_name_prefix = 'org.freedesktop.Telepathy' -tp_path_prefix = '/org/freedesktop/Telepathy' +tp_name_prefix = cs.PREFIX +tp_path_prefix = '/' + cs.PREFIX.replace('.', '/') -class Event: +class DictionarySupersetOf (object): + """Utility class for expecting "a dictionary with at least these keys".""" + def __init__(self, dictionary): + self._dictionary = dictionary + def __repr__(self): + return "DictionarySupersetOf(%s)" % self._dictionary + def __eq__(self, other): + """would like to just do: + return set(other.items()).issuperset(self._dictionary.items()) + but it turns out that this doesn't work if you have another dict + nested in the values of your dicts""" + try: + for k,v in list(self._dictionary.items()): + if k not in other or other[k] != v: + return False + return True + except TypeError: # other is not iterable + return False + +class Event(object): def __init__(self, type, **kw): self.__dict__.update(kw) self.type = type + (self.subqueue, self.subtype) = type.split ("-", 1) + + def __str__(self): + return '\n'.join([ str(type(self)) ] + format_event(self)) def format_event(event): ret = ['- type %s' % event.type] - for key in dir(event): + for key in sorted(dir(event)): if key != 'type' and not key.startswith('_'): ret.append('- %s: %s' % ( key, pprint.pformat(getattr(event, key)))) @@ -48,6 +73,7 @@ class EventPattern: self.predicate = properties['predicate'] del properties['predicate'] self.properties = properties + (self.subqueue, self.subtype) = type.split ("-", 1) def __repr__(self): properties = dict(self.properties) @@ -78,6 +104,14 @@ class EventPattern: class TimeoutError(Exception): pass +class ForbiddenEventOccurred(Exception): + def __init__(self, event): + Exception.__init__(self) + self.event = event + + def __str__(self): + return '\n' + '\n'.join(format_event(self.event)) + class BaseEventQueue: """Abstract event queue base class. @@ -87,6 +121,7 @@ class BaseEventQueue: def __init__(self, timeout=None): self.verbose = False self.forbidden_events = set() + self.event_queues = {} if timeout is None: self.timeout = 5 @@ -97,12 +132,14 @@ class BaseEventQueue: if self.verbose: print(s) + def log_queues(self, queues): + self.log ("Waiting for event on: %s" % ", ".join(queues)) + def log_event(self, event): - if self.verbose: - self.log('got event:') + self.log('got event:') - if self.verbose: - list(map(self.log, format_event(event))) + if self.verbose: + list(map(self.log, format_event(event))) def forbid_events(self, patterns): """ @@ -120,13 +157,16 @@ class BaseEventQueue: """ self.forbidden_events.difference_update(set(patterns)) + def unforbid_all(self): + """ + Remove all patterns from the set of forbidden events. + """ + self.forbidden_events.clear() + def _check_forbidden(self, event): for e in self.forbidden_events: if e.match(event): - print("forbidden event occurred:") - for x in format_event(event): - print(x) - assert False + raise ForbiddenEventOccurred(event) def expect(self, type, **kw): """ @@ -136,14 +176,15 @@ class BaseEventQueue: e = q.expect('dbus-signal', signal='Badgers', args=["foo", 42]) """ pattern = EventPattern(type, **kw) + t = time.time() while True: - event = self.wait() - self.log_event(event) + event = self.wait([pattern.subqueue]) self._check_forbidden(event) if pattern.match(event): - self.log('handled') + self.log('handled, took %0.3f ms' + % ((time.time() - t) * 1000.0) ) self.log('') return event @@ -180,10 +221,15 @@ class BaseEventQueue: ) """ ret = [None] * len(patterns) + t = time.time() while None in ret: try: - event = self.wait() + queues = set() + for i, pattern in enumerate(patterns): + if ret[i] is None: + queues.add(pattern.subqueue) + event = self.wait(queues) except TimeoutError: self.log('timeout') self.log('still expecting:') @@ -191,12 +237,12 @@ class BaseEventQueue: if ret[i] is None: self.log(' - %r' % pattern) raise - self.log_event(event) self._check_forbidden(event) for i, pattern in enumerate(patterns): if ret[i] is None and pattern.match(event): - self.log('handled') + self.log('handled, took %0.3f ms' + % ((time.time() - t) * 1000.0) ) self.log('') ret[i] = event break @@ -209,8 +255,7 @@ class BaseEventQueue: def demand(self, type, **kw): pattern = EventPattern(type, **kw) - event = self.wait() - self.log_event(event) + event = self.wait([pattern.subqueue]) if pattern.match(event): self.log('handled') @@ -220,14 +265,34 @@ class BaseEventQueue: self.log('not handled') raise RuntimeError('expected %r, got %r' % (pattern, event)) + def queues_available(self, queues): + if queues == None: + return list(self.event_queues.keys()) + else: + available = list(self.event_queues.keys()) + return [x for x in queues if x in available] + + + def pop_next(self, queue): + events = self.event_queues[queue] + e = events.pop(0) + if not events: + self.event_queues.pop (queue) + return e + + def append(self, event): + self.log ("Adding to queue") + self.log_event (event) + self.event_queues[event.subqueue] = \ + self.event_queues.get(event.subqueue, []) + [event] + class IteratingEventQueue(BaseEventQueue): """Event queue that works by iterating the Twisted reactor.""" def __init__(self, timeout=None): BaseEventQueue.__init__(self, timeout) - self.events = [] - def wait(self): + def wait(self, queues=None): stop = [False] def later(): @@ -235,68 +300,92 @@ class IteratingEventQueue(BaseEventQueue): delayed_call = reactor.callLater(self.timeout, later) - while (not self.events) and (not stop[0]): - reactor.iterate(0.1) + self.log_queues(queues) + + qa = self.queues_available(queues) + while not qa and (not stop[0]): + reactor.iterate(0.01) + qa = self.queues_available(queues) - if self.events: + if qa: delayed_call.cancel() - return self.events.pop(0) + e = self.pop_next (qa[0]) + self.log_event (e) + return e else: raise TimeoutError - def append(self, event): - self.events.append(event) - - # compatibility - handle_event = append - class TestEventQueue(BaseEventQueue): def __init__(self, events): BaseEventQueue.__init__(self) - self.events = events + for e in events: + self.append (e) - def wait(self): - if self.events: - return self.events.pop(0) + def wait(self, queues = None): + qa = self.queues_available(queues) + + if qa: + return self.pop_next (qa[0]) else: raise TimeoutError class EventQueueTest(unittest.TestCase): def test_expect(self): - queue = TestEventQueue([Event('foo'), Event('bar')]) - assert queue.expect('foo').type == 'foo' - assert queue.expect('bar').type == 'bar' + queue = TestEventQueue([Event('test-foo'), Event('test-bar')]) + assert queue.expect('test-foo').type == 'test-foo' + assert queue.expect('test-bar').type == 'test-bar' def test_expect_many(self): - queue = TestEventQueue([Event('foo'), Event('bar')]) + queue = TestEventQueue([Event('test-foo'), + Event('test-bar')]) bar, foo = queue.expect_many( - EventPattern('bar'), - EventPattern('foo')) - assert bar.type == 'bar' - assert foo.type == 'foo' + EventPattern('test-bar'), + EventPattern('test-foo')) + assert bar.type == 'test-bar' + assert foo.type == 'test-foo' def test_expect_many2(self): # Test that events are only matched against patterns that haven't yet # been matched. This tests a regression. - queue = TestEventQueue([Event('foo', x=1), Event('foo', x=2)]) + queue = TestEventQueue([Event('test-foo', x=1), Event('test-foo', x=2)]) foo1, foo2 = queue.expect_many( - EventPattern('foo'), - EventPattern('foo')) - assert foo1.type == 'foo' and foo1.x == 1 - assert foo2.type == 'foo' and foo2.x == 2 + EventPattern('test-foo'), + EventPattern('test-foo')) + assert foo1.type == 'test-foo' and foo1.x == 1 + assert foo2.type == 'test-foo' and foo2.x == 2 + + def test_expect_queueing(self): + queue = TestEventQueue([Event('foo-test', x=1), + Event('foo-test', x=2)]) + + queue.append(Event('bar-test', x=1)) + queue.append(Event('bar-test', x=2)) + + queue.append(Event('baz-test', x=1)) + queue.append(Event('baz-test', x=2)) + + for x in range(1,2): + e = queue.expect ('baz-test') + assertEquals (x, e.x) + + e = queue.expect ('bar-test') + assertEquals (x, e.x) + + e = queue.expect ('foo-test') + assertEquals (x, e.x) def test_timeout(self): queue = TestEventQueue([]) - self.assertRaises(TimeoutError, queue.expect, 'foo') + self.assertRaises(TimeoutError, queue.expect, 'test-foo') def test_demand(self): - queue = TestEventQueue([Event('foo'), Event('bar')]) - foo = queue.demand('foo') - assert foo.type == 'foo' + queue = TestEventQueue([Event('test-foo'), Event('test-bar')]) + foo = queue.demand('test-foo') + assert foo.type == 'test-foo' def test_demand_fail(self): - queue = TestEventQueue([Event('foo'), Event('bar')]) - self.assertRaises(RuntimeError, queue.demand, 'bar') + queue = TestEventQueue([Event('test-foo'), Event('test-bar')]) + self.assertRaises(RuntimeError, queue.demand, 'test-bar') def unwrap(x): """Hack to unwrap D-Bus values, so that they're easier to read when @@ -325,11 +414,11 @@ def call_async(test, proxy, method, *args, **kw): resulting method return/error.""" def reply_func(*ret): - test.handle_event(Event('dbus-return', method=method, + test.append(Event('dbus-return', method=method, value=unwrap(ret))) def error_func(err): - test.handle_event(Event('dbus-error', method=method, error=err, + test.append(Event('dbus-error', method=method, error=err, name=err.get_dbus_name(), message=str(err))) method_proxy = getattr(proxy, method) @@ -337,16 +426,21 @@ def call_async(test, proxy, method, *args, **kw): method_proxy(*args, **kw) def sync_dbus(bus, q, conn): - # Dummy D-Bus method call + # Dummy D-Bus method call. We can't use DBus.Peer.Ping() because libdbus + # replies to that message immediately, rather than handing it up to + # dbus-glib and thence Gabble, which means that Ping()ing Gabble doesn't + # ensure that it's processed all D-Bus messages prior to our ping. + # # This won't do the right thing unless the proxy has a unique name. assert conn.object.bus_name.startswith(':') - root_object = bus.get_object(conn.object.bus_name, '/') - call_async( - q, dbus.Interface(root_object, 'org.freedesktop.DBus.Peer'), 'Ping') - q.expect('dbus-return', method='Ping') + root_object = bus.get_object(conn.object.bus_name, '/', introspect=False) + call_async(q, + dbus.Interface(root_object, cs.PREFIX + '.Tests'), + 'DummySyncDBus') + q.expect('dbus-error', method='DummySyncDBus') class ProxyWrapper: - def __init__(self, object, default, others): + def __init__(self, object, default, others={}): self.object = object self.default_interface = dbus.Interface(object, default) self.Properties = dbus.Interface(object, dbus.PROPERTIES_IFACE) @@ -365,12 +459,29 @@ class ProxyWrapper: return getattr(self.default_interface, name) +class ConnWrapper(ProxyWrapper): + def inspect_contact_sync(self, handle): + return self.inspect_contacts_sync([handle])[0] + + def inspect_contacts_sync(self, handles): + h2asv = self.Contacts.GetContactAttributes(handles, [], True) + ret = [] + for h in handles: + ret.append(h2asv[h][cs.ATTR_CONTACT_ID]) + return ret + + def get_contact_handle_sync(self, identifier): + return self.Contacts.GetContactByID(identifier, [])[0] + + def get_contact_handles_sync(self, ids): + return [self.get_contact_handle_sync(i) for i in ids] + def wrap_connection(conn): - return ProxyWrapper(conn, tp_name_prefix + '.Connection', + return ConnWrapper(conn, tp_name_prefix + '.Connection', dict([ (name, tp_name_prefix + '.Connection.Interface.' + name) for name in ['Aliasing', 'Avatars', 'Capabilities', 'Contacts', - 'Presence', 'SimplePresence', 'Requests']] + + 'SimplePresence', 'Requests']] + [('Peer', 'org.freedesktop.DBus.Peer'), ('ContactCapabilities', cs.CONN_IFACE_CONTACT_CAPS), ('ContactInfo', cs.CONN_IFACE_CONTACT_INFO), @@ -379,6 +490,8 @@ def wrap_connection(conn): ('MailNotification', cs.CONN_IFACE_MAIL_NOTIFICATION), ('ContactList', cs.CONN_IFACE_CONTACT_LIST), ('ContactGroups', cs.CONN_IFACE_CONTACT_GROUPS), + ('PowerSaving', cs.CONN_IFACE_POWER_SAVING), + ('Addressing', cs.CONN_IFACE_ADDRESSING), ])) def wrap_channel(chan, type_, extra=None): @@ -394,32 +507,28 @@ def wrap_channel(chan, type_, extra=None): return ProxyWrapper(chan, tp_name_prefix + '.Channel', interfaces) + +def wrap_content(chan, extra=None): + interfaces = { } + + if extra: + interfaces.update(dict([ + (name, tp_name_prefix + '.Call1.Content.Interface.' + name) + for name in extra])) + + return ProxyWrapper(chan, tp_name_prefix + '.Call1.Content', interfaces) + def make_connection(bus, event_func, name, proto, params): cm = bus.get_object( tp_name_prefix + '.ConnectionManager.%s' % name, - tp_path_prefix + '/ConnectionManager/%s' % name) + tp_path_prefix + '/ConnectionManager/%s' % name, + introspect=False) cm_iface = dbus.Interface(cm, tp_name_prefix + '.ConnectionManager') connection_name, connection_path = cm_iface.RequestConnection( - proto, params) + proto, dbus.Dictionary(params, signature='sv')) conn = wrap_connection(bus.get_object(connection_name, connection_path)) - bus.add_signal_receiver( - lambda *args, **kw: - event_func( - Event('dbus-signal', - path=unwrap(kw['path']), - signal=kw['member'], args=list(map(unwrap, args)), - interface=kw['interface'])), - None, # signal name - None, # interface - cm._named_service, - path_keyword='path', - member_keyword='member', - interface_keyword='interface', - byte_arrays=True - ) - return conn def make_channel_proxy(conn, path, iface): @@ -437,7 +546,7 @@ class EventProtocol(Protocol): def dataReceived(self, data): if self.queue is not None: - self.queue.handle_event(Event('socket-data', protocol=self, + self.queue.append(Event('socket-data', protocol=self, data=data)) def sendData(self, data): @@ -449,7 +558,7 @@ class EventProtocol(Protocol): def connectionLost(self, reason=None): if self.queue is not None: - self.queue.handle_event(Event('socket-disconnected', protocol=self)) + self.queue.append(Event('socket-disconnected', protocol=self)) class EventProtocolFactory(Factory): def __init__(self, queue, block_reading=False): @@ -461,7 +570,7 @@ class EventProtocolFactory(Factory): def buildProtocol(self, addr): proto = self._create_protocol() - self.queue.handle_event(Event('socket-connected', protocol=proto)) + self.queue.append(Event('socket-connected', protocol=proto)) return proto class EventProtocolClientFactory(EventProtocolFactory, ClientFactory): @@ -469,7 +578,7 @@ class EventProtocolClientFactory(EventProtocolFactory, ClientFactory): def watch_tube_signals(q, tube): def got_signal_cb(*args, **kwargs): - q.handle_event(Event('tube-signal', + q.append(Event('tube-signal', path=kwargs['path'], signal=kwargs['member'], args=list(map(unwrap, args)), @@ -530,6 +639,12 @@ def assertFlagsUnset(flags, value): "expected none of flags %u, but %u are set in %u" % ( flags, masked, value)) +def assertDBusError(name, error): + if error.get_dbus_name() != name: + raise AssertionError( + "expected DBus error named:\n %s\ngot:\n %s\n(with message: %s)" + % (name, error.get_dbus_name(), error.message)) + def install_colourer(): def red(s): return '\x1b[31m%s\x1b[0m' % s @@ -548,12 +663,26 @@ def install_colourer(): self.patterns = patterns def write(self, s): - f = self.patterns.get(s, lambda x: x) - self.fh.write(f(s)) + for p, f in list(self.patterns.items()): + if s.startswith(p): + self.fh.write(f(p) + s[len(p):]) + return + + self.fh.write(s) sys.stdout = Colourer(sys.stdout, patterns) return sys.stdout -if __name__ == '__main__': - unittest.main() +# this is just to shut up unittest. +class DummyStream(object): + def write(self, s): + if 'CHECK_TWISTED_VERBOSE' in os.environ: + print(s, end=' ') + + def flush(self): + pass +if __name__ == '__main__': + stream = DummyStream() + runner = unittest.TextTestRunner(stream=stream) + unittest.main(testRunner=runner) |