Merge lp:~nataliabidart/ubuntuone-control-panel/add-file-sync-buttons into lp:ubuntuone-control-panel

Proposed by Natalia Bidart
Status: Merged
Approved by: Natalia Bidart
Approved revision: 58
Merged at revision: 47
Proposed branch: lp:~nataliabidart/ubuntuone-control-panel/add-file-sync-buttons
Merge into: lp:ubuntuone-control-panel
Diff against target: 1129 lines (+724/-161)
9 files modified
ubuntuone/controlpanel/backend.py (+38/-2)
ubuntuone/controlpanel/dbus_client.py (+24/-0)
ubuntuone/controlpanel/dbus_service.py (+109/-1)
ubuntuone/controlpanel/gtk/gui.py (+160/-65)
ubuntuone/controlpanel/gtk/tests/__init__.py (+2/-0)
ubuntuone/controlpanel/gtk/tests/test_gui.py (+191/-85)
ubuntuone/controlpanel/integrationtests/test_dbus_client_sd.py (+33/-1)
ubuntuone/controlpanel/integrationtests/test_dbus_service.py (+80/-0)
ubuntuone/controlpanel/tests/test_backend.py (+87/-7)
To merge this branch: bzr merge lp:~nataliabidart/ubuntuone-control-panel/add-file-sync-buttons
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Roman Yepishev (community) fieldtest Approve
Review via email: mp+46681@code.launchpad.net

Commit message

