Merge lp:~charlesk/keeper/upate-status-properties-pt-1 into lp:keeper

Proposed by Charles Kerr
Status: Merged
Merge reported by: Charles Kerr
Merged at revision: not available
Proposed branch: lp:~charlesk/keeper/upate-status-properties-pt-1
Merge into: lp:keeper
Diff against target: 373 lines (+71/-77)
7 files modified
src/qdbus-stubs/com.canonical.keeper.User.xml (+13/-15)
src/service/backup-choices.cpp (+8/-18)
tests/com_canonical_keeper.py (+42/-29)
tests/dbusmock/keeper-template-test.cpp (+0/-3)
tests/unit/metadata-providers/user-dirs-test.cpp (+1/-3)
tests/unit/tar/keeper-tar-create-test.cpp (+0/-1)
tests/utils/keeper-dbusmock-fixture.h (+7/-8)
To merge this branch: bzr merge lp:~charlesk/keeper/upate-status-properties-pt-1
Reviewer Review Type Date Requested Status
Xavi Garcia (community) Approve
Unity API Team Pending
Review via email: mp+301424@code.launchpad.net

Commit message

Update what properties are provided by the com.canonical.keeper.User methods.

Description of the change

Update what properties are provided by the com.canonical.keeper.User methods.

The low-hanging fruit from https://trello.com/c/dCHzIxCG/58-com-canonical-keeper-user-should-support-design-s-specs.

We don't have anything implementing the state property maps in the service itself, so the card can't be completed yet. But now I can at least test the dbusmock template for an error state when the helper errors out :)

To post a comment you must log in.
Revision history for this message
Xavi Garcia (xavi-garcia-mena) wrote :

I'm not sure if after landing this I will have conflicts with my branch:
https://code.launchpad.net/~xavi-garcia-mena/keeper/using-cwd-and-user-startbackup/+merge/301496

