1# Copyright (C) 2009 Nokia Corporation 2# Copyright (C) 2009-2010 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 20 21from servicetest import (EventPattern, tp_name_prefix, tp_path_prefix, 22 call_async, assertEquals) 23from mctest import exec_test, SimulatedConnection, create_fakecm_account 24import constants as cs 25 26def test(q, bus, mc): 27 # Create an account. We're setting register=True here to verify 28 # that after one successful connection, it'll be removed (fd.o #28118). 29 params = dbus.Dictionary({"account": "someguy@example.com", 30 "password": "secrecy", 31 "register": True}, signature='sv') 32 (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params) 33 34 call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'Enabled', False) 35 q.expect('dbus-return', method='Set') 36 37 # Enable the account 38 call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'Enabled', True) 39 40 # Set online presence 41 presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy', 42 'Fixing MC bugs'), signature='uss') 43 call_async(q, account.Properties, 'Set', cs.ACCOUNT, 44 'RequestedPresence', presence) 45 46 e = q.expect('dbus-method-call', method='RequestConnection', 47 args=['fakeprotocol', params], 48 destination=tp_name_prefix + '.ConnectionManager.fakecm', 49 path=tp_path_prefix + '/ConnectionManager/fakecm', 50 interface=tp_name_prefix + '.ConnectionManager', 51 handled=False) 52 53 conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_', 54 'myself', has_presence=True) 55 56 q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') 57 58 # MC calls GetStatus (maybe) and then Connect 59 60 q.expect('dbus-method-call', method='Connect', 61 path=conn.object_path, handled=True) 62 63 # Connect succeeds 64 conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE) 65 66 q.expect('dbus-method-call', 67 interface=cs.CONN_IFACE_SIMPLE_PRESENCE, 68 method='SetPresence', 69 args=list(presence[1:]), 70 handled=True) 71 72 # Connection falls over for a miscellaneous reason 73 conn.ConnectionError('com.example.My.Network.Is.Full.Of.Eels', 74 {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}) 75 conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED, 76 cs.CONN_STATUS_REASON_NETWORK_ERROR) 77 78 # MC reconnects. This time, we expect it to have deleted the 'register' 79 # parameter. 80 del params['register'] 81 82 disconnected, connecting, e = q.expect_many( 83 EventPattern('dbus-signal', signal='AccountPropertyChanged', 84 predicate=(lambda e: 85 e.args[0].get('ConnectionStatus') == 86 cs.CONN_STATUS_DISCONNECTED), 87 ), 88 EventPattern('dbus-signal', signal='AccountPropertyChanged', 89 predicate=(lambda e: 90 e.args[0].get('ConnectionStatus') == 91 cs.CONN_STATUS_CONNECTING), 92 ), 93 EventPattern('dbus-method-call', method='RequestConnection', 94 args=['fakeprotocol', params], 95 destination=tp_name_prefix + '.ConnectionManager.fakecm', 96 path=tp_path_prefix + '/ConnectionManager/fakecm', 97 interface=tp_name_prefix + '.ConnectionManager', 98 handled=False), 99 ) 100 101 assertEquals('/', disconnected.args[0].get('Connection')) 102 assertEquals('com.example.My.Network.Is.Full.Of.Eels', 103 disconnected.args[0].get('ConnectionError')) 104 assertEquals( 105 {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}, 106 disconnected.args[0].get('ConnectionErrorDetails')) 107 assertEquals(cs.CONN_STATUS_DISCONNECTED, 108 disconnected.args[0].get('ConnectionStatus')) 109 assertEquals(cs.CONN_STATUS_REASON_NETWORK_ERROR, 110 disconnected.args[0].get('ConnectionStatusReason')) 111 112 assertEquals('/', connecting.args[0].get('Connection')) 113 assertEquals('com.example.My.Network.Is.Full.Of.Eels', 114 connecting.args[0].get('ConnectionError')) 115 assertEquals( 116 {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}, 117 connecting.args[0].get('ConnectionErrorDetails')) 118 assertEquals(cs.CONN_STATUS_CONNECTING, 119 connecting.args[0].get('ConnectionStatus')) 120 assertEquals(cs.CONN_STATUS_REASON_REQUESTED, 121 connecting.args[0].get('ConnectionStatusReason')) 122 123 # The object path needs to be different from the first simulated 124 # connection which we made above, because the object isn't removed 125 # from this bus and it's actually hard to do so because it's not 126 # really on a bus, it's on the queue. So let's just change the 127 # object path and it's fine. 128 conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', 'second', 129 'myself', has_presence=True) 130 131 q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so') 132 133 # MC calls GetStatus (maybe) and then Connect 134 135 connecting, _ = q.expect_many( 136 EventPattern('dbus-signal', signal='AccountPropertyChanged', 137 predicate=(lambda e: 138 e.args[0].get('ConnectionStatus') == 139 cs.CONN_STATUS_CONNECTING), 140 ), 141 EventPattern('dbus-method-call', method='Connect', 142 path=conn.object_path, handled=True), 143 ) 144 145 assertEquals(conn.object_path, connecting.args[0].get('Connection')) 146 assertEquals('com.example.My.Network.Is.Full.Of.Eels', 147 connecting.args[0].get('ConnectionError')) 148 assertEquals( 149 {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}, 150 connecting.args[0].get('ConnectionErrorDetails')) 151 assertEquals(cs.CONN_STATUS_CONNECTING, 152 connecting.args[0].get('ConnectionStatus')) 153 assertEquals(cs.CONN_STATUS_REASON_REQUESTED, 154 connecting.args[0].get('ConnectionStatusReason')) 155 156 assertEquals('com.example.My.Network.Is.Full.Of.Eels', 157 account.Properties.Get(cs.ACCOUNT, 'ConnectionError')) 158 assertEquals( 159 {'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'}, 160 account.Properties.Get(cs.ACCOUNT, 'ConnectionErrorDetails')) 161 162 # Connect succeeds 163 conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE) 164 165 connected, _ = q.expect_many( 166 EventPattern('dbus-signal', signal='AccountPropertyChanged', 167 predicate=(lambda e: 168 e.args[0].get('ConnectionStatus') == 169 cs.CONN_STATUS_CONNECTED), 170 ), 171 EventPattern('dbus-method-call', 172 interface=cs.CONN_IFACE_SIMPLE_PRESENCE, 173 method='SetPresence', 174 args=list(presence[1:]), 175 handled=True), 176 ) 177 178 assertEquals(conn.object_path, connected.args[0].get('Connection')) 179 assertEquals('', connected.args[0].get('ConnectionError')) 180 assertEquals({}, connected.args[0].get('ConnectionErrorDetails')) 181 assertEquals(cs.CONN_STATUS_CONNECTED, 182 connected.args[0].get('ConnectionStatus')) 183 assertEquals(cs.CONN_STATUS_REASON_REQUESTED, 184 connected.args[0].get('ConnectionStatusReason')) 185 186 assertEquals('', account.Properties.Get(cs.ACCOUNT, 'ConnectionError')) 187 assertEquals({}, account.Properties.Get(cs.ACCOUNT, 'ConnectionErrorDetails')) 188 189if __name__ == '__main__': 190 exec_test(test, {}) 191