Merge lp:~unity-api-team/keeper/restore into lp:keeper/devel
- restore
- Merge into devel
Status: | Needs review |
---|---|
Proposed branch: | lp:~unity-api-team/keeper/restore |
Merge into: | lp:keeper/devel |
Diff against target: |
3175 lines (+1957/-302) 52 files modified
data/helper-registry.json.in (+6/-1) include/helper/data-dir-registry.h (+2/-0) include/helper/metadata.h (+1/-0) include/helper/registry.h (+1/-0) include/helper/restore-helper.h (+61/-0) src/CMakeLists.txt (+1/-0) src/cli/main.cpp (+42/-0) src/helper/CMakeLists.txt (+2/-0) src/helper/data-dir-registry.cpp (+43/-9) src/helper/helper.cpp (+2/-2) src/helper/metadata.cpp (+1/-0) src/helper/restore-helper.cpp (+378/-0) src/service/CMakeLists.txt (+1/-0) src/service/keeper-helper.cpp (+5/-2) src/service/keeper-task-backup.cpp (+2/-2) src/service/keeper-task-backup.h (+1/-1) src/service/keeper-task-restore.cpp (+129/-0) src/service/keeper-task-restore.h (+46/-0) src/service/keeper-task.cpp (+37/-4) src/service/keeper-task.h (+3/-1) src/service/keeper-user.cpp (+4/-2) src/service/keeper.cpp (+103/-48) src/service/keeper.h (+6/-1) src/service/manifest.cpp (+3/-3) src/service/private/keeper-task_p.h (+4/-2) src/service/task-manager.cpp (+55/-12) src/service/task-manager.h (+2/-0) src/storage-framework/CMakeLists.txt (+3/-0) src/storage-framework/downloader.h (+46/-0) src/storage-framework/sf-downloader.cpp (+71/-0) src/storage-framework/sf-downloader.h (+48/-0) src/storage-framework/storage_framework_client.cpp (+16/-15) src/storage-framework/storage_framework_client.h (+2/-1) src/test-restore/CMakeLists.txt (+40/-0) src/test-restore/main.cpp (+32/-0) src/test-restore/test-restore-socket.cpp (+139/-0) src/test-restore/test-restore-socket.h (+56/-0) tests/CMakeLists.txt (+6/-0) tests/com_canonical_keeper.py (+17/-0) tests/fakes/CMakeLists.txt (+10/-0) tests/fakes/fake-restore-helper.cpp (+101/-0) tests/fakes/fake-restore-helper.h (+26/-0) tests/fakes/restore-reader.cpp (+81/-0) tests/fakes/restore-reader.h (+43/-0) tests/integration/helpers/CMakeLists.txt (+4/-0) tests/integration/helpers/helpers-test.cc (+219/-184) tests/integration/helpers/test-helpers-base.cpp (+8/-3) tests/unit/manifest/manifest-test.cpp (+1/-1) tests/unit/storage-framework/create-uploader-test.cpp (+6/-7) tests/utils/file-utils.cpp (+3/-1) tests/utils/storage-framework-local.cpp (+34/-0) tests/utils/storage-framework-local.h (+4/-0) |
To merge this branch: | bzr merge lp:~unity-api-team/keeper/restore |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
unity-api-1-bot | continuous-integration | Needs Fixing | |
Unity API Team | Pending | ||
Review via email: mp+311070@code.launchpad.net |
Commit message
First version of restore.
Description of the change
DO NOT REVIEW YET, branch created for initial jenkins test
This is based on <https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
- 131. By Charles Kerr
-
debug messages and whitespace
- 132. By Charles Kerr
-
eliminate some possible points of failure in the RestoreReader fake
- 133. By Charles Kerr
-
add more debugging info to FileUtils:
:compare_ files()
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:133
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unmerged revisions
- 133. By Charles Kerr
-
add more debugging info to FileUtils:
:compare_ files() - 132. By Charles Kerr
-
eliminate some possible points of failure in the RestoreReader fake
- 131. By Charles Kerr
-
debug messages and whitespace
- 130. By Charles Kerr
-
fix missing gpl copyright in keeper dbusmock template
- 129. By Charles Kerr
-
fix cppcheck warning: non-explicit object ctor taking one argument
Preview Diff
1 | === modified file 'data/helper-registry.json.in' |
2 | --- data/helper-registry.json.in 2016-08-09 04:20:33 +0000 |
3 | +++ data/helper-registry.json.in 2016-11-17 00:23:33 +0000 |
4 | @@ -4,5 +4,10 @@ |
5 | "@FOLDER_BACKUP_EXEC@", |
6 | "${subtype}" |
7 | ] |
8 | - } |
9 | + , |
10 | + "restore-urls": [ |
11 | + "@FOLDER_RESTORE_EXEC@", |
12 | + "${subtype}" |
13 | + ] |
14 | + } |
15 | } |
16 | |
17 | === modified file 'include/helper/data-dir-registry.h' |
18 | --- include/helper/data-dir-registry.h 2016-08-09 05:44:25 +0000 |
19 | +++ include/helper/data-dir-registry.h 2016-11-17 00:23:33 +0000 |
20 | @@ -39,6 +39,8 @@ |
21 | |
22 | QStringList get_backup_helper_urls(Metadata const& metadata) override; |
23 | |
24 | + QStringList get_restore_helper_urls(Metadata const& metadata) override; |
25 | + |
26 | private: |
27 | class Impl; |
28 | friend class Impl; |
29 | |
30 | === modified file 'include/helper/metadata.h' |
31 | --- include/helper/metadata.h 2016-10-14 09:23:11 +0000 |
32 | +++ include/helper/metadata.h 2016-11-17 00:23:33 +0000 |
33 | @@ -42,6 +42,7 @@ |
34 | static QString const TITLE_KEY; |
35 | static QString const VERSION_KEY; |
36 | static QString const FILE_NAME_KEY; |
37 | + static QString const DIR_NAME_KEY; |
38 | static QString const DISPLAY_NAME_KEY; |
39 | |
40 | // metadata values |
41 | |
42 | === modified file 'include/helper/registry.h' |
43 | --- include/helper/registry.h 2016-08-08 04:56:35 +0000 |
44 | +++ include/helper/registry.h 2016-11-17 00:23:33 +0000 |
45 | @@ -30,6 +30,7 @@ |
46 | Q_DISABLE_COPY(HelperRegistry) |
47 | |
48 | virtual QStringList get_backup_helper_urls(Metadata const& task) =0; |
49 | + virtual QStringList get_restore_helper_urls(Metadata const& task) =0; |
50 | |
51 | protected: |
52 | HelperRegistry() =default; |
53 | |
54 | === added file 'include/helper/restore-helper.h' |
55 | --- include/helper/restore-helper.h 1970-01-01 00:00:00 +0000 |
56 | +++ include/helper/restore-helper.h 2016-11-17 00:23:33 +0000 |
57 | @@ -0,0 +1,61 @@ |
58 | +/* |
59 | + * Copyright (C) 2016 Canonical, Ltd. |
60 | + * |
61 | + * This program is free software: you can redistribute it and/or modify it |
62 | + * under the terms of the GNU General Public License version 3, as published |
63 | + * by the Free Software Foundation. |
64 | + * |
65 | + * This program is distributed in the hope that it will be useful, but |
66 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
67 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
68 | + * PURPOSE. See the GNU General Public License for more details. |
69 | + * |
70 | + * You should have received a copy of the GNU General Public License along |
71 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
72 | + * |
73 | + * Authors: |
74 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
75 | + * Charles Kerr <charles.kerr@canonical.com> |
76 | + */ |
77 | + |
78 | +#pragma once |
79 | + |
80 | +#include "storage-framework/downloader.h" |
81 | +#include "helper/helper.h" // parent class |
82 | +#include "helper/registry.h" |
83 | + |
84 | +#include <QObject> |
85 | +#include <QScopedPointer> |
86 | +#include <QString> |
87 | + |
88 | +#include <memory> |
89 | + |
90 | +class RestoreHelperPrivate; |
91 | +class RestoreHelper final: public Helper |
92 | +{ |
93 | + Q_OBJECT |
94 | + Q_DECLARE_PRIVATE(RestoreHelper) |
95 | + |
96 | +public: |
97 | + RestoreHelper( |
98 | + QString const & appid, |
99 | + clock_func const & clock=Helper::default_clock, |
100 | + QObject * parent=nullptr |
101 | + ); |
102 | + virtual ~RestoreHelper(); |
103 | + Q_DISABLE_COPY(RestoreHelper) |
104 | + |
105 | + static constexpr int MAX_INACTIVITY_TIME = 15000; |
106 | + |
107 | + void set_downloader(std::shared_ptr<Downloader> const& downloader); |
108 | + void start(QStringList const& urls) override; |
109 | + void stop() override; |
110 | + int get_helper_socket() const; |
111 | + QString to_string(Helper::State state) const override; |
112 | + void set_state(State) override; |
113 | +protected: |
114 | + void on_helper_finished() override; |
115 | + |
116 | +private: |
117 | + QScopedPointer<RestoreHelperPrivate> const d_ptr; |
118 | +}; |
119 | |
120 | === modified file 'src/CMakeLists.txt' |
121 | --- src/CMakeLists.txt 2016-08-09 10:13:48 +0000 |
122 | +++ src/CMakeLists.txt 2016-11-17 00:23:33 +0000 |
123 | @@ -11,6 +11,7 @@ |
124 | add_subdirectory(storage-framework) |
125 | add_subdirectory(tar) |
126 | add_subdirectory(util) |
127 | +add_subdirectory(test-restore) |
128 | |
129 | set( |
130 | COVERAGE_REPORT_TARGETS |
131 | |
132 | === modified file 'src/cli/main.cpp' |
133 | --- src/cli/main.cpp 2016-08-30 14:16:19 +0000 |
134 | +++ src/cli/main.cpp 2016-11-17 00:23:33 +0000 |
135 | @@ -88,6 +88,48 @@ |
136 | qWarning() << "Error starting backup:" << backup_reply.error().message(); |
137 | } |
138 | } |
139 | + else if(argc == 2 && QStringLiteral("--restore") == argv[1]) |
140 | + { |
141 | + QScopedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser( |
142 | + DBusTypes::KEEPER_SERVICE, |
143 | + DBusTypes::KEEPER_USER_PATH, |
144 | + QDBusConnection::sessionBus() |
145 | + ) ); |
146 | + QDBusPendingReply<QVariantDictMap> choices = user_iface->call("GetRestoreChoices"); |
147 | + choices.waitForFinished(); |
148 | + if (choices.isError()) |
149 | + { |
150 | + qFatal("Call to '%s.GetRestoreChoices() at '%s' call failed: %s", |
151 | + DBusTypes::KEEPER_SERVICE, |
152 | + qPrintable(DBusTypes::KEEPER_USER_PATH), |
153 | + qPrintable(choices.error().message()) |
154 | + ); |
155 | + } |
156 | + |
157 | + QStringList uuids; |
158 | + auto choices_values = choices.value(); |
159 | + for(auto iter = choices_values.begin(); iter != choices_values.end(); ++iter) |
160 | + { |
161 | + const auto& values = iter.value(); |
162 | + auto iter_values = values.find("type"); |
163 | + if (iter_values != values.end()) |
164 | + { |
165 | + if (iter_values.value().toString() == "folder") |
166 | + { |
167 | + qDebug() << "Adding uuid" << iter.key() << "with type:" << "folder"; |
168 | + uuids << iter.key(); |
169 | + } |
170 | + } |
171 | + } |
172 | + |
173 | + QStringList restoreUUids{uuids.at(0)}; |
174 | + QDBusPendingReply<void> backup_reply = user_iface->call("StartRestore", restoreUUids); |
175 | + |
176 | + if (!backup_reply.isValid()) |
177 | + { |
178 | + qWarning() << "Error starting restore:" << backup_reply.error().message(); |
179 | + } |
180 | + } |
181 | else |
182 | { |
183 | qWarning() << "FIXME"; |
184 | |
185 | === modified file 'src/helper/CMakeLists.txt' |
186 | --- src/helper/CMakeLists.txt 2016-09-06 01:31:59 +0000 |
187 | +++ src/helper/CMakeLists.txt 2016-11-17 00:23:33 +0000 |
188 | @@ -48,10 +48,12 @@ |
189 | ${HELPER_LIB} |
190 | STATIC |
191 | backup-helper.cpp |
192 | + restore-helper.cpp |
193 | data-dir-registry.cpp |
194 | helper.cpp |
195 | metadata.cpp |
196 | ${CMAKE_SOURCE_DIR}/include/helper/backup-helper.h |
197 | + ${CMAKE_SOURCE_DIR}/include/helper/restore-helper.h |
198 | ${CMAKE_SOURCE_DIR}/include/helper/data-dir-registry.h |
199 | ${CMAKE_SOURCE_DIR}/include/helper/helper.h |
200 | ${CMAKE_SOURCE_DIR}/include/helper/registry.h |
201 | |
202 | === modified file 'src/helper/data-dir-registry.cpp' |
203 | --- src/helper/data-dir-registry.cpp 2016-08-10 02:29:17 +0000 |
204 | +++ src/helper/data-dir-registry.cpp 2016-11-17 00:23:33 +0000 |
205 | @@ -49,15 +49,29 @@ |
206 | |
207 | QStringList get_backup_helper_urls(Metadata const& task) |
208 | { |
209 | + return get_helper_urls(task, "backup"); |
210 | + } |
211 | + |
212 | + QStringList get_restore_helper_urls(Metadata const& task) |
213 | + { |
214 | + return get_helper_urls(task, "restore"); |
215 | + } |
216 | + |
217 | + |
218 | + |
219 | +private: |
220 | + |
221 | + QStringList get_helper_urls(Metadata const& task, QString const & prop) |
222 | + { |
223 | QStringList ret; |
224 | |
225 | QString type; |
226 | if (task.get_property(Metadata::TYPE_KEY, type)) |
227 | { |
228 | - auto it = registry_.find(std::make_pair(type,QStringLiteral("backup"))); |
229 | + auto it = registry_.find(std::make_pair(type,prop)); |
230 | if (it == registry_.end()) |
231 | { |
232 | - qCritical() << "can't get backup helper urls for unhandled type" << type; |
233 | + qCritical() << "can't get " << prop << " helper urls for unhandled type" << type; |
234 | } |
235 | else |
236 | { |
237 | @@ -73,8 +87,6 @@ |
238 | return ret; |
239 | } |
240 | |
241 | -private: |
242 | - |
243 | // replace "${key}" with task.get_property("key") |
244 | QStringList perform_url_substitution(Metadata const& task, QStringList const& urls_in) |
245 | { |
246 | @@ -139,6 +151,10 @@ |
247 | * "backup-urls": [ |
248 | * "/path/to/helper.sh", |
249 | * "${subtype}" |
250 | + * ], |
251 | + * "restore-urls": [ |
252 | + * "/path/to/helper.sh", |
253 | + * "${subtype}" |
254 | * ] |
255 | * } |
256 | * } |
257 | @@ -160,21 +176,33 @@ |
258 | for (auto tit=obj.begin(), tend=obj.end(); tit!=tend; ++tit) |
259 | { |
260 | auto const type = tit.key(); |
261 | - auto& info = registry_[std::make_pair(type,QStringLiteral("backup"))]; |
262 | - |
263 | auto const props = tit.value().toObject(); |
264 | + |
265 | auto const urls_jsonval = props["backup-urls"]; |
266 | if (urls_jsonval.isArray()) |
267 | { |
268 | + auto& info = registry_[std::make_pair(type,QStringLiteral("backup"))]; |
269 | for (auto url_jsonval : urls_jsonval.toArray()) |
270 | { |
271 | info.urls.push_back(url_jsonval.toString()); |
272 | } |
273 | + qDebug() << "loaded" << type << "backup urls from" << path; |
274 | + for(auto const& url : info.urls) |
275 | + qDebug() << "\turl:" << url; |
276 | } |
277 | |
278 | - qDebug() << "loaded" << type << "backup urls from" << path; |
279 | - for(auto const& url : info.urls) |
280 | - qDebug() << "\turl:" << url; |
281 | + auto const urls_jsonval_restore = props["restore-urls"]; |
282 | + if (urls_jsonval_restore.isArray()) |
283 | + { |
284 | + auto& info = registry_[std::make_pair(type,QStringLiteral("restore"))]; |
285 | + for (auto url_jsonval : urls_jsonval_restore.toArray()) |
286 | + { |
287 | + info.urls.push_back(url_jsonval.toString()); |
288 | + } |
289 | + qDebug() << "loaded" << type << "restore urls from" << path; |
290 | + for(auto const& url : info.urls) |
291 | + qDebug() << "\turl:" << url; |
292 | + } |
293 | } |
294 | } |
295 | } |
296 | @@ -198,3 +226,9 @@ |
297 | { |
298 | return impl_->get_backup_helper_urls(task); |
299 | } |
300 | + |
301 | +QStringList |
302 | +DataDirRegistry::get_restore_helper_urls(Metadata const& task) |
303 | +{ |
304 | + return impl_->get_restore_helper_urls(task); |
305 | +} |
306 | |
307 | === modified file 'src/helper/helper.cpp' |
308 | --- src/helper/helper.cpp 2016-09-15 14:05:17 +0000 |
309 | +++ src/helper/helper.cpp 2016-11-17 00:23:33 +0000 |
310 | @@ -301,7 +301,7 @@ |
311 | |
312 | void ual_stop() |
313 | { |
314 | - qDebug() << "Stopping helper for app:" << appid_; |
315 | + qDebug() << "------------------------------------------------------ Stopping helper for app:" << appid_; |
316 | auto backupType = ubuntu::app_launch::Helper::Type::from_raw(HELPER_TYPE); |
317 | |
318 | auto appid = ubuntu::app_launch::AppID::parse(appid_.toStdString()); |
319 | @@ -359,7 +359,7 @@ |
320 | |
321 | void on_max_time_waiting_for_ual_started() |
322 | { |
323 | - qDebug() << "Max time reached waiting for UAL to start"; |
324 | + qDebug() << "========================================================================== Max time reached waiting for UAL to start"; |
325 | q_ptr->set_state(Helper::State::FAILED); |
326 | stop_wait_for_ual_timer(); |
327 | } |
328 | |
329 | === modified file 'src/helper/metadata.cpp' |
330 | --- src/helper/metadata.cpp 2016-10-14 09:23:11 +0000 |
331 | +++ src/helper/metadata.cpp 2016-11-17 00:23:33 +0000 |
332 | @@ -42,6 +42,7 @@ |
333 | const QString Metadata::TITLE_KEY = QStringLiteral("title"); |
334 | const QString Metadata::VERSION_KEY = QStringLiteral("version"); |
335 | const QString Metadata::FILE_NAME_KEY = QStringLiteral("file-name"); |
336 | +const QString Metadata::DIR_NAME_KEY = QStringLiteral("dir-name"); |
337 | const QString Metadata::DISPLAY_NAME_KEY = QStringLiteral("display-name"); |
338 | |
339 | // Metadata values |
340 | |
341 | === added file 'src/helper/restore-helper.cpp' |
342 | --- src/helper/restore-helper.cpp 1970-01-01 00:00:00 +0000 |
343 | +++ src/helper/restore-helper.cpp 2016-11-17 00:23:33 +0000 |
344 | @@ -0,0 +1,378 @@ |
345 | +/* |
346 | + * Copyright (C) 2016 Canonical, Ltd. |
347 | + * |
348 | + * This program is free software: you can redistribute it and/or modify it |
349 | + * under the terms of the GNU General Public License version 3, as published |
350 | + * by the Free Software Foundation. |
351 | + * |
352 | + * This program is distributed in the hope that it will be useful, but |
353 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
354 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
355 | + * PURPOSE. See the GNU General Public License for more details. |
356 | + * |
357 | + * You should have received a copy of the GNU General Public License along |
358 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
359 | + * |
360 | + * Authors: |
361 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
362 | + * Charles Kerr <charles.kerr@canonical.com> |
363 | + */ |
364 | + |
365 | +#include "util/connection-helper.h" |
366 | +#include "helper/restore-helper.h" |
367 | +#include "service/app-const.h" // HELPER_TYPE |
368 | + |
369 | +#include <QByteArray> |
370 | +#include <QDebug> |
371 | +#include <QLocalSocket> |
372 | +#include <QMap> |
373 | +#include <QObject> |
374 | +#include <QString> |
375 | +#include <QTimer> |
376 | +#include <QVector> |
377 | +#include <QCryptographicHash> |
378 | + |
379 | +#include <fcntl.h> |
380 | +#include <sys/types.h> |
381 | +#include <sys/socket.h> |
382 | + |
383 | +#include <functional> // std::bind() |
384 | + |
385 | + |
386 | +class RestoreHelperPrivate |
387 | +{ |
388 | +public: |
389 | + |
390 | + explicit RestoreHelperPrivate( |
391 | + RestoreHelper* backup_helper |
392 | + ) |
393 | + : q_ptr(backup_helper) |
394 | + { |
395 | + // listen for inactivity from storage framework |
396 | + QObject::connect(&timer_, &QTimer::timeout, |
397 | + std::bind(&RestoreHelperPrivate::on_inactivity_detected, this) |
398 | + ); |
399 | + |
400 | + // fire up the sockets |
401 | + int fds[2]; |
402 | + int rc = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds); |
403 | + if (rc == -1) |
404 | + { |
405 | + // TODO throw exception. |
406 | + qWarning() << "RestoreHelperPrivate: error creating socket pair to communicate with helper "; |
407 | + return; |
408 | + } |
409 | + |
410 | + // helper socket is for the client. |
411 | + helper_socket_.setSocketDescriptor(fds[0], QLocalSocket::ConnectedState, QIODevice::ReadOnly); |
412 | + |
413 | + write_socket_.setSocketDescriptor(fds[1], QLocalSocket::ConnectedState, QIODevice::WriteOnly); |
414 | + } |
415 | + |
416 | + ~RestoreHelperPrivate() = default; |
417 | + |
418 | + Q_DISABLE_COPY(RestoreHelperPrivate) |
419 | + |
420 | + void start(QStringList const& urls) |
421 | + { |
422 | + q_ptr->Helper::start(urls); |
423 | + reset_inactivity_timer(); |
424 | + } |
425 | + |
426 | + void set_downloader(std::shared_ptr<Downloader> const& downloader) |
427 | + { |
428 | + qDebug() << "RestoreHelper::set_downloader"; |
429 | + downloader_ = downloader; |
430 | + n_read_ = 0; |
431 | + n_uploaded_ = 0; |
432 | + read_error_ = false; |
433 | + write_error_ = false; |
434 | + cancelled_ = false; |
435 | + |
436 | + q_ptr->set_expected_size(downloader->file_size()); |
437 | + |
438 | + qDebug() << "Storage framework socket is: " << static_cast<void *>(downloader_->socket().get()); |
439 | + |
440 | + // listen for data ready to read |
441 | + QObject::connect(downloader_->socket().get(), &QLocalSocket::readyRead, |
442 | + std::bind(&RestoreHelperPrivate::on_ready_read, this) |
443 | + ); |
444 | + |
445 | + connections_.remember(QObject::connect( |
446 | + &write_socket_, &QLocalSocket::bytesWritten, |
447 | + std::bind(&RestoreHelperPrivate::on_data_uploaded, this, std::placeholders::_1) |
448 | + )); |
449 | + |
450 | + // maybe there's already readable data |
451 | + process_more(); |
452 | + |
453 | + reset_inactivity_timer(); |
454 | + } |
455 | + |
456 | + void stop() |
457 | + { |
458 | + write_socket_.disconnectFromServer(); |
459 | + cancelled_ = true; |
460 | + q_ptr->Helper::stop(); |
461 | + } |
462 | + |
463 | + int get_helper_socket() const |
464 | + { |
465 | + return int(helper_socket_.socketDescriptor()); |
466 | + } |
467 | + |
468 | + QString to_string(Helper::State state) const |
469 | + { |
470 | + return state == Helper::State::STARTED |
471 | + ? QStringLiteral("restoring") |
472 | + : q_ptr->Helper::to_string(state); |
473 | + } |
474 | + |
475 | + void on_state_changed(Helper::State state) |
476 | + { |
477 | + switch (state) |
478 | + { |
479 | + case Helper::State::CANCELLED: |
480 | + case Helper::State::FAILED: |
481 | + qDebug() << "cancelled/failed, calling downloader_.reset()"; |
482 | + downloader_.reset(); |
483 | + break; |
484 | + |
485 | + case Helper::State::DATA_COMPLETE: { |
486 | + qDebug() << "Restore helper finished, calling downloader_.finish()"; |
487 | + write_socket_.disconnectFromServer(); |
488 | + downloader_->finish(); |
489 | + downloader_.reset(); |
490 | + break; |
491 | + } |
492 | + |
493 | + //case Helper::State::NOT_STARTED: |
494 | + //case Helper::State::STARTED: |
495 | + default: |
496 | + break; |
497 | + } |
498 | + } |
499 | + |
500 | + void on_helper_finished() |
501 | + { |
502 | + stop_inactivity_timer(); |
503 | + check_for_done(); |
504 | + } |
505 | + |
506 | +private: |
507 | + |
508 | + void on_inactivity_detected() |
509 | + { |
510 | + stop_inactivity_timer(); |
511 | + qWarning() << "Inactivity detected in the helper...stopping it"; |
512 | + stop(); |
513 | + } |
514 | + |
515 | + void on_ready_read() |
516 | + { |
517 | + process_more(); |
518 | + } |
519 | + |
520 | + void on_data_uploaded(qint64 n) |
521 | + { |
522 | + n_uploaded_ += n; |
523 | + q_ptr->record_data_transferred(n); |
524 | + qDebug("n_read %zu n_uploaded %zu (newly uploaded %zu)", size_t(n_read_), size_t(n_uploaded_), size_t(n)); |
525 | + process_more(); |
526 | + check_for_done(); |
527 | + } |
528 | + |
529 | + void process_more() |
530 | + { |
531 | + qDebug() << Q_FUNC_INFO; |
532 | + |
533 | + if (!downloader_) |
534 | + return; |
535 | + |
536 | + qDebug() << Q_FUNC_INFO << "2"; |
537 | + |
538 | + char readbuf[UPLOAD_BUFFER_MAX_]; |
539 | + auto socket = downloader_->socket(); |
540 | + for(;;) |
541 | + { |
542 | + if (!socket->bytesAvailable()) |
543 | + break; |
544 | + // try to fill the upload buf |
545 | + int max_bytes = (UPLOAD_BUFFER_MAX_) - upload_buffer_.size(); |
546 | + if (max_bytes > 0) { |
547 | + const auto n = socket->read(readbuf, max_bytes); |
548 | + if (n > 0) { |
549 | + n_read_ += n; |
550 | + upload_buffer_.append(readbuf, int(n)); |
551 | + qDebug("buffer_.size() is %zu after reading %zu", size_t(upload_buffer_.size()), size_t(n)); |
552 | + } |
553 | + else if (n < 0) { |
554 | + read_error_ = true; |
555 | + qDebug() << "Read error in" << Q_FUNC_INFO << ":" << socket->errorString(); |
556 | + stop(); |
557 | + return; |
558 | + } |
559 | + } |
560 | + |
561 | + // THIS IS JUST FOR EXTRA DEBUG INFORMATION |
562 | + QCryptographicHash hash(QCryptographicHash::Sha1); |
563 | + hash.addData(upload_buffer_.left(100)); |
564 | + qDebug() << "************************************************ Hash send: " << hash.result().toHex() << " Size: " << upload_buffer_.size() << " Total: " << n_read_; |
565 | + // THIS IS JUST FOR EXTRA DEBUG INFORMATION |
566 | + |
567 | + // try to empty the upload buf |
568 | + const auto n = write_socket_.write(upload_buffer_); |
569 | + if (n > 0) { |
570 | + upload_buffer_.remove(0, int(n)); |
571 | + qDebug("buffer_.size() is %zu after writing %zu", size_t(upload_buffer_.size()), size_t(n)); |
572 | + continue; |
573 | + } |
574 | + else { |
575 | + if (n < 0) { |
576 | + write_error_ = true; |
577 | + qWarning() << "Write error:" << write_socket_.errorString(); |
578 | + stop(); |
579 | + } |
580 | + break; |
581 | + } |
582 | + } |
583 | + |
584 | + reset_inactivity_timer(); |
585 | + } |
586 | + |
587 | + void reset_inactivity_timer() |
588 | + { |
589 | + static constexpr int MAX_TIME_WAITING_FOR_DATA {RestoreHelper::MAX_INACTIVITY_TIME}; |
590 | + timer_.start(MAX_TIME_WAITING_FOR_DATA); |
591 | + } |
592 | + |
593 | + void stop_inactivity_timer() |
594 | + { |
595 | + timer_.stop(); |
596 | + } |
597 | + |
598 | + void check_for_done() |
599 | + { |
600 | + qDebug() << "Checking for done."; |
601 | + if (cancelled_) |
602 | + { |
603 | + q_ptr->set_state(Helper::State::CANCELLED); |
604 | + } |
605 | + else if (read_error_ || write_error_ || n_uploaded_ > q_ptr->expected_size()) |
606 | + { |
607 | + if (!q_ptr->is_helper_running()) |
608 | + { |
609 | + q_ptr->set_state(Helper::State::FAILED); |
610 | + } |
611 | + } |
612 | + else if (n_uploaded_ == q_ptr->expected_size()) |
613 | + { |
614 | + if (downloader_) |
615 | + { |
616 | + if (q_ptr->is_helper_running()) |
617 | + { |
618 | + // only in the case that the helper process finished we move to the next state |
619 | + // this is to prevent to start the next task too early |
620 | + q_ptr->set_state(Helper::State::DATA_COMPLETE); |
621 | + stop_inactivity_timer(); |
622 | + } |
623 | + } |
624 | + else |
625 | + q_ptr->set_state(Helper::State::COMPLETE); |
626 | + } |
627 | + } |
628 | + |
629 | + /*** |
630 | + **** |
631 | + ***/ |
632 | + |
633 | + static constexpr int UPLOAD_BUFFER_MAX_ {1024*16}; |
634 | + |
635 | + RestoreHelper * const q_ptr; |
636 | + QTimer timer_; |
637 | + std::shared_ptr<Downloader> downloader_; |
638 | + QLocalSocket helper_socket_; |
639 | + QLocalSocket write_socket_; |
640 | + QByteArray upload_buffer_; |
641 | + qint64 n_read_ = 0; |
642 | + qint64 n_uploaded_ = 0; |
643 | + bool read_error_ = false; |
644 | + bool write_error_ = false; |
645 | + bool cancelled_ = false; |
646 | + ConnectionHelper connections_; |
647 | + QString uploader_committed_file_name_; |
648 | +}; |
649 | + |
650 | +/*** |
651 | +**** |
652 | +***/ |
653 | + |
654 | +RestoreHelper::RestoreHelper( |
655 | + QString const & appid, |
656 | + clock_func const & clock, |
657 | + QObject * parent |
658 | +) |
659 | + : Helper(appid, clock, parent) |
660 | + , d_ptr(new RestoreHelperPrivate(this)) |
661 | +{ |
662 | +} |
663 | + |
664 | +RestoreHelper::~RestoreHelper() =default; |
665 | + |
666 | +void |
667 | +RestoreHelper::start(QStringList const& url) |
668 | +{ |
669 | + Q_D(RestoreHelper); |
670 | + |
671 | + d->start(url); |
672 | +} |
673 | + |
674 | +void |
675 | +RestoreHelper::stop() |
676 | +{ |
677 | + Q_D(RestoreHelper); |
678 | + |
679 | + d->stop(); |
680 | +} |
681 | + |
682 | +void |
683 | +RestoreHelper::set_downloader(std::shared_ptr<Downloader> const& downloader) |
684 | +{ |
685 | + Q_D(RestoreHelper); |
686 | + |
687 | + d->set_downloader(downloader); |
688 | +} |
689 | + |
690 | +int |
691 | +RestoreHelper::get_helper_socket() const |
692 | +{ |
693 | + Q_D(const RestoreHelper); |
694 | + |
695 | + return d->get_helper_socket(); |
696 | +} |
697 | + |
698 | +QString |
699 | +RestoreHelper::to_string(Helper::State state) const |
700 | +{ |
701 | + Q_D(const RestoreHelper); |
702 | + |
703 | + return d->to_string(state); |
704 | +} |
705 | + |
706 | +void |
707 | +RestoreHelper::set_state(Helper::State state) |
708 | +{ |
709 | + Q_D(RestoreHelper); |
710 | + |
711 | + qDebug() << Q_FUNC_INFO; |
712 | + Helper::set_state(state); |
713 | + d->on_state_changed(state); |
714 | +} |
715 | + |
716 | +void RestoreHelper::on_helper_finished() |
717 | +{ |
718 | + Q_D(RestoreHelper); |
719 | + |
720 | + Helper::on_helper_finished(); |
721 | + d->on_helper_finished(); |
722 | +} |
723 | |
724 | === modified file 'src/service/CMakeLists.txt' |
725 | --- src/service/CMakeLists.txt 2016-10-28 15:11:21 +0000 |
726 | +++ src/service/CMakeLists.txt 2016-11-17 00:23:33 +0000 |
727 | @@ -15,6 +15,7 @@ |
728 | task-manager.cpp |
729 | keeper-task.cpp |
730 | keeper-task-backup.cpp |
731 | + keeper-task-restore.cpp |
732 | manifest.cpp |
733 | metadata-provider.h |
734 | ) |
735 | |
736 | === modified file 'src/service/keeper-helper.cpp' |
737 | --- src/service/keeper-helper.cpp 2016-08-10 02:06:08 +0000 |
738 | +++ src/service/keeper-helper.cpp 2016-11-17 00:23:33 +0000 |
739 | @@ -44,8 +44,11 @@ |
740 | |
741 | QDBusUnixFileDescriptor KeeperHelper::StartRestore() |
742 | { |
743 | - // TODO get the file descriptor of the item in storage framework |
744 | - return QDBusUnixFileDescriptor(); |
745 | + // pass it back to Keeper to do the work |
746 | + Q_ASSERT(calledFromDBus()); |
747 | + auto bus = connection(); |
748 | + auto& msg = message(); |
749 | + return keeper_.StartRestore(bus, msg); |
750 | } |
751 | |
752 | void KeeperHelper::UpdateStatus(const QString &app_id, const QString &status, double percentage) |
753 | |
754 | === modified file 'src/service/keeper-task-backup.cpp' |
755 | --- src/service/keeper-task-backup.cpp 2016-10-06 14:53:44 +0000 |
756 | +++ src/service/keeper-task-backup.cpp 2016-11-17 00:23:33 +0000 |
757 | @@ -31,7 +31,7 @@ |
758 | Q_DECLARE_PUBLIC(KeeperTaskBackup) |
759 | public: |
760 | KeeperTaskBackupPrivate(KeeperTask * keeper_task, |
761 | - KeeperTask::TaskData const & task_data, |
762 | + KeeperTask::TaskData & task_data, |
763 | QSharedPointer<HelperRegistry> const & helper_registry, |
764 | QSharedPointer<StorageFrameworkClient> const & storage) |
765 | : KeeperTaskPrivate(keeper_task, task_data, helper_registry, storage) |
766 | @@ -90,7 +90,7 @@ |
767 | QString file_name_; |
768 | }; |
769 | |
770 | -KeeperTaskBackup::KeeperTaskBackup(TaskData const & task_data, |
771 | +KeeperTaskBackup::KeeperTaskBackup(TaskData & task_data, |
772 | QSharedPointer<HelperRegistry> const & helper_registry, |
773 | QSharedPointer<StorageFrameworkClient> const & storage, |
774 | QObject *parent) |
775 | |
776 | === modified file 'src/service/keeper-task-backup.h' |
777 | --- src/service/keeper-task-backup.h 2016-10-06 14:53:44 +0000 |
778 | +++ src/service/keeper-task-backup.h 2016-11-17 00:23:33 +0000 |
779 | @@ -29,7 +29,7 @@ |
780 | Q_DECLARE_PRIVATE(KeeperTaskBackup) |
781 | public: |
782 | |
783 | - KeeperTaskBackup(TaskData const & task_data, |
784 | + KeeperTaskBackup(TaskData & task_data, |
785 | QSharedPointer<HelperRegistry> const & helper_registry, |
786 | QSharedPointer<StorageFrameworkClient> const & storage, |
787 | QObject *parent = nullptr); |
788 | |
789 | === added file 'src/service/keeper-task-restore.cpp' |
790 | --- src/service/keeper-task-restore.cpp 1970-01-01 00:00:00 +0000 |
791 | +++ src/service/keeper-task-restore.cpp 2016-11-17 00:23:33 +0000 |
792 | @@ -0,0 +1,129 @@ |
793 | +/* |
794 | + * Copyright (C) 2016 Canonical, Ltd. |
795 | + * |
796 | + * This program is free software: you can redistribute it and/or modify it |
797 | + * under the terms of the GNU General Public License version 3, as published |
798 | + * by the Free Software Foundation. |
799 | + * |
800 | + * This program is distributed in the hope that it will be useful, but |
801 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
802 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
803 | + * PURPOSE. See the GNU General Public License for more details. |
804 | + * |
805 | + * You should have received a copy of the GNU General Public License along |
806 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
807 | + * |
808 | + * Authors: |
809 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
810 | + * Charles Kerr <charles.kerr@canonical.com> |
811 | + */ |
812 | + |
813 | +#include "util/connection-helper.h" |
814 | +#include "storage-framework/storage_framework_client.h" |
815 | +#include "helper/restore-helper.h" |
816 | +#include "service/app-const.h" // DEKKO_APP_ID |
817 | +#include "service/keeper-task-restore.h" |
818 | +#include "service/keeper-task.h" |
819 | +#include "service/private/keeper-task_p.h" |
820 | + |
821 | +namespace sf = unity::storage::qt::client; |
822 | + |
823 | +class KeeperTaskRestorePrivate : public KeeperTaskPrivate |
824 | +{ |
825 | + Q_DECLARE_PUBLIC(KeeperTaskRestore) |
826 | +public: |
827 | + KeeperTaskRestorePrivate(KeeperTask * keeper_task, |
828 | + KeeperTask::TaskData & task_data, |
829 | + QSharedPointer<HelperRegistry> const & helper_registry, |
830 | + QSharedPointer<StorageFrameworkClient> const & storage) |
831 | + : KeeperTaskPrivate(keeper_task, task_data, helper_registry, storage) |
832 | + { |
833 | + } |
834 | + |
835 | + ~KeeperTaskRestorePrivate() = default; |
836 | + |
837 | + QStringList get_helper_urls() const |
838 | + { |
839 | + return helper_registry_->get_restore_helper_urls(task_data_.metadata); |
840 | + } |
841 | + |
842 | + void init_helper() |
843 | + { |
844 | + qDebug() << Q_FUNC_INFO; |
845 | + helper_.reset(new RestoreHelper(DEKKO_APP_ID), [](Helper *h){h->deleteLater();}); // TODO change this to a restore helper |
846 | + qDebug() << "Helper " << static_cast<void*>(helper_.data()) << " was created"; |
847 | + } |
848 | + |
849 | + void ask_for_downloader() |
850 | + { |
851 | + qDebug() << "asking storage framework for a socket for reading"; |
852 | + |
853 | + QString file_name; |
854 | + task_data_.metadata.get_property(Metadata::FILE_NAME_KEY, file_name); |
855 | + if (file_name.isEmpty()) |
856 | + { |
857 | + qWarning() << "ERROR: the restore task does not provide a valid file name to read from."; |
858 | + return; |
859 | + } |
860 | + |
861 | + QString dir_name; |
862 | + task_data_.metadata.get_property(Metadata::DIR_NAME_KEY, dir_name); |
863 | + if (dir_name.isEmpty()) |
864 | + { |
865 | + qWarning() << "ERROR: the restore task does not provide a valid directory name."; |
866 | + return; |
867 | + } |
868 | + |
869 | + // extract the dir_name. |
870 | + connections_.connect_future( |
871 | + storage_->get_new_downloader(dir_name, file_name), |
872 | + std::function<void(std::shared_ptr<Downloader> const&)>{ |
873 | + [this](std::shared_ptr<Downloader> const& downloader){ |
874 | + qDebug() << "Downloader is" << static_cast<void*>(downloader.get()); |
875 | + int fd {-1}; |
876 | + if (downloader) { |
877 | + qDebug() << "Helper is " << static_cast<void*>(helper_.data()); |
878 | + auto restore_helper = qSharedPointerDynamicCast<RestoreHelper>(helper_); |
879 | + restore_helper->set_downloader(downloader); |
880 | + fd = restore_helper->get_helper_socket(); |
881 | + } |
882 | + qDebug("emitting task_socket_ready(socket=%d)", fd); |
883 | + Q_EMIT(q_ptr->task_socket_ready(fd)); |
884 | + } |
885 | + } |
886 | + ); |
887 | + } |
888 | +private: |
889 | + ConnectionHelper connections_; |
890 | +}; |
891 | + |
892 | +KeeperTaskRestore::KeeperTaskRestore(TaskData & task_data, |
893 | + QSharedPointer<HelperRegistry> const & helper_registry, |
894 | + QSharedPointer<StorageFrameworkClient> const & storage, |
895 | + QObject *parent) |
896 | + : KeeperTask(*new KeeperTaskRestorePrivate(this, task_data, helper_registry, storage), parent) |
897 | +{ |
898 | +} |
899 | + |
900 | +KeeperTaskRestore::~KeeperTaskRestore() = default; |
901 | + |
902 | +QStringList KeeperTaskRestore::get_helper_urls() const |
903 | +{ |
904 | + Q_D(const KeeperTaskRestore); |
905 | + |
906 | + return d->get_helper_urls(); |
907 | +} |
908 | + |
909 | +void KeeperTaskRestore::init_helper() |
910 | +{ |
911 | + Q_D(KeeperTaskRestore); |
912 | + |
913 | + d->init_helper(); |
914 | +} |
915 | + |
916 | +void KeeperTaskRestore::ask_for_downloader() |
917 | +{ |
918 | + Q_D(KeeperTaskRestore); |
919 | + |
920 | + d->ask_for_downloader(); |
921 | +} |
922 | |
923 | === added file 'src/service/keeper-task-restore.h' |
924 | --- src/service/keeper-task-restore.h 1970-01-01 00:00:00 +0000 |
925 | +++ src/service/keeper-task-restore.h 2016-11-17 00:23:33 +0000 |
926 | @@ -0,0 +1,46 @@ |
927 | +/* |
928 | + * Copyright (C) 2016 Canonical, Ltd. |
929 | + * |
930 | + * This program is free software: you can redistribute it and/or modify it |
931 | + * under the terms of the GNU General Public License version 3, as published |
932 | + * by the Free Software Foundation. |
933 | + * |
934 | + * This program is distributed in the hope that it will be useful, but |
935 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
936 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
937 | + * PURPOSE. See the GNU General Public License for more details. |
938 | + * |
939 | + * You should have received a copy of the GNU General Public License along |
940 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
941 | + * |
942 | + * Authors: |
943 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
944 | + * Charles Kerr <charles.kerr@canonical.com> |
945 | + */ |
946 | +#pragma once |
947 | + |
948 | +#include "keeper-task.h" |
949 | + |
950 | +class KeeperTaskRestorePrivate; |
951 | + |
952 | +class KeeperTaskRestore : public KeeperTask |
953 | +{ |
954 | + Q_OBJECT |
955 | + Q_DECLARE_PRIVATE(KeeperTaskRestore) |
956 | + |
957 | +public: |
958 | + KeeperTaskRestore(TaskData & task_data, |
959 | + QSharedPointer<HelperRegistry> const & helper_registry, |
960 | + QSharedPointer<StorageFrameworkClient> const & storage, |
961 | + QObject *parent = nullptr); |
962 | + virtual ~KeeperTaskRestore(); |
963 | + |
964 | + Q_DISABLE_COPY(KeeperTaskRestore) |
965 | + |
966 | + void ask_for_downloader(); |
967 | + |
968 | +protected: |
969 | + QStringList get_helper_urls() const override; |
970 | + void init_helper() override; |
971 | + |
972 | +}; |
973 | |
974 | === modified file 'src/service/keeper-task.cpp' |
975 | --- src/service/keeper-task.cpp 2016-09-30 09:23:09 +0000 |
976 | +++ src/service/keeper-task.cpp 2016-11-17 00:23:33 +0000 |
977 | @@ -28,7 +28,7 @@ |
978 | #include <QString> |
979 | |
980 | KeeperTaskPrivate::KeeperTaskPrivate(KeeperTask * keeper_task, |
981 | - KeeperTask::TaskData const & task_data, |
982 | + KeeperTask::TaskData & task_data, |
983 | QSharedPointer<HelperRegistry> const & helper_registry, |
984 | QSharedPointer<StorageFrameworkClient> const & storage) |
985 | : q_ptr(keeper_task) |
986 | @@ -132,7 +132,7 @@ |
987 | auto const percent_done = helper_->percent_done(); |
988 | ret.insert(QStringLiteral("percent-done"), double(percent_done)); |
989 | |
990 | - if (task_data_.action == "failed") |
991 | + if (task_data_.action == "failed" || task_data_.action == "cancelled") |
992 | ret.insert(QStringLiteral("error"), task_data_.error); |
993 | |
994 | ret.insert(QStringLiteral("uuid"), uuid); |
995 | @@ -145,8 +145,13 @@ |
996 | |
997 | void KeeperTaskPrivate::calculate_and_notify_state(Helper::State state) |
998 | { |
999 | + recalculate_task_state(); |
1000 | + Q_EMIT(q_ptr->task_state_changed(state)); |
1001 | +} |
1002 | + |
1003 | +void KeeperTaskPrivate::recalculate_task_state() |
1004 | +{ |
1005 | state_ = calculate_task_state(); |
1006 | - Q_EMIT(q_ptr->task_state_changed(state)); |
1007 | } |
1008 | |
1009 | void KeeperTaskPrivate::cancel() |
1010 | @@ -175,7 +180,20 @@ |
1011 | return ret; |
1012 | } |
1013 | |
1014 | -KeeperTask::KeeperTask(TaskData const & task_data, |
1015 | +QString KeeperTaskPrivate::to_string(Helper::State state) |
1016 | +{ |
1017 | + if (helper_) |
1018 | + { |
1019 | + return helper_->to_string(state); |
1020 | + } |
1021 | + else |
1022 | + { |
1023 | + qWarning() << "Asking for the string of a state when the helper is not initialized yet"; |
1024 | + return "bug"; |
1025 | + } |
1026 | +} |
1027 | + |
1028 | +KeeperTask::KeeperTask(TaskData & task_data, |
1029 | QSharedPointer<HelperRegistry> const & helper_registry, |
1030 | QSharedPointer<StorageFrameworkClient> const & storage, |
1031 | QObject *parent) |
1032 | @@ -207,6 +225,14 @@ |
1033 | return d->state(); |
1034 | } |
1035 | |
1036 | +void KeeperTask::recalculate_task_state() |
1037 | +{ |
1038 | + Q_D(KeeperTask); |
1039 | + |
1040 | + return d->recalculate_task_state(); |
1041 | +} |
1042 | + |
1043 | + |
1044 | QVariantMap KeeperTask::get_initial_state(KeeperTask::TaskData const &td) |
1045 | { |
1046 | return KeeperTaskPrivate::get_initial_state(td); |
1047 | @@ -218,3 +244,10 @@ |
1048 | |
1049 | return d->cancel(); |
1050 | } |
1051 | + |
1052 | +QString KeeperTask::to_string(Helper::State state) |
1053 | +{ |
1054 | + Q_D(KeeperTask); |
1055 | + |
1056 | + return d->to_string(state); |
1057 | +} |
1058 | |
1059 | === modified file 'src/service/keeper-task.h' |
1060 | --- src/service/keeper-task.h 2016-09-28 13:42:21 +0000 |
1061 | +++ src/service/keeper-task.h 2016-11-17 00:23:33 +0000 |
1062 | @@ -44,7 +44,7 @@ |
1063 | Metadata metadata; |
1064 | }; |
1065 | |
1066 | - KeeperTask(TaskData const & task_data, |
1067 | + KeeperTask(TaskData & task_data, |
1068 | QSharedPointer<HelperRegistry> const & helper_registry, |
1069 | QSharedPointer<StorageFrameworkClient> const & storage, |
1070 | QObject *parent = nullptr); |
1071 | @@ -54,11 +54,13 @@ |
1072 | |
1073 | bool start(); |
1074 | QVariantMap state() const; |
1075 | + void recalculate_task_state(); |
1076 | |
1077 | static QVariantMap get_initial_state(KeeperTask::TaskData const &td); |
1078 | |
1079 | void cancel(); |
1080 | |
1081 | + QString to_string(Helper::State state); |
1082 | Q_SIGNALS: |
1083 | void task_state_changed(Helper::State state); |
1084 | void task_socket_ready(int socket_descriptor); |
1085 | |
1086 | === modified file 'src/service/keeper-user.cpp' |
1087 | --- src/service/keeper-user.cpp 2016-10-28 15:11:21 +0000 |
1088 | +++ src/service/keeper-user.cpp 2016-11-17 00:23:33 +0000 |
1089 | @@ -70,9 +70,11 @@ |
1090 | void |
1091 | KeeperUser::StartRestore (const QStringList& keys) |
1092 | { |
1093 | - // FIXME: writeme |
1094 | + Q_ASSERT(calledFromDBus()); |
1095 | |
1096 | - qDebug() << keys; |
1097 | + auto bus = connection(); |
1098 | + auto& msg = message(); |
1099 | + keeper_.start_tasks(keys, bus, msg, true); |
1100 | } |
1101 | |
1102 | QVariantDictMap |
1103 | |
1104 | === modified file 'src/service/keeper.cpp' |
1105 | --- src/service/keeper.cpp 2016-10-28 15:11:21 +0000 |
1106 | +++ src/service/keeper.cpp 2016-11-17 00:23:33 +0000 |
1107 | @@ -76,14 +76,25 @@ |
1108 | { |
1109 | } |
1110 | |
1111 | + enum class ChoicesType { BACKUP_CHOICES, RESTORES_CHOICES }; |
1112 | + |
1113 | ~KeeperPrivate() =default; |
1114 | |
1115 | Q_DISABLE_COPY(KeeperPrivate) |
1116 | |
1117 | void start_tasks(QStringList const & uuids, |
1118 | - QDBusConnection bus, |
1119 | - QDBusMessage const & msg) |
1120 | + QDBusConnection bus, |
1121 | + QDBusMessage const & msg, |
1122 | + bool reset_cached_choices) |
1123 | { |
1124 | + if (reset_cached_choices) |
1125 | + { |
1126 | + // if we start a restore right after a backup the uuid |
1127 | + // will be found as a backup uuid. |
1128 | + // Just clear the backup cache to avoid that. |
1129 | + cached_backup_choices_.clear(); |
1130 | + } |
1131 | + |
1132 | auto get_tasks = [](const QVector<Metadata>& pool, QStringList const& keys){ |
1133 | QMap<QString,Metadata> tasks; |
1134 | for (auto const& key : keys) { |
1135 | @@ -95,9 +106,10 @@ |
1136 | }; |
1137 | |
1138 | // async part |
1139 | + qDebug() << "Looking for backup options...."; |
1140 | connections_.connect_oneshot( |
1141 | this, |
1142 | - &KeeperPrivate::choices_ready, |
1143 | + &KeeperPrivate::backup_choices_ready, |
1144 | std::function<void()>{[this, uuids, msg, bus, get_tasks](){ |
1145 | auto tasks = get_tasks(cached_backup_choices_, uuids); |
1146 | if (!tasks.empty()) |
1147 | @@ -114,12 +126,15 @@ |
1148 | } |
1149 | else // restore |
1150 | { |
1151 | + qDebug() << "Looking for restore options...."; |
1152 | connections_.connect_oneshot( |
1153 | this, |
1154 | - &KeeperPrivate::choices_ready, |
1155 | + &KeeperPrivate::restore_choices_ready, |
1156 | std::function<void()>{[this, uuids, msg, bus, get_tasks](){ |
1157 | + qDebug() << "Choices ready"; |
1158 | auto unhandled = QSet<QString>::fromList(uuids); |
1159 | auto restore_tasks = get_tasks(cached_restore_choices_, uuids); |
1160 | + qDebug() << "After getting tasks..."; |
1161 | if (!restore_tasks.empty() && task_manager_.start_restore(restore_tasks.values())) |
1162 | unhandled.subtract(QSet<QString>::fromList(restore_tasks.keys())); |
1163 | |
1164 | @@ -130,34 +145,58 @@ |
1165 | bus.send(reply); |
1166 | }} |
1167 | ); |
1168 | - get_restore_choices(); |
1169 | + get_choices(restore_choices_, KeeperPrivate::ChoicesType::RESTORES_CHOICES); |
1170 | } |
1171 | }} |
1172 | ); |
1173 | |
1174 | - get_backup_choices(); |
1175 | + get_choices(backup_choices_, KeeperPrivate::ChoicesType::BACKUP_CHOICES); |
1176 | msg.setDelayedReply(true); |
1177 | } |
1178 | |
1179 | - void get_backup_choices() |
1180 | - { |
1181 | - if (cached_backup_choices_.isEmpty()) |
1182 | + void emit_choices_ready(ChoicesType type) |
1183 | + { |
1184 | + switch(type) |
1185 | + { |
1186 | + case KeeperPrivate::ChoicesType::BACKUP_CHOICES: |
1187 | + Q_EMIT(backup_choices_ready()); |
1188 | + break; |
1189 | + case KeeperPrivate::ChoicesType::RESTORES_CHOICES: |
1190 | + Q_EMIT(restore_choices_ready()); |
1191 | + break; |
1192 | + } |
1193 | + } |
1194 | + void get_choices(const QSharedPointer<MetadataProvider> & provider, ChoicesType type) |
1195 | + { |
1196 | + qDebug() << Q_FUNC_INFO; |
1197 | + bool check_empty = (type == KeeperPrivate::ChoicesType::BACKUP_CHOICES) |
1198 | + ? cached_backup_choices_.isEmpty() : cached_restore_choices_.isEmpty(); |
1199 | + if (check_empty) |
1200 | { |
1201 | connections_.connect_oneshot( |
1202 | - backup_choices_.data(), |
1203 | + provider.data(), |
1204 | &MetadataProvider::finished, |
1205 | - std::function<void()>{[this](){ |
1206 | - qDebug() << "Get backups finished"; |
1207 | - cached_backup_choices_ = backup_choices_->get_backups(); |
1208 | - Q_EMIT(choices_ready()); |
1209 | + std::function<void()>{[this, provider, type](){ |
1210 | + qDebug() << "Get choices finished"; |
1211 | + switch (type) |
1212 | + { |
1213 | + case KeeperPrivate::ChoicesType::BACKUP_CHOICES: |
1214 | + cached_backup_choices_ = provider->get_backups(); |
1215 | + break; |
1216 | + case KeeperPrivate::ChoicesType::RESTORES_CHOICES: |
1217 | + cached_restore_choices_ = provider->get_backups(); |
1218 | + break; |
1219 | + }; |
1220 | + emit_choices_ready(type); |
1221 | }} |
1222 | ); |
1223 | |
1224 | - backup_choices_->get_backups_async(); |
1225 | + provider->get_backups_async(); |
1226 | } |
1227 | else |
1228 | { |
1229 | - Q_EMIT(choices_ready()); |
1230 | + qDebug() << "emit choices_ready()"; |
1231 | + emit_choices_ready(type); |
1232 | } |
1233 | } |
1234 | |
1235 | @@ -166,7 +205,7 @@ |
1236 | { |
1237 | connections_.connect_oneshot( |
1238 | this, |
1239 | - &KeeperPrivate::choices_ready, |
1240 | + &KeeperPrivate::backup_choices_ready, |
1241 | std::function<void()>{[this, msg, bus](){ |
1242 | qDebug() << "Backup choices are ready"; |
1243 | // reply now to the dbus call |
1244 | @@ -176,7 +215,7 @@ |
1245 | }} |
1246 | ); |
1247 | |
1248 | - get_backup_choices(); |
1249 | + get_choices(backup_choices_, KeeperPrivate::ChoicesType::BACKUP_CHOICES); |
1250 | msg.setDelayedReply(true); |
1251 | return QVariantDictMap(); |
1252 | } |
1253 | @@ -186,7 +225,7 @@ |
1254 | { |
1255 | connections_.connect_oneshot( |
1256 | this, |
1257 | - &KeeperPrivate::choices_ready, |
1258 | + &KeeperPrivate::restore_choices_ready, |
1259 | std::function<void()>{[this, msg, bus](){ |
1260 | qDebug() << "Restore choices are ready"; |
1261 | // reply now to the dbus call |
1262 | @@ -196,34 +235,11 @@ |
1263 | }} |
1264 | ); |
1265 | |
1266 | - get_restore_choices(); |
1267 | + get_choices(restore_choices_, KeeperPrivate::ChoicesType::RESTORES_CHOICES); |
1268 | msg.setDelayedReply(true); |
1269 | return QVariantDictMap(); |
1270 | } |
1271 | |
1272 | - // TODO REFACTOR THIS TO USE THE SAME METHOD POR RESTORES AND BACKUPS |
1273 | - void get_restore_choices() |
1274 | - { |
1275 | - if (cached_restore_choices_.isEmpty()) |
1276 | - { |
1277 | - connections_.connect_oneshot( |
1278 | - restore_choices_.data(), |
1279 | - &MetadataProvider::finished, |
1280 | - std::function<void()>{[this](){ |
1281 | - qDebug() << "Get restores finished"; |
1282 | - cached_restore_choices_ = restore_choices_->get_backups(); |
1283 | - Q_EMIT(choices_ready()); |
1284 | - }} |
1285 | - ); |
1286 | - |
1287 | - restore_choices_->get_backups_async(); |
1288 | - } |
1289 | - else |
1290 | - { |
1291 | - Q_EMIT(choices_ready()); |
1292 | - } |
1293 | - } |
1294 | - |
1295 | QVariantDictMap get_state() const |
1296 | { |
1297 | return task_manager_.get_state(); |
1298 | @@ -233,7 +249,7 @@ |
1299 | QDBusMessage const & msg, |
1300 | quint64 n_bytes) |
1301 | { |
1302 | - qDebug("Keeper::StartBackup(n_bytes=%zu)", size_t(n_bytes)); |
1303 | + qDebug() << Q_FUNC_INFO << "n_bytes:" << n_bytes; |
1304 | |
1305 | connections_.connect_oneshot( |
1306 | &task_manager_, |
1307 | @@ -248,7 +264,7 @@ |
1308 | } |
1309 | ); |
1310 | |
1311 | - qDebug() << "Asking for an storage framework socket to the task manager"; |
1312 | + qDebug() << "Asking TaskManager for a socket to upload to"; |
1313 | task_manager_.ask_for_uploader(n_bytes); |
1314 | |
1315 | // tell the caller that we'll be responding async |
1316 | @@ -256,12 +272,41 @@ |
1317 | return QDBusUnixFileDescriptor(0); |
1318 | } |
1319 | |
1320 | + |
1321 | + QDBusUnixFileDescriptor start_restore(QDBusConnection bus, |
1322 | + QDBusMessage const & msg) |
1323 | + { |
1324 | + qDebug() << Q_FUNC_INFO; |
1325 | + |
1326 | + connections_.connect_oneshot( |
1327 | + &task_manager_, |
1328 | + &TaskManager::socket_ready, |
1329 | + std::function<void(int)>{ |
1330 | + [bus,msg](int fd){ |
1331 | + qDebug("TaskManager::ask_for_downloader() returned socket %d", fd); |
1332 | + auto reply = msg.createReply(); |
1333 | + reply << QVariant::fromValue(QDBusUnixFileDescriptor(fd)); |
1334 | + bus.send(reply); |
1335 | + } |
1336 | + } |
1337 | + ); |
1338 | + |
1339 | + qDebug() << "Asking TaskManager for a socket to download from"; |
1340 | + task_manager_.ask_for_downloader(); |
1341 | + |
1342 | + // tell the caller that we'll be responding async |
1343 | + msg.setDelayedReply(true); |
1344 | + return QDBusUnixFileDescriptor(0); |
1345 | + } |
1346 | + |
1347 | void cancel() |
1348 | { |
1349 | task_manager_.cancel(); |
1350 | } |
1351 | + |
1352 | Q_SIGNALS: |
1353 | - void choices_ready(); |
1354 | + void backup_choices_ready(); |
1355 | + void restore_choices_ready(); |
1356 | |
1357 | private: |
1358 | |
1359 | @@ -305,11 +350,12 @@ |
1360 | void |
1361 | Keeper::start_tasks(QStringList const & uuids, |
1362 | QDBusConnection bus, |
1363 | - QDBusMessage const & msg) |
1364 | + QDBusMessage const & msg, |
1365 | + bool reset_cached_choices) |
1366 | { |
1367 | Q_D(Keeper); |
1368 | |
1369 | - d->start_tasks(uuids, bus, msg); |
1370 | + d->start_tasks(uuids, bus, msg, reset_cached_choices); |
1371 | } |
1372 | |
1373 | QDBusUnixFileDescriptor |
1374 | @@ -322,6 +368,15 @@ |
1375 | return d->start_backup(bus, msg, n_bytes); |
1376 | } |
1377 | |
1378 | +QDBusUnixFileDescriptor |
1379 | +Keeper::StartRestore(QDBusConnection bus, |
1380 | + QDBusMessage const & msg) |
1381 | +{ |
1382 | + Q_D(Keeper); |
1383 | + |
1384 | + return d->start_restore(bus, msg); |
1385 | +} |
1386 | + |
1387 | QVariantDictMap |
1388 | Keeper::get_backup_choices_var_dict_map(QDBusConnection bus, |
1389 | QDBusMessage const & msg) |
1390 | |
1391 | === modified file 'src/service/keeper.h' |
1392 | --- src/service/keeper.h 2016-10-28 15:11:21 +0000 |
1393 | +++ src/service/keeper.h 2016-11-17 00:23:33 +0000 |
1394 | @@ -59,9 +59,14 @@ |
1395 | QDBusMessage const & message, |
1396 | quint64 nbytes); |
1397 | |
1398 | + |
1399 | + QDBusUnixFileDescriptor StartRestore(QDBusConnection, |
1400 | + QDBusMessage const & message); |
1401 | + |
1402 | void start_tasks(QStringList const & uuids, |
1403 | QDBusConnection bus, |
1404 | - QDBusMessage const & msg); |
1405 | + QDBusMessage const & msg, |
1406 | + bool reset_cached_choices = false); |
1407 | |
1408 | QVariantDictMap get_state() const; |
1409 | |
1410 | |
1411 | === modified file 'src/service/manifest.cpp' |
1412 | --- src/service/manifest.cpp 2016-10-13 12:22:31 +0000 |
1413 | +++ src/service/manifest.cpp 2016-11-17 00:23:33 +0000 |
1414 | @@ -110,8 +110,8 @@ |
1415 | { |
1416 | connections_.connect_future( |
1417 | storage_->get_new_downloader(dir_, MANIFEST_FILE_NAME), |
1418 | - std::function<void(sf::Downloader::SPtr const&)>{ |
1419 | - [this](sf::Downloader::SPtr const& downloader){ |
1420 | + std::function<void(std::shared_ptr<Downloader> const&)>{ |
1421 | + [this](std::shared_ptr<Downloader> const& downloader){ |
1422 | qDebug() << "Manifest downloader is" << static_cast<void*>(downloader.get()); |
1423 | if (downloader) |
1424 | { |
1425 | @@ -125,7 +125,7 @@ |
1426 | } |
1427 | auto json_content = socket->readAll(); |
1428 | from_json(json_content); |
1429 | - downloader->finish_download(); |
1430 | + downloader->finish(); |
1431 | finish(); |
1432 | } |
1433 | else |
1434 | |
1435 | === modified file 'src/service/private/keeper-task_p.h' |
1436 | --- src/service/private/keeper-task_p.h 2016-09-28 13:42:21 +0000 |
1437 | +++ src/service/private/keeper-task_p.h 2016-11-17 00:23:33 +0000 |
1438 | @@ -26,7 +26,7 @@ |
1439 | Q_DECLARE_PUBLIC(KeeperTask) |
1440 | public: |
1441 | KeeperTaskPrivate(KeeperTask * keeper_task, |
1442 | - KeeperTask::TaskData const & task_data, |
1443 | + KeeperTask::TaskData & task_data, |
1444 | QSharedPointer<HelperRegistry> const & helper_registry, |
1445 | QSharedPointer<StorageFrameworkClient> const & storage); |
1446 | |
1447 | @@ -40,17 +40,19 @@ |
1448 | |
1449 | static QVariantMap get_initial_state(KeeperTask::TaskData const &td); |
1450 | |
1451 | + QString to_string(Helper::State state); |
1452 | protected: |
1453 | void set_current_task_action(QString const& action); |
1454 | void on_helper_percent_done_changed(float percent_done); |
1455 | QVariantMap calculate_task_state(); |
1456 | void calculate_and_notify_state(Helper::State state); |
1457 | + void recalculate_task_state(); |
1458 | void on_backup_socket_ready(std::shared_ptr<QLocalSocket> const & sf_socket); |
1459 | |
1460 | virtual void on_helper_state_changed(Helper::State state); |
1461 | |
1462 | KeeperTask * const q_ptr; |
1463 | - KeeperTask::TaskData task_data_; |
1464 | + KeeperTask::TaskData & task_data_; |
1465 | QSharedPointer<HelperRegistry> helper_registry_; |
1466 | QSharedPointer<StorageFrameworkClient> storage_; |
1467 | QSharedPointer<Helper> helper_; |
1468 | |
1469 | === modified file 'src/service/task-manager.cpp' |
1470 | --- src/service/task-manager.cpp 2016-11-03 10:32:49 +0000 |
1471 | +++ src/service/task-manager.cpp 2016-11-17 00:23:33 +0000 |
1472 | @@ -20,6 +20,7 @@ |
1473 | |
1474 | #include "helper/metadata.h" |
1475 | #include "keeper-task-backup.h" |
1476 | +#include "keeper-task-restore.h" |
1477 | #include "manifest.h" |
1478 | #include "storage-framework/storage_framework_client.h" |
1479 | #include "task-manager.h" |
1480 | @@ -50,6 +51,7 @@ |
1481 | |
1482 | bool start_restore(QList<Metadata> const& tasks) |
1483 | { |
1484 | + qDebug() << "Starting restore..."; |
1485 | return start_tasks(tasks, Mode::RESTORE); |
1486 | } |
1487 | |
1488 | @@ -78,6 +80,23 @@ |
1489 | } |
1490 | } |
1491 | |
1492 | + void ask_for_downloader() |
1493 | + { |
1494 | + qDebug() << Q_FUNC_INFO; |
1495 | + |
1496 | + if (task_) |
1497 | + { |
1498 | + auto restore_task_ = qSharedPointerDynamicCast<KeeperTaskRestore>(task_); |
1499 | + if (!restore_task_) |
1500 | + { |
1501 | + qWarning() << "Only restore tasks are allowed to ask for storage framework downloaders"; |
1502 | + // TODO Mark this as an error at the current task and move to the next task |
1503 | + return; |
1504 | + } |
1505 | + restore_task_->ask_for_downloader(); |
1506 | + } |
1507 | + } |
1508 | + |
1509 | void cancel() |
1510 | { |
1511 | if (task_) |
1512 | @@ -140,19 +159,40 @@ |
1513 | return success; |
1514 | } |
1515 | |
1516 | + void manifest_stored(bool success) |
1517 | + { |
1518 | + qDebug() << "Manifest upload finished success = " << success << " current task=" << current_task_; |
1519 | + auto& td = task_data_[current_task_]; |
1520 | + if (success) |
1521 | + { |
1522 | + update_task_state(td); |
1523 | + } |
1524 | + else |
1525 | + { |
1526 | + td.error = "Error storing manifest file"; |
1527 | + set_current_task_action(task_->to_string(Helper::State::FAILED)); |
1528 | + } |
1529 | + active_manifest_.reset(); |
1530 | + } |
1531 | + |
1532 | void on_helper_state_changed(Helper::State state) |
1533 | { |
1534 | - qDebug() << "Task State changed"; |
1535 | + auto backup_task_ = qSharedPointerDynamicCast<KeeperTaskBackup>(task_); |
1536 | auto& td = task_data_[current_task_]; |
1537 | update_task_state(td); |
1538 | |
1539 | + // for the last completed backup task we delay updating the |
1540 | + // state until the manifest file is stored |
1541 | + if (remaining_tasks_.size() || state != Helper::State::COMPLETE) |
1542 | + update_task_state(td); |
1543 | + |
1544 | if (state == Helper::State::COMPLETE || state == Helper::State::FAILED) |
1545 | { |
1546 | - auto backup_task_ = qSharedPointerDynamicCast<KeeperTaskBackup>(task_); |
1547 | if (backup_task_ && state == Helper::State::COMPLETE && active_manifest_) |
1548 | { |
1549 | qDebug() << "Backup task finished. The file created in storage framework is: [" << backup_task_->get_file_name() << "]"; |
1550 | td.metadata.set_property(Metadata::FILE_NAME_KEY, backup_task_->get_file_name()); |
1551 | + td.metadata.set_property(Metadata::DIR_NAME_KEY, backup_dir_name_); |
1552 | active_manifest_->add_entry(td.metadata); |
1553 | } |
1554 | if (remaining_tasks_.size()) |
1555 | @@ -162,9 +202,6 @@ |
1556 | } |
1557 | else |
1558 | { |
1559 | - // TODO we should revisit this. |
1560 | - // TODO Maybe we could treat the manifest storage as a new task (with a different task type) to check |
1561 | - // TODO when all tasks are finished and prompt something to the user. |
1562 | if (active_manifest_ && active_manifest_->get_entries().size()) |
1563 | { |
1564 | qDebug() << "STORING MANIFEST------------"; |
1565 | @@ -172,11 +209,7 @@ |
1566 | active_manifest_.data(), |
1567 | &Manifest::finished, |
1568 | std::function<void(bool)>{[this](bool success){ |
1569 | - if (!success) |
1570 | - qWarning() << "Manifest store finished with error: " << active_manifest_->error(); |
1571 | - else |
1572 | - qDebug() << "Manifest store finished successfully"; |
1573 | - active_manifest_.reset(); |
1574 | + manifest_stored(success); |
1575 | }} |
1576 | ); |
1577 | active_manifest_->store(); |
1578 | @@ -203,14 +236,16 @@ |
1579 | qDebug() << "Creating task for uuid = " << uuid; |
1580 | // initialize a new task |
1581 | |
1582 | - task_.data()->disconnect(); |
1583 | + if (task_) |
1584 | + task_.data()->disconnect(); |
1585 | + |
1586 | if (mode_ == Mode::BACKUP) |
1587 | { |
1588 | task_.reset(new KeeperTaskBackup(td, helper_registry_, storage_)); |
1589 | } |
1590 | else |
1591 | { |
1592 | - // TODO initialize a Restore task |
1593 | + task_.reset(new KeeperTaskRestore(td, helper_registry_, storage_)); |
1594 | } |
1595 | |
1596 | qDebug() << "task created: " << state_; |
1597 | @@ -311,6 +346,7 @@ |
1598 | { |
1599 | auto& td = task_data_[current_task_]; |
1600 | td.action = action; |
1601 | + task_->recalculate_task_state(); |
1602 | update_task_state(td); |
1603 | } |
1604 | |
1605 | @@ -381,6 +417,13 @@ |
1606 | d->ask_for_uploader(n_bytes); |
1607 | } |
1608 | |
1609 | +void TaskManager::ask_for_downloader() |
1610 | +{ |
1611 | + Q_D(TaskManager); |
1612 | + |
1613 | + d->ask_for_downloader(); |
1614 | +} |
1615 | + |
1616 | void TaskManager::cancel() |
1617 | { |
1618 | Q_D(TaskManager); |
1619 | |
1620 | === modified file 'src/service/task-manager.h' |
1621 | --- src/service/task-manager.h 2016-09-28 13:42:21 +0000 |
1622 | +++ src/service/task-manager.h 2016-11-17 00:23:33 +0000 |
1623 | @@ -58,6 +58,8 @@ |
1624 | |
1625 | void ask_for_uploader(quint64 n_bytes); |
1626 | |
1627 | + void ask_for_downloader(); |
1628 | + |
1629 | void cancel(); |
1630 | |
1631 | Q_SIGNALS: |
1632 | |
1633 | === modified file 'src/storage-framework/CMakeLists.txt' |
1634 | --- src/storage-framework/CMakeLists.txt 2016-09-05 17:24:18 +0000 |
1635 | +++ src/storage-framework/CMakeLists.txt 2016-11-17 00:23:33 +0000 |
1636 | @@ -11,6 +11,9 @@ |
1637 | uploader.h |
1638 | sf-uploader.cpp |
1639 | sf-uploader.h |
1640 | + downloader.h |
1641 | + sf-downloader.cpp |
1642 | + sf-downloader.h |
1643 | ) |
1644 | |
1645 | set_target_properties( |
1646 | |
1647 | === added file 'src/storage-framework/downloader.h' |
1648 | --- src/storage-framework/downloader.h 1970-01-01 00:00:00 +0000 |
1649 | +++ src/storage-framework/downloader.h 2016-11-17 00:23:33 +0000 |
1650 | @@ -0,0 +1,46 @@ |
1651 | +/* |
1652 | + * Copyright (C) 2016 Canonical, Ltd. |
1653 | + * |
1654 | + * This program is free software: you can redistribute it and/or modify it |
1655 | + * under the terms of the GNU General Public License version 3, as published |
1656 | + * by the Free Software Foundation. |
1657 | + * |
1658 | + * This program is distributed in the hope that it will be useful, but |
1659 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1660 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1661 | + * PURPOSE. See the GNU General Public License for more details. |
1662 | + * |
1663 | + * You should have received a copy of the GNU General Public License along |
1664 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1665 | + * |
1666 | + * Authors: |
1667 | + * Charles Kerr <charles.kerr@canonical.com> |
1668 | + * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> |
1669 | + */ |
1670 | + |
1671 | +#pragma once |
1672 | + |
1673 | +#include <QLocalSocket> |
1674 | +#include <QObject> |
1675 | + |
1676 | +#include <memory> |
1677 | + |
1678 | +class Downloader: public QObject |
1679 | +{ |
1680 | + Q_OBJECT |
1681 | + |
1682 | +public: |
1683 | + |
1684 | + Q_DISABLE_COPY(Downloader) |
1685 | + |
1686 | + Downloader(QObject *parent=nullptr): QObject(parent) {} |
1687 | + virtual ~Downloader() =default; |
1688 | + |
1689 | + virtual std::shared_ptr<QLocalSocket> socket() =0; |
1690 | + virtual void finish() =0; |
1691 | + virtual qint64 file_size() const =0; |
1692 | + |
1693 | +Q_SIGNALS: |
1694 | + |
1695 | + void download_finished(); |
1696 | +}; |
1697 | |
1698 | === added file 'src/storage-framework/sf-downloader.cpp' |
1699 | --- src/storage-framework/sf-downloader.cpp 1970-01-01 00:00:00 +0000 |
1700 | +++ src/storage-framework/sf-downloader.cpp 2016-11-17 00:23:33 +0000 |
1701 | @@ -0,0 +1,71 @@ |
1702 | +/* |
1703 | + * Copyright (C) 2016 Canonical, Ltd. |
1704 | + * |
1705 | + * This program is free software: you can redistribute it and/or modify it |
1706 | + * under the terms of the GNU General Public License version 3, as published |
1707 | + * by the Free Software Foundation. |
1708 | + * |
1709 | + * This program is distributed in the hope that it will be useful, but |
1710 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1711 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1712 | + * PURPOSE. See the GNU General Public License for more details. |
1713 | + * |
1714 | + * You should have received a copy of the GNU General Public License along |
1715 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1716 | + * |
1717 | + * Authors: |
1718 | + * Charles Kerr <charles.kerr@canonical.com> |
1719 | + * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> |
1720 | + */ |
1721 | + |
1722 | +#include "storage-framework/sf-downloader.h" |
1723 | + |
1724 | +#include <QFuture> |
1725 | +#include <QFutureWatcher> |
1726 | + |
1727 | +StorageFrameworkDownloader::StorageFrameworkDownloader( |
1728 | + unity::storage::qt::client::Downloader::SPtr const& downloader, |
1729 | + qint64 file_size, |
1730 | + QObject *parent |
1731 | +): |
1732 | + Downloader(parent), |
1733 | + downloader_(downloader), |
1734 | + file_size_(file_size) |
1735 | +{ |
1736 | + qDebug() << "StorageFrameworkDownloader"; |
1737 | +} |
1738 | + |
1739 | +std::shared_ptr<QLocalSocket> |
1740 | +StorageFrameworkDownloader::socket() |
1741 | +{ |
1742 | + return downloader_->socket(); |
1743 | +} |
1744 | + |
1745 | +void |
1746 | +StorageFrameworkDownloader::finish() |
1747 | +{ |
1748 | + qDebug() << Q_FUNC_INFO << "is finishing"; |
1749 | + |
1750 | +// connections_.connect_future( |
1751 | +// uploader_->finish_upload(), |
1752 | +// std::function<void(std::shared_ptr<unity::storage::qt::client::File> const&)>{ |
1753 | +// [this](std::shared_ptr<unity::storage::qt::client::File> const& file){ |
1754 | +// auto const success = bool(file); |
1755 | +// qDebug() << "commit finished with" << success; |
1756 | +// if (success) |
1757 | +// { |
1758 | +// file_name_after_commit_ = file->name(); |
1759 | +// } |
1760 | +// Q_EMIT(commit_finished(success)); |
1761 | +// } |
1762 | +// } |
1763 | +// ); |
1764 | + downloader_->finish_download(); |
1765 | + Q_EMIT(download_finished()); // TODO add the code to call finish_download |
1766 | +} |
1767 | + |
1768 | +qint64 |
1769 | +StorageFrameworkDownloader::file_size() const |
1770 | +{ |
1771 | + return file_size_; |
1772 | +} |
1773 | |
1774 | === added file 'src/storage-framework/sf-downloader.h' |
1775 | --- src/storage-framework/sf-downloader.h 1970-01-01 00:00:00 +0000 |
1776 | +++ src/storage-framework/sf-downloader.h 2016-11-17 00:23:33 +0000 |
1777 | @@ -0,0 +1,48 @@ |
1778 | +/* |
1779 | + * Copyright (C) 2016 Canonical, Ltd. |
1780 | + * |
1781 | + * This program is free software: you can redistribute it and/or modify it |
1782 | + * under the terms of the GNU General Public License version 3, as published |
1783 | + * by the Free Software Foundation. |
1784 | + * |
1785 | + * This program is distributed in the hope that it will be useful, but |
1786 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1787 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1788 | + * PURPOSE. See the GNU General Public License for more details. |
1789 | + * |
1790 | + * You should have received a copy of the GNU General Public License along |
1791 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1792 | + * |
1793 | + * Authors: |
1794 | + * Charles Kerr <charles.kerr@canonical.com> |
1795 | + */ |
1796 | + |
1797 | +#pragma once |
1798 | + |
1799 | +#include "util/connection-helper.h" |
1800 | +#include "storage-framework/downloader.h" |
1801 | + |
1802 | +#include <unity/storage/qt/client/client-api.h> |
1803 | + |
1804 | +#include <QLocalSocket> |
1805 | + |
1806 | +#include <memory> |
1807 | + |
1808 | +class StorageFrameworkDownloader final: public Downloader |
1809 | +{ |
1810 | +public: |
1811 | + |
1812 | + StorageFrameworkDownloader(unity::storage::qt::client::Downloader::SPtr const& uploader, |
1813 | + qint64 file_size, |
1814 | + QObject * parent = nullptr); |
1815 | + std::shared_ptr<QLocalSocket> socket() override; |
1816 | + void finish() override; |
1817 | + qint64 file_size() const override; |
1818 | + |
1819 | +private: |
1820 | + |
1821 | + unity::storage::qt::client::Downloader::SPtr const downloader_; |
1822 | + qint64 file_size_; |
1823 | + |
1824 | + ConnectionHelper connections_; |
1825 | +}; |
1826 | |
1827 | === modified file 'src/storage-framework/storage_framework_client.cpp' |
1828 | --- src/storage-framework/storage_framework_client.cpp 2016-11-03 10:32:49 +0000 |
1829 | +++ src/storage-framework/storage_framework_client.cpp 2016-11-17 00:23:33 +0000 |
1830 | @@ -19,6 +19,7 @@ |
1831 | */ |
1832 | |
1833 | #include "storage-framework/storage_framework_client.h" |
1834 | +#include "storage-framework/sf-downloader.h" |
1835 | #include "storage-framework/sf-uploader.h" |
1836 | |
1837 | #include <QDateTime> |
1838 | @@ -39,7 +40,7 @@ |
1839 | { |
1840 | } |
1841 | |
1842 | -StorageFrameworkClient::~StorageFrameworkClient() =default; |
1843 | +StorageFrameworkClient::~StorageFrameworkClient() = default; |
1844 | |
1845 | /*** |
1846 | **** |
1847 | @@ -154,10 +155,10 @@ |
1848 | return fi.future(); |
1849 | } |
1850 | |
1851 | -QFuture<sf::Downloader::SPtr> |
1852 | +QFuture<std::shared_ptr<Downloader>> |
1853 | StorageFrameworkClient::get_new_downloader(QString const & dir_name, QString const & file_name) |
1854 | { |
1855 | - QFutureInterface<sf::Downloader::SPtr> fi; |
1856 | + QFutureInterface<std::shared_ptr<Downloader>> fi; |
1857 | |
1858 | add_roots_task([this, fi, dir_name, file_name](QVector<sf::Root::SPtr> const& roots) |
1859 | { |
1860 | @@ -171,7 +172,7 @@ |
1861 | if (!keeper_root) |
1862 | { |
1863 | qWarning() << "Error accessing keeper root folder"; |
1864 | - sf::Downloader::SPtr ret; |
1865 | + std::shared_ptr<Downloader> ret; |
1866 | QFutureInterface<decltype(ret)> qfi(fi); |
1867 | qfi.reportResult(ret); |
1868 | qfi.reportFinished(); |
1869 | @@ -183,27 +184,27 @@ |
1870 | get_storage_framework_file(keeper_root, file_name), |
1871 | std::function<void(sf::File::SPtr const&)>{ |
1872 | [this, fi](sf::File::SPtr const& sf_file){ |
1873 | - sf::Downloader::SPtr ret_null; |
1874 | if (sf_file) { |
1875 | connection_helper_.connect_future( |
1876 | sf_file->create_downloader(), |
1877 | std::function<void(sf::Downloader::SPtr const&)>{ |
1878 | - [this, fi, ret_null](sf::Downloader::SPtr const& sf_downloader){ |
1879 | - QFutureInterface<decltype(ret_null)> qfi(fi); |
1880 | + [this, fi, sf_file](sf::Downloader::SPtr const& sf_downloader){ |
1881 | + std::shared_ptr<Downloader> ret; |
1882 | if (sf_downloader) |
1883 | { |
1884 | - qfi.reportResult(sf_downloader); |
1885 | - qfi.reportFinished(); |
1886 | - } |
1887 | - else |
1888 | - { |
1889 | - qfi.reportResult(ret_null); |
1890 | - qfi.reportFinished(); |
1891 | - } |
1892 | + ret.reset( |
1893 | + new StorageFrameworkDownloader(sf_downloader, sf_file->size(), this), |
1894 | + [](Downloader* d){d->deleteLater();} |
1895 | + ); |
1896 | + } |
1897 | + QFutureInterface<decltype(ret)> qfi(fi); |
1898 | + qfi.reportResult(ret); |
1899 | + qfi.reportFinished(); |
1900 | } |
1901 | } |
1902 | ); |
1903 | } else { |
1904 | + std::shared_ptr<Downloader> ret_null; |
1905 | QFutureInterface<decltype(ret_null)> qfi(fi); |
1906 | qfi.reportResult(ret_null); |
1907 | qfi.reportFinished(); |
1908 | |
1909 | === modified file 'src/storage-framework/storage_framework_client.h' |
1910 | --- src/storage-framework/storage_framework_client.h 2016-11-03 10:32:49 +0000 |
1911 | +++ src/storage-framework/storage_framework_client.h 2016-11-17 00:23:33 +0000 |
1912 | @@ -22,6 +22,7 @@ |
1913 | |
1914 | #include "util/connection-helper.h" |
1915 | #include "storage-framework/uploader.h" |
1916 | +#include "storage-framework/downloader.h" |
1917 | |
1918 | #include <unity/storage/qt/client/client-api.h> |
1919 | |
1920 | @@ -43,7 +44,7 @@ |
1921 | virtual ~StorageFrameworkClient(); |
1922 | |
1923 | QFuture<std::shared_ptr<Uploader>> get_new_uploader(int64_t n_bytes, QString const & dir_name, QString const & file_name); |
1924 | - QFuture<unity::storage::qt::client::Downloader::SPtr> get_new_downloader(QString const & dir_name, QString const & file_name); |
1925 | + QFuture<std::shared_ptr<Downloader>> get_new_downloader(QString const & dir_name, QString const & file_name); |
1926 | QFuture<QVector<QString>> get_keeper_dirs(); |
1927 | |
1928 | static QString const KEEPER_FOLDER; |
1929 | |
1930 | === added directory 'src/test-restore' |
1931 | === added file 'src/test-restore/CMakeLists.txt' |
1932 | --- src/test-restore/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1933 | +++ src/test-restore/CMakeLists.txt 2016-11-17 00:23:33 +0000 |
1934 | @@ -0,0 +1,40 @@ |
1935 | +set(TEST_RESTORE_EXEC "test-restore-socket") |
1936 | + |
1937 | +include_directories("${CMAKE_SOURCE_DIR}/src") |
1938 | +include_directories("${CMAKE_BINARY_DIR}/src/qdbus-stubs") |
1939 | +include_directories("${CMAKE_SOURCE_DIR}/src/qdbus-stubs") |
1940 | + |
1941 | +set(TEST_RESTORE_SOURCES |
1942 | + main.cpp |
1943 | + test-restore-socket.cpp |
1944 | +) |
1945 | + |
1946 | +add_executable( |
1947 | + ${TEST_RESTORE_EXEC} |
1948 | + ${TEST_RESTORE_SOURCES} |
1949 | +) |
1950 | + |
1951 | +link_directories( |
1952 | + ${SERVICE_DEPS_LIBRARY_DIRS} |
1953 | +) |
1954 | + |
1955 | +set( |
1956 | + RESTORE_STATIC_LIBS |
1957 | + storage-framework |
1958 | + util |
1959 | +# qdbus-stubs |
1960 | +) |
1961 | + |
1962 | +target_link_libraries( |
1963 | + ${TEST_RESTORE_EXEC} |
1964 | + ${RESTORE_STATIC_LIBS} |
1965 | + ${SERVICE_DEVEL_SF_DEPS_LIBRARIES} |
1966 | + Qt5::Core |
1967 | + Qt5::DBus |
1968 | +) |
1969 | + |
1970 | +install( |
1971 | + TARGETS |
1972 | + ${TEST_RESTORE_EXEC} |
1973 | + RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR} |
1974 | +) |
1975 | |
1976 | === added file 'src/test-restore/main.cpp' |
1977 | --- src/test-restore/main.cpp 1970-01-01 00:00:00 +0000 |
1978 | +++ src/test-restore/main.cpp 2016-11-17 00:23:33 +0000 |
1979 | @@ -0,0 +1,32 @@ |
1980 | +/* |
1981 | + * Copyright (C) 2016 Canonical, Ltd. |
1982 | + * |
1983 | + * This program is free software: you can redistribute it and/or modify it |
1984 | + * under the terms of the GNU General Public License version 3, as published |
1985 | + * by the Free Software Foundation. |
1986 | + * |
1987 | + * This program is distributed in the hope that it will be useful, but |
1988 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1989 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1990 | + * PURPOSE. See the GNU General Public License for more details. |
1991 | + * |
1992 | + * You should have received a copy of the GNU General Public License along |
1993 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1994 | + * |
1995 | + * Authors: |
1996 | + * Charles Kerr <charles.kerr@canonical.com> |
1997 | + * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> |
1998 | + */ |
1999 | +#include <QCoreApplication> |
2000 | + |
2001 | +#include "test-restore-socket.h" |
2002 | + |
2003 | +int main(int argc, char **argv) |
2004 | +{ |
2005 | + QCoreApplication app(argc, argv); |
2006 | + |
2007 | + TestRestoreSocket test_restore; |
2008 | + test_restore.start("test_dir", "test_file"); |
2009 | + |
2010 | + return app.exec(); |
2011 | +} |
2012 | |
2013 | === added file 'src/test-restore/test-restore-socket.cpp' |
2014 | --- src/test-restore/test-restore-socket.cpp 1970-01-01 00:00:00 +0000 |
2015 | +++ src/test-restore/test-restore-socket.cpp 2016-11-17 00:23:33 +0000 |
2016 | @@ -0,0 +1,139 @@ |
2017 | +/* |
2018 | + * Copyright (C) 2016 Canonical, Ltd. |
2019 | + * |
2020 | + * This program is free software: you can redistribute it and/or modify it |
2021 | + * under the terms of the GNU General Public License version 3, as published |
2022 | + * by the Free Software Foundation. |
2023 | + * |
2024 | + * This program is distributed in the hope that it will be useful, but |
2025 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2026 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2027 | + * PURPOSE. See the GNU General Public License for more details. |
2028 | + * |
2029 | + * You should have received a copy of the GNU General Public License along |
2030 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2031 | + * |
2032 | + * Authors: |
2033 | + * Charles Kerr <charles.kerr@canonical.com> |
2034 | + * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> |
2035 | + */ |
2036 | + |
2037 | +#include "test-restore-socket.h" |
2038 | + |
2039 | +#include "storage-framework/storage_framework_client.h" |
2040 | +#include "storage-framework/sf-downloader.h" |
2041 | + |
2042 | +constexpr int UPLOAD_BUFFER_MAX_ {1024*16}; |
2043 | + |
2044 | +TestRestoreSocket::TestRestoreSocket(QObject *parent) |
2045 | + : QObject(parent) |
2046 | + , sf_client_(new StorageFrameworkClient) |
2047 | + , file_("/tmp/test-downloader") |
2048 | +{ |
2049 | + file_.open(QIODevice::WriteOnly); |
2050 | + connect (&future_watcher_, &QFutureWatcher<std::shared_ptr<Downloader>>::finished, [this]{on_socket_received(future_watcher_.result());}); |
2051 | +} |
2052 | + |
2053 | +TestRestoreSocket::~TestRestoreSocket() = default; |
2054 | + |
2055 | +void TestRestoreSocket::start(QString const & dir_name, QString const & file_name) |
2056 | +{ |
2057 | + qDebug() << "asking storage framework for a socket for reading"; |
2058 | + |
2059 | + future_watcher_.setFuture(sf_client_->get_new_downloader(dir_name, file_name)); |
2060 | +// connections_.connect_future( |
2061 | +// sf_client_->get_new_downloader(dir_name, file_name), |
2062 | +// std::function<void(std::shared_ptr<Downloader> const&)>{ |
2063 | +// [this](std::shared_ptr<Downloader> const& downloader){ |
2064 | +// qDebug() << "Downloader is" << static_cast<void*>(downloader.get()); |
2065 | +// if (downloader) { |
2066 | +// this->on_socket_received(downloader); |
2067 | +// } |
2068 | +// } |
2069 | +// } |
2070 | +// ); |
2071 | +} |
2072 | + |
2073 | +void TestRestoreSocket::read_data() |
2074 | +{ |
2075 | + if (socket_->bytesAvailable()) |
2076 | + { |
2077 | +//// char readbuf[UPLOAD_BUFFER_MAX_]; |
2078 | +//// const auto n = socket_->read(readbuf, sizeof(readbuf)); |
2079 | +//// if (n > 0) { |
2080 | +//// n_read_ += n; |
2081 | +//// qDebug() << "Read " << n << " bytes. Total: " << n_read_; |
2082 | +// |
2083 | +// char readbuf[64 *1024]; |
2084 | +// // try to fill the upload buf |
2085 | +// int max_bytes = UPLOAD_BUFFER_MAX_;// - upload_buffer_.size(); |
2086 | +// if (max_bytes > 0) { |
2087 | +// const auto n = socket_->read(readbuf, max_bytes); |
2088 | +// if (n > 0) { |
2089 | +// n_read_ += n; |
2090 | +// qDebug() << "Read " << n << " bytes. Total: " << n_read_; |
2091 | +// |
2092 | +//// if (file_.isOpen()) |
2093 | +//// { |
2094 | +//// file_.write(readbuf, max_bytes); |
2095 | +//// } |
2096 | +//// } |
2097 | +//// else if (n < 0) { |
2098 | +//// qDebug() << "Read error: " << socket_->errorString(); |
2099 | +//// return; |
2100 | +// if (file_.isOpen()) |
2101 | +// { |
2102 | +// file_.write(readbuf, n); |
2103 | +// } |
2104 | +// } |
2105 | +// else if (n < 0) { |
2106 | +// qDebug() << "Read error: " << socket_->errorString(); |
2107 | +// return; |
2108 | +// } |
2109 | +// } |
2110 | + |
2111 | + char readbuf[64 *1024]; |
2112 | + const auto n = socket_->read(readbuf, sizeof(readbuf)); |
2113 | + if (n > 0) { |
2114 | + n_read_ += n; |
2115 | + qDebug() << "Read " << n << " bytes. Total: " << n_read_; |
2116 | + if (file_.isOpen()) |
2117 | + { |
2118 | + file_.write(readbuf, n); |
2119 | + } |
2120 | + } |
2121 | + else if (n < 0) { |
2122 | + qDebug() << "Read error: " << socket_->errorString(); |
2123 | + return; |
2124 | + } |
2125 | + } |
2126 | +} |
2127 | + |
2128 | +void TestRestoreSocket::on_disconnected() |
2129 | +{ |
2130 | + qDebug() << "Socket disconnected"; |
2131 | + auto avail = socket_->bytesAvailable(); |
2132 | + while (avail > 0) |
2133 | + { |
2134 | + read_data(); |
2135 | + avail = socket_->bytesAvailable(); |
2136 | + } |
2137 | + |
2138 | + if (file_.isOpen()) |
2139 | + { |
2140 | + file_.close(); |
2141 | + } |
2142 | +} |
2143 | + |
2144 | +void TestRestoreSocket::on_data_stored(qint64 /*n*/) |
2145 | +{ |
2146 | + read_data(); |
2147 | +} |
2148 | + |
2149 | +void TestRestoreSocket::on_socket_received(std::shared_ptr<Downloader> const & downloader) |
2150 | +{ |
2151 | + socket_ = downloader->socket(); |
2152 | + QObject::connect(socket_.get(), &QLocalSocket::readyRead, this, &TestRestoreSocket::read_data); |
2153 | + QObject::connect(socket_.get(), &QLocalSocket::disconnected, this, &TestRestoreSocket::on_disconnected); |
2154 | + QObject::connect(&file_, &QIODevice::bytesWritten, this, &TestRestoreSocket::on_data_stored); |
2155 | +} |
2156 | |
2157 | === added file 'src/test-restore/test-restore-socket.h' |
2158 | --- src/test-restore/test-restore-socket.h 1970-01-01 00:00:00 +0000 |
2159 | +++ src/test-restore/test-restore-socket.h 2016-11-17 00:23:33 +0000 |
2160 | @@ -0,0 +1,56 @@ |
2161 | +/* |
2162 | + * Copyright (C) 2016 Canonical, Ltd. |
2163 | + * |
2164 | + * This program is free software: you can redistribute it and/or modify it |
2165 | + * under the terms of the GNU General Public License version 3, as published |
2166 | + * by the Free Software Foundation. |
2167 | + * |
2168 | + * This program is distributed in the hope that it will be useful, but |
2169 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2170 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2171 | + * PURPOSE. See the GNU General Public License for more details. |
2172 | + * |
2173 | + * You should have received a copy of the GNU General Public License along |
2174 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2175 | + * |
2176 | + * Authors: |
2177 | + * Charles Kerr <charles.kerr@canonical.com> |
2178 | + * Xavi Garcia Mena <xavi.garcia.mena@canonical.com> |
2179 | + */ |
2180 | +#pragma once |
2181 | + |
2182 | +#include "util/connection-helper.h" |
2183 | + |
2184 | +#include <QObject> |
2185 | +#include <QScopedPointer> |
2186 | +#include <QFile> |
2187 | + |
2188 | +#include <memory> |
2189 | + |
2190 | +class QLocalSocket; |
2191 | +class StorageFrameworkClient; |
2192 | +class Downloader; |
2193 | + |
2194 | +class TestRestoreSocket : public QObject |
2195 | +{ |
2196 | + Q_OBJECT |
2197 | +public: |
2198 | + explicit TestRestoreSocket(QObject *parent = nullptr); |
2199 | + virtual ~TestRestoreSocket(); |
2200 | + |
2201 | + void start(QString const & dir_name, QString const & file_name); |
2202 | + |
2203 | +public Q_SLOTS: |
2204 | + void read_data(); |
2205 | + void on_socket_received(std::shared_ptr<Downloader> const & downloader); |
2206 | + void on_disconnected(); |
2207 | + void on_data_stored(qint64 n); |
2208 | + |
2209 | +private: |
2210 | + std::shared_ptr<QLocalSocket> socket_; |
2211 | + QScopedPointer<StorageFrameworkClient> sf_client_; |
2212 | + ConnectionHelper connections_; |
2213 | + qint64 n_read_ = 0; |
2214 | + QFile file_; |
2215 | + QFutureWatcher<std::shared_ptr<Downloader>> future_watcher_; |
2216 | +}; |
2217 | |
2218 | === modified file 'tests/CMakeLists.txt' |
2219 | --- tests/CMakeLists.txt 2016-09-05 13:54:15 +0000 |
2220 | +++ tests/CMakeLists.txt 2016-11-17 00:23:33 +0000 |
2221 | @@ -20,6 +20,11 @@ |
2222 | ) |
2223 | |
2224 | set( |
2225 | + RESTORE_HELPER |
2226 | + fake-restore-helper |
2227 | +) |
2228 | + |
2229 | +set( |
2230 | BACKUP_HELPER_FAILURE |
2231 | fake-backup-helper-failure |
2232 | ) |
2233 | @@ -27,6 +32,7 @@ |
2234 | set(KEEPER_TAR_CREATE_BIN ${CMAKE_BINARY_DIR}/src/tar/keeper-tar-create) |
2235 | set(KEEPER_HELPER_TEST_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/helpers-test.sh) |
2236 | set(BACKUP_HELPER_FAILURE_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/${BACKUP_HELPER_FAILURE}) |
2237 | +set(RESTORE_HELPER_TEST_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/${RESTORE_HELPER}) |
2238 | |
2239 | add_definitions( |
2240 | -DCMAKE_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}" |
2241 | |
2242 | === modified file 'tests/com_canonical_keeper.py' |
2243 | --- tests/com_canonical_keeper.py 2016-08-03 18:38:12 +0000 |
2244 | +++ tests/com_canonical_keeper.py 2016-11-17 00:23:33 +0000 |
2245 | @@ -1,3 +1,20 @@ |
2246 | +# Copyright (C) 2016 Canonical, Ltd. |
2247 | +# |
2248 | +# This program is free software: you can redistribute it and/or modify it |
2249 | +# under the terms of the GNU General Public License version 3, as published |
2250 | +# by the Free Software Foundation. |
2251 | +# |
2252 | +# This program is distributed in the hope that it will be useful, but |
2253 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
2254 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2255 | +# PURPOSE. See the GNU General Public License for more details. |
2256 | +# |
2257 | +# You should have received a copy of the GNU General Public License along |
2258 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
2259 | +# |
2260 | +# Authors: |
2261 | +# Charles Kerr <charles.kerr@canonical.com> |
2262 | + |
2263 | import copy |
2264 | import dbus |
2265 | import dbus.service |
2266 | |
2267 | === modified file 'tests/fakes/CMakeLists.txt' |
2268 | --- tests/fakes/CMakeLists.txt 2016-08-30 12:50:46 +0000 |
2269 | +++ tests/fakes/CMakeLists.txt 2016-11-17 00:23:33 +0000 |
2270 | @@ -30,6 +30,16 @@ |
2271 | ) |
2272 | |
2273 | add_executable( |
2274 | + ${RESTORE_HELPER} |
2275 | + fake-restore-helper.cpp |
2276 | + restore-reader.cpp |
2277 | +) |
2278 | +target_link_libraries( |
2279 | + ${RESTORE_HELPER} |
2280 | + ${LINK_LIBS} |
2281 | +) |
2282 | + |
2283 | +add_executable( |
2284 | ${BACKUP_HELPER_FAILURE} |
2285 | fake-backup-helper.cpp |
2286 | ) |
2287 | |
2288 | === added file 'tests/fakes/fake-restore-helper.cpp' |
2289 | --- tests/fakes/fake-restore-helper.cpp 1970-01-01 00:00:00 +0000 |
2290 | +++ tests/fakes/fake-restore-helper.cpp 2016-11-17 00:23:33 +0000 |
2291 | @@ -0,0 +1,101 @@ |
2292 | +/* |
2293 | + * Copyright (C) 2016 Canonical, Ltd. |
2294 | + * |
2295 | + * This program is free software: you can redistribute it and/or modify it |
2296 | + * under the terms of the GNU General Public License version 3, as published |
2297 | + * by the Free Software Foundation. |
2298 | + * |
2299 | + * This program is distributed in the hope that it will be useful, but |
2300 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2301 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2302 | + * PURPOSE. See the GNU General Public License for more details. |
2303 | + * |
2304 | + * You should have received a copy of the GNU General Public License along |
2305 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2306 | + * |
2307 | + * Authors: |
2308 | + * Charles Kerr <charles.kerr@canonical.com> |
2309 | + */ |
2310 | + |
2311 | +#include "fake-restore-helper.h" |
2312 | +#include "restore-reader.h" |
2313 | + |
2314 | +#include <qdbus-stubs/dbus-types.h> |
2315 | +#include <qdbus-stubs/keeper_helper_interface.h> |
2316 | + |
2317 | +#include <QCoreApplication> |
2318 | +#include <QDebug> |
2319 | +#include <QDBusConnection> |
2320 | +#include <QDBusInterface> |
2321 | +#include <QDBusReply> |
2322 | +#include <QProcessEnvironment> |
2323 | +#include <QLocalSocket> |
2324 | +#include <QtGlobal> |
2325 | + |
2326 | +#include <unistd.h> |
2327 | +#include <sys/ioctl.h> |
2328 | + |
2329 | +void myMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & msg) |
2330 | +{ |
2331 | + QString txt; |
2332 | + switch (type) { |
2333 | + case QtDebugMsg: |
2334 | + txt = QString("Debug: %1").arg(msg); |
2335 | + break; |
2336 | + case QtWarningMsg: |
2337 | + txt = QString("Warning: %1").arg(msg); |
2338 | + break; |
2339 | + case QtCriticalMsg: |
2340 | + txt = QString("Critical: %1").arg(msg); |
2341 | + break; |
2342 | + case QtFatalMsg: |
2343 | + txt = QString("Fatal: %1").arg(msg); |
2344 | + abort(); |
2345 | + } |
2346 | + QFile outFile("/tmp/restore-helper-output"); |
2347 | + outFile.open(QIODevice::WriteOnly | QIODevice::Append); |
2348 | + QTextStream ts(&outFile); |
2349 | + ts << txt << endl; |
2350 | +} |
2351 | + |
2352 | +int |
2353 | +main(int argc, char **argv) |
2354 | +{ |
2355 | + QCoreApplication app(argc, argv); |
2356 | + qInstallMessageHandler(myMessageHandler); |
2357 | + |
2358 | + // dump the inputs to stdout |
2359 | + qDebug() << "argc:" << argc; |
2360 | + for(int i=0; i<argc; ++i) |
2361 | + qDebug() << "argv[" << i << "] is" << argv[i]; |
2362 | + const auto env = QProcessEnvironment::systemEnvironment(); |
2363 | + for(const auto& key : env.keys()) |
2364 | + qDebug() << "env" << qPrintable(key) << "is" << qPrintable(env.value(key)); |
2365 | + |
2366 | + qDebug() << "Retrieving connection"; |
2367 | + |
2368 | + // ask the service for a socket |
2369 | + auto conn = QDBusConnection::connectToBus(QDBusConnection::SessionBus, DBusTypes::KEEPER_SERVICE); |
2370 | + const auto object_path = QString::fromUtf8(DBusTypes::KEEPER_HELPER_PATH); |
2371 | + DBusInterfaceKeeperHelper helper_iface (DBusTypes::KEEPER_SERVICE, object_path, conn); |
2372 | + |
2373 | + qDebug() << "Is valid:" << helper_iface.isValid(); |
2374 | + |
2375 | + auto fd_reply = helper_iface.StartRestore(); |
2376 | + fd_reply.waitForFinished(); |
2377 | + if (fd_reply.isError()) |
2378 | + { |
2379 | + qFatal("Call to '%s.StartRestore() at '%s' call failed: %s", |
2380 | + DBusTypes::KEEPER_SERVICE, |
2381 | + qPrintable(object_path), |
2382 | + qPrintable(fd_reply.error().message()) |
2383 | + ); |
2384 | + } |
2385 | + const auto ufd = fd_reply.value(); |
2386 | + |
2387 | + // write the blob |
2388 | + const auto fd = ufd.fileDescriptor(); |
2389 | + qDebug() << "The file descriptor obtained is: " << fd; |
2390 | + RestoreReader reader(fd, TEST_RESTORE_FILE_PATH); |
2391 | + return app.exec(); |
2392 | +} |
2393 | |
2394 | === added file 'tests/fakes/fake-restore-helper.h' |
2395 | --- tests/fakes/fake-restore-helper.h 1970-01-01 00:00:00 +0000 |
2396 | +++ tests/fakes/fake-restore-helper.h 2016-11-17 00:23:33 +0000 |
2397 | @@ -0,0 +1,26 @@ |
2398 | +/* |
2399 | + * Copyright (C) 2016 Canonical, Ltd. |
2400 | + * |
2401 | + * This program is free software: you can redistribute it and/or modify it |
2402 | + * under the terms of the GNU General Public License version 3, as published |
2403 | + * by the Free Software Foundation. |
2404 | + * |
2405 | + * This program is distributed in the hope that it will be useful, but |
2406 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2407 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2408 | + * PURPOSE. See the GNU General Public License for more details. |
2409 | + * |
2410 | + * You should have received a copy of the GNU General Public License along |
2411 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2412 | + * |
2413 | + * Authors: |
2414 | + * Charles Kerr <charles.kerr@canonical.com> |
2415 | + */ |
2416 | + |
2417 | +#pragma once |
2418 | + |
2419 | +namespace |
2420 | +{ |
2421 | +static char const TEST_RESTORE_FILE_PATH[] = "/tmp/test-restore-helper"; |
2422 | + |
2423 | +} |
2424 | |
2425 | === added file 'tests/fakes/restore-reader.cpp' |
2426 | --- tests/fakes/restore-reader.cpp 1970-01-01 00:00:00 +0000 |
2427 | +++ tests/fakes/restore-reader.cpp 2016-11-17 00:23:33 +0000 |
2428 | @@ -0,0 +1,81 @@ |
2429 | +/* |
2430 | + * Copyright (C) 2016 Canonical, Ltd. |
2431 | + * |
2432 | + * This program is free software: you can redistribute it and/or modify it |
2433 | + * under the terms of the GNU General Public License version 3, as published |
2434 | + * by the Free Software Foundation. |
2435 | + * |
2436 | + * This program is distributed in the hope that it will be useful, but |
2437 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2438 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2439 | + * PURPOSE. See the GNU General Public License for more details. |
2440 | + * |
2441 | + * You should have received a copy of the GNU General Public License along |
2442 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2443 | + * |
2444 | + * Authors: |
2445 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
2446 | + */ |
2447 | + |
2448 | +#include "restore-reader.h" |
2449 | + |
2450 | +#include <QCoreApplication> |
2451 | +#include <QCryptographicHash> |
2452 | + |
2453 | +#include <unistd.h> |
2454 | + |
2455 | +//static constexpr int UPLOAD_BUFFER_MAX_ {1024*16}; |
2456 | +constexpr int UPLOAD_BUFFER_MAX_ = 16 * 1024; |
2457 | + |
2458 | +RestoreReader::RestoreReader(qint64 fd, QString const & file_path, QObject * parent) |
2459 | + : QObject(parent) |
2460 | + , file_(file_path) |
2461 | +{ |
2462 | + socket_.setSocketDescriptor(fd); |
2463 | + connect(&socket_, &QLocalSocket::readyRead, this, &RestoreReader::read_all); |
2464 | + connect(&socket_, &QLocalSocket::disconnected, this, &RestoreReader::finish); |
2465 | + if (!file_.open(QIODevice::WriteOnly | QIODevice::Truncate)) |
2466 | + { |
2467 | + qFatal("Error opening file"); |
2468 | + } |
2469 | + |
2470 | + read_all(); |
2471 | +} |
2472 | + |
2473 | +void RestoreReader::read_all() |
2474 | +{ |
2475 | + qDebug() << Q_FUNC_INFO; |
2476 | + |
2477 | + for (;;) |
2478 | + { |
2479 | + auto const chunk = socket_.readAll(); |
2480 | + if (chunk.isEmpty()) |
2481 | + { |
2482 | + qDebug() << "Failed to read from server" << socket_.errorString(); |
2483 | + break; |
2484 | + } |
2485 | + |
2486 | + n_bytes_read_ += chunk.size(); |
2487 | + qDebug() << Q_FUNC_INFO << "n_bytes_read is now" << n_bytes_read_ << "after reading" << chunk.size(); |
2488 | + if (file_.write(chunk) == -1) |
2489 | + qDebug() << Q_FUNC_INFO << "file write failed" << file_.errorString(); |
2490 | + |
2491 | + // THIS IS JUST FOR EXTRA DEBUG INFORMATION |
2492 | + QCryptographicHash hash(QCryptographicHash::Sha1); |
2493 | + hash.addData(chunk.data(), 100); |
2494 | + qInfo() << "Hash: bytes total: " << n_bytes_read_ << " " << hash.result().toHex(); |
2495 | + // THIS IS JUST FOR EXTRA DEBUG INFORMATION |
2496 | + } |
2497 | +} |
2498 | + |
2499 | +void RestoreReader::finish() |
2500 | +{ |
2501 | + qDebug() << "Finishing"; |
2502 | + read_all(); |
2503 | + |
2504 | + file_.flush(); |
2505 | + fsync(file_.handle()); |
2506 | + file_.close(); |
2507 | + |
2508 | + QCoreApplication::exit(); |
2509 | +} |
2510 | |
2511 | === added file 'tests/fakes/restore-reader.h' |
2512 | --- tests/fakes/restore-reader.h 1970-01-01 00:00:00 +0000 |
2513 | +++ tests/fakes/restore-reader.h 2016-11-17 00:23:33 +0000 |
2514 | @@ -0,0 +1,43 @@ |
2515 | +/* |
2516 | + * Copyright (C) 2016 Canonical, Ltd. |
2517 | + * |
2518 | + * This program is free software: you can redistribute it and/or modify it |
2519 | + * under the terms of the GNU General Public License version 3, as published |
2520 | + * by the Free Software Foundation. |
2521 | + * |
2522 | + * This program is distributed in the hope that it will be useful, but |
2523 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
2524 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2525 | + * PURPOSE. See the GNU General Public License for more details. |
2526 | + * |
2527 | + * You should have received a copy of the GNU General Public License along |
2528 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
2529 | + * |
2530 | + * Authors: |
2531 | + * Xavi Garcia <xavi.garcia.mena@canonical.com> |
2532 | + */ |
2533 | + |
2534 | +#pragma once |
2535 | + |
2536 | +#include <QObject> |
2537 | +#include <QFile> |
2538 | +#include <QLocalSocket> |
2539 | + |
2540 | +class RestoreReader : public QObject |
2541 | +{ |
2542 | + Q_OBJECT |
2543 | +public: |
2544 | + RestoreReader(qint64 fd, QString const & file_path, QObject * parent = nullptr); |
2545 | + ~RestoreReader() = default; |
2546 | + |
2547 | +private Q_SLOTS: |
2548 | + void read_all(); |
2549 | + void finish(); |
2550 | + |
2551 | +private: |
2552 | + void check_for_done(); |
2553 | + |
2554 | + QLocalSocket socket_; |
2555 | + qint64 n_bytes_read_ = 0; |
2556 | + QFile file_; |
2557 | +}; |
2558 | |
2559 | === modified file 'tests/integration/helpers/CMakeLists.txt' |
2560 | --- tests/integration/helpers/CMakeLists.txt 2016-10-28 15:11:21 +0000 |
2561 | +++ tests/integration/helpers/CMakeLists.txt 2016-11-17 00:23:33 +0000 |
2562 | @@ -65,6 +65,10 @@ |
2563 | FOLDER_BACKUP_EXEC |
2564 | ${KEEPER_HELPER_TEST_LOCATION} |
2565 | ) |
2566 | +set( |
2567 | + FOLDER_RESTORE_EXEC |
2568 | + ${RESTORE_HELPER_TEST_LOCATION} |
2569 | +) |
2570 | configure_file( |
2571 | ${CMAKE_SOURCE_DIR}/data/${HELPER_REGISTRY_FILENAME}.in |
2572 | ${HELPERS_TEST}-registry.json |
2573 | |
2574 | === modified file 'tests/integration/helpers/helpers-test.cc' |
2575 | --- tests/integration/helpers/helpers-test.cc 2016-11-02 14:01:23 +0000 |
2576 | +++ tests/integration/helpers/helpers-test.cc 2016-11-17 00:23:33 +0000 |
2577 | @@ -20,6 +20,7 @@ |
2578 | */ |
2579 | |
2580 | #include "test-helpers-base.h" |
2581 | +#include "tests/fakes/fake-restore-helper.h" |
2582 | |
2583 | class TestHelpers: public TestHelpersBase |
2584 | { |
2585 | @@ -32,30 +33,31 @@ |
2586 | } |
2587 | }; |
2588 | |
2589 | -TEST_F(TestHelpers, StartHelper) |
2590 | -{ |
2591 | - // starts the services, including keeper-service |
2592 | - start_tasks(); |
2593 | - |
2594 | - BackupHelper helper("com.test.multiple_first_1.2.3"); |
2595 | - |
2596 | - QSignalSpy spy(&helper, &BackupHelper::state_changed); |
2597 | - |
2598 | - helper.start({"/bin/ls","/tmp"}); |
2599 | - |
2600 | - // wait for 2 signals. |
2601 | - // One for started, another one when the helper stops |
2602 | - WAIT_FOR_SIGNALS(spy, 2, 15000); |
2603 | - |
2604 | - ASSERT_EQ(spy.count(), 2); |
2605 | - QList<QVariant> arguments = spy.takeFirst(); |
2606 | - EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::STARTED); |
2607 | - arguments = spy.takeFirst(); |
2608 | - EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::COMPLETE); |
2609 | -} |
2610 | +//TEST_F(TestHelpers, StartHelper) |
2611 | +//{ |
2612 | +// // starts the services, including keeper-service |
2613 | +// start_tasks(); |
2614 | +// |
2615 | +// BackupHelper helper("com.test.multiple_first_1.2.3"); |
2616 | +// |
2617 | +// QSignalSpy spy(&helper, &BackupHelper::state_changed); |
2618 | +// |
2619 | +// helper.start({"/bin/ls","/tmp"}); |
2620 | +// |
2621 | +// // wait for 2 signals. |
2622 | +// // One for started, another one when the helper stops |
2623 | +// WAIT_FOR_SIGNALS(spy, 2, 15000); |
2624 | +// |
2625 | +// ASSERT_EQ(spy.count(), 2); |
2626 | +// QList<QVariant> arguments = spy.takeFirst(); |
2627 | +// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::STARTED); |
2628 | +// arguments = spy.takeFirst(); |
2629 | +// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::COMPLETE); |
2630 | +//} |
2631 | |
2632 | TEST_F(TestHelpers, StartFullTest) |
2633 | { |
2634 | + system("rm -f /tmp/restore-helper-output"); |
2635 | XdgUserDirsSandbox tmp_dir; |
2636 | |
2637 | // starts the services, including keeper-service |
2638 | @@ -82,7 +84,7 @@ |
2639 | qDebug() << "USER DIR:" << user_dir; |
2640 | |
2641 | // fill something in the music dir |
2642 | - FileUtils::fillTemporaryDirectory(user_dir, qrand() % 100); |
2643 | + FileUtils::fillTemporaryDirectory(user_dir, qrand() % 10); |
2644 | |
2645 | // search for the user folder uuid |
2646 | auto user_folder_uuid = get_uuid_for_xdg_folder_path(user_dir, choices.value()); |
2647 | @@ -101,7 +103,7 @@ |
2648 | qDebug() << "USER DIR 2:" << user_dir_2; |
2649 | |
2650 | // fill something in the music dir |
2651 | - FileUtils::fillTemporaryDirectory(user_dir_2, qrand() % 100); |
2652 | + FileUtils::fillTemporaryDirectory(user_dir_2, qrand() % 10); |
2653 | |
2654 | // search for the user folder uuid |
2655 | auto user_folder_uuid_2 = get_uuid_for_xdg_folder_path(user_dir_2, choices.value()); |
2656 | @@ -140,164 +142,197 @@ |
2657 | |
2658 | // finally check that we have a valid manifest file. |
2659 | EXPECT_TRUE(check_manifest_file(backup_items)); |
2660 | -} |
2661 | - |
2662 | -TEST_F(TestHelpers, StartFullTestCancelling) |
2663 | -{ |
2664 | - XdgUserDirsSandbox tmp_dir; |
2665 | - |
2666 | - // starts the services, including keeper-service |
2667 | - start_tasks(); |
2668 | - |
2669 | - QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser( |
2670 | - DBusTypes::KEEPER_SERVICE, |
2671 | - DBusTypes::KEEPER_USER_PATH, |
2672 | - dbus_test_runner.sessionConnection() |
2673 | - ) ); |
2674 | - |
2675 | - ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
2676 | - |
2677 | - // ask for a list of backup choices |
2678 | - QDBusReply<QVariantDictMap> choices = user_iface->call("GetBackupChoices"); |
2679 | - EXPECT_TRUE(choices.isValid()) << qPrintable(choices.error().message()); |
2680 | - |
2681 | - QString user_option = QStringLiteral("XDG_MUSIC_DIR"); |
2682 | - |
2683 | - auto user_dir = qgetenv(user_option.toLatin1().data()); |
2684 | - ASSERT_FALSE(user_dir.isEmpty()); |
2685 | - qDebug() << "USER DIR:" << user_dir; |
2686 | - |
2687 | - // fill something in the music dir |
2688 | - FileUtils::fillTemporaryDirectory(user_dir, qrand() % 1000); |
2689 | - |
2690 | - // search for the user folder uuid |
2691 | - auto user_folder_uuid = get_uuid_for_xdg_folder_path(user_dir, choices.value()); |
2692 | - ASSERT_FALSE(user_folder_uuid.isEmpty()); |
2693 | - qDebug() << "User folder UUID is:" << user_folder_uuid; |
2694 | - |
2695 | - QString user_option_2 = QStringLiteral("XDG_VIDEOS_DIR"); |
2696 | - |
2697 | - auto user_dir_2 = qgetenv(user_option_2.toLatin1().data()); |
2698 | - ASSERT_FALSE(user_dir_2.isEmpty()); |
2699 | - qDebug() << "USER DIR 2:" << user_dir_2; |
2700 | - |
2701 | - // fill something in the music dir |
2702 | - FileUtils::fillTemporaryDirectory(user_dir_2, qrand() % 1000); |
2703 | - |
2704 | - // search for the user folder uuid |
2705 | - auto user_folder_uuid_2 = get_uuid_for_xdg_folder_path(user_dir_2, choices.value()); |
2706 | - ASSERT_FALSE(user_folder_uuid_2.isEmpty()); |
2707 | - qDebug() << "User folder 2 UUID is:" << user_folder_uuid_2; |
2708 | - |
2709 | - QSharedPointer<DBusPropertiesInterface> properties_interface(new DBusPropertiesInterface( |
2710 | - DBusTypes::KEEPER_SERVICE, |
2711 | - DBusTypes::KEEPER_USER_PATH, |
2712 | - dbus_test_runner.sessionConnection() |
2713 | - ) ); |
2714 | - |
2715 | - ASSERT_TRUE(properties_interface->isValid()) << qPrintable(QDBusConnection::sessionBus().lastError().message()); |
2716 | - |
2717 | - QSignalSpy spy(properties_interface.data(),&DBusPropertiesInterface::PropertiesChanged); |
2718 | - |
2719 | - // Now we know the music folder uuid, let's start the backup for it. |
2720 | - QDBusReply<void> backup_reply = user_iface->call("StartBackup", QStringList{user_folder_uuid, user_folder_uuid_2}); |
2721 | - ASSERT_TRUE(backup_reply.isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
2722 | - |
2723 | - EXPECT_TRUE(cancel_first_task_at_percentage(spy, 0.05, user_iface)); |
2724 | - |
2725 | - // wait until all the tasks have the action state "complete" |
2726 | - // this one uses pooling so it should just call Get once |
2727 | - EXPECT_TRUE(wait_for_all_tasks_have_action_state({user_folder_uuid, user_folder_uuid_2}, "cancelled", user_iface)); |
2728 | - |
2729 | - // check that we have no files in storage framework |
2730 | - EXPECT_EQ(0, StorageFrameworkLocalUtils::check_storage_framework_nb_files()); |
2731 | -} |
2732 | - |
2733 | -TEST_F(TestHelpers, CheckBadUUIDS) |
2734 | -{ |
2735 | - XdgUserDirsSandbox tmp_dir; |
2736 | - |
2737 | - // starts the services, including keeper-service |
2738 | - start_tasks(); |
2739 | - |
2740 | - QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser( |
2741 | - DBusTypes::KEEPER_SERVICE, |
2742 | - DBusTypes::KEEPER_USER_PATH, |
2743 | - dbus_test_runner.sessionConnection() |
2744 | - ) ); |
2745 | - |
2746 | - ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
2747 | - |
2748 | - // Now we know the music folder uuid, let's start the backup for it. |
2749 | - QDBusReply<void> backup_reply = user_iface->call("StartBackup", QStringList{"bad_uuid_1", "bad_uuid_2"}); |
2750 | - |
2751 | - ASSERT_FALSE(backup_reply.isValid()); |
2752 | - |
2753 | - // check the error message |
2754 | - // the uuids are not printed always in the same order |
2755 | - QString error_message = dbus_test_runner.sessionConnection().lastError().message(); |
2756 | - EXPECT_TRUE(error_message.startsWith("unhandled uuids: ")); |
2757 | - EXPECT_TRUE(error_message.contains("bad_uuid_1")); |
2758 | - EXPECT_TRUE(error_message.contains("bad_uuid_2")); |
2759 | -} |
2760 | - |
2761 | -TEST_F(TestHelpers, SimplyCheckThatTheSecondDBusInterfaceIsFine) |
2762 | -{ |
2763 | - XdgUserDirsSandbox tmp_dir; |
2764 | - |
2765 | - // starts the services, including keeper-service |
2766 | - start_tasks(); |
2767 | - |
2768 | - QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser( |
2769 | - DBusTypes::KEEPER_SERVICE, |
2770 | - DBusTypes::KEEPER_USER_PATH, |
2771 | - dbus_test_runner.sessionConnection() |
2772 | - ) ); |
2773 | - |
2774 | - ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
2775 | - |
2776 | -} |
2777 | - |
2778 | -TEST_F(TestHelpers, BadHelperPath) |
2779 | -{ |
2780 | - // starts the services, including keeper-service |
2781 | - start_tasks(); |
2782 | - |
2783 | - BackupHelper helper("com.bar_foo_8432.13.1"); |
2784 | - |
2785 | - QSignalSpy spy(&helper, &BackupHelper::state_changed); |
2786 | - QStringList urls; |
2787 | - urls << "blah" << "/tmp"; |
2788 | - helper.start(urls); |
2789 | - |
2790 | - WAIT_FOR_SIGNALS(spy, 1, Helper::MAX_UAL_WAIT_TIME + 1000); |
2791 | - |
2792 | - ASSERT_EQ(spy.count(), 1); |
2793 | - QList<QVariant> arguments = spy.takeFirst(); |
2794 | - EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::FAILED); |
2795 | -} |
2796 | - |
2797 | -TEST_F(TestHelpers, Inactivity) |
2798 | -{ |
2799 | - // starts the services, including keeper-service |
2800 | - start_tasks(); |
2801 | - |
2802 | - BackupHelper helper("com.bar_foo_8432.13.1"); |
2803 | - |
2804 | - QSignalSpy spy(&helper, &BackupHelper::state_changed); |
2805 | - QStringList urls; |
2806 | - urls << TEST_INACTIVE_HELPER << "/tmp"; |
2807 | - helper.start(urls); |
2808 | - |
2809 | - // wait 15 seconds at most. |
2810 | - // the inactive helper sleeps for 100 seconds so |
2811 | - // if we get the 2 signals it means it was stopped due to inactivity |
2812 | - // We can also check at the end for the state, which should be CANCELLED |
2813 | - WAIT_FOR_SIGNALS(spy, 2, BackupHelper::MAX_INACTIVITY_TIME + 2000); |
2814 | - |
2815 | - ASSERT_EQ(spy.count(), 2); |
2816 | - QList<QVariant> arguments = spy.takeFirst(); |
2817 | - EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::STARTED); |
2818 | - arguments = spy.takeFirst(); |
2819 | - EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::CANCELLED); |
2820 | -} |
2821 | + |
2822 | + QDBusPendingReply<QVariantDictMap> restore_choices_reply = user_iface->call("GetRestoreChoices"); |
2823 | + restore_choices_reply.waitForFinished(); |
2824 | + EXPECT_TRUE(restore_choices_reply.isValid()) << qPrintable(choices.error().message()); |
2825 | + |
2826 | + const auto restore_choices = restore_choices_reply.value(); |
2827 | + EXPECT_EQ(2, restore_choices.size()); |
2828 | + |
2829 | + // check that we have the first uuid that we did the backup |
2830 | + const auto iter_restore = restore_choices.find(user_folder_uuid); |
2831 | + EXPECT_NE(iter_restore, restore_choices.end()); |
2832 | + EXPECT_EQ(user_folder_uuid, iter_restore.key()); |
2833 | + |
2834 | + // ask to restore that uuid |
2835 | + QDBusPendingReply<void> restore_reply = user_iface->call("StartRestore", QStringList{iter_restore.key()}); |
2836 | + restore_reply.waitForFinished(); |
2837 | + ASSERT_TRUE(restore_reply.isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
2838 | + |
2839 | + // waits until all tasks are complete, recording PropertiesChanged signals |
2840 | + // and checks all the recorded values |
2841 | + EXPECT_TRUE(capture_and_check_state_until_all_tasks_complete(spy, {iter_restore.key()}, "complete")); |
2842 | + |
2843 | + // verify that the file that the fake restore helper creates is one of the ones in storage framework |
2844 | + QString storage_framework_file_path; |
2845 | + EXPECT_TRUE(StorageFrameworkLocalUtils::get_storage_frameowork_file_equal_to(TEST_RESTORE_FILE_PATH, storage_framework_file_path)); |
2846 | + |
2847 | + // Finally check that the storage framework file that matched is the right one |
2848 | + // Keeper uses the display name plus .keeper extension for the files it creates |
2849 | + QFileInfo sf_file_info(storage_framework_file_path); |
2850 | + EXPECT_EQ(sf_file_info.fileName(), QStringLiteral("%1.keeper").arg(get_display_name_for_xdg_folder_path(user_dir, choices.value()))); |
2851 | + |
2852 | + qDebug() << "-----------------------------------------------------"; |
2853 | + system("cat /tmp/restore-helper-output"); |
2854 | +} |
2855 | + |
2856 | +//TEST_F(TestHelpers, StartFullTestCancelling) |
2857 | +//{ |
2858 | +// XdgUserDirsSandbox tmp_dir; |
2859 | +// |
2860 | +// // starts the services, including keeper-service |
2861 | +// start_tasks(); |
2862 | +// |
2863 | +// QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser( |
2864 | +// DBusTypes::KEEPER_SERVICE, |
2865 | +// DBusTypes::KEEPER_USER_PATH, |
2866 | +// dbus_test_runner.sessionConnection() |
2867 | +// ) ); |
2868 | +// |
2869 | +// ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
2870 | +// |
2871 | +// // ask for a list of backup choices |
2872 | +// QDBusReply<QVariantDictMap> choices = user_iface->call("GetBackupChoices"); |
2873 | +// EXPECT_TRUE(choices.isValid()) << qPrintable(choices.error().message()); |
2874 | +// |
2875 | +// QString user_option = QStringLiteral("XDG_MUSIC_DIR"); |
2876 | +// |
2877 | +// auto user_dir = qgetenv(user_option.toLatin1().data()); |
2878 | +// ASSERT_FALSE(user_dir.isEmpty()); |
2879 | +// qDebug() << "USER DIR:" << user_dir; |
2880 | +// |
2881 | +// // fill something in the music dir |
2882 | +// FileUtils::fillTemporaryDirectory(user_dir, qrand() % 1000); |
2883 | +// |
2884 | +// // search for the user folder uuid |
2885 | +// auto user_folder_uuid = get_uuid_for_xdg_folder_path(user_dir, choices.value()); |
2886 | +// ASSERT_FALSE(user_folder_uuid.isEmpty()); |
2887 | +// qDebug() << "User folder UUID is:" << user_folder_uuid; |
2888 | +// |
2889 | +// QString user_option_2 = QStringLiteral("XDG_VIDEOS_DIR"); |
2890 | +// |
2891 | +// auto user_dir_2 = qgetenv(user_option_2.toLatin1().data()); |
2892 | +// ASSERT_FALSE(user_dir_2.isEmpty()); |
2893 | +// qDebug() << "USER DIR 2:" << user_dir_2; |
2894 | +// |
2895 | +// // fill something in the music dir |
2896 | +// FileUtils::fillTemporaryDirectory(user_dir_2, qrand() % 1000); |
2897 | +// |
2898 | +// // search for the user folder uuid |
2899 | +// auto user_folder_uuid_2 = get_uuid_for_xdg_folder_path(user_dir_2, choices.value()); |
2900 | +// ASSERT_FALSE(user_folder_uuid_2.isEmpty()); |
2901 | +// qDebug() << "User folder 2 UUID is:" << user_folder_uuid_2; |
2902 | +// |
2903 | +// QSharedPointer<DBusPropertiesInterface> properties_interface(new DBusPropertiesInterface( |
2904 | +// DBusTypes::KEEPER_SERVICE, |
2905 | +// DBusTypes::KEEPER_USER_PATH, |
2906 | +// dbus_test_runner.sessionConnection() |
2907 | +// ) ); |
2908 | +// |
2909 | +// ASSERT_TRUE(properties_interface->isValid()) << qPrintable(QDBusConnection::sessionBus().lastError().message()); |
2910 | +// |
2911 | +// QSignalSpy spy(properties_interface.data(),&DBusPropertiesInterface::PropertiesChanged); |
2912 | +// |
2913 | +// // Now we know the music folder uuid, let's start the backup for it. |
2914 | +// QDBusReply<void> backup_reply = user_iface->call("StartBackup", QStringList{user_folder_uuid, user_folder_uuid_2}); |
2915 | +// ASSERT_TRUE(backup_reply.isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
2916 | +// |
2917 | +// EXPECT_TRUE(cancel_first_task_at_percentage(spy, 0.05, user_iface)); |
2918 | +// |
2919 | +// // wait until all the tasks have the action state "complete" |
2920 | +// // this one uses pooling so it should just call Get once |
2921 | +// EXPECT_TRUE(wait_for_all_tasks_have_action_state({user_folder_uuid, user_folder_uuid_2}, "cancelled", user_iface)); |
2922 | +// |
2923 | +// // check that we have no files in storage framework |
2924 | +// EXPECT_EQ(0, StorageFrameworkLocalUtils::check_storage_framework_nb_files()); |
2925 | +//} |
2926 | +// |
2927 | +//TEST_F(TestHelpers, CheckBadUUIDS) |
2928 | +//{ |
2929 | +// XdgUserDirsSandbox tmp_dir; |
2930 | +// |
2931 | +// // starts the services, including keeper-service |
2932 | +// start_tasks(); |
2933 | +// |
2934 | +// QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser( |
2935 | +// DBusTypes::KEEPER_SERVICE, |
2936 | +// DBusTypes::KEEPER_USER_PATH, |
2937 | +// dbus_test_runner.sessionConnection() |
2938 | +// ) ); |
2939 | +// |
2940 | +// ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
2941 | +// |
2942 | +// // Now we know the music folder uuid, let's start the backup for it. |
2943 | +// QDBusReply<void> backup_reply = user_iface->call("StartBackup", QStringList{"bad_uuid_1", "bad_uuid_2"}); |
2944 | +// |
2945 | +// ASSERT_FALSE(backup_reply.isValid()); |
2946 | +// |
2947 | +// // check the error message |
2948 | +// // the uuids are not printed always in the same order |
2949 | +// QString error_message = dbus_test_runner.sessionConnection().lastError().message(); |
2950 | +// EXPECT_TRUE(error_message.startsWith("unhandled uuids: ")); |
2951 | +// EXPECT_TRUE(error_message.contains("bad_uuid_1")); |
2952 | +// EXPECT_TRUE(error_message.contains("bad_uuid_2")); |
2953 | +//} |
2954 | +// |
2955 | +//TEST_F(TestHelpers, SimplyCheckThatTheSecondDBusInterfaceIsFine) |
2956 | +//{ |
2957 | +// XdgUserDirsSandbox tmp_dir; |
2958 | +// |
2959 | +// // starts the services, including keeper-service |
2960 | +// start_tasks(); |
2961 | +// |
2962 | +// QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser( |
2963 | +// DBusTypes::KEEPER_SERVICE, |
2964 | +// DBusTypes::KEEPER_USER_PATH, |
2965 | +// dbus_test_runner.sessionConnection() |
2966 | +// ) ); |
2967 | +// |
2968 | +// ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message()); |
2969 | +// |
2970 | +//} |
2971 | +// |
2972 | +//TEST_F(TestHelpers, BadHelperPath) |
2973 | +//{ |
2974 | +// // starts the services, including keeper-service |
2975 | +// start_tasks(); |
2976 | +// |
2977 | +// BackupHelper helper("com.bar_foo_8432.13.1"); |
2978 | +// |
2979 | +// QSignalSpy spy(&helper, &BackupHelper::state_changed); |
2980 | +// QStringList urls; |
2981 | +// urls << "blah" << "/tmp"; |
2982 | +// helper.start(urls); |
2983 | +// |
2984 | +// WAIT_FOR_SIGNALS(spy, 1, Helper::MAX_UAL_WAIT_TIME + 1000); |
2985 | +// |
2986 | +// ASSERT_EQ(spy.count(), 1); |
2987 | +// QList<QVariant> arguments = spy.takeFirst(); |
2988 | +// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::FAILED); |
2989 | +//} |
2990 | +// |
2991 | +//TEST_F(TestHelpers, Inactivity) |
2992 | +//{ |
2993 | +// // starts the services, including keeper-service |
2994 | +// start_tasks(); |
2995 | +// |
2996 | +// BackupHelper helper("com.bar_foo_8432.13.1"); |
2997 | +// |
2998 | +// QSignalSpy spy(&helper, &BackupHelper::state_changed); |
2999 | +// QStringList urls; |
3000 | +// urls << TEST_INACTIVE_HELPER << "/tmp"; |
3001 | +// helper.start(urls); |
3002 | +// |
3003 | +// // wait 15 seconds at most. |
3004 | +// // the inactive helper sleeps for 100 seconds so |
3005 | +// // if we get the 2 signals it means it was stopped due to inactivity |
3006 | +// // We can also check at the end for the state, which should be CANCELLED |
3007 | +// WAIT_FOR_SIGNALS(spy, 2, BackupHelper::MAX_INACTIVITY_TIME + 2000); |
3008 | +// |
3009 | +// ASSERT_EQ(spy.count(), 2); |
3010 | +// QList<QVariant> arguments = spy.takeFirst(); |
3011 | +// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::STARTED); |
3012 | +// arguments = spy.takeFirst(); |
3013 | +// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::CANCELLED); |
3014 | +//} |
3015 | |
3016 | === modified file 'tests/integration/helpers/test-helpers-base.cpp' |
3017 | --- tests/integration/helpers/test-helpers-base.cpp 2016-11-03 08:58:51 +0000 |
3018 | +++ tests/integration/helpers/test-helpers-base.cpp 2016-11-17 00:23:33 +0000 |
3019 | @@ -179,15 +179,19 @@ |
3020 | { |
3021 | return previous == "saving" || previous == "queued"; |
3022 | } |
3023 | + else if (current == "restoring") |
3024 | + { |
3025 | + return previous == "restoring" || previous == "queued"; |
3026 | + } |
3027 | else if (current == "finishing") |
3028 | { |
3029 | - return previous == "finishing" || previous == "saving"; |
3030 | + return previous == "finishing" || previous == "saving" || previous == "restoring"; |
3031 | } |
3032 | else if (current == "complete") |
3033 | { |
3034 | // we may pass from "saving" to "complete" if we don't have enough time |
3035 | // to emit the "finishing" state change |
3036 | - return previous == "complete" || previous == "finishing" || previous == "saving"; |
3037 | + return previous == "complete" || previous == "finishing" || previous == "saving" || previous == "restoring"; |
3038 | } |
3039 | else if (current == "failed") |
3040 | { |
3041 | @@ -704,7 +708,7 @@ |
3042 | return false; |
3043 | } |
3044 | |
3045 | - QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient); |
3046 | + QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient, [](StorageFrameworkClient* sf){sf->deleteLater();}); |
3047 | Manifest manifest_read(sf_client, dir_name); |
3048 | QSignalSpy spy_read(&manifest_read, &Manifest::finished); |
3049 | |
3050 | @@ -716,6 +720,7 @@ |
3051 | if (!spy_read.count()) |
3052 | { |
3053 | qWarning() << "Failed reading manifest file"; |
3054 | + sf_client.reset(); |
3055 | return false; |
3056 | } |
3057 | |
3058 | |
3059 | === modified file 'tests/unit/manifest/manifest-test.cpp' |
3060 | --- tests/unit/manifest/manifest-test.cpp 2016-10-06 14:53:44 +0000 |
3061 | +++ tests/unit/manifest/manifest-test.cpp 2016-11-17 00:23:33 +0000 |
3062 | @@ -78,7 +78,7 @@ |
3063 | |
3064 | g_setenv("XDG_DATA_HOME", tmp_dir.path().toLatin1().data(), true); |
3065 | |
3066 | - QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient); |
3067 | + QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient, [](StorageFrameworkClient* sf){sf->deleteLater();}); |
3068 | Manifest manifest(sf_client, test_dir); |
3069 | |
3070 | auto objects_to_test = 10; |
3071 | |
3072 | === modified file 'tests/unit/storage-framework/create-uploader-test.cpp' |
3073 | --- tests/unit/storage-framework/create-uploader-test.cpp 2016-11-02 11:31:09 +0000 |
3074 | +++ tests/unit/storage-framework/create-uploader-test.cpp 2016-11-17 00:23:33 +0000 |
3075 | @@ -86,7 +86,7 @@ |
3076 | // create a downloader |
3077 | auto downloader_fut = sf_client.get_new_downloader(test_dir, test_file_name); |
3078 | { |
3079 | - QFutureWatcher<sf::Downloader::SPtr> w; |
3080 | + QFutureWatcher<std::shared_ptr<Downloader>> w; |
3081 | QSignalSpy spy(&w, &decltype(w)::finished); |
3082 | w.setFuture(downloader_fut); |
3083 | assert(spy.wait()); |
3084 | @@ -107,14 +107,13 @@ |
3085 | |
3086 | EXPECT_EQ(downloader_content, test_content); |
3087 | |
3088 | - auto finish_downloader_fut = downloader->finish_download(); |
3089 | + QSignalSpy spy_downloader(downloader.get(), &Downloader::download_finished); |
3090 | + downloader->finish(); |
3091 | + if (!spy_downloader.count()) |
3092 | { |
3093 | - QFutureWatcher<void> w; |
3094 | - QSignalSpy spy(&w, &decltype(w)::finished); |
3095 | - w.setFuture(finish_downloader_fut); |
3096 | - assert(spy.wait()); |
3097 | - ASSERT_EQ(spy.count(), 1); |
3098 | + spy_downloader.wait(); |
3099 | } |
3100 | + EXPECT_EQ(1, spy_downloader.count()); |
3101 | |
3102 | // get another uploader |
3103 | QString test_file_name_2 = QStringLiteral("test_file2"); |
3104 | |
3105 | === modified file 'tests/utils/file-utils.cpp' |
3106 | --- tests/utils/file-utils.cpp 2016-11-02 10:43:30 +0000 |
3107 | +++ tests/utils/file-utils.cpp 2016-11-17 00:23:33 +0000 |
3108 | @@ -198,8 +198,10 @@ |
3109 | qWarning() << "File to compare:" << info2.absoluteFilePath() << "does not exist"; |
3110 | return false; |
3111 | } |
3112 | + qDebug() << "File 1 size: " << info1.size() << info1.absoluteFilePath(); |
3113 | + qDebug() << "File 2 size: " << info2.size() << info2.absoluteFilePath(); |
3114 | auto checksum1 = calculate_checksum(filePath1, QCryptographicHash::Md5); |
3115 | - auto checksum2 = calculate_checksum(filePath1, QCryptographicHash::Md5); |
3116 | + auto checksum2 = calculate_checksum(filePath2, QCryptographicHash::Md5); |
3117 | if (checksum1 != checksum2) |
3118 | { |
3119 | qWarning() << "Checksum for file:" << filePath1 << "differ"; |
3120 | |
3121 | === modified file 'tests/utils/storage-framework-local.cpp' |
3122 | --- tests/utils/storage-framework-local.cpp 2016-10-28 15:11:21 +0000 |
3123 | +++ tests/utils/storage-framework-local.cpp 2016-11-17 00:23:33 +0000 |
3124 | @@ -170,4 +170,38 @@ |
3125 | : ""; |
3126 | } |
3127 | |
3128 | +bool get_storage_frameowork_file_equal_to(QString const & file_path, QString & path) |
3129 | +{ |
3130 | + auto const backups = get_storage_framework_files(); |
3131 | + for (auto const& backup : backups) |
3132 | + { |
3133 | + auto const backup_filename = backup.absoluteFilePath(); |
3134 | + if (FileUtils::compareFiles(file_path, backup_filename)) |
3135 | + { |
3136 | + path = backup_filename; |
3137 | + return true; |
3138 | + } |
3139 | + } |
3140 | + return false; |
3141 | +} |
3142 | + |
3143 | +bool get_storage_frameowork_file_equal_in_size_to(QString const & file_path, QString & path) |
3144 | +{ |
3145 | + auto const backups = get_storage_framework_files(); |
3146 | + for (auto const& backup : backups) |
3147 | + { |
3148 | + auto const backup_filename = backup.absoluteFilePath(); |
3149 | + QFileInfo info1(backup_filename); |
3150 | + QFileInfo info2(file_path); |
3151 | + qDebug() << "File 1 size = " << info1.size(); |
3152 | + qDebug() << "File 2 size = " << info2.size(); |
3153 | + if (info1.size() == info2.size()) |
3154 | + { |
3155 | + path = backup_filename; |
3156 | + return true; |
3157 | + } |
3158 | + } |
3159 | + return false; |
3160 | +} |
3161 | + |
3162 | } // namespace StorageFrameworkLocalUtils |
3163 | |
3164 | === modified file 'tests/utils/storage-framework-local.h' |
3165 | --- tests/utils/storage-framework-local.h 2016-10-28 15:11:21 +0000 |
3166 | +++ tests/utils/storage-framework-local.h 2016-11-17 00:23:33 +0000 |
3167 | @@ -41,4 +41,8 @@ |
3168 | QFileInfoList get_storage_framework_files(); |
3169 | |
3170 | QString get_storage_framework_dir_name(); |
3171 | + |
3172 | + bool get_storage_frameowork_file_equal_to(QString const & file_path, QString & path); |
3173 | + |
3174 | + bool get_storage_frameowork_file_equal_in_size_to(QString const & file_path, QString & path); |
3175 | } |
FAILED: Continuous integration, rev:130 /jenkins. canonical. com/unity- api-1/job/ lp-keeper- ci/124/ /jenkins. canonical. com/unity- api-1/job/ build/1092/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/1099 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 890/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= zesty/890/ console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 890/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= zesty/890/ console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 890/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= zesty/890/ console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-keeper- ci/124/ rebuild
https:/