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