diff options
26 files changed, 463 insertions, 206 deletions
diff --git a/extensions/Makefile.am b/extensions/Makefile.am index bb837da..8812839 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -49,7 +49,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/src/idle-connection.c b/src/idle-connection.c index 6ab5fea..9ba1d23 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" @@ -489,7 +490,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 +566,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); 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..277dbdb 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" 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-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/channels/join-muc-channel-bouncer.py b/tests/twisted/channels/join-muc-channel-bouncer.py index 09f12a1..e9b145c 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 613756e..de3235a 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=[1L]) 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 c460ece..10ddf47 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 6200904..a62d59f 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 + u'.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..e1d3dfe 100644 --- a/tests/twisted/constants.py +++ b/tests/twisted/constants.py @@ -4,7 +4,9 @@ Some handy constants for other tests to share and enjoy. from dbus import PROPERTIES_IFACE -CM = "org.freedesktop.Telepathy.ConnectionManager" +PREFIX = "org.freedesktop.Telepathy" + +CM = PREFIX + ".ConnectionManager" HT_NONE = 0 HT_CONTACT = 1 @@ -12,40 +14,41 @@ 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_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 +62,100 @@ 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_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 = PREFIX + '.Call1.Content' CALL_CONTENT_IFACE_MEDIA = \ - 'org.freedesktop.Telepathy.Call.Content.Interface.Media.DRAFT' + PREFIX + '.Call1.Content.Interface.Media' +CALL_CONTENT_IFACE_DTMF = \ + PREFIX + '.Call1.Content.Interface.DTMF' -CALL_CONTENT_CODECOFFER = \ - 'org.freedesktop.Telepathy.Call.Content.CodecOffer.DRAFT' +CALL_CONTENT_MEDIADESCRIPTION = \ + PREFIX + '.Call1.Content.MediaDescription' -CALL_STREAM = 'org.freedesktop.Telepathy.Call.Stream.DRAFT' +CALL_STREAM = PREFIX + '.Call1.Stream' CALL_STREAM_IFACE_MEDIA = \ - 'org.freedesktop.Telepathy.Call.Stream.Interface.Media.DRAFT' + PREFIX + '.Call1.Stream.Interface.Media' -CALL_STREAM_ENDPOINT = 'org.freedesktop.Telepathy.Call.Stream.Endpoint.DRAFT' +CALL_STREAM_ENDPOINT = PREFIX + '.Call1.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 +168,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' @@ -130,15 +180,21 @@ 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' +ATTR_CONTACT_ID = CONN + '/contact-id' ATTR_CONTACT_CAPABILITIES = CONN_IFACE_CONTACT_CAPS + '/capabilities' +ATTR_PRESENCE = CONN_IFACE_SIMPLE_PRESENCE + '/presence' -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' @@ -151,7 +207,6 @@ CONNECTION_LOST = ERROR + '.ConnectionLost' CANCELLED = ERROR + '.Cancelled' DISCONNECTED = ERROR + '.Disconnected' REGISTRATION_EXISTS = ERROR + '.RegistrationExists' -SERVICE_BUSY = ERROR + '.ServiceBusy' AUTHENTICATION_FAILED = ERROR + '.AuthenticationFailed' CONNECTION_REPLACED = ERROR + '.ConnectionReplaced' ALREADY_CONNECTED = ERROR + '.AlreadyConnected' @@ -159,6 +214,10 @@ 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' + +BANNED = ERROR + '.Channel.Banned' UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod' @@ -192,6 +251,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 @@ -261,6 +327,9 @@ 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_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 +367,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,7 +403,7 @@ MEDIA_CAP_GTALKP2P = 8 MEDIA_CAP_ICEUDP = 16 MEDIA_CAP_IMMUTABLE_STREAMS = 32 -CLIENT = 'org.freedesktop.Telepathy.Client' +CLIENT = PREFIX + '.Client' PRESENCE_OFFLINE = 1 PRESENCE_AVAILABLE = 2 @@ -352,11 +416,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 +432,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 +459,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 +496,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 +508,34 @@ 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 = '/' + PREFIX.replace('.', '/') + '/debug' 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 b1ad857..d60e774 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=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/messages/contactinfo-request.py b/tests/twisted/messages/contactinfo-request.py index 1350afe..44464ca 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=[1L]) 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 3065e15..fcba708 100644 --- a/tests/twisted/servicetest.py +++ b/tests/twisted/servicetest.py @@ -7,6 +7,8 @@ from twisted.internet import glib2reactor from twisted.internet.protocol import Protocol, Factory, ClientFactory glib2reactor.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 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: - map(self.log, format_event(event)) + if self.verbose: + 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 self.event_queues.keys() + else: + available = self.event_queues.keys() + return filter(lambda x: x in available, queues) + + + 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 xrange(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=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=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 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, + + def flush(self): + pass +if __name__ == '__main__': + stream = DummyStream() + runner = unittest.TextTestRunner(stream=stream) + unittest.main(testRunner=runner) |