Merge lp:~facundo/magicicada-gui/fake-dbus into lp:magicicada-gui
- fake-dbus
- Merge into trunk
Proposed by
Facundo Batista
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Natalia Bidart | ||||
Approved revision: | 37 | ||||
Merged at revision: | 27 | ||||
Proposed branch: | lp:~facundo/magicicada-gui/fake-dbus | ||||
Merge into: | lp:magicicada-gui | ||||
Diff against target: |
2583 lines (+1509/-752) 6 files modified
magicicada/dbusiface.py (+288/-0) magicicada/syncdaemon.py (+104/-233) magicicada/tests/helpers.py (+49/-0) magicicada/tests/test_dbusiface.py (+665/-0) magicicada/tests/test_magicicada.py (+4/-3) magicicada/tests/test_syncdaemon.py (+399/-516) |
||||
To merge this branch: | bzr merge lp:~facundo/magicicada-gui/fake-dbus | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Natalia Bidart | Approve | ||
Review via email: mp+26007@code.launchpad.net |
Commit message
Description of the change
DBus refactoring.
Now all the dbus details are handled in a separate module/class, with its tests.
SyncDaemon now is a lot more simpler.
Zillion of test cases added and refactored.
To post a comment you must log in.
- 31. By Facundo Batista
-
Merged trunk in
- 32. By Facundo Batista
-
Changed where I log start
- 33. By Facundo Batista
-
Get initial data only when it should
- 34. By Facundo Batista
-
One more case
- 35. By Facundo Batista
- 36. By Facundo Batista
-
Initial callbacks
- 37. By Facundo Batista
-
Yes, we should put docstrings... but not twice!
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'magicicada/dbusiface.py' |
2 | --- magicicada/dbusiface.py 1970-01-01 00:00:00 +0000 |
3 | +++ magicicada/dbusiface.py 2010-05-27 20:56:26 +0000 |
4 | @@ -0,0 +1,288 @@ |
5 | +# dbusiface.py |
6 | +# |
7 | +# Author: Facundo Batista <facundo@taniquetil.com.ar> |
8 | +# |
9 | +# Copyright 2010 Chicharreros |
10 | +# |
11 | +# This program is free software: you can redistribute it and/or modify it |
12 | +# under the terms of the GNU General Public License version 3, as published |
13 | +# by the Free Software Foundation. |
14 | +# |
15 | +# This program is distributed in the hope that it will be useful, but |
16 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
17 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
18 | +# PURPOSE. See the GNU General Public License for more details. |
19 | +# |
20 | +# You should have received a copy of the GNU General Public License along |
21 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | + |
23 | +"""The DBus Interface.""" |
24 | + |
25 | +import collections |
26 | +import logging |
27 | +import re |
28 | +import sys |
29 | + |
30 | +import dbus |
31 | +from dbus import SessionBus |
32 | +from dbus.mainloop.glib import DBusGMainLoop |
33 | + |
34 | +from ubuntuone.syncdaemon.tools import SyncDaemonTool |
35 | + |
36 | +# log! |
37 | +logger = logging.getLogger('magicicada.dbusiface') |
38 | +handler = logging.StreamHandler(sys.stdout) |
39 | +logger.addHandler(handler) |
40 | +formatter = logging.Formatter("%(asctime)s %(name)s:%(lineno)-4d " |
41 | + "%(levelname)-8s %(message)s", |
42 | + '%Y-%m-%d %H:%M:%S') |
43 | +handler.setFormatter(formatter) |
44 | +logger.setLevel(logging.DEBUG) |
45 | + |
46 | + |
47 | +QueueData = collections.namedtuple('QueueData', 'operation path share node') |
48 | +FolderData = collections.namedtuple('FolderData', |
49 | + 'node path suggested_path subscribed volume') |
50 | + |
51 | +# regular expressions for parsing MetaQueue data |
52 | +RE_OP_LISTDIR = re.compile("(ListDir)\(share_id=(.*?), node_id=(.*?), .*") |
53 | +RE_OP_UNLINK = re.compile("(Unlink)\(share_id=(.*?), node_id=(.*?), .*") |
54 | +RE_OP_MAKEFILE = re.compile( |
55 | + "(MakeFile)\(share_id=(.*?), parent_id=(.*?), name=(.*?), .*") |
56 | +RE_OP_MAKEDIR = re.compile( |
57 | + "(MakeDir)\(share_id=(.*?), parent_id=(.*?), name=(.*?), .*") |
58 | +RE_OP_MOVE = re.compile( |
59 | + "(Move)\(share_id=(.*?), node_id=(.*?), old_parent_id=(.*?), " |
60 | + "new_parent_id=(.*?), new_name=(.*?)\)") |
61 | + |
62 | + |
63 | +class DBusInterface(object): |
64 | + """The DBus Interface to Ubuntu One's SyncDaemon.""" |
65 | + |
66 | + def __init__(self, msd): |
67 | + # magicicada's syncdaemon |
68 | + self.msd = msd |
69 | + logger.info("DBus interface starting") |
70 | + |
71 | + # set up dbus and related stuff |
72 | + loop = DBusGMainLoop(set_as_default=True) |
73 | + self._bus = bus = SessionBus(mainloop=loop) |
74 | + self.sync_daemon_tool = SyncDaemonTool(bus) |
75 | + |
76 | + # hook up for signals and store info for the shutdown |
77 | + _signals = [ |
78 | + (self._on_status_changed, 'Status', 'StatusChanged'), |
79 | + (self._on_content_queue_changed, 'Status', 'ContentQueueChanged'), |
80 | + (self._on_name_owner_changed, None, 'NameOwnerChanged'), |
81 | + (self._on_folder_created, 'Folders', 'FolderCreated'), |
82 | + (self._on_folder_deleted, 'Folders', 'FolderDeleted'), |
83 | + ] |
84 | + self._dbus_matches = [] |
85 | + for method, dbus_lastname, signal_name in _signals: |
86 | + if dbus_lastname is None: |
87 | + dbus_interface = None |
88 | + else: |
89 | + dbus_interface = 'com.ubuntuone.SyncDaemon.' + dbus_lastname |
90 | + match = bus.add_signal_receiver(method, |
91 | + dbus_interface=dbus_interface, |
92 | + signal_name=signal_name) |
93 | + self._dbus_matches.append((match, dbus_interface, signal_name)) |
94 | + |
95 | + |
96 | + def shutdown(self): |
97 | + """Shut down the SyncDaemon.""" |
98 | + logger.info("DBus interface going down") |
99 | + |
100 | + # remove the signals from DBus |
101 | + remove = self._bus.remove_signal_receiver |
102 | + for match, dbus_interface, signal in self._dbus_matches: |
103 | + remove(match, dbus_interface=dbus_interface, signal_name=signal) |
104 | + |
105 | + def _process_status(self, state): |
106 | + """Transform status information.""" |
107 | + name = state['name'] |
108 | + description = state['description'] |
109 | + is_error = bool(state['is_error']) |
110 | + is_connected = bool(state['is_connected']) |
111 | + is_online = bool(state['is_online']) |
112 | + queues = state['queues'] |
113 | + connection = state['connection'] |
114 | + return (name, description, is_error, is_connected, |
115 | + is_online, queues, connection) |
116 | + |
117 | + def get_status(self): |
118 | + """Gets SD status.""" |
119 | + logger.info("Getting status") |
120 | + d = self.sync_daemon_tool.get_status() |
121 | + d.addCallback(self._process_status) |
122 | + return d |
123 | + |
124 | + def _on_status_changed(self, state): |
125 | + """Call the SD callback.""" |
126 | + logger.info("Received Status changed") |
127 | + logger.debug("Status changed data: %r", state) |
128 | + data = self._process_status(state) |
129 | + self.msd.on_sd_status_changed(*data) |
130 | + |
131 | + def _on_content_queue_changed(self, _): |
132 | + """Call the SD callback.""" |
133 | + logger.info("Received Content Queue changed") |
134 | + self.msd.on_sd_content_queue_changed() |
135 | + |
136 | + def _on_name_owner_changed(self, name, oldowner, newowner): |
137 | + """Receive the NameOwnerChanged signal from DBus.""" |
138 | + if name != 'com.ubuntuone.SyncDaemon': |
139 | + return |
140 | + |
141 | + logger.info("Received Name Owner changed") |
142 | + logger.debug("Name Owner data: %r %r", oldowner, newowner) |
143 | + old = bool(oldowner) |
144 | + new = bool(newowner) |
145 | + if old == new: |
146 | + logger.error("Name Owner invalid data: Same bool in old and new!") |
147 | + return |
148 | + self.msd.on_sd_name_owner_changed(new) |
149 | + |
150 | + def _on_folder_created(self, _): |
151 | + """Call the SD callback.""" |
152 | + logger.info("Received Folder created") |
153 | + self.msd.on_sd_folders_changed() |
154 | + |
155 | + def _on_folder_deleted(self, _): |
156 | + """Call the SD callback.""" |
157 | + logger.info("Received Folder deleted") |
158 | + self.msd.on_sd_folders_changed() |
159 | + |
160 | + def get_content_queue(self): |
161 | + """Get the content queue from SDT.""" |
162 | + def process(data): |
163 | + """Enhance data format.""" |
164 | + logger.info("Processing Content Queue items (%d)", len(data)) |
165 | + all_items = [] |
166 | + for d in data: |
167 | + logger.debug(" Content Queue data: %r", d) |
168 | + cq = QueueData(operation=d['operation'], path=d['path'], |
169 | + node=d['node'], share=d['share']) |
170 | + all_items.append(cq) |
171 | + return all_items |
172 | + |
173 | + logger.info("Getting content queue") |
174 | + d = self.sync_daemon_tool.waiting_content() |
175 | + d.addCallback(process) |
176 | + return d |
177 | + |
178 | + def _parse_mq(self, data): |
179 | + """Parse MetaQueue string to extract its data.""" |
180 | + if data in ('AccountInquiry', 'FreeSpaceInquiry', 'GetPublicFiles', |
181 | + 'ListShares', 'ListVolumes', 'Query'): |
182 | + return QueueData(operation=data, path=None, node=None, share=None) |
183 | + |
184 | + m = RE_OP_LISTDIR.match(data) |
185 | + if m: |
186 | + op, share, node = m.groups() |
187 | + path = '?' # we should get the real path, no API now |
188 | + return QueueData(operation=op, path=path, node=node, share=share) |
189 | + |
190 | + m = RE_OP_MAKEFILE.match(data) |
191 | + if m: |
192 | + op, share, parent, name = m.groups() |
193 | + path = '/?.../' + name # we should get the real path, no API now |
194 | + return QueueData(operation=op, path=path, node=None, share=share) |
195 | + |
196 | + m = RE_OP_MAKEDIR.match(data) |
197 | + if m: |
198 | + op, share, parent, name = m.groups() |
199 | + path = '/?.../' + name # we should get the real path, no API now |
200 | + return QueueData(operation=op, path=path, node=None, share=share) |
201 | + |
202 | + m = RE_OP_UNLINK.match(data) |
203 | + if m: |
204 | + op, share, node, = m.groups() |
205 | + path = '?' # we should get the real path, no API now |
206 | + return QueueData(operation=op, path=path, node=node, share=share) |
207 | + |
208 | + m = RE_OP_MOVE.match(data) |
209 | + if m: |
210 | + op, share, node, old_parent, new_parent, new_name, = m.groups() |
211 | + |
212 | + # we should get the real info, no API now |
213 | + old_path = '/?...' |
214 | + old_name = '?' |
215 | + new_path = '/?...' |
216 | + composed_path = "%s/%s -> %s/%s" % (old_path, old_name, |
217 | + new_path, new_name) |
218 | + return QueueData(operation=op, path=composed_path, |
219 | + node=node, share=share) |
220 | + |
221 | + raise ValueError("Not supported MetaQueue data: %r" % data) |
222 | + |
223 | + def get_meta_queue(self): |
224 | + """Get the meta queue from SDT.""" |
225 | + def process(data): |
226 | + """Enhance data format.""" |
227 | + logger.info("Processing Meta Queue items (%d)", len(data)) |
228 | + all_items = [] |
229 | + for d in data: |
230 | + logger.debug(" Meta Queue data: %r", d) |
231 | + parsed = self._parse_mq(d) |
232 | + all_items.append(parsed) |
233 | + return all_items |
234 | + |
235 | + logger.info("Getting meta queue") |
236 | + d = self.sync_daemon_tool.waiting_metadata() |
237 | + d.addCallback(process) |
238 | + return d |
239 | + |
240 | + def get_folders(self): |
241 | + """Get the folders info from SDT.""" |
242 | + def process(data): |
243 | + """Enhance data format.""" |
244 | + logger.info("Processing Folders items (%d)", len(data)) |
245 | + all_items = [] |
246 | + for d in data: |
247 | + logger.debug(" Folders data: %r", d) |
248 | + f = FolderData(node=d['node_id'], path=d['path'], |
249 | + suggested_path=d['suggested_path'], |
250 | + volume=d['volume_id'], |
251 | + subscribed=bool(d['subscribed'])) |
252 | + all_items.append(f) |
253 | + return all_items |
254 | + |
255 | + logger.info("Getting folders") |
256 | + d = self.sync_daemon_tool.get_folders() |
257 | + d.addCallback(process) |
258 | + return d |
259 | + |
260 | + def start(self): |
261 | + """Start SDT.""" |
262 | + logger.info("Calling start") |
263 | + self.sync_daemon_tool.start() |
264 | + |
265 | + def quit(self): |
266 | + """Stop SDT.""" |
267 | + logger.info("Calling quit") |
268 | + self.sync_daemon_tool.quit() |
269 | + |
270 | + def connect(self): |
271 | + """Connect SDT.""" |
272 | + logger.info("Calling connect") |
273 | + self.sync_daemon_tool.connect() |
274 | + |
275 | + def disconnect(self): |
276 | + """Disconnect SDT.""" |
277 | + logger.info("Calling disconnect") |
278 | + self.sync_daemon_tool.disconnect() |
279 | + |
280 | + def is_sd_started(self): |
281 | + """Find out if SD is active in the system.""" |
282 | + try: |
283 | + self._bus.get_name_owner('com.ubuntuone.SyncDaemon') |
284 | + except dbus.exceptions.DBusException, err: |
285 | + if err.get_dbus_name() != \ |
286 | + 'org.freedesktop.DBus.Error.NameHasNoOwner': |
287 | + raise |
288 | + started = False |
289 | + else: |
290 | + started = True |
291 | + logger.info("Checking if SD is started: %s", started) |
292 | + return started |
293 | |
294 | === modified file 'magicicada/syncdaemon.py' |
295 | --- magicicada/syncdaemon.py 2010-05-23 10:23:35 +0000 |
296 | +++ magicicada/syncdaemon.py 2010-05-27 20:56:26 +0000 |
297 | @@ -18,17 +18,12 @@ |
298 | |
299 | """The backend that communicates Magicicada with the SyncDaemon.""" |
300 | |
301 | -import collections |
302 | import logging |
303 | -import re |
304 | import sys |
305 | |
306 | -import dbus |
307 | -from dbus.mainloop.glib import DBusGMainLoop |
308 | -from twisted.internet import reactor |
309 | - |
310 | -from ubuntuone.syncdaemon import tools |
311 | - |
312 | +from twisted.internet import defer, reactor |
313 | + |
314 | +from magicicada.dbusiface import DBusInterface |
315 | from magicicada.helpers import NO_OP |
316 | |
317 | # log! |
318 | @@ -41,19 +36,6 @@ |
319 | handler.setFormatter(formatter) |
320 | logger.setLevel(logging.DEBUG) |
321 | |
322 | -# regular expressions for parsing MetaQueue data |
323 | -RE_OP_LISTDIR = re.compile("(ListDir)\(share_id=(.*?), node_id=(.*?), .*") |
324 | -RE_OP_UNLINK = re.compile("(Unlink)\(share_id=(.*?), node_id=(.*?), .*") |
325 | -RE_OP_MAKEFILE = re.compile( |
326 | - "(MakeFile)\(share_id=(.*?), parent_id=(.*?), name=(.*?), .*") |
327 | -RE_OP_MAKEDIR = re.compile( |
328 | - "(MakeDir)\(share_id=(.*?), parent_id=(.*?), name=(.*?), .*") |
329 | -RE_OP_MOVE = re.compile( |
330 | - "(Move)\(share_id=(.*?), node_id=(.*?), old_parent_id=(.*?), " |
331 | - "new_parent_id=(.*?), new_name=(.*?)\)") |
332 | - |
333 | -# structure that hold content and queue information |
334 | -QueueData = collections.namedtuple('QueueData', 'operation path share node') |
335 | |
336 | class State(object): |
337 | """Holds the state of SD.""" |
338 | @@ -96,29 +78,17 @@ |
339 | class SyncDaemon(object): |
340 | """Interface to Ubuntu One's SyncDaemon.""" |
341 | |
342 | - def __init__(self): |
343 | + def __init__(self, dbus_class=DBusInterface): |
344 | + logger.info("SyncDaemon interface started!") |
345 | + |
346 | # set up dbus and related stuff |
347 | - loop = DBusGMainLoop(set_as_default=True) |
348 | - self._bus = bus = dbus.SessionBus(mainloop=loop) |
349 | - self.sync_daemon_tool = tools.SyncDaemonTool(bus) |
350 | + self.dbus = dbus_class(self) |
351 | + |
352 | + # attributes for GUI, definition and filling |
353 | self.current_state = State() |
354 | - |
355 | - # hook up for signals and store info for the shutdown |
356 | - _signals = [ |
357 | - (self._on_status_changed, 'Status', 'StatusChanged'), |
358 | - (self._on_content_queue_changed, 'Status', 'ContentQueueChanged'), |
359 | - (self._on_name_owner_changed, None, 'NameOwnerChanged'), |
360 | - ] |
361 | - self._dbus_matches = [] |
362 | - for method, dbus_lastname, signal_name in _signals: |
363 | - if dbus_lastname is None: |
364 | - dbus_interface = None |
365 | - else: |
366 | - dbus_interface = 'com.ubuntuone.SyncDaemon.' + dbus_lastname |
367 | - match = bus.add_signal_receiver(method, |
368 | - dbus_interface=dbus_interface, |
369 | - signal_name=signal_name) |
370 | - self._dbus_matches.append((match, dbus_interface, signal_name)) |
371 | + self.folders = None |
372 | + self.content_queue = None |
373 | + self.meta_queue = None |
374 | |
375 | # callbacks for GUI to hook in |
376 | self.status_changed_callback = NO_OP |
377 | @@ -131,70 +101,69 @@ |
378 | self.on_online_callback = NO_OP |
379 | self.on_offline_callback = NO_OP |
380 | |
381 | - # calls to obtain data from SDT |
382 | - self._get_content_queue = self.sync_daemon_tool.waiting_content |
383 | - self._get_meta_queue = self.sync_daemon_tool.waiting_metadata |
384 | - self._do_start = self.sync_daemon_tool.start |
385 | - self._do_quit = self.sync_daemon_tool.quit |
386 | - self._do_connect = self.sync_daemon_tool.connect |
387 | - self._do_disconnect = self.sync_daemon_tool.disconnect |
388 | - |
389 | - # previous data |
390 | - self._last_CQ_data = None |
391 | - self._last_MQ_data = None |
392 | - |
393 | # mq needs to be polled to know progress |
394 | self._mqcaller = None |
395 | self._mq_poll_time = 5 # seconds |
396 | |
397 | - # let's log! |
398 | - logger.info("SyncDaemon interface started!") |
399 | + # load initial data if ubuntuone-client already started |
400 | + if self.dbus.is_sd_started(): |
401 | + self._get_initial_data() |
402 | |
403 | |
404 | def shutdown(self): |
405 | """Shut down the SyncDaemon.""" |
406 | logger.info("SyncDaemon interface going down") |
407 | - |
408 | - # remove the signals from DBus |
409 | - remove = self._bus.remove_signal_receiver |
410 | - for match, dbus_interface, signal in self._dbus_matches: |
411 | - remove(match, dbus_interface=dbus_interface, signal_name=signal) |
412 | + self.dbus.shutdown() |
413 | |
414 | # cancel the mq polling caller, if any |
415 | if self._mqcaller is not None and self._mqcaller.active(): |
416 | self._mqcaller.cancel() |
417 | |
418 | - def _on_name_owner_changed(self, name, oldowner, newowner): |
419 | - """Receives the NameOwnerChanged signal from DBus.""" |
420 | - if name == 'com.ubuntuone.SyncDaemon': |
421 | - logger.info("DBus informing about SD: old: %r new: %r", |
422 | - oldowner, newowner) |
423 | - |
424 | - old = bool(oldowner) |
425 | - new = bool(newowner) |
426 | - if old == new: |
427 | - raise ValueError("Owners should have changed! Old: %r " |
428 | - "New: %r" % (oldowner, newowner)) |
429 | - self.current_state._set(is_started=new) |
430 | - if new: |
431 | - self.on_started_callback() |
432 | - else: |
433 | - self.on_stopped_callback() |
434 | - |
435 | - def _on_status_changed(self, state): |
436 | - """Receives the StatusChanged signal and send its data.""" |
437 | - logger.info("New status info from SD") |
438 | - logger.debug("New status from SD: %r", state) |
439 | - |
440 | - name = state['name'] |
441 | - description = state['description'] |
442 | - is_error = bool(state['is_error']) |
443 | - is_connected = bool(state['is_connected']) |
444 | - is_online = bool(state['is_online']) |
445 | - queues = state['queues'] |
446 | - connection = state['connection'] |
447 | - |
448 | - # check status changes to call callbacks |
449 | + @defer.inlineCallbacks |
450 | + def _get_initial_data(self): |
451 | + """Gets the initial SD data.""" |
452 | + logger.info("Getting initial data") |
453 | + |
454 | + status_data = yield self.dbus.get_status() |
455 | + self._send_status_changed(*status_data) |
456 | + |
457 | + self.content_queue = yield self.dbus.get_content_queue() |
458 | + self.content_queue_changed_callback(self.content_queue) |
459 | + |
460 | + self.meta_queue = yield self.dbus.get_meta_queue() |
461 | + self.meta_queue_changed_callback(self.meta_queue) |
462 | + |
463 | + self.folders = yield self.dbus.get_folders() |
464 | + |
465 | + @defer.inlineCallbacks |
466 | + def on_sd_folders_changed(self): |
467 | + """Folders changed, ask for new information.""" |
468 | + logger.info("SD Folders changed") |
469 | + self.folders = yield self.dbus.get_folders() |
470 | + |
471 | + def on_sd_name_owner_changed(self, now_active): |
472 | + """SyncDaemon name owner changed.""" |
473 | + logger.info("SD Name Owner changed: %s", now_active) |
474 | + self.current_state._set(is_started=now_active) |
475 | + if now_active: |
476 | + self.on_started_callback() |
477 | + self._get_initial_data() |
478 | + else: |
479 | + self.on_stopped_callback() |
480 | + |
481 | + def on_sd_status_changed(self, *status_data): |
482 | + """The Status of SD changed..""" |
483 | + logger.info("SD Status changed") |
484 | + self._send_status_changed(*status_data) |
485 | + |
486 | + def _send_status_changed(self, name, description, is_error, is_connected, |
487 | + is_online, queues, connection): |
488 | + logger.debug(" new status: name=%r, description=%r, is_error=%s, " |
489 | + "is_connected=%s, is_online=%s, queues=%r, connection=%r", |
490 | + name, description, is_error, is_connected, is_online, |
491 | + queues, connection) |
492 | + |
493 | + # check status changes to call other callbacks |
494 | if is_connected and not self.current_state.is_connected: |
495 | self.on_connected_callback() |
496 | if not is_connected and self.current_state.is_connected: |
497 | @@ -204,168 +173,70 @@ |
498 | if not is_online and self.current_state.is_online: |
499 | self.on_offline_callback() |
500 | |
501 | - |
502 | # set current state to new values and call status changed cb |
503 | - self.current_state._set(**state) |
504 | - self.status_changed_callback(name, description, is_error, |
505 | - is_connected, is_online, |
506 | - queues, connection) |
507 | + self.current_state._set(name=name, description=description, |
508 | + is_error=is_error, is_connected=is_connected, |
509 | + is_online=is_online, queues=queues, |
510 | + connection=connection) |
511 | + self.status_changed_callback(name, description, is_error, is_connected, |
512 | + is_online, queues, connection) |
513 | |
514 | # if corresponds, supervise MQ |
515 | self._check_mq() |
516 | |
517 | - def _generate_cq_info(self, data): |
518 | - """Genereates an api friendly version of the data.""" |
519 | - all_items = [] |
520 | - for d in data: |
521 | - logger.debug("Processing CQ data: %r", d) |
522 | - cq = QueueData(operation=d['operation'], path=d['path'], |
523 | - node=d['node'], share=d['share']) |
524 | - all_items.append(cq) |
525 | - return all_items |
526 | - |
527 | - @property |
528 | - def content_queue(self): |
529 | - """Returns the last known CQ info.""" |
530 | - if self._last_CQ_data is None: |
531 | - return [] |
532 | - else: |
533 | - return self._generate_cq_info(self._last_CQ_data) |
534 | - |
535 | - def _process_cq(self, data): |
536 | - """Processes ContentQueue data.""" |
537 | - # if same data than before, abort notification; else store it for later |
538 | - logger.info("Processing CQ data") |
539 | - if data == self._last_CQ_data: |
540 | - return |
541 | - self._last_CQ_data = data |
542 | - logger.info("New CQ data to process") |
543 | - |
544 | - all_items = self._generate_cq_info(data) |
545 | - self.content_queue_changed_callback(all_items) |
546 | - |
547 | - def _on_content_queue_changed(self, _): |
548 | - """Receives the ContentQueueChanged signal and finds real data.""" |
549 | - logger.info("CQ changed in u1.SD!") |
550 | - |
551 | - # get the info |
552 | - d = self._get_content_queue() |
553 | - d.addCallback(self._process_cq) |
554 | - |
555 | - @property |
556 | - def meta_queue(self): |
557 | - """Returns the last known MQ info.""" |
558 | - if self._last_MQ_data is None: |
559 | - return [] |
560 | - else: |
561 | - all_items = [] |
562 | - for d in self._last_MQ_data: |
563 | - all_items.append(self._parse_mq(d)) |
564 | - return all_items |
565 | - |
566 | - def _parse_mq(self, data): |
567 | - """Parse MetaQueue string to extract its data.""" |
568 | - if data in ('AccountInquiry', 'FreeSpaceInquiry', 'GetPublicFiles', |
569 | - 'ListShares', 'ListVolumes', 'Query'): |
570 | - return QueueData(operation=data, path=None, node=None, share=None) |
571 | - |
572 | - m = RE_OP_LISTDIR.match(data) |
573 | - if m: |
574 | - op, share, node = m.groups() |
575 | - path = '?' # we should get the real path, no API now |
576 | - return QueueData(operation=op, path=path, node=node, share=share) |
577 | - |
578 | - m = RE_OP_MAKEFILE.match(data) |
579 | - if m: |
580 | - op, share, parent, name = m.groups() |
581 | - path = '/?.../' + name # we should get the real path, no API now |
582 | - return QueueData(operation=op, path=path, node=None, share=share) |
583 | - |
584 | - m = RE_OP_MAKEDIR.match(data) |
585 | - if m: |
586 | - op, share, parent, name = m.groups() |
587 | - path = '/?.../' + name # we should get the real path, no API now |
588 | - return QueueData(operation=op, path=path, node=None, share=share) |
589 | - |
590 | - m = RE_OP_UNLINK.match(data) |
591 | - if m: |
592 | - op, share, node, = m.groups() |
593 | - path = '?' # we should get the real path, no API now |
594 | - return QueueData(operation=op, path=path, node=node, share=share) |
595 | - |
596 | - m = RE_OP_MOVE.match(data) |
597 | - if m: |
598 | - op, share, node, old_parent, new_parent, new_name, = m.groups() |
599 | - |
600 | - # we should get the real info, no API now |
601 | - old_path = '/?...' |
602 | - old_name = '?' |
603 | - new_path = '/?...' |
604 | - composed_path = "%s/%s -> %s/%s" % (old_path, old_name, |
605 | - new_path, new_name) |
606 | - return QueueData(operation=op, path=composed_path, |
607 | - node=node, share=share) |
608 | - |
609 | - raise ValueError("Not supported MetaQueue data: %r" % data) |
610 | - |
611 | - def _process_mq(self, data): |
612 | - """Processes MetaQueue data.""" |
613 | - # if same data than before, abort notification; else store it for later |
614 | - logger.info("Processing MQ data") |
615 | - if data == self._last_MQ_data: |
616 | - return |
617 | - self._last_MQ_data = data |
618 | - logger.info("New MQ data to process") |
619 | - |
620 | - all_items = [] |
621 | - for d in data: |
622 | - logger.debug("Processing MQ data: %r", d) |
623 | - parsed = self._parse_mq(d) |
624 | - logger.debug(" parsed: %s", parsed) |
625 | - all_items.append(parsed) |
626 | - |
627 | - self.meta_queue_changed_callback(all_items) |
628 | - |
629 | - def _on_meta_queue_changed(self): |
630 | - """Finds real data about meta queue.""" |
631 | - d = self._get_meta_queue() |
632 | - d.addCallback(self._process_mq) |
633 | - |
634 | + @defer.inlineCallbacks |
635 | + def on_sd_content_queue_changed(self): |
636 | + """Content Queue changed, ask for new information.""" |
637 | + logger.info("SD Content Queue changed") |
638 | + new_cq = yield self.dbus.get_content_queue() |
639 | + if new_cq != self.content_queue: |
640 | + logger.info("Content Queue info is new! %d items", len(new_cq)) |
641 | + self.content_queue = new_cq |
642 | + self.content_queue_changed_callback(new_cq) |
643 | + |
644 | + @defer.inlineCallbacks |
645 | def _check_mq(self): |
646 | """Check MQ if we should.""" |
647 | - # check if we have something to show in MQ! |
648 | - if self.current_state.name != 'QUEUE_MANAGER' or \ |
649 | - self.current_state.queues not in ( |
650 | - 'WORKING_ON_METADATA', 'WORKING_ON_BOTH'): |
651 | + state = self.current_state |
652 | + if state.name != 'QUEUE_MANAGER' or \ |
653 | + state.queues not in ('WORKING_ON_METADATA', 'WORKING_ON_BOTH'): |
654 | logger.info("Check MQ called but States not in MQ") |
655 | - return |
656 | - |
657 | - # we have a previous call later running? |
658 | - if self._mqcaller is not None and self._mqcaller.active(): |
659 | - self._mqcaller.cancel() |
660 | - |
661 | - # get the info a programa |
662 | - logger.info("Asking for MQ information") |
663 | - d = self._get_meta_queue() |
664 | - d.addCallback(self._process_mq) |
665 | - self._mqcaller = reactor.callLater(self._mq_poll_time, self._check_mq) |
666 | + else: |
667 | + logger.info("Asking for MQ information") |
668 | + |
669 | + # have we a previous call later still running? |
670 | + if self._mqcaller is not None and self._mqcaller.active(): |
671 | + self._mqcaller.cancel() |
672 | + |
673 | + # get the info |
674 | + new_mq = yield self.dbus.get_meta_queue() |
675 | + |
676 | + if new_mq != self.meta_queue: |
677 | + logger.info("SD Meta Queue changed: %d items", len(new_mq)) |
678 | + self.meta_queue = new_mq |
679 | + self.meta_queue_changed_callback(new_mq) |
680 | + |
681 | + # check again later |
682 | + self._mqcaller = reactor.callLater(self._mq_poll_time, |
683 | + self._check_mq) |
684 | |
685 | def start(self): |
686 | """Starts the SyncDaemon.""" |
687 | logger.info("Starting u1.SD") |
688 | - self._do_start() |
689 | + self.dbus.start() |
690 | + self._get_initial_data() |
691 | |
692 | def quit(self): |
693 | """Stops the SyncDaemon and makes it quit.""" |
694 | logger.info("Stopping u1.SD") |
695 | - self._do_quit() |
696 | + self.dbus.quit() |
697 | |
698 | def connect(self): |
699 | """Tells the SyncDaemon that the user wants it to connect.""" |
700 | logger.info("Telling u1.SD to connect") |
701 | - self._do_connect() |
702 | + self.dbus.connect() |
703 | |
704 | def disconnect(self): |
705 | """Tells the SyncDaemon that the user wants it to disconnect.""" |
706 | logger.info("Telling u1.SD to disconnect") |
707 | - self._do_disconnect() |
708 | + self.dbus.disconnect() |
709 | |
710 | === added file 'magicicada/tests/helpers.py' |
711 | --- magicicada/tests/helpers.py 1970-01-01 00:00:00 +0000 |
712 | +++ magicicada/tests/helpers.py 2010-05-27 20:56:26 +0000 |
713 | @@ -0,0 +1,49 @@ |
714 | +# Helpers for the tessts |
715 | +# |
716 | +# Author: Facundo Batista <facundo@taniquetil.com.ar> |
717 | +# |
718 | +# Copyright 2010 Chicharreros |
719 | +# |
720 | +# This program is free software: you can redistribute it and/or modify it |
721 | +# under the terms of the GNU General Public License version 3, as published |
722 | +# by the Free Software Foundation. |
723 | +# |
724 | +# This program is distributed in the hope that it will be useful, but |
725 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
726 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
727 | +# PURPOSE. See the GNU General Public License for more details. |
728 | +# |
729 | +# You should have received a copy of the GNU General Public License along |
730 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
731 | + |
732 | +"""Helpers for the tests.""" |
733 | + |
734 | +import logging |
735 | + |
736 | + |
737 | +class MementoHandler(logging.Handler): |
738 | + """A handler class which store logging records in a list.""" |
739 | + |
740 | + def __init__(self, *args, **kwargs): |
741 | + """Create the instance, and add a records attribute.""" |
742 | + logging.Handler.__init__(self, *args, **kwargs) |
743 | + self.records = [] |
744 | + |
745 | + def emit(self, record): |
746 | + """Just add the record to self.records.""" |
747 | + self.records.append(record) |
748 | + |
749 | + def check(self, level, msg): |
750 | + """Check that something is logged.""" |
751 | + for rec in self.records: |
752 | + if rec.levelname == level and rec.message == msg: |
753 | + return True |
754 | + return False |
755 | + |
756 | + def check_inf(self, msg): |
757 | + """Shortcut for INFO check.""" |
758 | + return self.check('INFO', msg) |
759 | + |
760 | + def check_dbg(self, msg): |
761 | + """Shortcut for DEBUG check.""" |
762 | + return self.check('DEBUG', msg) |
763 | |
764 | === added file 'magicicada/tests/test_dbusiface.py' |
765 | --- magicicada/tests/test_dbusiface.py 1970-01-01 00:00:00 +0000 |
766 | +++ magicicada/tests/test_dbusiface.py 2010-05-27 20:56:26 +0000 |
767 | @@ -0,0 +1,665 @@ |
768 | +# Tests for the DBus interface |
769 | +# |
770 | +# Author: Facundo Batista <facundo@taniquetil.com.ar> |
771 | +# |
772 | +# Copyright 2010 Chicharreros |
773 | +# |
774 | +# This program is free software: you can redistribute it and/or modify it |
775 | +# under the terms of the GNU General Public License version 3, as published |
776 | +# by the Free Software Foundation. |
777 | +# |
778 | +# This program is distributed in the hope that it will be useful, but |
779 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
780 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
781 | +# PURPOSE. See the GNU General Public License for more details. |
782 | +# |
783 | +# You should have received a copy of the GNU General Public License along |
784 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
785 | + |
786 | +"""Tests for the DBus interce towards real syncdaemon.""" |
787 | + |
788 | +import logging |
789 | + |
790 | +import dbus |
791 | +from twisted.trial.unittest import TestCase as TwistedTestCase |
792 | +from twisted.internet import defer |
793 | + |
794 | +from magicicada import dbusiface |
795 | +from magicicada.tests.helpers import MementoHandler |
796 | + |
797 | + |
798 | +class FakeSessionBus(object): |
799 | + """Fake Session Bus.""" |
800 | + def __init__(self, **kwargs): |
801 | + self._callbacks = {} |
802 | + self.fake_name_owner = "foo" |
803 | + |
804 | + def add_signal_receiver(self, method, dbus_interface, signal_name): |
805 | + """Add a signal receiver.""" |
806 | + self._callbacks[(dbus_interface, signal_name)] = method |
807 | + |
808 | + def remove_signal_receiver(self, match, dbus_interface, signal_name): |
809 | + """Remove the signal receiver.""" |
810 | + del self._callbacks[(dbus_interface, signal_name)] |
811 | + |
812 | + def get_name_owner(self, name): |
813 | + """Fakes the response of the method.""" |
814 | + assert name == 'com.ubuntuone.SyncDaemon' |
815 | + if isinstance(self.fake_name_owner, str): |
816 | + return self.fake_name_owner |
817 | + else: |
818 | + raise self.fake_name_owner |
819 | + |
820 | + |
821 | +class CallLoguer(object): |
822 | + """Class that logs the methods called.""" |
823 | + def __init__(self): |
824 | + self._called_method = None, () |
825 | + self._fake_response = None |
826 | + |
827 | + def __getattribute__(self, name): |
828 | + """Return the value if there.""" |
829 | + if name[0] == "_": |
830 | + return object.__getattribute__(self, name) |
831 | + else: |
832 | + def f(*args): |
833 | + setattr(self, "_called_method", (name, args)) |
834 | + if self._fake_response is None: |
835 | + # no hurt in returning a deferred, it may be needed |
836 | + return defer.Deferred() |
837 | + methname, response = self._fake_response |
838 | + assert methname == name |
839 | + return response |
840 | + return f |
841 | + |
842 | + |
843 | +class FakeSDTool(CallLoguer): |
844 | + """Fake real SyncDaemonTool.""" |
845 | + def __init__(self, _): |
846 | + CallLoguer.__init__(self) |
847 | + |
848 | + |
849 | +class FakeSyncDaemon(CallLoguer): |
850 | + """Fake Magicicada's SyncDaemon.""" |
851 | + |
852 | + |
853 | +class SafeTests(TwistedTestCase): |
854 | + """Safe tests not going outside the testing box.""" |
855 | + |
856 | + def setUp(self): |
857 | + """Set up.""" |
858 | + dbusiface.SessionBus = FakeSessionBus |
859 | + dbusiface.SyncDaemonTool = FakeSDTool |
860 | + self.fsd = FakeSyncDaemon() |
861 | + self.dbus = dbusiface.DBusInterface(self.fsd) |
862 | + |
863 | + def check_sdt_called(self, name): |
864 | + """Check that the SyncDaemonTool method was called.""" |
865 | + self.assertEqual(self.dbus.sync_daemon_tool._called_method[0], name) |
866 | + |
867 | + def get_msd_called(self, name): |
868 | + """Get the args from the called Magicicada's SyncDaemon method.""" |
869 | + called_method, called_args = self.fsd._called_method |
870 | + self.assertEqual(called_method, name) |
871 | + return called_args |
872 | + |
873 | + def fake_sdt_response(self, method_name, response): |
874 | + """Fakes SDT answer in deferred mode.""" |
875 | + self.dbus.sync_daemon_tool._fake_response = (method_name, |
876 | + defer.succeed(response)) |
877 | + |
878 | +class TestSignalHooking(SafeTests): |
879 | + """Signal hooking tests. |
880 | + |
881 | + We can not check if the methods are really called, because DBus holds the |
882 | + method object itself, so no chance in monkeypatching. |
883 | + """ |
884 | + def _get_hooked(self, iface, signal): |
885 | + """Return the hooked method if any.""" |
886 | + if iface is None: |
887 | + interface = None |
888 | + else: |
889 | + interface = 'com.ubuntuone.SyncDaemon.' + iface |
890 | + return self.dbus._bus._callbacks.get((interface, signal)) |
891 | + |
892 | + def test_hook_unhook(self): |
893 | + """Test the hooked signals are unhooked.""" |
894 | + self.dbus.shutdown() |
895 | + self.assertEqual(self.dbus._bus._callbacks, {}) |
896 | + |
897 | + def test_status_changed(self): |
898 | + """Test status changed callback.""" |
899 | + self.assertEqual(self._get_hooked('Status', 'StatusChanged'), |
900 | + self.dbus._on_status_changed) |
901 | + |
902 | + def test_content_queue_changed(self): |
903 | + """Test content queue changed callback.""" |
904 | + self.assertEqual(self._get_hooked('Status', 'ContentQueueChanged'), |
905 | + self.dbus._on_content_queue_changed) |
906 | + |
907 | + def test_name_owner_changed(self): |
908 | + """Test name owner changed callback.""" |
909 | + self.assertEqual(self._get_hooked(None, 'NameOwnerChanged'), |
910 | + self.dbus._on_name_owner_changed) |
911 | + |
912 | + def test_folder_created_changed(self): |
913 | + """Test folder created changed callback.""" |
914 | + self.assertEqual(self._get_hooked('Folders', 'FolderCreated'), |
915 | + self.dbus._on_folder_created) |
916 | + |
917 | + def test_folder_deleted_changed(self): |
918 | + """Test folder deleted changed callback.""" |
919 | + self.assertEqual(self._get_hooked('Folders', 'FolderDeleted'), |
920 | + self.dbus._on_folder_deleted) |
921 | + |
922 | + |
923 | +class TestSimpleCalls(SafeTests): |
924 | + """Tests for some simple calls.""" |
925 | + |
926 | + @defer.inlineCallbacks |
927 | + def test_is_sd_started_yes(self): |
928 | + """Test is SD started, yes.""" |
929 | + self.dbus._bus.fake_name_owner = 'some owner' |
930 | + resp = yield self.dbus.is_sd_started() |
931 | + self.assertTrue(resp) |
932 | + |
933 | + @defer.inlineCallbacks |
934 | + def test_is_sd_started_no(self): |
935 | + """Test is SD started, no.""" |
936 | + self.dbus._bus.fake_name_owner = dbus.exceptions.DBusException( |
937 | + name='org.freedesktop.DBus.Error.NameHasNoOwner') |
938 | + resp = yield self.dbus.is_sd_started() |
939 | + self.assertFalse(resp) |
940 | + |
941 | + |
942 | +class TestDataProcessingStatus(SafeTests): |
943 | + """Processes Status before sending it to SyncDaemon.""" |
944 | + |
945 | + @defer.inlineCallbacks |
946 | + def test_get_status(self): |
947 | + """Test getting status.""" |
948 | + d = dict(name='n', description='d', is_error='', is_connected='True', |
949 | + is_online='', queues='q', connection='c') |
950 | + self.fake_sdt_response('get_status', d) |
951 | + args = yield self.dbus.get_status() |
952 | + name, descrip, error, connected, online, queues, connection = args |
953 | + self.assertEqual(name, 'n') |
954 | + self.assertEqual(descrip, 'd') |
955 | + self.assertEqual(error, False) |
956 | + self.assertEqual(connected, True) |
957 | + self.assertEqual(online, False) |
958 | + self.assertEqual(queues, 'q') |
959 | + self.assertEqual(connection, 'c') |
960 | + |
961 | + def test_status_changed(self): |
962 | + """Test status changed callback.""" |
963 | + d = dict(name='name', description='description', is_error='', |
964 | + is_connected='True', is_online='', queues='queues', |
965 | + connection='connection') |
966 | + self.dbus._on_status_changed(d) |
967 | + args = self.get_msd_called("on_sd_status_changed") |
968 | + name, descrip, error, connected, online, queues, connection = args |
969 | + self.assertEqual(name, 'name') |
970 | + self.assertEqual(descrip, 'description') |
971 | + self.assertEqual(error, False) |
972 | + self.assertEqual(connected, True) |
973 | + self.assertEqual(online, False) |
974 | + self.assertEqual(queues, 'queues') |
975 | + self.assertEqual(connection, 'connection') |
976 | + |
977 | + |
978 | +class TestDataProcessingNameOwner(SafeTests): |
979 | + """Processes Name Owner data before sending it to SyncDaemon.""" |
980 | + |
981 | + def test_name_owner_changed_no_syncdaemon(self): |
982 | + """Test name owner changed callback.""" |
983 | + self.dbus._on_name_owner_changed("foo", "bar", "baz") |
984 | + self.get_msd_called(None) |
985 | + |
986 | + def test_name_owner_changed_yes_syncdaemon_TF(self): |
987 | + """Test name owner changed callback.""" |
988 | + self.dbus._on_name_owner_changed("com.ubuntuone.SyncDaemon", "T", "") |
989 | + rcv, = self.get_msd_called("on_sd_name_owner_changed") |
990 | + self.assertEqual(rcv, False) |
991 | + |
992 | + def test_name_owner_changed_yes_syncdaemon_FT(self): |
993 | + """Test name owner changed callback.""" |
994 | + self.dbus._on_name_owner_changed("com.ubuntuone.SyncDaemon", "", "T") |
995 | + rcv, = self.get_msd_called("on_sd_name_owner_changed") |
996 | + self.assertEqual(rcv, True) |
997 | + |
998 | + |
999 | +class TestDataProcessingCQ(SafeTests): |
1000 | + """Processes CQ data before sending it to SyncDaemon.""" |
1001 | + |
1002 | + @defer.inlineCallbacks |
1003 | + def test_nodata(self): |
1004 | + """Test with no data in the queue.""" |
1005 | + self.fake_sdt_response('waiting_content', []) |
1006 | + rcv = yield self.dbus.get_content_queue() |
1007 | + self.assertEqual(len(rcv), 0) |
1008 | + |
1009 | + @defer.inlineCallbacks |
1010 | + def test_one_item(self): |
1011 | + """Test with one item in the queue.""" |
1012 | + c = dict(operation='oper', path='path', share='share', node='node') |
1013 | + self.fake_sdt_response('waiting_content', [c]) |
1014 | + rcv = yield self.dbus.get_content_queue() |
1015 | + self.assertEqual(len(rcv), 1) |
1016 | + data = rcv[0] |
1017 | + self.assertEqual(data.operation, 'oper') |
1018 | + self.assertEqual(data.path, 'path') |
1019 | + self.assertEqual(data.share, 'share') |
1020 | + self.assertEqual(data.node, 'node') |
1021 | + |
1022 | + @defer.inlineCallbacks |
1023 | + def test_two_items(self): |
1024 | + """Test with two items in the queue.""" |
1025 | + c = dict(operation='oper1', path='path1', share='share1', node='node1') |
1026 | + d = dict(operation='oper2', path='path2', share='share2', node='node2') |
1027 | + self.fake_sdt_response('waiting_content', [c, d]) |
1028 | + rcv = yield self.dbus.get_content_queue() |
1029 | + self.assertEqual(len(rcv), 2) |
1030 | + data = rcv[0] |
1031 | + self.assertEqual(data.operation, 'oper1') |
1032 | + self.assertEqual(data.path, 'path1') |
1033 | + self.assertEqual(data.share, 'share1') |
1034 | + self.assertEqual(data.node, 'node1') |
1035 | + data = rcv[1] |
1036 | + self.assertEqual(data.operation, 'oper2') |
1037 | + self.assertEqual(data.path, 'path2') |
1038 | + self.assertEqual(data.share, 'share2') |
1039 | + self.assertEqual(data.node, 'node2') |
1040 | + |
1041 | + |
1042 | +class TestDataProcessingMQ(SafeTests): |
1043 | + """Processes MQ data before sending it to SyncDaemon.""" |
1044 | + |
1045 | + @defer.inlineCallbacks |
1046 | + def test_nodata(self): |
1047 | + """Test with no data in the queue.""" |
1048 | + self.fake_sdt_response('waiting_metadata', []) |
1049 | + rcv = yield self.dbus.get_meta_queue() |
1050 | + self.assertEqual(len(rcv), 0) |
1051 | + |
1052 | + @defer.inlineCallbacks |
1053 | + def test_one_item(self): |
1054 | + """Test with one item in the queue.""" |
1055 | + self.fake_sdt_response('waiting_metadata', ['ListShares']) |
1056 | + rcv = yield self.dbus.get_meta_queue() |
1057 | + self.assertEqual(len(rcv), 1) |
1058 | + data = rcv[0] |
1059 | + self.assertEqual(data.operation, 'ListShares') |
1060 | + self.assertEqual(data.path, None) |
1061 | + self.assertEqual(data.share, None) |
1062 | + self.assertEqual(data.node, None) |
1063 | + |
1064 | + @defer.inlineCallbacks |
1065 | + def test_two_items(self): |
1066 | + """Test ContentQueueChanged signal with two items in the queue.""" |
1067 | + cmd1 = 'MakeDir(share_id=a, parent_id=b, name=c, marker=d)' |
1068 | + cmd2 = 'GetPublicFiles' |
1069 | + self.fake_sdt_response('waiting_metadata', [cmd1, cmd2]) |
1070 | + rcv = yield self.dbus.get_meta_queue() |
1071 | + self.assertEqual(len(rcv), 2) |
1072 | + data = rcv[0] |
1073 | + self.assertEqual(data.operation, 'MakeDir') |
1074 | + self.assertEqual(data.path, '/?.../c') |
1075 | + self.assertEqual(data.share, 'a') |
1076 | + self.assertEqual(data.node, None) |
1077 | + data = rcv[1] |
1078 | + self.assertEqual(data.operation, 'GetPublicFiles') |
1079 | + self.assertEqual(data.path, None) |
1080 | + self.assertEqual(data.share, None) |
1081 | + self.assertEqual(data.node, None) |
1082 | + |
1083 | + @defer.inlineCallbacks |
1084 | + def test_GetPublicFiles(self): |
1085 | + """Test meta with GetPublicFiles.""" |
1086 | + cmd = 'GetPublicFiles' |
1087 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1088 | + rcv = yield self.dbus.get_meta_queue() |
1089 | + data = rcv[0] |
1090 | + self.assertEqual(data.operation, 'GetPublicFiles') |
1091 | + self.assertEqual(data.path, None) |
1092 | + self.assertEqual(data.share, None) |
1093 | + self.assertEqual(data.node, None) |
1094 | + |
1095 | + @defer.inlineCallbacks |
1096 | + def test_AccountInquiry(self): |
1097 | + """Test meta with AccountInquiry.""" |
1098 | + cmd = 'AccountInquiry' |
1099 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1100 | + rcv = yield self.dbus.get_meta_queue() |
1101 | + data = rcv[0] |
1102 | + self.assertEqual(data.operation, 'AccountInquiry') |
1103 | + self.assertEqual(data.path, None) |
1104 | + self.assertEqual(data.share, None) |
1105 | + self.assertEqual(data.node, None) |
1106 | + |
1107 | + @defer.inlineCallbacks |
1108 | + def test_FreeSpaceInquiry(self): |
1109 | + """Test meta with FreeSpaceInquiry.""" |
1110 | + cmd = 'FreeSpaceInquiry' |
1111 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1112 | + rcv = yield self.dbus.get_meta_queue() |
1113 | + data = rcv[0] |
1114 | + self.assertEqual(data.operation, 'FreeSpaceInquiry') |
1115 | + self.assertEqual(data.path, None) |
1116 | + self.assertEqual(data.share, None) |
1117 | + self.assertEqual(data.node, None) |
1118 | + |
1119 | + @defer.inlineCallbacks |
1120 | + def test_ListShares(self): |
1121 | + """Test meta with ListShares.""" |
1122 | + cmd = 'ListShares' |
1123 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1124 | + rcv = yield self.dbus.get_meta_queue() |
1125 | + data = rcv[0] |
1126 | + self.assertEqual(data.operation, 'ListShares') |
1127 | + self.assertEqual(data.path, None) |
1128 | + self.assertEqual(data.share, None) |
1129 | + self.assertEqual(data.node, None) |
1130 | + |
1131 | + @defer.inlineCallbacks |
1132 | + def test_ListVolumes(self): |
1133 | + """Test meta with ListVolumes.""" |
1134 | + cmd = 'ListVolumes' |
1135 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1136 | + rcv = yield self.dbus.get_meta_queue() |
1137 | + data = rcv[0] |
1138 | + self.assertEqual(data.operation, 'ListVolumes') |
1139 | + self.assertEqual(data.path, None) |
1140 | + self.assertEqual(data.share, None) |
1141 | + self.assertEqual(data.node, None) |
1142 | + |
1143 | + @defer.inlineCallbacks |
1144 | + def test_Query(self): |
1145 | + """Test meta with Query.""" |
1146 | + cmd = 'Query' |
1147 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1148 | + rcv = yield self.dbus.get_meta_queue() |
1149 | + data = rcv[0] |
1150 | + self.assertEqual(data.operation, 'Query') |
1151 | + self.assertEqual(data.path, None) |
1152 | + self.assertEqual(data.share, None) |
1153 | + self.assertEqual(data.node, None) |
1154 | + |
1155 | + @defer.inlineCallbacks |
1156 | + def test_ListDir(self): |
1157 | + """Test meta with ListDir.""" |
1158 | + cmd = 'ListDir(share_id=a, node_id=b, server_hash=c)' |
1159 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1160 | + rcv = yield self.dbus.get_meta_queue() |
1161 | + data = rcv[0] |
1162 | + self.assertEqual(data.operation, 'ListDir') |
1163 | + self.assertEqual(data.path, '?') |
1164 | + self.assertEqual(data.share, 'a') |
1165 | + self.assertEqual(data.node, 'b') |
1166 | + |
1167 | + @defer.inlineCallbacks |
1168 | + def test_MakeDir(self): |
1169 | + """Test meta with MakeDir.""" |
1170 | + cmd = 'MakeDir(share_id=a, parent_id=b, name=c, marker=d)' |
1171 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1172 | + rcv = yield self.dbus.get_meta_queue() |
1173 | + data = rcv[0] |
1174 | + self.assertEqual(data.operation, 'MakeDir') |
1175 | + self.assertEqual(data.path, '/?.../c') |
1176 | + self.assertEqual(data.share, 'a') |
1177 | + self.assertEqual(data.node, None) |
1178 | + |
1179 | + @defer.inlineCallbacks |
1180 | + def test_MakeFile(self): |
1181 | + """Test meta with MakeFile.""" |
1182 | + cmd = 'MakeFile(share_id=a, parent_id=b, name=c, marker=d)' |
1183 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1184 | + rcv = yield self.dbus.get_meta_queue() |
1185 | + data = rcv[0] |
1186 | + self.assertEqual(data.operation, 'MakeFile') |
1187 | + self.assertEqual(data.path, '/?.../c') |
1188 | + self.assertEqual(data.share, 'a') |
1189 | + self.assertEqual(data.node, None) |
1190 | + |
1191 | + @defer.inlineCallbacks |
1192 | + def test_Unlink(self): |
1193 | + """Test meta with Unlink.""" |
1194 | + cmd = 'Unlink(share_id=a, node_id=b, server_hash=c)' |
1195 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1196 | + rcv = yield self.dbus.get_meta_queue() |
1197 | + data = rcv[0] |
1198 | + self.assertEqual(data.operation, 'Unlink') |
1199 | + self.assertEqual(data.path, '?') |
1200 | + self.assertEqual(data.share, 'a') |
1201 | + self.assertEqual(data.node, 'b') |
1202 | + |
1203 | + @defer.inlineCallbacks |
1204 | + def test_Move(self): |
1205 | + """Test meta with Move.""" |
1206 | + cmd = 'Move(share_id=a, node_id=b, old_parent_id=c, '\ |
1207 | + 'new_parent_id=d, new_name=e)' |
1208 | + self.fake_sdt_response('waiting_metadata', [cmd]) |
1209 | + rcv = yield self.dbus.get_meta_queue() |
1210 | + data = rcv[0] |
1211 | + self.assertEqual(data.operation, 'Move') |
1212 | + self.assertEqual(data.path, '/?.../? -> /?.../e') |
1213 | + self.assertEqual(data.share, 'a') |
1214 | + self.assertEqual(data.node, 'b') |
1215 | + |
1216 | + |
1217 | +class TestDataProcessingFolders(SafeTests): |
1218 | + """Processes Folders data before sending it to SyncDaemon.""" |
1219 | + |
1220 | + @defer.inlineCallbacks |
1221 | + def test_nodata(self): |
1222 | + """Test get folders with no data.""" |
1223 | + self.fake_sdt_response('get_folders', []) |
1224 | + rcv = yield self.dbus.get_folders() |
1225 | + self.assertEqual(len(rcv), 0) |
1226 | + |
1227 | + @defer.inlineCallbacks |
1228 | + def test_one(self): |
1229 | + """Test get folders with one.""" |
1230 | + d = dict(node_id='nid', path=u'pth', subscribed='True', |
1231 | + suggested_path=u'sgp', type='UDF', volume_id='vid') |
1232 | + self.fake_sdt_response('get_folders', [d]) |
1233 | + rcv = yield self.dbus.get_folders() |
1234 | + self.assertEqual(len(rcv), 1) |
1235 | + folder = rcv[0] |
1236 | + self.assertEqual(folder.node, 'nid') |
1237 | + self.assertEqual(folder.path, u'pth') |
1238 | + self.assertEqual(folder.suggested_path, u'sgp') |
1239 | + self.assertEqual(folder.subscribed, True) |
1240 | + self.assertEqual(folder.volume, 'vid') |
1241 | + |
1242 | + @defer.inlineCallbacks |
1243 | + def test_getting_info_two(self): |
1244 | + """When changed, update info, got two.""" |
1245 | + d1 = dict(node_id='nid1', path=u'pth1', subscribed='True', |
1246 | + suggested_path=u'sgp1', type='UDF', volume_id='vid1') |
1247 | + d2 = dict(node_id='nid2', path=u'pth2', subscribed='', |
1248 | + suggested_path=u'sgp2', type='UDF', volume_id='vid2') |
1249 | + self.fake_sdt_response('get_folders', [d1, d2]) |
1250 | + rcv = yield self.dbus.get_folders() |
1251 | + self.assertEqual(len(rcv), 2) |
1252 | + folder = rcv[0] |
1253 | + self.assertEqual(folder.node, 'nid1') |
1254 | + self.assertEqual(folder.path, u'pth1') |
1255 | + self.assertEqual(folder.suggested_path, u'sgp1') |
1256 | + self.assertEqual(folder.subscribed, True) |
1257 | + self.assertEqual(folder.volume, 'vid1') |
1258 | + folder = rcv[1] |
1259 | + self.assertEqual(folder.node, 'nid2') |
1260 | + self.assertEqual(folder.path, u'pth2') |
1261 | + self.assertEqual(folder.suggested_path, u'sgp2') |
1262 | + self.assertEqual(folder.subscribed, False) |
1263 | + self.assertEqual(folder.volume, 'vid2') |
1264 | + |
1265 | + |
1266 | +class TestToolActions(SafeTests): |
1267 | + """Actions against SD.tools. |
1268 | + |
1269 | + Here we test only the actions, not callbacks, as they're tested before |
1270 | + in what they return. |
1271 | + """ |
1272 | + |
1273 | + def test_start(self): |
1274 | + """Test call to start.""" |
1275 | + self.dbus.start() |
1276 | + self.check_sdt_called("start") |
1277 | + |
1278 | + def test_quit(self): |
1279 | + """Test call to quit.""" |
1280 | + self.dbus.quit() |
1281 | + self.check_sdt_called("quit") |
1282 | + |
1283 | + def test_connect(self): |
1284 | + """Test call to connect.""" |
1285 | + self.dbus.connect() |
1286 | + self.check_sdt_called("connect") |
1287 | + |
1288 | + def test_disconnect(self): |
1289 | + """Test call to disconnect.""" |
1290 | + self.dbus.disconnect() |
1291 | + self.check_sdt_called("disconnect") |
1292 | + |
1293 | + |
1294 | +class TestLogs(SafeTests): |
1295 | + """Test logging.""" |
1296 | + |
1297 | + def setUp(self): |
1298 | + """Set up.""" |
1299 | + self.handler = MementoHandler() |
1300 | + logging.getLogger('magicicada.dbusiface').addHandler(self.handler) |
1301 | + self.handler.setLevel(logging.DEBUG) |
1302 | + SafeTests.setUp(self) |
1303 | + |
1304 | + def test_instancing(self): |
1305 | + """Just logged SD instancing.""" |
1306 | + self.assertTrue(self.handler.check_inf("DBus interface starting")) |
1307 | + |
1308 | + def test_shutdown(self): |
1309 | + """Log when SD shutdowns.""" |
1310 | + self.dbus.shutdown() |
1311 | + self.assertTrue(self.handler.check_inf("DBus interface going down")) |
1312 | + |
1313 | + def test_waiting_content(self): |
1314 | + """Test call to waiting content.""" |
1315 | + self.dbus.get_content_queue() |
1316 | + self.assertTrue(self.handler.check_inf("Getting content queue")) |
1317 | + |
1318 | + def test_waiting_meta(self): |
1319 | + """Test call to waiting meta.""" |
1320 | + self.dbus.get_meta_queue() |
1321 | + self.assertTrue(self.handler.check_inf("Getting meta queue")) |
1322 | + |
1323 | + def test_get_status(self): |
1324 | + """Test call to status.""" |
1325 | + self.dbus.get_status() |
1326 | + self.assertTrue(self.handler.check_inf("Getting status")) |
1327 | + |
1328 | + def test_get_folders(self): |
1329 | + """Test call to folders.""" |
1330 | + self.dbus.get_folders() |
1331 | + self.assertTrue(self.handler.check_inf("Getting folders")) |
1332 | + |
1333 | + def test_is_sd_started(self): |
1334 | + """Test call to is_sd_started.""" |
1335 | + self.dbus.is_sd_started() |
1336 | + self.assertTrue(self.handler.check_inf( |
1337 | + "Checking if SD is started: True")) |
1338 | + |
1339 | + def test_start(self): |
1340 | + """Test call to start.""" |
1341 | + self.dbus.start() |
1342 | + self.assertTrue(self.handler.check_inf("Calling start")) |
1343 | + |
1344 | + def test_quit(self): |
1345 | + """Test call to quit.""" |
1346 | + self.dbus.quit() |
1347 | + self.assertTrue(self.handler.check_inf("Calling quit")) |
1348 | + |
1349 | + def test_connect(self): |
1350 | + """Test call to connect.""" |
1351 | + self.dbus.connect() |
1352 | + self.assertTrue(self.handler.check_inf("Calling connect")) |
1353 | + |
1354 | + def test_disconnect(self): |
1355 | + """Test call to disconnect.""" |
1356 | + self.dbus.disconnect() |
1357 | + self.assertTrue(self.handler.check_inf("Calling disconnect")) |
1358 | + |
1359 | + def test_status_changed(self): |
1360 | + """Test status changed callback.""" |
1361 | + d = dict(name='name', description='description', is_error='', |
1362 | + is_connected='True', is_online='', queues='queues', |
1363 | + connection='connection') |
1364 | + self.dbus._on_status_changed(d) |
1365 | + self.assertTrue(self.handler.check_inf("Received Status changed")) |
1366 | + self.assertTrue(self.handler.check_dbg("Status changed data: %r" % d)) |
1367 | + |
1368 | + def test_content_queue_changed(self): |
1369 | + """Test content queue changed callback.""" |
1370 | + self.dbus._on_content_queue_changed("foo") |
1371 | + self.assertTrue(self.handler.check_inf( |
1372 | + "Received Content Queue changed")) |
1373 | + |
1374 | + def test_name_owner_changed_other(self): |
1375 | + """Test name owner changed callback, no SD.""" |
1376 | + self.dbus._on_name_owner_changed("other", "", "T") |
1377 | + self.assertFalse(self.handler.check_inf("Received Name Owner changed")) |
1378 | + |
1379 | + def test_name_owner_changed_syncdaemon(self): |
1380 | + """Test name owner changed callback, SD value ok.""" |
1381 | + self.dbus._on_name_owner_changed("com.ubuntuone.SyncDaemon", "", "T") |
1382 | + self.assertTrue(self.handler.check_inf("Received Name Owner changed")) |
1383 | + self.assertTrue(self.handler.check_dbg("Name Owner data: u'' u'T'")) |
1384 | + |
1385 | + def test_name_owner_changed_yes_syncdaemon_TF(self): |
1386 | + """Test name owner changed callback, SD value bad.""" |
1387 | + self.dbus._on_name_owner_changed("com.ubuntuone.SyncDaemon", "F", "T") |
1388 | + self.assertTrue(self.handler.check_inf("Received Name Owner changed")) |
1389 | + self.assertTrue(self.handler.check_dbg("Name Owner data: u'F' u'T'")) |
1390 | + self.assertTrue(self.handler.check("ERROR", |
1391 | + "Name Owner invalid data: Same bool in old and new!")) |
1392 | + |
1393 | + def test_folder_created_changed(self): |
1394 | + """Test folder created changed callback.""" |
1395 | + self.dbus._on_folder_created("foo") |
1396 | + self.assertTrue(self.handler.check_inf("Received Folder created")) |
1397 | + |
1398 | + def test_folder_deleted_changed(self): |
1399 | + """Test folder deleted changed callback.""" |
1400 | + self.dbus._on_folder_deleted("foo") |
1401 | + self.assertTrue(self.handler.check_inf("Received Folder deleted")) |
1402 | + |
1403 | + @defer.inlineCallbacks |
1404 | + def test_content_queue_processing(self): |
1405 | + """Test with one item in the queue.""" |
1406 | + c = dict(operation='oper', path='path', share='share', node='node') |
1407 | + self.fake_sdt_response('waiting_content', [c]) |
1408 | + yield self.dbus.get_content_queue() |
1409 | + self.assertTrue(self.handler.check_inf( |
1410 | + "Processing Content Queue items (1)")) |
1411 | + self.assertTrue(self.handler.check_dbg( |
1412 | + " Content Queue data: %s" % c)) |
1413 | + |
1414 | + @defer.inlineCallbacks |
1415 | + def test_meta_queue_processing(self): |
1416 | + """Test with one item in the queue.""" |
1417 | + self.fake_sdt_response('waiting_metadata', ['ListShares']) |
1418 | + yield self.dbus.get_meta_queue() |
1419 | + self.assertTrue(self.handler.check_inf( |
1420 | + "Processing Meta Queue items (1)")) |
1421 | + self.assertTrue(self.handler.check_dbg( |
1422 | + " Meta Queue data: u'ListShares'")) |
1423 | + |
1424 | + @defer.inlineCallbacks |
1425 | + def test_folders_processing(self): |
1426 | + """Test get folders with one.""" |
1427 | + d = dict(node_id='nid', path=u'pth', subscribed='True', |
1428 | + suggested_path=u'sgp', type='UDF', volume_id='vid') |
1429 | + self.fake_sdt_response('get_folders', [d]) |
1430 | + yield self.dbus.get_folders() |
1431 | + self.assertTrue(self.handler.check_inf("Processing Folders items (1)")) |
1432 | + self.assertTrue(self.handler.check_dbg(" Folders data: %r" % d)) |
1433 | |
1434 | === modified file 'magicicada/tests/test_magicicada.py' |
1435 | --- magicicada/tests/test_magicicada.py 2010-05-27 02:01:27 +0000 |
1436 | +++ magicicada/tests/test_magicicada.py 2010-05-27 20:56:26 +0000 |
1437 | @@ -25,6 +25,7 @@ |
1438 | from twisted.trial.unittest import TestCase |
1439 | |
1440 | from magicicada import MagicicadaUI, CONTENT_QUEUE, META_QUEUE, syncdaemon |
1441 | +from magicicada.dbusiface import QueueData |
1442 | from magicicada.helpers import NO_OP |
1443 | |
1444 | |
1445 | @@ -278,9 +279,9 @@ |
1446 | """Build some data to pass to queue changed callback and related.""" |
1447 | items = [] |
1448 | for i in xrange(limit): |
1449 | - cq = syncdaemon.QueueData(operation='operation %i' % i, |
1450 | - path='path %i' % i, node='node %i' % i, |
1451 | - share='share %i' % i) |
1452 | + cq = QueueData(operation='operation %i' % i, |
1453 | + path='path %i' % i, node='node %i' % i, |
1454 | + share='share %i' % i) |
1455 | items.append(cq) |
1456 | return items |
1457 | |
1458 | |
1459 | === modified file 'magicicada/tests/test_syncdaemon.py' |
1460 | --- magicicada/tests/test_syncdaemon.py 2010-05-22 20:27:11 +0000 |
1461 | +++ magicicada/tests/test_syncdaemon.py 2010-05-27 20:56:26 +0000 |
1462 | @@ -21,49 +21,133 @@ |
1463 | import logging |
1464 | import unittest |
1465 | |
1466 | -import dbus |
1467 | -from dbus.mainloop.glib import DBusGMainLoop |
1468 | - |
1469 | -# this should be imported *before* importing the reactor below, as needs to |
1470 | -# install the glib connection first |
1471 | from magicicada.syncdaemon import SyncDaemon, State |
1472 | -from magicicada.helpers import NO_OP |
1473 | +from magicicada.tests.helpers import MementoHandler |
1474 | |
1475 | -from dbus.lowlevel import SignalMessage |
1476 | from twisted.trial.unittest import TestCase as TwistedTestCase |
1477 | from twisted.internet import defer, reactor |
1478 | |
1479 | -from ubuntuone.syncdaemon.dbus_interface import DBUS_IFACE_STATUS_NAME |
1480 | - |
1481 | - |
1482 | -class SignalsBaseTest(TwistedTestCase): |
1483 | - """Base infrastructure to tests the signals.""" |
1484 | - |
1485 | - timeout = 2 |
1486 | + |
1487 | +class FakeDBusInterface(object): |
1488 | + """Fake DBus Interface, for SD to not use dbus at all during tests.""" |
1489 | + |
1490 | + fake_sd_started = False |
1491 | + |
1492 | + def __init__(self, sd): |
1493 | + pass |
1494 | + |
1495 | + def shutdown(self): |
1496 | + pass |
1497 | + |
1498 | + def get_status(self): |
1499 | + """Fake status.""" |
1500 | + return defer.succeed(('fakename', 'fakedescrip', False, True, |
1501 | + False, 'fakequeues', 'fakeconnection')) |
1502 | + def get_folders(self): |
1503 | + """Fake folders.""" |
1504 | + return defer.succeed('fakedata') |
1505 | + get_content_queue = get_meta_queue = get_folders |
1506 | + start = quit = connect = disconnect = get_folders |
1507 | + |
1508 | + def is_sd_started(self): |
1509 | + """Fake response.""" |
1510 | + return self.fake_sd_started |
1511 | + |
1512 | + |
1513 | +class BaseTest(TwistedTestCase): |
1514 | + """Base test with a SD.""" |
1515 | + |
1516 | + timeout = 1 |
1517 | |
1518 | def setUp(self): |
1519 | - """Set up the test.""" |
1520 | - self.loop = DBusGMainLoop(set_as_default=True) |
1521 | - self.bus = dbus.bus.BusConnection(mainloop=self.loop) |
1522 | - self.sd = SyncDaemon() |
1523 | + """Set up.""" |
1524 | + self.sd = SyncDaemon(FakeDBusInterface) |
1525 | |
1526 | def tearDown(self): |
1527 | - """Tear down the test.""" |
1528 | + """Tear down.""" |
1529 | self.sd.shutdown() |
1530 | |
1531 | - def send_signal(self, interface, signal, signature, *args): |
1532 | - """Send a DBus signal.""" |
1533 | - msg = SignalMessage('/status', interface, signal) |
1534 | - msg.set_no_reply(True) |
1535 | - msg.append(*args, signature=signature) |
1536 | - self.bus.send_message(msg) |
1537 | - |
1538 | - |
1539 | -class SimpleSignalsTests(SignalsBaseTest): |
1540 | + |
1541 | +class InitialDataTests(unittest.TestCase): |
1542 | + """Tests for initial data gathering.""" |
1543 | + |
1544 | + def test_called_by_start(self): |
1545 | + """Check that start calls get initial data.""" |
1546 | + sd = SyncDaemon(FakeDBusInterface) |
1547 | + called = [] |
1548 | + sd._get_initial_data = lambda: called.append(True) |
1549 | + sd.start() |
1550 | + self.assertTrue(called) |
1551 | + |
1552 | + def test_called_by_nameownerchanged_no(self): |
1553 | + """Check that it is called when discover that sd started.""" |
1554 | + sd = SyncDaemon(FakeDBusInterface) |
1555 | + called = [] |
1556 | + sd._get_initial_data = lambda: called.append(True) |
1557 | + sd.on_sd_name_owner_changed(True) |
1558 | + self.assertTrue(called) |
1559 | + |
1560 | + def test_called_by_nameownerchanged_yes(self): |
1561 | + """Check that it is not called when discover that sd stopped.""" |
1562 | + sd = SyncDaemon(FakeDBusInterface) |
1563 | + called = [] |
1564 | + sd._get_initial_data = lambda: called.append(True) |
1565 | + sd.on_sd_name_owner_changed(False) |
1566 | + self.assertFalse(called) |
1567 | + |
1568 | + def test_called_beggining_no(self): |
1569 | + """Check that it should not be called if no SD.""" |
1570 | + called = [] |
1571 | + orig_met = SyncDaemon._get_initial_data |
1572 | + SyncDaemon._get_initial_data = lambda s: called.append(True) |
1573 | + SyncDaemon(FakeDBusInterface) |
1574 | + SyncDaemon._get_initial_data = orig_met |
1575 | + self.assertFalse(called) |
1576 | + |
1577 | + def test_called_beggining_yes(self): |
1578 | + """Check that it should be called if SD already started.""" |
1579 | + called = [] |
1580 | + orig_met = SyncDaemon._get_initial_data |
1581 | + SyncDaemon._get_initial_data = lambda s: called.append(True) |
1582 | + FakeDBusInterface.fake_sd_started = True |
1583 | + SyncDaemon(FakeDBusInterface) |
1584 | + SyncDaemon._get_initial_data = orig_met |
1585 | + self.assertTrue(called) |
1586 | + |
1587 | + def test_calls_callbacks(self): |
1588 | + """Check that initial data calls the callbacks for new data.""" |
1589 | + called = [] |
1590 | + sd = SyncDaemon(FakeDBusInterface) |
1591 | + f = lambda *a: called.append(True) |
1592 | + sd.status_changed_callback = f |
1593 | + sd.content_queue_changed_callback = f |
1594 | + sd.meta_queue_changed_callback = f |
1595 | + |
1596 | + sd._get_initial_data() |
1597 | + self.assertEqual(len(called), 3) |
1598 | + |
1599 | + |
1600 | +class StatusChangedTests(BaseTest): |
1601 | """Simple signals checking.""" |
1602 | |
1603 | + @defer.inlineCallbacks |
1604 | + def test_initial_value(self): |
1605 | + """Fills the status info initially.""" |
1606 | + called = [] |
1607 | + def fake(): |
1608 | + """Fake method.""" |
1609 | + called.append(True) |
1610 | + return defer.succeed(('fakename', 'fakedescrip', False, True, |
1611 | + False, 'fakequeues', 'fakeconnection')) |
1612 | + |
1613 | + self.sd.dbus.get_status = fake |
1614 | + yield self.sd._get_initial_data() |
1615 | + self.assertTrue(called) |
1616 | + |
1617 | def test_statuschanged(self): |
1618 | """Test StatusChanged signal.""" |
1619 | + deferred = defer.Deferred() |
1620 | + |
1621 | def callback(name, description, is_error, is_connected, is_online, |
1622 | queues, connection): |
1623 | """Check received data.""" |
1624 | @@ -76,325 +160,208 @@ |
1625 | self.assertEqual(connection, 'connection') |
1626 | deferred.callback(True) |
1627 | |
1628 | - # set the callback |
1629 | self.sd.status_changed_callback = callback |
1630 | - |
1631 | - # send signal with signature and structures like original syncdaemon |
1632 | - d = dict(name='name', description='description', is_error='', |
1633 | - is_connected='True', is_online='', queues='queues', |
1634 | - connection='connection') |
1635 | - self.send_signal(DBUS_IFACE_STATUS_NAME, 'StatusChanged', 'a{ss}', d) |
1636 | - |
1637 | - deferred = defer.Deferred() |
1638 | + self.sd.on_sd_status_changed('name', 'description', False, True, |
1639 | + False, 'queues', 'connection') |
1640 | return deferred |
1641 | |
1642 | - |
1643 | -class ContentQueueChangedTests(SignalsBaseTest): |
1644 | + def test_status_changed_affects_cuurent_status(self): |
1645 | + """Makes changes to see how status are reflected.""" |
1646 | + # one set of values |
1647 | + self.sd.on_sd_status_changed('name1', 'description1', False, True, |
1648 | + False, 'queues1', 'connection1') |
1649 | + self.assertEqual(self.sd.current_state.name, 'name1') |
1650 | + self.assertEqual(self.sd.current_state.description, 'description1') |
1651 | + self.assertEqual(self.sd.current_state.is_error, False) |
1652 | + self.assertEqual(self.sd.current_state.is_connected, True) |
1653 | + self.assertEqual(self.sd.current_state.is_online, False) |
1654 | + self.assertEqual(self.sd.current_state.queues, 'queues1') |
1655 | + self.assertEqual(self.sd.current_state.connection, 'connection1') |
1656 | + |
1657 | + # again, to be sure they actually are updated |
1658 | + self.sd.on_sd_status_changed('name2', 'description2', True, False, |
1659 | + True, 'queues2', 'connection2') |
1660 | + self.assertEqual(self.sd.current_state.name, 'name2') |
1661 | + self.assertEqual(self.sd.current_state.description, 'description2') |
1662 | + self.assertEqual(self.sd.current_state.is_error, True) |
1663 | + self.assertEqual(self.sd.current_state.is_connected, False) |
1664 | + self.assertEqual(self.sd.current_state.is_online, True) |
1665 | + self.assertEqual(self.sd.current_state.queues, 'queues2') |
1666 | + self.assertEqual(self.sd.current_state.connection, 'connection2') |
1667 | + |
1668 | + |
1669 | +class ContentQueueChangedTests(BaseTest): |
1670 | """Check the ContenQueueChanged handling.""" |
1671 | |
1672 | + @defer.inlineCallbacks |
1673 | + def test_initial_value(self): |
1674 | + """Fills the content queue info initially.""" |
1675 | + called = [] |
1676 | + self.sd.dbus.get_content_queue = lambda: called.append(True) |
1677 | + yield self.sd._get_initial_data() |
1678 | + self.assertTrue(called) |
1679 | + |
1680 | def test_without_setting_callback(self): |
1681 | """It should work even if not hooking into the callback.""" |
1682 | - self.sd._process_cq([]) |
1683 | - |
1684 | - def _contentqueuechanged_test(self, somedata): |
1685 | - """Test ContentQueueChanged signal with some data.""" |
1686 | - def callback(queued_elements): |
1687 | - """Check received data.""" |
1688 | - self.assertEqual(len(queued_elements), len(somedata)) |
1689 | - for received, original in zip(queued_elements, somedata): |
1690 | - self.assertEqual(received.operation, original['operation']) |
1691 | - self.assertEqual(received.path, original['path']) |
1692 | - self.assertEqual(received.share, original['share']) |
1693 | - self.assertEqual(received.node, original['node']) |
1694 | - deferred.callback(True) |
1695 | - |
1696 | - # set the callback |
1697 | - self.sd.content_queue_changed_callback = callback |
1698 | - |
1699 | - # monkeypatch SyncDaemon to quickly return the queued elements |
1700 | - self.sd._get_content_queue = lambda: defer.succeed(somedata) |
1701 | - |
1702 | - # send signal with signature and structures like original syncdaemon, |
1703 | - # but note that in this case we don't care of this info |
1704 | - data = {'foo': {'bar':'1', 'baz':'2'}} |
1705 | - self.send_signal(DBUS_IFACE_STATUS_NAME, 'ContentQueueChanged', |
1706 | - 'a{sa{ss}}', data) |
1707 | - deferred = defer.Deferred() |
1708 | - return deferred |
1709 | - |
1710 | - def test_contentqueuechanged_nodata(self): |
1711 | - """Test ContentQueueChanged signal with no data in the queue.""" |
1712 | - return self._contentqueuechanged_test([]) |
1713 | - |
1714 | - def test_contentqueuechanged_oneitem(self): |
1715 | - """Test ContentQueueChanged signal with one item in the queue.""" |
1716 | - c = dict(operation='oper', path='path', share='share', node='node') |
1717 | - return self._contentqueuechanged_test([c]) |
1718 | - |
1719 | - def test_contentqueuechanged_twoitems(self): |
1720 | - """Test ContentQueueChanged signal with two items in the queue.""" |
1721 | - c = dict(operation='oper1', path='path1', share='share1', node='node1') |
1722 | - d = dict(operation='oper2', path='path2', share='share2', node='node2') |
1723 | - return self._contentqueuechanged_test([c, d]) |
1724 | - |
1725 | - def test_no_double_callback_for_same_info(self): |
1726 | - """No callback call for same info in the CQ.""" |
1727 | - callback_called = [] |
1728 | - def callback(queued_elements): |
1729 | - """Store the callbacked stuff.""" |
1730 | - callback_called.append(queued_elements) |
1731 | - |
1732 | - # set the callback |
1733 | - self.sd.content_queue_changed_callback = callback |
1734 | - |
1735 | - # data to test |
1736 | - c = dict(operation='oper1', path='path1', share='share1', node='node1') |
1737 | - d = dict(operation='oper2', path='path2', share='share2', node='node2') |
1738 | - e = dict(operation='oper3', path='path3', share='share3', node='node3') |
1739 | - |
1740 | - # call a sequence of different and repeated data |
1741 | - self.sd._process_cq([c]) |
1742 | - self.sd._process_cq([d]) |
1743 | - self.sd._process_cq([d]) # repeated! |
1744 | - self.sd._process_cq([c]) |
1745 | - self.sd._process_cq([e]) |
1746 | - self.sd._process_cq([e]) # repeated! |
1747 | - self.sd._process_cq([e]) # repeated! |
1748 | - self.sd._process_cq([d]) |
1749 | - self.sd._process_cq([d, d]) |
1750 | - self.sd._process_cq([d, d]) # repeated! |
1751 | - self.sd._process_cq([d]) |
1752 | - should_be = [ [c], [d], [c], [e], [d], [d, d], [d] ] |
1753 | - |
1754 | - # check order and that it wasn't repeated |
1755 | - self.assertEqual(len(callback_called), len(should_be)) |
1756 | - for cq_received, cq_original in zip(callback_called, should_be): |
1757 | - for received, original in zip(cq_received, cq_original): |
1758 | - self.assertEqual(received.operation, original['operation']) |
1759 | - self.assertEqual(received.path, original['path']) |
1760 | - self.assertEqual(received.share, original['share']) |
1761 | - self.assertEqual(received.node, original['node']) |
1762 | - |
1763 | - def test_CQ_state_none(self): |
1764 | - """Check the ContentQueue info, being none.""" |
1765 | - self.assertEqual(len(self.sd.content_queue), 0) |
1766 | + self.sd.dbus.get_content_queue = lambda: defer.succeed(['foo']) |
1767 | + self.sd.on_sd_content_queue_changed() |
1768 | + |
1769 | + def test_callback_call(self): |
1770 | + """Call the callback.""" |
1771 | + called = [] |
1772 | + self.sd.content_queue_changed_callback = lambda cq: called.append(cq) |
1773 | + self.sd.dbus.get_content_queue = lambda: defer.succeed(['foo']) |
1774 | + self.sd.on_sd_content_queue_changed() |
1775 | + self.assertTrue(called) |
1776 | + |
1777 | + def test_callback_call_twice_different(self): |
1778 | + """Call the callback twice for different info.""" |
1779 | + called = [] |
1780 | + self.sd.content_queue_changed_callback = lambda cq: called.append(cq) |
1781 | + |
1782 | + # first call |
1783 | + self.sd.dbus.get_content_queue = lambda: defer.succeed(['foo']) |
1784 | + self.sd.on_sd_content_queue_changed() |
1785 | + self.assertEqual(called, [['foo']]) |
1786 | + |
1787 | + # second call, different info |
1788 | + self.sd.dbus.get_content_queue = lambda: defer.succeed(['bar']) |
1789 | + self.sd.on_sd_content_queue_changed() |
1790 | + self.assertEqual(called, [['foo'], ['bar']]) |
1791 | + |
1792 | + def test_callback_call_twice_same(self): |
1793 | + """Call the callback once, even getting twice the same info.""" |
1794 | + called = [] |
1795 | + self.sd.content_queue_changed_callback = lambda cq: called.append(cq) |
1796 | + |
1797 | + # first call |
1798 | + self.sd.dbus.get_content_queue = lambda: defer.succeed(['foo']) |
1799 | + self.sd.on_sd_content_queue_changed() |
1800 | + self.assertEqual(called, [['foo']]) |
1801 | + |
1802 | + # second call, same info |
1803 | + self.sd.dbus.get_content_queue = lambda: defer.succeed(['foo']) |
1804 | + self.sd.on_sd_content_queue_changed() |
1805 | + self.assertEqual(called, [['foo']]) |
1806 | + |
1807 | + def test_CQ_state_nothing(self): |
1808 | + """Check the ContentQueue info, being nothing.""" |
1809 | + self.sd.dbus.get_content_queue = lambda: defer.succeed([]) |
1810 | + self.sd.on_sd_content_queue_changed() |
1811 | + self.assertEqual(self.sd.content_queue, []) |
1812 | |
1813 | def test_CQ_state_one(self): |
1814 | """Check the ContentQueue info, being one.""" |
1815 | - d = dict(operation='oper', path='path', share='share', node='node') |
1816 | - self.sd._process_cq([d]) |
1817 | - self.assertEqual(len(self.sd.content_queue), 1) |
1818 | - |
1819 | - # check the data |
1820 | - cqit = self.sd.content_queue[0] |
1821 | - self.assertEqual(cqit.operation, 'oper') |
1822 | - self.assertEqual(cqit.path, 'path') |
1823 | - self.assertEqual(cqit.share, 'share') |
1824 | - self.assertEqual(cqit.node, 'node') |
1825 | - |
1826 | - def test_CQ_state_several(self): |
1827 | - """Check the ContentQueue info, several calls, last one is bigger.""" |
1828 | - c = dict(operation='oper1', path='path1', share='share1', node='node1') |
1829 | - d = dict(operation='oper2', path='path2', share='share2', node='node2') |
1830 | - self.sd._process_cq([c]) |
1831 | - self.sd._process_cq([d]) |
1832 | - self.sd._process_cq([c, d]) |
1833 | - self.assertEqual(len(self.sd.content_queue), 2) |
1834 | - |
1835 | - # check the data |
1836 | - cqit = self.sd.content_queue[0] |
1837 | - self.assertEqual(cqit.operation, 'oper1') |
1838 | - self.assertEqual(cqit.path, 'path1') |
1839 | - self.assertEqual(cqit.share, 'share1') |
1840 | - self.assertEqual(cqit.node, 'node1') |
1841 | - cqit = self.sd.content_queue[1] |
1842 | - self.assertEqual(cqit.operation, 'oper2') |
1843 | - self.assertEqual(cqit.path, 'path2') |
1844 | - self.assertEqual(cqit.share, 'share2') |
1845 | - self.assertEqual(cqit.node, 'node2') |
1846 | - |
1847 | - |
1848 | -class MetaQueueChangedTests(SignalsBaseTest): |
1849 | + self.sd.dbus.get_content_queue = lambda: defer.succeed(['foo']) |
1850 | + self.sd.on_sd_content_queue_changed() |
1851 | + self.assertEqual(self.sd.content_queue, ['foo']) |
1852 | + |
1853 | + def test_CQ_state_two(self): |
1854 | + """Check the ContentQueue info, two.""" |
1855 | + self.sd.dbus.get_content_queue = lambda: defer.succeed(['foo', 'bar']) |
1856 | + self.sd.on_sd_content_queue_changed() |
1857 | + self.assertEqual(self.sd.content_queue, ['foo', 'bar']) |
1858 | + |
1859 | + |
1860 | +class MetaQueueChangedTests(BaseTest): |
1861 | """Check the MetaQueueChanged handling.""" |
1862 | |
1863 | - def test_without_setting_callback(self): |
1864 | - """It should work even if not hooking into the callback.""" |
1865 | - self.sd._process_mq([]) |
1866 | - |
1867 | - def _metaqueuechanged_test(self, inpdata, outdata): |
1868 | - """Test MetaQueueChanged signal with some data.""" |
1869 | - deferred = defer.Deferred() |
1870 | - def callback(queued_elements): |
1871 | - """Check received data.""" |
1872 | - self.assertEqual(len(queued_elements), len(outdata)) |
1873 | - for received, original in zip(queued_elements, outdata): |
1874 | - self.assertEqual(received.operation, original['operation']) |
1875 | - self.assertEqual(received.path, original['path']) |
1876 | - self.assertEqual(received.share, original['share']) |
1877 | - self.assertEqual(received.node, original['node']) |
1878 | - deferred.callback(True) |
1879 | - |
1880 | - # set the callback |
1881 | - self.sd.meta_queue_changed_callback = callback |
1882 | - |
1883 | - # execute the function that trigger this (not by a dbus signal, as |
1884 | - # that was not available in Lucid) |
1885 | - self.sd._process_mq(inpdata) |
1886 | - |
1887 | - return deferred |
1888 | - |
1889 | - def test_metaqueuechanged_nodata(self): |
1890 | - """Test MetaQueueChanged signal with no data in the queue.""" |
1891 | - return self._metaqueuechanged_test([], []) |
1892 | - |
1893 | - def test_GetPublicFiles(self): |
1894 | - """Test meta with GetPublicFiles.""" |
1895 | - r = dict(operation='GetPublicFiles', path=None, share=None, node=None) |
1896 | - return self._metaqueuechanged_test(['GetPublicFiles'], [r]) |
1897 | - |
1898 | - def test_AccountInquiry(self): |
1899 | - """Test meta with AccountInquiry.""" |
1900 | - r = dict(operation='AccountInquiry', path=None, share=None, node=None) |
1901 | - return self._metaqueuechanged_test(['AccountInquiry'], [r]) |
1902 | - |
1903 | - def test_FreeSpaceInquiry(self): |
1904 | - """Test meta with FreeSpaceInquiry.""" |
1905 | - r = dict(operation='FreeSpaceInquiry', path=None, |
1906 | - share=None, node=None) |
1907 | - return self._metaqueuechanged_test(['FreeSpaceInquiry'], [r]) |
1908 | - |
1909 | - def test_ListShares(self): |
1910 | - """Test meta with ListShares.""" |
1911 | - r = dict(operation='ListShares', path=None, share=None, node=None) |
1912 | - return self._metaqueuechanged_test(['ListShares'], [r]) |
1913 | - |
1914 | - def test_ListVolumes(self): |
1915 | - """Test meta with ListVolumes.""" |
1916 | - r = dict(operation='ListVolumes', path=None, share=None, node=None) |
1917 | - return self._metaqueuechanged_test(['ListVolumes'], [r]) |
1918 | - |
1919 | - def test_Query(self): |
1920 | - """Test meta with Query.""" |
1921 | - r = dict(operation='Query', path=None, share=None, node=None) |
1922 | - return self._metaqueuechanged_test(['Query'], [r]) |
1923 | - |
1924 | - def test_ListDir(self): |
1925 | - """Test meta with ListDir.""" |
1926 | - r = dict(operation='ListDir', path='?', share='a', node='b') |
1927 | - cmd = 'ListDir(share_id=a, node_id=b, server_hash=c)' |
1928 | - return self._metaqueuechanged_test([cmd], [r]) |
1929 | - |
1930 | - def test_MakeDir(self): |
1931 | - """Test meta with MakeDir.""" |
1932 | - r = dict(operation='MakeDir', path='/?.../c', share='a', node=None) |
1933 | - cmd = 'MakeDir(share_id=a, parent_id=b, name=c, marker=d)' |
1934 | - return self._metaqueuechanged_test([cmd], [r]) |
1935 | - |
1936 | - def test_MakeFile(self): |
1937 | - """Test meta with MakeFile.""" |
1938 | - r = dict(operation='MakeFile', path='/?.../c', share='a', node=None) |
1939 | - cmd = 'MakeFile(share_id=a, parent_id=b, name=c, marker=d)' |
1940 | - return self._metaqueuechanged_test([cmd], [r]) |
1941 | - |
1942 | - def test_Unlink(self): |
1943 | - """Test meta with Unlink.""" |
1944 | - r = dict(operation='Unlink', path='?', share='a', node='b') |
1945 | - cmd = 'Unlink(share_id=a, node_id=b, server_hash=c)' |
1946 | - return self._metaqueuechanged_test([cmd], [r]) |
1947 | - |
1948 | - def test_Move(self): |
1949 | - """Test meta with Move.""" |
1950 | - r = dict(operation='Move', path='/?.../? -> /?.../e', |
1951 | - share='a', node='b') |
1952 | - cmd = 'Move(share_id=a, node_id=b, old_parent_id=c, '\ |
1953 | - 'new_parent_id=d, new_name=e)' |
1954 | - return self._metaqueuechanged_test([cmd], [r]) |
1955 | - |
1956 | - def test_metaqueuechanged_twoitems(self): |
1957 | - """Test MetaQueueChanged signal with two items in the queue.""" |
1958 | - r1 = dict(operation='AccountInquiry', path=None, share=None, node=None) |
1959 | - r2 = dict(operation='ListShares', path=None, share=None, node=None) |
1960 | - return self._metaqueuechanged_test(['AccountInquiry', 'ListShares'], |
1961 | - [r1, r2]) |
1962 | - |
1963 | - def test_no_double_callback_for_same_info(self): |
1964 | - """No callback call for same info in the MQ.""" |
1965 | - callback_called = [] |
1966 | - def callback(queued_elements): |
1967 | - """Store the callbacked stuff.""" |
1968 | - callback_called.append(queued_elements) |
1969 | - |
1970 | - # set the callback |
1971 | - self.sd.meta_queue_changed_callback = callback |
1972 | - |
1973 | - # data to test |
1974 | - r1 = dict(operation='AccountInquiry', path=None, share=None, node=None) |
1975 | - cmd1 = 'AccountInquiry' |
1976 | - r2 = dict(operation='ListShares', path=None, share=None, node=None) |
1977 | - cmd2 = 'ListShares' |
1978 | - r3 = dict(operation='ListDir', path='?', share='a', node='b') |
1979 | - cmd3 = 'ListDir(share_id=a, node_id=b, server_hash=c)' |
1980 | - |
1981 | - # call a sequence of different and repeated data |
1982 | - self.sd._process_mq([cmd1]) |
1983 | - self.sd._process_mq([cmd2]) |
1984 | - self.sd._process_mq([cmd2]) # repeated! |
1985 | - self.sd._process_mq([cmd1]) |
1986 | - self.sd._process_mq([cmd3]) |
1987 | - self.sd._process_mq([cmd3]) # repeated! |
1988 | - self.sd._process_mq([cmd3]) # repeated! |
1989 | - self.sd._process_mq([cmd2]) |
1990 | - self.sd._process_mq([cmd2, cmd2]) |
1991 | - self.sd._process_mq([cmd2, cmd2]) # repeated! |
1992 | - self.sd._process_mq([cmd2]) |
1993 | - should_be = [ [r1], [r2], [r1], [r3], [r2], [r2, r2], [r2] ] |
1994 | - |
1995 | - # check order and that it wasn't repeated |
1996 | - self.assertEqual(len(callback_called), len(should_be)) |
1997 | - for cq_received, cq_original in zip(callback_called, should_be): |
1998 | - for received, original in zip(cq_received, cq_original): |
1999 | - self.assertEqual(received.operation, original['operation']) |
2000 | - self.assertEqual(received.path, original['path']) |
2001 | - self.assertEqual(received.share, original['share']) |
2002 | - self.assertEqual(received.node, original['node']) |
2003 | + def setUp(self): |
2004 | + """Set up.""" |
2005 | + BaseTest.setUp(self) |
2006 | + self.sd.current_state._set(name='QUEUE_MANAGER', |
2007 | + queues='WORKING_ON_METADATA') |
2008 | + |
2009 | + @defer.inlineCallbacks |
2010 | + def test_initial_value(self): |
2011 | + """Fills the meta queue info initially.""" |
2012 | + called = [] |
2013 | + self.sd.dbus.get_meta_queue = lambda: called.append(True) |
2014 | + yield self.sd._get_initial_data() |
2015 | + self.assertTrue(called) |
2016 | + |
2017 | + def test_callback_call(self): |
2018 | + """Call the callback.""" |
2019 | + called = [] |
2020 | + self.sd.meta_queue_changed_callback = lambda mq: called.append(mq) |
2021 | + self.sd.dbus.get_meta_queue = lambda: defer.succeed(['foo']) |
2022 | + self.sd._check_mq() |
2023 | + self.assertTrue(called) |
2024 | + |
2025 | + def test_callback_call_twice_different(self): |
2026 | + """Call the callback twice for different info.""" |
2027 | + called = [] |
2028 | + self.sd.meta_queue_changed_callback = lambda mq: called.append(mq) |
2029 | + |
2030 | + # first call |
2031 | + self.sd.dbus.get_meta_queue = lambda: defer.succeed(['foo']) |
2032 | + self.sd._check_mq() |
2033 | + self.assertEqual(called, [['foo']]) |
2034 | + |
2035 | + # second call, different info |
2036 | + self.sd.dbus.get_meta_queue = lambda: defer.succeed(['bar']) |
2037 | + self.sd._check_mq() |
2038 | + self.assertEqual(called, [['foo'], ['bar']]) |
2039 | + |
2040 | + def test_callback_call_twice_same(self): |
2041 | + """Call the callback once, even getting twice the same info.""" |
2042 | + called = [] |
2043 | + self.sd.meta_queue_changed_callback = lambda mq: called.append(mq) |
2044 | + |
2045 | + # first call |
2046 | + self.sd.dbus.get_meta_queue = lambda: defer.succeed(['foo']) |
2047 | + self.sd._check_mq() |
2048 | + self.assertEqual(called, [['foo']]) |
2049 | + |
2050 | + # second call, same info |
2051 | + self.sd.dbus.get_meta_queue = lambda: defer.succeed(['foo']) |
2052 | + self.sd._check_mq() |
2053 | + self.assertEqual(called, [['foo']]) |
2054 | + |
2055 | + def test_polling_initiated_state_changed(self): |
2056 | + """The polling initiates when state changes.""" |
2057 | + called = [] |
2058 | + self.sd._check_mq = lambda: called.append(True) |
2059 | + |
2060 | + # send some status changed |
2061 | + self.sd.on_sd_status_changed('name', 'description', False, True, |
2062 | + False, 'queues', 'connection') |
2063 | + self.assertTrue(called) |
2064 | |
2065 | def test_mq_polling_workinginmetadata(self): |
2066 | """Check that it polls mq while working in metadata.""" |
2067 | - |
2068 | # set the callback |
2069 | - self.sd._get_meta_queue = lambda *a: deferred.callback(True) |
2070 | - |
2071 | - # send signal with signature and structures like original syncdaemon |
2072 | - d = dict(name='QUEUE_MANAGER', queues='WORKING_ON_METADATA', |
2073 | - description='description', is_error='', is_connected='True', |
2074 | - is_online='', connection='conn') |
2075 | - self.send_signal(DBUS_IFACE_STATUS_NAME, 'StatusChanged', 'a{ss}', d) |
2076 | - |
2077 | deferred = defer.Deferred() |
2078 | + def fake(): |
2079 | + """Fake.""" |
2080 | + deferred.callback(True) |
2081 | + return defer.succeed("foo") |
2082 | + self.sd.dbus.get_meta_queue = fake |
2083 | + |
2084 | + # send status changed to working in metadata |
2085 | + self.sd.on_sd_status_changed('QUEUE_MANAGER', 'description', False, |
2086 | + True, False, 'WORKING_ON_METADATA', |
2087 | + 'connection') |
2088 | return deferred |
2089 | |
2090 | def test_mq_polling_workinginboth(self): |
2091 | """Check that it polls mq while working in both.""" |
2092 | - |
2093 | # set the callback |
2094 | - self.sd._get_meta_queue = lambda *a: deferred.callback(True) |
2095 | - |
2096 | - # send signal with signature and structures like original syncdaemon |
2097 | - d = dict(name='QUEUE_MANAGER', queues='WORKING_ON_BOTH', |
2098 | - description='description', is_error='', is_connected='True', |
2099 | - is_online='', connection='conn') |
2100 | - self.send_signal(DBUS_IFACE_STATUS_NAME, 'StatusChanged', 'a{ss}', d) |
2101 | - |
2102 | deferred = defer.Deferred() |
2103 | + def fake(): |
2104 | + """Fake.""" |
2105 | + deferred.callback(True) |
2106 | + return defer.succeed("foo") |
2107 | + self.sd.dbus.get_meta_queue = fake |
2108 | + |
2109 | + # send status changed to working in metadata |
2110 | + self.sd.on_sd_status_changed('QUEUE_MANAGER', 'description', False, |
2111 | + True, False, 'WORKING_ON_BOTH', |
2112 | + 'connection') |
2113 | return deferred |
2114 | |
2115 | def test_mq_polling_untilfinish(self): |
2116 | """Check that it polls mq until no more is needed.""" |
2117 | - # prepare different status changed signals |
2118 | - d1 = dict(name='QUEUE_MANAGER', queues='WORKING_ON_BOTH', |
2119 | - description='description', is_error='', is_connected='True', |
2120 | - is_online='', connection='conn') |
2121 | - |
2122 | d2 = dict(name='QUEUE_MANAGER', queues='WORKING_ON_CONTENT', |
2123 | description='description', is_error='', is_connected='True', |
2124 | is_online='', connection='conn') |
2125 | @@ -402,61 +369,47 @@ |
2126 | # set the callback, and adjust the polling time to faster |
2127 | calls = [] |
2128 | def fake_get(*a): |
2129 | + """Fake get.""" |
2130 | calls.append(None) |
2131 | if len(calls) < 3: |
2132 | pass # no changes, should keep calling |
2133 | elif len(calls) == 3: |
2134 | - self.send_signal(DBUS_IFACE_STATUS_NAME, |
2135 | - 'StatusChanged', 'a{ss}', d2) |
2136 | + self.sd.on_sd_status_changed('QUEUE_MANAGER', 'description', |
2137 | + False, True, False, |
2138 | + 'WORKING_ON_CONTENT', 'connect') |
2139 | + |
2140 | # allow time to see if a mistaken call happens |
2141 | reactor.callLater(.5, deferred.callback, True) |
2142 | else: |
2143 | deferred.errback(ValueError("Too many calls")) |
2144 | - return defer.Deferred() |
2145 | + return defer.succeed("foo") |
2146 | |
2147 | - self.sd._get_meta_queue = fake_get |
2148 | + self.sd.dbus.get_meta_queue = fake_get |
2149 | self.sd._mq_poll_time = .1 |
2150 | |
2151 | - self.send_signal(DBUS_IFACE_STATUS_NAME, 'StatusChanged', 'a{ss}', d1) |
2152 | + self.sd.on_sd_status_changed('QUEUE_MANAGER', 'description', False, |
2153 | + True, False, 'WORKING_ON_BOTH', |
2154 | + 'connection') |
2155 | deferred = defer.Deferred() |
2156 | return deferred |
2157 | |
2158 | - def test_MQ_state_none(self): |
2159 | - """Check the MetaQueue info, being none.""" |
2160 | - self.assertEqual(len(self.sd.meta_queue), 0) |
2161 | + def test_MQ_state_nothing(self): |
2162 | + """Check the MetaQueue info, being nothing.""" |
2163 | + self.sd.dbus.get_meta_queue = lambda: defer.succeed([]) |
2164 | + self.sd._check_mq() |
2165 | + self.assertEqual(self.sd.meta_queue, []) |
2166 | |
2167 | def test_MQ_state_one(self): |
2168 | """Check the MetaQueue info, being one.""" |
2169 | - self.sd._process_mq(['ListShares']) |
2170 | - self.assertEqual(len(self.sd.meta_queue), 1) |
2171 | - |
2172 | - # check the data |
2173 | - mqit = self.sd.meta_queue[0] |
2174 | - self.assertEqual(mqit.operation, 'ListShares') |
2175 | - self.assertEqual(mqit.path, None) |
2176 | - self.assertEqual(mqit.share, None) |
2177 | - self.assertEqual(mqit.node, None) |
2178 | - |
2179 | - def test_MQ_state_several(self): |
2180 | - """Check the MetaQueue info, several calls, last one is bigger.""" |
2181 | - cmd1 = 'MakeDir(share_id=a, parent_id=b, name=c, marker=d)' |
2182 | - cmd2 = 'GetPublicFiles' |
2183 | - self.sd._process_mq([cmd1]) |
2184 | - self.sd._process_mq([cmd2]) |
2185 | - self.sd._process_mq([cmd1, cmd2]) |
2186 | - self.assertEqual(len(self.sd.meta_queue), 2) |
2187 | - |
2188 | - # check the data |
2189 | - mqit = self.sd.meta_queue[0] |
2190 | - self.assertEqual(mqit.operation, 'MakeDir') |
2191 | - self.assertEqual(mqit.path, '/?.../c') |
2192 | - self.assertEqual(mqit.share, 'a') |
2193 | - self.assertEqual(mqit.node, None) |
2194 | - mqit = self.sd.meta_queue[1] |
2195 | - self.assertEqual(mqit.operation, 'GetPublicFiles') |
2196 | - self.assertEqual(mqit.path, None) |
2197 | - self.assertEqual(mqit.share, None) |
2198 | - self.assertEqual(mqit.node, None) |
2199 | + self.sd.dbus.get_meta_queue = lambda: defer.succeed(['foo']) |
2200 | + self.sd._check_mq() |
2201 | + self.assertEqual(self.sd.meta_queue, ['foo']) |
2202 | + |
2203 | + def test_MQ_state_two(self): |
2204 | + """Check the MetaQueue info, two.""" |
2205 | + self.sd.dbus.get_meta_queue = lambda: defer.succeed(['foo', 'bar']) |
2206 | + self.sd._check_mq() |
2207 | + self.assertEqual(self.sd.meta_queue, ['foo', 'bar']) |
2208 | |
2209 | |
2210 | class StateTests(unittest.TestCase): |
2211 | @@ -519,95 +472,51 @@ |
2212 | f = lambda *a, **k: setattr(self, 'called', True) |
2213 | setattr(obj, method_name, f) |
2214 | |
2215 | - def test_defaults_are_callable(self): |
2216 | - """Check the attributes are callable.""" |
2217 | - meths = (self.sd._get_content_queue, self.sd._get_meta_queue, |
2218 | - self.sd._do_start, self.sd._do_quit, |
2219 | - self.sd._do_connect, self.sd._do_disconnect) |
2220 | - for meth in meths: |
2221 | - self.assertTrue(callable(meth), "Meth %r is not callable" % meth) |
2222 | - |
2223 | - def test_is_connected_yes(self): |
2224 | - """Check is_connected, True.""" |
2225 | - d = dict(name='name', description='description', is_error='', |
2226 | - is_connected='True', is_online='', queues='queues', |
2227 | - connection='connection') |
2228 | - self.sd._on_status_changed(d) |
2229 | - self.assertTrue(self.sd.current_state.is_connected) |
2230 | - |
2231 | - def test_is_connected_no(self): |
2232 | - """Check is_connected, False.""" |
2233 | - d = dict(name='name', description='description', is_error='', |
2234 | - is_connected='', is_online='', queues='queues', |
2235 | - connection='connection') |
2236 | - self.sd._on_status_changed(d) |
2237 | - self.assertFalse(self.sd.current_state.is_connected) |
2238 | - |
2239 | - def test_is_online_yes(self): |
2240 | - """Check is_online, True.""" |
2241 | - d = dict(name='name', description='description', is_error='', |
2242 | - is_connected='True', is_online='True', queues='queues', |
2243 | - connection='connection') |
2244 | - self.sd._on_status_changed(d) |
2245 | - self.assertTrue(self.sd.current_state.is_online) |
2246 | - |
2247 | - def test_is_online_no(self): |
2248 | - """Check is_online, False.""" |
2249 | - d = dict(name='name', description='description', is_error='', |
2250 | - is_connected='True', is_online='', queues='queues', |
2251 | - connection='connection') |
2252 | - self.sd._on_status_changed(d) |
2253 | - self.assertFalse(self.sd.current_state.is_online) |
2254 | - |
2255 | def test_is_started_yes(self): |
2256 | """Check is_started, True.""" |
2257 | # simulate the signal that indicates the name was registered |
2258 | - self.sd._on_name_owner_changed('com.ubuntuone.SyncDaemon', '', 'yes') |
2259 | + self.sd.on_sd_name_owner_changed(True) |
2260 | self.assertTrue(self.sd.current_state.is_started) |
2261 | |
2262 | def test_is_started_no(self): |
2263 | """Check is_started, False.""" |
2264 | - self.sd._on_name_owner_changed('com.ubuntuone.SyncDaemon', 'yes', '') |
2265 | + self.sd.on_sd_name_owner_changed(False) |
2266 | self.assertFalse(self.sd.current_state.is_started) |
2267 | |
2268 | def test_start(self): |
2269 | """Test start calls SD.""" |
2270 | - self.mpatch_called(self.sd, '_do_start') |
2271 | + self.mpatch_called(self.sd.dbus, 'start') |
2272 | self.sd.start() |
2273 | self.assertTrue(self.called) |
2274 | |
2275 | def test_quit(self): |
2276 | """Test quit calls SD.""" |
2277 | - self.mpatch_called(self.sd, '_do_quit') |
2278 | + self.mpatch_called(self.sd.dbus, 'quit') |
2279 | self.sd.quit() |
2280 | self.assertTrue(self.called) |
2281 | |
2282 | def test_connect(self): |
2283 | """Test connect calls SD.""" |
2284 | - self.mpatch_called(self.sd, '_do_connect') |
2285 | + self.mpatch_called(self.sd.dbus, 'connect') |
2286 | self.sd.connect() |
2287 | self.assertTrue(self.called) |
2288 | |
2289 | def test_disconnect(self): |
2290 | """Test disconnect calls SD.""" |
2291 | - self.mpatch_called(self.sd, '_do_disconnect') |
2292 | + self.mpatch_called(self.sd.dbus, 'disconnect') |
2293 | self.sd.disconnect() |
2294 | self.assertTrue(self.called) |
2295 | |
2296 | def test_on_started(self): |
2297 | """Called when SD started.""" |
2298 | self.flag_called(self.sd, 'on_started_callback') |
2299 | - |
2300 | - # simulate the signal that indicates the name was registered |
2301 | - self.sd._on_name_owner_changed('com.ubuntuone.SyncDaemon', '', 'yes') |
2302 | + self.sd.on_sd_name_owner_changed(True) |
2303 | self.assertTrue(self.called) |
2304 | |
2305 | def test_on_stopped(self): |
2306 | """Called when SD stopped.""" |
2307 | self.flag_called(self.sd, 'on_stopped_callback') |
2308 | - |
2309 | - # simulate the signal that indicates the name was registered |
2310 | - self.sd._on_name_owner_changed('com.ubuntuone.SyncDaemon', 'yes', '') |
2311 | + self.sd.on_sd_name_owner_changed(False) |
2312 | self.assertTrue(self.called) |
2313 | |
2314 | def test_on_connected(self): |
2315 | @@ -615,10 +524,8 @@ |
2316 | self.flag_called(self.sd, 'on_connected_callback') |
2317 | |
2318 | # first signal with connected in True |
2319 | - d = dict(name='name', description='description', is_error='', |
2320 | - is_connected='True', is_online='', queues='queues', |
2321 | - connection='connection') |
2322 | - self.sd._on_status_changed(d) |
2323 | + self.sd.on_sd_status_changed('name', 'description', False, True, |
2324 | + False, 'queues', 'connection') |
2325 | self.assertTrue(self.called) |
2326 | |
2327 | def test_on_disconnected(self): |
2328 | @@ -626,12 +533,10 @@ |
2329 | self.flag_called(self.sd, 'on_disconnected_callback') |
2330 | |
2331 | # connect and disconnect |
2332 | - d = dict(name='name', description='description', is_error='', |
2333 | - is_connected='True', is_online='', queues='queues', |
2334 | - connection='connection') |
2335 | - self.sd._on_status_changed(d) |
2336 | - d['is_connected'] = '' |
2337 | - self.sd._on_status_changed(d) |
2338 | + self.sd.on_sd_status_changed('name', 'description', False, True, |
2339 | + False, 'queues', 'connection') |
2340 | + self.sd.on_sd_status_changed('name', 'description', False, False, |
2341 | + False, 'queues', 'connection') |
2342 | self.assertTrue(self.called) |
2343 | |
2344 | def test_on_online(self): |
2345 | @@ -639,10 +544,8 @@ |
2346 | self.flag_called(self.sd, 'on_online_callback') |
2347 | |
2348 | # first signal with online in True |
2349 | - d = dict(name='name', description='description', is_error='', |
2350 | - is_connected='True', is_online='True', queues='queues', |
2351 | - connection='connection') |
2352 | - self.sd._on_status_changed(d) |
2353 | + self.sd.on_sd_status_changed('name', 'description', False, True, |
2354 | + True, 'queues', 'connection') |
2355 | self.assertTrue(self.called) |
2356 | |
2357 | def test_on_offline(self): |
2358 | @@ -650,52 +553,23 @@ |
2359 | self.flag_called(self.sd, 'on_offline_callback') |
2360 | |
2361 | # go online and then offline |
2362 | - d = dict(name='name', description='description', is_error='', |
2363 | - is_connected='True', is_online='True', queues='queues', |
2364 | - connection='connection') |
2365 | - self.sd._on_status_changed(d) |
2366 | - d['is_online'] = '' |
2367 | - self.sd._on_status_changed(d) |
2368 | + self.sd.on_sd_status_changed('name', 'description', False, True, |
2369 | + True, 'queues', 'connection') |
2370 | + self.sd.on_sd_status_changed('name', 'description', False, True, |
2371 | + False, 'queues', 'connection') |
2372 | self.assertTrue(self.called) |
2373 | |
2374 | |
2375 | -class MementoHandler(logging.Handler): |
2376 | - """A handler class which store logging records in a list.""" |
2377 | - |
2378 | - def __init__(self, *args, **kwargs): |
2379 | - """Create the instance, and add a records attribute.""" |
2380 | - logging.Handler.__init__(self, *args, **kwargs) |
2381 | - self.records = [] |
2382 | - |
2383 | - def emit(self, record): |
2384 | - """Just add the record to self.records.""" |
2385 | - self.records.append(record) |
2386 | - |
2387 | - def check(self, level, msg): |
2388 | - """Check that something is logged.""" |
2389 | - for rec in self.records: |
2390 | - if rec.levelname == level and rec.message == msg: |
2391 | - return True |
2392 | - raise ValueError("Log not found (%s) %r" % (level, msg)) |
2393 | - |
2394 | |
2395 | class TestLogs(unittest.TestCase): |
2396 | """Test logging.""" |
2397 | |
2398 | def setUp(self): |
2399 | """Set up.""" |
2400 | - self.handler = MementoHandler() |
2401 | - logging.getLogger('magicicada.syncdaemon').addHandler(self.handler) |
2402 | - self.handler.setLevel(logging.DEBUG) |
2403 | - self.sd = SyncDaemon() |
2404 | - |
2405 | - # don't use real SD! |
2406 | - self.sd._get_content_queue = lambda: defer.Deferred() |
2407 | - self.sd._get_meta_queue = lambda: defer.Deferred() |
2408 | - self.sd._do_start = NO_OP |
2409 | - self.sd._do_quit = NO_OP |
2410 | - self.sd._do_connect = NO_OP |
2411 | - self.sd._do_disconnect = NO_OP |
2412 | + self.hdlr = MementoHandler() |
2413 | + logging.getLogger('magicicada.syncdaemon').addHandler(self.hdlr) |
2414 | + self.hdlr.setLevel(logging.DEBUG) |
2415 | + self.sd = SyncDaemon(FakeDBusInterface) |
2416 | |
2417 | def tearDown(self): |
2418 | """Shut down!""" |
2419 | @@ -703,100 +577,109 @@ |
2420 | |
2421 | def test_instancing(self): |
2422 | """Just logged SD instancing.""" |
2423 | - self.assertTrue(self.handler.check('INFO', |
2424 | - "SyncDaemon interface started!")) |
2425 | + self.assertTrue(self.hdlr.check_inf("SyncDaemon interface started!")) |
2426 | |
2427 | def test_shutdown(self): |
2428 | """Log when SD shutdowns.""" |
2429 | self.sd.shutdown() |
2430 | - self.assertTrue(self.handler.check('INFO', |
2431 | - "SyncDaemon interface going down")) |
2432 | + self.assertTrue(self.hdlr.check_inf("SyncDaemon interface going down")) |
2433 | + |
2434 | + @defer.inlineCallbacks |
2435 | + def test_initial_value(self): |
2436 | + """Log the initial filling.""" |
2437 | + yield self.sd._get_initial_data() |
2438 | + self.assertTrue(self.hdlr.check_inf("Getting initial data")) |
2439 | |
2440 | def test_start(self): |
2441 | """Log the call to start.""" |
2442 | self.sd.start() |
2443 | - self.assertTrue(self.handler.check('INFO', |
2444 | - "Starting u1.SD")) |
2445 | + self.assertTrue(self.hdlr.check_inf("Starting u1.SD")) |
2446 | |
2447 | def test_quit(self): |
2448 | """Log the call to quit.""" |
2449 | self.sd.quit() |
2450 | - self.assertTrue(self.handler.check('INFO', |
2451 | - "Stopping u1.SD")) |
2452 | + self.assertTrue(self.hdlr.check_inf("Stopping u1.SD")) |
2453 | |
2454 | def test_connect(self): |
2455 | """Log the call to connect.""" |
2456 | self.sd.connect() |
2457 | - self.assertTrue(self.handler.check('INFO', |
2458 | - "Telling u1.SD to connect")) |
2459 | + self.assertTrue(self.hdlr.check_inf("Telling u1.SD to connect")) |
2460 | |
2461 | def test_disconnect(self): |
2462 | """Log the call to disconnect.""" |
2463 | self.sd.disconnect() |
2464 | - self.assertTrue(self.handler.check('INFO', |
2465 | - "Telling u1.SD to disconnect")) |
2466 | + self.assertTrue(self.hdlr.check_inf("Telling u1.SD to disconnect")) |
2467 | |
2468 | def test_check_mq_true(self): |
2469 | """Log the MQ check when it asks for info.""" |
2470 | self.sd.current_state._set(name='QUEUE_MANAGER', |
2471 | queues='WORKING_ON_METADATA') |
2472 | self.sd._check_mq() |
2473 | - self.assertTrue(self.handler.check('INFO', |
2474 | - "Asking for MQ information")) |
2475 | + self.assertTrue(self.hdlr.check_inf("Asking for MQ information")) |
2476 | |
2477 | def test_check_mq_noreally(self): |
2478 | """Log the MQ check when it should not work.""" |
2479 | self.sd.current_state._set(name='QUEUE_MANAGER', |
2480 | queues='WORKING_ON_CONTENT') |
2481 | self.sd._check_mq() |
2482 | - self.assertTrue(self.handler.check('INFO', |
2483 | + self.assertTrue(self.hdlr.check_inf( |
2484 | "Check MQ called but States not in MQ")) |
2485 | |
2486 | - def test_process_mq_called(self): |
2487 | - """Log that process_mq is called.""" |
2488 | - self.sd._process_mq([]) |
2489 | - self.assertTrue(self.handler.check('INFO', "Processing MQ data")) |
2490 | - |
2491 | - def test_process_mq_new_data(self): |
2492 | - """Log that process_mq has new data.""" |
2493 | - self.sd._process_mq(['AccountInquiry']) |
2494 | - self.assertTrue(self.handler.check('INFO', "New MQ data to process")) |
2495 | - self.assertTrue(self.handler.check('DEBUG', |
2496 | - "Processing MQ data: u'AccountInquiry'")) |
2497 | - self.assertTrue(self.handler.check('DEBUG', |
2498 | - " parsed: QueueData(operation=" |
2499 | - "'AccountInquiry', path=None, share=None, node=None)")) |
2500 | - |
2501 | - def test_process_cq_called(self): |
2502 | - """Log that process_cq is called.""" |
2503 | - self.sd._process_cq([]) |
2504 | - self.assertTrue(self.handler.check('INFO', "Processing CQ data")) |
2505 | - |
2506 | - def test_process_cq_new_data(self): |
2507 | + def test_meta_queue_changed(self): |
2508 | + """Log that MQ has new data.""" |
2509 | + self.sd.dbus.get_meta_queue = lambda: defer.succeed(['foo']) |
2510 | + self.sd.current_state._set(name='QUEUE_MANAGER', |
2511 | + queues='WORKING_ON_METADATA') |
2512 | + self.sd._check_mq() |
2513 | + self.assertTrue(self.hdlr.check_inf("SD Meta Queue changed: 1 items")) |
2514 | + |
2515 | + def test_content_queue_changed(self): |
2516 | """Log that process_cq has new data.""" |
2517 | - c = dict(operation='op', path='pth', share='shr', node='n') |
2518 | - self.sd._process_cq([c]) |
2519 | - self.assertTrue(self.handler.check('INFO', "New CQ data to process")) |
2520 | - self.assertTrue(self.handler.check('DEBUG', |
2521 | - "Processing CQ data: %r" % c)) |
2522 | + self.sd.dbus.get_content_queue = lambda: defer.succeed(['foo']) |
2523 | + self.sd.on_sd_content_queue_changed() |
2524 | + self.assertTrue(self.hdlr.check_inf("SD Content Queue changed")) |
2525 | + self.assertTrue(self.hdlr.check_inf( |
2526 | + "Content Queue info is new! 1 items")) |
2527 | |
2528 | def test_on_status_changed(self): |
2529 | """Log status changed.""" |
2530 | - d = dict(name='name', description='description', is_error='', |
2531 | - is_connected='True', is_online='', queues='queues', |
2532 | - connection='connection') |
2533 | - self.sd._on_status_changed(d) |
2534 | - self.assertTrue(self.handler.check('INFO', "New status info from SD")) |
2535 | - self.assertTrue(self.handler.check('DEBUG', |
2536 | - "New status from SD: %r" % d)) |
2537 | + self.sd.on_sd_status_changed('name', 'description', False, True, |
2538 | + False, 'queues', 'connection') |
2539 | + self.assertTrue(self.hdlr.check_inf("SD Status changed")) |
2540 | + self.assertTrue(self.hdlr.check_dbg(" new status: name=u'name', " |
2541 | + "description=u'description', is_error=False, is_connected=True, " |
2542 | + "is_online=False, queues=u'queues', connection=u'connection'")) |
2543 | |
2544 | - def test_on_content_queue_changed(self): |
2545 | - """Log content queue changed.""" |
2546 | - self.sd._on_content_queue_changed(None) |
2547 | - self.assertTrue(self.handler.check('INFO', "CQ changed in u1.SD!")) |
2548 | + def test_folders_changed(self): |
2549 | + """Log when folders changed.""" |
2550 | + self.sd.on_sd_folders_changed() |
2551 | + self.assertTrue(self.hdlr.check_inf("SD Folders changed")) |
2552 | |
2553 | def test_on_name_owner_changed(self): |
2554 | """Log name owner changed.""" |
2555 | - self.sd._on_name_owner_changed('com.ubuntuone.SyncDaemon', 'old', '') |
2556 | - self.assertTrue(self.handler.check('INFO', |
2557 | - "DBus informing about SD: old: u'old' new: u''")) |
2558 | + self.sd.on_sd_name_owner_changed(True) |
2559 | + self.assertTrue(self.hdlr.check_inf("SD Name Owner changed: True")) |
2560 | + |
2561 | + |
2562 | +class FoldersTests(BaseTest): |
2563 | + """Folders checking.""" |
2564 | + |
2565 | + def test_foldercreated_callback(self): |
2566 | + """Gets the new data after the folders changed.""" |
2567 | + # set the callback |
2568 | + called = [] |
2569 | + self.sd.dbus.get_folders = lambda: called.append(True) |
2570 | + |
2571 | + # they changed! |
2572 | + self.sd.on_sd_folders_changed() |
2573 | + |
2574 | + # test |
2575 | + self.assertTrue(called) |
2576 | + |
2577 | + @defer.inlineCallbacks |
2578 | + def test_initial_value(self): |
2579 | + """Fills the folder info initially.""" |
2580 | + called = [] |
2581 | + self.sd.dbus.get_folders = lambda: called.append(True) |
2582 | + yield self.sd._get_initial_data() |
2583 | + self.assertTrue(called) |
Very nice!