Merge lp:~mandel/ubuntu-sso-client/use-unix-domain into lp:ubuntu-sso-client

Proposed by Manuel de la Peña on 2012-05-01
Status: Merged
Approved by: Alejandro J. Cura on 2012-05-16
Approved revision: 967
Merged at revision: 956
Proposed branch: lp:~mandel/ubuntu-sso-client/use-unix-domain
Merge into: lp:ubuntu-sso-client
Prerequisite: lp:~diegosarmentero/ubuntu-sso-client/mac-port
Diff against target: 1243 lines (+428/-194)
12 files modified
bin/ubuntu-sso-login (+1/-1)
bin/ubuntu-sso-login-qt (+3/-1)
run-mac-tests (+1/-1)
ubuntu_sso/main/__init__.py (+9/-8)
ubuntu_sso/main/darwin.py (+25/-15)
ubuntu_sso/main/tests/test_darwin.py (+32/-14)
ubuntu_sso/main/tests/test_windows.py (+27/-0)
ubuntu_sso/main/windows.py (+17/-4)
ubuntu_sso/utils/ipc.py (+25/-22)
ubuntu_sso/utils/tcpactivation.py (+21/-15)
ubuntu_sso/utils/tests/test_ipc.py (+110/-34)
ubuntu_sso/utils/tests/test_tcpactivation.py (+157/-79)
To merge this branch: bzr merge lp:~mandel/ubuntu-sso-client/use-unix-domain
Reviewer Review Type Date Requested Status
Alejandro J. Cura (community) Approve on 2012-05-16
Diego Sarmentero (community) 2012-05-01 Approve on 2012-05-03
Review via email: mp+104244@code.launchpad.net

Commit Message

Added support for domain sockets in the tcpactivation and the ipc on darwin which removed the need of using random ports (LP: #984665).

Description of the Change

- Added support for domain sockets in the tcpactivation and the ipc on darwin which removed the need of using random ports (LP: #984665).

To post a comment you must log in.
Diego Sarmentero (diegosarmentero) wrote :

The same as in my branch, it would be better if we have instead of:

from ubuntu_sso.main import windows
from ubuntu_sso.main import darwin
from ubuntu_sso.main import linux
source = X

something like:

from ubuntu_sso.main import darwin as source

review: Needs Fixing
961. By Manuel de la Peña on 2012-05-01

Do smarter imports.

962. By Manuel de la Peña on 2012-05-01

Skip if on win32.

963. By Manuel de la Peña on 2012-05-01

Skip if on win32.

964. By Manuel de la Peña on 2012-05-03

Use the service runner to clean the tests on windows.

965. By Manuel de la Peña on 2012-05-03

Use run server to clean reactor on windows.

966. By Manuel de la Peña on 2012-05-03

Clean tests to work in all platforms.

Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve
Alejandro J. Cura (alecu) wrote :

I liked a lot this branch; I specially liked the refactoring of port -> service description a lot!

A few comments:
---
We need to check that the path returned by get_sso_domain_socket is only readable by the current user. Please consider opening a new bug for this.

"prot =" -> "port ="
---
I've only ran tests on Linux, and everything seems fine otherwise, so I'm ready to approve when the above small things are taken care of. Thanks for working on this!

review: Needs Fixing
Manuel de la Peña (mandel) wrote :

> I liked a lot this branch; I specially liked the refactoring of port ->
> service description a lot!
>
> A few comments:
> ---
> We need to check that the path returned by get_sso_domain_socket is only
> readable by the current user. Please consider opening a new bug for this.
>
> "prot =" -> "port ="
> ---
> I've only ran tests on Linux, and everything seems fine otherwise, so I'm
> ready to approve when the above small things are taken care of. Thanks for
> working on this!

Thx!! I have updated the branch and removed the spelling error. You can find the bug regarding security here: lp:#1000155.

I thin using peereid on the connecting client to get the uid of the user running the process will ensure that the correct client connects.

967. By Manuel de la Peña on 2012-05-16

Spelling fail.

Alejandro J. Cura (alecu) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/ubuntu-sso-login'
2--- bin/ubuntu-sso-login 2012-05-09 13:39:29 +0000
3+++ bin/ubuntu-sso-login 2012-05-16 10:20:23 +0000
4@@ -52,7 +52,7 @@
5 import os
6 import sys
7
8-if sys.platform == 'win32':
9+if sys.platform in ('win32', 'darwin'):
10 from PyQt4 import QtGui
11 # need to create the QApplication before installing the reactor
12 if os.environ.get('TESTABILITY', False):
13
14=== modified file 'bin/ubuntu-sso-login-qt'
15--- bin/ubuntu-sso-login-qt 2012-04-09 17:38:24 +0000
16+++ bin/ubuntu-sso-login-qt 2012-05-16 10:20:23 +0000
17@@ -33,7 +33,9 @@
18 # Access to a protected member, pylint: disable=W0212
19
20 import sys
21-if sys.platform == 'win32':
22+if sys.platform in ('win32', 'darwin'):
23+ from PyQt4 import QtGui
24+ app = QtGui.QApplication(sys.argv)
25 import qt4reactor
26 qt4reactor.install()
27
28
29=== modified file 'run-mac-tests'
30--- run-mac-tests 2012-04-27 15:42:22 +0000
31+++ run-mac-tests 2012-05-16 10:20:23 +0000
32@@ -49,7 +49,7 @@
33
34 echo "*** Running QT test suite for ""$MODULE"" ***"
35 ./setup.py build
36-python $u1trial --reactor=qt4 --gui -p "$GTK_TESTS_PATH" -i "test_gui.py, test_linux.py, test_qt.py, test_windows.py, test_glib.py, test_txsecrets.py, test_ipc.py, test_tcpactivation.py" "$MODULE"
37+python $u1trial --reactor=qt4 --gui -p "$GTK_TESTS_PATH" -i "test_gui.py, test_linux.py, test_qt.py, test_windows.py, test_glib.py, test_txsecrets.py" "$MODULE"
38 rm -rf _trial_temp
39 rm -rf build
40
41
42=== modified file 'ubuntu_sso/main/__init__.py'
43--- ubuntu_sso/main/__init__.py 2012-05-09 17:37:55 +0000
44+++ ubuntu_sso/main/__init__.py 2012-05-16 10:20:23 +0000
45@@ -60,15 +60,16 @@
46 # pylint: disable=C0103, W0703, W0621
47
48 if sys.platform == 'win32':
49- from ubuntu_sso.main import windows
50+ from ubuntu_sso.main import windows as source
51 from ubuntu_sso.main.perspective_broker import (
52+ finish_setup,
53+ main as main_func,
54 timeout_func,
55 shutdown_func,
56 start_setup,
57- main as main_func,
58 )
59
60- source = windows
61+ source.finish_setup = finish_setup
62 source.timeout_func = timeout_func
63 source.shutdown_func = shutdown_func
64 source.start_setup = start_setup
65@@ -76,22 +77,22 @@
66
67 TIMEOUT_INTERVAL = 10000000000 # forever (hack)
68 elif sys.platform == 'darwin':
69- from ubuntu_sso.main import darwin
70+ from ubuntu_sso.main import darwin as source
71 from ubuntu_sso.main.perspective_broker import (
72+ finish_setup,
73+ main as main_func,
74 timeout_func,
75 shutdown_func,
76 start_setup,
77- main as main_func,
78 )
79
80- source = darwin
81+ source.finish_setup = finish_setup
82 source.timeout_func = timeout_func
83 source.shutdown_func = shutdown_func
84 source.start_setup = start_setup
85 source.main = main_func
86 else:
87- from ubuntu_sso.main import linux
88- source = linux
89+ from ubuntu_sso.main import linux as source
90
91 UbuntuSSOClient = source.UbuntuSSOClient
92 UbuntuSSOProxy = source.UbuntuSSOProxy
93
94=== modified file 'ubuntu_sso/main/darwin.py'
95--- ubuntu_sso/main/darwin.py 2012-04-23 12:22:03 +0000
96+++ ubuntu_sso/main/darwin.py 2012-05-16 10:20:23 +0000
97@@ -28,6 +28,7 @@
98 import os
99 import os.path
100
101+from dirspec import basedir
102 from twisted.internet import defer
103
104 import ubuntu_sso
105@@ -45,17 +46,26 @@
106
107
108 logger = setup_logging("ubuntu_sso.main.darwin")
109-U1_REG_PATH = r'Software\Ubuntu One'
110 SSO_INSTALL_PATH = 'SSOInstallPath'
111-SSO_BASE_PB_PORT = 50000
112-SSO_RESERVED_PORTS = 3000
113-SSO_PORT_ALLOCATION_STEP = 3 # contiguous ports for sso, u1client, and u1cp
114-
115-
116-def get_sso_pb_port():
117- """Compute the port the SSO service should run on per-user."""
118- uid_modulo = os.getuid() % SSO_RESERVED_PORTS
119- return SSO_BASE_PB_PORT + uid_modulo * SSO_PORT_ALLOCATION_STEP
120+
121+
122+def get_sso_domain_socket():
123+ """Compute the domain socket for the sso ipc."""
124+ path = os.path.join(basedir.xdg_cache_home, 'sso', 'ipc')
125+ return path
126+
127+
128+class DescriptionFactory(object):
129+ """Factory that provides the server and client descriptions."""
130+
131+ client_description_pattern = 'unix:path=%s'
132+ server_description_pattern = 'unix:%s'
133+
134+ def __init__(self):
135+ """Create a new instance."""
136+ self.domain = get_sso_domain_socket()
137+ self.server = self.server_description_pattern % self.domain
138+ self.client = self.client_description_pattern % self.domain
139
140
141 class UbuntuSSOProxy(UbuntuSSOProxyBase):
142@@ -64,9 +74,9 @@
143 name = SSO_SERVICE_NAME
144
145 @property
146- def port(self):
147- """Get the port on which the SSO pb is running."""
148- return get_sso_pb_port()
149+ def description(self):
150+ """Get the description on which the SSO pb is running."""
151+ return DescriptionFactory()
152
153 @property
154 def cmdline(self):
155@@ -77,7 +87,7 @@
156 ubuntu_sso_pkg_dir = os.path.dirname(
157 os.path.dirname(ubuntu_sso.__file__))
158 ubuntu_sso_bin_dir = os.path.join(ubuntu_sso_pkg_dir, 'bin')
159- ubuntu_sso_bin = os.path.join(ubuntu_sso_bin_dir, self.name)
160+ ubuntu_sso_bin = os.path.join(ubuntu_sso_bin_dir, 'ubuntu-sso-login')
161 ubuntuone_client_bin_dir = os.path.join(ubuntu_sso_pkg_dir,
162 '../ubuntuone-client/bin')
163 ubuntuone_client_bin = os.path.join(ubuntuone_client_bin_dir,
164@@ -98,7 +108,7 @@
165 }
166
167 service_name = UbuntuSSOProxy.name
168- service_port = UbuntuSSOProxy.port
169+ service_description = UbuntuSSOProxy.description
170 service_cmdline = UbuntuSSOProxy.cmdline
171
172
173
174=== modified file 'ubuntu_sso/main/tests/test_darwin.py'
175--- ubuntu_sso/main/tests/test_darwin.py 2012-04-23 12:22:03 +0000
176+++ ubuntu_sso/main/tests/test_darwin.py 2012-05-16 10:20:23 +0000
177@@ -15,29 +15,47 @@
178 # with this program. If not, see <http://www.gnu.org/licenses/>.
179 """Darwin specific tests for the main module."""
180
181+import os
182+
183+from dirspec import basedir
184+from twisted.internet import defer
185+
186 from ubuntu_sso.main import darwin
187 from ubuntu_sso.tests import TestCase
188
189 # because we are using twisted we have java like names C0103
190 # pylint: disable=C0103
191
192-MOCK_SSO_DARWIN_UID = 1001
193-
194-
195-class MockOsGetuid(object):
196- """Mocked os.getuid to support reliable uid for test"""
197-
198- def getuid(self):
199- """Return the same uid for tests"""
200- return MOCK_SSO_DARWIN_UID
201-
202
203 class DarwinTestCase(TestCase):
204 """Tests for module level misc functions"""
205
206 def test_get_sso_pb_port(self):
207 """Test the get_sso_pb_port function, by patching os.getuid"""
208- mock_os = MockOsGetuid()
209- self.patch(darwin, "os", mock_os)
210- expected_port = 53003
211- self.assertEqual(darwin.get_sso_pb_port(), expected_port)
212+ expected = os.path.join(basedir.xdg_cache_home, 'sso', 'ipc')
213+ self.assertEqual(darwin.get_sso_domain_socket(), expected)
214+
215+
216+class DescriptionFactoryTestcase(TestCase):
217+ """Test the factory."""
218+
219+ @defer.inlineCallbacks
220+ def setUp(self):
221+ """Set the tests."""
222+ yield super(DescriptionFactoryTestcase, self).setUp()
223+ self.domain = '/path/to/domain'
224+ self.patch(darwin, 'get_sso_domain_socket', lambda: self.domain)
225+
226+ def test_server_description(self):
227+ """Test getting the description info."""
228+ expected = darwin.DescriptionFactory.server_description_pattern % \
229+ self.domain
230+ factory = darwin.DescriptionFactory()
231+ self.assertEqual(expected, factory.server)
232+
233+ def test_client_description(self):
234+ """Test getting the description info."""
235+ expected = darwin.DescriptionFactory.client_description_pattern % \
236+ self.domain
237+ factory = darwin.DescriptionFactory()
238+ self.assertEqual(expected, factory.client)
239
240=== modified file 'ubuntu_sso/main/tests/test_windows.py'
241--- ubuntu_sso/main/tests/test_windows.py 2012-04-20 16:27:04 +0000
242+++ ubuntu_sso/main/tests/test_windows.py 2012-05-16 10:20:23 +0000
243@@ -31,6 +31,8 @@
244 # pylint: disable=F0401
245 from _winreg import REG_SZ
246
247+from twisted.internet import defer
248+
249 from ubuntu_sso.main import windows
250 from ubuntu_sso.main import perspective_broker
251 from ubuntu_sso.tests import TestCase
252@@ -114,3 +116,28 @@
253 cmdline = windows.get_activation_cmdline(
254 perspective_broker.SSO_SERVICE_NAME)
255 self.assertEqual(sample_value, cmdline)
256+
257+
258+class DescriptionFactoryTestcase(TestCase):
259+ """Test the factory."""
260+
261+ @defer.inlineCallbacks
262+ def setUp(self):
263+ """Set the tests."""
264+ yield super(DescriptionFactoryTestcase, self).setUp()
265+ self.port = 55555
266+ self.patch(windows, 'get_sso_pb_port', lambda: self.port)
267+
268+ def test_server_description(self):
269+ """Test getting the description info."""
270+ expected = windows.DescriptionFactory.server_description_pattern % \
271+ self.port
272+ factory = windows.DescriptionFactory()
273+ self.assertEqual(expected, factory.server)
274+
275+ def test_client_description(self):
276+ """Test getting the description info."""
277+ expected = windows.DescriptionFactory.client_description_pattern % \
278+ self.port
279+ factory = windows.DescriptionFactory()
280+ self.assertEqual(expected, factory.client)
281
282=== modified file 'ubuntu_sso/main/windows.py'
283--- ubuntu_sso/main/windows.py 2012-04-23 12:22:03 +0000
284+++ ubuntu_sso/main/windows.py 2012-05-16 10:20:23 +0000
285@@ -89,15 +89,28 @@
286 return value
287
288
289+class DescriptionFactory(object):
290+ """Factory that provides the server and client descriptions."""
291+
292+ client_description_pattern = 'tcp:host=127.0.0.1:port=%s'
293+ server_description_pattern = 'tcp:%s:interface=127.0.0.1'
294+
295+ def __init__(self):
296+ """Create a new instance."""
297+ self.port = get_sso_pb_port()
298+ self.server = self.server_description_pattern % self.port
299+ self.client = self.client_description_pattern % self.port
300+
301+
302 class UbuntuSSOProxy(UbuntuSSOProxyBase):
303 """Object that exposes the diff referenceable objects."""
304
305 name = SSO_SERVICE_NAME
306
307 @property
308- def port(self):
309- """Get the port on which the SSO pb is running."""
310- return get_sso_pb_port()
311+ def description(self):
312+ """Get the description on which the SSO pb is running."""
313+ return DescriptionFactory()
314
315 @property
316 def cmdline(self):
317@@ -116,7 +129,7 @@
318 }
319
320 service_name = UbuntuSSOProxy.name
321- service_port = UbuntuSSOProxy.port
322+ service_description = UbuntuSSOProxy.description
323 service_cmdline = UbuntuSSOProxy.cmdline
324
325
326
327=== modified file 'ubuntu_sso/utils/ipc.py'
328--- ubuntu_sso/utils/ipc.py 2012-04-10 10:43:48 +0000
329+++ ubuntu_sso/utils/ipc.py 2012-05-16 10:20:23 +0000
330@@ -31,7 +31,7 @@
331 from functools import wraps, partial
332 from collections import defaultdict
333
334-from twisted.internet import defer
335+from twisted.internet import defer, endpoints
336 from twisted.spread.pb import (
337 DeadReferenceError,
338 NoSuchMethod,
339@@ -46,41 +46,44 @@
340 ActivationClient,
341 ActivationConfig,
342 ActivationInstance,
343- LOCALHOST,
344 )
345
346
347 logger = setup_logging("ubuntu_sso.utils.ipc")
348-
349+LOCALHOST = '127.0.0.1'
350
351 # pylint: disable=E1103
352
353+
354 @defer.inlineCallbacks
355-def server_listen(server_factory, service_name, activation_cmdline, port,
356- reactor=None):
357+def server_listen(server_factory, service_name, activation_cmdline,
358+ description, reactor=None):
359 """Connect the IPC server factory."""
360- config = ActivationConfig(service_name, activation_cmdline, port)
361+ config = ActivationConfig(service_name, activation_cmdline, description)
362 ai = ActivationInstance(config)
363- port = yield ai.get_port()
364+ description = yield ai.get_server_description()
365
366 if reactor is None:
367 from twisted.internet import reactor
368- connector = reactor.listenTCP(port, server_factory, interface=LOCALHOST)
369+ server = endpoints.serverFromString(reactor, description)
370+ connector = yield server.listen(server_factory)
371 defer.returnValue(connector)
372
373
374 @defer.inlineCallbacks
375-def client_connect(client_factory, service_name, activation_cmdline, port,
376- reactor=None):
377+def client_connect(client_factory, service_name, activation_cmdline,
378+ description, reactor=None):
379 """Connect the IPC client factory."""
380- config = ActivationConfig(service_name, activation_cmdline, port)
381+ config = ActivationConfig(service_name, activation_cmdline, description)
382 ac = ActivationClient(config)
383- port = yield ac.get_active_port()
384+ description = yield ac.get_active_client_description()
385
386 if reactor is None:
387 from twisted.internet import reactor
388- connector = reactor.connectTCP(LOCALHOST, port, client_factory)
389- defer.returnValue(connector)
390+
391+ client = endpoints.clientFromString(reactor, description)
392+ port = yield client.connect(client_factory)
393+ defer.returnValue(port)
394
395
396 # pylint: enable=E1103
397@@ -179,7 +182,7 @@
398 class BaseService(object, Root):
399 """Base PB service.
400
401- Inherit from this class and define name, port and cmdline.
402+ Inherit from this class and define name, description and cmdline.
403
404 If 'start' is called, 'shutdown' should be called when done.
405
406@@ -188,7 +191,7 @@
407 # a mapping of (service name, service class (an instance of RemoteService))
408 services = {}
409 name = None
410- port = None
411+ description = None
412 cmdline = None
413
414 def __init__(self, *a, **kw):
415@@ -207,12 +210,12 @@
416
417 @defer.inlineCallbacks
418 def start(self):
419- """Start listening in the proper port."""
420+ """Start listening in the proper description."""
421 self.factory = PBServerFactory(self)
422 self.listener = yield server_listen(self.factory,
423 self.name,
424 self.cmdline,
425- self.port)
426+ self.description)
427
428 def shutdown(self):
429 """Stop listening."""
430@@ -312,9 +315,9 @@
431
432
433 class BaseClient(object):
434- """Client that will connect to the service listening on service_port.
435+ """Client that will connect to the service listening on the description.
436
437- Inherit from this class and define service_name, service_port and
438+ Inherit from this class and define service_name, service_description and
439 service_cmdline so they return the proper values.
440
441 The service_cmdline must be redefined so it returns the command line to
442@@ -327,7 +330,7 @@
443 # a mapping of (client name, client class (an instance of RemoteClient))
444 clients = {}
445 service_name = None
446- service_port = None
447+ service_description = None
448 service_cmdline = None
449
450 def __init__(self):
451@@ -352,7 +355,7 @@
452 self.client = yield client_connect(self.factory,
453 self.service_name,
454 self.service_cmdline,
455- self.service_port)
456+ self.service_description)
457 root = yield self.factory.getRootObject()
458 yield self._request_remote_objects(root)
459 yield self.register_to_signals()
460
461=== modified file 'ubuntu_sso/utils/tcpactivation.py'
462--- ubuntu_sso/utils/tcpactivation.py 2012-04-10 10:43:53 +0000
463+++ ubuntu_sso/utils/tcpactivation.py 2012-05-16 10:20:23 +0000
464@@ -30,7 +30,8 @@
465
466 import subprocess
467
468-from twisted.internet import defer, protocol, reactor
469+from twisted.internet import defer, error, protocol, reactor
470+from twisted.internet.endpoints import clientFromString
471
472 LOCALHOST = "127.0.0.1"
473 DELAY_BETWEEN_CHECKS = 0.1
474@@ -67,6 +68,8 @@
475 class PortDetectFactory(protocol.ClientFactory):
476 """Will detect if something is listening in a given port."""
477
478+ protocol = NullProtocol
479+
480 def __init__(self):
481 """Initialize this instance."""
482 self.d = defer.Deferred()
483@@ -77,9 +80,10 @@
484
485 def buildProtocol(self, addr):
486 """Connected."""
487+ p = protocol.ClientFactory.buildProtocol(self, addr)
488 if not self.d.called:
489 self.d.callback(True)
490- return NullProtocol()
491+ return p
492
493 def clientConnectionLost(self, connector, reason):
494 """The connection was lost."""
495@@ -95,11 +99,11 @@
496 class ActivationConfig(object):
497 """The configuration for tcp activation."""
498
499- def __init__(self, service_name, command_line, port):
500+ def __init__(self, service_name, command_line, description):
501 """Initialize this instance."""
502 self.service_name = service_name
503 self.command_line = command_line
504- self.port = port
505+ self.description = description
506
507
508 class ActivationDetector(object):
509@@ -113,10 +117,12 @@
510 def is_already_running(self):
511 """Check if the instance is already running."""
512 factory = PortDetectFactory()
513- # pylint: disable=E1101
514- connector = reactor.connectTCP(LOCALHOST, self.config.port, factory)
515+ client = clientFromString(reactor, self.config.description.client)
516+ try:
517+ yield client.connect(factory)
518+ except error.ConnectError:
519+ defer.returnValue(False)
520 result = yield factory.is_listening()
521- connector.disconnect()
522 defer.returnValue(result)
523
524
525@@ -144,20 +150,20 @@
526 subprocess.Popen(self.config.command_line, close_fds=True)
527
528 @defer.inlineCallbacks
529- def _do_get_active_port(self):
530- """Get the port for the running instance, starting it if needed."""
531+ def _do_get_active_description(self):
532+ """Get the details for the running instance, starting it if needed."""
533 is_running = yield self.is_already_running()
534 if not is_running:
535 self._spawn_server()
536 yield self._wait_server_active()
537- defer.returnValue(self.config.port)
538+ defer.returnValue(self.config.description.client)
539
540 @defer.inlineCallbacks
541- def get_active_port(self):
542- """Serialize the requests to _do_get_active_port."""
543+ def get_active_client_description(self):
544+ """Serialize the requests to _do_get_active_description."""
545 yield self.lock.acquire()
546 try:
547- result = yield self._do_get_active_port()
548+ result = yield self._do_get_active_description()
549 defer.returnValue(result)
550 finally:
551 self.lock.release()
552@@ -167,9 +173,9 @@
553 """A tcp activation server instance."""
554
555 @defer.inlineCallbacks
556- def get_port(self):
557+ def get_server_description(self):
558 """Get the port to run this service or fail if already started."""
559 is_running = yield self.is_already_running()
560 if is_running:
561 raise AlreadyStartedError()
562- defer.returnValue(self.config.port)
563+ defer.returnValue(self.config.description.server)
564
565=== modified file 'ubuntu_sso/utils/tests/test_ipc.py'
566--- ubuntu_sso/utils/tests/test_ipc.py 2012-04-26 11:35:46 +0000
567+++ ubuntu_sso/utils/tests/test_ipc.py 2012-05-16 10:20:23 +0000
568@@ -38,7 +38,11 @@
569 NoSuchMethod,
570 )
571 from ubuntuone.devtools.handlers import MementoHandler
572-from ubuntuone.devtools.testcases.txsocketserver import TCPPbServerTestCase
573+from ubuntuone.devtools.testcases import skipIfOS
574+from ubuntuone.devtools.testcases.txsocketserver import (
575+ TidyUnixServer,
576+ TCPPbServerTestCase,
577+)
578
579 from ubuntu_sso.tests import TestCase
580 from ubuntu_sso.utils import ipc
581@@ -46,7 +50,8 @@
582
583 TEST_SERVICE = 'foo-service'
584 TEST_CMDLINE = 'foo.bin'
585-TEST_PORT = 40404
586+TEST_SERVER_DESCRIPTION = 'tcp:40404:interface=127.0.0.1'
587+TEST_CLIENT_DESCRIPTION = 'tcp:host=127.0.0.1:port=40404'
588
589
590 class RandomException(Exception):
591@@ -60,15 +65,30 @@
592 """Initialize this fake instance."""
593 self.config = config
594
595- def get_active_port(self):
596- """Return the port where the pb server is running."""
597- return defer.succeed(self.config.port)
598-
599-
600-class FakeActivationInstance(FakeActivationClient):
601+ def get_active_client_description(self):
602+ """Return the description where the pb server is running."""
603+ return defer.succeed(self.config.description.client)
604+
605+
606+class FakeActivationInstance(object):
607 """A fake ActivationInstance."""
608
609- get_port = FakeActivationClient.get_active_port
610+ def __init__(self, config):
611+ """Initialize the fake instance."""
612+ self.config = config
613+
614+ def get_server_description(self):
615+ """Return the description where the pb server is running."""
616+ return defer.succeed(self.config.description.server)
617+
618+
619+class FakeDescriptionFactory(object):
620+ """A fake description factory."""
621+
622+ def __init__(self, server_description, client_description):
623+ """Create a new instace."""
624+ self.server = server_description
625+ self.client = client_description
626
627
628 # Invalid name "callRemote", etc.
629@@ -80,20 +100,33 @@
630
631 def __init__(self):
632 """Initialize this faker."""
633- self.connection_class = namedtuple("Connection", "host port factory")
634+ self.connection_class = namedtuple("Connection",
635+ "host port factory backlog")
636 self.connections = []
637
638- def connectTCP(self, host, port, factory):
639+ def connectTCP(self, host, port, factory, timeout=None, bindAddress=None):
640 """Store the connected factory."""
641- connection = self.connection_class(host, port, factory)
642+ connection = self.connection_class(host, port, factory, None)
643 self.connections.append(connection)
644
645- def listenTCP(self, port, factory, interface):
646+ def listenTCP(self, port, factory, interface=None, backlog=None):
647 """Store the listenning factory."""
648- connection = self.connection_class(interface, port, factory)
649+ connection = self.connection_class(interface, port, factory, backlog)
650 self.connections.append(connection)
651
652
653+class FakeTCP4ClientEndpoint(object):
654+ """A fake tcp4 client."""
655+
656+ def __init__(self, protocol):
657+ """Create a new instance."""
658+ self.protocol = protocol
659+
660+ def connect(self, *args, **kwargs):
661+ """Return the client."""
662+ return defer.succeed(self.protocol)
663+
664+
665 class FakeRemoteClient(object):
666 """A fake RemoteClient."""
667
668@@ -166,7 +199,7 @@
669
670 services = {'dummy': DummyRemoteService}
671 name = 'Dummy Service'
672- port = TEST_PORT
673+ description = TEST_CLIENT_DESCRIPTION
674 cmdline = 'yadda yo'
675
676
677@@ -182,10 +215,19 @@
678
679 clients = {'dummy': DummyRemoteClient}
680 service_name = DummyService.name
681- service_port = DummyService.port
682+ service_port = TEST_SERVER_DESCRIPTION
683 service_cmdline = DummyService.cmdline
684
685
686+class DummyDescription(object):
687+ """Return the descriptions accordingly."""
688+
689+ def __init__(self, client, server):
690+ """Create a new instance."""
691+ self.client = client
692+ self.server = server
693+
694+
695 class BaseIPCTestCase(TCPPbServerTestCase, TestCase):
696 """Set the ipc to a random port for this instance."""
697
698@@ -219,7 +261,7 @@
699
700 @defer.inlineCallbacks
701 def server_listen(server_factory, service_name, activation_cmd,
702- port, reactor=None):
703+ description, reactor=None):
704 """Connect to the local running service."""
705 yield self.listen_server(self.service)
706 defer.returnValue(self.listener)
707@@ -228,7 +270,7 @@
708
709 @defer.inlineCallbacks
710 def client_connect(client_factory, service_name,
711- activation_cmdline, port, reactor=None):
712+ activation_cmdline, description, reactor=None):
713 """Connect the local running client."""
714 yield self.connect_client()
715 self.client.factory = self.client_factory
716@@ -322,12 +364,12 @@
717 # pylint: enable=E1102
718
719
720-class ListenConnectTestCase(BaseIPCTestCase):
721+class TCPListenConnectTestCase(BaseIPCTestCase):
722 """Test suite for the server_listen and client_connect methods."""
723
724 @defer.inlineCallbacks
725 def setUp(self):
726- yield super(ListenConnectTestCase, self).setUp()
727+ yield super(TCPListenConnectTestCase, self).setUp()
728 self.fake_reactor = FakeReactor()
729
730 @defer.inlineCallbacks
731@@ -335,35 +377,60 @@
732 """Test the server_listen function."""
733 self.patch(ipc, "ActivationInstance", FakeActivationInstance)
734
735+ description_factory = FakeDescriptionFactory(TEST_SERVER_DESCRIPTION,
736+ TEST_CLIENT_DESCRIPTION)
737+
738 fake_factory = object()
739 yield ipc.server_listen(fake_factory, TEST_SERVICE,
740- TEST_CMDLINE, TEST_PORT,
741+ TEST_CMDLINE, description_factory,
742 reactor=self.fake_reactor)
743
744 self.assertEqual(len(self.fake_reactor.connections), 1)
745 conn = self.fake_reactor.connections[0]
746- self.assertEqual(conn.port, TEST_PORT)
747 self.assertEqual(conn.factory, fake_factory)
748 self.assertEqual(conn.host, ipc.LOCALHOST)
749
750 @defer.inlineCallbacks
751 def test_client_connect(self):
752 """Test the client_connect function."""
753+ called = []
754 self.patch(ipc, "ActivationClient", FakeActivationClient)
755
756+ protocol = 'protocol'
757+ client = FakeTCP4ClientEndpoint(protocol)
758+
759+ def client_from_string(reactor, description):
760+ """Create a client from the given string."""
761+ called.append(('clientFromString', reactor, description))
762+ return client
763+
764+ self.patch(ipc.endpoints, 'clientFromString', client_from_string)
765+
766+ description_factory = FakeDescriptionFactory(TEST_SERVER_DESCRIPTION,
767+ TEST_CLIENT_DESCRIPTION)
768+
769 fake_factory = object()
770- yield ipc.client_connect(fake_factory, TEST_SERVICE,
771- TEST_CMDLINE, TEST_PORT,
772- reactor=self.fake_reactor)
773-
774- self.assertEqual(len(self.fake_reactor.connections), 1)
775- conn = self.fake_reactor.connections[0]
776- self.assertEqual(conn.port, TEST_PORT)
777- self.assertEqual(conn.factory, fake_factory)
778- self.assertEqual(conn.host, ipc.LOCALHOST)
779-
780-
781-class DummyClientTestCase(BaseIPCTestCase):
782+ returned_protocol = yield ipc.client_connect(fake_factory,
783+ TEST_SERVICE,
784+ TEST_CMDLINE,
785+ description_factory,
786+ reactor=self.fake_reactor)
787+
788+ self.assertIn(('clientFromString', self.fake_reactor,
789+ description_factory.client), called)
790+ self.assertEqual(protocol, returned_protocol)
791+
792+
793+@skipIfOS('win32', 'Unix domain sockets not supported on windows.')
794+class DomainListenConnectTestCase(TCPListenConnectTestCase):
795+ """Test suite for the server_listen and client_connect methods."""
796+
797+ def get_server(self):
798+ """Return the server to be used to run the tests."""
799+ return TidyUnixServer()
800+
801+
802+class TCPDummyClientTestCase(BaseIPCTestCase):
803 """Test the status client class."""
804
805 client_class = DummyClient
806@@ -422,6 +489,15 @@
807 self.assertEqual(0, actual)
808
809
810+@skipIfOS('win32', 'Unix domain sockets not supported on windows.')
811+class DomainDummyClientTestCase(TCPDummyClientTestCase):
812+ """Test the status client class."""
813+
814+ def get_server(self):
815+ """Return the server to be used to run the tests."""
816+ return TidyUnixServer()
817+
818+
819 class RemoteMetaTestCase(TestCase):
820 """Tests for the RemoteMeta metaclass."""
821
822
823=== modified file 'ubuntu_sso/utils/tests/test_tcpactivation.py'
824--- ubuntu_sso/utils/tests/test_tcpactivation.py 2012-04-10 10:43:53 +0000
825+++ ubuntu_sso/utils/tests/test_tcpactivation.py 2012-05-16 10:20:23 +0000
826@@ -1,6 +1,5 @@
827 # -*- coding: utf-8 -*-
828
829-# Author: Alejandro J. Cura <alecu@canonical.com>
830 #
831 # Copyright 2011-2012 Canonical Ltd.
832 #
833@@ -39,6 +38,14 @@
834 from twisted.internet import defer, protocol, reactor, task
835 from twisted.trial.unittest import TestCase
836
837+# pylint: disable=W0611
838+from ubuntuone.devtools.testcases import skipIfOS
839+# pylint: enable=W0611
840+from ubuntuone.devtools.testcases.txsocketserver import (
841+ ServerTestCase,
842+ TidyTCPServer,
843+)
844+
845 from ubuntu_sso.utils import tcpactivation
846 from ubuntu_sso.utils.tcpactivation import (
847 ActivationClient,
848@@ -53,7 +60,8 @@
849
850 SAMPLE_SERVICE = "test_service_name"
851 SAMPLE_CMDLINE = ["python", __file__, "-server"]
852-SAMPLE_PORT = 55555
853+SAMPLE_SERVER_DESCRIPTION = 'tcp:55555:interface=127.0.0.1'
854+SAMPLE_CLIENT_DESCRIPTION = 'tcp:host=127.0.0.1:port=55555'
855
856
857 class FakeServerProtocol(protocol.Protocol):
858@@ -63,25 +71,12 @@
859 """Echo the data received."""
860 self.transport.write(data)
861
862- #pylint:disable=E1101
863- def connectionLost(self, *a):
864- self.factory.onConnectionLost.callback(self)
865- #pylint:enable=E1101
866-
867
868 class FakeServerFactory(protocol.Factory):
869 """A factory for the test server."""
870
871 protocol = FakeServerProtocol
872
873- #pylint:disable=W0201
874- def __init__(self, testcase=None):
875- """Create a new instance for the testcase."""
876- if testcase is not None:
877- self.onConnectionLost = defer.Deferred()
878- testcase.addCleanup(lambda: self.onConnectionLost)
879- #pylint:enable=W0201
880-
881
882 class FakeTransport(object):
883 """A fake transport."""
884@@ -93,6 +88,46 @@
885 self.connectionLost = True
886
887
888+class FakeDescriptionFactory(object):
889+ """A fake description factory."""
890+
891+ def __init__(self, server_description, client_description):
892+ """Create a new instace."""
893+ self.server = server_description
894+ self.client = client_description
895+
896+
897+class FakeConnectedClient(object):
898+ """Fake class use to patch connections."""
899+
900+ def __init__(self, testcase, inner):
901+ """Create a new instance."""
902+ self.testcase = testcase
903+ self.inner = inner
904+
905+ @defer.inlineCallbacks
906+ def connect(self, factory):
907+ """Connect using the given factory."""
908+ # we need to get the class of the factory and patch it
909+ yield self.testcase.connect_client(PortDetectFactory)
910+ self.inner.factory = self.testcase.client_factory
911+ defer.returnValue(self.testcase.connector)
912+
913+
914+class WrapperFactory(object):
915+ """Wrapps a factory so that it can be replaced in a test."""
916+
917+ def __init__(self, factory):
918+ self.factory = None
919+
920+ def __call__(self, *args, **kwargs):
921+ return self
922+
923+ def is_listening(self):
924+ """Return if the service is listening."""
925+ return self.factory.is_listening()
926+
927+
928 class AsyncSleepTestCase(TestCase):
929 """Tests for the async_sleep function."""
930
931@@ -146,7 +181,7 @@
932 @defer.inlineCallbacks
933 def test_is_listening(self):
934 """Test that the deferred returns True when something is listening."""
935- addr = (tcpactivation.LOCALHOST, SAMPLE_PORT)
936+ addr = (tcpactivation.LOCALHOST, SAMPLE_CLIENT_DESCRIPTION)
937 self.factory.buildProtocol(addr)
938 is_listening = yield self.factory.is_listening()
939 self.assertTrue(is_listening)
940@@ -176,7 +211,7 @@
941 @defer.inlineCallbacks
942 def test_connection_works_then_lost(self):
943 """It's not an error if two events happen."""
944- addr = (tcpactivation.LOCALHOST, SAMPLE_PORT)
945+ addr = (tcpactivation.LOCALHOST, SAMPLE_CLIENT_DESCRIPTION)
946 self.factory.buildProtocol(addr)
947 d = self.factory.is_listening()
948 self.factory.clientConnectionLost(None, "test reason")
949@@ -189,26 +224,39 @@
950
951 def test_initialization(self):
952 """Test the constructor."""
953- config = ActivationConfig(SAMPLE_SERVICE, SAMPLE_CMDLINE, SAMPLE_PORT)
954+ config = ActivationConfig(SAMPLE_SERVICE, SAMPLE_CMDLINE,
955+ SAMPLE_CLIENT_DESCRIPTION)
956 self.assertEqual(config.service_name, SAMPLE_SERVICE)
957 self.assertEqual(config.command_line, SAMPLE_CMDLINE)
958- self.assertEqual(config.port, SAMPLE_PORT)
959-
960-
961-class ActivationDetectorTestCase(TestCase):
962+ self.assertEqual(config.description, SAMPLE_CLIENT_DESCRIPTION)
963+
964+
965+class ActivationDetectorTestCase(ServerTestCase):
966 """Tests for the ActivationDetector class."""
967
968+ timeoue = 3
969+
970+ client_description = 'tcp:host=127.0.0.1:port=55555'
971+ server_description = 'tcp:55555:interface=127.0.0.1'
972+
973 @defer.inlineCallbacks
974 def setUp(self):
975 """Initialize this test instance."""
976 yield super(ActivationDetectorTestCase, self).setUp()
977+ self.description_factory = FakeDescriptionFactory(
978+ self.server_description,
979+ self.client_description)
980 self.config = ActivationConfig(SAMPLE_SERVICE, SAMPLE_CMDLINE,
981- SAMPLE_PORT)
982+ self.description_factory)
983+
984+ def get_server(self):
985+ """Return the server to be used to run the tests."""
986+ return TidyTCPServer()
987
988 def test_initialization(self):
989 """Test the constructor."""
990 self.config = ActivationConfig(SAMPLE_SERVICE, SAMPLE_CMDLINE,
991- SAMPLE_PORT)
992+ self.description_factory)
993 ai = ActivationDetector(self.config)
994 self.assertEqual(ai.config, self.config)
995
996@@ -222,11 +270,16 @@
997 @defer.inlineCallbacks
998 def test_is_already_running(self):
999 """The is_already_running method returns True if already started."""
1000- f = FakeServerFactory(self)
1001+ inner = WrapperFactory(None)
1002+
1003+ self.patch(tcpactivation, 'PortDetectFactory', inner)
1004+ client = FakeConnectedClient(self, inner)
1005+
1006+ self.patch(tcpactivation, 'clientFromString',
1007+ lambda *args: client)
1008+
1009+ yield self.listen_server(FakeServerFactory)
1010 # pylint: disable=E1101
1011- listener = reactor.listenTCP(SAMPLE_PORT, f,
1012- interface=tcpactivation.LOCALHOST)
1013- self.addCleanup(defer.maybeDeferred, listener.stopListening)
1014 ad = ActivationDetector(self.config)
1015 result = yield ad.is_already_running()
1016 self.assertTrue(result, "It should be already running.")
1017@@ -237,12 +290,18 @@
1018
1019 timeout = 2
1020
1021+ server_description = 'tcp:55555:interface=127.0.0.1'
1022+ client_description = 'tcp:host=127.0.0.1:port=55555'
1023+
1024 @defer.inlineCallbacks
1025 def setUp(self):
1026 """Initialize this test instance."""
1027 yield super(ActivationClientTestCase, self).setUp()
1028+ self.description_factory = FakeDescriptionFactory(
1029+ self.server_description,
1030+ self.client_description)
1031 self.config = ActivationConfig(SAMPLE_SERVICE, SAMPLE_CMDLINE,
1032- SAMPLE_PORT)
1033+ self.description_factory)
1034
1035 def test_initialization(self):
1036 """Test the constructor."""
1037@@ -250,37 +309,38 @@
1038 self.assertEqual(ac.config, self.config)
1039
1040 @defer.inlineCallbacks
1041- def test_do_get_active_port_running(self):
1042- """Test the _do_get_active_port method when the server is running."""
1043+ def test_do_get_active_description_running(self):
1044+ """Test the _do_get_active_description method when is running."""
1045 ac = ActivationClient(self.config)
1046 self.patch(ac, "is_already_running", lambda: defer.succeed(True))
1047- result = yield ac._do_get_active_port()
1048- self.assertEqual(result, SAMPLE_PORT)
1049+ result = yield ac._do_get_active_description()
1050+ self.assertEqual(result, self.client_description)
1051
1052 @defer.inlineCallbacks
1053- def test_do_get_active_port_not_running(self):
1054- """Test _do_get_active_port method when the server is not running."""
1055+ def test_do_get_active_description_not_running(self):
1056+ """Test _do_get_active_description method when is not running."""
1057 server_spawned = []
1058 ac = ActivationClient(self.config)
1059 self.patch(ac, "_spawn_server",
1060 lambda *args: server_spawned.append(args))
1061 self.patch(ac, "is_already_running", lambda: defer.succeed(False))
1062 self.patch(ac, "_wait_server_active", lambda: defer.succeed(None))
1063- result = yield ac._do_get_active_port()
1064- self.assertEqual(result, SAMPLE_PORT)
1065+ result = yield ac._do_get_active_description()
1066+ self.assertEqual(result, self.client_description)
1067 self.assertEqual(len(server_spawned), 1)
1068
1069- def test_get_active_port_waits_classwide(self):
1070- """Test the get_active_port method locks classwide."""
1071+ def test_get_active_description_waits_classwide(self):
1072+ """Test the get_active_description method locks classwide."""
1073 d = defer.Deferred()
1074 ac1 = ActivationClient(self.config)
1075 ac2 = ActivationClient(self.config)
1076- self.patch(ac1, "_do_get_active_port", lambda: d)
1077- self.patch(ac2, "_do_get_active_port", lambda: defer.succeed(None))
1078- ac1.get_active_port()
1079- d2 = ac2.get_active_port()
1080+ self.patch(ac1, "_do_get_active_description", lambda: d)
1081+ self.patch(ac2, "_do_get_active_description",
1082+ lambda: defer.succeed(None))
1083+ ac1.get_active_client_description()
1084+ d2 = ac2.get_active_client_description()
1085 self.assertFalse(d2.called, "The second must wait for the first.")
1086- d.callback(SAMPLE_PORT)
1087+ d.callback(self.client_description)
1088 self.assertTrue(d2.called, "The second can fire after the first.")
1089
1090 def test_wait_server_active(self):
1091@@ -320,17 +380,27 @@
1092 self.assertEqual(len(popen_calls), 1)
1093
1094
1095-class ActivationInstanceTestCase(TestCase):
1096+class ActivationInstanceTestCase(ServerTestCase):
1097 """Tests for the ActivationServer class."""
1098
1099 timeout = 2
1100
1101+ server_description = 'tcp:55555:interface=127.0.0.1'
1102+ client_description = 'tcp:host=127.0.0.1:port=55555'
1103+
1104 @defer.inlineCallbacks
1105 def setUp(self):
1106 """Initialize this test instance."""
1107 yield super(ActivationInstanceTestCase, self).setUp()
1108+ self.description_factory = FakeDescriptionFactory(
1109+ self.server_description,
1110+ self.client_description)
1111 self.config = ActivationConfig(SAMPLE_SERVICE, SAMPLE_CMDLINE,
1112- SAMPLE_PORT)
1113+ self.description_factory)
1114+
1115+ def get_server(self):
1116+ """Return the server to be used to run the tests."""
1117+ return TidyTCPServer()
1118
1119 def test_initialization(self):
1120 """Test the constructor."""
1121@@ -338,42 +408,48 @@
1122 self.assertEqual(ai.config, self.config)
1123
1124 @defer.inlineCallbacks
1125- def test_get_port(self):
1126- """Test the get_port method."""
1127+ def test_get_sever_description(self):
1128+ """Test the get_description method."""
1129 ai = ActivationInstance(self.config)
1130- port = yield ai.get_port()
1131- self.assertEqual(port, SAMPLE_PORT)
1132+ self.patch(ai, 'is_already_running', lambda: False)
1133+
1134+ description = yield ai.get_server_description()
1135+ self.assertEqual(description, self.server_description)
1136
1137 #pylint:disable=W0201
1138 @defer.inlineCallbacks
1139- def test_get_port_fails_if_service_already_started(self):
1140- """The get_port method fails if service already started."""
1141- ai1 = ActivationInstance(self.config)
1142- port1 = yield ai1.get_port()
1143- f = FakeServerFactory(self)
1144- # pylint: disable=E1101
1145- listener = reactor.listenTCP(port1, f,
1146- interface=tcpactivation.LOCALHOST)
1147- self.addCleanup(listener.stopListening)
1148- ai2 = ActivationInstance(self.config)
1149- yield self.assertFailure(ai2.get_port(), AlreadyStartedError)
1150+ def test_get_description_fails_if_service_already_started(self):
1151+ """The get_description method fails if service already started."""
1152+ inner = WrapperFactory(None)
1153+
1154+ self.patch(tcpactivation, 'PortDetectFactory', inner)
1155+ client = FakeConnectedClient(self, inner)
1156+
1157+ self.patch(tcpactivation, 'clientFromString',
1158+ lambda *args: client)
1159+
1160+ yield self.listen_server(FakeServerFactory)
1161+
1162+ ai = ActivationInstance(self.config)
1163+ yield self.assertFailure(ai.get_server_description(),
1164+ AlreadyStartedError)
1165 #pylint:enable=W0201
1166
1167
1168 def server_test(config):
1169 """An IRL test of the server."""
1170
1171- def got_port(port_number):
1172- """The port number was found."""
1173- print "got server port:", port_number
1174+ def got_description(description):
1175+ """The description was found."""
1176+ print "got server description:", description
1177
1178 # start listening
1179 f = FakeServerFactory()
1180 # pylint: disable=E1101
1181- reactor.listenTCP(port_number, f)
1182+ reactor.listenTCP(description, f)
1183
1184- # try to get the port again
1185- get_port()
1186+ # try to get the description again
1187+ get_description()
1188
1189 def already_started(failure):
1190 """This instance was already started."""
1191@@ -381,15 +457,15 @@
1192 # pylint: disable=E1101
1193 reactor.callLater(3, reactor.stop)
1194
1195- def get_port():
1196- """Try to get the port number."""
1197- get_port_d = ai.get_port()
1198- get_port_d.addCallback(got_port)
1199- get_port_d.addErrback(already_started)
1200+ def get_description():
1201+ """Try to get the description number."""
1202+ get_description_d = ai.get_server_description()
1203+ get_description_d.addCallback(got_description)
1204+ get_description_d.addErrback(already_started)
1205
1206 print "starting the server."
1207 ai = ActivationInstance(config)
1208- get_port()
1209+ get_description()
1210 # pylint: disable=E1101
1211 reactor.run()
1212
1213@@ -398,14 +474,14 @@
1214 """An IRL test of the client."""
1215 print "starting the client."
1216 ac = ActivationClient(config)
1217- d = ac.get_active_port()
1218+ d = ac.get_active_client_description()
1219
1220- def got_port(port_number):
1221- """The port number was found."""
1222- print "client got server port:", port_number
1223+ def got_description(description):
1224+ """The description was found."""
1225+ print "client got server description:", description
1226 reactor.stop()
1227
1228- d.addCallback(got_port)
1229+ d.addCallback(got_description)
1230 # pylint: disable=E1101
1231 reactor.run()
1232
1233@@ -413,7 +489,9 @@
1234 def irl_test():
1235 """Do an IRL test of the client and the server."""
1236 import sys
1237- config = ActivationConfig(SAMPLE_SERVICE, SAMPLE_CMDLINE, SAMPLE_PORT)
1238+ description_f = FakeDescriptionFactory(SAMPLE_SERVER_DESCRIPTION,
1239+ SAMPLE_CLIENT_DESCRIPTION)
1240+ config = ActivationConfig(SAMPLE_SERVICE, SAMPLE_CMDLINE, description_f)
1241 if "-server" in sys.argv[1:]:
1242 server_test(config)
1243 else:

Subscribers

People subscribed via source and target branches