Added a button to file sync status to manage the files service (LP: #693373).

Description of the change

To test, open 2 terminals pointing to this branch and run:

terminal 1: DEBUG=True PYTHONPATH=. ./bin/ubuntuone-control-panel-backend
terminal 2: DEBUG=True PYTHONPATH=. ./bin/ubuntuone-control-panel-gtk

And play with the top right corner, you'll get syncdaemon status and buttons to manage the service.

NOTE: if you stop syncdaemon from the "outside" (u1sdtool -q), you need to run this branch as syncdaemon to be able to grab the quiting state change from it: lp:~nataliabidart/ubuntuone-client/send-status-changed-when-quitting

To post a comment you must log in.
57. By Natalia Bidart

WAITING is actually disconnected.

58. By Natalia Bidart

Added tests for file sync button sensitivity.

Revision history for this message
Roman Yepishev (rye) wrote :

<rye> nessita, i mean why an "Action" is tied to the "Link" presentation? It's like if we had a music player with Stop, Play, Pause underlined labels instead of buttons...
<nessita> rye: is a design thing, putting a raw button calls too much user attention and that button is not 'important', since the user should almost never require using them
<nessita> rye: also, a button there gets mixed (in the eye) with the buttons in the tab bar
<nessita> (Dashboard, Folders, etc)
<nessita> rye: all the sync actions are links
<rye> nessita, blank tooltips that causes - http://ubuntuone.com/p/Z3a/
<nessita> rye: that's the button uri :-/
<nessita> rye: maybe I can set the name of the button as uri... not sure how much that can break
<nessita> rye: let me investigate a bit

review: Needs Fixing (fieldtest)
Revision history for this message
Roman Yepishev (rye) wrote :

Ok, approving since we need to have these buttons, filed LP:704895

review: Approve (fieldtest)
Revision history for this message
Roberto Alsina (ralsina) wrote :

+1, looks good

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntuone/controlpanel/backend.py'
2--- ubuntuone/controlpanel/backend.py 2011-01-06 20:33:15 +0000
3+++ ubuntuone/controlpanel/backend.py 2011-01-19 12:21:44 +0000
4@@ -43,6 +43,7 @@
5 FILE_SYNC_ERROR = 'file-sync-error'
6 FILE_SYNC_IDLE = 'file-sync-idle'
7 FILE_SYNC_STARTING = 'file-sync-starting'
8+FILE_SYNC_STOPPED = 'file-sync-stopped'
9 FILE_SYNC_SYNCING = 'file-sync-syncing'
10 FILE_SYNC_UNKNOWN = 'file-sync-unknown'
11
12@@ -88,9 +89,11 @@
13 is_error = bool(status['is_error'])
14 is_synching = bool(status['is_connected'])
15 is_idle = bool(status['is_online']) and status['queues'] == 'IDLE'
16- is_disconnected = status['name'] == 'READY' and \
17- 'Not User' in status['connection']
18+ is_disconnected = status['name'] == 'WAITING' or \
19+ (status['name'] == 'READY' and \
20+ 'Not User' in status['connection'])
21 is_starting = status['name'] in ('INIT', 'LOCAL_RESCAN', 'READY')
22+ is_stopped = status['name'] == 'SHUTDOWN'
23
24 if is_error:
25 result[STATUS_KEY] = FILE_SYNC_ERROR
26@@ -102,6 +105,8 @@
27 result[STATUS_KEY] = FILE_SYNC_DISCONNECTED
28 elif is_starting:
29 result[STATUS_KEY] = FILE_SYNC_STARTING
30+ elif is_stopped:
31+ result[STATUS_KEY] = FILE_SYNC_STOPPED
32 else:
33 logger.warning('file_sync_status: unknown (got %r)', status)
34 result[STATUS_KEY] = FILE_SYNC_UNKNOWN
35@@ -289,6 +294,37 @@
36
37 @log_call(logger.debug)
38 @inlineCallbacks
39+ def connect_files(self):
40+ """Connect the files service."""
41+ yield dbus_client.connect_file_sync()
42+
43+ @log_call(logger.debug)
44+ @inlineCallbacks
45+ def disconnect_files(self):
46+ """Disconnect the files service."""
47+ yield dbus_client.disconnect_file_sync()
48+
49+ @log_call(logger.debug)
50+ @inlineCallbacks
51+ def restart_files(self):
52+ """restart the files service."""
53+ yield dbus_client.stop_file_sync()
54+ yield dbus_client.start_file_sync()
55+
56+ @log_call(logger.debug)
57+ @inlineCallbacks
58+ def start_files(self):
59+ """start the files service."""
60+ yield dbus_client.start_file_sync()
61+
62+ @log_call(logger.debug)
63+ @inlineCallbacks
64+ def stop_files(self):
65+ """stop the files service."""
66+ yield dbus_client.stop_file_sync()
67+
68+ @log_call(logger.debug)
69+ @inlineCallbacks
70 def volumes_info(self):
71 """Get the volumes info."""
72 result = yield dbus_client.get_folders()
73
74=== modified file 'ubuntuone/controlpanel/dbus_client.py'
75--- ubuntuone/controlpanel/dbus_client.py 2011-01-04 21:28:51 +0000
76+++ ubuntuone/controlpanel/dbus_client.py 2011-01-19 12:21:44 +0000
77@@ -309,3 +309,27 @@
78 def set_files_sync_enabled(enabled):
79 """Set the file sync service to be 'enabled'."""
80 yield SyncDaemonTool(bus=dbus.SessionBus()).enable_files_sync(enabled)
81+
82+
83+@defer.inlineCallbacks
84+def connect_file_sync():
85+ """Connect the file sync service."""
86+ yield SyncDaemonTool(bus=dbus.SessionBus()).connect()
87+
88+
89+@defer.inlineCallbacks
90+def disconnect_file_sync():
91+ """Disconnect the file sync service."""
92+ yield SyncDaemonTool(bus=dbus.SessionBus()).disconnect()
93+
94+
95+@defer.inlineCallbacks
96+def start_file_sync():
97+ """Start the file sync service."""
98+ yield SyncDaemonTool(bus=dbus.SessionBus()).start()
99+
100+
101+@defer.inlineCallbacks
102+def stop_file_sync():
103+ """Stop the file sync service."""
104+ yield SyncDaemonTool(bus=dbus.SessionBus()).quit()
105
106=== modified file 'ubuntuone/controlpanel/dbus_service.py'
107--- ubuntuone/controlpanel/dbus_service.py 2011-01-06 20:33:15 +0000
108+++ ubuntuone/controlpanel/dbus_service.py 2011-01-19 12:21:44 +0000
109@@ -31,7 +31,8 @@
110 DBUS_PREFERENCES_IFACE)
111 from ubuntuone.controlpanel.backend import (
112 ControlBackend, FILE_SYNC_DISABLED, FILE_SYNC_DISCONNECTED,
113- FILE_SYNC_ERROR, FILE_SYNC_IDLE, FILE_SYNC_STARTING, FILE_SYNC_SYNCING,
114+ FILE_SYNC_ERROR, FILE_SYNC_IDLE, FILE_SYNC_STARTING, FILE_SYNC_STOPPED,
115+ FILE_SYNC_SYNCING,
116 MSG_KEY, STATUS_KEY,
117 )
118 from ubuntuone.controlpanel.logger import setup_logging, log_call
119@@ -196,6 +197,8 @@
120 self.FileSyncStatusDisabled(msg)
121 elif status == FILE_SYNC_STARTING:
122 self.FileSyncStatusStarting(msg)
123+ elif status == FILE_SYNC_STOPPED:
124+ self.FileSyncStatusStopped(msg)
125 elif status == FILE_SYNC_DISCONNECTED:
126 self.FileSyncStatusDisconnected(msg)
127 elif status == FILE_SYNC_SYNCING:
128@@ -231,6 +234,11 @@
129
130 @log_call(logger.debug)
131 @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="s")
132+ def FileSyncStatusStopped(self, msg):
133+ """The file sync service is stopped."""
134+
135+ @log_call(logger.debug)
136+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="s")
137 def FileSyncStatusDisconnected(self, msg):
138 """The file sync service is waiting for user to request connection."""
139
140@@ -298,6 +306,106 @@
141
142 @log_call(logger.debug)
143 @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="")
144+ def connect_files(self):
145+ """Connect the files service."""
146+ d = self.backend.connect_files()
147+ d.addCallback(lambda _: self.FilesConnected())
148+ d.addErrback(transform_failure(self.FilesConnectError))
149+
150+ @log_call(logger.debug)
151+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE)
152+ def FilesConnected(self):
153+ """The files service is connected."""
154+
155+ @log_call(logger.error)
156+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}")
157+ def FilesConnectError(self, error):
158+ """Problem connecting the files service."""
159+
160+ #---
161+
162+ @log_call(logger.debug)
163+ @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="")
164+ def disconnect_files(self):
165+ """Disconnect the files service."""
166+ d = self.backend.disconnect_files()
167+ d.addCallback(lambda _: self.FilesDisconnected())
168+ d.addErrback(transform_failure(self.FilesDisconnectError))
169+
170+ @log_call(logger.debug)
171+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE)
172+ def FilesDisconnected(self):
173+ """The files service is disconnected."""
174+
175+ @log_call(logger.error)
176+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}")
177+ def FilesDisconnectError(self, error):
178+ """Problem disconnecting the files service."""
179+
180+ #---
181+
182+ @log_call(logger.debug)
183+ @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="")
184+ def restart_files(self):
185+ """Restart the files service."""
186+ d = self.backend.restart_files()
187+ d.addCallback(lambda _: self.FilesRestarted())
188+ d.addErrback(transform_failure(self.FilesRestartError))
189+
190+ @log_call(logger.debug)
191+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE)
192+ def FilesRestarted(self):
193+ """The files service is restarted."""
194+
195+ @log_call(logger.error)
196+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}")
197+ def FilesRestartError(self, error):
198+ """Problem restarting the files service."""
199+
200+ #---
201+
202+ @log_call(logger.debug)
203+ @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="")
204+ def start_files(self):
205+ """Start the files service."""
206+ d = self.backend.start_files()
207+ d.addCallback(lambda _: self.FilesStarted())
208+ d.addErrback(transform_failure(self.FilesStartError))
209+
210+ @log_call(logger.debug)
211+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE)
212+ def FilesStarted(self):
213+ """The files service is started."""
214+
215+ @log_call(logger.error)
216+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}")
217+ def FilesStartError(self, error):
218+ """Problem starting the files service."""
219+
220+ #---
221+
222+ @log_call(logger.debug)
223+ @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="")
224+ def stop_files(self):
225+ """Stop the files service."""
226+ d = self.backend.stop_files()
227+ d.addCallback(lambda _: self.FilesStopped())
228+ d.addErrback(transform_failure(self.FilesStopError))
229+
230+ @log_call(logger.debug)
231+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE)
232+ def FilesStopped(self):
233+ """The files service is stopped."""
234+
235+ @log_call(logger.error)
236+ @signal(dbus_interface=DBUS_PREFERENCES_IFACE, signature="a{ss}")
237+ def FilesStopError(self, error):
238+ """Problem stopping the files service."""
239+
240+ #---
241+
242+ @log_call(logger.debug)
243+ @method(dbus_interface=DBUS_PREFERENCES_IFACE, in_signature="")
244 def volumes_info(self):
245 """Find out the volumes info for the logged in user."""
246 d = self.backend.volumes_info()
247
248=== modified file 'ubuntuone/controlpanel/gtk/gui.py'
249--- ubuntuone/controlpanel/gtk/gui.py 2011-01-06 20:18:29 +0000
250+++ ubuntuone/controlpanel/gtk/gui.py 2011-01-19 12:21:44 +0000
251@@ -1048,40 +1048,41 @@
252 self.on_error()
253
254
255-class ManagementPanel(gtk.VBox, ControlPanelMixin):
256- """The management panel.
257-
258- The user can manage dashboard, folders, devices and services.
259-
260- """
261-
262- QUOTA_LABEL = _('%(used)s used of %(total)s (%(percentage).1f%%)')
263- FILE_SYNC_DISABLED = _('File synchronization service is not enabled.')
264- FILE_SYNC_STARTING = _('File synchronization service is starting,\n'
265- 'please wait...')
266- FILE_SYNC_DISCONNECTED = _('File synchronization service is ready,\nplease'
267- ' connect it to access your personal cloud. ')
268- FILE_SYNC_SYNCING = _('File synchronization service is fully functional,\n'
269- 'performing synchronization now...')
270- FILE_SYNC_IDLE = _('File synchronization service is idle,\n'
271- 'all the files are synchronized.')
272- FILE_SYNC_ERROR = _('File synchronization status can not be retrieved.')
273+class FileSyncStatus(gtk.HBox, ControlPanelMixin):
274+ """A file sync status widget."""
275+
276+ FILE_SYNC_DISABLED = _('File synchronization is disabled.')
277+ FILE_SYNC_STARTING = _('File synchronization starting...')
278+ FILE_SYNC_STOPPED = _('File synchronization is stopped.')
279+ FILE_SYNC_DISCONNECTED = _('File synchronization is disconnected.')
280+ FILE_SYNC_SYNCING = _('Synchronization in progress...')
281+ FILE_SYNC_IDLE = _('All files up-to-date.')
282+ FILE_SYNC_ERROR = _('File synchronization error.')
283+
284+ CONNECT = _('Connect')
285+ DISCONNECT = _('Disconnect')
286+ ENABLE = _('Enable')
287+ RESTART = _('Restart')
288+ START = _('Start')
289+ STOP = _('Stop')
290
291 def __init__(self):
292- gtk.VBox.__init__(self)
293- ControlPanelMixin.__init__(self, filename='management.ui')
294- self.add(self.itself)
295- self.show()
296-
297- self.backend.connect_to_signal('AccountInfoReady',
298- self.on_account_info_ready)
299- self.backend.connect_to_signal('AccountInfoError',
300- self.on_account_info_error)
301+ gtk.HBox.__init__(self)
302+ ControlPanelMixin.__init__(self)
303+
304+ self.label = LabelLoading(LOADING, fg_color=DEFAULT_FG)
305+ self.pack_start(self.label, expand=False)
306+
307+ self.button = gtk.LinkButton(uri='')
308+ self.button.connect('clicked', self._on_button_clicked)
309+ self.pack_start(self.button, expand=False)
310
311 self.backend.connect_to_signal('FileSyncStatusDisabled',
312 self.on_file_sync_status_disabled)
313 self.backend.connect_to_signal('FileSyncStatusStarting',
314 self.on_file_sync_status_starting)
315+ self.backend.connect_to_signal('FileSyncStatusStopped',
316+ self.on_file_sync_status_stopped)
317 self.backend.connect_to_signal('FileSyncStatusDisconnected',
318 self.on_file_sync_status_disconnected)
319 self.backend.connect_to_signal('FileSyncStatusSyncing',
320@@ -1090,13 +1091,144 @@
321 self.on_file_sync_status_idle)
322 self.backend.connect_to_signal('FileSyncStatusError',
323 self.on_file_sync_status_error)
324+ self.backend.connect_to_signal('FilesStartError',
325+ self.on_files_start_error)
326+
327+ self.backend.file_sync_status(reply_handler=NO_OP,
328+ error_handler=error_handler)
329+ self.show_all()
330+
331+ def _update_status(self, msg, action, callback, icon=None, color=None):
332+ """Update the status info."""
333+ if icon is not None:
334+ foreground = '' if color is None else 'foreground="%s"' % color
335+ msg = '<span %s>%s</span> %s' % (foreground, icon, msg)
336+ self.label.set_markup(msg)
337+ self.label.stop()
338+
339+ self.button.set_label(action)
340+ self.button.set_sensitive(True)
341+ self.button.set_data('callback', callback)
342+
343+ def _on_button_clicked(self, button):
344+ """Button was clicked, act accordingly the label."""
345+ button.set_visited(False)
346+ button.set_sensitive(False)
347+ button.get_data('callback')(button)
348+
349+ @log_call(logger.info)
350+ def on_file_sync_status_disabled(self, msg):
351+ """Backend notifies of file sync status being disabled."""
352+ self._update_status(self.FILE_SYNC_DISABLED,
353+ self.ENABLE, self.on_enable_clicked,
354+ '✘', 'red')
355+
356+ @log_call(logger.info)
357+ def on_file_sync_status_starting(self, msg):
358+ """Backend notifies of file sync status being starting."""
359+ self._update_status(self.FILE_SYNC_STARTING,
360+ self.STOP, self.on_stop_clicked,
361+ '⇅', ORANGE)
362+
363+ @log_call(logger.info)
364+ def on_file_sync_status_stopped(self, msg):
365+ """Backend notifies of file sync being stopped."""
366+ self._update_status(self.FILE_SYNC_STOPPED,
367+ self.START, self.on_start_clicked,
368+ '✘', 'red')
369+
370+ @log_call(logger.info)
371+ def on_file_sync_status_disconnected(self, msg):
372+ """Backend notifies of file sync status being ready."""
373+ self._update_status(self.FILE_SYNC_DISCONNECTED,
374+ self.CONNECT, self.on_connect_clicked,
375+ '✘', 'red')
376+
377+ @log_call(logger.info)
378+ def on_file_sync_status_syncing(self, msg):
379+ """Backend notifies of file sync status being syncing."""
380+ self._update_status(self.FILE_SYNC_SYNCING,
381+ self.DISCONNECT, self.on_disconnect_clicked,
382+ '⇅', ORANGE)
383+
384+ @log_call(logger.info)
385+ def on_file_sync_status_idle(self, msg):
386+ """Backend notifies of file sync status being idle."""
387+ self._update_status(self.FILE_SYNC_IDLE,
388+ self.DISCONNECT, self.on_disconnect_clicked,
389+ '✔', 'green')
390+
391+ @log_call(logger.error)
392+ def on_file_sync_status_error(self, error_dict=None):
393+ """Backend notifies of an error when fetching file sync status."""
394+ self._update_status(WARNING_MARKUP % self.FILE_SYNC_ERROR,
395+ self.RESTART, self.on_restart_clicked)
396+
397+ @log_call(logger.error)
398+ def on_files_start_error(self, error_dict=None):
399+ """Backend notifies of an error when starting the files service."""
400+ # service is probably disabled, ask for status to backend
401+ self.backend.file_sync_status(reply_handler=NO_OP,
402+ error_handler=error_handler)
403+
404+ def on_connect_clicked(self, button=None):
405+ """User requested connection."""
406+ self.backend.connect_files(reply_handler=NO_OP,
407+ error_handler=error_handler)
408+
409+ def on_disconnect_clicked(self, button=None):
410+ """User requested disconnection."""
411+ self.backend.disconnect_files(reply_handler=NO_OP,
412+ error_handler=error_handler)
413+
414+ def on_enable_clicked(self, button=None):
415+ """User requested enable the service."""
416+ self.backend.enable_files(reply_handler=NO_OP,
417+ error_handler=error_handler)
418+
419+ def on_restart_clicked(self, button=None):
420+ """User requested restart the service."""
421+ self.backend.restart_files(reply_handler=NO_OP,
422+ error_handler=error_handler)
423+
424+ def on_start_clicked(self, button=None):
425+ """User requested start the service."""
426+ self.backend.start_files(reply_handler=NO_OP,
427+ error_handler=error_handler)
428+
429+ def on_stop_clicked(self, button=None):
430+ """User requested stop the service."""
431+ self.backend.stop_files(reply_handler=NO_OP,
432+ error_handler=error_handler)
433+
434+
435+class ManagementPanel(gtk.VBox, ControlPanelMixin):
436+ """The management panel.
437+
438+ The user can manage dashboard, folders, devices and services.
439+
440+ """
441+
442+ QUOTA_LABEL = _('%(used)s used of %(total)s (%(percentage).1f%%)')
443+
444+ def __init__(self):
445+ gtk.VBox.__init__(self)
446+ ControlPanelMixin.__init__(self, filename='management.ui')
447+ self.add(self.itself)
448+ self.show()
449+
450+ self.backend.connect_to_signal('AccountInfoReady',
451+ self.on_account_info_ready)
452+ self.backend.connect_to_signal('AccountInfoError',
453+ self.on_account_info_error)
454
455 self.header.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(DEFAULT_BG))
456
457+ self.quota_progressbar.set_sensitive(False)
458 self.quota_label = LabelLoading(LOADING, fg_color=DEFAULT_FG)
459 self.quota_box.pack_start(self.quota_label, expand=False)
460
461- self.status_label = LabelLoading(LOADING, fg_color=DEFAULT_FG)
462+ self.status_label = FileSyncStatus()
463 self.status_box.pack_end(self.status_label, expand=False)
464
465 self.dashboard = DashboardPanel()
466@@ -1131,17 +1263,10 @@
467 fraction = data.get('percentage', 0.0) / 100
468 self.quota_progressbar.set_fraction(fraction)
469
470- def _update_status(self, msg):
471- """Update the status info."""
472- self.status_label.set_markup(msg)
473- self.status_label.stop()
474-
475 def load(self):
476 """Load the account info and file sync status list."""
477 self.backend.account_info(reply_handler=NO_OP,
478 error_handler=error_handler)
479- self.backend.file_sync_status(reply_handler=NO_OP,
480- error_handler=error_handler)
481 self.dashboard_button.clicked()
482
483 @log_call(logger.debug)
484@@ -1158,36 +1283,6 @@
485 """Backend notifies of an error when fetching account info."""
486 self._update_quota(WARNING_MARKUP % VALUE_ERROR)
487
488- @log_call(logger.info)
489- def on_file_sync_status_disabled(self, msg):
490- """Backend notifies of file sync status being disabled."""
491- self._update_status(self.FILE_SYNC_DISABLED)
492-
493- @log_call(logger.info)
494- def on_file_sync_status_starting(self, msg):
495- """Backend notifies of file sync status being starting."""
496- self._update_status(self.FILE_SYNC_STARTING)
497-
498- @log_call(logger.info)
499- def on_file_sync_status_disconnected(self, msg):
500- """Backend notifies of file sync status being ready."""
501- self._update_status(self.FILE_SYNC_DISCONNECTED)
502-
503- @log_call(logger.info)
504- def on_file_sync_status_syncing(self, msg):
505- """Backend notifies of file sync status being syncing."""
506- self._update_status(self.FILE_SYNC_SYNCING)
507-
508- @log_call(logger.info)
509- def on_file_sync_status_idle(self, msg):
510- """Backend notifies of file sync status being idle."""
511- self._update_status(self.FILE_SYNC_IDLE)
512-
513- @log_call(logger.error)
514- def on_file_sync_status_error(self, error_dict=None):
515- """Backend notifies of an error when fetching file sync status."""
516- self._update_status(WARNING_MARKUP % self.FILE_SYNC_ERROR)
517-
518
519 gobject.signal_new('credentials-found', OverviewPanel,
520 gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
521
522=== modified file 'ubuntuone/controlpanel/gtk/tests/__init__.py'
523--- ubuntuone/controlpanel/gtk/tests/__init__.py 2011-01-05 21:04:07 +0000
524+++ ubuntuone/controlpanel/gtk/tests/__init__.py 2011-01-19 12:21:44 +0000
525@@ -131,6 +131,8 @@
526 'volumes_info', 'change_volume_settings', # volumes
527 'replications_info', 'change_replication_settings', # replications
528 'file_sync_status', 'enable_files', 'disable_files', # files
529+ 'connect_files', 'disconnect_files',
530+ 'restart_files', 'start_files', 'stop_files',
531 ]
532
533
534
535=== modified file 'ubuntuone/controlpanel/gtk/tests/test_gui.py'
536--- ubuntuone/controlpanel/gtk/tests/test_gui.py 2011-01-06 20:18:29 +0000
537+++ ubuntuone/controlpanel/gtk/tests/test_gui.py 2011-01-19 12:21:44 +0000
538@@ -1795,6 +1795,179 @@
539 self.assert_warning_correct(self.ui.message, gui.VALUE_ERROR)
540
541
542+class FileSyncStatusTestCase(ControlPanelMixinTestCase):
543+ """Test case for a file sync status widget."""
544+
545+ klass = gui.FileSyncStatus
546+
547+ def assert_status_correct(self, status, action=None, callback=None):
548+ """The shown status is correct.
549+
550+ * The ui's label shows 'status'.
551+ * If action is not None, the ui's button shows that 'action' as label
552+ and when clicking it, 'self._set_called' gets executed.
553+ * If action is None, the ui's button should be hidden.
554+
555+ """
556+ self.assertTrue(self.ui.label.get_visible())
557+ self.assertFalse(self.ui.label.active)
558+ self.assertTrue(self.ui.label.get_label().endswith(status))
559+
560+ self.assertTrue(self.ui.button.is_sensitive())
561+ self.assertFalse(self.ui.button.get_visited())
562+
563+ if action is not None:
564+ self.assertTrue(self.ui.button.get_visible())
565+ self.assertTrue(self.ui.button.get_sensitive())
566+ self.assertEqual(self.ui.button.get_label(), action)
567+
568+ self.ui.button.clicked()
569+ self.assertFalse(self.ui.button.get_visited())
570+ self.assertFalse(self.ui.button.get_sensitive())
571+ self.assertEqual(self._called, ((self.ui.button,), {}))
572+ else:
573+ self.assertFalse(self.ui.button.get_visible())
574+
575+ def test_is_a_box(self):
576+ """Inherits from gtk.Box."""
577+ self.assertIsInstance(self.ui, gui.gtk.Box)
578+
579+ def test_startup_visibility(self):
580+ """The widget is visible at startup."""
581+ self.assertTrue(self.ui.get_visible(),
582+ 'must be visible at startup.')
583+
584+ def test_label(self):
585+ """The label is packed."""
586+ self.assertIsInstance(self.ui.label, gui.LabelLoading)
587+ self.assertTrue(self.ui.label.active)
588+ self.assertIn(self.ui.label, self.ui.get_children())
589+
590+ def test_button(self):
591+ """The button is packed."""
592+ self.assertIn(self.ui.button, self.ui.get_children())
593+
594+ def test_backend_file_sync_signals(self):
595+ """The proper signals are connected to the backend."""
596+ matches = (
597+ # status
598+ ('FileSyncStatusDisabled', [self.ui.on_file_sync_status_disabled]),
599+ ('FileSyncStatusStarting', [self.ui.on_file_sync_status_starting]),
600+ ('FileSyncStatusStopped', [self.ui.on_file_sync_status_stopped]),
601+ ('FileSyncStatusDisconnected',
602+ [self.ui.on_file_sync_status_disconnected]),
603+ ('FileSyncStatusSyncing', [self.ui.on_file_sync_status_syncing]),
604+ ('FileSyncStatusIdle', [self.ui.on_file_sync_status_idle]),
605+ ('FileSyncStatusError', [self.ui.on_file_sync_status_error]),
606+ ('FilesStartError', [self.ui.on_files_start_error]),
607+ )
608+ for sig, handlers in matches:
609+ self.assertEqual(self.ui.backend._signals[sig], handlers)
610+
611+ def test_file_sync_status_is_requested(self):
612+ """The file sync status is requested to the backend."""
613+ self.assert_backend_called('file_sync_status', ())
614+
615+ def test_on_file_sync_status_disabled(self):
616+ """The file sync is disabled."""
617+ self.patch(self.ui, 'on_enable_clicked', self._set_called)
618+ self.ui.on_file_sync_status_disabled('msg')
619+
620+ self.assert_status_correct(self.ui.FILE_SYNC_DISABLED,
621+ action=self.ui.ENABLE)
622+
623+ def test_on_file_sync_status_starting(self):
624+ """The file sync status is starting."""
625+ self.patch(self.ui, 'on_stop_clicked', self._set_called)
626+ self.ui.on_file_sync_status_starting('msg')
627+
628+ self.assert_status_correct(self.ui.FILE_SYNC_STARTING,
629+ action=self.ui.STOP)
630+
631+ def test_on_file_sync_status_stopped(self):
632+ """The file sync is stopped."""
633+ self.patch(self.ui, 'on_start_clicked', self._set_called)
634+ self.ui.on_file_sync_status_stopped('msg')
635+
636+ self.assert_status_correct(self.ui.FILE_SYNC_STOPPED,
637+ action=self.ui.START)
638+
639+ def test_on_file_sync_status_disconnected(self):
640+ """The file sync status is disconnected."""
641+ self.patch(self.ui, 'on_connect_clicked', self._set_called)
642+ self.ui.on_file_sync_status_disconnected('msg')
643+
644+ self.assert_status_correct(self.ui.FILE_SYNC_DISCONNECTED,
645+ action=self.ui.CONNECT)
646+
647+ def test_on_file_sync_status_syncing(self):
648+ """The file sync status is syncing."""
649+ self.patch(self.ui, 'on_disconnect_clicked', self._set_called)
650+ self.ui.on_file_sync_status_syncing('msg')
651+
652+ self.assert_status_correct(self.ui.FILE_SYNC_SYNCING,
653+ action=self.ui.DISCONNECT)
654+
655+ def test_on_file_sync_status_idle(self):
656+ """The file sync status is idle."""
657+ self.patch(self.ui, 'on_disconnect_clicked', self._set_called)
658+ self.ui.on_file_sync_status_idle('msg')
659+
660+ self.assert_status_correct(self.ui.FILE_SYNC_IDLE,
661+ action=self.ui.DISCONNECT)
662+
663+ def test_on_file_sync_status_error(self):
664+ """The file sync status couldn't be retrieved."""
665+ self.patch(self.ui, 'on_restart_clicked', self._set_called)
666+ self.ui.on_file_sync_status_error({'error_msg': 'error msg'})
667+
668+ msg = gui.WARNING_MARKUP % self.ui.FILE_SYNC_ERROR
669+ self.assert_status_correct(msg, action=self.ui.RESTART)
670+
671+ def test_on_files_start_error(self):
672+ """The files service could not be started."""
673+ self.ui.backend._called.clear()
674+ self.ui.on_files_start_error({'error_msg': 'error msg'})
675+
676+ self.assert_backend_called('file_sync_status', ())
677+
678+ def test_on_connect_clicked(self):
679+ """User requested connection."""
680+ self.ui.on_connect_clicked(self.ui.button)
681+
682+ self.assert_backend_called('connect_files', ())
683+
684+ def test_on_disconnect_clicked(self):
685+ """User requested disconnection."""
686+ self.ui.on_disconnect_clicked(self.ui.button)
687+
688+ self.assert_backend_called('disconnect_files', ())
689+
690+ def test_on_enable_clicked(self):
691+ """User requested enable the service."""
692+ self.ui.on_enable_clicked(self.ui.button)
693+
694+ self.assert_backend_called('enable_files', ())
695+
696+ def test_on_restart_clicked(self):
697+ """User requested restart the service."""
698+ self.ui.on_restart_clicked(self.ui.button)
699+
700+ self.assert_backend_called('restart_files', ())
701+
702+ def test_on_start_clicked(self):
703+ """User requested start the service."""
704+ self.ui.on_start_clicked(self.ui.button)
705+
706+ self.assert_backend_called('start_files', ())
707+
708+ def test_on_stop_clicked(self):
709+ """User requested stop the service."""
710+ self.ui.on_stop_clicked(self.ui.button)
711+
712+ self.assert_backend_called('stop_files', ())
713+
714+
715 class ManagementPanelTestCase(ControlPanelMixinTestCase):
716 """The test suite for the management panel."""
717
718@@ -1925,93 +2098,26 @@
719 self.assertIsInstance(self.ui.quota_label, gui.LabelLoading)
720 self.assertIn(self.ui.quota_label, self.ui.quota_box.get_children())
721
722- def test_file_sync_status_placeholder_is_loading(self):
723- """Placeholders for file sync label is a Loading widget."""
724- self.assertIsInstance(self.ui.status_label, gui.LabelLoading)
725+ def test_on_account_info_ready(self):
726+ """The account info is processed when ready."""
727+ self.ui.on_account_info_ready(FAKE_ACCOUNT_INFO)
728+ self.assert_account_info_correct(FAKE_ACCOUNT_INFO)
729+
730+ for widget in (self.ui.quota_label,):
731+ self.assertFalse(widget.active)
732+
733+ def test_on_account_info_error(self):
734+ """The account info couldn't be retrieved."""
735+ self.ui.on_account_info_error()
736+ for widget in (self.ui.quota_label,):
737+ self.assert_warning_correct(widget, gui.VALUE_ERROR)
738+ self.assertFalse(widget.active)
739+
740+ def test_file_sync_status(self):
741+ """The file sync status is shown correctly."""
742+ self.assertIsInstance(self.ui.status_label, gui.FileSyncStatus)
743 self.assertIn(self.ui.status_label, self.ui.status_box.get_children())
744
745- def test_on_account_info_ready(self):
746- """The account info is processed when ready."""
747- self.ui.on_account_info_ready(FAKE_ACCOUNT_INFO)
748- self.assert_account_info_correct(FAKE_ACCOUNT_INFO)
749-
750- for widget in (self.ui.quota_label,):
751- self.assertFalse(widget.active)
752-
753- def test_on_account_info_error(self):
754- """The account info couldn't be retrieved."""
755- self.ui.on_account_info_error()
756- for widget in (self.ui.quota_label,):
757- self.assert_warning_correct(widget, gui.VALUE_ERROR)
758- self.assertFalse(widget.active)
759-
760- def test_backend_file_sync_signals(self):
761- """The proper signals are connected to the backend."""
762- matches = (
763- ('FileSyncStatusDisabled', [self.ui.on_file_sync_status_disabled]),
764- ('FileSyncStatusStarting', [self.ui.on_file_sync_status_starting]),
765- ('FileSyncStatusDisconnected',
766- [self.ui.on_file_sync_status_disconnected]),
767- ('FileSyncStatusSyncing', [self.ui.on_file_sync_status_syncing]),
768- ('FileSyncStatusIdle', [self.ui.on_file_sync_status_idle]),
769- ('FileSyncStatusError', [self.ui.on_file_sync_status_error]),
770- )
771- for sig, handlers in matches:
772- self.assertEqual(self.ui.backend._signals[sig], handlers)
773-
774- def test_file_sync_status_is_requested_on_load(self):
775- """The file sync status is requested to the backend."""
776- self.ui.load()
777- self.assert_backend_called('file_sync_status', ())
778-
779- def test_on_file_sync_status_disabled(self):
780- """The file sync is disabled."""
781- self.ui.on_file_sync_status_disabled('msg')
782-
783- self.assertFalse(self.ui.status_label.active)
784- self.assertEqual(self.ui.status_label.get_text(),
785- self.ui.FILE_SYNC_DISABLED)
786-
787- def test_on_file_sync_status_starting(self):
788- """The file sync status is starting."""
789- self.ui.on_file_sync_status_starting('msg')
790-
791- self.assertFalse(self.ui.status_label.active)
792- self.assertEqual(self.ui.status_label.get_text(),
793- self.ui.FILE_SYNC_STARTING)
794-
795- def test_on_file_sync_status_disconnected(self):
796- """The file sync status is disconnected."""
797- self.ui.on_file_sync_status_disconnected('msg')
798-
799- self.assertFalse(self.ui.status_label.active)
800- self.assertEqual(self.ui.status_label.get_text(),
801- self.ui.FILE_SYNC_DISCONNECTED)
802-
803- def test_on_file_sync_status_syncing(self):
804- """The file sync status is syncing."""
805- self.ui.on_file_sync_status_syncing('msg')
806-
807- self.assertFalse(self.ui.status_label.active)
808- self.assertEqual(self.ui.status_label.get_text(),
809- self.ui.FILE_SYNC_SYNCING)
810-
811- def test_on_file_sync_status_idle(self):
812- """The file sync status is idle."""
813- self.ui.on_file_sync_status_idle('msg')
814-
815- self.assertFalse(self.ui.status_label.active)
816- self.assertEqual(self.ui.status_label.get_text(),
817- self.ui.FILE_SYNC_IDLE)
818-
819- def test_on_file_sync_status_error(self):
820- """The file sync status couldn't be retrieved."""
821- self.ui.on_file_sync_status_error({'error_msg': 'error msg'})
822-
823- self.assert_warning_correct(self.ui.status_label,
824- self.ui.FILE_SYNC_ERROR)
825- self.assertFalse(self.ui.status_label.active)
826-
827 def test_local_device_removed_is_emitted(self):
828 """Signal local-device-removed is sent when DevicesPanel emits it."""
829 self.ui.connect('local-device-removed', self._set_called)
830
831=== modified file 'ubuntuone/controlpanel/integrationtests/test_dbus_client_sd.py'
832--- ubuntuone/controlpanel/integrationtests/test_dbus_client_sd.py 2010-12-13 22:13:05 +0000
833+++ ubuntuone/controlpanel/integrationtests/test_dbus_client_sd.py 2011-01-19 12:21:44 +0000
834@@ -507,7 +507,39 @@
835 self.patch(dbus_client.SyncDaemonTool, 'enable_files_sync',
836 self._set_called)
837 expected = object()
838- # set the opposite value
839+ # set some unique value
840 yield dbus_client.set_files_sync_enabled(expected)
841
842 self.assertEqual(self._called, ((expected,), {}))
843+
844+ @inlineCallbacks
845+ def test_connect_file_sync(self):
846+ """Set if file sync is enabled or not."""
847+ self.patch(dbus_client.SyncDaemonTool, 'connect', self._set_called)
848+ yield dbus_client.connect_file_sync()
849+
850+ self.assertEqual(self._called, ((), {}))
851+
852+ @inlineCallbacks
853+ def test_disconnect_file_sync(self):
854+ """Set if file sync is enabled or not."""
855+ self.patch(dbus_client.SyncDaemonTool, 'disconnect', self._set_called)
856+ yield dbus_client.disconnect_file_sync()
857+
858+ self.assertEqual(self._called, ((), {}))
859+
860+ @inlineCallbacks
861+ def test_start_file_sync(self):
862+ """Set if file sync is enabled or not."""
863+ self.patch(dbus_client.SyncDaemonTool, 'start', self._set_called)
864+ yield dbus_client.start_file_sync()
865+
866+ self.assertEqual(self._called, ((), {}))
867+
868+ @inlineCallbacks
869+ def test_stop_file_sync(self):
870+ """Set if file sync is enabled or not."""
871+ self.patch(dbus_client.SyncDaemonTool, 'quit', self._set_called)
872+ yield dbus_client.stop_file_sync()
873+
874+ self.assertEqual(self._called, ((), {}))
875
876=== modified file 'ubuntuone/controlpanel/integrationtests/test_dbus_service.py'
877--- ubuntuone/controlpanel/integrationtests/test_dbus_service.py 2011-01-06 20:33:15 +0000
878+++ ubuntuone/controlpanel/integrationtests/test_dbus_service.py 2011-01-19 12:21:44 +0000
879@@ -163,6 +163,26 @@
880 """Disable files service."""
881 return self._process(None)
882
883+ def connect_files(self):
884+ """Connect files service."""
885+ return self._process(None)
886+
887+ def disconnect_files(self):
888+ """Disconnect files service."""
889+ return self._process(None)
890+
891+ def restart_files(self):
892+ """Restart the files service."""
893+ return self._process(None)
894+
895+ def start_files(self):
896+ """Start the files service."""
897+ return self._process(None)
898+
899+ def stop_files(self):
900+ """Stop the files service."""
901+ return self._process(None)
902+
903 def volumes_info(self):
904 """Get the user volumes info."""
905 return self._process(SAMPLE_VOLUMES_INFO)
906@@ -435,6 +455,61 @@
907 self.backend.disable_files)
908 return self.assert_correct_method_call(*args)
909
910+ def test_connect_files(self):
911+ """Connect files service."""
912+
913+ def got_signal():
914+ """The correct signal was received."""
915+ self.deferred.callback("success")
916+
917+ args = ("FilesConnected", "FilesConnectError", got_signal,
918+ self.backend.connect_files)
919+ return self.assert_correct_method_call(*args)
920+
921+ def test_disconnect_files(self):
922+ """Disconnect files service."""
923+
924+ def got_signal():
925+ """The correct signal was received."""
926+ self.deferred.callback("success")
927+
928+ args = ("FilesDisconnected", "FilesDisconnectError", got_signal,
929+ self.backend.disconnect_files)
930+ return self.assert_correct_method_call(*args)
931+
932+ def test_restart_files(self):
933+ """Restart files service."""
934+
935+ def got_signal():
936+ """The correct signal was received."""
937+ self.deferred.callback("success")
938+
939+ args = ("FilesRestarted", "FilesRestartError", got_signal,
940+ self.backend.restart_files)
941+ return self.assert_correct_method_call(*args)
942+
943+ def test_start_files(self):
944+ """Start files service."""
945+
946+ def got_signal():
947+ """The correct signal was received."""
948+ self.deferred.callback("success")
949+
950+ args = ("FilesStarted", "FilesStartError", got_signal,
951+ self.backend.start_files)
952+ return self.assert_correct_method_call(*args)
953+
954+ def test_stop_files(self):
955+ """Stop files service."""
956+
957+ def got_signal():
958+ """The correct signal was received."""
959+ self.deferred.callback("success")
960+
961+ args = ("FilesStopped", "FilesStopError", got_signal,
962+ self.backend.stop_files)
963+ return self.assert_correct_method_call(*args)
964+
965 def test_volumes_info(self):
966 """The volumes info is reported."""
967
968@@ -589,6 +664,11 @@
969 args = (dbus_service.FILE_SYNC_STARTING, "FileSyncStatusStarting")
970 return self.assert_correct_status_signal(*args)
971
972+ def test_file_sync_status_stopped(self):
973+ """The file sync status is reported properly."""
974+ args = (dbus_service.FILE_SYNC_STOPPED, "FileSyncStatusStopped")
975+ return self.assert_correct_status_signal(*args)
976+
977 def test_file_sync_status_disconnected(self):
978 """The file sync status is reported properly."""
979 args = (dbus_service.FILE_SYNC_DISCONNECTED,
980
981=== modified file 'ubuntuone/controlpanel/tests/test_backend.py'
982--- ubuntuone/controlpanel/tests/test_backend.py 2011-01-06 20:33:15 +0000
983+++ ubuntuone/controlpanel/tests/test_backend.py 2011-01-19 12:21:44 +0000
984@@ -33,6 +33,7 @@
985 FILE_SYNC_ERROR,
986 FILE_SYNC_IDLE,
987 FILE_SYNC_STARTING,
988+ FILE_SYNC_STOPPED,
989 FILE_SYNC_SYNCING,
990 FILE_SYNC_UNKNOWN,
991 MSG_KEY, STATUS_KEY,
992@@ -85,6 +86,7 @@
993 }
994 status_changed_handler = None
995 subscribed_folders = []
996+ actions = []
997
998 def get_credentials(self):
999 """Return the mock credentials."""
1000@@ -124,6 +126,22 @@
1001 """Set the file sync service to be 'enabled'."""
1002 MockDBusClient.file_sync = enabled
1003
1004+ def connect_file_sync(self):
1005+ """Connect files service."""
1006+ MockDBusClient.actions.append('connect')
1007+
1008+ def disconnect_file_sync(self):
1009+ """Disconnect file_sync service."""
1010+ MockDBusClient.actions.append('disconnect')
1011+
1012+ def start_file_sync(self):
1013+ """Start the file_sync service."""
1014+ MockDBusClient.actions.append('start')
1015+
1016+ def stop_file_sync(self):
1017+ """Stop the file_sync service."""
1018+ MockDBusClient.actions.append('stop')
1019+
1020 def get_folders(self):
1021 """Grab list of folders."""
1022 return SAMPLE_FOLDERS
1023@@ -487,6 +505,16 @@
1024 yield self.assert_correct_status(FILE_SYNC_DISCONNECTED)
1025
1026 @inlineCallbacks
1027+ def test_disconnected_when_waiting(self):
1028+ """The syncdaemon status is processed and emitted."""
1029+ MockDBusClient.status = {
1030+ 'is_error': '', 'is_online': '', 'is_connected': '',
1031+ 'connection': 'With User With Network', 'queues': '',
1032+ 'name': 'WAITING', 'description': 'what a long wait!',
1033+ }
1034+ yield self.assert_correct_status(FILE_SYNC_DISCONNECTED)
1035+
1036+ @inlineCallbacks
1037 def test_syncing_if_online(self):
1038 """The syncdaemon status is processed and emitted."""
1039 MockDBusClient.status = {
1040@@ -520,6 +548,17 @@
1041 yield self.assert_correct_status(FILE_SYNC_IDLE)
1042
1043 @inlineCallbacks
1044+ def test_stopped(self):
1045+ """The syncdaemon status is processed and emitted."""
1046+ MockDBusClient.status = {
1047+ 'is_error': '', 'is_online': '', 'is_connected': '',
1048+ 'name': 'SHUTDOWN', 'connection': '',
1049+ 'queues': 'IDLE',
1050+ 'description': 'something nice',
1051+ }
1052+ yield self.assert_correct_status(FILE_SYNC_STOPPED)
1053+
1054+ @inlineCallbacks
1055 def test_unknown(self):
1056 """The syncdaemon status is processed and emitted."""
1057 MockDBusClient.status = {
1058@@ -547,23 +586,64 @@
1059 self.assertEqual(self._called, ((expected_status,), {}))
1060
1061
1062-class BackendSyncEnabledTestCase(BackendBasicTestCase):
1063- """Syncdaemon enable/disable for the backend."""
1064-
1065+class BackendFileSyncOpsTestCase(BackendBasicTestCase):
1066+ """Syncdaemon operations for the backend."""
1067+
1068+ def setUp(self):
1069+ super(BackendFileSyncOpsTestCase, self).setUp()
1070+ MockDBusClient.actions = []
1071+
1072+ @inlineCallbacks
1073 def test_enable_files(self):
1074 """Files service is enabled."""
1075- self.be.disable_files()
1076+ yield self.be.disable_files()
1077
1078- self.be.enable_files()
1079+ yield self.be.enable_files()
1080 self.assertTrue(MockDBusClient.file_sync)
1081
1082+ @inlineCallbacks
1083 def test_disable_files(self):
1084 """Files service is disabled."""
1085- self.be.enable_files()
1086+ yield self.be.enable_files()
1087
1088- self.be.disable_files()
1089+ yield self.be.disable_files()
1090 self.assertFalse(MockDBusClient.file_sync)
1091
1092+ @inlineCallbacks
1093+ def test_connect_files(self):
1094+ """Connect files service."""
1095+ yield self.be.connect_files()
1096+
1097+ self.assertEqual(MockDBusClient.actions, ['connect'])
1098+
1099+ @inlineCallbacks
1100+ def test_disconnect_files(self):
1101+ """Disconnect files service."""
1102+ yield self.be.disconnect_files()
1103+
1104+ self.assertEqual(MockDBusClient.actions, ['disconnect'])
1105+
1106+ @inlineCallbacks
1107+ def test_restart_files(self):
1108+ """Restart the files service."""
1109+ yield self.be.restart_files()
1110+
1111+ self.assertEqual(MockDBusClient.actions, ['stop', 'start'])
1112+
1113+ @inlineCallbacks
1114+ def test_start_files(self):
1115+ """Start the files service."""
1116+ yield self.be.start_files()
1117+
1118+ self.assertEqual(MockDBusClient.actions, ['start'])
1119+
1120+ @inlineCallbacks
1121+ def test_stop_files(self):
1122+ """Stop the files service."""
1123+ yield self.be.stop_files()
1124+
1125+ self.assertEqual(MockDBusClient.actions, ['stop'])
1126+
1127
1128 class BackendReplicationsTestCase(BackendBasicTestCase):
1129 """Replications tests for the backend."""

Subscribers

People subscribed via source and target branches