Merge lp:~mandel/ubuntuone-client/domain-sockets into lp:ubuntuone-client
- domain-sockets
- Merge into trunk
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Manuel de la Peña | ||||||||||||
Approved revision: | 1254 | ||||||||||||
Merged at revision: | 1247 | ||||||||||||
Proposed branch: | lp:~mandel/ubuntuone-client/domain-sockets | ||||||||||||
Merge into: | lp:ubuntuone-client | ||||||||||||
Diff against target: |
938 lines (+417/-159) 16 files modified
contrib/testing/testcase.py (+5/-1) tests/platform/__init__.py (+2/-5) tests/platform/ipc/test_darwin.py (+0/-65) tests/platform/ipc/test_perspective_broker.py (+131/-59) tests/platform/ipc/test_unix.py (+50/-0) tests/platform/ipc/test_windows.py (+61/-0) tests/syncdaemon/test_main.py (+4/-0) ubuntuone/platform/ipc/__init__.py (+2/-2) ubuntuone/platform/ipc/ipc_client.py (+5/-2) ubuntuone/platform/ipc/linux.py (+4/-0) ubuntuone/platform/ipc/perspective_broker.py (+43/-24) ubuntuone/platform/ipc/unix.py (+52/-0) ubuntuone/platform/ipc/windows.py (+51/-0) ubuntuone/platform/tools/windows.py (+1/-1) ubuntuone/syncdaemon/interaction_interfaces.py (+5/-0) ubuntuone/syncdaemon/main.py (+1/-0) |
||||||||||||
To merge this branch: | bzr merge lp:~mandel/ubuntuone-client/domain-sockets | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Diego Sarmentero (community) | Approve | ||
Eric Casteleijn (community) | Approve | ||
Review via email: mp+106833@code.launchpad.net |
Description of the change
- Fixed tests on windows by using the new sso api found in trunk and nightlies (LP: #1001296).
- Added support for domain sockets by using endpoints to listen to a socket and description factories (LP:
#1002208).
Please it is important that you run the tests for this branch using at least revno 73 of ubuntuone-
Diego Sarmentero (diegosarmentero) wrote : | # |
As i mention early today, a lot of tests are failing in my windows evil vm.
I'm marking this as need fixing so we can talk tomorrow, if i'm doing something wrong or what is going on.
Ubuntu One Auto Pilot (otto-pilot) wrote : | # |
The attempt to merge lp:~mandel/ubuntuone-client/domain-sockets into lp:ubuntuone-client failed. Below is the output from the failed tests.
/usr/bin/
checking for autoconf >= 2.53...
testing autoconf2.50... not found.
testing autoconf... found 2.68
checking for automake >= 1.10...
testing automake-1.11... found 1.11.3
checking for libtool >= 1.5...
testing libtoolize... found 2.4.2
checking for intltool >= 0.30...
testing intltoolize... found 0.50.2
checking for pkg-config >= 0.14.0...
testing pkg-config... found 0.26
checking for gtk-doc >= 1.0...
testing gtkdocize... found 1.18
Checking for required M4 macros...
Checking for forbidden M4 macros...
Processing ./configure.ac
Running libtoolize...
libtoolize: putting auxiliary files in `.'.
libtoolize: copying file `./ltmain.sh'
libtoolize: putting macros in AC_CONFIG_
libtoolize: copying file `m4/libtool.m4'
libtoolize: copying file `m4/ltoptions.m4'
libtoolize: copying file `m4/ltsugar.m4'
libtoolize: copying file `m4/ltversion.m4'
libtoolize: copying file `m4/lt~obsolete.m4'
Running intltoolize...
Running gtkdocize...
Running aclocal-1.11...
Running autoconf...
Running autoheader...
Running automake-1.11...
Running ./configure --enable-gtk-doc --enable-debug ...
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for style of include used by make... GNU
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking dependency style of gcc... gcc3
checking for library containing strerror... none required
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking dependency style of gcc... (cached) gcc3
checking build system type... i686-pc-linux-gnu
checking host system type... i686-pc-linux-gnu
checking how to print strings... printf
checking for a sed that does not truncate output... /bin/sed
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for fgrep... /bin/grep -F
checking for ld used by gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 1572864
checking whether the shell understands some XSI constructs... yes
checking whether the shell understands "+="... yes
checking how to c...
Preview Diff
1 | === modified file 'contrib/testing/testcase.py' |
2 | --- contrib/testing/testcase.py 2012-05-14 14:46:32 +0000 |
3 | +++ contrib/testing/testcase.py 2012-05-22 16:21:33 +0000 |
4 | @@ -122,8 +122,12 @@ |
5 | class FakeExternalInterface(object): |
6 | """A fake DBusInterface...""" |
7 | |
8 | + def start(self): |
9 | + """... that knows how to start.""" |
10 | + return defer.succeed(None) |
11 | + |
12 | def shutdown(self, with_restart=False): |
13 | - """...that only knows how to go away""" |
14 | + """... how to go away""" |
15 | |
16 | def _request_token(self, *args, **kwargs): |
17 | """Return a token which is a fixed set of credentials.""" |
18 | |
19 | === modified file 'tests/platform/__init__.py' |
20 | --- tests/platform/__init__.py 2012-05-15 18:44:46 +0000 |
21 | +++ tests/platform/__init__.py 2012-05-22 16:21:33 +0000 |
22 | @@ -30,12 +30,9 @@ |
23 | if sys.platform.startswith('linux'): |
24 | from tests.platform.ipc import test_linux |
25 | ipc_source = test_linux |
26 | -elif sys.platform == 'darwin': |
27 | - from tests.platform.ipc import test_darwin |
28 | - ipc_source = test_darwin |
29 | else: |
30 | - from tests.platform.ipc import test_windows |
31 | - ipc_source = test_windows |
32 | + from tests.platform.ipc import test_perspective_broker |
33 | + ipc_source = test_perspective_broker |
34 | |
35 | IPCTestCase = ipc_source.IPCTestCase |
36 | StatusTestCase = ipc_source.StatusTestCase |
37 | |
38 | === removed file 'tests/platform/ipc/test_darwin.py' |
39 | --- tests/platform/ipc/test_darwin.py 2012-05-17 11:59:26 +0000 |
40 | +++ tests/platform/ipc/test_darwin.py 1970-01-01 00:00:00 +0000 |
41 | @@ -1,65 +0,0 @@ |
42 | -# -*- coding: utf-8 -*- |
43 | -# |
44 | -# Copyright 2012 Canonical Ltd. |
45 | -# |
46 | -# This program is free software: you can redistribute it and/or modify it |
47 | -# under the terms of the GNU General Public License version 3, as published |
48 | -# by the Free Software Foundation. |
49 | -# |
50 | -# This program is distributed in the hope that it will be useful, but |
51 | -# WITHOUT ANY WARRANTY; without even the implied warranties of |
52 | -# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
53 | -# PURPOSE. See the GNU General Public License for more details. |
54 | -# |
55 | -# You should have received a copy of the GNU General Public License along |
56 | -# with this program. If not, see <http://www.gnu.org/licenses/>. |
57 | -# |
58 | -# In addition, as a special exception, the copyright holders give |
59 | -# permission to link the code of portions of this program with the |
60 | -# OpenSSL library under certain conditions as described in each |
61 | -# individual source file, and distribute linked combinations |
62 | -# including the two. |
63 | -# You must obey the GNU General Public License in all respects |
64 | -# for all of the code used other than OpenSSL. If you modify |
65 | -# file(s) with this exception, you may extend this exception to your |
66 | -# version of the file(s), but you are not obligated to do so. If you |
67 | -# do not wish to do so, delete this exception statement from your |
68 | -# version. If you delete this exception statement from all source |
69 | -# files in the program, then also delete it here. |
70 | -"""Tests for the IPC interface.""" |
71 | - |
72 | - |
73 | -class IPCTestCase(object): |
74 | - """Empty Implementation""" |
75 | - |
76 | - |
77 | -class StatusTestCase(object): |
78 | - """Empty Implementation""" |
79 | - |
80 | - |
81 | -class EventsTestCase(object): |
82 | - """Empty Implementation""" |
83 | - |
84 | - |
85 | -class SyncDaemonTestCase(object): |
86 | - """Empty Implementation""" |
87 | - |
88 | - |
89 | -class FileSystemTestCase(object): |
90 | - """Empty Implementation""" |
91 | - |
92 | - |
93 | -class SharesTestCase(object): |
94 | - """Empty Implementation""" |
95 | - |
96 | - |
97 | -class ConfigTestCase(object): |
98 | - """Empty Implementation""" |
99 | - |
100 | - |
101 | -class FoldersTestCase(object): |
102 | - """Empty Implementation""" |
103 | - |
104 | - |
105 | -class PublicFilesTestCase(object): |
106 | - """Empty Implementation""" |
107 | |
108 | === renamed file 'tests/platform/ipc/test_windows.py' => 'tests/platform/ipc/test_perspective_broker.py' |
109 | --- tests/platform/ipc/test_windows.py 2012-04-30 14:24:55 +0000 |
110 | +++ tests/platform/ipc/test_perspective_broker.py 2012-05-22 16:21:33 +0000 |
111 | @@ -26,17 +26,16 @@ |
112 | # do not wish to do so, delete this exception statement from your |
113 | # version. If you delete this exception statement from all source |
114 | # files in the program, then also delete it here. |
115 | -"""IPC tests on windows.""" |
116 | - |
117 | -from collections import namedtuple |
118 | +"""IPC tests on perspective broker.""" |
119 | +import os |
120 | |
121 | from mocker import MockerTestCase, ANY |
122 | |
123 | +from dirspec import basedir |
124 | from twisted.internet import defer |
125 | from twisted.spread.pb import ( |
126 | DeadReferenceError, |
127 | NoSuchMethod, |
128 | - PBClientFactory, |
129 | RemoteReference, |
130 | ) |
131 | from twisted.trial.unittest import TestCase |
132 | @@ -45,8 +44,13 @@ |
133 | FakedService, |
134 | FakeMainTestCase, |
135 | ) |
136 | -from ubuntuone.platform.ipc import windows as ipc |
137 | -from ubuntuone.platform.ipc.windows import ( |
138 | +from ubuntuone.devtools.testcases import skipIfOS |
139 | +from ubuntuone.devtools.testcases.txsocketserver import ( |
140 | + TidyUnixServer, |
141 | + TCPPbServerTestCase, |
142 | +) |
143 | +from ubuntuone.platform.ipc import perspective_broker as ipc |
144 | +from ubuntuone.platform.ipc.perspective_broker import ( |
145 | Config, |
146 | Events, |
147 | Folders, |
148 | @@ -57,7 +61,6 @@ |
149 | SignalBroadcaster, |
150 | Status, |
151 | SyncDaemon, |
152 | - ipc_client_connect, |
153 | ) |
154 | from ubuntuone.platform.ipc.ipc_client import ( |
155 | signal, |
156 | @@ -71,9 +74,11 @@ |
157 | SyncDaemonClient, |
158 | SharesClient, |
159 | ) |
160 | +from ubuntuone.syncdaemon import interaction_interfaces |
161 | |
162 | |
163 | TEST_PORT = 40404 |
164 | +TEST_DOMAIN_SOCKET = os.path.join(basedir.xdg_cache_home, 'ubuntuone', 'ipc') |
165 | |
166 | |
167 | class RandomException(Exception): |
168 | @@ -87,23 +92,9 @@ |
169 | """Initialize this fake instance.""" |
170 | self.config = config |
171 | |
172 | - def get_active_port(self): |
173 | + def get_active_client_description(self): |
174 | """Return the port where the pb server is running.""" |
175 | - return defer.succeed(self.config.port) |
176 | - |
177 | - |
178 | -class FakeReactor(object): |
179 | - """A fake reactor.""" |
180 | - |
181 | - def __init__(self): |
182 | - """Initialize this faker.""" |
183 | - self.connection_class = namedtuple("Connection", "host port factory") |
184 | - self.connections = [] |
185 | - |
186 | - def connectTCP(self, host, port, factory): |
187 | - """Store the connected factory.""" |
188 | - connection = self.connection_class(host, port, factory) |
189 | - self.connections.append(connection) |
190 | + return defer.succeed(self.config.description.client) |
191 | |
192 | |
193 | class FakeDecoratedObject(object): |
194 | @@ -373,7 +364,7 @@ |
195 | self.assertEqual(fake_remote_object.called, expected) |
196 | |
197 | |
198 | -class IPCTestCase(FakeMainTestCase): |
199 | +class IPCTestCase(FakeMainTestCase, TCPPbServerTestCase): |
200 | """Set the ipc to a random port for this instance.""" |
201 | |
202 | timeout = 5 |
203 | @@ -385,22 +376,45 @@ |
204 | @defer.inlineCallbacks |
205 | def setUp(self): |
206 | """Initialize this test instance.""" |
207 | - self.patch(ipc, "get_sd_pb_port", lambda: TEST_PORT) |
208 | - self.patch(ipc, "ActivationClient", FakeActivationClient) |
209 | + self.patch(ipc, 'ActivationClient', FakeActivationClient) |
210 | + # patch the interaction interfaces to not choose the system one but |
211 | + # always the perspective broker one |
212 | + self.patch(interaction_interfaces, 'ExternalInterface', ipc.IPCInterface) |
213 | |
214 | yield super(IPCTestCase, self).setUp() |
215 | |
216 | + class FakeDescriptionFactory(object): |
217 | + """Factory used that returns settings for the test.""" |
218 | + |
219 | + def __init__(my_self): |
220 | + """Create a new instance.""" |
221 | + my_self.server = self.server_runner.get_server_endpoint() |
222 | + my_self.client = self.server_runner.get_client_endpoint() |
223 | + |
224 | + # patch the description facotry to return the settings used by the |
225 | + # test |
226 | + self.patch(ipc, 'DescriptionFactory', FakeDescriptionFactory) |
227 | + |
228 | self.bus = None # parity with linux code |
229 | |
230 | self.service = self.service_class(main=self.main, send_events=True) |
231 | self.service.oauth_credentials = ('foo', 'bar') |
232 | - yield self.service.connect() |
233 | - |
234 | - self.addCleanup(self.service.shutdown) |
235 | + |
236 | + # patch the way the ipc interface is started so that we use the clean |
237 | + # method provided by the test case |
238 | + |
239 | + @defer.inlineCallbacks |
240 | + def server_listen(*args): |
241 | + """Start listening using the interface.""" |
242 | + yield self.listen_server(self.service.interface) |
243 | + self.service.interface.listener = self.listener |
244 | + defer.returnValue(self.listener) |
245 | + |
246 | + self.patch(ipc, 'ipc_server_listen', server_listen) |
247 | + self.connector = yield self.service.start() |
248 | + self.service.connect() |
249 | + |
250 | self.interface = self.service.interface |
251 | - self.client_factory = PBClientFactory() |
252 | - self.connector = yield ipc_client_connect(self.client_factory) |
253 | - self.addCleanup(self.connector.disconnect) |
254 | |
255 | if self.client_name is not None: |
256 | client = getattr(self.interface, self.client_name) |
257 | @@ -410,6 +424,7 @@ |
258 | def get_client(self): |
259 | """Get the client.""" |
260 | # request the remote object and create a client |
261 | + yield self.connect_client() |
262 | root = yield self.client_factory.getRootObject() |
263 | if self.client_name is not None: |
264 | remote = yield root.callRemote('get_%s' % self.client_name) |
265 | @@ -422,7 +437,6 @@ |
266 | result = client |
267 | else: |
268 | result = root |
269 | - |
270 | defer.returnValue(result) |
271 | |
272 | @defer.inlineCallbacks |
273 | @@ -480,74 +494,131 @@ |
274 | expected signature. |
275 | |
276 | """ |
277 | + |
278 | for signal_name, args in self.signal_mapping: |
279 | self.assert_remote_signal(signal_name, *args) |
280 | |
281 | |
282 | -class IPCFunctionsTestCase(IPCTestCase): |
283 | - """Test the functions in the ubuntuone.platform.windows.ipc module.""" |
284 | - |
285 | - @defer.inlineCallbacks |
286 | - def test_connect(self): |
287 | - """Test the ipc_client_connect function.""" |
288 | - fake_reactor = FakeReactor() |
289 | - self.patch(ipc, "reactor", fake_reactor) |
290 | - fake_factory = object() |
291 | - yield ipc_client_connect(fake_factory) |
292 | - self.assertEqual(len(fake_reactor.connections), 1) |
293 | - c = fake_reactor.connections[0] |
294 | - self.assertEqual(c.port, TEST_PORT) |
295 | - self.assertEqual(c.factory, fake_factory) |
296 | - |
297 | - |
298 | class StatusTestCase(IPCTestCase): |
299 | """Test the status client class.""" |
300 | |
301 | client_class = StatusClient |
302 | |
303 | |
304 | +@skipIfOS('win32', 'Unix domain sockets not supported on windows.') |
305 | +class DUSStatusTestCase(StatusTestCase): |
306 | + """Test the status client class.""" |
307 | + |
308 | + def get_server(self): |
309 | + """Return the server to be used to run the tests.""" |
310 | + return TidyUnixServer() |
311 | + |
312 | + |
313 | class EventsTestCase(IPCTestCase): |
314 | """Test the events client class.""" |
315 | |
316 | client_class = EventsClient |
317 | |
318 | |
319 | +@skipIfOS('win32', 'Unix domain sockets not supported on windows.') |
320 | +class DUSEventsTestCase(EventsTestCase): |
321 | + """Test the events client class.""" |
322 | + |
323 | + def get_server(self): |
324 | + """Return the server to be used to run the tests.""" |
325 | + return TidyUnixServer() |
326 | + |
327 | + |
328 | class SyncDaemonTestCase(IPCTestCase): |
329 | """Test the syncdaemon client class.""" |
330 | |
331 | client_class = SyncDaemonClient |
332 | |
333 | |
334 | +@skipIfOS('win32', 'Unix domain sockets not supported on windows.') |
335 | +class DUSSyncDaemonTestCase(SyncDaemonTestCase): |
336 | + """Test the syncdaemon client class.""" |
337 | + |
338 | + def get_server(self): |
339 | + """Return the server to be used to run the tests.""" |
340 | + return TidyUnixServer() |
341 | + |
342 | + |
343 | class FileSystemTestCase(IPCTestCase): |
344 | """Test the file system client class.""" |
345 | |
346 | client_class = FileSystemClient |
347 | |
348 | |
349 | +@skipIfOS('win32', 'Unix domain sockets not supported on windows.') |
350 | +class DUSFileSystemTestCase(FileSystemTestCase): |
351 | + """Test the file system client class.""" |
352 | + |
353 | + def get_server(self): |
354 | + """Return the server to be used to run the tests.""" |
355 | + return TidyUnixServer() |
356 | + |
357 | + |
358 | class SharesTestCase(IPCTestCase): |
359 | """Test the shares client class.""" |
360 | |
361 | client_class = SharesClient |
362 | |
363 | |
364 | +@skipIfOS('win32', 'Unix domain sockets not supported on windows.') |
365 | +class DUSSharesTestCase(SharesTestCase): |
366 | + """Test the shares client class.""" |
367 | + |
368 | + def get_server(self): |
369 | + """Return the server to be used to run the tests.""" |
370 | + return TidyUnixServer() |
371 | + |
372 | + |
373 | class ConfigTestCase(IPCTestCase): |
374 | """Test the status client class.""" |
375 | |
376 | client_class = ConfigClient |
377 | |
378 | |
379 | +@skipIfOS('win32', 'Unix domain sockets not supported on windows.') |
380 | +class DUSConfigTestCase(ConfigTestCase): |
381 | + """Test the status client class.""" |
382 | + |
383 | + def get_server(self): |
384 | + """Return the server to be used to run the tests.""" |
385 | + return TidyUnixServer() |
386 | + |
387 | + |
388 | class FoldersTestCase(IPCTestCase): |
389 | """Test the status client class.""" |
390 | |
391 | client_class = FoldersClient |
392 | |
393 | |
394 | +@skipIfOS('win32', 'Unix domain sockets not supported on windows.') |
395 | +class DUSFoldersTestCase(FoldersTestCase): |
396 | + """Test the status client class.""" |
397 | + |
398 | + def get_server(self): |
399 | + """Return the server to be used to run the tests.""" |
400 | + return TidyUnixServer() |
401 | + |
402 | + |
403 | class PublicFilesTestCase(IPCTestCase): |
404 | """Test the status client class.""" |
405 | |
406 | client_class = PublicFilesClient |
407 | |
408 | |
409 | +@skipIfOS('win32', 'Unix domain sockets not supported on windows.') |
410 | +class DUSPublicFilesTestCase(PublicFilesTestCase): |
411 | + """Test the status client class.""" |
412 | + |
413 | + def get_server(self): |
414 | + """Return the server to be used to run the tests.""" |
415 | + return TidyUnixServer() |
416 | + |
417 | + |
418 | class RemoteMetaTestCase(TestCase): |
419 | """Tests for the RemoteMeta metaclass.""" |
420 | |
421 | @@ -666,21 +737,22 @@ |
422 | self.assertIsInstance(remote, RemoteReference) |
423 | |
424 | |
425 | +@skipIfOS('win32', 'Unix domain sockets not supported on windows.') |
426 | +class DUSInterfaceTestCase(IPCInterfaceTestCase): |
427 | + """Ensure that the IPCInterface works as expected.""" |
428 | + |
429 | + def get_server(self): |
430 | + """Return the server to be used to run the tests.""" |
431 | + return TidyUnixServer() |
432 | + |
433 | + |
434 | class IPCPortTestCase(TestCase): |
435 | """Tests for the ipc port setup.""" |
436 | |
437 | - def test_get_sd_pb_port(self): |
438 | - """A test for the get_sd_pb_port function.""" |
439 | - sso_port = 50001 |
440 | - self.patch(ipc, "get_sso_pb_port", lambda: sso_port) |
441 | - result = ipc.get_sd_pb_port() |
442 | - expected = sso_port + ipc.SD_SSO_PORT_OFFSET |
443 | - self.assertEqual(result, expected) |
444 | - |
445 | @defer.inlineCallbacks |
446 | def test_is_already_running_no(self): |
447 | """Test the is_already_running function.""" |
448 | - self.patch(ipc.ActivationInstance, "get_port", |
449 | + self.patch(ipc.ActivationInstance, "get_server_description", |
450 | lambda _: defer.succeed(TEST_PORT)) |
451 | is_running = yield ipc.is_already_running() |
452 | self.assertFalse(is_running, "Should not be running.") |
453 | @@ -688,7 +760,7 @@ |
454 | @defer.inlineCallbacks |
455 | def test_is_already_running_yes(self): |
456 | """Test the is_already_running function.""" |
457 | - self.patch(ipc.ActivationInstance, "get_port", |
458 | + self.patch(ipc.ActivationInstance, "get_server_description", |
459 | lambda _: defer.fail(ipc.AlreadyStartedError())) |
460 | is_running = yield ipc.is_already_running() |
461 | self.assertTrue(is_running, "Should be running by now.") |
462 | |
463 | === added file 'tests/platform/ipc/test_unix.py' |
464 | --- tests/platform/ipc/test_unix.py 1970-01-01 00:00:00 +0000 |
465 | +++ tests/platform/ipc/test_unix.py 2012-05-22 16:21:33 +0000 |
466 | @@ -0,0 +1,50 @@ |
467 | +# -*- coding: utf-8 -*- |
468 | +# |
469 | +# Copyright 2012 Canonical Ltd. |
470 | +# |
471 | +# This program is free software: you can redistribute it and/or modify it |
472 | +# under the terms of the GNU General Public License version 3, as published |
473 | +# by the Free Software Foundation. |
474 | +# |
475 | +# This program is distributed in the hope that it will be useful, but |
476 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
477 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
478 | +# PURPOSE. See the GNU General Public License for more details. |
479 | +# |
480 | +# You should have received a copy of the GNU General Public License along |
481 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
482 | +# |
483 | +# In addition, as a special exception, the copyright holders give |
484 | +# permission to link the code of portions of this program with the |
485 | +# OpenSSL library under certain conditions as described in each |
486 | +# individual source file, and distribute linked combinations |
487 | +# including the two. |
488 | +# You must obey the GNU General Public License in all respects |
489 | +# for all of the code used other than OpenSSL. If you modify |
490 | +# file(s) with this exception, you may extend this exception to your |
491 | +# version of the file(s), but you are not obligated to do so. If you |
492 | +# do not wish to do so, delete this exception statement from your |
493 | +# version. If you delete this exception statement from all source |
494 | +# files in the program, then also delete it here. |
495 | +"""Tests for the unix ipc.""" |
496 | + |
497 | +from twisted.trial.unittest import TestCase |
498 | + |
499 | +from ubuntuone.platform.ipc import unix |
500 | + |
501 | + |
502 | +class DescriptionFactoryTestCase(TestCase): |
503 | + """Tests for the description factory test.""" |
504 | + |
505 | + def test_init(self): |
506 | + """Test that we correctly init the factory.""" |
507 | + path = '/path/to/socket' |
508 | + |
509 | + self.patch(unix, 'get_u1_domain_socket', lambda: path) |
510 | + |
511 | + factory = unix.DescriptionFactory() |
512 | + self.assertEqual(factory.server_description_pattern % path, |
513 | + factory.server) |
514 | + self.assertEqual(factory.client_description_pattern % path, |
515 | + factory.client) |
516 | + |
517 | |
518 | === added file 'tests/platform/ipc/test_windows.py' |
519 | --- tests/platform/ipc/test_windows.py 1970-01-01 00:00:00 +0000 |
520 | +++ tests/platform/ipc/test_windows.py 2012-05-22 16:21:33 +0000 |
521 | @@ -0,0 +1,61 @@ |
522 | +# -*- coding: utf-8 -*- |
523 | +# |
524 | +# Copyright 2012 Canonical Ltd. |
525 | +# |
526 | +# This program is free software: you can redistribute it and/or modify it |
527 | +# under the terms of the GNU General Public License version 3, as published |
528 | +# by the Free Software Foundation. |
529 | +# |
530 | +# This program is distributed in the hope that it will be useful, but |
531 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
532 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
533 | +# PURPOSE. See the GNU General Public License for more details. |
534 | +# |
535 | +# You should have received a copy of the GNU General Public License along |
536 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
537 | +# |
538 | +# In addition, as a special exception, the copyright holders give |
539 | +# permission to link the code of portions of this program with the |
540 | +# OpenSSL library under certain conditions as described in each |
541 | +# individual source file, and distribute linked combinations |
542 | +# including the two. |
543 | +# You must obey the GNU General Public License in all respects |
544 | +# for all of the code used other than OpenSSL. If you modify |
545 | +# file(s) with this exception, you may extend this exception to your |
546 | +# version of the file(s), but you are not obligated to do so. If you |
547 | +# do not wish to do so, delete this exception statement from your |
548 | +# version. If you delete this exception statement from all source |
549 | +# files in the program, then also delete it here. |
550 | +"""Tests for the windows ipc.""" |
551 | + |
552 | +from twisted.trial.unittest import TestCase |
553 | + |
554 | +from ubuntuone.platform.ipc import windows |
555 | + |
556 | + |
557 | +class IPCPortTestCase(TestCase): |
558 | + """Tests for the ipc port setup.""" |
559 | + |
560 | + def test_get_sd_pb_port(self): |
561 | + """A test for the get_sd_pb_port function.""" |
562 | + sso_port = 50001 |
563 | + self.patch(windows, "get_sso_pb_port", lambda: sso_port) |
564 | + result = windows.get_sd_pb_port() |
565 | + expected = sso_port + windows.SD_SSO_PORT_OFFSET |
566 | + self.assertEqual(result, expected) |
567 | + |
568 | + |
569 | +class DescriptionFactoryTestCase(TestCase): |
570 | + """Tests for the description factory test.""" |
571 | + |
572 | + def test_init(self): |
573 | + """Test that we correctly init the factory.""" |
574 | + port = 11111 |
575 | + self.patch(windows, 'get_sd_pb_port', lambda: port) |
576 | + |
577 | + factory = windows.DescriptionFactory() |
578 | + self.assertEqual(factory.server_description_pattern % port, |
579 | + factory.server) |
580 | + self.assertEqual(factory.client_description_pattern % port, |
581 | + factory.client) |
582 | + |
583 | |
584 | === modified file 'tests/syncdaemon/test_main.py' |
585 | --- tests/syncdaemon/test_main.py 2012-04-09 20:07:05 +0000 |
586 | +++ tests/syncdaemon/test_main.py 2012-05-22 16:21:33 +0000 |
587 | @@ -65,6 +65,10 @@ |
588 | self.connect = lambda *a, **kw: self._called.append(('connect', a, kw)) |
589 | self.shutdown = lambda *a, **kw: None |
590 | |
591 | + def start(self): |
592 | + """Do nothing.""" |
593 | + return defer.succeed(None) |
594 | + |
595 | |
596 | class MainTests(BaseTwistedTestCase): |
597 | """ Basic tests to check main.Main """ |
598 | |
599 | === modified file 'ubuntuone/platform/ipc/__init__.py' |
600 | --- ubuntuone/platform/ipc/__init__.py 2012-05-15 14:56:44 +0000 |
601 | +++ ubuntuone/platform/ipc/__init__.py 2012-05-22 16:21:33 +0000 |
602 | @@ -31,8 +31,8 @@ |
603 | import sys |
604 | |
605 | |
606 | -if sys.platform == "win32": |
607 | - from ubuntuone.platform.ipc import windows as source |
608 | +if sys.platform in ('win32', 'darwin'): |
609 | + from ubuntuone.platform.ipc import perspective_broker as source |
610 | ExternalInterface = source.IPCInterface |
611 | elif sys.platform == "darwin": |
612 | from ubuntuone.platform.ipc import darwin as source |
613 | |
614 | === modified file 'ubuntuone/platform/ipc/ipc_client.py' |
615 | --- ubuntuone/platform/ipc/ipc_client.py 2012-04-30 14:24:55 +0000 |
616 | +++ ubuntuone/platform/ipc/ipc_client.py 2012-05-22 16:21:33 +0000 |
617 | @@ -34,7 +34,10 @@ |
618 | from twisted.internet import defer |
619 | from twisted.spread.pb import Referenceable, PBClientFactory |
620 | |
621 | -from ubuntuone.platform.ipc.windows import RemoteMeta, ipc_client_connect |
622 | +from ubuntuone.platform.ipc.perspective_broker import ( |
623 | + RemoteMeta, |
624 | + ipc_client_connect, |
625 | +) |
626 | |
627 | logger = logging.getLogger("ubuntuone.SyncDaemon.Client") |
628 | |
629 | @@ -786,4 +789,4 @@ |
630 | def disconnect(self): |
631 | """Disconnect from the process.""" |
632 | if self.client: |
633 | - self.client.disconnect() |
634 | + self.client.transport.loseConnection() |
635 | |
636 | === modified file 'ubuntuone/platform/ipc/linux.py' |
637 | --- ubuntuone/platform/ipc/linux.py 2012-05-02 19:07:59 +0000 |
638 | +++ ubuntuone/platform/ipc/linux.py 2012-05-22 16:21:33 +0000 |
639 | @@ -861,6 +861,10 @@ |
640 | |
641 | logger.info('DBusInterface initialized.') |
642 | |
643 | + def start(self): |
644 | + """Start listening for ipc messages.""" |
645 | + return defer.succeed(None) |
646 | + |
647 | def shutdown(self, with_restart=False): |
648 | """Remove the registered object from the bus.""" |
649 | logger.info('Shutting down DBusInterface!') |
650 | |
651 | === renamed file 'ubuntuone/platform/ipc/windows.py' => 'ubuntuone/platform/ipc/perspective_broker.py' |
652 | --- ubuntuone/platform/ipc/windows.py 2012-04-30 14:24:55 +0000 |
653 | +++ ubuntuone/platform/ipc/perspective_broker.py 2012-05-22 16:21:33 +0000 |
654 | @@ -26,15 +26,16 @@ |
655 | # do not wish to do so, delete this exception statement from your |
656 | # version. If you delete this exception statement from all source |
657 | # files in the program, then also delete it here. |
658 | -"""IPC implementation for windows.""" |
659 | +"""IPC implementation using perspective broker.""" |
660 | |
661 | import logging |
662 | +import sys |
663 | import warnings |
664 | |
665 | from functools import wraps |
666 | from collections import defaultdict |
667 | |
668 | -from twisted.internet import defer, reactor |
669 | +from twisted.internet import defer, endpoints |
670 | from twisted.spread.pb import ( |
671 | DeadReferenceError, |
672 | NoSuchMethod, |
673 | @@ -42,7 +43,7 @@ |
674 | Referenceable, |
675 | Root, |
676 | ) |
677 | -from ubuntu_sso.main.windows import get_activation_cmdline, get_sso_pb_port |
678 | +from ubuntu_sso.main import get_activation_cmdline |
679 | from ubuntu_sso.utils.tcpactivation import ( |
680 | ActivationClient, |
681 | ActivationConfig, |
682 | @@ -50,31 +51,41 @@ |
683 | AlreadyStartedError, |
684 | ) |
685 | |
686 | +# we do not do from package import as source becauser pyflakes will complain |
687 | +if sys.platform == 'win32': |
688 | + from ubuntuone.platform.ipc import windows |
689 | + source = windows |
690 | +else: |
691 | + from ubuntuone.platform.ipc import unix |
692 | + source = unix |
693 | + |
694 | +DescriptionFactory = source.DescriptionFactory |
695 | + |
696 | logger = logging.getLogger("ubuntuone.SyncDaemon.Pb") |
697 | -LOCALHOST = "127.0.0.1" |
698 | SD_SSO_PORT_OFFSET = 1 |
699 | SD_SERVICE_NAME = "ubuntuone-syncdaemon" |
700 | CLIENT_NOT_PROCESSED = -1 |
701 | |
702 | |
703 | -def get_sd_pb_port(): |
704 | - """Returns the host and port for this user.""" |
705 | - return get_sso_pb_port() + SD_SSO_PORT_OFFSET |
706 | - |
707 | - |
708 | def get_activation_config(): |
709 | """Get the configuration to activate the sso service.""" |
710 | - port = get_sd_pb_port() |
711 | + description = DescriptionFactory() |
712 | service_name = SD_SERVICE_NAME |
713 | cmdline = get_activation_cmdline(service_name) |
714 | - return ActivationConfig(service_name, cmdline, port) |
715 | - |
716 | - |
717 | -def ipc_server_listen(server_factory): |
718 | + return ActivationConfig(service_name, cmdline, description) |
719 | + |
720 | + |
721 | +@defer.inlineCallbacks |
722 | +def ipc_server_listen(server_factory, reactor=None): |
723 | """Connect the IPC server factory.""" |
724 | - port = get_sd_pb_port() |
725 | - # pylint: disable=E1101 |
726 | - return reactor.listenTCP(port, server_factory, interface=LOCALHOST) |
727 | + description = DescriptionFactory() |
728 | + |
729 | + if reactor is None: |
730 | + from twisted.internet import reactor |
731 | + |
732 | + server = endpoints.serverFromString(reactor, description.server) |
733 | + connector = yield server.listen(server_factory) |
734 | + defer.returnValue(connector) |
735 | |
736 | |
737 | @defer.inlineCallbacks |
738 | @@ -82,20 +93,24 @@ |
739 | """Return if the sd is running by trying to get the port.""" |
740 | ai = ActivationInstance(get_activation_config()) |
741 | try: |
742 | - yield ai.get_port() |
743 | + yield ai.get_server_description() |
744 | defer.returnValue(False) |
745 | except AlreadyStartedError: |
746 | defer.returnValue(True) |
747 | |
748 | |
749 | @defer.inlineCallbacks |
750 | -def ipc_client_connect(client_factory): |
751 | +def ipc_client_connect(client_factory, reactor=None): |
752 | """Connect the IPC client factory.""" |
753 | ac = ActivationClient(get_activation_config()) |
754 | - port = yield ac.get_active_port() |
755 | - # pylint: disable=E1101 |
756 | - connector = reactor.connectTCP(LOCALHOST, port, client_factory) |
757 | - defer.returnValue(connector) |
758 | + |
759 | + if reactor is None: |
760 | + from twisted.internet import reactor |
761 | + |
762 | + description = yield ac.get_active_client_description() |
763 | + client = endpoints.clientFromString(reactor, description) |
764 | + port = yield client.connect(client_factory) |
765 | + defer.returnValue(port) |
766 | |
767 | |
768 | def remote_handler(handler): |
769 | @@ -951,10 +966,14 @@ |
770 | self.public_files = PublicFiles(service) |
771 | self.config = Config(service) |
772 | self.factory = PBServerFactory(self) |
773 | - self.listener = ipc_server_listen(self.factory) |
774 | |
775 | logger.info('IPC initialized.') |
776 | |
777 | + @defer.inlineCallbacks |
778 | + def start(self): |
779 | + """Start listening for ipc messages.""" |
780 | + self.listener = yield ipc_server_listen(self.factory) |
781 | + |
782 | def shutdown(self, with_restart=False): |
783 | """Remove the registered objects.""" |
784 | logger.info('Shutting down IPC!') |
785 | |
786 | === added file 'ubuntuone/platform/ipc/unix.py' |
787 | --- ubuntuone/platform/ipc/unix.py 1970-01-01 00:00:00 +0000 |
788 | +++ ubuntuone/platform/ipc/unix.py 2012-05-22 16:21:33 +0000 |
789 | @@ -0,0 +1,52 @@ |
790 | +# -*- coding: utf-8 -*- |
791 | +# |
792 | +# Copyright 2012 Canonical Ltd. |
793 | +# |
794 | +# This program is free software: you can redistribute it and/or modify it |
795 | +# under the terms of the GNU General Public License version 3, as published |
796 | +# by the Free Software Foundation. |
797 | +# |
798 | +# This program is distributed in the hope that it will be useful, but |
799 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
800 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
801 | +# PURPOSE. See the GNU General Public License for more details. |
802 | +# |
803 | +# You should have received a copy of the GNU General Public License along |
804 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
805 | +# |
806 | +# In addition, as a special exception, the copyright holders give |
807 | +# permission to link the code of portions of this program with the |
808 | +# OpenSSL library under certain conditions as described in each |
809 | +# individual source file, and distribute linked combinations |
810 | +# including the two. |
811 | +# You must obey the GNU General Public License in all respects |
812 | +# for all of the code used other than OpenSSL. If you modify |
813 | +# file(s) with this exception, you may extend this exception to your |
814 | +# version of the file(s), but you are not obligated to do so. If you |
815 | +# do not wish to do so, delete this exception statement from your |
816 | +# version. If you delete this exception statement from all source |
817 | +# files in the program, then also delete it here. |
818 | +"""IPC implementation for unix.""" |
819 | + |
820 | +import os |
821 | + |
822 | +from dirspec import basedir |
823 | + |
824 | + |
825 | +def get_u1_domain_socket(): |
826 | + """Compute the domain socket for the sso ipc.""" |
827 | + path = os.path.join(basedir.xdg_cache_home, 'ubuntuone', 'ipc') |
828 | + return path |
829 | + |
830 | + |
831 | +class DescriptionFactory(object): |
832 | + """Factory that provides the server and client descriptions.""" |
833 | + |
834 | + client_description_pattern = 'unix:path=%s' |
835 | + server_description_pattern = 'unix:%s' |
836 | + |
837 | + def __init__(self): |
838 | + """Create a new instance.""" |
839 | + self.domain = get_u1_domain_socket() |
840 | + self.server = self.server_description_pattern % self.domain |
841 | + self.client = self.client_description_pattern % self.domain |
842 | |
843 | === added file 'ubuntuone/platform/ipc/windows.py' |
844 | --- ubuntuone/platform/ipc/windows.py 1970-01-01 00:00:00 +0000 |
845 | +++ ubuntuone/platform/ipc/windows.py 2012-05-22 16:21:33 +0000 |
846 | @@ -0,0 +1,51 @@ |
847 | +# -*- coding: utf-8 -*- |
848 | +# |
849 | +# Copyright 2012 Canonical Ltd. |
850 | +# |
851 | +# This program is free software: you can redistribute it and/or modify it |
852 | +# under the terms of the GNU General Public License version 3, as published |
853 | +# by the Free Software Foundation. |
854 | +# |
855 | +# This program is distributed in the hope that it will be useful, but |
856 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
857 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
858 | +# PURPOSE. See the GNU General Public License for more details. |
859 | +# |
860 | +# You should have received a copy of the GNU General Public License along |
861 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
862 | +# |
863 | +# In addition, as a special exception, the copyright holders give |
864 | +# permission to link the code of portions of this program with the |
865 | +# OpenSSL library under certain conditions as described in each |
866 | +# individual source file, and distribute linked combinations |
867 | +# including the two. |
868 | +# You must obey the GNU General Public License in all respects |
869 | +# for all of the code used other than OpenSSL. If you modify |
870 | +# file(s) with this exception, you may extend this exception to your |
871 | +# version of the file(s), but you are not obligated to do so. If you |
872 | +# do not wish to do so, delete this exception statement from your |
873 | +# version. If you delete this exception statement from all source |
874 | +# files in the program, then also delete it here. |
875 | +"""IPC implementation for windows.""" |
876 | + |
877 | +from ubuntu_sso.main.windows import get_sso_pb_port |
878 | + |
879 | +SD_SSO_PORT_OFFSET = 1 |
880 | + |
881 | + |
882 | +def get_sd_pb_port(): |
883 | + """Returns the host and port for this user.""" |
884 | + return get_sso_pb_port() + SD_SSO_PORT_OFFSET |
885 | + |
886 | + |
887 | +class DescriptionFactory(object): |
888 | + """Factory that provides the server and client descriptions.""" |
889 | + |
890 | + client_description_pattern = 'tcp:host=127.0.0.1:port=%s' |
891 | + server_description_pattern = 'tcp:%s:interface=127.0.0.1' |
892 | + |
893 | + def __init__(self): |
894 | + """Create a new instance.""" |
895 | + self.port = get_sd_pb_port() |
896 | + self.server = self.server_description_pattern % self.port |
897 | + self.client = self.client_description_pattern % self.port |
898 | |
899 | === modified file 'ubuntuone/platform/tools/windows.py' |
900 | --- ubuntuone/platform/tools/windows.py 2012-04-30 14:24:55 +0000 |
901 | +++ ubuntuone/platform/tools/windows.py 2012-05-22 16:21:33 +0000 |
902 | @@ -36,7 +36,7 @@ |
903 | from twisted.internet import defer |
904 | from _winreg import OpenKey, HKEY_LOCAL_MACHINE, QueryValueEx |
905 | |
906 | -from ubuntuone.platform.ipc.windows import is_already_running |
907 | +from ubuntuone.platform.ipc.perspective_broker import is_already_running |
908 | from ubuntuone.platform.ipc.ipc_client import UbuntuOneClient |
909 | |
910 | |
911 | |
912 | === modified file 'ubuntuone/syncdaemon/interaction_interfaces.py' |
913 | --- ubuntuone/syncdaemon/interaction_interfaces.py 2012-04-09 20:07:05 +0000 |
914 | +++ ubuntuone/syncdaemon/interaction_interfaces.py 2012-05-22 16:21:33 +0000 |
915 | @@ -1213,6 +1213,11 @@ |
916 | self.sync = self # for API compatibility |
917 | |
918 | @log_call(logger.info) |
919 | + def start(self): |
920 | + """Start listening for ipc messages.""" |
921 | + return self.interface.start() |
922 | + |
923 | + @log_call(logger.info) |
924 | def shutdown(self, with_restart=False): |
925 | """Shutdown the interface and unsubscribe from the event queue.""" |
926 | self.main.event_q.unsubscribe(self.event_listener) |
927 | |
928 | === modified file 'ubuntuone/syncdaemon/main.py' |
929 | --- ubuntuone/syncdaemon/main.py 2012-04-09 20:08:42 +0000 |
930 | +++ ubuntuone/syncdaemon/main.py 2012-05-22 16:21:33 +0000 |
931 | @@ -216,6 +216,7 @@ |
932 | """Setup the daemon to be ready to run.""" |
933 | # hook the event queue to the root dir |
934 | self.event_q.push('SYS_INIT_DONE') |
935 | + return self.external.start() |
936 | |
937 | @defer.inlineCallbacks |
938 | def shutdown(self, with_restart=False): |
diff line 224: s/facotry/factory/
Also the DescriptionFactory does not really look like a factory to me, but perhaps I am missing some of the magic parts.