Merge lp:~unity-api-team/keeper/restore into lp:keeper/devel

Proposed by Charles Kerr
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
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://code.launchpad.net/~xavi-garcia-mena/keeper/restore/> and is here so that multiple devs can kick the tires as neeed

To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
lp:~unity-api-team/keeper/restore updated
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()

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'data/helper-registry.json.in'
--- data/helper-registry.json.in 2016-08-09 04:20:33 +0000
+++ data/helper-registry.json.in 2016-11-17 00:23:33 +0000
@@ -4,5 +4,10 @@
4 "@FOLDER_BACKUP_EXEC@",4 "@FOLDER_BACKUP_EXEC@",
5 "${subtype}"5 "${subtype}"
6 ]6 ]
7 }7 ,
8 "restore-urls": [
9 "@FOLDER_RESTORE_EXEC@",
10 "${subtype}"
11 ]
12 }
8}13}
914
=== modified file 'include/helper/data-dir-registry.h'
--- include/helper/data-dir-registry.h 2016-08-09 05:44:25 +0000
+++ include/helper/data-dir-registry.h 2016-11-17 00:23:33 +0000
@@ -39,6 +39,8 @@
3939
40 QStringList get_backup_helper_urls(Metadata const& metadata) override;40 QStringList get_backup_helper_urls(Metadata const& metadata) override;
4141
42 QStringList get_restore_helper_urls(Metadata const& metadata) override;
43
42private:44private:
43 class Impl;45 class Impl;
44 friend class Impl;46 friend class Impl;
4547
=== modified file 'include/helper/metadata.h'
--- include/helper/metadata.h 2016-10-14 09:23:11 +0000
+++ include/helper/metadata.h 2016-11-17 00:23:33 +0000
@@ -42,6 +42,7 @@
42 static QString const TITLE_KEY;42 static QString const TITLE_KEY;
43 static QString const VERSION_KEY;43 static QString const VERSION_KEY;
44 static QString const FILE_NAME_KEY;44 static QString const FILE_NAME_KEY;
45 static QString const DIR_NAME_KEY;
45 static QString const DISPLAY_NAME_KEY;46 static QString const DISPLAY_NAME_KEY;
4647
47 // metadata values48 // metadata values
4849
=== modified file 'include/helper/registry.h'
--- include/helper/registry.h 2016-08-08 04:56:35 +0000
+++ include/helper/registry.h 2016-11-17 00:23:33 +0000
@@ -30,6 +30,7 @@
30 Q_DISABLE_COPY(HelperRegistry)30 Q_DISABLE_COPY(HelperRegistry)
3131
32 virtual QStringList get_backup_helper_urls(Metadata const& task) =0;32 virtual QStringList get_backup_helper_urls(Metadata const& task) =0;
33 virtual QStringList get_restore_helper_urls(Metadata const& task) =0;
3334
34protected:35protected:
35 HelperRegistry() =default;36 HelperRegistry() =default;
3637
=== added file 'include/helper/restore-helper.h'
--- include/helper/restore-helper.h 1970-01-01 00:00:00 +0000
+++ include/helper/restore-helper.h 2016-11-17 00:23:33 +0000
@@ -0,0 +1,61 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Xavi Garcia <xavi.garcia.mena@canonical.com>
18 * Charles Kerr <charles.kerr@canonical.com>
19 */
20
21#pragma once
22
23#include "storage-framework/downloader.h"
24#include "helper/helper.h" // parent class
25#include "helper/registry.h"
26
27#include <QObject>
28#include <QScopedPointer>
29#include <QString>
30
31#include <memory>
32
33class RestoreHelperPrivate;
34class RestoreHelper final: public Helper
35{
36 Q_OBJECT
37 Q_DECLARE_PRIVATE(RestoreHelper)
38
39public:
40 RestoreHelper(
41 QString const & appid,
42 clock_func const & clock=Helper::default_clock,
43 QObject * parent=nullptr
44 );
45 virtual ~RestoreHelper();
46 Q_DISABLE_COPY(RestoreHelper)
47
48 static constexpr int MAX_INACTIVITY_TIME = 15000;
49
50 void set_downloader(std::shared_ptr<Downloader> const& downloader);
51 void start(QStringList const& urls) override;
52 void stop() override;
53 int get_helper_socket() const;
54 QString to_string(Helper::State state) const override;
55 void set_state(State) override;
56protected:
57 void on_helper_finished() override;
58
59private:
60 QScopedPointer<RestoreHelperPrivate> const d_ptr;
61};
062
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2016-08-09 10:13:48 +0000
+++ src/CMakeLists.txt 2016-11-17 00:23:33 +0000
@@ -11,6 +11,7 @@
11add_subdirectory(storage-framework)11add_subdirectory(storage-framework)
12add_subdirectory(tar)12add_subdirectory(tar)
13add_subdirectory(util)13add_subdirectory(util)
14add_subdirectory(test-restore)
1415
15set(16set(
16 COVERAGE_REPORT_TARGETS17 COVERAGE_REPORT_TARGETS
1718
=== modified file 'src/cli/main.cpp'
--- src/cli/main.cpp 2016-08-30 14:16:19 +0000
+++ src/cli/main.cpp 2016-11-17 00:23:33 +0000
@@ -88,6 +88,48 @@
88 qWarning() << "Error starting backup:" << backup_reply.error().message();88 qWarning() << "Error starting backup:" << backup_reply.error().message();
89 }89 }
90 }90 }
91 else if(argc == 2 && QStringLiteral("--restore") == argv[1])
92 {
93 QScopedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser(
94 DBusTypes::KEEPER_SERVICE,
95 DBusTypes::KEEPER_USER_PATH,
96 QDBusConnection::sessionBus()
97 ) );
98 QDBusPendingReply<QVariantDictMap> choices = user_iface->call("GetRestoreChoices");
99 choices.waitForFinished();
100 if (choices.isError())
101 {
102 qFatal("Call to '%s.GetRestoreChoices() at '%s' call failed: %s",
103 DBusTypes::KEEPER_SERVICE,
104 qPrintable(DBusTypes::KEEPER_USER_PATH),
105 qPrintable(choices.error().message())
106 );
107 }
108
109 QStringList uuids;
110 auto choices_values = choices.value();
111 for(auto iter = choices_values.begin(); iter != choices_values.end(); ++iter)
112 {
113 const auto& values = iter.value();
114 auto iter_values = values.find("type");
115 if (iter_values != values.end())
116 {
117 if (iter_values.value().toString() == "folder")
118 {
119 qDebug() << "Adding uuid" << iter.key() << "with type:" << "folder";
120 uuids << iter.key();
121 }
122 }
123 }
124
125 QStringList restoreUUids{uuids.at(0)};
126 QDBusPendingReply<void> backup_reply = user_iface->call("StartRestore", restoreUUids);
127
128 if (!backup_reply.isValid())
129 {
130 qWarning() << "Error starting restore:" << backup_reply.error().message();
131 }
132 }
91 else133 else
92 {134 {
93 qWarning() << "FIXME";135 qWarning() << "FIXME";
94136
=== modified file 'src/helper/CMakeLists.txt'
--- src/helper/CMakeLists.txt 2016-09-06 01:31:59 +0000
+++ src/helper/CMakeLists.txt 2016-11-17 00:23:33 +0000
@@ -48,10 +48,12 @@
48 ${HELPER_LIB}48 ${HELPER_LIB}
49 STATIC49 STATIC
50 backup-helper.cpp50 backup-helper.cpp
51 restore-helper.cpp
51 data-dir-registry.cpp52 data-dir-registry.cpp
52 helper.cpp53 helper.cpp
53 metadata.cpp54 metadata.cpp
54 ${CMAKE_SOURCE_DIR}/include/helper/backup-helper.h55 ${CMAKE_SOURCE_DIR}/include/helper/backup-helper.h
56 ${CMAKE_SOURCE_DIR}/include/helper/restore-helper.h
55 ${CMAKE_SOURCE_DIR}/include/helper/data-dir-registry.h57 ${CMAKE_SOURCE_DIR}/include/helper/data-dir-registry.h
56 ${CMAKE_SOURCE_DIR}/include/helper/helper.h58 ${CMAKE_SOURCE_DIR}/include/helper/helper.h
57 ${CMAKE_SOURCE_DIR}/include/helper/registry.h59 ${CMAKE_SOURCE_DIR}/include/helper/registry.h
5860
=== modified file 'src/helper/data-dir-registry.cpp'
--- src/helper/data-dir-registry.cpp 2016-08-10 02:29:17 +0000
+++ src/helper/data-dir-registry.cpp 2016-11-17 00:23:33 +0000
@@ -49,15 +49,29 @@
4949
50 QStringList get_backup_helper_urls(Metadata const& task)50 QStringList get_backup_helper_urls(Metadata const& task)
51 {51 {
52 return get_helper_urls(task, "backup");
53 }
54
55 QStringList get_restore_helper_urls(Metadata const& task)
56 {
57 return get_helper_urls(task, "restore");
58 }
59
60
61
62private:
63
64 QStringList get_helper_urls(Metadata const& task, QString const & prop)
65 {
52 QStringList ret;66 QStringList ret;
5367
54 QString type;68 QString type;
55 if (task.get_property(Metadata::TYPE_KEY, type))69 if (task.get_property(Metadata::TYPE_KEY, type))
56 {70 {
57 auto it = registry_.find(std::make_pair(type,QStringLiteral("backup")));71 auto it = registry_.find(std::make_pair(type,prop));
58 if (it == registry_.end())72 if (it == registry_.end())
59 {73 {
60 qCritical() << "can't get backup helper urls for unhandled type" << type;74 qCritical() << "can't get " << prop << " helper urls for unhandled type" << type;
61 }75 }
62 else76 else
63 {77 {
@@ -73,8 +87,6 @@
73 return ret;87 return ret;
74 }88 }
7589
76private:
77
78 // replace "${key}" with task.get_property("key")90 // replace "${key}" with task.get_property("key")
79 QStringList perform_url_substitution(Metadata const& task, QStringList const& urls_in)91 QStringList perform_url_substitution(Metadata const& task, QStringList const& urls_in)
80 {92 {
@@ -139,6 +151,10 @@
139 * "backup-urls": [151 * "backup-urls": [
140 * "/path/to/helper.sh",152 * "/path/to/helper.sh",
141 * "${subtype}"153 * "${subtype}"
154 * ],
155 * "restore-urls": [
156 * "/path/to/helper.sh",
157 * "${subtype}"
142 * ]158 * ]
143 * }159 * }
144 * }160 * }
@@ -160,21 +176,33 @@
160 for (auto tit=obj.begin(), tend=obj.end(); tit!=tend; ++tit)176 for (auto tit=obj.begin(), tend=obj.end(); tit!=tend; ++tit)
161 {177 {
162 auto const type = tit.key();178 auto const type = tit.key();
163 auto& info = registry_[std::make_pair(type,QStringLiteral("backup"))];
164
165 auto const props = tit.value().toObject();179 auto const props = tit.value().toObject();
180
166 auto const urls_jsonval = props["backup-urls"];181 auto const urls_jsonval = props["backup-urls"];
167 if (urls_jsonval.isArray())182 if (urls_jsonval.isArray())
168 {183 {
184 auto& info = registry_[std::make_pair(type,QStringLiteral("backup"))];
169 for (auto url_jsonval : urls_jsonval.toArray())185 for (auto url_jsonval : urls_jsonval.toArray())
170 {186 {
171 info.urls.push_back(url_jsonval.toString());187 info.urls.push_back(url_jsonval.toString());
172 }188 }
189 qDebug() << "loaded" << type << "backup urls from" << path;
190 for(auto const& url : info.urls)
191 qDebug() << "\turl:" << url;
173 }192 }
174193
175 qDebug() << "loaded" << type << "backup urls from" << path;194 auto const urls_jsonval_restore = props["restore-urls"];
176 for(auto const& url : info.urls)195 if (urls_jsonval_restore.isArray())
177 qDebug() << "\turl:" << url;196 {
197 auto& info = registry_[std::make_pair(type,QStringLiteral("restore"))];
198 for (auto url_jsonval : urls_jsonval_restore.toArray())
199 {
200 info.urls.push_back(url_jsonval.toString());
201 }
202 qDebug() << "loaded" << type << "restore urls from" << path;
203 for(auto const& url : info.urls)
204 qDebug() << "\turl:" << url;
205 }
178 }206 }
179 }207 }
180 }208 }
@@ -198,3 +226,9 @@
198{226{
199 return impl_->get_backup_helper_urls(task);227 return impl_->get_backup_helper_urls(task);
200}228}
229
230QStringList
231DataDirRegistry::get_restore_helper_urls(Metadata const& task)
232{
233 return impl_->get_restore_helper_urls(task);
234}
201235
=== modified file 'src/helper/helper.cpp'
--- src/helper/helper.cpp 2016-09-15 14:05:17 +0000
+++ src/helper/helper.cpp 2016-11-17 00:23:33 +0000
@@ -301,7 +301,7 @@
301301
302 void ual_stop()302 void ual_stop()
303 {303 {
304 qDebug() << "Stopping helper for app:" << appid_;304 qDebug() << "------------------------------------------------------ Stopping helper for app:" << appid_;
305 auto backupType = ubuntu::app_launch::Helper::Type::from_raw(HELPER_TYPE);305 auto backupType = ubuntu::app_launch::Helper::Type::from_raw(HELPER_TYPE);
306306
307 auto appid = ubuntu::app_launch::AppID::parse(appid_.toStdString());307 auto appid = ubuntu::app_launch::AppID::parse(appid_.toStdString());
@@ -359,7 +359,7 @@
359359
360 void on_max_time_waiting_for_ual_started()360 void on_max_time_waiting_for_ual_started()
361 {361 {
362 qDebug() << "Max time reached waiting for UAL to start";362 qDebug() << "========================================================================== Max time reached waiting for UAL to start";
363 q_ptr->set_state(Helper::State::FAILED);363 q_ptr->set_state(Helper::State::FAILED);
364 stop_wait_for_ual_timer();364 stop_wait_for_ual_timer();
365 }365 }
366366
=== modified file 'src/helper/metadata.cpp'
--- src/helper/metadata.cpp 2016-10-14 09:23:11 +0000
+++ src/helper/metadata.cpp 2016-11-17 00:23:33 +0000
@@ -42,6 +42,7 @@
42const QString Metadata::TITLE_KEY = QStringLiteral("title");42const QString Metadata::TITLE_KEY = QStringLiteral("title");
43const QString Metadata::VERSION_KEY = QStringLiteral("version");43const QString Metadata::VERSION_KEY = QStringLiteral("version");
44const QString Metadata::FILE_NAME_KEY = QStringLiteral("file-name");44const QString Metadata::FILE_NAME_KEY = QStringLiteral("file-name");
45const QString Metadata::DIR_NAME_KEY = QStringLiteral("dir-name");
45const QString Metadata::DISPLAY_NAME_KEY = QStringLiteral("display-name");46const QString Metadata::DISPLAY_NAME_KEY = QStringLiteral("display-name");
4647
47// Metadata values48// Metadata values
4849
=== added file 'src/helper/restore-helper.cpp'
--- src/helper/restore-helper.cpp 1970-01-01 00:00:00 +0000
+++ src/helper/restore-helper.cpp 2016-11-17 00:23:33 +0000
@@ -0,0 +1,378 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Xavi Garcia <xavi.garcia.mena@canonical.com>
18 * Charles Kerr <charles.kerr@canonical.com>
19 */
20
21#include "util/connection-helper.h"
22#include "helper/restore-helper.h"
23#include "service/app-const.h" // HELPER_TYPE
24
25#include <QByteArray>
26#include <QDebug>
27#include <QLocalSocket>
28#include <QMap>
29#include <QObject>
30#include <QString>
31#include <QTimer>
32#include <QVector>
33#include <QCryptographicHash>
34
35#include <fcntl.h>
36#include <sys/types.h>
37#include <sys/socket.h>
38
39#include <functional> // std::bind()
40
41
42class RestoreHelperPrivate
43{
44public:
45
46 explicit RestoreHelperPrivate(
47 RestoreHelper* backup_helper
48 )
49 : q_ptr(backup_helper)
50 {
51 // listen for inactivity from storage framework
52 QObject::connect(&timer_, &QTimer::timeout,
53 std::bind(&RestoreHelperPrivate::on_inactivity_detected, this)
54 );
55
56 // fire up the sockets
57 int fds[2];
58 int rc = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds);
59 if (rc == -1)
60 {
61 // TODO throw exception.
62 qWarning() << "RestoreHelperPrivate: error creating socket pair to communicate with helper ";
63 return;
64 }
65
66 // helper socket is for the client.
67 helper_socket_.setSocketDescriptor(fds[0], QLocalSocket::ConnectedState, QIODevice::ReadOnly);
68
69 write_socket_.setSocketDescriptor(fds[1], QLocalSocket::ConnectedState, QIODevice::WriteOnly);
70 }
71
72 ~RestoreHelperPrivate() = default;
73
74 Q_DISABLE_COPY(RestoreHelperPrivate)
75
76 void start(QStringList const& urls)
77 {
78 q_ptr->Helper::start(urls);
79 reset_inactivity_timer();
80 }
81
82 void set_downloader(std::shared_ptr<Downloader> const& downloader)
83 {
84 qDebug() << "RestoreHelper::set_downloader";
85 downloader_ = downloader;
86 n_read_ = 0;
87 n_uploaded_ = 0;
88 read_error_ = false;
89 write_error_ = false;
90 cancelled_ = false;
91
92 q_ptr->set_expected_size(downloader->file_size());
93
94 qDebug() << "Storage framework socket is: " << static_cast<void *>(downloader_->socket().get());
95
96 // listen for data ready to read
97 QObject::connect(downloader_->socket().get(), &QLocalSocket::readyRead,
98 std::bind(&RestoreHelperPrivate::on_ready_read, this)
99 );
100
101 connections_.remember(QObject::connect(
102 &write_socket_, &QLocalSocket::bytesWritten,
103 std::bind(&RestoreHelperPrivate::on_data_uploaded, this, std::placeholders::_1)
104 ));
105
106 // maybe there's already readable data
107 process_more();
108
109 reset_inactivity_timer();
110 }
111
112 void stop()
113 {
114 write_socket_.disconnectFromServer();
115 cancelled_ = true;
116 q_ptr->Helper::stop();
117 }
118
119 int get_helper_socket() const
120 {
121 return int(helper_socket_.socketDescriptor());
122 }
123
124 QString to_string(Helper::State state) const
125 {
126 return state == Helper::State::STARTED
127 ? QStringLiteral("restoring")
128 : q_ptr->Helper::to_string(state);
129 }
130
131 void on_state_changed(Helper::State state)
132 {
133 switch (state)
134 {
135 case Helper::State::CANCELLED:
136 case Helper::State::FAILED:
137 qDebug() << "cancelled/failed, calling downloader_.reset()";
138 downloader_.reset();
139 break;
140
141 case Helper::State::DATA_COMPLETE: {
142 qDebug() << "Restore helper finished, calling downloader_.finish()";
143 write_socket_.disconnectFromServer();
144 downloader_->finish();
145 downloader_.reset();
146 break;
147 }
148
149 //case Helper::State::NOT_STARTED:
150 //case Helper::State::STARTED:
151 default:
152 break;
153 }
154 }
155
156 void on_helper_finished()
157 {
158 stop_inactivity_timer();
159 check_for_done();
160 }
161
162private:
163
164 void on_inactivity_detected()
165 {
166 stop_inactivity_timer();
167 qWarning() << "Inactivity detected in the helper...stopping it";
168 stop();
169 }
170
171 void on_ready_read()
172 {
173 process_more();
174 }
175
176 void on_data_uploaded(qint64 n)
177 {
178 n_uploaded_ += n;
179 q_ptr->record_data_transferred(n);
180 qDebug("n_read %zu n_uploaded %zu (newly uploaded %zu)", size_t(n_read_), size_t(n_uploaded_), size_t(n));
181 process_more();
182 check_for_done();
183 }
184
185 void process_more()
186 {
187 qDebug() << Q_FUNC_INFO;
188
189 if (!downloader_)
190 return;
191
192 qDebug() << Q_FUNC_INFO << "2";
193
194 char readbuf[UPLOAD_BUFFER_MAX_];
195 auto socket = downloader_->socket();
196 for(;;)
197 {
198 if (!socket->bytesAvailable())
199 break;
200 // try to fill the upload buf
201 int max_bytes = (UPLOAD_BUFFER_MAX_) - upload_buffer_.size();
202 if (max_bytes > 0) {
203 const auto n = socket->read(readbuf, max_bytes);
204 if (n > 0) {
205 n_read_ += n;
206 upload_buffer_.append(readbuf, int(n));
207 qDebug("buffer_.size() is %zu after reading %zu", size_t(upload_buffer_.size()), size_t(n));
208 }
209 else if (n < 0) {
210 read_error_ = true;
211 qDebug() << "Read error in" << Q_FUNC_INFO << ":" << socket->errorString();
212 stop();
213 return;
214 }
215 }
216
217 // THIS IS JUST FOR EXTRA DEBUG INFORMATION
218 QCryptographicHash hash(QCryptographicHash::Sha1);
219 hash.addData(upload_buffer_.left(100));
220 qDebug() << "************************************************ Hash send: " << hash.result().toHex() << " Size: " << upload_buffer_.size() << " Total: " << n_read_;
221 // THIS IS JUST FOR EXTRA DEBUG INFORMATION
222
223 // try to empty the upload buf
224 const auto n = write_socket_.write(upload_buffer_);
225 if (n > 0) {
226 upload_buffer_.remove(0, int(n));
227 qDebug("buffer_.size() is %zu after writing %zu", size_t(upload_buffer_.size()), size_t(n));
228 continue;
229 }
230 else {
231 if (n < 0) {
232 write_error_ = true;
233 qWarning() << "Write error:" << write_socket_.errorString();
234 stop();
235 }
236 break;
237 }
238 }
239
240 reset_inactivity_timer();
241 }
242
243 void reset_inactivity_timer()
244 {
245 static constexpr int MAX_TIME_WAITING_FOR_DATA {RestoreHelper::MAX_INACTIVITY_TIME};
246 timer_.start(MAX_TIME_WAITING_FOR_DATA);
247 }
248
249 void stop_inactivity_timer()
250 {
251 timer_.stop();
252 }
253
254 void check_for_done()
255 {
256 qDebug() << "Checking for done.";
257 if (cancelled_)
258 {
259 q_ptr->set_state(Helper::State::CANCELLED);
260 }
261 else if (read_error_ || write_error_ || n_uploaded_ > q_ptr->expected_size())
262 {
263 if (!q_ptr->is_helper_running())
264 {
265 q_ptr->set_state(Helper::State::FAILED);
266 }
267 }
268 else if (n_uploaded_ == q_ptr->expected_size())
269 {
270 if (downloader_)
271 {
272 if (q_ptr->is_helper_running())
273 {
274 // only in the case that the helper process finished we move to the next state
275 // this is to prevent to start the next task too early
276 q_ptr->set_state(Helper::State::DATA_COMPLETE);
277 stop_inactivity_timer();
278 }
279 }
280 else
281 q_ptr->set_state(Helper::State::COMPLETE);
282 }
283 }
284
285 /***
286 ****
287 ***/
288
289 static constexpr int UPLOAD_BUFFER_MAX_ {1024*16};
290
291 RestoreHelper * const q_ptr;
292 QTimer timer_;
293 std::shared_ptr<Downloader> downloader_;
294 QLocalSocket helper_socket_;
295 QLocalSocket write_socket_;
296 QByteArray upload_buffer_;
297 qint64 n_read_ = 0;
298 qint64 n_uploaded_ = 0;
299 bool read_error_ = false;
300 bool write_error_ = false;
301 bool cancelled_ = false;
302 ConnectionHelper connections_;
303 QString uploader_committed_file_name_;
304};
305
306/***
307****
308***/
309
310RestoreHelper::RestoreHelper(
311 QString const & appid,
312 clock_func const & clock,
313 QObject * parent
314)
315 : Helper(appid, clock, parent)
316 , d_ptr(new RestoreHelperPrivate(this))
317{
318}
319
320RestoreHelper::~RestoreHelper() =default;
321
322void
323RestoreHelper::start(QStringList const& url)
324{
325 Q_D(RestoreHelper);
326
327 d->start(url);
328}
329
330void
331RestoreHelper::stop()
332{
333 Q_D(RestoreHelper);
334
335 d->stop();
336}
337
338void
339RestoreHelper::set_downloader(std::shared_ptr<Downloader> const& downloader)
340{
341 Q_D(RestoreHelper);
342
343 d->set_downloader(downloader);
344}
345
346int
347RestoreHelper::get_helper_socket() const
348{
349 Q_D(const RestoreHelper);
350
351 return d->get_helper_socket();
352}
353
354QString
355RestoreHelper::to_string(Helper::State state) const
356{
357 Q_D(const RestoreHelper);
358
359 return d->to_string(state);
360}
361
362void
363RestoreHelper::set_state(Helper::State state)
364{
365 Q_D(RestoreHelper);
366
367 qDebug() << Q_FUNC_INFO;
368 Helper::set_state(state);
369 d->on_state_changed(state);
370}
371
372void RestoreHelper::on_helper_finished()
373{
374 Q_D(RestoreHelper);
375
376 Helper::on_helper_finished();
377 d->on_helper_finished();
378}
0379
=== modified file 'src/service/CMakeLists.txt'
--- src/service/CMakeLists.txt 2016-10-28 15:11:21 +0000
+++ src/service/CMakeLists.txt 2016-11-17 00:23:33 +0000
@@ -15,6 +15,7 @@
15 task-manager.cpp15 task-manager.cpp
16 keeper-task.cpp16 keeper-task.cpp
17 keeper-task-backup.cpp17 keeper-task-backup.cpp
18 keeper-task-restore.cpp
18 manifest.cpp19 manifest.cpp
19 metadata-provider.h20 metadata-provider.h
20)21)
2122
=== modified file 'src/service/keeper-helper.cpp'
--- src/service/keeper-helper.cpp 2016-08-10 02:06:08 +0000
+++ src/service/keeper-helper.cpp 2016-11-17 00:23:33 +0000
@@ -44,8 +44,11 @@
4444
45QDBusUnixFileDescriptor KeeperHelper::StartRestore()45QDBusUnixFileDescriptor KeeperHelper::StartRestore()
46{46{
47 // TODO get the file descriptor of the item in storage framework47 // pass it back to Keeper to do the work
48 return QDBusUnixFileDescriptor();48 Q_ASSERT(calledFromDBus());
49 auto bus = connection();
50 auto& msg = message();
51 return keeper_.StartRestore(bus, msg);
49}52}
5053
51void KeeperHelper::UpdateStatus(const QString &app_id, const QString &status, double percentage)54void KeeperHelper::UpdateStatus(const QString &app_id, const QString &status, double percentage)
5255
=== modified file 'src/service/keeper-task-backup.cpp'
--- src/service/keeper-task-backup.cpp 2016-10-06 14:53:44 +0000
+++ src/service/keeper-task-backup.cpp 2016-11-17 00:23:33 +0000
@@ -31,7 +31,7 @@
31 Q_DECLARE_PUBLIC(KeeperTaskBackup)31 Q_DECLARE_PUBLIC(KeeperTaskBackup)
32public:32public:
33 KeeperTaskBackupPrivate(KeeperTask * keeper_task,33 KeeperTaskBackupPrivate(KeeperTask * keeper_task,
34 KeeperTask::TaskData const & task_data,34 KeeperTask::TaskData & task_data,
35 QSharedPointer<HelperRegistry> const & helper_registry,35 QSharedPointer<HelperRegistry> const & helper_registry,
36 QSharedPointer<StorageFrameworkClient> const & storage)36 QSharedPointer<StorageFrameworkClient> const & storage)
37 : KeeperTaskPrivate(keeper_task, task_data, helper_registry, storage)37 : KeeperTaskPrivate(keeper_task, task_data, helper_registry, storage)
@@ -90,7 +90,7 @@
90 QString file_name_;90 QString file_name_;
91};91};
9292
93KeeperTaskBackup::KeeperTaskBackup(TaskData const & task_data,93KeeperTaskBackup::KeeperTaskBackup(TaskData & task_data,
94 QSharedPointer<HelperRegistry> const & helper_registry,94 QSharedPointer<HelperRegistry> const & helper_registry,
95 QSharedPointer<StorageFrameworkClient> const & storage,95 QSharedPointer<StorageFrameworkClient> const & storage,
96 QObject *parent)96 QObject *parent)
9797
=== modified file 'src/service/keeper-task-backup.h'
--- src/service/keeper-task-backup.h 2016-10-06 14:53:44 +0000
+++ src/service/keeper-task-backup.h 2016-11-17 00:23:33 +0000
@@ -29,7 +29,7 @@
29 Q_DECLARE_PRIVATE(KeeperTaskBackup)29 Q_DECLARE_PRIVATE(KeeperTaskBackup)
30public:30public:
3131
32 KeeperTaskBackup(TaskData const & task_data,32 KeeperTaskBackup(TaskData & task_data,
33 QSharedPointer<HelperRegistry> const & helper_registry,33 QSharedPointer<HelperRegistry> const & helper_registry,
34 QSharedPointer<StorageFrameworkClient> const & storage,34 QSharedPointer<StorageFrameworkClient> const & storage,
35 QObject *parent = nullptr);35 QObject *parent = nullptr);
3636
=== added file 'src/service/keeper-task-restore.cpp'
--- src/service/keeper-task-restore.cpp 1970-01-01 00:00:00 +0000
+++ src/service/keeper-task-restore.cpp 2016-11-17 00:23:33 +0000
@@ -0,0 +1,129 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Xavi Garcia <xavi.garcia.mena@canonical.com>
18 * Charles Kerr <charles.kerr@canonical.com>
19 */
20
21#include "util/connection-helper.h"
22#include "storage-framework/storage_framework_client.h"
23#include "helper/restore-helper.h"
24#include "service/app-const.h" // DEKKO_APP_ID
25#include "service/keeper-task-restore.h"
26#include "service/keeper-task.h"
27#include "service/private/keeper-task_p.h"
28
29namespace sf = unity::storage::qt::client;
30
31class KeeperTaskRestorePrivate : public KeeperTaskPrivate
32{
33 Q_DECLARE_PUBLIC(KeeperTaskRestore)
34public:
35 KeeperTaskRestorePrivate(KeeperTask * keeper_task,
36 KeeperTask::TaskData & task_data,
37 QSharedPointer<HelperRegistry> const & helper_registry,
38 QSharedPointer<StorageFrameworkClient> const & storage)
39 : KeeperTaskPrivate(keeper_task, task_data, helper_registry, storage)
40 {
41 }
42
43 ~KeeperTaskRestorePrivate() = default;
44
45 QStringList get_helper_urls() const
46 {
47 return helper_registry_->get_restore_helper_urls(task_data_.metadata);
48 }
49
50 void init_helper()
51 {
52 qDebug() << Q_FUNC_INFO;
53 helper_.reset(new RestoreHelper(DEKKO_APP_ID), [](Helper *h){h->deleteLater();}); // TODO change this to a restore helper
54 qDebug() << "Helper " << static_cast<void*>(helper_.data()) << " was created";
55 }
56
57 void ask_for_downloader()
58 {
59 qDebug() << "asking storage framework for a socket for reading";
60
61 QString file_name;
62 task_data_.metadata.get_property(Metadata::FILE_NAME_KEY, file_name);
63 if (file_name.isEmpty())
64 {
65 qWarning() << "ERROR: the restore task does not provide a valid file name to read from.";
66 return;
67 }
68
69 QString dir_name;
70 task_data_.metadata.get_property(Metadata::DIR_NAME_KEY, dir_name);
71 if (dir_name.isEmpty())
72 {
73 qWarning() << "ERROR: the restore task does not provide a valid directory name.";
74 return;
75 }
76
77 // extract the dir_name.
78 connections_.connect_future(
79 storage_->get_new_downloader(dir_name, file_name),
80 std::function<void(std::shared_ptr<Downloader> const&)>{
81 [this](std::shared_ptr<Downloader> const& downloader){
82 qDebug() << "Downloader is" << static_cast<void*>(downloader.get());
83 int fd {-1};
84 if (downloader) {
85 qDebug() << "Helper is " << static_cast<void*>(helper_.data());
86 auto restore_helper = qSharedPointerDynamicCast<RestoreHelper>(helper_);
87 restore_helper->set_downloader(downloader);
88 fd = restore_helper->get_helper_socket();
89 }
90 qDebug("emitting task_socket_ready(socket=%d)", fd);
91 Q_EMIT(q_ptr->task_socket_ready(fd));
92 }
93 }
94 );
95 }
96private:
97 ConnectionHelper connections_;
98};
99
100KeeperTaskRestore::KeeperTaskRestore(TaskData & task_data,
101 QSharedPointer<HelperRegistry> const & helper_registry,
102 QSharedPointer<StorageFrameworkClient> const & storage,
103 QObject *parent)
104 : KeeperTask(*new KeeperTaskRestorePrivate(this, task_data, helper_registry, storage), parent)
105{
106}
107
108KeeperTaskRestore::~KeeperTaskRestore() = default;
109
110QStringList KeeperTaskRestore::get_helper_urls() const
111{
112 Q_D(const KeeperTaskRestore);
113
114 return d->get_helper_urls();
115}
116
117void KeeperTaskRestore::init_helper()
118{
119 Q_D(KeeperTaskRestore);
120
121 d->init_helper();
122}
123
124void KeeperTaskRestore::ask_for_downloader()
125{
126 Q_D(KeeperTaskRestore);
127
128 d->ask_for_downloader();
129}
0130
=== added file 'src/service/keeper-task-restore.h'
--- src/service/keeper-task-restore.h 1970-01-01 00:00:00 +0000
+++ src/service/keeper-task-restore.h 2016-11-17 00:23:33 +0000
@@ -0,0 +1,46 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Xavi Garcia <xavi.garcia.mena@canonical.com>
18 * Charles Kerr <charles.kerr@canonical.com>
19 */
20#pragma once
21
22#include "keeper-task.h"
23
24class KeeperTaskRestorePrivate;
25
26class KeeperTaskRestore : public KeeperTask
27{
28 Q_OBJECT
29 Q_DECLARE_PRIVATE(KeeperTaskRestore)
30
31public:
32 KeeperTaskRestore(TaskData & task_data,
33 QSharedPointer<HelperRegistry> const & helper_registry,
34 QSharedPointer<StorageFrameworkClient> const & storage,
35 QObject *parent = nullptr);
36 virtual ~KeeperTaskRestore();
37
38 Q_DISABLE_COPY(KeeperTaskRestore)
39
40 void ask_for_downloader();
41
42protected:
43 QStringList get_helper_urls() const override;
44 void init_helper() override;
45
46};
047
=== modified file 'src/service/keeper-task.cpp'
--- src/service/keeper-task.cpp 2016-09-30 09:23:09 +0000
+++ src/service/keeper-task.cpp 2016-11-17 00:23:33 +0000
@@ -28,7 +28,7 @@
28#include <QString>28#include <QString>
2929
30KeeperTaskPrivate::KeeperTaskPrivate(KeeperTask * keeper_task,30KeeperTaskPrivate::KeeperTaskPrivate(KeeperTask * keeper_task,
31 KeeperTask::TaskData const & task_data,31 KeeperTask::TaskData & task_data,
32 QSharedPointer<HelperRegistry> const & helper_registry,32 QSharedPointer<HelperRegistry> const & helper_registry,
33 QSharedPointer<StorageFrameworkClient> const & storage)33 QSharedPointer<StorageFrameworkClient> const & storage)
34 : q_ptr(keeper_task)34 : q_ptr(keeper_task)
@@ -132,7 +132,7 @@
132 auto const percent_done = helper_->percent_done();132 auto const percent_done = helper_->percent_done();
133 ret.insert(QStringLiteral("percent-done"), double(percent_done));133 ret.insert(QStringLiteral("percent-done"), double(percent_done));
134134
135 if (task_data_.action == "failed")135 if (task_data_.action == "failed" || task_data_.action == "cancelled")
136 ret.insert(QStringLiteral("error"), task_data_.error);136 ret.insert(QStringLiteral("error"), task_data_.error);
137137
138 ret.insert(QStringLiteral("uuid"), uuid);138 ret.insert(QStringLiteral("uuid"), uuid);
@@ -145,8 +145,13 @@
145145
146void KeeperTaskPrivate::calculate_and_notify_state(Helper::State state)146void KeeperTaskPrivate::calculate_and_notify_state(Helper::State state)
147{147{
148 recalculate_task_state();
149 Q_EMIT(q_ptr->task_state_changed(state));
150}
151
152void KeeperTaskPrivate::recalculate_task_state()
153{
148 state_ = calculate_task_state();154 state_ = calculate_task_state();
149 Q_EMIT(q_ptr->task_state_changed(state));
150}155}
151156
152void KeeperTaskPrivate::cancel()157void KeeperTaskPrivate::cancel()
@@ -175,7 +180,20 @@
175 return ret;180 return ret;
176}181}
177182
178KeeperTask::KeeperTask(TaskData const & task_data,183QString KeeperTaskPrivate::to_string(Helper::State state)
184{
185 if (helper_)
186 {
187 return helper_->to_string(state);
188 }
189 else
190 {
191 qWarning() << "Asking for the string of a state when the helper is not initialized yet";
192 return "bug";
193 }
194}
195
196KeeperTask::KeeperTask(TaskData & task_data,
179 QSharedPointer<HelperRegistry> const & helper_registry,197 QSharedPointer<HelperRegistry> const & helper_registry,
180 QSharedPointer<StorageFrameworkClient> const & storage,198 QSharedPointer<StorageFrameworkClient> const & storage,
181 QObject *parent)199 QObject *parent)
@@ -207,6 +225,14 @@
207 return d->state();225 return d->state();
208}226}
209227
228void KeeperTask::recalculate_task_state()
229{
230 Q_D(KeeperTask);
231
232 return d->recalculate_task_state();
233}
234
235
210QVariantMap KeeperTask::get_initial_state(KeeperTask::TaskData const &td)236QVariantMap KeeperTask::get_initial_state(KeeperTask::TaskData const &td)
211{237{
212 return KeeperTaskPrivate::get_initial_state(td);238 return KeeperTaskPrivate::get_initial_state(td);
@@ -218,3 +244,10 @@
218244
219 return d->cancel();245 return d->cancel();
220}246}
247
248QString KeeperTask::to_string(Helper::State state)
249{
250 Q_D(KeeperTask);
251
252 return d->to_string(state);
253}
221254
=== modified file 'src/service/keeper-task.h'
--- src/service/keeper-task.h 2016-09-28 13:42:21 +0000
+++ src/service/keeper-task.h 2016-11-17 00:23:33 +0000
@@ -44,7 +44,7 @@
44 Metadata metadata;44 Metadata metadata;
45 };45 };
4646
47 KeeperTask(TaskData const & task_data,47 KeeperTask(TaskData & task_data,
48 QSharedPointer<HelperRegistry> const & helper_registry,48 QSharedPointer<HelperRegistry> const & helper_registry,
49 QSharedPointer<StorageFrameworkClient> const & storage,49 QSharedPointer<StorageFrameworkClient> const & storage,
50 QObject *parent = nullptr);50 QObject *parent = nullptr);
@@ -54,11 +54,13 @@
5454
55 bool start();55 bool start();
56 QVariantMap state() const;56 QVariantMap state() const;
57 void recalculate_task_state();
5758
58 static QVariantMap get_initial_state(KeeperTask::TaskData const &td);59 static QVariantMap get_initial_state(KeeperTask::TaskData const &td);
5960
60 void cancel();61 void cancel();
6162
63 QString to_string(Helper::State state);
62Q_SIGNALS:64Q_SIGNALS:
63 void task_state_changed(Helper::State state);65 void task_state_changed(Helper::State state);
64 void task_socket_ready(int socket_descriptor);66 void task_socket_ready(int socket_descriptor);
6567
=== modified file 'src/service/keeper-user.cpp'
--- src/service/keeper-user.cpp 2016-10-28 15:11:21 +0000
+++ src/service/keeper-user.cpp 2016-11-17 00:23:33 +0000
@@ -70,9 +70,11 @@
70void70void
71KeeperUser::StartRestore (const QStringList& keys)71KeeperUser::StartRestore (const QStringList& keys)
72{72{
73 // FIXME: writeme73 Q_ASSERT(calledFromDBus());
7474
75 qDebug() << keys;75 auto bus = connection();
76 auto& msg = message();
77 keeper_.start_tasks(keys, bus, msg, true);
76}78}
7779
78QVariantDictMap80QVariantDictMap
7981
=== modified file 'src/service/keeper.cpp'
--- src/service/keeper.cpp 2016-10-28 15:11:21 +0000
+++ src/service/keeper.cpp 2016-11-17 00:23:33 +0000
@@ -76,14 +76,25 @@
76 {76 {
77 }77 }
7878
79 enum class ChoicesType { BACKUP_CHOICES, RESTORES_CHOICES };
80
79 ~KeeperPrivate() =default;81 ~KeeperPrivate() =default;
8082
81 Q_DISABLE_COPY(KeeperPrivate)83 Q_DISABLE_COPY(KeeperPrivate)
8284
83 void start_tasks(QStringList const & uuids,85 void start_tasks(QStringList const & uuids,
84 QDBusConnection bus,86 QDBusConnection bus,
85 QDBusMessage const & msg)87 QDBusMessage const & msg,
88 bool reset_cached_choices)
86 {89 {
90 if (reset_cached_choices)
91 {
92 // if we start a restore right after a backup the uuid
93 // will be found as a backup uuid.
94 // Just clear the backup cache to avoid that.
95 cached_backup_choices_.clear();
96 }
97
87 auto get_tasks = [](const QVector<Metadata>& pool, QStringList const& keys){98 auto get_tasks = [](const QVector<Metadata>& pool, QStringList const& keys){
88 QMap<QString,Metadata> tasks;99 QMap<QString,Metadata> tasks;
89 for (auto const& key : keys) {100 for (auto const& key : keys) {
@@ -95,9 +106,10 @@
95 };106 };
96107
97 // async part108 // async part
109 qDebug() << "Looking for backup options....";
98 connections_.connect_oneshot(110 connections_.connect_oneshot(
99 this,111 this,
100 &KeeperPrivate::choices_ready,112 &KeeperPrivate::backup_choices_ready,
101 std::function<void()>{[this, uuids, msg, bus, get_tasks](){113 std::function<void()>{[this, uuids, msg, bus, get_tasks](){
102 auto tasks = get_tasks(cached_backup_choices_, uuids);114 auto tasks = get_tasks(cached_backup_choices_, uuids);
103 if (!tasks.empty())115 if (!tasks.empty())
@@ -114,12 +126,15 @@
114 }126 }
115 else // restore127 else // restore
116 {128 {
129 qDebug() << "Looking for restore options....";
117 connections_.connect_oneshot(130 connections_.connect_oneshot(
118 this,131 this,
119 &KeeperPrivate::choices_ready,132 &KeeperPrivate::restore_choices_ready,
120 std::function<void()>{[this, uuids, msg, bus, get_tasks](){133 std::function<void()>{[this, uuids, msg, bus, get_tasks](){
134 qDebug() << "Choices ready";
121 auto unhandled = QSet<QString>::fromList(uuids);135 auto unhandled = QSet<QString>::fromList(uuids);
122 auto restore_tasks = get_tasks(cached_restore_choices_, uuids);136 auto restore_tasks = get_tasks(cached_restore_choices_, uuids);
137 qDebug() << "After getting tasks...";
123 if (!restore_tasks.empty() && task_manager_.start_restore(restore_tasks.values()))138 if (!restore_tasks.empty() && task_manager_.start_restore(restore_tasks.values()))
124 unhandled.subtract(QSet<QString>::fromList(restore_tasks.keys()));139 unhandled.subtract(QSet<QString>::fromList(restore_tasks.keys()));
125140
@@ -130,34 +145,58 @@
130 bus.send(reply);145 bus.send(reply);
131 }}146 }}
132 );147 );
133 get_restore_choices();148 get_choices(restore_choices_, KeeperPrivate::ChoicesType::RESTORES_CHOICES);
134 }149 }
135 }}150 }}
136 );151 );
137152
138 get_backup_choices();153 get_choices(backup_choices_, KeeperPrivate::ChoicesType::BACKUP_CHOICES);
139 msg.setDelayedReply(true);154 msg.setDelayedReply(true);
140 }155 }
141156
142 void get_backup_choices()157 void emit_choices_ready(ChoicesType type)
143 {158 {
144 if (cached_backup_choices_.isEmpty())159 switch(type)
160 {
161 case KeeperPrivate::ChoicesType::BACKUP_CHOICES:
162 Q_EMIT(backup_choices_ready());
163 break;
164 case KeeperPrivate::ChoicesType::RESTORES_CHOICES:
165 Q_EMIT(restore_choices_ready());
166 break;
167 }
168 }
169 void get_choices(const QSharedPointer<MetadataProvider> & provider, ChoicesType type)
170 {
171 qDebug() << Q_FUNC_INFO;
172 bool check_empty = (type == KeeperPrivate::ChoicesType::BACKUP_CHOICES)
173 ? cached_backup_choices_.isEmpty() : cached_restore_choices_.isEmpty();
174 if (check_empty)
145 {175 {
146 connections_.connect_oneshot(176 connections_.connect_oneshot(
147 backup_choices_.data(),177 provider.data(),
148 &MetadataProvider::finished,178 &MetadataProvider::finished,
149 std::function<void()>{[this](){179 std::function<void()>{[this, provider, type](){
150 qDebug() << "Get backups finished";180 qDebug() << "Get choices finished";
151 cached_backup_choices_ = backup_choices_->get_backups();181 switch (type)
152 Q_EMIT(choices_ready());182 {
183 case KeeperPrivate::ChoicesType::BACKUP_CHOICES:
184 cached_backup_choices_ = provider->get_backups();
185 break;
186 case KeeperPrivate::ChoicesType::RESTORES_CHOICES:
187 cached_restore_choices_ = provider->get_backups();
188 break;
189 };
190 emit_choices_ready(type);
153 }}191 }}
154 );192 );
155193
156 backup_choices_->get_backups_async();194 provider->get_backups_async();
157 }195 }
158 else196 else
159 {197 {
160 Q_EMIT(choices_ready());198 qDebug() << "emit choices_ready()";
199 emit_choices_ready(type);
161 }200 }
162 }201 }
163202
@@ -166,7 +205,7 @@
166 {205 {
167 connections_.connect_oneshot(206 connections_.connect_oneshot(
168 this,207 this,
169 &KeeperPrivate::choices_ready,208 &KeeperPrivate::backup_choices_ready,
170 std::function<void()>{[this, msg, bus](){209 std::function<void()>{[this, msg, bus](){
171 qDebug() << "Backup choices are ready";210 qDebug() << "Backup choices are ready";
172 // reply now to the dbus call211 // reply now to the dbus call
@@ -176,7 +215,7 @@
176 }}215 }}
177 );216 );
178217
179 get_backup_choices();218 get_choices(backup_choices_, KeeperPrivate::ChoicesType::BACKUP_CHOICES);
180 msg.setDelayedReply(true);219 msg.setDelayedReply(true);
181 return QVariantDictMap();220 return QVariantDictMap();
182 }221 }
@@ -186,7 +225,7 @@
186 {225 {
187 connections_.connect_oneshot(226 connections_.connect_oneshot(
188 this,227 this,
189 &KeeperPrivate::choices_ready,228 &KeeperPrivate::restore_choices_ready,
190 std::function<void()>{[this, msg, bus](){229 std::function<void()>{[this, msg, bus](){
191 qDebug() << "Restore choices are ready";230 qDebug() << "Restore choices are ready";
192 // reply now to the dbus call231 // reply now to the dbus call
@@ -196,34 +235,11 @@
196 }}235 }}
197 );236 );
198237
199 get_restore_choices();238 get_choices(restore_choices_, KeeperPrivate::ChoicesType::RESTORES_CHOICES);
200 msg.setDelayedReply(true);239 msg.setDelayedReply(true);
201 return QVariantDictMap();240 return QVariantDictMap();
202 }241 }
203242
204 // TODO REFACTOR THIS TO USE THE SAME METHOD POR RESTORES AND BACKUPS
205 void get_restore_choices()
206 {
207 if (cached_restore_choices_.isEmpty())
208 {
209 connections_.connect_oneshot(
210 restore_choices_.data(),
211 &MetadataProvider::finished,
212 std::function<void()>{[this](){
213 qDebug() << "Get restores finished";
214 cached_restore_choices_ = restore_choices_->get_backups();
215 Q_EMIT(choices_ready());
216 }}
217 );
218
219 restore_choices_->get_backups_async();
220 }
221 else
222 {
223 Q_EMIT(choices_ready());
224 }
225 }
226
227 QVariantDictMap get_state() const243 QVariantDictMap get_state() const
228 {244 {
229 return task_manager_.get_state();245 return task_manager_.get_state();
@@ -233,7 +249,7 @@
233 QDBusMessage const & msg,249 QDBusMessage const & msg,
234 quint64 n_bytes)250 quint64 n_bytes)
235 {251 {
236 qDebug("Keeper::StartBackup(n_bytes=%zu)", size_t(n_bytes));252 qDebug() << Q_FUNC_INFO << "n_bytes:" << n_bytes;
237253
238 connections_.connect_oneshot(254 connections_.connect_oneshot(
239 &task_manager_,255 &task_manager_,
@@ -248,7 +264,7 @@
248 }264 }
249 );265 );
250266
251 qDebug() << "Asking for an storage framework socket to the task manager";267 qDebug() << "Asking TaskManager for a socket to upload to";
252 task_manager_.ask_for_uploader(n_bytes);268 task_manager_.ask_for_uploader(n_bytes);
253269
254 // tell the caller that we'll be responding async270 // tell the caller that we'll be responding async
@@ -256,12 +272,41 @@
256 return QDBusUnixFileDescriptor(0);272 return QDBusUnixFileDescriptor(0);
257 }273 }
258274
275
276 QDBusUnixFileDescriptor start_restore(QDBusConnection bus,
277 QDBusMessage const & msg)
278 {
279 qDebug() << Q_FUNC_INFO;
280
281 connections_.connect_oneshot(
282 &task_manager_,
283 &TaskManager::socket_ready,
284 std::function<void(int)>{
285 [bus,msg](int fd){
286 qDebug("TaskManager::ask_for_downloader() returned socket %d", fd);
287 auto reply = msg.createReply();
288 reply << QVariant::fromValue(QDBusUnixFileDescriptor(fd));
289 bus.send(reply);
290 }
291 }
292 );
293
294 qDebug() << "Asking TaskManager for a socket to download from";
295 task_manager_.ask_for_downloader();
296
297 // tell the caller that we'll be responding async
298 msg.setDelayedReply(true);
299 return QDBusUnixFileDescriptor(0);
300 }
301
259 void cancel()302 void cancel()
260 {303 {
261 task_manager_.cancel();304 task_manager_.cancel();
262 }305 }
306
263Q_SIGNALS:307Q_SIGNALS:
264 void choices_ready();308 void backup_choices_ready();
309 void restore_choices_ready();
265310
266private:311private:
267312
@@ -305,11 +350,12 @@
305void350void
306Keeper::start_tasks(QStringList const & uuids,351Keeper::start_tasks(QStringList const & uuids,
307 QDBusConnection bus,352 QDBusConnection bus,
308 QDBusMessage const & msg)353 QDBusMessage const & msg,
354 bool reset_cached_choices)
309{355{
310 Q_D(Keeper);356 Q_D(Keeper);
311357
312 d->start_tasks(uuids, bus, msg);358 d->start_tasks(uuids, bus, msg, reset_cached_choices);
313}359}
314360
315QDBusUnixFileDescriptor361QDBusUnixFileDescriptor
@@ -322,6 +368,15 @@
322 return d->start_backup(bus, msg, n_bytes);368 return d->start_backup(bus, msg, n_bytes);
323}369}
324370
371QDBusUnixFileDescriptor
372Keeper::StartRestore(QDBusConnection bus,
373 QDBusMessage const & msg)
374{
375 Q_D(Keeper);
376
377 return d->start_restore(bus, msg);
378}
379
325QVariantDictMap380QVariantDictMap
326Keeper::get_backup_choices_var_dict_map(QDBusConnection bus,381Keeper::get_backup_choices_var_dict_map(QDBusConnection bus,
327 QDBusMessage const & msg)382 QDBusMessage const & msg)
328383
=== modified file 'src/service/keeper.h'
--- src/service/keeper.h 2016-10-28 15:11:21 +0000
+++ src/service/keeper.h 2016-11-17 00:23:33 +0000
@@ -59,9 +59,14 @@
59 QDBusMessage const & message,59 QDBusMessage const & message,
60 quint64 nbytes);60 quint64 nbytes);
6161
62
63 QDBusUnixFileDescriptor StartRestore(QDBusConnection,
64 QDBusMessage const & message);
65
62 void start_tasks(QStringList const & uuids,66 void start_tasks(QStringList const & uuids,
63 QDBusConnection bus,67 QDBusConnection bus,
64 QDBusMessage const & msg);68 QDBusMessage const & msg,
69 bool reset_cached_choices = false);
6570
66 QVariantDictMap get_state() const;71 QVariantDictMap get_state() const;
6772
6873
=== modified file 'src/service/manifest.cpp'
--- src/service/manifest.cpp 2016-10-13 12:22:31 +0000
+++ src/service/manifest.cpp 2016-11-17 00:23:33 +0000
@@ -110,8 +110,8 @@
110 {110 {
111 connections_.connect_future(111 connections_.connect_future(
112 storage_->get_new_downloader(dir_, MANIFEST_FILE_NAME),112 storage_->get_new_downloader(dir_, MANIFEST_FILE_NAME),
113 std::function<void(sf::Downloader::SPtr const&)>{113 std::function<void(std::shared_ptr<Downloader> const&)>{
114 [this](sf::Downloader::SPtr const& downloader){114 [this](std::shared_ptr<Downloader> const& downloader){
115 qDebug() << "Manifest downloader is" << static_cast<void*>(downloader.get());115 qDebug() << "Manifest downloader is" << static_cast<void*>(downloader.get());
116 if (downloader)116 if (downloader)
117 {117 {
@@ -125,7 +125,7 @@
125 }125 }
126 auto json_content = socket->readAll();126 auto json_content = socket->readAll();
127 from_json(json_content);127 from_json(json_content);
128 downloader->finish_download();128 downloader->finish();
129 finish();129 finish();
130 }130 }
131 else131 else
132132
=== modified file 'src/service/private/keeper-task_p.h'
--- src/service/private/keeper-task_p.h 2016-09-28 13:42:21 +0000
+++ src/service/private/keeper-task_p.h 2016-11-17 00:23:33 +0000
@@ -26,7 +26,7 @@
26 Q_DECLARE_PUBLIC(KeeperTask)26 Q_DECLARE_PUBLIC(KeeperTask)
27public:27public:
28 KeeperTaskPrivate(KeeperTask * keeper_task,28 KeeperTaskPrivate(KeeperTask * keeper_task,
29 KeeperTask::TaskData const & task_data,29 KeeperTask::TaskData & task_data,
30 QSharedPointer<HelperRegistry> const & helper_registry,30 QSharedPointer<HelperRegistry> const & helper_registry,
31 QSharedPointer<StorageFrameworkClient> const & storage);31 QSharedPointer<StorageFrameworkClient> const & storage);
3232
@@ -40,17 +40,19 @@
4040
41 static QVariantMap get_initial_state(KeeperTask::TaskData const &td);41 static QVariantMap get_initial_state(KeeperTask::TaskData const &td);
4242
43 QString to_string(Helper::State state);
43protected:44protected:
44 void set_current_task_action(QString const& action);45 void set_current_task_action(QString const& action);
45 void on_helper_percent_done_changed(float percent_done);46 void on_helper_percent_done_changed(float percent_done);
46 QVariantMap calculate_task_state();47 QVariantMap calculate_task_state();
47 void calculate_and_notify_state(Helper::State state);48 void calculate_and_notify_state(Helper::State state);
49 void recalculate_task_state();
48 void on_backup_socket_ready(std::shared_ptr<QLocalSocket> const & sf_socket);50 void on_backup_socket_ready(std::shared_ptr<QLocalSocket> const & sf_socket);
4951
50 virtual void on_helper_state_changed(Helper::State state);52 virtual void on_helper_state_changed(Helper::State state);
5153
52 KeeperTask * const q_ptr;54 KeeperTask * const q_ptr;
53 KeeperTask::TaskData task_data_;55 KeeperTask::TaskData & task_data_;
54 QSharedPointer<HelperRegistry> helper_registry_;56 QSharedPointer<HelperRegistry> helper_registry_;
55 QSharedPointer<StorageFrameworkClient> storage_;57 QSharedPointer<StorageFrameworkClient> storage_;
56 QSharedPointer<Helper> helper_;58 QSharedPointer<Helper> helper_;
5759
=== modified file 'src/service/task-manager.cpp'
--- src/service/task-manager.cpp 2016-11-03 10:32:49 +0000
+++ src/service/task-manager.cpp 2016-11-17 00:23:33 +0000
@@ -20,6 +20,7 @@
2020
21#include "helper/metadata.h"21#include "helper/metadata.h"
22#include "keeper-task-backup.h"22#include "keeper-task-backup.h"
23#include "keeper-task-restore.h"
23#include "manifest.h"24#include "manifest.h"
24#include "storage-framework/storage_framework_client.h"25#include "storage-framework/storage_framework_client.h"
25#include "task-manager.h"26#include "task-manager.h"
@@ -50,6 +51,7 @@
5051
51 bool start_restore(QList<Metadata> const& tasks)52 bool start_restore(QList<Metadata> const& tasks)
52 {53 {
54 qDebug() << "Starting restore...";
53 return start_tasks(tasks, Mode::RESTORE);55 return start_tasks(tasks, Mode::RESTORE);
54 }56 }
5557
@@ -78,6 +80,23 @@
78 }80 }
79 }81 }
8082
83 void ask_for_downloader()
84 {
85 qDebug() << Q_FUNC_INFO;
86
87 if (task_)
88 {
89 auto restore_task_ = qSharedPointerDynamicCast<KeeperTaskRestore>(task_);
90 if (!restore_task_)
91 {
92 qWarning() << "Only restore tasks are allowed to ask for storage framework downloaders";
93 // TODO Mark this as an error at the current task and move to the next task
94 return;
95 }
96 restore_task_->ask_for_downloader();
97 }
98 }
99
81 void cancel()100 void cancel()
82 {101 {
83 if (task_)102 if (task_)
@@ -140,19 +159,40 @@
140 return success;159 return success;
141 }160 }
142161
162 void manifest_stored(bool success)
163 {
164 qDebug() << "Manifest upload finished success = " << success << " current task=" << current_task_;
165 auto& td = task_data_[current_task_];
166 if (success)
167 {
168 update_task_state(td);
169 }
170 else
171 {
172 td.error = "Error storing manifest file";
173 set_current_task_action(task_->to_string(Helper::State::FAILED));
174 }
175 active_manifest_.reset();
176 }
177
143 void on_helper_state_changed(Helper::State state)178 void on_helper_state_changed(Helper::State state)
144 {179 {
145 qDebug() << "Task State changed";180 auto backup_task_ = qSharedPointerDynamicCast<KeeperTaskBackup>(task_);
146 auto& td = task_data_[current_task_];181 auto& td = task_data_[current_task_];
147 update_task_state(td);182 update_task_state(td);
148183
184 // for the last completed backup task we delay updating the
185 // state until the manifest file is stored
186 if (remaining_tasks_.size() || state != Helper::State::COMPLETE)
187 update_task_state(td);
188
149 if (state == Helper::State::COMPLETE || state == Helper::State::FAILED)189 if (state == Helper::State::COMPLETE || state == Helper::State::FAILED)
150 {190 {
151 auto backup_task_ = qSharedPointerDynamicCast<KeeperTaskBackup>(task_);
152 if (backup_task_ && state == Helper::State::COMPLETE && active_manifest_)191 if (backup_task_ && state == Helper::State::COMPLETE && active_manifest_)
153 {192 {
154 qDebug() << "Backup task finished. The file created in storage framework is: [" << backup_task_->get_file_name() << "]";193 qDebug() << "Backup task finished. The file created in storage framework is: [" << backup_task_->get_file_name() << "]";
155 td.metadata.set_property(Metadata::FILE_NAME_KEY, backup_task_->get_file_name());194 td.metadata.set_property(Metadata::FILE_NAME_KEY, backup_task_->get_file_name());
195 td.metadata.set_property(Metadata::DIR_NAME_KEY, backup_dir_name_);
156 active_manifest_->add_entry(td.metadata);196 active_manifest_->add_entry(td.metadata);
157 }197 }
158 if (remaining_tasks_.size())198 if (remaining_tasks_.size())
@@ -162,9 +202,6 @@
162 }202 }
163 else203 else
164 {204 {
165 // TODO we should revisit this.
166 // TODO Maybe we could treat the manifest storage as a new task (with a different task type) to check
167 // TODO when all tasks are finished and prompt something to the user.
168 if (active_manifest_ && active_manifest_->get_entries().size())205 if (active_manifest_ && active_manifest_->get_entries().size())
169 {206 {
170 qDebug() << "STORING MANIFEST------------";207 qDebug() << "STORING MANIFEST------------";
@@ -172,11 +209,7 @@
172 active_manifest_.data(),209 active_manifest_.data(),
173 &Manifest::finished,210 &Manifest::finished,
174 std::function<void(bool)>{[this](bool success){211 std::function<void(bool)>{[this](bool success){
175 if (!success)212 manifest_stored(success);
176 qWarning() << "Manifest store finished with error: " << active_manifest_->error();
177 else
178 qDebug() << "Manifest store finished successfully";
179 active_manifest_.reset();
180 }}213 }}
181 );214 );
182 active_manifest_->store();215 active_manifest_->store();
@@ -203,14 +236,16 @@
203 qDebug() << "Creating task for uuid = " << uuid;236 qDebug() << "Creating task for uuid = " << uuid;
204 // initialize a new task237 // initialize a new task
205238
206 task_.data()->disconnect();239 if (task_)
240 task_.data()->disconnect();
241
207 if (mode_ == Mode::BACKUP)242 if (mode_ == Mode::BACKUP)
208 {243 {
209 task_.reset(new KeeperTaskBackup(td, helper_registry_, storage_));244 task_.reset(new KeeperTaskBackup(td, helper_registry_, storage_));
210 }245 }
211 else246 else
212 {247 {
213 // TODO initialize a Restore task248 task_.reset(new KeeperTaskRestore(td, helper_registry_, storage_));
214 }249 }
215250
216 qDebug() << "task created: " << state_;251 qDebug() << "task created: " << state_;
@@ -311,6 +346,7 @@
311 {346 {
312 auto& td = task_data_[current_task_];347 auto& td = task_data_[current_task_];
313 td.action = action;348 td.action = action;
349 task_->recalculate_task_state();
314 update_task_state(td);350 update_task_state(td);
315 }351 }
316352
@@ -381,6 +417,13 @@
381 d->ask_for_uploader(n_bytes);417 d->ask_for_uploader(n_bytes);
382}418}
383419
420void TaskManager::ask_for_downloader()
421{
422 Q_D(TaskManager);
423
424 d->ask_for_downloader();
425}
426
384void TaskManager::cancel()427void TaskManager::cancel()
385{428{
386 Q_D(TaskManager);429 Q_D(TaskManager);
387430
=== modified file 'src/service/task-manager.h'
--- src/service/task-manager.h 2016-09-28 13:42:21 +0000
+++ src/service/task-manager.h 2016-11-17 00:23:33 +0000
@@ -58,6 +58,8 @@
5858
59 void ask_for_uploader(quint64 n_bytes);59 void ask_for_uploader(quint64 n_bytes);
6060
61 void ask_for_downloader();
62
61 void cancel();63 void cancel();
6264
63Q_SIGNALS:65Q_SIGNALS:
6466
=== modified file 'src/storage-framework/CMakeLists.txt'
--- src/storage-framework/CMakeLists.txt 2016-09-05 17:24:18 +0000
+++ src/storage-framework/CMakeLists.txt 2016-11-17 00:23:33 +0000
@@ -11,6 +11,9 @@
11 uploader.h11 uploader.h
12 sf-uploader.cpp12 sf-uploader.cpp
13 sf-uploader.h13 sf-uploader.h
14 downloader.h
15 sf-downloader.cpp
16 sf-downloader.h
14)17)
1518
16set_target_properties(19set_target_properties(
1720
=== added file 'src/storage-framework/downloader.h'
--- src/storage-framework/downloader.h 1970-01-01 00:00:00 +0000
+++ src/storage-framework/downloader.h 2016-11-17 00:23:33 +0000
@@ -0,0 +1,46 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 * Xavi Garcia Mena <xavi.garcia.mena@canonical.com>
19 */
20
21#pragma once
22
23#include <QLocalSocket>
24#include <QObject>
25
26#include <memory>
27
28class Downloader: public QObject
29{
30 Q_OBJECT
31
32public:
33
34 Q_DISABLE_COPY(Downloader)
35
36 Downloader(QObject *parent=nullptr): QObject(parent) {}
37 virtual ~Downloader() =default;
38
39 virtual std::shared_ptr<QLocalSocket> socket() =0;
40 virtual void finish() =0;
41 virtual qint64 file_size() const =0;
42
43Q_SIGNALS:
44
45 void download_finished();
46};
047
=== added file 'src/storage-framework/sf-downloader.cpp'
--- src/storage-framework/sf-downloader.cpp 1970-01-01 00:00:00 +0000
+++ src/storage-framework/sf-downloader.cpp 2016-11-17 00:23:33 +0000
@@ -0,0 +1,71 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 * Xavi Garcia Mena <xavi.garcia.mena@canonical.com>
19 */
20
21#include "storage-framework/sf-downloader.h"
22
23#include <QFuture>
24#include <QFutureWatcher>
25
26StorageFrameworkDownloader::StorageFrameworkDownloader(
27 unity::storage::qt::client::Downloader::SPtr const& downloader,
28 qint64 file_size,
29 QObject *parent
30):
31 Downloader(parent),
32 downloader_(downloader),
33 file_size_(file_size)
34{
35 qDebug() << "StorageFrameworkDownloader";
36}
37
38std::shared_ptr<QLocalSocket>
39StorageFrameworkDownloader::socket()
40{
41 return downloader_->socket();
42}
43
44void
45StorageFrameworkDownloader::finish()
46{
47 qDebug() << Q_FUNC_INFO << "is finishing";
48
49// connections_.connect_future(
50// uploader_->finish_upload(),
51// std::function<void(std::shared_ptr<unity::storage::qt::client::File> const&)>{
52// [this](std::shared_ptr<unity::storage::qt::client::File> const& file){
53// auto const success = bool(file);
54// qDebug() << "commit finished with" << success;
55// if (success)
56// {
57// file_name_after_commit_ = file->name();
58// }
59// Q_EMIT(commit_finished(success));
60// }
61// }
62// );
63 downloader_->finish_download();
64 Q_EMIT(download_finished()); // TODO add the code to call finish_download
65}
66
67qint64
68StorageFrameworkDownloader::file_size() const
69{
70 return file_size_;
71}
072
=== added file 'src/storage-framework/sf-downloader.h'
--- src/storage-framework/sf-downloader.h 1970-01-01 00:00:00 +0000
+++ src/storage-framework/sf-downloader.h 2016-11-17 00:23:33 +0000
@@ -0,0 +1,48 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#pragma once
21
22#include "util/connection-helper.h"
23#include "storage-framework/downloader.h"
24
25#include <unity/storage/qt/client/client-api.h>
26
27#include <QLocalSocket>
28
29#include <memory>
30
31class StorageFrameworkDownloader final: public Downloader
32{
33public:
34
35 StorageFrameworkDownloader(unity::storage::qt::client::Downloader::SPtr const& uploader,
36 qint64 file_size,
37 QObject * parent = nullptr);
38 std::shared_ptr<QLocalSocket> socket() override;
39 void finish() override;
40 qint64 file_size() const override;
41
42private:
43
44 unity::storage::qt::client::Downloader::SPtr const downloader_;
45 qint64 file_size_;
46
47 ConnectionHelper connections_;
48};
049
=== modified file 'src/storage-framework/storage_framework_client.cpp'
--- src/storage-framework/storage_framework_client.cpp 2016-11-03 10:32:49 +0000
+++ src/storage-framework/storage_framework_client.cpp 2016-11-17 00:23:33 +0000
@@ -19,6 +19,7 @@
19 */19 */
2020
21#include "storage-framework/storage_framework_client.h"21#include "storage-framework/storage_framework_client.h"
22#include "storage-framework/sf-downloader.h"
22#include "storage-framework/sf-uploader.h"23#include "storage-framework/sf-uploader.h"
2324
24#include <QDateTime>25#include <QDateTime>
@@ -39,7 +40,7 @@
39{40{
40}41}
4142
42StorageFrameworkClient::~StorageFrameworkClient() =default;43StorageFrameworkClient::~StorageFrameworkClient() = default;
4344
44/***45/***
45****46****
@@ -154,10 +155,10 @@
154 return fi.future();155 return fi.future();
155}156}
156157
157QFuture<sf::Downloader::SPtr>158QFuture<std::shared_ptr<Downloader>>
158StorageFrameworkClient::get_new_downloader(QString const & dir_name, QString const & file_name)159StorageFrameworkClient::get_new_downloader(QString const & dir_name, QString const & file_name)
159{160{
160 QFutureInterface<sf::Downloader::SPtr> fi;161 QFutureInterface<std::shared_ptr<Downloader>> fi;
161162
162 add_roots_task([this, fi, dir_name, file_name](QVector<sf::Root::SPtr> const& roots)163 add_roots_task([this, fi, dir_name, file_name](QVector<sf::Root::SPtr> const& roots)
163 {164 {
@@ -171,7 +172,7 @@
171 if (!keeper_root)172 if (!keeper_root)
172 {173 {
173 qWarning() << "Error accessing keeper root folder";174 qWarning() << "Error accessing keeper root folder";
174 sf::Downloader::SPtr ret;175 std::shared_ptr<Downloader> ret;
175 QFutureInterface<decltype(ret)> qfi(fi);176 QFutureInterface<decltype(ret)> qfi(fi);
176 qfi.reportResult(ret);177 qfi.reportResult(ret);
177 qfi.reportFinished();178 qfi.reportFinished();
@@ -183,27 +184,27 @@
183 get_storage_framework_file(keeper_root, file_name),184 get_storage_framework_file(keeper_root, file_name),
184 std::function<void(sf::File::SPtr const&)>{185 std::function<void(sf::File::SPtr const&)>{
185 [this, fi](sf::File::SPtr const& sf_file){186 [this, fi](sf::File::SPtr const& sf_file){
186 sf::Downloader::SPtr ret_null;
187 if (sf_file) {187 if (sf_file) {
188 connection_helper_.connect_future(188 connection_helper_.connect_future(
189 sf_file->create_downloader(),189 sf_file->create_downloader(),
190 std::function<void(sf::Downloader::SPtr const&)>{190 std::function<void(sf::Downloader::SPtr const&)>{
191 [this, fi, ret_null](sf::Downloader::SPtr const& sf_downloader){191 [this, fi, sf_file](sf::Downloader::SPtr const& sf_downloader){
192 QFutureInterface<decltype(ret_null)> qfi(fi);192 std::shared_ptr<Downloader> ret;
193 if (sf_downloader)193 if (sf_downloader)
194 {194 {
195 qfi.reportResult(sf_downloader);195 ret.reset(
196 qfi.reportFinished();196 new StorageFrameworkDownloader(sf_downloader, sf_file->size(), this),
197 }197 [](Downloader* d){d->deleteLater();}
198 else198 );
199 {199 }
200 qfi.reportResult(ret_null);200 QFutureInterface<decltype(ret)> qfi(fi);
201 qfi.reportFinished();201 qfi.reportResult(ret);
202 }202 qfi.reportFinished();
203 }203 }
204 }204 }
205 );205 );
206 } else {206 } else {
207 std::shared_ptr<Downloader> ret_null;
207 QFutureInterface<decltype(ret_null)> qfi(fi);208 QFutureInterface<decltype(ret_null)> qfi(fi);
208 qfi.reportResult(ret_null);209 qfi.reportResult(ret_null);
209 qfi.reportFinished();210 qfi.reportFinished();
210211
=== modified file 'src/storage-framework/storage_framework_client.h'
--- src/storage-framework/storage_framework_client.h 2016-11-03 10:32:49 +0000
+++ src/storage-framework/storage_framework_client.h 2016-11-17 00:23:33 +0000
@@ -22,6 +22,7 @@
2222
23#include "util/connection-helper.h"23#include "util/connection-helper.h"
24#include "storage-framework/uploader.h"24#include "storage-framework/uploader.h"
25#include "storage-framework/downloader.h"
2526
26#include <unity/storage/qt/client/client-api.h>27#include <unity/storage/qt/client/client-api.h>
2728
@@ -43,7 +44,7 @@
43 virtual ~StorageFrameworkClient();44 virtual ~StorageFrameworkClient();
4445
45 QFuture<std::shared_ptr<Uploader>> get_new_uploader(int64_t n_bytes, QString const & dir_name, QString const & file_name);46 QFuture<std::shared_ptr<Uploader>> get_new_uploader(int64_t n_bytes, QString const & dir_name, QString const & file_name);
46 QFuture<unity::storage::qt::client::Downloader::SPtr> get_new_downloader(QString const & dir_name, QString const & file_name);47 QFuture<std::shared_ptr<Downloader>> get_new_downloader(QString const & dir_name, QString const & file_name);
47 QFuture<QVector<QString>> get_keeper_dirs();48 QFuture<QVector<QString>> get_keeper_dirs();
4849
49 static QString const KEEPER_FOLDER;50 static QString const KEEPER_FOLDER;
5051
=== added directory 'src/test-restore'
=== added file 'src/test-restore/CMakeLists.txt'
--- src/test-restore/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ src/test-restore/CMakeLists.txt 2016-11-17 00:23:33 +0000
@@ -0,0 +1,40 @@
1set(TEST_RESTORE_EXEC "test-restore-socket")
2
3include_directories("${CMAKE_SOURCE_DIR}/src")
4include_directories("${CMAKE_BINARY_DIR}/src/qdbus-stubs")
5include_directories("${CMAKE_SOURCE_DIR}/src/qdbus-stubs")
6
7set(TEST_RESTORE_SOURCES
8 main.cpp
9 test-restore-socket.cpp
10)
11
12add_executable(
13 ${TEST_RESTORE_EXEC}
14 ${TEST_RESTORE_SOURCES}
15)
16
17link_directories(
18 ${SERVICE_DEPS_LIBRARY_DIRS}
19)
20
21set(
22 RESTORE_STATIC_LIBS
23 storage-framework
24 util
25# qdbus-stubs
26)
27
28target_link_libraries(
29 ${TEST_RESTORE_EXEC}
30 ${RESTORE_STATIC_LIBS}
31 ${SERVICE_DEVEL_SF_DEPS_LIBRARIES}
32 Qt5::Core
33 Qt5::DBus
34)
35
36install(
37 TARGETS
38 ${TEST_RESTORE_EXEC}
39 RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}
40)
041
=== added file 'src/test-restore/main.cpp'
--- src/test-restore/main.cpp 1970-01-01 00:00:00 +0000
+++ src/test-restore/main.cpp 2016-11-17 00:23:33 +0000
@@ -0,0 +1,32 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 * Xavi Garcia Mena <xavi.garcia.mena@canonical.com>
19 */
20#include <QCoreApplication>
21
22#include "test-restore-socket.h"
23
24int main(int argc, char **argv)
25{
26 QCoreApplication app(argc, argv);
27
28 TestRestoreSocket test_restore;
29 test_restore.start("test_dir", "test_file");
30
31 return app.exec();
32}
033
=== added file 'src/test-restore/test-restore-socket.cpp'
--- src/test-restore/test-restore-socket.cpp 1970-01-01 00:00:00 +0000
+++ src/test-restore/test-restore-socket.cpp 2016-11-17 00:23:33 +0000
@@ -0,0 +1,139 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 * Xavi Garcia Mena <xavi.garcia.mena@canonical.com>
19 */
20
21#include "test-restore-socket.h"
22
23#include "storage-framework/storage_framework_client.h"
24#include "storage-framework/sf-downloader.h"
25
26constexpr int UPLOAD_BUFFER_MAX_ {1024*16};
27
28TestRestoreSocket::TestRestoreSocket(QObject *parent)
29 : QObject(parent)
30 , sf_client_(new StorageFrameworkClient)
31 , file_("/tmp/test-downloader")
32{
33 file_.open(QIODevice::WriteOnly);
34 connect (&future_watcher_, &QFutureWatcher<std::shared_ptr<Downloader>>::finished, [this]{on_socket_received(future_watcher_.result());});
35}
36
37TestRestoreSocket::~TestRestoreSocket() = default;
38
39void TestRestoreSocket::start(QString const & dir_name, QString const & file_name)
40{
41 qDebug() << "asking storage framework for a socket for reading";
42
43 future_watcher_.setFuture(sf_client_->get_new_downloader(dir_name, file_name));
44// connections_.connect_future(
45// sf_client_->get_new_downloader(dir_name, file_name),
46// std::function<void(std::shared_ptr<Downloader> const&)>{
47// [this](std::shared_ptr<Downloader> const& downloader){
48// qDebug() << "Downloader is" << static_cast<void*>(downloader.get());
49// if (downloader) {
50// this->on_socket_received(downloader);
51// }
52// }
53// }
54// );
55}
56
57void TestRestoreSocket::read_data()
58{
59 if (socket_->bytesAvailable())
60 {
61//// char readbuf[UPLOAD_BUFFER_MAX_];
62//// const auto n = socket_->read(readbuf, sizeof(readbuf));
63//// if (n > 0) {
64//// n_read_ += n;
65//// qDebug() << "Read " << n << " bytes. Total: " << n_read_;
66//
67// char readbuf[64 *1024];
68// // try to fill the upload buf
69// int max_bytes = UPLOAD_BUFFER_MAX_;// - upload_buffer_.size();
70// if (max_bytes > 0) {
71// const auto n = socket_->read(readbuf, max_bytes);
72// if (n > 0) {
73// n_read_ += n;
74// qDebug() << "Read " << n << " bytes. Total: " << n_read_;
75//
76//// if (file_.isOpen())
77//// {
78//// file_.write(readbuf, max_bytes);
79//// }
80//// }
81//// else if (n < 0) {
82//// qDebug() << "Read error: " << socket_->errorString();
83//// return;
84// if (file_.isOpen())
85// {
86// file_.write(readbuf, n);
87// }
88// }
89// else if (n < 0) {
90// qDebug() << "Read error: " << socket_->errorString();
91// return;
92// }
93// }
94
95 char readbuf[64 *1024];
96 const auto n = socket_->read(readbuf, sizeof(readbuf));
97 if (n > 0) {
98 n_read_ += n;
99 qDebug() << "Read " << n << " bytes. Total: " << n_read_;
100 if (file_.isOpen())
101 {
102 file_.write(readbuf, n);
103 }
104 }
105 else if (n < 0) {
106 qDebug() << "Read error: " << socket_->errorString();
107 return;
108 }
109 }
110}
111
112void TestRestoreSocket::on_disconnected()
113{
114 qDebug() << "Socket disconnected";
115 auto avail = socket_->bytesAvailable();
116 while (avail > 0)
117 {
118 read_data();
119 avail = socket_->bytesAvailable();
120 }
121
122 if (file_.isOpen())
123 {
124 file_.close();
125 }
126}
127
128void TestRestoreSocket::on_data_stored(qint64 /*n*/)
129{
130 read_data();
131}
132
133void TestRestoreSocket::on_socket_received(std::shared_ptr<Downloader> const & downloader)
134{
135 socket_ = downloader->socket();
136 QObject::connect(socket_.get(), &QLocalSocket::readyRead, this, &TestRestoreSocket::read_data);
137 QObject::connect(socket_.get(), &QLocalSocket::disconnected, this, &TestRestoreSocket::on_disconnected);
138 QObject::connect(&file_, &QIODevice::bytesWritten, this, &TestRestoreSocket::on_data_stored);
139}
0140
=== added file 'src/test-restore/test-restore-socket.h'
--- src/test-restore/test-restore-socket.h 1970-01-01 00:00:00 +0000
+++ src/test-restore/test-restore-socket.h 2016-11-17 00:23:33 +0000
@@ -0,0 +1,56 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 * Xavi Garcia Mena <xavi.garcia.mena@canonical.com>
19 */
20#pragma once
21
22#include "util/connection-helper.h"
23
24#include <QObject>
25#include <QScopedPointer>
26#include <QFile>
27
28#include <memory>
29
30class QLocalSocket;
31class StorageFrameworkClient;
32class Downloader;
33
34class TestRestoreSocket : public QObject
35{
36 Q_OBJECT
37public:
38 explicit TestRestoreSocket(QObject *parent = nullptr);
39 virtual ~TestRestoreSocket();
40
41 void start(QString const & dir_name, QString const & file_name);
42
43public Q_SLOTS:
44 void read_data();
45 void on_socket_received(std::shared_ptr<Downloader> const & downloader);
46 void on_disconnected();
47 void on_data_stored(qint64 n);
48
49private:
50 std::shared_ptr<QLocalSocket> socket_;
51 QScopedPointer<StorageFrameworkClient> sf_client_;
52 ConnectionHelper connections_;
53 qint64 n_read_ = 0;
54 QFile file_;
55 QFutureWatcher<std::shared_ptr<Downloader>> future_watcher_;
56};
057
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2016-09-05 13:54:15 +0000
+++ tests/CMakeLists.txt 2016-11-17 00:23:33 +0000
@@ -20,6 +20,11 @@
20)20)
2121
22set(22set(
23 RESTORE_HELPER
24 fake-restore-helper
25)
26
27set(
23 BACKUP_HELPER_FAILURE28 BACKUP_HELPER_FAILURE
24 fake-backup-helper-failure29 fake-backup-helper-failure
25)30)
@@ -27,6 +32,7 @@
27set(KEEPER_TAR_CREATE_BIN ${CMAKE_BINARY_DIR}/src/tar/keeper-tar-create)32set(KEEPER_TAR_CREATE_BIN ${CMAKE_BINARY_DIR}/src/tar/keeper-tar-create)
28set(KEEPER_HELPER_TEST_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/helpers-test.sh)33set(KEEPER_HELPER_TEST_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/helpers-test.sh)
29set(BACKUP_HELPER_FAILURE_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/${BACKUP_HELPER_FAILURE})34set(BACKUP_HELPER_FAILURE_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/${BACKUP_HELPER_FAILURE})
35set(RESTORE_HELPER_TEST_LOCATION ${CMAKE_BINARY_DIR}/tests/fakes/${RESTORE_HELPER})
3036
31add_definitions(37add_definitions(
32 -DCMAKE_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}"38 -DCMAKE_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
3339
=== modified file 'tests/com_canonical_keeper.py'
--- tests/com_canonical_keeper.py 2016-08-03 18:38:12 +0000
+++ tests/com_canonical_keeper.py 2016-11-17 00:23:33 +0000
@@ -1,3 +1,20 @@
1# Copyright (C) 2016 Canonical, Ltd.
2#
3# This program is free software: you can redistribute it and/or modify it
4# under the terms of the GNU General Public License version 3, as published
5# by the Free Software Foundation.
6#
7# This program is distributed in the hope that it will be useful, but
8# WITHOUT ANY WARRANTY; without even the implied warranties of
9# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
10# PURPOSE. See the GNU General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License along
13# with this program. If not, see <http://www.gnu.org/licenses/>.
14#
15# Authors:
16# Charles Kerr <charles.kerr@canonical.com>
17
1import copy18import copy
2import dbus19import dbus
3import dbus.service20import dbus.service
421
=== modified file 'tests/fakes/CMakeLists.txt'
--- tests/fakes/CMakeLists.txt 2016-08-30 12:50:46 +0000
+++ tests/fakes/CMakeLists.txt 2016-11-17 00:23:33 +0000
@@ -30,6 +30,16 @@
30)30)
3131
32add_executable(32add_executable(
33 ${RESTORE_HELPER}
34 fake-restore-helper.cpp
35 restore-reader.cpp
36)
37target_link_libraries(
38 ${RESTORE_HELPER}
39 ${LINK_LIBS}
40)
41
42add_executable(
33 ${BACKUP_HELPER_FAILURE}43 ${BACKUP_HELPER_FAILURE}
34 fake-backup-helper.cpp44 fake-backup-helper.cpp
35)45)
3646
=== added file 'tests/fakes/fake-restore-helper.cpp'
--- tests/fakes/fake-restore-helper.cpp 1970-01-01 00:00:00 +0000
+++ tests/fakes/fake-restore-helper.cpp 2016-11-17 00:23:33 +0000
@@ -0,0 +1,101 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include "fake-restore-helper.h"
21#include "restore-reader.h"
22
23#include <qdbus-stubs/dbus-types.h>
24#include <qdbus-stubs/keeper_helper_interface.h>
25
26#include <QCoreApplication>
27#include <QDebug>
28#include <QDBusConnection>
29#include <QDBusInterface>
30#include <QDBusReply>
31#include <QProcessEnvironment>
32#include <QLocalSocket>
33#include <QtGlobal>
34
35#include <unistd.h>
36#include <sys/ioctl.h>
37
38void myMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & msg)
39{
40 QString txt;
41 switch (type) {
42 case QtDebugMsg:
43 txt = QString("Debug: %1").arg(msg);
44 break;
45 case QtWarningMsg:
46 txt = QString("Warning: %1").arg(msg);
47 break;
48 case QtCriticalMsg:
49 txt = QString("Critical: %1").arg(msg);
50 break;
51 case QtFatalMsg:
52 txt = QString("Fatal: %1").arg(msg);
53 abort();
54 }
55 QFile outFile("/tmp/restore-helper-output");
56 outFile.open(QIODevice::WriteOnly | QIODevice::Append);
57 QTextStream ts(&outFile);
58 ts << txt << endl;
59}
60
61int
62main(int argc, char **argv)
63{
64 QCoreApplication app(argc, argv);
65 qInstallMessageHandler(myMessageHandler);
66
67 // dump the inputs to stdout
68 qDebug() << "argc:" << argc;
69 for(int i=0; i<argc; ++i)
70 qDebug() << "argv[" << i << "] is" << argv[i];
71 const auto env = QProcessEnvironment::systemEnvironment();
72 for(const auto& key : env.keys())
73 qDebug() << "env" << qPrintable(key) << "is" << qPrintable(env.value(key));
74
75 qDebug() << "Retrieving connection";
76
77 // ask the service for a socket
78 auto conn = QDBusConnection::connectToBus(QDBusConnection::SessionBus, DBusTypes::KEEPER_SERVICE);
79 const auto object_path = QString::fromUtf8(DBusTypes::KEEPER_HELPER_PATH);
80 DBusInterfaceKeeperHelper helper_iface (DBusTypes::KEEPER_SERVICE, object_path, conn);
81
82 qDebug() << "Is valid:" << helper_iface.isValid();
83
84 auto fd_reply = helper_iface.StartRestore();
85 fd_reply.waitForFinished();
86 if (fd_reply.isError())
87 {
88 qFatal("Call to '%s.StartRestore() at '%s' call failed: %s",
89 DBusTypes::KEEPER_SERVICE,
90 qPrintable(object_path),
91 qPrintable(fd_reply.error().message())
92 );
93 }
94 const auto ufd = fd_reply.value();
95
96 // write the blob
97 const auto fd = ufd.fileDescriptor();
98 qDebug() << "The file descriptor obtained is: " << fd;
99 RestoreReader reader(fd, TEST_RESTORE_FILE_PATH);
100 return app.exec();
101}
0102
=== added file 'tests/fakes/fake-restore-helper.h'
--- tests/fakes/fake-restore-helper.h 1970-01-01 00:00:00 +0000
+++ tests/fakes/fake-restore-helper.h 2016-11-17 00:23:33 +0000
@@ -0,0 +1,26 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#pragma once
21
22namespace
23{
24static char const TEST_RESTORE_FILE_PATH[] = "/tmp/test-restore-helper";
25
26}
027
=== added file 'tests/fakes/restore-reader.cpp'
--- tests/fakes/restore-reader.cpp 1970-01-01 00:00:00 +0000
+++ tests/fakes/restore-reader.cpp 2016-11-17 00:23:33 +0000
@@ -0,0 +1,81 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Xavi Garcia <xavi.garcia.mena@canonical.com>
18 */
19
20#include "restore-reader.h"
21
22#include <QCoreApplication>
23#include <QCryptographicHash>
24
25#include <unistd.h>
26
27//static constexpr int UPLOAD_BUFFER_MAX_ {1024*16};
28constexpr int UPLOAD_BUFFER_MAX_ = 16 * 1024;
29
30RestoreReader::RestoreReader(qint64 fd, QString const & file_path, QObject * parent)
31 : QObject(parent)
32 , file_(file_path)
33{
34 socket_.setSocketDescriptor(fd);
35 connect(&socket_, &QLocalSocket::readyRead, this, &RestoreReader::read_all);
36 connect(&socket_, &QLocalSocket::disconnected, this, &RestoreReader::finish);
37 if (!file_.open(QIODevice::WriteOnly | QIODevice::Truncate))
38 {
39 qFatal("Error opening file");
40 }
41
42 read_all();
43}
44
45void RestoreReader::read_all()
46{
47 qDebug() << Q_FUNC_INFO;
48
49 for (;;)
50 {
51 auto const chunk = socket_.readAll();
52 if (chunk.isEmpty())
53 {
54 qDebug() << "Failed to read from server" << socket_.errorString();
55 break;
56 }
57
58 n_bytes_read_ += chunk.size();
59 qDebug() << Q_FUNC_INFO << "n_bytes_read is now" << n_bytes_read_ << "after reading" << chunk.size();
60 if (file_.write(chunk) == -1)
61 qDebug() << Q_FUNC_INFO << "file write failed" << file_.errorString();
62
63 // THIS IS JUST FOR EXTRA DEBUG INFORMATION
64 QCryptographicHash hash(QCryptographicHash::Sha1);
65 hash.addData(chunk.data(), 100);
66 qInfo() << "Hash: bytes total: " << n_bytes_read_ << " " << hash.result().toHex();
67 // THIS IS JUST FOR EXTRA DEBUG INFORMATION
68 }
69}
70
71void RestoreReader::finish()
72{
73 qDebug() << "Finishing";
74 read_all();
75
76 file_.flush();
77 fsync(file_.handle());
78 file_.close();
79
80 QCoreApplication::exit();
81}
082
=== added file 'tests/fakes/restore-reader.h'
--- tests/fakes/restore-reader.h 1970-01-01 00:00:00 +0000
+++ tests/fakes/restore-reader.h 2016-11-17 00:23:33 +0000
@@ -0,0 +1,43 @@
1/*
2 * Copyright (C) 2016 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Xavi Garcia <xavi.garcia.mena@canonical.com>
18 */
19
20#pragma once
21
22#include <QObject>
23#include <QFile>
24#include <QLocalSocket>
25
26class RestoreReader : public QObject
27{
28 Q_OBJECT
29public:
30 RestoreReader(qint64 fd, QString const & file_path, QObject * parent = nullptr);
31 ~RestoreReader() = default;
32
33private Q_SLOTS:
34 void read_all();
35 void finish();
36
37private:
38 void check_for_done();
39
40 QLocalSocket socket_;
41 qint64 n_bytes_read_ = 0;
42 QFile file_;
43};
044
=== modified file 'tests/integration/helpers/CMakeLists.txt'
--- tests/integration/helpers/CMakeLists.txt 2016-10-28 15:11:21 +0000
+++ tests/integration/helpers/CMakeLists.txt 2016-11-17 00:23:33 +0000
@@ -65,6 +65,10 @@
65 FOLDER_BACKUP_EXEC65 FOLDER_BACKUP_EXEC
66 ${KEEPER_HELPER_TEST_LOCATION}66 ${KEEPER_HELPER_TEST_LOCATION}
67)67)
68set(
69 FOLDER_RESTORE_EXEC
70 ${RESTORE_HELPER_TEST_LOCATION}
71)
68configure_file(72configure_file(
69 ${CMAKE_SOURCE_DIR}/data/${HELPER_REGISTRY_FILENAME}.in73 ${CMAKE_SOURCE_DIR}/data/${HELPER_REGISTRY_FILENAME}.in
70 ${HELPERS_TEST}-registry.json74 ${HELPERS_TEST}-registry.json
7175
=== modified file 'tests/integration/helpers/helpers-test.cc'
--- tests/integration/helpers/helpers-test.cc 2016-11-02 14:01:23 +0000
+++ tests/integration/helpers/helpers-test.cc 2016-11-17 00:23:33 +0000
@@ -20,6 +20,7 @@
20 */20 */
2121
22#include "test-helpers-base.h"22#include "test-helpers-base.h"
23#include "tests/fakes/fake-restore-helper.h"
2324
24class TestHelpers: public TestHelpersBase25class TestHelpers: public TestHelpersBase
25{26{
@@ -32,30 +33,31 @@
32 }33 }
33};34};
3435
35TEST_F(TestHelpers, StartHelper)36//TEST_F(TestHelpers, StartHelper)
36{37//{
37 // starts the services, including keeper-service38// // starts the services, including keeper-service
38 start_tasks();39// start_tasks();
3940//
40 BackupHelper helper("com.test.multiple_first_1.2.3");41// BackupHelper helper("com.test.multiple_first_1.2.3");
4142//
42 QSignalSpy spy(&helper, &BackupHelper::state_changed);43// QSignalSpy spy(&helper, &BackupHelper::state_changed);
4344//
44 helper.start({"/bin/ls","/tmp"});45// helper.start({"/bin/ls","/tmp"});
4546//
46 // wait for 2 signals.47// // wait for 2 signals.
47 // One for started, another one when the helper stops48// // One for started, another one when the helper stops
48 WAIT_FOR_SIGNALS(spy, 2, 15000);49// WAIT_FOR_SIGNALS(spy, 2, 15000);
4950//
50 ASSERT_EQ(spy.count(), 2);51// ASSERT_EQ(spy.count(), 2);
51 QList<QVariant> arguments = spy.takeFirst();52// QList<QVariant> arguments = spy.takeFirst();
52 EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::STARTED);53// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::STARTED);
53 arguments = spy.takeFirst();54// arguments = spy.takeFirst();
54 EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::COMPLETE);55// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::COMPLETE);
55}56//}
5657
57TEST_F(TestHelpers, StartFullTest)58TEST_F(TestHelpers, StartFullTest)
58{59{
60 system("rm -f /tmp/restore-helper-output");
59 XdgUserDirsSandbox tmp_dir;61 XdgUserDirsSandbox tmp_dir;
6062
61 // starts the services, including keeper-service63 // starts the services, including keeper-service
@@ -82,7 +84,7 @@
82 qDebug() << "USER DIR:" << user_dir;84 qDebug() << "USER DIR:" << user_dir;
8385
84 // fill something in the music dir86 // fill something in the music dir
85 FileUtils::fillTemporaryDirectory(user_dir, qrand() % 100);87 FileUtils::fillTemporaryDirectory(user_dir, qrand() % 10);
8688
87 // search for the user folder uuid89 // search for the user folder uuid
88 auto user_folder_uuid = get_uuid_for_xdg_folder_path(user_dir, choices.value());90 auto user_folder_uuid = get_uuid_for_xdg_folder_path(user_dir, choices.value());
@@ -101,7 +103,7 @@
101 qDebug() << "USER DIR 2:" << user_dir_2;103 qDebug() << "USER DIR 2:" << user_dir_2;
102104
103 // fill something in the music dir105 // fill something in the music dir
104 FileUtils::fillTemporaryDirectory(user_dir_2, qrand() % 100);106 FileUtils::fillTemporaryDirectory(user_dir_2, qrand() % 10);
105107
106 // search for the user folder uuid108 // search for the user folder uuid
107 auto user_folder_uuid_2 = get_uuid_for_xdg_folder_path(user_dir_2, choices.value());109 auto user_folder_uuid_2 = get_uuid_for_xdg_folder_path(user_dir_2, choices.value());
@@ -140,164 +142,197 @@
140142
141 // finally check that we have a valid manifest file.143 // finally check that we have a valid manifest file.
142 EXPECT_TRUE(check_manifest_file(backup_items));144 EXPECT_TRUE(check_manifest_file(backup_items));
143}145
144146 QDBusPendingReply<QVariantDictMap> restore_choices_reply = user_iface->call("GetRestoreChoices");
145TEST_F(TestHelpers, StartFullTestCancelling)147 restore_choices_reply.waitForFinished();
146{148 EXPECT_TRUE(restore_choices_reply.isValid()) << qPrintable(choices.error().message());
147 XdgUserDirsSandbox tmp_dir;149
148150 const auto restore_choices = restore_choices_reply.value();
149 // starts the services, including keeper-service151 EXPECT_EQ(2, restore_choices.size());
150 start_tasks();152
151153 // check that we have the first uuid that we did the backup
152 QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser(154 const auto iter_restore = restore_choices.find(user_folder_uuid);
153 DBusTypes::KEEPER_SERVICE,155 EXPECT_NE(iter_restore, restore_choices.end());
154 DBusTypes::KEEPER_USER_PATH,156 EXPECT_EQ(user_folder_uuid, iter_restore.key());
155 dbus_test_runner.sessionConnection()157
156 ) );158 // ask to restore that uuid
157159 QDBusPendingReply<void> restore_reply = user_iface->call("StartRestore", QStringList{iter_restore.key()});
158 ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message());160 restore_reply.waitForFinished();
159161 ASSERT_TRUE(restore_reply.isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message());
160 // ask for a list of backup choices162
161 QDBusReply<QVariantDictMap> choices = user_iface->call("GetBackupChoices");163 // waits until all tasks are complete, recording PropertiesChanged signals
162 EXPECT_TRUE(choices.isValid()) << qPrintable(choices.error().message());164 // and checks all the recorded values
163165 EXPECT_TRUE(capture_and_check_state_until_all_tasks_complete(spy, {iter_restore.key()}, "complete"));
164 QString user_option = QStringLiteral("XDG_MUSIC_DIR");166
165167 // verify that the file that the fake restore helper creates is one of the ones in storage framework
166 auto user_dir = qgetenv(user_option.toLatin1().data());168 QString storage_framework_file_path;
167 ASSERT_FALSE(user_dir.isEmpty());169 EXPECT_TRUE(StorageFrameworkLocalUtils::get_storage_frameowork_file_equal_to(TEST_RESTORE_FILE_PATH, storage_framework_file_path));
168 qDebug() << "USER DIR:" << user_dir;170
169171 // Finally check that the storage framework file that matched is the right one
170 // fill something in the music dir172 // Keeper uses the display name plus .keeper extension for the files it creates
171 FileUtils::fillTemporaryDirectory(user_dir, qrand() % 1000);173 QFileInfo sf_file_info(storage_framework_file_path);
172174 EXPECT_EQ(sf_file_info.fileName(), QStringLiteral("%1.keeper").arg(get_display_name_for_xdg_folder_path(user_dir, choices.value())));
173 // search for the user folder uuid175
174 auto user_folder_uuid = get_uuid_for_xdg_folder_path(user_dir, choices.value());176 qDebug() << "-----------------------------------------------------";
175 ASSERT_FALSE(user_folder_uuid.isEmpty());177 system("cat /tmp/restore-helper-output");
176 qDebug() << "User folder UUID is:" << user_folder_uuid;178}
177179
178 QString user_option_2 = QStringLiteral("XDG_VIDEOS_DIR");180//TEST_F(TestHelpers, StartFullTestCancelling)
179181//{
180 auto user_dir_2 = qgetenv(user_option_2.toLatin1().data());182// XdgUserDirsSandbox tmp_dir;
181 ASSERT_FALSE(user_dir_2.isEmpty());183//
182 qDebug() << "USER DIR 2:" << user_dir_2;184// // starts the services, including keeper-service
183185// start_tasks();
184 // fill something in the music dir186//
185 FileUtils::fillTemporaryDirectory(user_dir_2, qrand() % 1000);187// QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser(
186188// DBusTypes::KEEPER_SERVICE,
187 // search for the user folder uuid189// DBusTypes::KEEPER_USER_PATH,
188 auto user_folder_uuid_2 = get_uuid_for_xdg_folder_path(user_dir_2, choices.value());190// dbus_test_runner.sessionConnection()
189 ASSERT_FALSE(user_folder_uuid_2.isEmpty());191// ) );
190 qDebug() << "User folder 2 UUID is:" << user_folder_uuid_2;192//
191193// ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message());
192 QSharedPointer<DBusPropertiesInterface> properties_interface(new DBusPropertiesInterface(194//
193 DBusTypes::KEEPER_SERVICE,195// // ask for a list of backup choices
194 DBusTypes::KEEPER_USER_PATH,196// QDBusReply<QVariantDictMap> choices = user_iface->call("GetBackupChoices");
195 dbus_test_runner.sessionConnection()197// EXPECT_TRUE(choices.isValid()) << qPrintable(choices.error().message());
196 ) );198//
197199// QString user_option = QStringLiteral("XDG_MUSIC_DIR");
198 ASSERT_TRUE(properties_interface->isValid()) << qPrintable(QDBusConnection::sessionBus().lastError().message());200//
199201// auto user_dir = qgetenv(user_option.toLatin1().data());
200 QSignalSpy spy(properties_interface.data(),&DBusPropertiesInterface::PropertiesChanged);202// ASSERT_FALSE(user_dir.isEmpty());
201203// qDebug() << "USER DIR:" << user_dir;
202 // Now we know the music folder uuid, let's start the backup for it.204//
203 QDBusReply<void> backup_reply = user_iface->call("StartBackup", QStringList{user_folder_uuid, user_folder_uuid_2});205// // fill something in the music dir
204 ASSERT_TRUE(backup_reply.isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message());206// FileUtils::fillTemporaryDirectory(user_dir, qrand() % 1000);
205207//
206 EXPECT_TRUE(cancel_first_task_at_percentage(spy, 0.05, user_iface));208// // search for the user folder uuid
207209// auto user_folder_uuid = get_uuid_for_xdg_folder_path(user_dir, choices.value());
208 // wait until all the tasks have the action state "complete"210// ASSERT_FALSE(user_folder_uuid.isEmpty());
209 // this one uses pooling so it should just call Get once211// qDebug() << "User folder UUID is:" << user_folder_uuid;
210 EXPECT_TRUE(wait_for_all_tasks_have_action_state({user_folder_uuid, user_folder_uuid_2}, "cancelled", user_iface));212//
211213// QString user_option_2 = QStringLiteral("XDG_VIDEOS_DIR");
212 // check that we have no files in storage framework214//
213 EXPECT_EQ(0, StorageFrameworkLocalUtils::check_storage_framework_nb_files());215// auto user_dir_2 = qgetenv(user_option_2.toLatin1().data());
214}216// ASSERT_FALSE(user_dir_2.isEmpty());
215217// qDebug() << "USER DIR 2:" << user_dir_2;
216TEST_F(TestHelpers, CheckBadUUIDS)218//
217{219// // fill something in the music dir
218 XdgUserDirsSandbox tmp_dir;220// FileUtils::fillTemporaryDirectory(user_dir_2, qrand() % 1000);
219221//
220 // starts the services, including keeper-service222// // search for the user folder uuid
221 start_tasks();223// auto user_folder_uuid_2 = get_uuid_for_xdg_folder_path(user_dir_2, choices.value());
222224// ASSERT_FALSE(user_folder_uuid_2.isEmpty());
223 QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser(225// qDebug() << "User folder 2 UUID is:" << user_folder_uuid_2;
224 DBusTypes::KEEPER_SERVICE,226//
225 DBusTypes::KEEPER_USER_PATH,227// QSharedPointer<DBusPropertiesInterface> properties_interface(new DBusPropertiesInterface(
226 dbus_test_runner.sessionConnection()228// DBusTypes::KEEPER_SERVICE,
227 ) );229// DBusTypes::KEEPER_USER_PATH,
228230// dbus_test_runner.sessionConnection()
229 ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message());231// ) );
230232//
231 // Now we know the music folder uuid, let's start the backup for it.233// ASSERT_TRUE(properties_interface->isValid()) << qPrintable(QDBusConnection::sessionBus().lastError().message());
232 QDBusReply<void> backup_reply = user_iface->call("StartBackup", QStringList{"bad_uuid_1", "bad_uuid_2"});234//
233235// QSignalSpy spy(properties_interface.data(),&DBusPropertiesInterface::PropertiesChanged);
234 ASSERT_FALSE(backup_reply.isValid());236//
235237// // Now we know the music folder uuid, let's start the backup for it.
236 // check the error message238// QDBusReply<void> backup_reply = user_iface->call("StartBackup", QStringList{user_folder_uuid, user_folder_uuid_2});
237 // the uuids are not printed always in the same order239// ASSERT_TRUE(backup_reply.isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message());
238 QString error_message = dbus_test_runner.sessionConnection().lastError().message();240//
239 EXPECT_TRUE(error_message.startsWith("unhandled uuids: "));241// EXPECT_TRUE(cancel_first_task_at_percentage(spy, 0.05, user_iface));
240 EXPECT_TRUE(error_message.contains("bad_uuid_1"));242//
241 EXPECT_TRUE(error_message.contains("bad_uuid_2"));243// // wait until all the tasks have the action state "complete"
242}244// // this one uses pooling so it should just call Get once
243245// EXPECT_TRUE(wait_for_all_tasks_have_action_state({user_folder_uuid, user_folder_uuid_2}, "cancelled", user_iface));
244TEST_F(TestHelpers, SimplyCheckThatTheSecondDBusInterfaceIsFine)246//
245{247// // check that we have no files in storage framework
246 XdgUserDirsSandbox tmp_dir;248// EXPECT_EQ(0, StorageFrameworkLocalUtils::check_storage_framework_nb_files());
247249//}
248 // starts the services, including keeper-service250//
249 start_tasks();251//TEST_F(TestHelpers, CheckBadUUIDS)
250252//{
251 QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser(253// XdgUserDirsSandbox tmp_dir;
252 DBusTypes::KEEPER_SERVICE,254//
253 DBusTypes::KEEPER_USER_PATH,255// // starts the services, including keeper-service
254 dbus_test_runner.sessionConnection()256// start_tasks();
255 ) );257//
256258// QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser(
257 ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message());259// DBusTypes::KEEPER_SERVICE,
258260// DBusTypes::KEEPER_USER_PATH,
259}261// dbus_test_runner.sessionConnection()
260262// ) );
261TEST_F(TestHelpers, BadHelperPath)263//
262{264// ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message());
263 // starts the services, including keeper-service265//
264 start_tasks();266// // Now we know the music folder uuid, let's start the backup for it.
265267// QDBusReply<void> backup_reply = user_iface->call("StartBackup", QStringList{"bad_uuid_1", "bad_uuid_2"});
266 BackupHelper helper("com.bar_foo_8432.13.1");268//
267269// ASSERT_FALSE(backup_reply.isValid());
268 QSignalSpy spy(&helper, &BackupHelper::state_changed);270//
269 QStringList urls;271// // check the error message
270 urls << "blah" << "/tmp";272// // the uuids are not printed always in the same order
271 helper.start(urls);273// QString error_message = dbus_test_runner.sessionConnection().lastError().message();
272274// EXPECT_TRUE(error_message.startsWith("unhandled uuids: "));
273 WAIT_FOR_SIGNALS(spy, 1, Helper::MAX_UAL_WAIT_TIME + 1000);275// EXPECT_TRUE(error_message.contains("bad_uuid_1"));
274276// EXPECT_TRUE(error_message.contains("bad_uuid_2"));
275 ASSERT_EQ(spy.count(), 1);277//}
276 QList<QVariant> arguments = spy.takeFirst();278//
277 EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::FAILED);279//TEST_F(TestHelpers, SimplyCheckThatTheSecondDBusInterfaceIsFine)
278}280//{
279281// XdgUserDirsSandbox tmp_dir;
280TEST_F(TestHelpers, Inactivity)282//
281{283// // starts the services, including keeper-service
282 // starts the services, including keeper-service284// start_tasks();
283 start_tasks();285//
284286// QSharedPointer<DBusInterfaceKeeperUser> user_iface(new DBusInterfaceKeeperUser(
285 BackupHelper helper("com.bar_foo_8432.13.1");287// DBusTypes::KEEPER_SERVICE,
286288// DBusTypes::KEEPER_USER_PATH,
287 QSignalSpy spy(&helper, &BackupHelper::state_changed);289// dbus_test_runner.sessionConnection()
288 QStringList urls;290// ) );
289 urls << TEST_INACTIVE_HELPER << "/tmp";291//
290 helper.start(urls);292// ASSERT_TRUE(user_iface->isValid()) << qPrintable(dbus_test_runner.sessionConnection().lastError().message());
291293//
292 // wait 15 seconds at most.294//}
293 // the inactive helper sleeps for 100 seconds so295//
294 // if we get the 2 signals it means it was stopped due to inactivity296//TEST_F(TestHelpers, BadHelperPath)
295 // We can also check at the end for the state, which should be CANCELLED297//{
296 WAIT_FOR_SIGNALS(spy, 2, BackupHelper::MAX_INACTIVITY_TIME + 2000);298// // starts the services, including keeper-service
297299// start_tasks();
298 ASSERT_EQ(spy.count(), 2);300//
299 QList<QVariant> arguments = spy.takeFirst();301// BackupHelper helper("com.bar_foo_8432.13.1");
300 EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::STARTED);302//
301 arguments = spy.takeFirst();303// QSignalSpy spy(&helper, &BackupHelper::state_changed);
302 EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::CANCELLED);304// QStringList urls;
303}305// urls << "blah" << "/tmp";
306// helper.start(urls);
307//
308// WAIT_FOR_SIGNALS(spy, 1, Helper::MAX_UAL_WAIT_TIME + 1000);
309//
310// ASSERT_EQ(spy.count(), 1);
311// QList<QVariant> arguments = spy.takeFirst();
312// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::FAILED);
313//}
314//
315//TEST_F(TestHelpers, Inactivity)
316//{
317// // starts the services, including keeper-service
318// start_tasks();
319//
320// BackupHelper helper("com.bar_foo_8432.13.1");
321//
322// QSignalSpy spy(&helper, &BackupHelper::state_changed);
323// QStringList urls;
324// urls << TEST_INACTIVE_HELPER << "/tmp";
325// helper.start(urls);
326//
327// // wait 15 seconds at most.
328// // the inactive helper sleeps for 100 seconds so
329// // if we get the 2 signals it means it was stopped due to inactivity
330// // We can also check at the end for the state, which should be CANCELLED
331// WAIT_FOR_SIGNALS(spy, 2, BackupHelper::MAX_INACTIVITY_TIME + 2000);
332//
333// ASSERT_EQ(spy.count(), 2);
334// QList<QVariant> arguments = spy.takeFirst();
335// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::STARTED);
336// arguments = spy.takeFirst();
337// EXPECT_EQ(qvariant_cast<Helper::State>(arguments.at(0)), Helper::State::CANCELLED);
338//}
304339
=== modified file 'tests/integration/helpers/test-helpers-base.cpp'
--- tests/integration/helpers/test-helpers-base.cpp 2016-11-03 08:58:51 +0000
+++ tests/integration/helpers/test-helpers-base.cpp 2016-11-17 00:23:33 +0000
@@ -179,15 +179,19 @@
179 {179 {
180 return previous == "saving" || previous == "queued";180 return previous == "saving" || previous == "queued";
181 }181 }
182 else if (current == "restoring")
183 {
184 return previous == "restoring" || previous == "queued";
185 }
182 else if (current == "finishing")186 else if (current == "finishing")
183 {187 {
184 return previous == "finishing" || previous == "saving";188 return previous == "finishing" || previous == "saving" || previous == "restoring";
185 }189 }
186 else if (current == "complete")190 else if (current == "complete")
187 {191 {
188 // we may pass from "saving" to "complete" if we don't have enough time192 // we may pass from "saving" to "complete" if we don't have enough time
189 // to emit the "finishing" state change193 // to emit the "finishing" state change
190 return previous == "complete" || previous == "finishing" || previous == "saving";194 return previous == "complete" || previous == "finishing" || previous == "saving" || previous == "restoring";
191 }195 }
192 else if (current == "failed")196 else if (current == "failed")
193 {197 {
@@ -704,7 +708,7 @@
704 return false;708 return false;
705 }709 }
706710
707 QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient);711 QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient, [](StorageFrameworkClient* sf){sf->deleteLater();});
708 Manifest manifest_read(sf_client, dir_name);712 Manifest manifest_read(sf_client, dir_name);
709 QSignalSpy spy_read(&manifest_read, &Manifest::finished);713 QSignalSpy spy_read(&manifest_read, &Manifest::finished);
710714
@@ -716,6 +720,7 @@
716 if (!spy_read.count())720 if (!spy_read.count())
717 {721 {
718 qWarning() << "Failed reading manifest file";722 qWarning() << "Failed reading manifest file";
723 sf_client.reset();
719 return false;724 return false;
720 }725 }
721726
722727
=== modified file 'tests/unit/manifest/manifest-test.cpp'
--- tests/unit/manifest/manifest-test.cpp 2016-10-06 14:53:44 +0000
+++ tests/unit/manifest/manifest-test.cpp 2016-11-17 00:23:33 +0000
@@ -78,7 +78,7 @@
7878
79 g_setenv("XDG_DATA_HOME", tmp_dir.path().toLatin1().data(), true);79 g_setenv("XDG_DATA_HOME", tmp_dir.path().toLatin1().data(), true);
8080
81 QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient);81 QSharedPointer<StorageFrameworkClient> sf_client(new StorageFrameworkClient, [](StorageFrameworkClient* sf){sf->deleteLater();});
82 Manifest manifest(sf_client, test_dir);82 Manifest manifest(sf_client, test_dir);
8383
84 auto objects_to_test = 10;84 auto objects_to_test = 10;
8585
=== modified file 'tests/unit/storage-framework/create-uploader-test.cpp'
--- tests/unit/storage-framework/create-uploader-test.cpp 2016-11-02 11:31:09 +0000
+++ tests/unit/storage-framework/create-uploader-test.cpp 2016-11-17 00:23:33 +0000
@@ -86,7 +86,7 @@
86 // create a downloader86 // create a downloader
87 auto downloader_fut = sf_client.get_new_downloader(test_dir, test_file_name);87 auto downloader_fut = sf_client.get_new_downloader(test_dir, test_file_name);
88 {88 {
89 QFutureWatcher<sf::Downloader::SPtr> w;89 QFutureWatcher<std::shared_ptr<Downloader>> w;
90 QSignalSpy spy(&w, &decltype(w)::finished);90 QSignalSpy spy(&w, &decltype(w)::finished);
91 w.setFuture(downloader_fut);91 w.setFuture(downloader_fut);
92 assert(spy.wait());92 assert(spy.wait());
@@ -107,14 +107,13 @@
107107
108 EXPECT_EQ(downloader_content, test_content);108 EXPECT_EQ(downloader_content, test_content);
109109
110 auto finish_downloader_fut = downloader->finish_download();110 QSignalSpy spy_downloader(downloader.get(), &Downloader::download_finished);
111 downloader->finish();
112 if (!spy_downloader.count())
111 {113 {
112 QFutureWatcher<void> w;114 spy_downloader.wait();
113 QSignalSpy spy(&w, &decltype(w)::finished);
114 w.setFuture(finish_downloader_fut);
115 assert(spy.wait());
116 ASSERT_EQ(spy.count(), 1);
117 }115 }
116 EXPECT_EQ(1, spy_downloader.count());
118117
119 // get another uploader118 // get another uploader
120 QString test_file_name_2 = QStringLiteral("test_file2");119 QString test_file_name_2 = QStringLiteral("test_file2");
121120
=== modified file 'tests/utils/file-utils.cpp'
--- tests/utils/file-utils.cpp 2016-11-02 10:43:30 +0000
+++ tests/utils/file-utils.cpp 2016-11-17 00:23:33 +0000
@@ -198,8 +198,10 @@
198 qWarning() << "File to compare:" << info2.absoluteFilePath() << "does not exist";198 qWarning() << "File to compare:" << info2.absoluteFilePath() << "does not exist";
199 return false;199 return false;
200 }200 }
201 qDebug() << "File 1 size: " << info1.size() << info1.absoluteFilePath();
202 qDebug() << "File 2 size: " << info2.size() << info2.absoluteFilePath();
201 auto checksum1 = calculate_checksum(filePath1, QCryptographicHash::Md5);203 auto checksum1 = calculate_checksum(filePath1, QCryptographicHash::Md5);
202 auto checksum2 = calculate_checksum(filePath1, QCryptographicHash::Md5);204 auto checksum2 = calculate_checksum(filePath2, QCryptographicHash::Md5);
203 if (checksum1 != checksum2)205 if (checksum1 != checksum2)
204 {206 {
205 qWarning() << "Checksum for file:" << filePath1 << "differ";207 qWarning() << "Checksum for file:" << filePath1 << "differ";
206208
=== modified file 'tests/utils/storage-framework-local.cpp'
--- tests/utils/storage-framework-local.cpp 2016-10-28 15:11:21 +0000
+++ tests/utils/storage-framework-local.cpp 2016-11-17 00:23:33 +0000
@@ -170,4 +170,38 @@
170 : "";170 : "";
171}171}
172172
173bool get_storage_frameowork_file_equal_to(QString const & file_path, QString & path)
174{
175 auto const backups = get_storage_framework_files();
176 for (auto const& backup : backups)
177 {
178 auto const backup_filename = backup.absoluteFilePath();
179 if (FileUtils::compareFiles(file_path, backup_filename))
180 {
181 path = backup_filename;
182 return true;
183 }
184 }
185 return false;
186}
187
188bool get_storage_frameowork_file_equal_in_size_to(QString const & file_path, QString & path)
189{
190 auto const backups = get_storage_framework_files();
191 for (auto const& backup : backups)
192 {
193 auto const backup_filename = backup.absoluteFilePath();
194 QFileInfo info1(backup_filename);
195 QFileInfo info2(file_path);
196 qDebug() << "File 1 size = " << info1.size();
197 qDebug() << "File 2 size = " << info2.size();
198 if (info1.size() == info2.size())
199 {
200 path = backup_filename;
201 return true;
202 }
203 }
204 return false;
205}
206
173} // namespace StorageFrameworkLocalUtils207} // namespace StorageFrameworkLocalUtils
174208
=== modified file 'tests/utils/storage-framework-local.h'
--- tests/utils/storage-framework-local.h 2016-10-28 15:11:21 +0000
+++ tests/utils/storage-framework-local.h 2016-11-17 00:23:33 +0000
@@ -41,4 +41,8 @@
41 QFileInfoList get_storage_framework_files();41 QFileInfoList get_storage_framework_files();
4242
43 QString get_storage_framework_dir_name();43 QString get_storage_framework_dir_name();
44
45 bool get_storage_frameowork_file_equal_to(QString const & file_path, QString & path);
46
47 bool get_storage_frameowork_file_equal_in_size_to(QString const & file_path, QString & path);
44}48}

Subscribers

People subscribed via source and target branches

to all changes: