Merge lp:~mandel/ubuntuone-client/windows_sdtool into lp:ubuntuone-client
- windows_sdtool
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Natalia Bidart |
Approved revision: | 1061 |
Merged at revision: | 1019 |
Proposed branch: | lp:~mandel/ubuntuone-client/windows_sdtool |
Merge into: | lp:ubuntuone-client |
Diff against target: |
1771 lines (+1721/-3) 4 files modified
tests/platform/windows/test_ipc.py (+1/-1) tests/platform/windows/test_tools.py (+1043/-0) ubuntuone/platform/windows/ipc_client.py (+107/-2) ubuntuone/platform/windows/tools.py (+570/-0) |
To merge this branch: | bzr merge lp:~mandel/ubuntuone-client/windows_sdtool |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Natalia Bidart (community) | Approve | ||
Alejandro J. Cura (community) | Approve | ||
Review via email: mp+65493@code.launchpad.net |
Commit message
Provides an SDTool implementation that works on windows.
Description of the change
Provides an SDTool implementation that works on windows. In order to run the tests please do:
python C:\Python27\
- 1056. By Manuel de la Peña
-
Added the tests to ensure that the sdtool works as expected.
- 1057. By Manuel de la Peña
-
Merged with previous changes made on linux.
- 1058. By Manuel de la Peña
-
Fixed a number of lint issues
- 1059. By Manuel de la Peña
-
Use inlineCallbacks in the connect method.
- 1060. By Manuel de la Peña
-
Added forgotten test file.
- 1061. By Manuel de la Peña
-
Fixed lint issues and comments from reviews.
Natalia Bidart (nataliabidart) : | # |
Alejandro J. Cura (alecu) wrote : | # |
As we discussed on IRC, it would make sense to have the functions that create and return a deferred use inlineCallbacks instead. Please fix this and remove the self.bus that's not defined anywhere.
Good branch otherwise, thanks!
Natalia Bidart (nataliabidart) wrote : | # |
Marking as Needs Fixing to track what Alejandro asked.
Alejandro J. Cura (alecu) wrote : | # |
I'm changing the review to approve, pending the fixes that nessita will check.
Natalia Bidart (nataliabidart) wrote : | # |
Filed bug #801685 so Manuel can make the improvements later, without blocking this branch.
Preview Diff
1 | === modified file 'tests/platform/windows/test_ipc.py' | |||
2 | --- tests/platform/windows/test_ipc.py 2011-06-22 14:30:55 +0000 | |||
3 | +++ tests/platform/windows/test_ipc.py 2011-06-23 16:46:29 +0000 | |||
4 | @@ -2131,6 +2131,7 @@ | |||
5 | 2131 | return d | 2131 | return d |
6 | 2132 | 2132 | ||
7 | 2133 | def test_enable_bandwidth_throttling(self): | 2133 | def test_enable_bandwidth_throttling(self): |
8 | 2134 | """Enable bandwidth throttling.""" | ||
9 | 2134 | reply_handler = lambda: None | 2135 | reply_handler = lambda: None |
10 | 2135 | error_handler = lambda: None | 2136 | error_handler = lambda: None |
11 | 2136 | 2137 | ||
12 | @@ -2148,7 +2149,6 @@ | |||
13 | 2148 | d.addCallback(test_execution) | 2149 | d.addCallback(test_execution) |
14 | 2149 | # pylint: enable=E1101 | 2150 | # pylint: enable=E1101 |
15 | 2150 | return d | 2151 | return d |
16 | 2151 | """Enable bandwidth throttling.""" | ||
17 | 2152 | 2152 | ||
18 | 2153 | def test_disable_bandwidth_throttling(self): | 2153 | def test_disable_bandwidth_throttling(self): |
19 | 2154 | """Disable bandwidth throttling.""" | 2154 | """Disable bandwidth throttling.""" |
20 | 2155 | 2155 | ||
21 | === added file 'tests/platform/windows/test_tools.py' | |||
22 | --- tests/platform/windows/test_tools.py 1970-01-01 00:00:00 +0000 | |||
23 | +++ tests/platform/windows/test_tools.py 2011-06-23 16:46:29 +0000 | |||
24 | @@ -0,0 +1,1043 @@ | |||
25 | 1 | # tests.platform.windows.test_tools - test tools for SyncDaemon | ||
26 | 2 | # | ||
27 | 3 | # Author: Manuel de la Pena <manuel@canonical.com> | ||
28 | 4 | # | ||
29 | 5 | # Copyright 2011 Canonical Ltd. | ||
30 | 6 | # | ||
31 | 7 | # This program is free software: you can redistribute it and/or modify it | ||
32 | 8 | # under the terms of the GNU General Public License version 3, as published | ||
33 | 9 | # by the Free Software Foundation. | ||
34 | 10 | # | ||
35 | 11 | # This program is distributed in the hope that it will be useful, but | ||
36 | 12 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
37 | 13 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
38 | 14 | # PURPOSE. See the GNU General Public License for more details. | ||
39 | 15 | # | ||
40 | 16 | # You should have received a copy of the GNU General Public License along | ||
41 | 17 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
42 | 18 | |||
43 | 19 | from mocker import Mocker, ANY | ||
44 | 20 | |||
45 | 21 | from twisted.trial.unittest import TestCase | ||
46 | 22 | from twisted.internet import defer, reactor | ||
47 | 23 | from twisted.spread.pb import ( | ||
48 | 24 | PBServerFactory, | ||
49 | 25 | Root) | ||
50 | 26 | |||
51 | 27 | from ubuntuone.platform.windows.tools import SyncDaemonTool | ||
52 | 28 | from ubuntuone.platform.windows.ipc import ( | ||
53 | 29 | Config, | ||
54 | 30 | Events, | ||
55 | 31 | Folders, | ||
56 | 32 | FileSystem, | ||
57 | 33 | PublicFiles, | ||
58 | 34 | Shares, | ||
59 | 35 | Status, | ||
60 | 36 | SyncDaemon, | ||
61 | 37 | NAMED_PIPE_URL) | ||
62 | 38 | |||
63 | 39 | |||
64 | 40 | class SaveProtocolServerFactory(PBServerFactory): | ||
65 | 41 | """A PBServerFactory that saves the latest connected client.""" | ||
66 | 42 | |||
67 | 43 | protocolInstance = None | ||
68 | 44 | |||
69 | 45 | def clientConnectionMade(self, protocol): | ||
70 | 46 | """Keep track of the given protocol.""" | ||
71 | 47 | self.protocolInstance = protocol | ||
72 | 48 | |||
73 | 49 | |||
74 | 50 | class FakeRoot(Root): | ||
75 | 51 | """Root object that exposes the diff referenceable objects.""" | ||
76 | 52 | |||
77 | 53 | def __init__(self, status, events, sync_daemon, file_system, shares, | ||
78 | 54 | config, folders, public_files): | ||
79 | 55 | """Create a new instance that will expose the objects.""" | ||
80 | 56 | self._status = status | ||
81 | 57 | self._events = events | ||
82 | 58 | self._sync_daemon = sync_daemon | ||
83 | 59 | self._file_system = file_system | ||
84 | 60 | self._shares = shares | ||
85 | 61 | self._config = config | ||
86 | 62 | self._folders = folders | ||
87 | 63 | self._public_files = public_files | ||
88 | 64 | |||
89 | 65 | def remote_get_status(self): | ||
90 | 66 | """Return the status remote object.""" | ||
91 | 67 | return self._status | ||
92 | 68 | |||
93 | 69 | def remote_get_events(self): | ||
94 | 70 | """Return the events remote object.""" | ||
95 | 71 | return self._events | ||
96 | 72 | |||
97 | 73 | def remote_get_sync_daemon(self): | ||
98 | 74 | """Return the sync daemon remote object.""" | ||
99 | 75 | return self._sync_daemon | ||
100 | 76 | |||
101 | 77 | def remote_get_file_system(self): | ||
102 | 78 | """Return the file system remote object.""" | ||
103 | 79 | return self._file_system | ||
104 | 80 | |||
105 | 81 | def remote_get_shares(self): | ||
106 | 82 | """Return the shares remote object.""" | ||
107 | 83 | return self._shares | ||
108 | 84 | |||
109 | 85 | def remote_get_config(self): | ||
110 | 86 | """Return the config remote object.""" | ||
111 | 87 | return self._config | ||
112 | 88 | |||
113 | 89 | def remote_get_folders(self): | ||
114 | 90 | """Return the folders remote object.""" | ||
115 | 91 | return self._folders | ||
116 | 92 | |||
117 | 93 | def remote_get_public_files(self): | ||
118 | 94 | """Return the public files remote object.""" | ||
119 | 95 | return self._public_files | ||
120 | 96 | |||
121 | 97 | |||
122 | 98 | class TestSyncDaemonTool(TestCase): | ||
123 | 99 | """Various utility methods to test/play with the SyncDaemon.""" | ||
124 | 100 | |||
125 | 101 | def setUp(self): | ||
126 | 102 | """Set up the different tests.""" | ||
127 | 103 | super(TestSyncDaemonTool, self).setUp() | ||
128 | 104 | self.pipe = NAMED_PIPE_URL % 'test_stdtool' | ||
129 | 105 | self.mocker = Mocker() | ||
130 | 106 | self.root = self.mocker.mock() | ||
131 | 107 | self.status = Status(None, None, None) | ||
132 | 108 | self.status.syncdaemon_status = self.root | ||
133 | 109 | self.events = Events(None) | ||
134 | 110 | self.events.events = self.root | ||
135 | 111 | self.daemon = SyncDaemon(None, None, None, None) | ||
136 | 112 | self.daemon.service = self.root | ||
137 | 113 | self.fs = FileSystem(None, None) | ||
138 | 114 | self.fs.syncdaemon_filesystem = self.root | ||
139 | 115 | self.shares = Shares(None, None) | ||
140 | 116 | self.shares.syncdaemon_shares = self.root | ||
141 | 117 | self.config = Config(None, None) | ||
142 | 118 | self.config.syncdaemon_config = self.root | ||
143 | 119 | self.folders = Folders(None, None) | ||
144 | 120 | self.folders.syncdaemon_folders = self.root | ||
145 | 121 | self.files = PublicFiles(None, None) | ||
146 | 122 | self.files.syncdaemon_public_files = self.root | ||
147 | 123 | self.is_running = self.mocker.replace( | ||
148 | 124 | 'ubuntuone.platform.windows.tools.is_running') | ||
149 | 125 | # start pb | ||
150 | 126 | self.syncdaemon_root = FakeRoot(self.status, self.events, self.daemon, | ||
151 | 127 | self.fs, self.shares, self.config, | ||
152 | 128 | self.folders, self.files) | ||
153 | 129 | self.server_factory = SaveProtocolServerFactory(self.syncdaemon_root) | ||
154 | 130 | # pylint: disable=E1101 | ||
155 | 131 | self.listener = reactor.listenPipe(self.pipe, self.server_factory) | ||
156 | 132 | self.sdtool = SyncDaemonTool(named_pipe=self.pipe) | ||
157 | 133 | |||
158 | 134 | def tearDown(self): | ||
159 | 135 | """Clean reactor.""" | ||
160 | 136 | if self.server_factory.protocolInstance is not None: | ||
161 | 137 | self.server_factory.protocolInstance.transport.loseConnection() | ||
162 | 138 | return defer.gatherResults([self._tearDownServer(), | ||
163 | 139 | self._tearDownClient()]) | ||
164 | 140 | |||
165 | 141 | def _tearDownServer(self): | ||
166 | 142 | """Teardown the server.""" | ||
167 | 143 | return defer.maybeDeferred(self.listener.stopListening) | ||
168 | 144 | |||
169 | 145 | def _tearDownClient(self): | ||
170 | 146 | """Tear down the client.""" | ||
171 | 147 | self.sdtool.client.disconnect() | ||
172 | 148 | return defer.succeed(None) | ||
173 | 149 | |||
174 | 150 | @defer.inlineCallbacks | ||
175 | 151 | def _connect(self): | ||
176 | 152 | """Connect to the running service.""" | ||
177 | 153 | yield self.sdtool.client.connect(self.pipe) | ||
178 | 154 | defer.returnValue(self.sdtool) | ||
179 | 155 | |||
180 | 156 | def test_wait_connected(self): | ||
181 | 157 | """Test that we wait until we connect to the server.""" | ||
182 | 158 | |||
183 | 159 | def test_get_current_downloads(self): | ||
184 | 160 | """Test gettting the current downloads.""" | ||
185 | 161 | downloads = [dict(name='name', id='id'), | ||
186 | 162 | dict(name='name', id='id')] | ||
187 | 163 | |||
188 | 164 | @defer.inlineCallbacks | ||
189 | 165 | def test_execution(sdtool): | ||
190 | 166 | """Actual test.""" | ||
191 | 167 | self.root.current_downloads() | ||
192 | 168 | self.mocker.result(downloads) | ||
193 | 169 | self.mocker.replay() | ||
194 | 170 | result = yield sdtool.get_current_downloads() | ||
195 | 171 | self.mocker.verify() | ||
196 | 172 | self.assertEqual(downloads, result) | ||
197 | 173 | |||
198 | 174 | d = self._connect() | ||
199 | 175 | # pylint: disable=E1101 | ||
200 | 176 | d.addCallback(test_execution) | ||
201 | 177 | # pylint: enable=E1101 | ||
202 | 178 | return d | ||
203 | 179 | |||
204 | 180 | def test_get_current_uploads(self): | ||
205 | 181 | """Test that we get all the current uploads.""" | ||
206 | 182 | uploads = [dict(name='name', id='id'), | ||
207 | 183 | dict(name='name', id='id')] | ||
208 | 184 | |||
209 | 185 | @defer.inlineCallbacks | ||
210 | 186 | def test_execution(sdtool): | ||
211 | 187 | """Actual test.""" | ||
212 | 188 | self.root.current_uploads() | ||
213 | 189 | self.mocker.replay() | ||
214 | 190 | self.mocker.result(uploads) | ||
215 | 191 | result = yield sdtool.get_current_uploads() | ||
216 | 192 | self.mocker.verify() | ||
217 | 193 | self.assertEqual(uploads, result) | ||
218 | 194 | |||
219 | 195 | d = self._connect() | ||
220 | 196 | # pylint: disable=E1101 | ||
221 | 197 | d.addCallback(test_execution) | ||
222 | 198 | # pylint: enable=E1101 | ||
223 | 199 | return d | ||
224 | 200 | |||
225 | 201 | def test_wait_for_nirvana(self, last_event_interval=5, verbose=False): | ||
226 | 202 | """Test that we can reach nirvana.""" | ||
227 | 203 | last_event_interval = 5 | ||
228 | 204 | |||
229 | 205 | @defer.inlineCallbacks | ||
230 | 206 | def test_execution(sdtool): | ||
231 | 207 | """Actual test.""" | ||
232 | 208 | self.root.wait_for_nirvana(last_event_interval, ANY, ANY) | ||
233 | 209 | self.mocker.replay() | ||
234 | 210 | yield sdtool.wait_for_nirvana() | ||
235 | 211 | self.mocker.verify() | ||
236 | 212 | |||
237 | 213 | d = self._connect() | ||
238 | 214 | # pylint: disable=E1101 | ||
239 | 215 | d.addCallback(test_execution) | ||
240 | 216 | # pylint: enable=E1101 | ||
241 | 217 | return d | ||
242 | 218 | |||
243 | 219 | def test_accept_share(self): | ||
244 | 220 | """Test that we do accept the share.""" | ||
245 | 221 | share_id = 'share_id' | ||
246 | 222 | |||
247 | 223 | @defer.inlineCallbacks | ||
248 | 224 | def test_execution(sdtool): | ||
249 | 225 | """Actual test.""" | ||
250 | 226 | self.root.accept_share(share_id, ANY, ANY) | ||
251 | 227 | self.mocker.replay() | ||
252 | 228 | yield sdtool.accept_share(share_id) | ||
253 | 229 | self.mocker.verify() | ||
254 | 230 | |||
255 | 231 | d = self._connect() | ||
256 | 232 | # pylint: disable=E1101 | ||
257 | 233 | d.addCallback(test_execution) | ||
258 | 234 | # pylint: enable=E1101 | ||
259 | 235 | return d | ||
260 | 236 | |||
261 | 237 | def test_reject_share(self): | ||
262 | 238 | """Test that we do reject the share.""" | ||
263 | 239 | share_id = 'share_id' | ||
264 | 240 | |||
265 | 241 | @defer.inlineCallbacks | ||
266 | 242 | def test_execution(sdtool): | ||
267 | 243 | """Actual test.""" | ||
268 | 244 | self.root.reject_share(share_id, ANY, ANY) | ||
269 | 245 | self.mocker.replay() | ||
270 | 246 | yield sdtool.reject_share(share_id) | ||
271 | 247 | self.mocker.verify() | ||
272 | 248 | |||
273 | 249 | d = self._connect() | ||
274 | 250 | # pylint: disable=E1101 | ||
275 | 251 | d.addCallback(test_execution) | ||
276 | 252 | # pylint: enable=E1101 | ||
277 | 253 | return d | ||
278 | 254 | |||
279 | 255 | def test_subscribe_share(self): | ||
280 | 256 | """Test that we subscribe to the share.""" | ||
281 | 257 | share_id = 'share_id' | ||
282 | 258 | |||
283 | 259 | @defer.inlineCallbacks | ||
284 | 260 | def test_execution(sdtool): | ||
285 | 261 | """Actual test.""" | ||
286 | 262 | self.root.subscribe(share_id) | ||
287 | 263 | self.mocker.replay() | ||
288 | 264 | yield sdtool.subscribe_share(share_id) | ||
289 | 265 | self.mocker.verify() | ||
290 | 266 | |||
291 | 267 | d = self._connect() | ||
292 | 268 | # pylint: disable=E1101 | ||
293 | 269 | d.addCallback(test_execution) | ||
294 | 270 | # pylint: enable=E1101 | ||
295 | 271 | return d | ||
296 | 272 | |||
297 | 273 | def test_unsubscribe_share(self): | ||
298 | 274 | """Unsubscribe from a share given its id.""" | ||
299 | 275 | share_id = 'share_id' | ||
300 | 276 | |||
301 | 277 | @defer.inlineCallbacks | ||
302 | 278 | def test_execution(sdtool): | ||
303 | 279 | """Actual test.""" | ||
304 | 280 | self.root.unsubscribe(share_id) | ||
305 | 281 | self.mocker.replay() | ||
306 | 282 | yield sdtool.unsubscribe_share(share_id) | ||
307 | 283 | self.mocker.verify() | ||
308 | 284 | |||
309 | 285 | d = self._connect() | ||
310 | 286 | # pylint: disable=E1101 | ||
311 | 287 | d.addCallback(test_execution) | ||
312 | 288 | # pylint: enable=E1101 | ||
313 | 289 | return d | ||
314 | 290 | |||
315 | 291 | def test_get_shares(self): | ||
316 | 292 | """Test that we get the list of shares.""" | ||
317 | 293 | shares = [dict(name='name', id='id'), | ||
318 | 294 | dict(name='name', id='id')] | ||
319 | 295 | |||
320 | 296 | @defer.inlineCallbacks | ||
321 | 297 | def test_execution(sdtool): | ||
322 | 298 | """Actual test.""" | ||
323 | 299 | self.root.get_shares() | ||
324 | 300 | self.mocker.result(shares) | ||
325 | 301 | self.mocker.replay() | ||
326 | 302 | yield sdtool.get_shares() | ||
327 | 303 | self.mocker.verify() | ||
328 | 304 | |||
329 | 305 | d = self._connect() | ||
330 | 306 | # pylint: disable=E1101 | ||
331 | 307 | d.addCallback(test_execution) | ||
332 | 308 | # pylint: enable=E1101 | ||
333 | 309 | return d | ||
334 | 310 | |||
335 | 311 | def test_refresh_shares(self): | ||
336 | 312 | """Test that we can refresh the shares.""" | ||
337 | 313 | |||
338 | 314 | @defer.inlineCallbacks | ||
339 | 315 | def test_execution(sdtool): | ||
340 | 316 | """Actual test.""" | ||
341 | 317 | self.root.refresh_shares() | ||
342 | 318 | self.mocker.replay() | ||
343 | 319 | yield sdtool.refresh_shares() | ||
344 | 320 | self.mocker.verify() | ||
345 | 321 | |||
346 | 322 | d = self._connect() | ||
347 | 323 | # pylint: disable=E1101 | ||
348 | 324 | d.addCallback(test_execution) | ||
349 | 325 | # pylint: enable=E1101 | ||
350 | 326 | return d | ||
351 | 327 | |||
352 | 328 | def test_offer_share(self): | ||
353 | 329 | """Test that we can indeed offer a share.""" | ||
354 | 330 | path = 'path' | ||
355 | 331 | username = 'username' | ||
356 | 332 | name = 'name' | ||
357 | 333 | access_level = 'level' | ||
358 | 334 | |||
359 | 335 | @defer.inlineCallbacks | ||
360 | 336 | def test_execution(sdtool): | ||
361 | 337 | """Actual test.""" | ||
362 | 338 | self.root.create_share(path, username, name, access_level) | ||
363 | 339 | self.mocker.replay() | ||
364 | 340 | yield sdtool.offer_share(path, username, name, access_level) | ||
365 | 341 | self.mocker.verify() | ||
366 | 342 | |||
367 | 343 | d = self._connect() | ||
368 | 344 | # pylint: disable=E1101 | ||
369 | 345 | d.addCallback(test_execution) | ||
370 | 346 | # pylint: enable=E1101 | ||
371 | 347 | return d | ||
372 | 348 | |||
373 | 349 | def test_list_shared(self): | ||
374 | 350 | """Test that we can list the shared.""" | ||
375 | 351 | shares = [dict(name='name', id='id'), | ||
376 | 352 | dict(name='name', id='id')] | ||
377 | 353 | |||
378 | 354 | @defer.inlineCallbacks | ||
379 | 355 | def test_execution(sdtool): | ||
380 | 356 | """Actual test.""" | ||
381 | 357 | self.root.get_shared() | ||
382 | 358 | self.mocker.result(shares) | ||
383 | 359 | self.mocker.replay() | ||
384 | 360 | yield sdtool.list_shared() | ||
385 | 361 | self.mocker.verify() | ||
386 | 362 | |||
387 | 363 | d = self._connect() | ||
388 | 364 | # pylint: disable=E1101 | ||
389 | 365 | d.addCallback(test_execution) | ||
390 | 366 | # pylint: enable=E1101 | ||
391 | 367 | return d | ||
392 | 368 | |||
393 | 369 | def test_create_folder(self): | ||
394 | 370 | """Test that we can create a folder.""" | ||
395 | 371 | path = 'path' | ||
396 | 372 | |||
397 | 373 | @defer.inlineCallbacks | ||
398 | 374 | def test_execution(sdtool): | ||
399 | 375 | """Actual test.""" | ||
400 | 376 | self.root.create(path) | ||
401 | 377 | self.mocker.replay() | ||
402 | 378 | yield sdtool.create_folder(path) | ||
403 | 379 | self.mocker.verify() | ||
404 | 380 | |||
405 | 381 | d = self._connect() | ||
406 | 382 | # pylint: disable=E1101 | ||
407 | 383 | d.addCallback(test_execution) | ||
408 | 384 | # pylint: enable=E1101 | ||
409 | 385 | return d | ||
410 | 386 | |||
411 | 387 | def test_delete_folder(self): | ||
412 | 388 | """Test that we can delete a folder.""" | ||
413 | 389 | folder_id = 'folder_id' | ||
414 | 390 | |||
415 | 391 | @defer.inlineCallbacks | ||
416 | 392 | def test_execution(sdtool): | ||
417 | 393 | """Actual test.""" | ||
418 | 394 | self.root.delete(folder_id) | ||
419 | 395 | self.mocker.replay() | ||
420 | 396 | yield sdtool.delete_folder(folder_id) | ||
421 | 397 | self.mocker.verify() | ||
422 | 398 | |||
423 | 399 | d = self._connect() | ||
424 | 400 | # pylint: disable=E1101 | ||
425 | 401 | d.addCallback(test_execution) | ||
426 | 402 | # pylint: enable=E1101 | ||
427 | 403 | return d | ||
428 | 404 | |||
429 | 405 | def test_subscribe_folder(self): | ||
430 | 406 | """Test that we can subscribe to a folder.""" | ||
431 | 407 | folder_id = 'folder_id' | ||
432 | 408 | |||
433 | 409 | @defer.inlineCallbacks | ||
434 | 410 | def test_execution(sdtool): | ||
435 | 411 | """Actual test.""" | ||
436 | 412 | self.root.subscribe(folder_id ) | ||
437 | 413 | self.mocker.replay() | ||
438 | 414 | yield sdtool.subscribe_folder(folder_id ) | ||
439 | 415 | self.mocker.verify() | ||
440 | 416 | |||
441 | 417 | d = self._connect() | ||
442 | 418 | # pylint: disable=E1101 | ||
443 | 419 | d.addCallback(test_execution) | ||
444 | 420 | # pylint: enable=E1101 | ||
445 | 421 | return d | ||
446 | 422 | |||
447 | 423 | def test_unsubscribe_folder(self): | ||
448 | 424 | """Test that we can unsubscribe to a folder.""" | ||
449 | 425 | folder_id = 'folder_id' | ||
450 | 426 | |||
451 | 427 | @defer.inlineCallbacks | ||
452 | 428 | def test_execution(sdtool): | ||
453 | 429 | """Actual test.""" | ||
454 | 430 | self.root.unsubscribe(folder_id) | ||
455 | 431 | self.mocker.replay() | ||
456 | 432 | yield sdtool.unsubscribe_folder(folder_id) | ||
457 | 433 | self.mocker.verify() | ||
458 | 434 | |||
459 | 435 | d = self._connect() | ||
460 | 436 | # pylint: disable=E1101 | ||
461 | 437 | d.addCallback(test_execution) | ||
462 | 438 | # pylint: enable=E1101 | ||
463 | 439 | return d | ||
464 | 440 | |||
465 | 441 | def test_get_folders(self): | ||
466 | 442 | """Test that we can get the folders.""" | ||
467 | 443 | folders = [dict(name='name', id='id'), | ||
468 | 444 | dict(name='name', id='id')] | ||
469 | 445 | |||
470 | 446 | @defer.inlineCallbacks | ||
471 | 447 | def test_execution(sdtool): | ||
472 | 448 | """Actual test.""" | ||
473 | 449 | self.root.get_folders() | ||
474 | 450 | self.mocker.result(folders) | ||
475 | 451 | self.mocker.replay() | ||
476 | 452 | yield sdtool.get_folders() | ||
477 | 453 | self.mocker.verify() | ||
478 | 454 | |||
479 | 455 | d = self._connect() | ||
480 | 456 | # pylint: disable=E1101 | ||
481 | 457 | d.addCallback(test_execution) | ||
482 | 458 | # pylint: enable=E1101 | ||
483 | 459 | return d | ||
484 | 460 | |||
485 | 461 | def test_get_folder_info(self): | ||
486 | 462 | """Test that we can get the info of a folder.""" | ||
487 | 463 | path = 'path' | ||
488 | 464 | |||
489 | 465 | @defer.inlineCallbacks | ||
490 | 466 | def test_execution(client): | ||
491 | 467 | """Actual test.""" | ||
492 | 468 | self.root.get_info(path) | ||
493 | 469 | self.mocker.replay() | ||
494 | 470 | yield client.get_folder_info(path) | ||
495 | 471 | self.mocker.verify() | ||
496 | 472 | |||
497 | 473 | d = self._connect() | ||
498 | 474 | # pylint: disable=E1101 | ||
499 | 475 | d.addCallback(test_execution) | ||
500 | 476 | # pylint: enable=E1101 | ||
501 | 477 | return d | ||
502 | 478 | |||
503 | 479 | def test_get_metadata(self): | ||
504 | 480 | """Test that we can get the metadata.""" | ||
505 | 481 | path = 'path' | ||
506 | 482 | |||
507 | 483 | @defer.inlineCallbacks | ||
508 | 484 | def test_execution(sdtool): | ||
509 | 485 | """Actual test.""" | ||
510 | 486 | self.root.get_metadata(path) | ||
511 | 487 | self.mocker.replay() | ||
512 | 488 | yield sdtool.get_metadata(path) | ||
513 | 489 | self.mocker.verify() | ||
514 | 490 | |||
515 | 491 | d = self._connect() | ||
516 | 492 | # pylint: disable=E1101 | ||
517 | 493 | d.addCallback(test_execution) | ||
518 | 494 | # pylint: enable=E1101 | ||
519 | 495 | return d | ||
520 | 496 | |||
521 | 497 | def test_change_public_access(self): | ||
522 | 498 | """Test that we can change the public access.""" | ||
523 | 499 | path = 'path' | ||
524 | 500 | share_id = 'share_id' | ||
525 | 501 | node_id = 'node_id' | ||
526 | 502 | is_public = False | ||
527 | 503 | metadata = dict(share_id=share_id, node_id=node_id) | ||
528 | 504 | |||
529 | 505 | @defer.inlineCallbacks | ||
530 | 506 | def test_execution(sdtool): | ||
531 | 507 | """Actual test.""" | ||
532 | 508 | self.root.get_metadata(path) | ||
533 | 509 | self.mocker.result(metadata) | ||
534 | 510 | self.root.change_public_access(share_id, node_id, is_public) | ||
535 | 511 | self.mocker.replay() | ||
536 | 512 | yield sdtool.change_public_access(path, is_public) | ||
537 | 513 | self.mocker.verify() | ||
538 | 514 | |||
539 | 515 | d = self._connect() | ||
540 | 516 | # pylint: disable=E1101 | ||
541 | 517 | d.addCallback(test_execution) | ||
542 | 518 | # pylint: enable=E1101 | ||
543 | 519 | return d | ||
544 | 520 | |||
545 | 521 | def test_quit(self): | ||
546 | 522 | """Test that we can quit.""" | ||
547 | 523 | |||
548 | 524 | @defer.inlineCallbacks | ||
549 | 525 | def test_execution(sdtool): | ||
550 | 526 | """Actual test.""" | ||
551 | 527 | self.is_running() | ||
552 | 528 | self.mocker.result(True) | ||
553 | 529 | self.root.quit(None, None) | ||
554 | 530 | self.mocker.replay() | ||
555 | 531 | yield sdtool.quit() | ||
556 | 532 | self.mocker.verify() | ||
557 | 533 | |||
558 | 534 | d = self._connect() | ||
559 | 535 | # pylint: disable=E1101 | ||
560 | 536 | d.addCallback(test_execution) | ||
561 | 537 | # pylint: enable=E1101 | ||
562 | 538 | return d | ||
563 | 539 | |||
564 | 540 | def test_connect(self): | ||
565 | 541 | """Test we can connect.""" | ||
566 | 542 | |||
567 | 543 | @defer.inlineCallbacks | ||
568 | 544 | def test_execution(sdtool): | ||
569 | 545 | """Actual test.""" | ||
570 | 546 | self.root.connect() | ||
571 | 547 | self.mocker.replay() | ||
572 | 548 | yield sdtool.connect() | ||
573 | 549 | self.mocker.verify() | ||
574 | 550 | |||
575 | 551 | d = self._connect() | ||
576 | 552 | # pylint: disable=E1101 | ||
577 | 553 | d.addCallback(test_execution) | ||
578 | 554 | # pylint: enable=E1101 | ||
579 | 555 | return d | ||
580 | 556 | |||
581 | 557 | def test_disconnect(self): | ||
582 | 558 | """Test we can disconnect.""" | ||
583 | 559 | |||
584 | 560 | @defer.inlineCallbacks | ||
585 | 561 | def test_execution(sdtool): | ||
586 | 562 | """Actual test.""" | ||
587 | 563 | self.root.disconnect() | ||
588 | 564 | self.mocker.replay() | ||
589 | 565 | yield sdtool.disconnect() | ||
590 | 566 | self.mocker.verify() | ||
591 | 567 | |||
592 | 568 | d = self._connect() | ||
593 | 569 | # pylint: disable=E1101 | ||
594 | 570 | d.addCallback(test_execution) | ||
595 | 571 | # pylint: enable=E1101 | ||
596 | 572 | return d | ||
597 | 573 | |||
598 | 574 | def test_get_status(self): | ||
599 | 575 | """Test we can get the status.""" | ||
600 | 576 | status = dict(is_error=False, is_online=True, is_connected=True) | ||
601 | 577 | |||
602 | 578 | @defer.inlineCallbacks | ||
603 | 579 | def test_execution(sdtool): | ||
604 | 580 | """Actual test.""" | ||
605 | 581 | self.root.current_status() | ||
606 | 582 | self.mocker.result(status) | ||
607 | 583 | self.mocker.replay() | ||
608 | 584 | yield sdtool.get_status() | ||
609 | 585 | self.mocker.verify() | ||
610 | 586 | |||
611 | 587 | d = self._connect() | ||
612 | 588 | # pylint: disable=E1101 | ||
613 | 589 | d.addCallback(test_execution) | ||
614 | 590 | # pylint: enable=E1101 | ||
615 | 591 | return d | ||
616 | 592 | |||
617 | 593 | def test_waiting(self): | ||
618 | 594 | """Test that we get the info of what is waitig.""" | ||
619 | 595 | |||
620 | 596 | @defer.inlineCallbacks | ||
621 | 597 | def test_execution(sdtool): | ||
622 | 598 | """Actual test.""" | ||
623 | 599 | self.root.waiting() | ||
624 | 600 | self.mocker.result({}) | ||
625 | 601 | self.mocker.replay() | ||
626 | 602 | yield sdtool.waiting() | ||
627 | 603 | self.mocker.verify() | ||
628 | 604 | |||
629 | 605 | d = self._connect() | ||
630 | 606 | # pylint: disable=E1101 | ||
631 | 607 | d.addCallback(test_execution) | ||
632 | 608 | # pylint: enable=E1101 | ||
633 | 609 | return d | ||
634 | 610 | |||
635 | 611 | def test_waiting_metadata(self): | ||
636 | 612 | """Test that we can get the waiting metadata.""" | ||
637 | 613 | |||
638 | 614 | @defer.inlineCallbacks | ||
639 | 615 | def test_execution(sdtool): | ||
640 | 616 | """Actual test.""" | ||
641 | 617 | self.root.waiting_metadata() | ||
642 | 618 | self.mocker.replay() | ||
643 | 619 | yield sdtool.waiting_metadata() | ||
644 | 620 | self.mocker.verify() | ||
645 | 621 | |||
646 | 622 | d = self._connect() | ||
647 | 623 | # pylint: disable=E1101 | ||
648 | 624 | d.addCallback(test_execution) | ||
649 | 625 | # pylint: enable=E1101 | ||
650 | 626 | return d | ||
651 | 627 | |||
652 | 628 | def test_waiting_content(self): | ||
653 | 629 | """Test that we get the waiting content.""" | ||
654 | 630 | |||
655 | 631 | @defer.inlineCallbacks | ||
656 | 632 | def test_execution(sdtool): | ||
657 | 633 | """Actual test.""" | ||
658 | 634 | self.root.waiting_content() | ||
659 | 635 | self.mocker.replay() | ||
660 | 636 | yield sdtool.waiting_content() | ||
661 | 637 | self.mocker.verify() | ||
662 | 638 | |||
663 | 639 | d = self._connect() | ||
664 | 640 | # pylint: disable=E1101 | ||
665 | 641 | d.addCallback(test_execution) | ||
666 | 642 | # pylint: enable=E1101 | ||
667 | 643 | return d | ||
668 | 644 | |||
669 | 645 | def test_get_throttling_limits(self): | ||
670 | 646 | """Test that we get the throttling limits.""" | ||
671 | 647 | |||
672 | 648 | @defer.inlineCallbacks | ||
673 | 649 | def test_execution(sdtool): | ||
674 | 650 | """Actual test.""" | ||
675 | 651 | self.root.get_throttling_limits(ANY, ANY) | ||
676 | 652 | self.mocker.replay() | ||
677 | 653 | yield sdtool.get_throttling_limits() | ||
678 | 654 | self.mocker.verify() | ||
679 | 655 | |||
680 | 656 | d = self._connect() | ||
681 | 657 | # pylint: disable=E1101 | ||
682 | 658 | d.addCallback(test_execution) | ||
683 | 659 | # pylint: enable=E1101 | ||
684 | 660 | return d | ||
685 | 661 | |||
686 | 662 | def test_set_throttling_limits(self): | ||
687 | 663 | """Test that we can set the limits.""" | ||
688 | 664 | download = 'download' | ||
689 | 665 | upload = 'upload' | ||
690 | 666 | |||
691 | 667 | @defer.inlineCallbacks | ||
692 | 668 | def test_execution(sdtool): | ||
693 | 669 | """Actual test.""" | ||
694 | 670 | self.root.set_throttling_limits(download, upload, ANY, ANY) | ||
695 | 671 | self.mocker.replay() | ||
696 | 672 | yield sdtool.set_throttling_limits(download, upload) | ||
697 | 673 | self.mocker.verify() | ||
698 | 674 | |||
699 | 675 | d = self._connect() | ||
700 | 676 | # pylint: disable=E1101 | ||
701 | 677 | d.addCallback(test_execution) | ||
702 | 678 | # pylint: enable=E1101 | ||
703 | 679 | return d | ||
704 | 680 | |||
705 | 681 | def test_is_throttling_enabled(self): | ||
706 | 682 | """Test that we get the bool stating if they are active.""" | ||
707 | 683 | |||
708 | 684 | @defer.inlineCallbacks | ||
709 | 685 | def test_execution(sdtool): | ||
710 | 686 | """Actual test.""" | ||
711 | 687 | self.root.bandwidth_throttling_enabled(ANY, ANY) | ||
712 | 688 | self.mocker.result(True) | ||
713 | 689 | self.mocker.replay() | ||
714 | 690 | result = yield sdtool.is_throttling_enabled() | ||
715 | 691 | self.mocker.verify() | ||
716 | 692 | self.assertTrue(result) | ||
717 | 693 | |||
718 | 694 | d = self._connect() | ||
719 | 695 | # pylint: disable=E1101 | ||
720 | 696 | d.addCallback(test_execution) | ||
721 | 697 | # pylint: enable=E1101 | ||
722 | 698 | return d | ||
723 | 699 | |||
724 | 700 | def test_enable_throttling_true(self): | ||
725 | 701 | """Test that we can set them.""" | ||
726 | 702 | |||
727 | 703 | @defer.inlineCallbacks | ||
728 | 704 | def test_execution(sdtool): | ||
729 | 705 | """Actual test.""" | ||
730 | 706 | self.root.enable_bandwidth_throttling(ANY, ANY) | ||
731 | 707 | self.mocker.replay() | ||
732 | 708 | yield sdtool.enable_throttling(True) | ||
733 | 709 | self.mocker.verify() | ||
734 | 710 | |||
735 | 711 | d = self._connect() | ||
736 | 712 | # pylint: disable=E1101 | ||
737 | 713 | d.addCallback(test_execution) | ||
738 | 714 | # pylint: enable=E1101 | ||
739 | 715 | return d | ||
740 | 716 | |||
741 | 717 | def test_enable_throttling_false(self): | ||
742 | 718 | """Test that we can set them.""" | ||
743 | 719 | |||
744 | 720 | @defer.inlineCallbacks | ||
745 | 721 | def test_execution(sdtool): | ||
746 | 722 | """Actual test.""" | ||
747 | 723 | self.root.disable_bandwidth_throttling(ANY, ANY) | ||
748 | 724 | self.mocker.replay() | ||
749 | 725 | yield sdtool.enable_throttling(False) | ||
750 | 726 | self.mocker.verify() | ||
751 | 727 | |||
752 | 728 | d = self._connect() | ||
753 | 729 | # pylint: disable=E1101 | ||
754 | 730 | d.addCallback(test_execution) | ||
755 | 731 | # pylint: enable=E1101 | ||
756 | 732 | return d | ||
757 | 733 | |||
758 | 734 | def test_is_autoconnect_enabled(self): | ||
759 | 735 | """Test that we can read the config.""" | ||
760 | 736 | |||
761 | 737 | @defer.inlineCallbacks | ||
762 | 738 | def test_execution(sdtool): | ||
763 | 739 | """Actual test.""" | ||
764 | 740 | self.root.autoconnect_enabled() | ||
765 | 741 | self.mocker.replay() | ||
766 | 742 | self.mocker.result(True) | ||
767 | 743 | result = yield sdtool.is_autoconnect_enabled() | ||
768 | 744 | self.mocker.verify() | ||
769 | 745 | self.assertTrue(result) | ||
770 | 746 | |||
771 | 747 | d = self._connect() | ||
772 | 748 | # pylint: disable=E1101 | ||
773 | 749 | d.addCallback(test_execution) | ||
774 | 750 | # pylint: enable=E1101 | ||
775 | 751 | return d | ||
776 | 752 | |||
777 | 753 | def test_enable_autoconnect(self): | ||
778 | 754 | """Test that we can enable the autoconnect.""" | ||
779 | 755 | enabled = False | ||
780 | 756 | |||
781 | 757 | @defer.inlineCallbacks | ||
782 | 758 | def test_execution(sdtool): | ||
783 | 759 | """Actual test.""" | ||
784 | 760 | self.root.set_autoconnect_enabled(enabled) | ||
785 | 761 | self.mocker.replay() | ||
786 | 762 | yield sdtool.enable_autoconnect(enabled) | ||
787 | 763 | self.mocker.verify() | ||
788 | 764 | |||
789 | 765 | d = self._connect() | ||
790 | 766 | # pylint: disable=E1101 | ||
791 | 767 | d.addCallback(test_execution) | ||
792 | 768 | # pylint: enable=E1101 | ||
793 | 769 | return d | ||
794 | 770 | |||
795 | 771 | def test_is_show_all_notifications_enabled(self): | ||
796 | 772 | """Test if we can read the info.""" | ||
797 | 773 | |||
798 | 774 | @defer.inlineCallbacks | ||
799 | 775 | def test_execution(sdtool): | ||
800 | 776 | """Actual test.""" | ||
801 | 777 | self.root.show_all_notifications_enabled() | ||
802 | 778 | self.mocker.result(True) | ||
803 | 779 | self.mocker.replay() | ||
804 | 780 | result = yield sdtool.is_show_all_notifications_enabled() | ||
805 | 781 | self.mocker.verify() | ||
806 | 782 | self.assertTrue(result) | ||
807 | 783 | |||
808 | 784 | d = self._connect() | ||
809 | 785 | # pylint: disable=E1101 | ||
810 | 786 | d.addCallback(test_execution) | ||
811 | 787 | # pylint: enable=E1101 | ||
812 | 788 | return d | ||
813 | 789 | |||
814 | 790 | def test_enable_show_all_notifications_true(self): | ||
815 | 791 | """Enable/disable show_all_notifications.""" | ||
816 | 792 | |||
817 | 793 | @defer.inlineCallbacks | ||
818 | 794 | def test_execution(sdtool): | ||
819 | 795 | """Actual test.""" | ||
820 | 796 | self.root.enable_show_all_notifications() | ||
821 | 797 | self.mocker.replay() | ||
822 | 798 | yield sdtool.enable_show_all_notifications(True) | ||
823 | 799 | self.mocker.verify() | ||
824 | 800 | |||
825 | 801 | d = self._connect() | ||
826 | 802 | # pylint: disable=E1101 | ||
827 | 803 | d.addCallback(test_execution) | ||
828 | 804 | # pylint: enable=E1101 | ||
829 | 805 | return d | ||
830 | 806 | |||
831 | 807 | def test_enable_show_all_notifications_false(self): | ||
832 | 808 | """Enable/disable show_all_notifications.""" | ||
833 | 809 | |||
834 | 810 | @defer.inlineCallbacks | ||
835 | 811 | def test_execution(sdtool): | ||
836 | 812 | """Actual test.""" | ||
837 | 813 | self.root.disable_show_all_notifications() | ||
838 | 814 | self.mocker.replay() | ||
839 | 815 | yield sdtool.enable_show_all_notifications(False) | ||
840 | 816 | self.mocker.verify() | ||
841 | 817 | |||
842 | 818 | d = self._connect() | ||
843 | 819 | # pylint: disable=E1101 | ||
844 | 820 | d.addCallback(test_execution) | ||
845 | 821 | # pylint: enable=E1101 | ||
846 | 822 | return d | ||
847 | 823 | |||
848 | 824 | def test_is_share_autosubscribe_enabled(self): | ||
849 | 825 | """Test that we can get the config.""" | ||
850 | 826 | |||
851 | 827 | @defer.inlineCallbacks | ||
852 | 828 | def test_execution(sdtool): | ||
853 | 829 | """Actual test.""" | ||
854 | 830 | self.root.share_autosubscribe_enabled() | ||
855 | 831 | self.mocker.result(True) | ||
856 | 832 | self.mocker.replay() | ||
857 | 833 | result = yield sdtool.is_share_autosubscribe_enabled() | ||
858 | 834 | self.mocker.verify() | ||
859 | 835 | self.assertTrue(result) | ||
860 | 836 | |||
861 | 837 | d = self._connect() | ||
862 | 838 | # pylint: disable=E1101 | ||
863 | 839 | d.addCallback(test_execution) | ||
864 | 840 | # pylint: enable=E1101 | ||
865 | 841 | return d | ||
866 | 842 | |||
867 | 843 | def test_enable_share_autosubscribe_true(self): | ||
868 | 844 | """Enable/disable share_autosubscribe.""" | ||
869 | 845 | |||
870 | 846 | @defer.inlineCallbacks | ||
871 | 847 | def test_execution(sdtool): | ||
872 | 848 | """Actual test.""" | ||
873 | 849 | self.root.enable_share_autosubscribe() | ||
874 | 850 | self.mocker.replay() | ||
875 | 851 | yield sdtool.enable_share_autosubscribe(True) | ||
876 | 852 | self.mocker.verify() | ||
877 | 853 | |||
878 | 854 | d = self._connect() | ||
879 | 855 | # pylint: disable=E1101 | ||
880 | 856 | d.addCallback(test_execution) | ||
881 | 857 | # pylint: enable=E1101 | ||
882 | 858 | return d | ||
883 | 859 | |||
884 | 860 | def test_enable_share_autosubscribe_false(self): | ||
885 | 861 | """Enable/disable share_autosubscribe.""" | ||
886 | 862 | |||
887 | 863 | @defer.inlineCallbacks | ||
888 | 864 | def test_execution(sdtool): | ||
889 | 865 | """Actual test.""" | ||
890 | 866 | self.root.disable_share_autosubscribe() | ||
891 | 867 | self.mocker.replay() | ||
892 | 868 | yield sdtool.enable_share_autosubscribe(False) | ||
893 | 869 | self.mocker.verify() | ||
894 | 870 | |||
895 | 871 | d = self._connect() | ||
896 | 872 | # pylint: disable=E1101 | ||
897 | 873 | d.addCallback(test_execution) | ||
898 | 874 | # pylint: enable=E1101 | ||
899 | 875 | return d | ||
900 | 876 | |||
901 | 877 | def test_is_udf_autosubscribe_enabled(self): | ||
902 | 878 | """Test that we can get the config value.""" | ||
903 | 879 | |||
904 | 880 | @defer.inlineCallbacks | ||
905 | 881 | def test_execution(sdtool): | ||
906 | 882 | """Actual test.""" | ||
907 | 883 | self.root.udf_autosubscribe_enabled() | ||
908 | 884 | self.mocker.result(True) | ||
909 | 885 | self.mocker.replay() | ||
910 | 886 | result = yield sdtool.is_udf_autosubscribe_enabled() | ||
911 | 887 | self.mocker.verify() | ||
912 | 888 | self.assertTrue(result) | ||
913 | 889 | |||
914 | 890 | d = self._connect() | ||
915 | 891 | # pylint: disable=E1101 | ||
916 | 892 | d.addCallback(test_execution) | ||
917 | 893 | # pylint: enable=E1101 | ||
918 | 894 | return d | ||
919 | 895 | |||
920 | 896 | def test_enable_udf_autosubscribe_true(self): | ||
921 | 897 | """Test that we can get the config.""" | ||
922 | 898 | |||
923 | 899 | @defer.inlineCallbacks | ||
924 | 900 | def test_execution(sdtool): | ||
925 | 901 | """Actual test.""" | ||
926 | 902 | self.root.enable_udf_autosubscribe() | ||
927 | 903 | self.mocker.replay() | ||
928 | 904 | yield sdtool.enable_udf_autosubscribe(True) | ||
929 | 905 | self.mocker.verify() | ||
930 | 906 | |||
931 | 907 | d = self._connect() | ||
932 | 908 | # pylint: disable=E1101 | ||
933 | 909 | d.addCallback(test_execution) | ||
934 | 910 | # pylint: enable=E1101 | ||
935 | 911 | return d | ||
936 | 912 | |||
937 | 913 | def test_enable_udf_autosubscribe_false(self): | ||
938 | 914 | """Test that we can set the config.""" | ||
939 | 915 | |||
940 | 916 | @defer.inlineCallbacks | ||
941 | 917 | def test_execution(sdtool): | ||
942 | 918 | """Actual test.""" | ||
943 | 919 | self.root.disable_udf_autosubscribe() | ||
944 | 920 | self.mocker.replay() | ||
945 | 921 | yield sdtool.enable_udf_autosubscribe(False) | ||
946 | 922 | self.mocker.verify() | ||
947 | 923 | |||
948 | 924 | d = self._connect() | ||
949 | 925 | # pylint: disable=E1101 | ||
950 | 926 | d.addCallback(test_execution) | ||
951 | 927 | # pylint: enable=E1101 | ||
952 | 928 | return d | ||
953 | 929 | |||
954 | 930 | def test_refresh_volumes(self): | ||
955 | 931 | """Test that we can refresh the volumes.""" | ||
956 | 932 | |||
957 | 933 | @defer.inlineCallbacks | ||
958 | 934 | def test_execution(sdtool): | ||
959 | 935 | """Actual test.""" | ||
960 | 936 | self.root.refresh_volumes() | ||
961 | 937 | self.mocker.replay() | ||
962 | 938 | yield sdtool.refresh_volumes() | ||
963 | 939 | self.mocker.verify() | ||
964 | 940 | |||
965 | 941 | d = self._connect() | ||
966 | 942 | # pylint: disable=E1101 | ||
967 | 943 | d.addCallback(test_execution) | ||
968 | 944 | # pylint: enable=E1101 | ||
969 | 945 | return d | ||
970 | 946 | |||
971 | 947 | def test_rescan_from_scratch(self): | ||
972 | 948 | """Test that we can rescan from scratch.""" | ||
973 | 949 | volume_id = 'volume_id' | ||
974 | 950 | |||
975 | 951 | @defer.inlineCallbacks | ||
976 | 952 | def test_execution(sdtool): | ||
977 | 953 | """Actual test.""" | ||
978 | 954 | self.root.rescan_from_scratch(volume_id) | ||
979 | 955 | self.mocker.replay() | ||
980 | 956 | yield sdtool.rescan_from_scratch(volume_id) | ||
981 | 957 | self.mocker.verify() | ||
982 | 958 | |||
983 | 959 | d = self._connect() | ||
984 | 960 | # pylint: disable=E1101 | ||
985 | 961 | d.addCallback(test_execution) | ||
986 | 962 | # pylint: enable=E1101 | ||
987 | 963 | return d | ||
988 | 964 | |||
989 | 965 | def test_get_dirty_nodes(self): | ||
990 | 966 | """Test that we get the dirty nodes.""" | ||
991 | 967 | dirty_nodes = ['node_1', 'node_2', 'node_3'] | ||
992 | 968 | |||
993 | 969 | @defer.inlineCallbacks | ||
994 | 970 | def test_execution(sdtool): | ||
995 | 971 | """Actual test.""" | ||
996 | 972 | self.root.get_dirty_nodes() | ||
997 | 973 | self.mocker.result(dirty_nodes) | ||
998 | 974 | self.mocker.replay() | ||
999 | 975 | result = yield sdtool.get_dirty_nodes() | ||
1000 | 976 | self.mocker.verify() | ||
1001 | 977 | self.assertEqual(dirty_nodes, result) | ||
1002 | 978 | |||
1003 | 979 | d = self._connect() | ||
1004 | 980 | # pylint: disable=E1101 | ||
1005 | 981 | d.addCallback(test_execution) | ||
1006 | 982 | # pylint: enable=E1101 | ||
1007 | 983 | return d | ||
1008 | 984 | |||
1009 | 985 | def test_get_root_dir(self): | ||
1010 | 986 | """Test that we get the root dir.""" | ||
1011 | 987 | root = '/path/to/root' | ||
1012 | 988 | |||
1013 | 989 | @defer.inlineCallbacks | ||
1014 | 990 | def test_execution(sdtool): | ||
1015 | 991 | """Actual test.""" | ||
1016 | 992 | self.root.get_rootdir() | ||
1017 | 993 | self.mocker.result(root) | ||
1018 | 994 | self.mocker.replay() | ||
1019 | 995 | result = yield sdtool.get_root_dir() | ||
1020 | 996 | self.mocker.verify() | ||
1021 | 997 | self.assertEqual(root, result) | ||
1022 | 998 | |||
1023 | 999 | d = self._connect() | ||
1024 | 1000 | # pylint: disable=E1101 | ||
1025 | 1001 | d.addCallback(test_execution) | ||
1026 | 1002 | # pylint: enable=E1101 | ||
1027 | 1003 | return d | ||
1028 | 1004 | |||
1029 | 1005 | def test_get_shares_dir(self): | ||
1030 | 1006 | """Test that we get the shares dir.""" | ||
1031 | 1007 | shares_dir = '/path/to/shares' | ||
1032 | 1008 | |||
1033 | 1009 | @defer.inlineCallbacks | ||
1034 | 1010 | def test_execution(sdtool): | ||
1035 | 1011 | """Actual test.""" | ||
1036 | 1012 | self.root.get_sharesdir() | ||
1037 | 1013 | self.mocker.result(shares_dir) | ||
1038 | 1014 | self.mocker.replay() | ||
1039 | 1015 | result = yield sdtool.get_shares_dir() | ||
1040 | 1016 | self.mocker.verify() | ||
1041 | 1017 | self.assertEqual(shares_dir, result) | ||
1042 | 1018 | |||
1043 | 1019 | d = self._connect() | ||
1044 | 1020 | # pylint: disable=E1101 | ||
1045 | 1021 | d.addCallback(test_execution) | ||
1046 | 1022 | # pylint: enable=E1101 | ||
1047 | 1023 | return d | ||
1048 | 1024 | |||
1049 | 1025 | def test_get_shares_dir_link(self): | ||
1050 | 1026 | """Test that we get the link dir.""" | ||
1051 | 1027 | link = 'path/to/link' | ||
1052 | 1028 | |||
1053 | 1029 | @defer.inlineCallbacks | ||
1054 | 1030 | def test_execution(sdtool): | ||
1055 | 1031 | """Actual test.""" | ||
1056 | 1032 | self.root.get_sharesdir_link() | ||
1057 | 1033 | self.mocker.result(link) | ||
1058 | 1034 | self.mocker.replay() | ||
1059 | 1035 | result = yield sdtool.get_shares_dir_link() | ||
1060 | 1036 | self.mocker.verify() | ||
1061 | 1037 | self.assertEqual(link, result) | ||
1062 | 1038 | |||
1063 | 1039 | d = self._connect() | ||
1064 | 1040 | # pylint: disable=E1101 | ||
1065 | 1041 | d.addCallback(test_execution) | ||
1066 | 1042 | # pylint: enable=E1101 | ||
1067 | 1043 | return d | ||
1068 | 0 | 1044 | ||
1069 | === modified file 'ubuntuone/platform/windows/ipc_client.py' | |||
1070 | --- ubuntuone/platform/windows/ipc_client.py 2011-05-04 13:39:41 +0000 | |||
1071 | +++ ubuntuone/platform/windows/ipc_client.py 2011-06-23 16:46:29 +0000 | |||
1072 | @@ -18,13 +18,26 @@ | |||
1073 | 18 | """Client lib to simplify the ipc client code.""" | 18 | """Client lib to simplify the ipc client code.""" |
1074 | 19 | 19 | ||
1075 | 20 | import logging | 20 | import logging |
1076 | 21 | |||
1077 | 21 | from functools import wraps | 22 | from functools import wraps |
1080 | 22 | from twisted.spread.pb import Referenceable | 23 | from win32api import GetUserNameEx |
1081 | 23 | from ubuntuone.platform.windows.ipc import RemoteMeta | 24 | from win32con import NameSamCompatible |
1082 | 25 | from twisted.internet import defer, reactor | ||
1083 | 26 | from twisted.spread.pb import Referenceable, PBClientFactory | ||
1084 | 27 | |||
1085 | 28 | from ubuntuone.platform.windows.ipc import RemoteMeta, NAMED_PIPE_URL | ||
1086 | 24 | 29 | ||
1087 | 25 | logger = logging.getLogger("ubuntuone.SyncDaemon.Client") | 30 | logger = logging.getLogger("ubuntuone.SyncDaemon.Client") |
1088 | 26 | 31 | ||
1089 | 27 | 32 | ||
1090 | 33 | class SyncDaemonClientError(Exception): | ||
1091 | 34 | """Error ocurred when trying to be a client.""" | ||
1092 | 35 | |||
1093 | 36 | |||
1094 | 37 | class SyncDaemonClientConnectionError(SyncDaemonClientError): | ||
1095 | 38 | """Error ocurrend when trying to connect.""" | ||
1096 | 39 | |||
1097 | 40 | |||
1098 | 28 | def remote(function): | 41 | def remote(function): |
1099 | 29 | """Decorate the function to make the remote call.""" | 42 | """Decorate the function to make the remote call.""" |
1100 | 30 | @wraps(function) | 43 | @wraps(function) |
1101 | @@ -660,3 +673,95 @@ | |||
1102 | 660 | @signal | 673 | @signal |
1103 | 661 | def on_public_files_list_error(self, error): | 674 | def on_public_files_list_error(self, error): |
1104 | 662 | """Emit the PublicFilesListError signal.""" | 675 | """Emit the PublicFilesListError signal.""" |
1105 | 676 | |||
1106 | 677 | class UbuntuOneClient(object): | ||
1107 | 678 | """Root object that provides access to all the remote objects.""" | ||
1108 | 679 | |||
1109 | 680 | def __init__(self): | ||
1110 | 681 | """Create a new instance.""" | ||
1111 | 682 | self.status = None | ||
1112 | 683 | self.events = None | ||
1113 | 684 | self.sync_daemon = None | ||
1114 | 685 | self.file_system = None | ||
1115 | 686 | self.shares = None | ||
1116 | 687 | self.config = None | ||
1117 | 688 | self.folders = None | ||
1118 | 689 | self.public_files = None | ||
1119 | 690 | self.factory = None | ||
1120 | 691 | self.client = None | ||
1121 | 692 | |||
1122 | 693 | @defer.inlineCallbacks | ||
1123 | 694 | def _request_remote_objects(self, root): | ||
1124 | 695 | """Request all the diff remote objects used for the communication.""" | ||
1125 | 696 | status = yield root.callRemote('get_status') | ||
1126 | 697 | self.status = StatusClient(status) | ||
1127 | 698 | |||
1128 | 699 | events = yield root.callRemote('get_events') | ||
1129 | 700 | self.events = EventsClient(events) | ||
1130 | 701 | |||
1131 | 702 | sync_daemon = yield root.callRemote('get_sync_daemon') | ||
1132 | 703 | self.sync_daemon = SyncDaemonClient(sync_daemon) | ||
1133 | 704 | |||
1134 | 705 | file_system = yield root.callRemote('get_file_system') | ||
1135 | 706 | self.file_system = FileSystemClient(file_system) | ||
1136 | 707 | |||
1137 | 708 | shares = yield root.callRemote('get_shares') | ||
1138 | 709 | self.shares = SharesClient(shares) | ||
1139 | 710 | |||
1140 | 711 | config = yield root.callRemote('get_config') | ||
1141 | 712 | self.config = ConfigClient(config) | ||
1142 | 713 | |||
1143 | 714 | folders = yield root.callRemote('get_folders') | ||
1144 | 715 | self.folders = FoldersClient(folders) | ||
1145 | 716 | |||
1146 | 717 | public_files = yield root.callRemote('get_public_files') | ||
1147 | 718 | self.public_files = PublicFilesClient(public_files) | ||
1148 | 719 | |||
1149 | 720 | defer.returnValue(self) | ||
1150 | 721 | |||
1151 | 722 | @defer.inlineCallbacks | ||
1152 | 723 | def connect(self, pipe=None): | ||
1153 | 724 | """Connect to the sso service.""" | ||
1154 | 725 | # pylint: disable=W0702 | ||
1155 | 726 | try: | ||
1156 | 727 | if pipe is None: | ||
1157 | 728 | pipe = NAMED_PIPE_URL % GetUserNameEx(NameSamCompatible) | ||
1158 | 729 | # got the pipe, lets try and connect to it and get the diff | ||
1159 | 730 | # remote objects for the wrappers | ||
1160 | 731 | self.factory = PBClientFactory() | ||
1161 | 732 | # the reactor does have a connectTCP method | ||
1162 | 733 | # pylint: disable=E1101 | ||
1163 | 734 | self.client = reactor.connectPipe(pipe, self.factory) | ||
1164 | 735 | # pylint: enable=E1101 | ||
1165 | 736 | yield self.factory.getRootObject() | ||
1166 | 737 | yield self._request_remote_objects() | ||
1167 | 738 | except: | ||
1168 | 739 | raise SyncDaemonClientConnectionError( | ||
1169 | 740 | 'Could not connect to the syncdaemon on pipe %.', | ||
1170 | 741 | pipe) | ||
1171 | 742 | # pylint: disable=W0702 | ||
1172 | 743 | |||
1173 | 744 | @defer.inlineCallbacks | ||
1174 | 745 | def register_to_signals(self): | ||
1175 | 746 | """Register the different clients to the signals.""" | ||
1176 | 747 | for client in [self.status, self.events, self.sync_daemon, self.shares, | ||
1177 | 748 | self.folders, self.public_files]: | ||
1178 | 749 | register = getattr(client, 'register_to_signals', None) | ||
1179 | 750 | if register is not None: | ||
1180 | 751 | yield register() | ||
1181 | 752 | defer.returnValue(self) | ||
1182 | 753 | |||
1183 | 754 | @defer.inlineCallbacks | ||
1184 | 755 | def unregister_to_signals(self): | ||
1185 | 756 | """Unregister from the diff signals.""" | ||
1186 | 757 | for client in [self.status, self.events, self.sync_daemon, self.shares, | ||
1187 | 758 | self.folders, self.public_files]: | ||
1188 | 759 | unregister = getattr(client, 'unregister_to_signals', None) | ||
1189 | 760 | if unregister is not None: | ||
1190 | 761 | yield unregister() | ||
1191 | 762 | defer.returnValue(self) | ||
1192 | 763 | |||
1193 | 764 | def disconnect(self): | ||
1194 | 765 | """Disconnect from the process.""" | ||
1195 | 766 | if self.client: | ||
1196 | 767 | self.client.disconnect() | ||
1197 | 663 | 768 | ||
1198 | === added file 'ubuntuone/platform/windows/tools.py' | |||
1199 | --- ubuntuone/platform/windows/tools.py 1970-01-01 00:00:00 +0000 | |||
1200 | +++ ubuntuone/platform/windows/tools.py 2011-06-23 16:46:29 +0000 | |||
1201 | @@ -0,0 +1,570 @@ | |||
1202 | 1 | # ubuntuone.syncdaemon.tools - tools for SyncDaemon | ||
1203 | 2 | # | ||
1204 | 3 | # Author: Guillermo Gonzalez <guillermo.gonzalez@canonical.com> | ||
1205 | 4 | # Manuel de la Pena <manuel@canonical.com> | ||
1206 | 5 | # | ||
1207 | 6 | # Copyright 2011 Canonical Ltd. | ||
1208 | 7 | # | ||
1209 | 8 | # This program is free software: you can redistribute it and/or modify it | ||
1210 | 9 | # under the terms of the GNU General Public License version 3, as published | ||
1211 | 10 | # by the Free Software Foundation. | ||
1212 | 11 | # | ||
1213 | 12 | # This program is distributed in the hope that it will be useful, but | ||
1214 | 13 | # WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1215 | 14 | # MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1216 | 15 | # PURPOSE. See the GNU General Public License for more details. | ||
1217 | 16 | # | ||
1218 | 17 | # You should have received a copy of the GNU General Public License along | ||
1219 | 18 | # with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1220 | 19 | |||
1221 | 20 | """SyncDaemon Tools.""" | ||
1222 | 21 | |||
1223 | 22 | import logging | ||
1224 | 23 | import time | ||
1225 | 24 | import sys | ||
1226 | 25 | |||
1227 | 26 | from win32api import GetUserNameEx | ||
1228 | 27 | from win32con import NameSamCompatible | ||
1229 | 28 | from win32pipe import CallNamedPipe | ||
1230 | 29 | from twisted.internet import defer, reactor | ||
1231 | 30 | |||
1232 | 31 | from ubuntuone.syncdaemon.config import get_user_config | ||
1233 | 32 | from ubuntuone.platform.windows.ipc import NAMED_PIPE_URL | ||
1234 | 33 | from ubuntuone.platform.windows.ipc_client import UbuntuOneClient | ||
1235 | 34 | |||
1236 | 35 | |||
1237 | 36 | def is_running(bus=None): | ||
1238 | 37 | """Check if there is a syncdaemon instance running. | ||
1239 | 38 | |||
1240 | 39 | Running means the name is registered in the given bus. | ||
1241 | 40 | |||
1242 | 41 | """ | ||
1243 | 42 | pipe = NAMED_PIPE_URL % GetUserNameEx(NameSamCompatible) | ||
1244 | 43 | try: | ||
1245 | 44 | CallNamedPipe(pipe, '', 512, 0) | ||
1246 | 45 | return True | ||
1247 | 46 | except: | ||
1248 | 47 | return False | ||
1249 | 48 | |||
1250 | 49 | |||
1251 | 50 | class SyncDaemonTool(object): | ||
1252 | 51 | """Various utility methods to test/play with the SyncDaemon.""" | ||
1253 | 52 | |||
1254 | 53 | def __init__(self, named_pipe=None): | ||
1255 | 54 | self.named_pipe = named_pipe | ||
1256 | 55 | self.client = UbuntuOneClient() | ||
1257 | 56 | self.last_event = 0 | ||
1258 | 57 | self.delayed_call = None | ||
1259 | 58 | self.log = logging.getLogger('ubuntuone.SyncDaemon.SDTool') | ||
1260 | 59 | |||
1261 | 60 | |||
1262 | 61 | def _get_dict(self, a_dict): | ||
1263 | 62 | """Converts a dict returned by the IPC to a dict of strings.""" | ||
1264 | 63 | str_dict = {} | ||
1265 | 64 | for key in a_dict: | ||
1266 | 65 | str_dict[key] = unicode(a_dict[key]) | ||
1267 | 66 | return str_dict | ||
1268 | 67 | |||
1269 | 68 | def wait_connected(self): | ||
1270 | 69 | """Wait until syncdaemon is connected to the server.""" | ||
1271 | 70 | self.log.debug('wait_connected') | ||
1272 | 71 | d = defer.Deferred() | ||
1273 | 72 | |||
1274 | 73 | def check_connection_status(): | ||
1275 | 74 | """Check if the daemon is up and running.""" | ||
1276 | 75 | # check if the syncdaemon is running | ||
1277 | 76 | # catch all errors, pylint: disable-msg=W0703 | ||
1278 | 77 | try: | ||
1279 | 78 | self.client.connect(pipe=self.named_pipe) | ||
1280 | 79 | d.callback(True) | ||
1281 | 80 | except Exception, e: | ||
1282 | 81 | self.log.debug('Not connected: %s', e) | ||
1283 | 82 | d.errback() | ||
1284 | 83 | |||
1285 | 84 | reactor.callLater(.5, check_connection_status) | ||
1286 | 85 | return d | ||
1287 | 86 | |||
1288 | 87 | def get_current_downloads(self): | ||
1289 | 88 | """Return a deferred that will be fired with the current downloads.""" | ||
1290 | 89 | d = defer.Deferred() | ||
1291 | 90 | |||
1292 | 91 | def reply_handler(downloads, d): | ||
1293 | 92 | """Current downloads callback.""" | ||
1294 | 93 | downloads_str = [] | ||
1295 | 94 | for download in downloads: | ||
1296 | 95 | downloads_str.append(self._get_dict(download)) | ||
1297 | 96 | d.callback(downloads_str) | ||
1298 | 97 | |||
1299 | 98 | downloads_d = self.client.status.current_downloads() | ||
1300 | 99 | downloads_d.addCallback(lambda downloads: reply_handler(downloads, d)) | ||
1301 | 100 | return d | ||
1302 | 101 | |||
1303 | 102 | def wait_all_downloads(self, verbose=False): | ||
1304 | 103 | """Wait until there is no more pending downloads.""" | ||
1305 | 104 | self.log.debug('wait_all_downloads') | ||
1306 | 105 | d = self.get_current_downloads() | ||
1307 | 106 | |||
1308 | 107 | def reply_handler(downloads): | ||
1309 | 108 | """Check if the are downloads in progress. | ||
1310 | 109 | |||
1311 | 110 | If so, reschelude a new check if there is at least one. | ||
1312 | 111 | |||
1313 | 112 | """ | ||
1314 | 113 | if verbose: | ||
1315 | 114 | sys.stdout.write(', %s' % str(len(downloads))) | ||
1316 | 115 | sys.stdout.flush() | ||
1317 | 116 | if len(downloads) > 0: | ||
1318 | 117 | self.log.debug('wait_all_downloads: %d', len(downloads)) | ||
1319 | 118 | return self.get_current_downloads() | ||
1320 | 119 | else: | ||
1321 | 120 | self.log.debug('wait_all_downloads: No more downloads') | ||
1322 | 121 | return True | ||
1323 | 122 | |||
1324 | 123 | if verbose: | ||
1325 | 124 | sys.stdout.write('\nchecking current downloads') | ||
1326 | 125 | sys.stdout.flush() | ||
1327 | 126 | d.addCallback(reply_handler) | ||
1328 | 127 | return d | ||
1329 | 128 | |||
1330 | 129 | def get_current_uploads(self): | ||
1331 | 130 | """Return a deferred that will be called with the current uploads.""" | ||
1332 | 131 | d = defer.Deferred() | ||
1333 | 132 | |||
1334 | 133 | def reply_handler(uploads, d): | ||
1335 | 134 | """Reply handler.""" | ||
1336 | 135 | uploads_str = [] | ||
1337 | 136 | for upload in uploads: | ||
1338 | 137 | uploads_str.append(self._get_dict(upload)) | ||
1339 | 138 | d.callback(uploads_str) | ||
1340 | 139 | |||
1341 | 140 | uploads_d = self.client.status.current_uploads() | ||
1342 | 141 | uploads_d.addCallback(lambda uploads: reply_handler(uploads, d)) | ||
1343 | 142 | return d | ||
1344 | 143 | |||
1345 | 144 | def wait_all_uploads(self, verbose=False): | ||
1346 | 145 | """Wait until there is no more pending uploads.""" | ||
1347 | 146 | self.log.debug('wait_all_uploads') | ||
1348 | 147 | d = self.get_current_uploads() | ||
1349 | 148 | |||
1350 | 149 | def reply_handler(uploads): | ||
1351 | 150 | """Check if the are downloads in progress. | ||
1352 | 151 | |||
1353 | 152 | If so, reschelude a new check if there is at least one. | ||
1354 | 153 | |||
1355 | 154 | """ | ||
1356 | 155 | if verbose: | ||
1357 | 156 | sys.stdout.write(', %s' % str(len(uploads))) | ||
1358 | 157 | sys.stdout.flush() | ||
1359 | 158 | if len(uploads) > 0: | ||
1360 | 159 | self.log.debug('wait_all_uploads: %d', len(uploads)) | ||
1361 | 160 | return self.get_current_uploads() | ||
1362 | 161 | else: | ||
1363 | 162 | self.log.debug('wait_all_uploads: No more uploads') | ||
1364 | 163 | return True | ||
1365 | 164 | |||
1366 | 165 | if verbose: | ||
1367 | 166 | sys.stdout.write('\nchecking current uploads') | ||
1368 | 167 | sys.stdout.flush() | ||
1369 | 168 | |||
1370 | 169 | d.addCallback(reply_handler) | ||
1371 | 170 | return d | ||
1372 | 171 | |||
1373 | 172 | def wait_no_more_events(self, last_event_interval, verbose=False): | ||
1374 | 173 | """Wait until no more events are fired by the syncdaemon.""" | ||
1375 | 174 | self.log.debug('wait_no_more_events') | ||
1376 | 175 | d = defer.Deferred() | ||
1377 | 176 | |||
1378 | 177 | def check_last_event(): | ||
1379 | 178 | """Check time! | ||
1380 | 179 | |||
1381 | 180 | Check if the daemon is connected and didn't received event | ||
1382 | 181 | in the last_event_interval. | ||
1383 | 182 | """ | ||
1384 | 183 | current_time = time.time() | ||
1385 | 184 | if self.last_event and \ | ||
1386 | 185 | current_time - self.last_event < last_event_interval: | ||
1387 | 186 | # keep it running in case this is the last event | ||
1388 | 187 | self.log.debug('rescheduling wait_no_more_events') | ||
1389 | 188 | if not self.delayed_call.active(): | ||
1390 | 189 | self.delayed_call = reactor.callLater(last_event_interval, | ||
1391 | 190 | check_last_event) | ||
1392 | 191 | else: | ||
1393 | 192 | self.delayed_call.reset(last_event_interval) | ||
1394 | 193 | else: | ||
1395 | 194 | self.log.debug('wait_no_more_events: No more events!') | ||
1396 | 195 | d.callback(True) | ||
1397 | 196 | |||
1398 | 197 | if verbose: | ||
1399 | 198 | sys.stdout.write("Listening events") | ||
1400 | 199 | sys.stdout.flush() | ||
1401 | 200 | |||
1402 | 201 | def event_handler(event_dict): | ||
1403 | 202 | """Update last_event and run checks.""" | ||
1404 | 203 | self.last_event = time.time() | ||
1405 | 204 | self.log.debug('wait_no_more_events - new event: %s - %s', | ||
1406 | 205 | event_dict['event_name'], str(self.last_event)) | ||
1407 | 206 | if verbose: | ||
1408 | 207 | sys.stdout.write('.') | ||
1409 | 208 | sys.stdout.flush() | ||
1410 | 209 | if self.delayed_call.active(): | ||
1411 | 210 | self.delayed_call.reset(last_event_interval) | ||
1412 | 211 | |||
1413 | 212 | self.client.events.on_event_cb = event_handler | ||
1414 | 213 | |||
1415 | 214 | def cleanup(result): | ||
1416 | 215 | """Remove the signal handler.""" | ||
1417 | 216 | self.client.events.on_event_cb = None | ||
1418 | 217 | return result | ||
1419 | 218 | d.addBoth(cleanup) | ||
1420 | 219 | |||
1421 | 220 | # in case the daemon already reached nirvana | ||
1422 | 221 | self.delayed_call = reactor.callLater(last_event_interval, | ||
1423 | 222 | check_last_event) | ||
1424 | 223 | return d | ||
1425 | 224 | |||
1426 | 225 | def wait_for_nirvana(self, last_event_interval=5, verbose=False): | ||
1427 | 226 | """Wait until the syncdaemon reachs nirvana. | ||
1428 | 227 | |||
1429 | 228 | This is when there are: | ||
1430 | 229 | - the syncdaemon is connected | ||
1431 | 230 | - 0 transfers inprogress | ||
1432 | 231 | - no more events are fired in the event queue | ||
1433 | 232 | @param last_event_interval: the seconds to wait to determine that there | ||
1434 | 233 | is no more events in the queue and the daemon reached nirvana | ||
1435 | 234 | """ | ||
1436 | 235 | self.log.debug('wait_for_nirvana') | ||
1437 | 236 | return self.client.sync_daemon.wait_for_nirvana(last_event_interval) | ||
1438 | 237 | |||
1439 | 238 | def accept_share(self, share_id): | ||
1440 | 239 | """Accept the share with id: share_id.""" | ||
1441 | 240 | self.log.debug('accept_share(%s)', share_id) | ||
1442 | 241 | self.client.shares.on_share_answer_response = lambda info:\ | ||
1443 | 242 | info['volume_id']==share_id | ||
1444 | 243 | return self.client.shares.accept_share(share_id) | ||
1445 | 244 | |||
1446 | 245 | def reject_share(self, share_id): | ||
1447 | 246 | """Reject the share with id: share_id.""" | ||
1448 | 247 | self.log.debug('reject_share(%s)', share_id) | ||
1449 | 248 | self.client.shares.on_share_answer_response = lambda info:\ | ||
1450 | 249 | info['volume_id']==share_id | ||
1451 | 250 | return self.client.shares.reject_share(share_id) | ||
1452 | 251 | |||
1453 | 252 | def subscribe_share(self, share_id): | ||
1454 | 253 | """Subscribe to a share given its id.""" | ||
1455 | 254 | self.log.debug('subscribe_share: %r', share_id) | ||
1456 | 255 | return self.client.shares.subscribe(share_id) | ||
1457 | 256 | |||
1458 | 257 | def unsubscribe_share(self, share_id): | ||
1459 | 258 | """Unsubscribe from a share given its id.""" | ||
1460 | 259 | self.log.debug('unsubscribe_share: %r', share_id) | ||
1461 | 260 | return self.client.shares.unsubscribe(share_id) | ||
1462 | 261 | |||
1463 | 262 | def get_shares(self): | ||
1464 | 263 | """Get the list of shares (accepted or not).""" | ||
1465 | 264 | self.log.debug('get_shares') | ||
1466 | 265 | d = defer.Deferred() | ||
1467 | 266 | |||
1468 | 267 | def reply_handler(results): | ||
1469 | 268 | """Get_shares reply handler.""" | ||
1470 | 269 | shares = [] | ||
1471 | 270 | for result in results: | ||
1472 | 271 | shares.append(self._get_dict(result)) | ||
1473 | 272 | self.log.debug('shares: %r', shares) | ||
1474 | 273 | d.callback(shares) | ||
1475 | 274 | |||
1476 | 275 | shares_d = self.client.shares.get_shares() | ||
1477 | 276 | shares_d.addCallback(reply_handler) | ||
1478 | 277 | return d | ||
1479 | 278 | |||
1480 | 279 | def refresh_shares(self): | ||
1481 | 280 | """Call refresh_shares method via DBus. | ||
1482 | 281 | |||
1483 | 282 | Request a refresh of share list to the server. | ||
1484 | 283 | |||
1485 | 284 | """ | ||
1486 | 285 | self.log.debug('refresh_shares') | ||
1487 | 286 | return self.client.shares.refresh_shares() | ||
1488 | 287 | |||
1489 | 288 | def offer_share(self, path, username, name, access_level): | ||
1490 | 289 | """Offer a share at the specified path to user with id: username.""" | ||
1491 | 290 | self.log.debug('offer_share(%s, %s, %s, %s)', | ||
1492 | 291 | path, username, name, access_level) | ||
1493 | 292 | return self.client.shares.create_share(path, username, name, | ||
1494 | 293 | access_level) | ||
1495 | 294 | |||
1496 | 295 | def list_shared(self): | ||
1497 | 296 | """Get the list of the shares "shared"/created/offered.""" | ||
1498 | 297 | self.log.debug('list_shared') | ||
1499 | 298 | d = defer.Deferred() | ||
1500 | 299 | |||
1501 | 300 | def reply_handler(results): | ||
1502 | 301 | """Get_shares reply handler.""" | ||
1503 | 302 | shares = [] | ||
1504 | 303 | for result in results: | ||
1505 | 304 | shares.append(self._get_dict(result)) | ||
1506 | 305 | self.log.debug('shared: %r', shares) | ||
1507 | 306 | d.callback(shares) | ||
1508 | 307 | |||
1509 | 308 | shared_d = self.client.shares.get_shared() | ||
1510 | 309 | shared_d.addCallback(reply_handler) | ||
1511 | 310 | return d | ||
1512 | 311 | |||
1513 | 312 | def wait_for_signals(self, signal_ok, signal_error, | ||
1514 | 313 | dbus_iface=None): | ||
1515 | 314 | """Wait for one of the specified signals, return a deferred. | ||
1516 | 315 | |||
1517 | 316 | @param signal_ok: this will fire the deferred's callback | ||
1518 | 317 | @param signal_error: the will fire the deferred's errback | ||
1519 | 318 | @param dbus_iface: the interface the signal belongs to | ||
1520 | 319 | """ | ||
1521 | 320 | raise NotImplementedError('Not implemented yet!') | ||
1522 | 321 | |||
1523 | 322 | def create_folder(self, path): | ||
1524 | 323 | """Create a user defined folder in the specified path.""" | ||
1525 | 324 | self.log.debug('create_folder') | ||
1526 | 325 | return self.client.folders.create(path) | ||
1527 | 326 | |||
1528 | 327 | def delete_folder(self, folder_id): | ||
1529 | 328 | """Delete a user defined folder given its id.""" | ||
1530 | 329 | self.log.debug('delete_folder') | ||
1531 | 330 | return self.client.folders.delete(folder_id) | ||
1532 | 331 | |||
1533 | 332 | def subscribe_folder(self, folder_id): | ||
1534 | 333 | """Subscribe to a user defined folder given its id.""" | ||
1535 | 334 | self.log.debug('subscribe_folder') | ||
1536 | 335 | return self.client.folders.subscribe(folder_id) | ||
1537 | 336 | |||
1538 | 337 | def unsubscribe_folder(self, folder_id): | ||
1539 | 338 | """Unsubscribe from a user defined folder given its id.""" | ||
1540 | 339 | self.log.debug('unsubscribe_folder') | ||
1541 | 340 | return self.client.folders.unsubscribe(folder_id) | ||
1542 | 341 | |||
1543 | 342 | def get_folders(self): | ||
1544 | 343 | """Return the list of folders (a list of dicts).""" | ||
1545 | 344 | self.log.debug('get_folders') | ||
1546 | 345 | d = defer.Deferred() | ||
1547 | 346 | |||
1548 | 347 | def reply_handler(results): | ||
1549 | 348 | """Get_folders reply handler.""" | ||
1550 | 349 | folders = [] | ||
1551 | 350 | for result in results: | ||
1552 | 351 | folders.append(self._get_dict(result)) | ||
1553 | 352 | self.log.debug('folders: %r', folders) | ||
1554 | 353 | d.callback(folders) | ||
1555 | 354 | |||
1556 | 355 | folders_d = self.client.folders.get_folders() | ||
1557 | 356 | folders_d.addCallback(reply_handler) | ||
1558 | 357 | return d | ||
1559 | 358 | |||
1560 | 359 | def get_folder_info(self, path): | ||
1561 | 360 | """Call the get_info method for a UDF path.""" | ||
1562 | 361 | self.log.debug('get_info') | ||
1563 | 362 | return self.client.folders.get_info(path) | ||
1564 | 363 | |||
1565 | 364 | def get_metadata(self, path): | ||
1566 | 365 | """Call the exposed mtehod FileSystem.get_metadata using DBus.""" | ||
1567 | 366 | self.log.debug('get_metadata(%s)', path) | ||
1568 | 367 | return self.client.file_system.get_metadata(path) | ||
1569 | 368 | |||
1570 | 369 | @defer.inlineCallbacks | ||
1571 | 370 | def change_public_access(self, path, is_public): | ||
1572 | 371 | """Change the public access for a given path.""" | ||
1573 | 372 | self.log.debug('change_public_access(%s)', path) | ||
1574 | 373 | metadata = yield self.client.file_system.get_metadata(path) | ||
1575 | 374 | file_info = yield self.client.public_files.change_public_access( | ||
1576 | 375 | metadata['share_id'], | ||
1577 | 376 | metadata['node_id'], | ||
1578 | 377 | is_public) | ||
1579 | 378 | defer.returnValue(file_info) | ||
1580 | 379 | |||
1581 | 380 | def quit(self): | ||
1582 | 381 | """Quit the syncdaemon.""" | ||
1583 | 382 | self.log.debug('quit') | ||
1584 | 383 | # avoid triggering dbus activation while calling quit | ||
1585 | 384 | if not is_running(): | ||
1586 | 385 | return defer.succeed(None) | ||
1587 | 386 | |||
1588 | 387 | def check(r): | ||
1589 | 388 | """Wait 0.5 sec to return, to allow syncdaemon to shutdown.""" | ||
1590 | 389 | d1 = defer.Deferred() | ||
1591 | 390 | reactor.callLater(0.5, d1.callback, r) | ||
1592 | 391 | return d1 | ||
1593 | 392 | |||
1594 | 393 | d = self.client.sync_daemon.quit() | ||
1595 | 394 | d.addCallback(check) | ||
1596 | 395 | return d | ||
1597 | 396 | |||
1598 | 397 | def wait_for_signal(self, signal_name, filter): | ||
1599 | 398 | """Wait for the specified DBus signal (the first received). | ||
1600 | 399 | |||
1601 | 400 | @param signal_name: the signal name | ||
1602 | 401 | @param filter: a callable to filter signal, must return True, and is | ||
1603 | 402 | used to fire the deferred callback. | ||
1604 | 403 | |||
1605 | 404 | """ | ||
1606 | 405 | raise NotImplementedError('Not implemented.') | ||
1607 | 406 | |||
1608 | 407 | def connect(self): | ||
1609 | 408 | """Connect syncdaemon.""" | ||
1610 | 409 | return self.client.sync_daemon.connect() | ||
1611 | 410 | |||
1612 | 411 | def disconnect(self): | ||
1613 | 412 | """Disconnect syncdaemon.""" | ||
1614 | 413 | return self.client.sync_daemon.disconnect() | ||
1615 | 414 | |||
1616 | 415 | def get_status(self): | ||
1617 | 416 | """Get the current_status dict.""" | ||
1618 | 417 | |||
1619 | 418 | d = defer.Deferred() | ||
1620 | 419 | def reply_handler(status): | ||
1621 | 420 | """The reply handler""" | ||
1622 | 421 | state_dict = self._get_dict(status) | ||
1623 | 422 | state_dict['is_connected'] = bool(state_dict['is_connected']) | ||
1624 | 423 | state_dict['is_online'] = bool(state_dict['is_online']) | ||
1625 | 424 | state_dict['is_error'] = bool(state_dict['is_error']) | ||
1626 | 425 | d.callback(state_dict) | ||
1627 | 426 | status_d = self.client.status.current_status() | ||
1628 | 427 | status_d.addCallback(reply_handler) | ||
1629 | 428 | status_d.addErrback(d.errback) | ||
1630 | 429 | return d | ||
1631 | 430 | |||
1632 | 431 | def waiting(self): | ||
1633 | 432 | """Return a description of the waiting queue elements.""" | ||
1634 | 433 | return self.client.status.waiting() | ||
1635 | 434 | |||
1636 | 435 | def waiting_metadata(self): | ||
1637 | 436 | """Return a description of the waiting metadata queue elements.""" | ||
1638 | 437 | return self.client.status.waiting_metadata() | ||
1639 | 438 | |||
1640 | 439 | def waiting_content(self): | ||
1641 | 440 | """Return the waiting content queue elements.""" | ||
1642 | 441 | return self.client.status.waiting_content() | ||
1643 | 442 | |||
1644 | 443 | def start(self): | ||
1645 | 444 | """Start syncdaemon if it's not running.""" | ||
1646 | 445 | if not is_running(self.bus): | ||
1647 | 446 | raise Exception('Not implemented yet!') | ||
1648 | 447 | else: | ||
1649 | 448 | return defer.succeed(None) | ||
1650 | 449 | |||
1651 | 450 | def get_throttling_limits(self): | ||
1652 | 451 | """Return a dict with the read and write limits.""" | ||
1653 | 452 | return self.client.config.get_throttling_limits() | ||
1654 | 453 | |||
1655 | 454 | def set_throttling_limits(self, read_limit, write_limit): | ||
1656 | 455 | """Set the read and write limits.""" | ||
1657 | 456 | return self.client.config.set_throttling_limits(read_limit, | ||
1658 | 457 | write_limit) | ||
1659 | 458 | |||
1660 | 459 | def is_throttling_enabled(self): | ||
1661 | 460 | """Check if throttling is enabled.""" | ||
1662 | 461 | return self.client.config.bandwidth_throttling_enabled() | ||
1663 | 462 | |||
1664 | 463 | def enable_throttling(self, enabled): | ||
1665 | 464 | """Enable/disable throttling.""" | ||
1666 | 465 | if enabled: | ||
1667 | 466 | return self.client.config.enable_bandwidth_throttling() | ||
1668 | 467 | else: | ||
1669 | 468 | return self.client.config.disable_bandwidth_throttling() | ||
1670 | 469 | |||
1671 | 470 | def is_files_sync_enabled(self): | ||
1672 | 471 | """Check if files sync is enabled.""" | ||
1673 | 472 | self.log.debug('is_files_sync_enabled') | ||
1674 | 473 | return get_user_config().get_files_sync_enabled() | ||
1675 | 474 | |||
1676 | 475 | @defer.inlineCallbacks | ||
1677 | 476 | def enable_files_sync(self, enabled): | ||
1678 | 477 | """Enable/disable files sync.""" | ||
1679 | 478 | config = get_user_config() | ||
1680 | 479 | was_enabled = config.get_files_sync_enabled() | ||
1681 | 480 | self.log.debug('enable_files_sync: enable? %r was enabled? %r', | ||
1682 | 481 | enabled, was_enabled) | ||
1683 | 482 | if was_enabled: | ||
1684 | 483 | yield self.client.config.set_files_sync_enabled(enabled) | ||
1685 | 484 | config.set_files_sync_enabled(enabled) | ||
1686 | 485 | if not enabled: | ||
1687 | 486 | # User requested the service to be disabled | ||
1688 | 487 | self.quit() | ||
1689 | 488 | else: | ||
1690 | 489 | if enabled: | ||
1691 | 490 | config.set_files_sync_enabled(True) | ||
1692 | 491 | config.save() | ||
1693 | 492 | self.start() | ||
1694 | 493 | |||
1695 | 494 | def is_autoconnect_enabled(self): | ||
1696 | 495 | """Check if autoconnect is enabled.""" | ||
1697 | 496 | return self.client.config.autoconnect_enabled() | ||
1698 | 497 | |||
1699 | 498 | def enable_autoconnect(self, enabled): | ||
1700 | 499 | """Enable/disable autoconnect.""" | ||
1701 | 500 | return self.client.config.set_autoconnect_enabled(enabled) | ||
1702 | 501 | |||
1703 | 502 | def is_show_all_notifications_enabled(self): | ||
1704 | 503 | """Check if show_all_notifications is enabled.""" | ||
1705 | 504 | return self.client.config.show_all_notifications_enabled() | ||
1706 | 505 | |||
1707 | 506 | def enable_show_all_notifications(self, enabled): | ||
1708 | 507 | """Enable/disable show_all_notifications.""" | ||
1709 | 508 | if enabled: | ||
1710 | 509 | return self.client.config.enable_show_all_notifications() | ||
1711 | 510 | else: | ||
1712 | 511 | return self.client.config.disable_show_all_notifications() | ||
1713 | 512 | |||
1714 | 513 | def is_share_autosubscribe_enabled(self): | ||
1715 | 514 | """Check if share_autosubscribe is enabled.""" | ||
1716 | 515 | return self.client.config.share_autosubscribe_enabled() | ||
1717 | 516 | |||
1718 | 517 | def enable_share_autosubscribe(self, enabled): | ||
1719 | 518 | """Enable/disable share_autosubscribe.""" | ||
1720 | 519 | if enabled: | ||
1721 | 520 | return self.client.config.enable_share_autosubscribe() | ||
1722 | 521 | else: | ||
1723 | 522 | return self.client.config.disable_share_autosubscribe() | ||
1724 | 523 | |||
1725 | 524 | def is_udf_autosubscribe_enabled(self): | ||
1726 | 525 | """Check if udf_autosubscribe is enabled.""" | ||
1727 | 526 | return self.client.config.udf_autosubscribe_enabled() | ||
1728 | 527 | |||
1729 | 528 | def enable_udf_autosubscribe(self, enabled): | ||
1730 | 529 | """Enable/disable udf_autosubscribe.""" | ||
1731 | 530 | if enabled: | ||
1732 | 531 | return self.client.config.enable_udf_autosubscribe() | ||
1733 | 532 | else: | ||
1734 | 533 | return self.client.config.disable_udf_autosubscribe() | ||
1735 | 534 | |||
1736 | 535 | def refresh_volumes(self): | ||
1737 | 536 | """Call refresh_volumes method via DBus. | ||
1738 | 537 | |||
1739 | 538 | Request the volumes list to the server. | ||
1740 | 539 | """ | ||
1741 | 540 | self.log.debug('refresh_volumes') | ||
1742 | 541 | return self.client.folders.refresh_volumes() | ||
1743 | 542 | |||
1744 | 543 | def rescan_from_scratch(self, volume_id): | ||
1745 | 544 | """Call rescan_from_scratch via DBus. | ||
1746 | 545 | |||
1747 | 546 | Request a rescan from scratch for volume_id. | ||
1748 | 547 | """ | ||
1749 | 548 | self.log.debug('rescan_from_scratch %r', volume_id) | ||
1750 | 549 | return self.client.sync_daemon.rescan_from_scratch(volume_id) | ||
1751 | 550 | |||
1752 | 551 | def get_dirty_nodes(self): | ||
1753 | 552 | """Call get_dirty_nodes via DBus. | ||
1754 | 553 | |||
1755 | 554 | Return the list of dirty nodes. | ||
1756 | 555 | """ | ||
1757 | 556 | self.log.debug('get_dirty_nodes') | ||
1758 | 557 | return self.client.file_system.get_dirty_nodes() | ||
1759 | 558 | |||
1760 | 559 | def get_root_dir(self): | ||
1761 | 560 | """Return the root directory.""" | ||
1762 | 561 | return self.client.sync_daemon.get_rootdir() | ||
1763 | 562 | |||
1764 | 563 | def get_shares_dir(self): | ||
1765 | 564 | """Return the shares directory.""" | ||
1766 | 565 | return self.client.sync_daemon.get_sharesdir() | ||
1767 | 566 | |||
1768 | 567 | def get_shares_dir_link(self): | ||
1769 | 568 | """Return the shares link directory.""" | ||
1770 | 569 | return self.client.sync_daemon.get_sharesdir_link() | ||
1771 | 570 |
* In order to really handle all the possible errors in UbuntuOneClient .connect, please add to it the inlineCallbacks decorator and change:
d = self.factory. getRootObject( )
d. addCallback( self._request_ remote_ objects)
return d
for:
yield self.factory. getRootObject( ) remote_ objects
yield self._request_
* We need tests for the SDTool...