It looks good and your branch was first, so... let's merge it. :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/qdbus-stubs/com.canonical.keeper.User.xml'
2--- src/qdbus-stubs/com.canonical.keeper.User.xml 2016-07-07 21:42:19 +0000
3+++ src/qdbus-stubs/com.canonical.keeper.User.xml 2016-07-28 19:50:41 +0000
4@@ -14,8 +14,7 @@
5 as a map from opaque backup keys to key/value pairs
6 of the choice’s properties,
7 including a ‘display-name’ string,
8- ‘type’ string (‘application’, ‘system-data’, or ‘folder’)
9- and, when possible, an ‘icon’ symbolic icon string.</doc:para>
10+ ‘type’ string (‘application’, ‘system-data’, or ‘folder’).</doc:para>
11 <doc:para>The choices should be presented to the user,
12 and the keys of those selected should be passed
13 to StartBackup().</doc:para>
14@@ -71,19 +70,18 @@
15 <doc:description>
16 <doc:para>Provides state information so the user interface can show
17 the progress of backup or restore tasks.</doc:para>
18- <doc:para>State is a map of opaque backup keys to property maps,
19- which will contain a 'display-name' string and 'action' int32
20- whose possible values are queued(0), saving(1),
21- restoring(2), complete(3), stopped(4)</doc:para>
22- <doc:para>Some property maps may also have an 'item' string
23- and a 'percent-done' double [0..1.0].
24- For example if these are set to (1, “Photos”, 0.36),
25- the user interface could show “Backing up Photos (36%)”.
26- Clients should gracefully handle missing properties;
27- eg a missing percent-done could instead show
28- “Backing up Photos”.</doc:para>
29- <doc:para>A failed task's property map may also contain an 'error'
30- string if set by the backup helpers.</doc:para>
31+ <doc:para>State is a map of opaque backup keys to property maps.
32+ The property maps include:
33+ * 'action' (string): tells what the task is doing right now.
34+ Possible values are 'queued', 'saving', 'restoring',
35+ 'cancelled', 'failed', and 'complete'
36+ * 'display-name' (string): human-readable task name, e.g. "Pictures"
37+ * 'percent-done' (double): how much of this task is complete
38+ * 'speed' (int32): bytes per second
39+ </doc:para>
40+ <doc:para>If a task's 'action' state is 'failed' the property map also includes:
41+ * 'error' (string): a human-readable error message
42+ </doc:para>
43 </doc:description>
44 </doc:doc>
45 </property>
46
47=== modified file 'src/service/backup-choices.cpp'
48--- src/service/backup-choices.cpp 2016-07-07 14:04:38 +0000
49+++ src/service/backup-choices.cpp 2016-07-28 19:50:41 +0000
50@@ -59,12 +59,10 @@
51 //
52
53 const auto type_key = QStringLiteral("type");
54- const auto icon_key = QStringLiteral("icon");
55 const auto system_data_str = QStringLiteral("system-data");
56 {
57 Metadata m(generate_new_uuid(), "System Data"); // FIXME: how to i18n in a Qt DBus service?
58 m.set_property(type_key, system_data_str);
59- m.set_property(icon_key, QStringLiteral("folder-system"));
60 ret.push_back(m);
61 }
62
63@@ -129,10 +127,6 @@
64 if (version != QJsonValue::Undefined)
65 m.set_property(version_key, version.toString());
66
67- const auto icon = o[icon_key];
68- if (icon != QJsonValue::Undefined)
69- m.set_property(icon_key, icon.toString());
70-
71 ret.push_back(m);
72 }
73 }
74@@ -142,22 +136,19 @@
75 // XDG User Directories
76 //
77
78- const struct {
79- QStandardPaths::StandardLocation location;
80- QString icon;
81- } standard_locations[] = {
82- { QStandardPaths::DocumentsLocation, QStringLiteral("folder-documents") },
83- { QStandardPaths::MoviesLocation, QStringLiteral("folder-movies") },
84- { QStandardPaths::PicturesLocation, QStringLiteral("folder-pictures") },
85- { QStandardPaths::MusicLocation, QStringLiteral("folder-music") }
86+ const std::array<QStandardPaths::StandardLocation,4> standard_locations = {
87+ QStandardPaths::DocumentsLocation,
88+ QStandardPaths::MoviesLocation,
89+ QStandardPaths::PicturesLocation,
90+ QStandardPaths::MusicLocation
91 };
92
93 const auto path_key = QStringLiteral("path");
94 const auto user_folder_str = QStringLiteral("folder");
95- for (const auto& sl : standard_locations)
96+ for (const auto& location : standard_locations)
97 {
98- const auto name = QStandardPaths::displayName(sl.location);
99- const auto locations = QStandardPaths::standardLocations(sl.location);
100+ const auto name = QStandardPaths::displayName(location);
101+ const auto locations = QStandardPaths::standardLocations(location);
102 if (locations.empty())
103 {
104 qWarning() << "unable to find path for" << name;
105@@ -168,7 +159,6 @@
106 Metadata m(keystr, name);
107 m.set_property(path_key, locations.front());
108 m.set_property(type_key, user_folder_str);
109- m.set_property(icon_key, sl.icon);
110 ret.push_back(m);
111 }
112 }
113
114=== modified file 'tests/com_canonical_keeper.py'
115--- tests/com_canonical_keeper.py 2016-07-21 04:21:47 +0000
116+++ tests/com_canonical_keeper.py 2016-07-28 19:50:41 +0000
117@@ -5,6 +5,7 @@
118 import socket
119 import subprocess
120 import sys
121+import time
122 from dbusmock import OBJECT_MANAGER_IFACE, mockobject
123 from gi.repository import GLib
124
125@@ -36,17 +37,19 @@
126 MAIN_OBJ = SERVICE_PATH
127 SYSTEM_BUS = False
128
129-ACTION_QUEUED = 0
130-ACTION_SAVING = 1
131-ACTION_RESTORING = 2
132-ACTION_COMPLETE = 3
133-ACTION_STOPPED = 4
134+ACTION_QUEUED = 'queued'
135+ACTION_SAVING = 'saving'
136+ACTION_RESTORING = 'restoring'
137+ACTION_CANCELLED = 'cancelled'
138+ACTION_FAILED = 'failed'
139+ACTION_COMPLETE = 'complete'
140
141+KEY_ACTION = 'action'
142 KEY_CTIME = 'ctime'
143 KEY_BLOB = 'blob-data'
144 KEY_HELPER = 'helper-exec'
145-KEY_ICON = 'icon'
146 KEY_NAME = 'display-name'
147+KEY_SPEED = 'speed'
148 KEY_SIZE = 'size'
149 KEY_SUBTYPE = 'subtype'
150 KEY_TYPE = 'type'
151@@ -179,21 +182,9 @@
152 def user_build_state(user):
153 """Returns a generated state dictionary.
154
155- State is a map of opaque backup keys to property maps,
156- which will contain a 'display-name' string and 'action' int
157- whose possible values are queued(0), saving(1),
158- restoring(2), complete(3), and stopped(4).
159-
160- Some property maps may also have an 'item' string
161- and a 'percent-done' double [0..1.0].
162- For example if these are set to (1, "Photos", 0.36),
163- the user interface could show "Backing up Photos (36%)".
164- Clients should gracefully handle missing properties;
165- eg a missing percent-done could instead show
166- "Backing up Photos".
167-
168- A failed task's property map may also contain an 'error'
169- string if set by the backup helpers.
170+ State is a map of opaque backup keys to property maps.
171+ See the documentation for com.canonical.keeper.User's
172+ State() method for more information.
173 """
174
175 tasks_states = {}
176@@ -208,9 +199,9 @@
177 action = ACTION_RESTORING
178 elif uuid in user.remaining_tasks:
179 action = ACTION_QUEUED
180- else: # FIXME: 'ACTION_STOPPED' not handled yet
181+ else: # fixme: handle ACTION_CANCELLED, ACTION_FAILED
182 action = ACTION_COMPLETE
183- task_state['action'] = dbus.Int32(action)
184+ task_state[KEY_ACTION] = dbus.String(action)
185
186 # get the task's display-name
187 choice = user.backup_choices.get(uuid, None)
188@@ -221,7 +212,22 @@
189 display_name = choice.get(KEY_NAME, None)
190 task_state[KEY_NAME] = dbus.String(display_name)
191
192+ # speed
193+ helper = mockobject.objects[HELPER_PATH]
194+ if (uuid == user.current_task) and helper.work:
195+ n_secs = 2
196+ n_bytes = 0
197+ too_old = time.time() - n_secs
198+ for key in helper.work.bytes_per_second:
199+ if key > too_old:
200+ n_bytes += helper.work.bytes_per_second[key]
201+ bytes_per_second = n_bytes / n_secs
202+ else:
203+ bytes_per_second = 0
204+ task_state[KEY_SPEED] = dbus.Int32(bytes_per_second)
205+
206 # FIXME: use a real percentage here
207+ # FIXME: handle ACTION_CANCELLED, ACTION_FAILED
208 if action == ACTION_COMPLETE:
209 percent_done = dbus.Double(1.0)
210 elif action == ACTION_SAVING or action == ACTION_RESTORING:
211@@ -256,6 +262,7 @@
212 n_left = None
213 sock = None
214 uuid = None
215+ bytes_per_second = None
216
217
218 def helper_periodic_func(helper):
219@@ -265,10 +272,15 @@
220
221 # try to read a bit
222 chunk = helper.work.sock.recv(4096*2)
223- if len(chunk):
224+ chunk_len = len(chunk)
225+ if chunk_len:
226 helper.work.chunks.append(chunk)
227- helper.work.n_left -= len(chunk)
228- helper.log('got %s bytes; %s left' % (len(chunk), helper.work.n_left))
229+ helper.work.n_left -= chunk_len
230+ key = int(time.time())
231+ old_n_bytes = helper.work.bytes_per_second.get(key, 0)
232+ new_n_bytes = old_n_bytes + chunk_len
233+ helper.work.bytes_per_second[key] = new_n_bytes
234+ helper.log('got %s bytes; %s left' % (chunk_len, helper.work.n_left))
235
236 # cleanup if done
237 done = helper.work.n_left <= 0
238@@ -284,7 +296,7 @@
239 user.start_next_task(user)
240 helper.work = None
241
242- if len(chunk) or done:
243+ if chunk_len or done:
244 user = mockobject.objects[USER_PATH]
245 user.update_state_property(user)
246
247@@ -306,6 +318,7 @@
248 work.n_left = n_bytes
249 work.sock = parent
250 work.uuid = mockobject.objects[USER_PATH].current_task
251+ work.bytes_per_second = {}
252 helper.work = work
253
254 # start checking periodically
255@@ -325,7 +338,7 @@
256
257 def mock_add_backup_choice(mock, uuid, props):
258
259- keys = [KEY_NAME, KEY_TYPE, KEY_SUBTYPE, KEY_ICON, KEY_HELPER]
260+ keys = [KEY_NAME, KEY_TYPE, KEY_SUBTYPE, KEY_HELPER]
261 if set(keys) != set(props.keys()):
262 badarg('need props: %s got %s' % (keys, props.keys()))
263
264@@ -339,7 +352,7 @@
265
266 def mock_add_restore_choice(mock, uuid, props):
267
268- keys = [KEY_NAME, KEY_TYPE, KEY_SUBTYPE, KEY_ICON, KEY_HELPER,
269+ keys = [KEY_NAME, KEY_TYPE, KEY_SUBTYPE, KEY_HELPER,
270 KEY_SIZE, KEY_CTIME, KEY_BLOB]
271 if set(keys) != set(props.keys()):
272 badarg('need props: %s got %s' % (keys, props.keys()))
273
274=== modified file 'tests/dbusmock/keeper-template-test.cpp'
275--- tests/dbusmock/keeper-template-test.cpp 2016-07-27 10:13:02 +0000
276+++ tests/dbusmock/keeper-template-test.cpp 2016-07-28 19:50:41 +0000
277@@ -51,7 +51,6 @@
278 { KEY_NAME, QStringLiteral("some-name") },
279 { KEY_TYPE, QStringLiteral("some-type") },
280 { KEY_SUBTYPE, QStringLiteral("some-subtype") },
281- { KEY_ICON, QStringLiteral("some-icon") },
282 { KEY_HELPER, QString::fromUtf8(FAKE_BACKUP_HELPER_EXEC) }
283 };
284
285@@ -90,7 +89,6 @@
286 { KEY_NAME, QStringLiteral("some-name") },
287 { KEY_TYPE, QStringLiteral("some-type") },
288 { KEY_SUBTYPE, QStringLiteral("some-subtype") },
289- { KEY_ICON, QStringLiteral("some-icon") },
290 { KEY_HELPER, QString::fromUtf8("/dev/null") },
291 { KEY_SIZE, quint64(blob.size()) },
292 { KEY_CTIME, quint64(time(nullptr)) },
293@@ -143,7 +141,6 @@
294 { KEY_NAME, QStringLiteral("Music") },
295 { KEY_TYPE, QStringLiteral("folder") },
296 { KEY_SUBTYPE, sandbox.path() },
297- { KEY_ICON, QStringLiteral("music-icon") },
298 { KEY_HELPER, QString::fromUtf8(FAKE_BACKUP_HELPER_EXEC) }
299 };
300
301
302=== modified file 'tests/unit/metadata-providers/user-dirs-test.cpp'
303--- tests/unit/metadata-providers/user-dirs-test.cpp 2016-07-01 15:17:06 +0000
304+++ tests/unit/metadata-providers/user-dirs-test.cpp 2016-07-28 19:50:41 +0000
305@@ -70,13 +70,11 @@
306
307 // confirm that choices has the advertised public properties
308 const auto type_str = QStringLiteral("type");
309- const auto icon_str = QStringLiteral("icon");
310 for(const auto& choice : choices)
311 {
312 ASSERT_FALSE(choice.key().isEmpty());
313 ASSERT_FALSE(choice.display_name().isEmpty());
314 ASSERT_TRUE(choice.has_property(type_str));
315- EXPECT_TRUE(choice.has_property(icon_str));
316 }
317
318 // confirm that we have a system-data choice
319@@ -86,7 +84,7 @@
320 break;
321 ASSERT_TRUE(i != n);
322 auto system_data = choices[i];
323- EXPECT_TRUE(system_data.has_property(icon_str));
324+ EXPECT_TRUE(system_data.has_property(type_str));
325
326 // confirm that we have user-dir choices
327 std::set<QString> expected_user_dir_display_names = {
328
329=== modified file 'tests/unit/tar/keeper-tar-create-test.cpp'
330--- tests/unit/tar/keeper-tar-create-test.cpp 2016-07-22 13:49:34 +0000
331+++ tests/unit/tar/keeper-tar-create-test.cpp 2016-07-28 19:50:41 +0000
332@@ -43,7 +43,6 @@
333 // tell keeper that's a backup choice
334 const auto uuid = add_backup_choice(QMap<QString,QVariant>{
335 { KEY_NAME, QDir(in.path()).dirName() },
336- { KEY_ICON, QStringLiteral("folder") },
337 { KEY_TYPE, QStringLiteral("folder") },
338 { KEY_SUBTYPE, in.path() },
339 { KEY_HELPER, QString::fromUtf8(KEEPER_TAR_CREATE_INVOKE) }
340
341=== modified file 'tests/utils/keeper-dbusmock-fixture.h'
342--- tests/utils/keeper-dbusmock-fixture.h 2016-07-22 13:47:58 +0000
343+++ tests/utils/keeper-dbusmock-fixture.h 2016-07-28 19:50:41 +0000
344@@ -37,22 +37,21 @@
345 #define KEY_CTIME "ctime"
346 #define KEY_BLOB "blob-data"
347 #define KEY_HELPER "helper-exec"
348-#define KEY_ICON "icon"
349 #define KEY_NAME "display-name"
350 #define KEY_PERCENT "percent-done"
351 #define KEY_SIZE "size"
352+#define KEY_SPEED "speed"
353 #define KEY_SUBTYPE "subtype"
354 #define KEY_TYPE "type"
355 #define KEY_UUID "uuid"
356
357 // FIXME: this should go in a shared header in include/
358-enum
359-{
360- ACTION_QUEUED = 0,
361- ACTION_SAVING = 1,
362- ACTION_RESTORING = 2,
363- ACTION_IDLE = 3
364-};
365+static constexpr char const * ACTION_QUEUED = {"queued"};
366+static constexpr char const * ACTION_SAVING = {"saving"};
367+static constexpr char const * ACTION_RESTORING = {"restoring"};
368+static constexpr char const * ACTION_CANCELLED = {"cancelled"};
369+static constexpr char const * ACTION_FAILED = {"failed"};
370+static constexpr char const * ACTION_COMPLETE = {"complete"};
371
372 using namespace QtDBusMock;
373 using namespace QtDBusTest;

Subscribers

People subscribed via source and target branches

to all changes: