1# Copyright (C) 2009 Nokia Corporation
2# Copyright (C) 2009 Collabora Ltd.
3#
4# This library is free software; you can redistribute it and/or
5# modify it under the terms of the GNU Lesser General Public
6# License as published by the Free Software Foundation; either
7# version 2.1 of the License, or (at your option) any later version.
8#
9# This library is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12# Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public
15# License along with this library; if not, write to the Free Software
16# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17# 02110-1301 USA
18
19import dbus
20import dbus
21import dbus.service
22
23from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
24        call_async, sync_dbus, TimeoutError
25from mctest import exec_test, SimulatedConnection, create_fakecm_account,\
26        SimulatedChannel
27import constants as cs
28
29params = dbus.Dictionary({"account": "someguy@example.com",
30    "password": "secrecy"}, signature='sv')
31
32def test(q, bus, mc):
33    cm_name_ref = dbus.service.BusName(
34            tp_name_prefix + '.ConnectionManager.fakecm', bus=bus)
35
36    # Create an account
37    (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
38
39    account_iface = dbus.Interface(account, cs.ACCOUNT)
40    account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
41
42    call_async(q, account, 'Set', cs.ACCOUNT, 'Enabled', False,
43            dbus_interface=cs.PROPERTIES_IFACE)
44    q.expect('dbus-return', method='Set')
45
46    # Enable the account
47    call_async(q, account, 'Set', cs.ACCOUNT, 'Enabled', True,
48            dbus_interface=cs.PROPERTIES_IFACE)
49
50    # Set online presence
51    presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
52            'Fixing MC bugs'), signature='uss')
53    call_async(q, account, 'Set', cs.ACCOUNT,
54            'RequestedPresence', presence,
55            dbus_interface=cs.PROPERTIES_IFACE)
56
57    e = q.expect('dbus-method-call', method='RequestConnection',
58            args=['fakeprotocol', params],
59            destination=tp_name_prefix + '.ConnectionManager.fakecm',
60            path=tp_path_prefix + '/ConnectionManager/fakecm',
61            interface=tp_name_prefix + '.ConnectionManager',
62            handled=False)
63
64    conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_',
65            'myself', has_presence=True)
66
67    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
68
69    # MC calls GetStatus (maybe) and then Connect
70
71    q.expect('dbus-method-call', method='Connect',
72            path=conn.object_path, handled=True)
73
74    # Connect succeeds
75    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
76
77    conn = drop_and_expect_reconnect(q, bus, conn)
78    conn = drop_and_expect_reconnect(q, bus, conn)
79    conn = drop_and_expect_reconnect(q, bus, conn)
80
81    forbidden = [EventPattern('dbus-method-call', method='RequestConnection')]
82    q.forbid_events(forbidden)
83
84    # Connection falls over for a miscellaneous reason
85    conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED,
86            cs.CONN_STATUS_REASON_NETWORK_ERROR)
87    # Right, that's it, I'm giving up...
88
89    # This test can be considered to have succeeded if we don't
90    # RequestConnection again before the test fails due to timeout.
91    try:
92        q.expect('the end of the world')
93    except TimeoutError:
94        return
95    else:
96        raise AssertionError('An impossible event happened')
97
98def drop_and_expect_reconnect(q, bus, conn):
99    # Connection falls over for a miscellaneous reason
100    conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED,
101            cs.CONN_STATUS_REASON_NETWORK_ERROR)
102
103    # MC reconnects
104
105    e = q.expect('dbus-method-call', method='RequestConnection',
106            args=['fakeprotocol', params],
107            destination=tp_name_prefix + '.ConnectionManager.fakecm',
108            path=tp_path_prefix + '/ConnectionManager/fakecm',
109            interface=tp_name_prefix + '.ConnectionManager',
110            handled=False)
111
112    conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_',
113            'myself', has_presence=True)
114
115    q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
116
117    # MC calls GetStatus (maybe) and then Connect
118
119    q.expect('dbus-method-call', method='Connect',
120            path=conn.object_path, handled=True)
121
122    # Connect succeeds
123    conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
124
125    return conn
126
127if __name__ == '__main__':
128    exec_test(test, {})
129