1"""
2Test that redundant calls to SetPresence don't cause anything to happen.
3"""
4
5import dbus
6
7from servicetest import EventPattern
8from gabbletest import exec_test
9import constants as cs
10from invisible_helper import Xep0186Stream, ValidInvisibleListStream, \
11    Xep0186AndValidInvisibleListStream
12
13def run_test(q, bus, conn, stream):
14    # Expect an initial presence push from the client.
15    q.expect('stream-presence')
16
17    # Set presence to away. This should cause PresencesChanged to be emitted,
18    # and a new <presence> stanza to be sent to the server.
19    conn.SimplePresence.SetPresence('away', 'gone')
20
21    simple_signal, presence = q.expect_many (
22        EventPattern('dbus-signal', signal='PresencesChanged'),
23        EventPattern('stream-presence'))
24    assert simple_signal.args == [{1L: (3L, u'away',  u'gone')}]
25    assert conn.Contacts.GetContactAttributes([1], [cs.CONN_IFACE_SIMPLE_PRESENCE], False) == { 1L:
26      { cs.CONN_IFACE_SIMPLE_PRESENCE + "/presence": (3L, u'away', u'gone'),
27        'org.freedesktop.Telepathy.Connection/contact-id':
28            'test@localhost'}}
29
30    children = list(presence.stanza.elements())
31    assert children[0].name == 'show'
32    assert str(children[0]) == 'away'
33    assert children[1].name == 'status'
34    assert str(children[1]) == 'gone'
35
36    # Set presence a second time. Since this call is redundant, there should
37    # be no PresencesChanged or <presence> sent to the server.
38    conn.SimplePresence.SetPresence('away', 'gone')
39    assert conn.Contacts.GetContactAttributes([1], [cs.CONN_IFACE_SIMPLE_PRESENCE], False) == { 1L:
40      { cs.CONN_IFACE_SIMPLE_PRESENCE + "/presence": (3L, u'away', u'gone'),
41        'org.freedesktop.Telepathy.Connection/contact-id':
42            'test@localhost'}}
43
44    # Set presence a third time. This call is not redundant, and should
45    # generate a signal/message.
46    conn.SimplePresence.SetPresence('available', 'yo')
47
48    simple_signal, presence = q.expect_many (
49        EventPattern('dbus-signal', signal='PresencesChanged'),
50        EventPattern('stream-presence'))
51
52    assert simple_signal.args == [{1L: (2L, u'available',  u'yo')}]
53    children = list(presence.stanza.elements())
54    assert children[0].name == 'status'
55    assert str(children[0]) == 'yo'
56    assert conn.Contacts.GetContactAttributes([1], [cs.CONN_IFACE_SIMPLE_PRESENCE], False) == { 1L:
57      { cs.CONN_IFACE_SIMPLE_PRESENCE + "/presence": (2L, u'available', u'yo'),
58        'org.freedesktop.Telepathy.Connection/contact-id':
59            'test@localhost'}}
60
61    # call SetPresence with an empty message, as this used to cause a
62    # crash in tp-glib
63    conn.SimplePresence.SetPresence('available', '')
64
65    simple_signal, presence = q.expect_many (
66        EventPattern('dbus-signal', signal='PresencesChanged'),
67        EventPattern('stream-presence'))
68    assert simple_signal.args == [{1L: (2L, u'available',  u'')}]
69    assert conn.Contacts.GetContactAttributes([1], [cs.CONN_IFACE_SIMPLE_PRESENCE], False) == { 1L:
70      { cs.CONN_IFACE_SIMPLE_PRESENCE + "/presence": (2L, u'available', u''),
71        'org.freedesktop.Telepathy.Connection/contact-id':
72            'test@localhost'}}
73
74if __name__ == '__main__':
75    exec_test(run_test)
76    # Run this test against some invisibility-capable servers, even though we
77    # don't use invisibility, to check that invisibility support doesn't break
78    # us. This is a regression test for
79    # <https://bugs.freedesktop.org/show_bug.cgi?id=30117>. It turned out that
80    # XEP-0126 support meant that our own presence changes were never
81    # signalled.
82    for protocol in [Xep0186AndValidInvisibleListStream, Xep0186Stream,
83                     ValidInvisibleListStream]:
84        exec_test(run_test, protocol=protocol)
85        exec_test(run_test, protocol=protocol)
86
87