Merge lp:~diegosarmentero/ubuntu-sso-client/remove-disconnect-signal into lp:ubuntu-sso-client

Proposed by Diego Sarmentero on 2012-01-23
Status: Merged
Approved by: Diego Sarmentero on 2012-01-27
Approved revision: 838
Merged at revision: 839
Proposed branch: lp:~diegosarmentero/ubuntu-sso-client/remove-disconnect-signal
Merge into: lp:ubuntu-sso-client
Diff against target: 180 lines (+104/-22)
2 files modified
ubuntu_sso/networkstate/linux.py (+0/-2)
ubuntu_sso/networkstate/tests/test_linux.py (+104/-20)
To merge this branch: bzr merge lp:~diegosarmentero/ubuntu-sso-client/remove-disconnect-signal
Reviewer Review Type Date Requested Status
Natalia Bidart Approve on 2012-01-27
Roberto Alsina (community) 2012-01-23 Approve on 2012-01-25
Review via email: mp+89761@code.launchpad.net

Commit Message

- Delete signal removal to keep listening to network state changes (LP: #920591).

Description of the Change

Maybe you will have in windows a trace where some tests related to test_webclient might be failing, this is happening also in trunk (and seems to be a timing issue):

https://bugs.launchpad.net/ubuntu-sso-client/+bug/920591

To post a comment you must log in.
Roberto Alsina (ralsina) wrote :

+1

review: Approve
Natalia Bidart (nataliabidart) wrote :

Branch looks mostly good, but I have some suggestions to improve the test readability. ATM, since the fake connect_to_siganl is returning self, it makes difficult to notice that dbus signals are also being faked by the same FakeDbusModule. Also, this is self.DBusException = self very complex to understand... why are you mocking an exception with a FakeDbusModule?

I advice not to mix fakes in this way, since future debugging may take longer and will be difficult to follow. Also, fakes and mocks should have an almost identical API with the object they are faking, so, for example, connect_to_signal should expect a siganl name and a callback, and it should return a different object than self, which has a certain API (has a remove method, for example). The fact that a test (that uses a fake with the correct API) pass, ensures more correctness in the production code.

So, below a proposal to improve the tests:
http://pastebin.ubuntu.com/816828/

review: Needs Fixing
838. By Diego Sarmentero on 2012-01-26

Improving Tests

Diego Sarmentero (diegosarmentero) wrote :

> Branch looks mostly good, but I have some suggestions to improve the test
> readability. ATM, since the fake connect_to_siganl is returning self, it makes
> difficult to notice that dbus signals are also being faked by the same
> FakeDbusModule. Also, this is self.DBusException = self very complex to
> understand... why are you mocking an exception with a FakeDbusModule?
>
> I advice not to mix fakes in this way, since future debugging may take longer
> and will be difficult to follow. Also, fakes and mocks should have an almost
> identical API with the object they are faking, so, for example,
> connect_to_signal should expect a siganl name and a callback, and it should
> return a different object than self, which has a certain API (has a remove
> method, for example). The fact that a test (that uses a fake with the correct
> API) pass, ensures more correctness in the production code.
>
> So, below a proposal to improve the tests:
> http://pastebin.ubuntu.com/816828/

Thanks for the suggestion, the tests has been improved.

Natalia Bidart (nataliabidart) wrote :

Looks good!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntu_sso/networkstate/linux.py'
2--- ubuntu_sso/networkstate/linux.py 2011-11-11 19:20:59 +0000
3+++ ubuntu_sso/networkstate/linux.py 2012-01-26 12:32:24 +0000
4@@ -78,8 +78,6 @@
5
6 def call_result_cb(self, state):
7 """Return the state thru the result callback."""
8- if self.state_signal:
9- self.state_signal.remove()
10 self.result_cb(state)
11
12 def got_state(self, state):
13
14=== modified file 'ubuntu_sso/networkstate/tests/test_linux.py'
15--- ubuntu_sso/networkstate/tests/test_linux.py 2011-11-11 19:20:59 +0000
16+++ ubuntu_sso/networkstate/tests/test_linux.py 2012-01-26 12:32:24 +0000
17@@ -4,7 +4,7 @@
18 #
19 # Author: Alejandro J. Cura <alecu@canonical.com>
20 #
21-# Copyright 2010 Canonical Ltd.
22+# Copyright 2010-2012 Canonical Ltd.
23 #
24 # This program is free software: you can redistribute it and/or modify it
25 # under the terms of the GNU General Public License version 3, as published
26@@ -19,29 +19,35 @@
27 # with this program. If not, see <http://www.gnu.org/licenses/>.
28 """Tests for the network state detection code."""
29
30+from collections import defaultdict
31+
32 from twisted.internet.defer import inlineCallbacks
33+from mocker import ARGS, KWARGS, ANY, MockerTestCase
34
35 from ubuntu_sso.tests import TestCase
36-from ubuntu_sso.networkstate import (NetworkManagerState,
37- ONLINE, OFFLINE, UNKNOWN)
38+from ubuntu_sso.networkstate import (
39+ linux,
40+ NetworkFailException,
41+ NetworkManagerState,
42+ ONLINE, OFFLINE, UNKNOWN,
43+)
44
45-from ubuntu_sso.networkstate import NetworkFailException
46-from ubuntu_sso.networkstate import linux
47 from ubuntu_sso.networkstate.linux import (is_machine_connected,
48- DBUS_UNKNOWN_SERVICE,
49- NM_STATE_ASLEEP,
50- NM_STATE_ASLEEP_OLD,
51- NM_STATE_CONNECTING,
52- NM_STATE_CONNECTING_OLD,
53- NM_STATE_CONNECTED_OLD,
54- NM_STATE_CONNECTED_LOCAL,
55- NM_STATE_CONNECTED_SITE,
56- NM_STATE_CONNECTED_GLOBAL,
57- NM_STATE_DISCONNECTED,
58- NM_STATE_DISCONNECTED_OLD,
59- NM_STATE_UNKNOWN)
60-
61-from mocker import ARGS, KWARGS, ANY, MockerTestCase
62+ DBUS_UNKNOWN_SERVICE,
63+ NM_DBUS_INTERFACE,
64+ NM_DBUS_OBJECTPATH,
65+ NM_STATE_ASLEEP,
66+ NM_STATE_ASLEEP_OLD,
67+ NM_STATE_CONNECTING,
68+ NM_STATE_CONNECTING_OLD,
69+ NM_STATE_CONNECTED_OLD,
70+ NM_STATE_CONNECTED_LOCAL,
71+ NM_STATE_CONNECTED_SITE,
72+ NM_STATE_CONNECTED_GLOBAL,
73+ NM_STATE_DISCONNECTED,
74+ NM_STATE_DISCONNECTED_OLD,
75+ NM_STATE_UNKNOWN,
76+)
77
78
79 class TestException(Exception):
80@@ -66,6 +72,57 @@
81 self.call_function(self.connection_state)
82
83
84+class FakeDBusMatch(object):
85+
86+ """Fake a DBus match."""
87+
88+ def __init__(self, name, callback, interface):
89+ self.name = name
90+ self.callback = callback
91+ self.interface = interface
92+ self.removed = False
93+
94+ def remove(self):
95+ """Stop calling the handler function on remove."""
96+ self.removed = True
97+
98+
99+class FakeDBusInterface(object):
100+
101+ """Fake DBus Interface."""
102+
103+ def __init__(self):
104+ self._signals = defaultdict(list)
105+
106+ # pylint: disable=C0103
107+ def Get(self, *args, **kwargs):
108+ """Fake Get."""
109+ # pylint: enable=C0103
110+
111+ def connect_to_signal(self, signal_name, handler_function, dbus_interface):
112+ """Fake connect_to_signal."""
113+ match = FakeDBusMatch(signal_name, handler_function, dbus_interface)
114+ self._signals[signal_name].append(match)
115+ return match
116+
117+ def emit_signal(self, signal_name, state):
118+ """Emit signal for network state change."""
119+ for match in self._signals[signal_name]:
120+ match.callback(state)
121+
122+
123+class FakeSystemBus(object):
124+
125+ """Fake SystemBus."""
126+
127+ objects = {(NM_DBUS_INTERFACE, NM_DBUS_OBJECTPATH, True): object()}
128+
129+ def get_object(self, interface, object_path, follow_name_owner_changes):
130+ """Fake get_object."""
131+ key = (interface, object_path, follow_name_owner_changes)
132+ return self.objects[key]
133+
134+
135 class TestConnection(TestCase):
136
137 """Test the state of the connection.
138@@ -79,6 +136,34 @@
139 """Setup the mocker dbus object tree."""
140 yield super(TestConnection, self).setUp()
141 self.patch(linux, "NetworkManagerState", FakeNetworkManagerState)
142+ self.patch(linux.dbus, 'SystemBus', FakeSystemBus)
143+ self.nm_interface = FakeDBusInterface()
144+ self.patch(linux.dbus, 'Interface', lambda *a: self.nm_interface)
145+ self.network_changes = []
146+
147+ def _listen_network_changes(self, state):
148+ """Fake callback function."""
149+ self.network_changes.append(state)
150+
151+ def test_network_state_change(self):
152+ """Test the changes in the network connection."""
153+ nms = NetworkManagerState(self._listen_network_changes)
154+
155+ nms.find_online_state()
156+
157+ self.nm_interface.emit_signal('StateChanged',
158+ NM_STATE_CONNECTED_GLOBAL)
159+ self.nm_interface.emit_signal('StateChanged', NM_STATE_DISCONNECTED)
160+ self.nm_interface.emit_signal('StateChanged',
161+ NM_STATE_CONNECTED_GLOBAL)
162+
163+ self.assertEqual(nms.state_signal.name, "StateChanged")
164+ self.assertEqual(nms.state_signal.callback, nms.state_changed)
165+ self.assertEqual(nms.state_signal.interface,
166+ "org.freedesktop.NetworkManager")
167+ self.assertEqual(self.network_changes,
168+ [UNKNOWN, ONLINE, OFFLINE, ONLINE])
169+ self.assertFalse(nms.state_signal.removed)
170
171 @inlineCallbacks
172 def test_is_machine_connected_nm_state_connected_old(self):
173@@ -216,7 +301,6 @@
174 if exc is not None:
175 self.expect(self.dbusmock.exceptions.DBusException)
176 self.mocker.result(exc)
177- signalmock.remove()
178 self.mocker.replay()
179
180 # Invalid name "assert[A-Z].*"

Subscribers

People subscribed via source and target branches