Merge lp:~michihenning/storage-framework/more-coverage into lp:storage-framework/devel
- more-coverage
- Merge into devel
Status: | Superseded |
---|---|
Proposed branch: | lp:~michihenning/storage-framework/more-coverage |
Merge into: | lp:storage-framework/devel |
Diff against target: |
5240 lines (+2562/-575) (has conflicts) 41 files modified
include/unity/storage/qt/client/Account.h (+1/-1) include/unity/storage/qt/client/Exceptions.h (+8/-1) include/unity/storage/qt/client/Item.h (+1/-1) include/unity/storage/qt/client/Root.h (+1/-1) include/unity/storage/qt/client/Runtime.h (+2/-0) include/unity/storage/qt/client/internal/AccountBase.h (+1/-1) include/unity/storage/qt/client/internal/ItemBase.h (+3/-1) include/unity/storage/qt/client/internal/RootBase.h (+1/-1) include/unity/storage/qt/client/internal/RuntimeBase.h (+7/-4) include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h (+2/-1) include/unity/storage/qt/client/internal/local_client/FolderImpl.h (+1/-0) include/unity/storage/qt/client/internal/local_client/ItemImpl.h (+4/-4) include/unity/storage/qt/client/internal/local_client/UploaderImpl.h (+2/-2) include/unity/storage/qt/client/internal/make_future.h (+59/-0) include/unity/storage/qt/client/internal/remote_client/Handler.h (+2/-3) include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h (+1/-1) src/qt/client/Account.cpp (+1/-1) src/qt/client/Exceptions.cpp (+12/-1) src/qt/client/Item.cpp (+1/-1) src/qt/client/Root.cpp (+2/-1) src/qt/client/internal/AccountBase.cpp (+10/-3) src/qt/client/internal/ItemBase.cpp (+24/-4) src/qt/client/internal/RootBase.cpp (+11/-2) src/qt/client/internal/RuntimeBase.cpp (+0/-5) src/qt/client/internal/local_client/AccountImpl.cpp (+16/-3) src/qt/client/internal/local_client/DownloaderImpl.cpp (+18/-8) src/qt/client/internal/local_client/FileImpl.cpp (+28/-5) src/qt/client/internal/local_client/FolderImpl.cpp (+123/-25) src/qt/client/internal/local_client/ItemImpl.cpp (+174/-96) src/qt/client/internal/local_client/RootImpl.cpp (+87/-15) src/qt/client/internal/local_client/RuntimeImpl.cpp (+6/-1) src/qt/client/internal/local_client/UploaderImpl.cpp (+19/-22) src/qt/client/internal/remote_client/AccountImpl.cpp (+13/-0) src/qt/client/internal/remote_client/FileImpl.cpp (+22/-10) src/qt/client/internal/remote_client/FolderImpl.cpp (+17/-13) src/qt/client/internal/remote_client/ItemImpl.cpp (+39/-11) src/qt/client/internal/remote_client/RootImpl.cpp (+33/-8) src/qt/client/internal/remote_client/RuntimeImpl.cpp (+14/-3) src/qt/client/internal/remote_client/UploaderImpl.cpp (+3/-10) tests/local-client/local-client_test.cpp (+1782/-294) tests/remote-client/remote-client_test.cpp (+11/-11) Text conflict in tests/local-client/local-client_test.cpp |
To merge this branch: | bzr merge lp:~michihenning/storage-framework/more-coverage |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
unity-api-1-bot | continuous-integration | Needs Fixing | |
Unity API Team | Pending | ||
Review via email: mp+301448@code.launchpad.net |
This proposal has been superseded by a proposal from 2016-07-29.
Commit message
Improved coverage. Better error reporting/handling.
Description of the change
Very boring branch. Lots of extra tests for proper coverage, particularly for error handling/reporting.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
- 72. By Michi Henning
-
Removed dependency on boost from remote client for exception handling.
Refactored exception handling logic and fixed tests to look for the correct exception. - 73. By Michi Henning
-
More refactoring for error handling.
- 74. By Michi Henning
-
More refactoring to get rid of repeated exception handlers.
- 75. By Michi Henning
-
Removed stale code, fixed spy usage in tests.
- 76. By Michi Henning
-
A few coverage suppressions.
- 77. By Michi Henning
-
Fixed hang in test. Fixed sigpipe problem when cancelling upload.
- 78. By Michi Henning
-
Added a few missing checks for destroyed runtime or item.
- 79. By Michi Henning
-
Fixed incorrect check for parent destruction in copy() and move().
- 80. By Michi Henning
-
Fix typos.
Unmerged revisions
Preview Diff
1 | === modified file 'include/unity/storage/qt/client/Account.h' | |||
2 | --- include/unity/storage/qt/client/Account.h 2016-07-22 02:35:12 +0000 | |||
3 | +++ include/unity/storage/qt/client/Account.h 2016-07-29 05:58:49 +0000 | |||
4 | @@ -77,7 +77,7 @@ | |||
5 | 77 | 77 | ||
6 | 78 | typedef std::shared_ptr<Account> SPtr; | 78 | typedef std::shared_ptr<Account> SPtr; |
7 | 79 | 79 | ||
9 | 80 | Runtime* runtime() const; | 80 | std::shared_ptr<Runtime> runtime() const; |
10 | 81 | 81 | ||
11 | 82 | QString owner() const; | 82 | QString owner() const; |
12 | 83 | QString owner_id() const; | 83 | QString owner_id() const; |
13 | 84 | 84 | ||
14 | === modified file 'include/unity/storage/qt/client/Exceptions.h' | |||
15 | --- include/unity/storage/qt/client/Exceptions.h 2016-07-22 02:35:12 +0000 | |||
16 | +++ include/unity/storage/qt/client/Exceptions.h 2016-07-29 05:58:49 +0000 | |||
17 | @@ -46,6 +46,8 @@ | |||
18 | 46 | 46 | ||
19 | 47 | virtual char const* what() const noexcept override; | 47 | virtual char const* what() const noexcept override; |
20 | 48 | 48 | ||
21 | 49 | QString error_message() const; | ||
22 | 50 | |||
23 | 49 | private: | 51 | private: |
24 | 50 | std::string what_string_; | 52 | std::string what_string_; |
25 | 51 | QString error_message_; | 53 | QString error_message_; |
26 | @@ -234,11 +236,16 @@ | |||
27 | 234 | class UNITY_STORAGE_EXPORT ResourceException : public StorageException | 236 | class UNITY_STORAGE_EXPORT ResourceException : public StorageException |
28 | 235 | { | 237 | { |
29 | 236 | public: | 238 | public: |
31 | 237 | ResourceException(QString const& error_message); | 239 | ResourceException(QString const& error_message, int error_code); |
32 | 238 | ~ResourceException(); | 240 | ~ResourceException(); |
33 | 239 | 241 | ||
34 | 240 | virtual ResourceException* clone() const override; | 242 | virtual ResourceException* clone() const override; |
35 | 241 | virtual void raise() const override; | 243 | virtual void raise() const override; |
36 | 244 | |||
37 | 245 | int error_code() const noexcept; | ||
38 | 246 | |||
39 | 247 | private: | ||
40 | 248 | int error_code_; | ||
41 | 242 | }; | 249 | }; |
42 | 243 | 250 | ||
43 | 244 | } // namespace client | 251 | } // namespace client |
44 | 245 | 252 | ||
45 | === modified file 'include/unity/storage/qt/client/Item.h' | |||
46 | --- include/unity/storage/qt/client/Item.h 2016-07-22 02:45:24 +0000 | |||
47 | +++ include/unity/storage/qt/client/Item.h 2016-07-29 05:58:49 +0000 | |||
48 | @@ -103,7 +103,7 @@ | |||
49 | 103 | 103 | ||
50 | 104 | If this item is a root, the returned pointer points at this item. | 104 | If this item is a root, the returned pointer points at this item. |
51 | 105 | */ | 105 | */ |
53 | 106 | Root* root() const; | 106 | std::shared_ptr<Root> root() const; |
54 | 107 | 107 | ||
55 | 108 | /** | 108 | /** |
56 | 109 | \brief Returns the type of the item. | 109 | \brief Returns the type of the item. |
57 | 110 | 110 | ||
58 | === modified file 'include/unity/storage/qt/client/Root.h' | |||
59 | --- include/unity/storage/qt/client/Root.h 2016-07-12 02:22:05 +0000 | |||
60 | +++ include/unity/storage/qt/client/Root.h 2016-07-29 05:58:49 +0000 | |||
61 | @@ -70,7 +70,7 @@ | |||
62 | 70 | /** | 70 | /** |
63 | 71 | \brief Returns the account for this root. | 71 | \brief Returns the account for this root. |
64 | 72 | */ | 72 | */ |
66 | 73 | Account* account() const; | 73 | std::shared_ptr<Account> account() const; |
67 | 74 | 74 | ||
68 | 75 | QFuture<int64_t> free_space_bytes() const; | 75 | QFuture<int64_t> free_space_bytes() const; |
69 | 76 | QFuture<int64_t> used_space_bytes() const; | 76 | QFuture<int64_t> used_space_bytes() const; |
70 | 77 | 77 | ||
71 | === modified file 'include/unity/storage/qt/client/Runtime.h' | |||
72 | --- include/unity/storage/qt/client/Runtime.h 2016-07-22 02:35:12 +0000 | |||
73 | +++ include/unity/storage/qt/client/Runtime.h 2016-07-29 05:58:49 +0000 | |||
74 | @@ -44,6 +44,7 @@ | |||
75 | 44 | namespace internal | 44 | namespace internal |
76 | 45 | { | 45 | { |
77 | 46 | 46 | ||
78 | 47 | class AccountBase; | ||
79 | 47 | class RuntimeBase; | 48 | class RuntimeBase; |
80 | 48 | 49 | ||
81 | 49 | namespace remote_client | 50 | namespace remote_client |
82 | @@ -100,6 +101,7 @@ | |||
83 | 100 | 101 | ||
84 | 101 | std::shared_ptr<internal::RuntimeBase> p_; | 102 | std::shared_ptr<internal::RuntimeBase> p_; |
85 | 102 | 103 | ||
86 | 104 | friend class internal::AccountBase; | ||
87 | 103 | friend class internal::remote_client::AccountImpl; | 105 | friend class internal::remote_client::AccountImpl; |
88 | 104 | }; | 106 | }; |
89 | 105 | 107 | ||
90 | 106 | 108 | ||
91 | === modified file 'include/unity/storage/qt/client/internal/AccountBase.h' | |||
92 | --- include/unity/storage/qt/client/internal/AccountBase.h 2016-07-22 02:35:12 +0000 | |||
93 | +++ include/unity/storage/qt/client/internal/AccountBase.h 2016-07-29 05:58:49 +0000 | |||
94 | @@ -52,7 +52,7 @@ | |||
95 | 52 | AccountBase(AccountBase const&) = delete; | 52 | AccountBase(AccountBase const&) = delete; |
96 | 53 | AccountBase& operator=(AccountBase const&) = delete; | 53 | AccountBase& operator=(AccountBase const&) = delete; |
97 | 54 | 54 | ||
99 | 55 | Runtime* runtime() const; | 55 | std::shared_ptr<Runtime> runtime() const; |
100 | 56 | virtual QString owner() const = 0; | 56 | virtual QString owner() const = 0; |
101 | 57 | virtual QString owner_id() const = 0; | 57 | virtual QString owner_id() const = 0; |
102 | 58 | virtual QString description() const = 0; | 58 | virtual QString description() const = 0; |
103 | 59 | 59 | ||
104 | === modified file 'include/unity/storage/qt/client/internal/ItemBase.h' | |||
105 | --- include/unity/storage/qt/client/internal/ItemBase.h 2016-07-27 02:19:17 +0000 | |||
106 | +++ include/unity/storage/qt/client/internal/ItemBase.h 2016-07-29 05:58:49 +0000 | |||
107 | @@ -60,7 +60,7 @@ | |||
108 | 60 | 60 | ||
109 | 61 | QString native_identity() const; | 61 | QString native_identity() const; |
110 | 62 | ItemType type() const; | 62 | ItemType type() const; |
112 | 63 | Root* root() const; | 63 | std::shared_ptr<Root> root() const; |
113 | 64 | 64 | ||
114 | 65 | virtual QString name() const = 0; | 65 | virtual QString name() const = 0; |
115 | 66 | virtual QString etag() const = 0; | 66 | virtual QString etag() const = 0; |
116 | @@ -82,6 +82,8 @@ | |||
117 | 82 | void set_public_instance(std::weak_ptr<Item> p); | 82 | void set_public_instance(std::weak_ptr<Item> p); |
118 | 83 | 83 | ||
119 | 84 | protected: | 84 | protected: |
120 | 85 | std::shared_ptr<Root> get_root() const noexcept; | ||
121 | 86 | |||
122 | 85 | const QString identity_; | 87 | const QString identity_; |
123 | 86 | const ItemType type_; | 88 | const ItemType type_; |
124 | 87 | std::weak_ptr<Root> root_; | 89 | std::weak_ptr<Root> root_; |
125 | 88 | 90 | ||
126 | === modified file 'include/unity/storage/qt/client/internal/RootBase.h' | |||
127 | --- include/unity/storage/qt/client/internal/RootBase.h 2016-07-12 02:22:05 +0000 | |||
128 | +++ include/unity/storage/qt/client/internal/RootBase.h 2016-07-29 05:58:49 +0000 | |||
129 | @@ -46,7 +46,7 @@ | |||
130 | 46 | public: | 46 | public: |
131 | 47 | RootBase(QString const& identity, std::weak_ptr<Account> const& account); | 47 | RootBase(QString const& identity, std::weak_ptr<Account> const& account); |
132 | 48 | 48 | ||
134 | 49 | Account* account() const; | 49 | std::shared_ptr<Account> account() const; |
135 | 50 | virtual QFuture<int64_t> free_space_bytes() const = 0; | 50 | virtual QFuture<int64_t> free_space_bytes() const = 0; |
136 | 51 | virtual QFuture<int64_t> used_space_bytes() const = 0; | 51 | virtual QFuture<int64_t> used_space_bytes() const = 0; |
137 | 52 | virtual QFuture<Item::SPtr> get(QString native_identity) const = 0; | 52 | virtual QFuture<Item::SPtr> get(QString native_identity) const = 0; |
138 | 53 | 53 | ||
139 | === modified file 'include/unity/storage/qt/client/internal/RuntimeBase.h' | |||
140 | --- include/unity/storage/qt/client/internal/RuntimeBase.h 2016-07-22 02:35:12 +0000 | |||
141 | +++ include/unity/storage/qt/client/internal/RuntimeBase.h 2016-07-29 05:58:49 +0000 | |||
142 | @@ -25,7 +25,6 @@ | |||
143 | 25 | #pragma GCC diagnostic pop | 25 | #pragma GCC diagnostic pop |
144 | 26 | #include <QVector> | 26 | #include <QVector> |
145 | 27 | 27 | ||
146 | 28 | #include <atomic> | ||
147 | 29 | #include <memory> | 28 | #include <memory> |
148 | 30 | 29 | ||
149 | 31 | namespace unity | 30 | namespace unity |
150 | @@ -43,10 +42,12 @@ | |||
151 | 43 | namespace internal | 42 | namespace internal |
152 | 44 | { | 43 | { |
153 | 45 | 44 | ||
154 | 45 | class AccountBase; | ||
155 | 46 | |||
156 | 46 | class RuntimeBase : public QObject | 47 | class RuntimeBase : public QObject |
157 | 47 | { | 48 | { |
158 | 48 | public: | 49 | public: |
160 | 49 | RuntimeBase(); | 50 | RuntimeBase() = default; |
161 | 50 | virtual ~RuntimeBase() = default; | 51 | virtual ~RuntimeBase() = default; |
162 | 51 | RuntimeBase(RuntimeBase const&) = delete; | 52 | RuntimeBase(RuntimeBase const&) = delete; |
163 | 52 | RuntimeBase& operator=(RuntimeBase const&) = delete; | 53 | RuntimeBase& operator=(RuntimeBase const&) = delete; |
164 | @@ -57,9 +58,11 @@ | |||
165 | 57 | void set_public_instance(std::weak_ptr<Runtime> p); | 58 | void set_public_instance(std::weak_ptr<Runtime> p); |
166 | 58 | 59 | ||
167 | 59 | protected: | 60 | protected: |
170 | 60 | std::atomic_bool destroyed_; | 61 | bool destroyed_ = false; |
171 | 61 | QVector<std::shared_ptr<Account>> accounts_; // Immutable once set | 62 | QVector<std::shared_ptr<Account>> accounts_; |
172 | 62 | std::weak_ptr<Runtime> public_instance_; // Immutable once set | 63 | std::weak_ptr<Runtime> public_instance_; // Immutable once set |
173 | 64 | |||
174 | 65 | friend class unity::storage::qt::client::internal::AccountBase; | ||
175 | 63 | }; | 66 | }; |
176 | 64 | 67 | ||
177 | 65 | } // namespace internal | 68 | } // namespace internal |
178 | 66 | 69 | ||
179 | === modified file 'include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h' | |||
180 | --- include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h 2016-07-14 04:50:36 +0000 | |||
181 | +++ include/unity/storage/qt/client/internal/local_client/DownloaderImpl.h 2016-07-29 05:58:49 +0000 | |||
182 | @@ -60,7 +60,7 @@ | |||
183 | 60 | 60 | ||
184 | 61 | private: | 61 | private: |
185 | 62 | void read_and_write_chunk(); | 62 | void read_and_write_chunk(); |
187 | 63 | void handle_error(QString const& msg); | 63 | void handle_error(QString const& msg, int error_code); |
188 | 64 | 64 | ||
189 | 65 | enum State { in_progress, finalized, cancelled, error }; | 65 | enum State { in_progress, finalized, cancelled, error }; |
190 | 66 | 66 | ||
191 | @@ -73,6 +73,7 @@ | |||
192 | 73 | QFutureInterface<void>& worker_initialized_; | 73 | QFutureInterface<void>& worker_initialized_; |
193 | 74 | qint64 bytes_to_write_; | 74 | qint64 bytes_to_write_; |
194 | 75 | QString error_msg_; | 75 | QString error_msg_; |
195 | 76 | int error_code_ = 0; | ||
196 | 76 | }; | 77 | }; |
197 | 77 | 78 | ||
198 | 78 | class DownloadThread : public QThread | 79 | class DownloadThread : public QThread |
199 | 79 | 80 | ||
200 | === modified file 'include/unity/storage/qt/client/internal/local_client/FolderImpl.h' | |||
201 | --- include/unity/storage/qt/client/internal/local_client/FolderImpl.h 2016-07-14 00:17:14 +0000 | |||
202 | +++ include/unity/storage/qt/client/internal/local_client/FolderImpl.h 2016-07-29 05:58:49 +0000 | |||
203 | @@ -40,6 +40,7 @@ | |||
204 | 40 | FolderImpl(QString const& identity); | 40 | FolderImpl(QString const& identity); |
205 | 41 | FolderImpl(QString const& identity, ItemType type); | 41 | FolderImpl(QString const& identity, ItemType type); |
206 | 42 | 42 | ||
207 | 43 | virtual QString name() const override; | ||
208 | 43 | QFuture<QVector<std::shared_ptr<Item>>> list() const override; | 44 | QFuture<QVector<std::shared_ptr<Item>>> list() const override; |
209 | 44 | QFuture<QVector<std::shared_ptr<Item>>> lookup(QString const& name) const override; | 45 | QFuture<QVector<std::shared_ptr<Item>>> lookup(QString const& name) const override; |
210 | 45 | QFuture<std::shared_ptr<Folder>> create_folder(QString const& name) override; | 46 | QFuture<std::shared_ptr<Folder>> create_folder(QString const& name) override; |
211 | 46 | 47 | ||
212 | === modified file 'include/unity/storage/qt/client/internal/local_client/ItemImpl.h' | |||
213 | --- include/unity/storage/qt/client/internal/local_client/ItemImpl.h 2016-07-27 02:19:17 +0000 | |||
214 | +++ include/unity/storage/qt/client/internal/local_client/ItemImpl.h 2016-07-29 05:58:49 +0000 | |||
215 | @@ -47,7 +47,6 @@ | |||
216 | 47 | ItemImpl(QString const& identity, ItemType type); | 47 | ItemImpl(QString const& identity, ItemType type); |
217 | 48 | virtual ~ItemImpl(); | 48 | virtual ~ItemImpl(); |
218 | 49 | 49 | ||
219 | 50 | virtual QString name() const override; | ||
220 | 51 | virtual QString etag() const override; | 50 | virtual QString etag() const override; |
221 | 52 | virtual QVariantMap metadata() const override; | 51 | virtual QVariantMap metadata() const override; |
222 | 53 | virtual QDateTime last_modified_time() const override; | 52 | virtual QDateTime last_modified_time() const override; |
223 | @@ -65,8 +64,6 @@ | |||
224 | 65 | void set_timestamps() noexcept; | 64 | void set_timestamps() noexcept; |
225 | 66 | bool has_conflict() const noexcept; | 65 | bool has_conflict() const noexcept; |
226 | 67 | 66 | ||
227 | 68 | std::unique_lock<std::mutex> get_lock(); | ||
228 | 69 | |||
229 | 70 | protected: | 67 | protected: |
230 | 71 | static boost::filesystem::path sanitize(QString const& name, QString const& method); | 68 | static boost::filesystem::path sanitize(QString const& name, QString const& method); |
231 | 72 | static bool is_reserved_path(boost::filesystem::path const& path) noexcept; | 69 | static bool is_reserved_path(boost::filesystem::path const& path) noexcept; |
232 | @@ -78,7 +75,10 @@ | |||
233 | 78 | QString etag_; | 75 | QString etag_; |
234 | 79 | QDateTime modified_time_; | 76 | QDateTime modified_time_; |
235 | 80 | QVariantMap metadata_; | 77 | QVariantMap metadata_; |
237 | 81 | std::mutex mutable mutex_; | 78 | std::recursive_mutex mutable mutex_; |
238 | 79 | |||
239 | 80 | private: | ||
240 | 81 | static void copy_recursively(boost::filesystem::path const& source, boost::filesystem::path const& target); | ||
241 | 82 | }; | 82 | }; |
242 | 83 | 83 | ||
243 | 84 | } // namespace local_client | 84 | } // namespace local_client |
244 | 85 | 85 | ||
245 | === modified file 'include/unity/storage/qt/client/internal/local_client/UploaderImpl.h' | |||
246 | --- include/unity/storage/qt/client/internal/local_client/UploaderImpl.h 2016-07-26 01:51:26 +0000 | |||
247 | +++ include/unity/storage/qt/client/internal/local_client/UploaderImpl.h 2016-07-29 05:58:49 +0000 | |||
248 | @@ -68,12 +68,11 @@ | |||
249 | 68 | private Q_SLOTS: | 68 | private Q_SLOTS: |
250 | 69 | void on_bytes_ready(); | 69 | void on_bytes_ready(); |
251 | 70 | void on_read_channel_finished(); | 70 | void on_read_channel_finished(); |
252 | 71 | void on_error(); | ||
253 | 72 | 71 | ||
254 | 73 | private: | 72 | private: |
255 | 74 | void read_and_write_chunk(); | 73 | void read_and_write_chunk(); |
256 | 75 | void finalize(); | 74 | void finalize(); |
258 | 76 | void handle_error(QString const& msg); | 75 | void handle_error(QString const& msg, int error_code); |
259 | 77 | 76 | ||
260 | 78 | enum State { in_progress, finalized, cancelled, error }; | 77 | enum State { in_progress, finalized, cancelled, error }; |
261 | 79 | 78 | ||
262 | @@ -91,6 +90,7 @@ | |||
263 | 91 | QFutureInterface<std::shared_ptr<File>>& qf_; | 90 | QFutureInterface<std::shared_ptr<File>>& qf_; |
264 | 92 | QFutureInterface<void>& worker_initialized_; | 91 | QFutureInterface<void>& worker_initialized_; |
265 | 93 | QString error_msg_; | 92 | QString error_msg_; |
266 | 93 | int error_code_ = 0; | ||
267 | 94 | bool use_linkat_ = true; | 94 | bool use_linkat_ = true; |
268 | 95 | }; | 95 | }; |
269 | 96 | 96 | ||
270 | 97 | 97 | ||
271 | === modified file 'include/unity/storage/qt/client/internal/make_future.h' | |||
272 | --- include/unity/storage/qt/client/internal/make_future.h 2016-07-22 02:35:12 +0000 | |||
273 | +++ include/unity/storage/qt/client/internal/make_future.h 2016-07-29 05:58:49 +0000 | |||
274 | @@ -18,6 +18,9 @@ | |||
275 | 18 | 18 | ||
276 | 19 | #pragma once | 19 | #pragma once |
277 | 20 | 20 | ||
278 | 21 | #include <unity/storage/qt/client/Exceptions.h> | ||
279 | 22 | #include <unity/storage/qt/client/internal/boost_filesystem.h> | ||
280 | 23 | |||
281 | 21 | #pragma GCC diagnostic push | 24 | #pragma GCC diagnostic push |
282 | 22 | #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" | 25 | #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
283 | 23 | #pragma GCC diagnostic ignored "-Wcast-align" | 26 | #pragma GCC diagnostic ignored "-Wcast-align" |
284 | @@ -94,6 +97,62 @@ | |||
285 | 94 | return qf.future(); | 97 | return qf.future(); |
286 | 95 | } | 98 | } |
287 | 96 | 99 | ||
288 | 100 | template<typename T> | ||
289 | 101 | QFuture<T> make_exceptional_future(QString const& msg, boost::filesystem::filesystem_error const& e) | ||
290 | 102 | { | ||
291 | 103 | QFutureInterface<T> qf; | ||
292 | 104 | switch (e.code().value()) | ||
293 | 105 | { | ||
294 | 106 | case EACCES: | ||
295 | 107 | case EPERM: | ||
296 | 108 | { | ||
297 | 109 | qf.reportException(PermissionException(msg)); | ||
298 | 110 | break; | ||
299 | 111 | } | ||
300 | 112 | case EDQUOT: | ||
301 | 113 | case ENOSPC: | ||
302 | 114 | { | ||
303 | 115 | qf.reportException(QuotaException(msg)); | ||
304 | 116 | break; | ||
305 | 117 | } | ||
306 | 118 | case ENOENT: | ||
307 | 119 | { | ||
308 | 120 | //qf.reportException(NotExistsException(msg)); | ||
309 | 121 | qDebug() << "ENOENT"; | ||
310 | 122 | qf.reportException(ResourceException(msg, e.code().value())); | ||
311 | 123 | break; | ||
312 | 124 | } | ||
313 | 125 | default: | ||
314 | 126 | { | ||
315 | 127 | qf.reportException(ResourceException(msg, e.code().value())); | ||
316 | 128 | break; | ||
317 | 129 | } | ||
318 | 130 | } | ||
319 | 131 | qf.reportFinished(); | ||
320 | 132 | return qf.future(); | ||
321 | 133 | } | ||
322 | 134 | |||
323 | 135 | template<typename T> | ||
324 | 136 | QFuture<T> make_exceptional_future(QString const& msg, boost::filesystem::filesystem_error const& e, QString const& key) | ||
325 | 137 | { | ||
326 | 138 | QFutureInterface<T> qf; | ||
327 | 139 | switch (e.code().value()) | ||
328 | 140 | { | ||
329 | 141 | case ENOENT: | ||
330 | 142 | { | ||
331 | 143 | qf.reportException(NotExistsException(msg, key)); | ||
332 | 144 | break; | ||
333 | 145 | } | ||
334 | 146 | default: | ||
335 | 147 | { | ||
336 | 148 | return make_exceptional_future<T>(msg, e); | ||
337 | 149 | break; | ||
338 | 150 | } | ||
339 | 151 | } | ||
340 | 152 | qf.reportFinished(); | ||
341 | 153 | return qf.future(); | ||
342 | 154 | } | ||
343 | 155 | |||
344 | 97 | } // namespace internal | 156 | } // namespace internal |
345 | 98 | } // namespace client | 157 | } // namespace client |
346 | 99 | } // namespace qt | 158 | } // namespace qt |
347 | 100 | 159 | ||
348 | === modified file 'include/unity/storage/qt/client/internal/remote_client/Handler.h' | |||
349 | --- include/unity/storage/qt/client/internal/remote_client/Handler.h 2016-07-15 03:58:35 +0000 | |||
350 | +++ include/unity/storage/qt/client/internal/remote_client/Handler.h 2016-07-29 05:58:49 +0000 | |||
351 | @@ -18,7 +18,6 @@ | |||
352 | 18 | 18 | ||
353 | 19 | #pragma once | 19 | #pragma once |
354 | 20 | 20 | ||
355 | 21 | #include <unity/storage/qt/client/Exceptions.h> | ||
356 | 22 | #include <unity/storage/qt/client/internal/make_future.h> | 21 | #include <unity/storage/qt/client/internal/make_future.h> |
357 | 23 | #include <unity/storage/qt/client/internal/remote_client/HandlerBase.h> | 22 | #include <unity/storage/qt/client/internal/remote_client/HandlerBase.h> |
358 | 24 | 23 | ||
359 | @@ -72,8 +71,8 @@ | |||
360 | 72 | { | 71 | { |
361 | 73 | if (call.isError()) | 72 | if (call.isError()) |
362 | 74 | { | 73 | { |
365 | 75 | qDebug() << call.error().message(); // TODO, remove this | 74 | int err = call.error().type(); |
366 | 76 | make_exceptional_future<T>(ResourceException("DBus error return")); | 75 | make_exceptional_future<T>(ResourceException("DBus error return", err)); |
367 | 77 | return; | 76 | return; |
368 | 78 | } | 77 | } |
369 | 79 | // TODO: See HACK above. Should just be closure(call, qf_); | 78 | // TODO: See HACK above. Should just be closure(call, qf_); |
370 | 80 | 79 | ||
371 | === modified file 'include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h' | |||
372 | --- include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h 2016-07-22 00:17:24 +0000 | |||
373 | +++ include/unity/storage/qt/client/internal/remote_client/UploaderImpl.h 2016-07-29 05:58:49 +0000 | |||
374 | @@ -69,7 +69,7 @@ | |||
375 | 69 | QDBusUnixFileDescriptor fd_; | 69 | QDBusUnixFileDescriptor fd_; |
376 | 70 | int64_t size_; | 70 | int64_t size_; |
377 | 71 | QString old_etag_; | 71 | QString old_etag_; |
379 | 72 | std::weak_ptr<Root> root_; | 72 | std::shared_ptr<Root> root_; |
380 | 73 | std::shared_ptr<ProviderInterface> provider_; | 73 | std::shared_ptr<ProviderInterface> provider_; |
381 | 74 | std::shared_ptr<QLocalSocket> write_socket_; | 74 | std::shared_ptr<QLocalSocket> write_socket_; |
382 | 75 | }; | 75 | }; |
383 | 76 | 76 | ||
384 | === modified file 'src/qt/client/Account.cpp' | |||
385 | --- src/qt/client/Account.cpp 2016-07-12 02:22:05 +0000 | |||
386 | +++ src/qt/client/Account.cpp 2016-07-29 05:58:49 +0000 | |||
387 | @@ -41,7 +41,7 @@ | |||
388 | 41 | 41 | ||
389 | 42 | Account::~Account() = default; | 42 | Account::~Account() = default; |
390 | 43 | 43 | ||
392 | 44 | Runtime* Account::runtime() const | 44 | shared_ptr<Runtime> Account::runtime() const |
393 | 45 | { | 45 | { |
394 | 46 | return p_->runtime(); | 46 | return p_->runtime(); |
395 | 47 | } | 47 | } |
396 | 48 | 48 | ||
397 | === modified file 'src/qt/client/Exceptions.cpp' | |||
398 | --- src/qt/client/Exceptions.cpp 2016-07-22 01:45:39 +0000 | |||
399 | +++ src/qt/client/Exceptions.cpp 2016-07-29 05:58:49 +0000 | |||
400 | @@ -42,6 +42,11 @@ | |||
401 | 42 | return what_string_.c_str(); | 42 | return what_string_.c_str(); |
402 | 43 | } | 43 | } |
403 | 44 | 44 | ||
404 | 45 | QString StorageException::error_message() const | ||
405 | 46 | { | ||
406 | 47 | return error_message_; | ||
407 | 48 | } | ||
408 | 49 | |||
409 | 45 | LocalCommsException::LocalCommsException(QString const& error_message) | 50 | LocalCommsException::LocalCommsException(QString const& error_message) |
410 | 46 | : StorageException("LocalCommsException", error_message) | 51 | : StorageException("LocalCommsException", error_message) |
411 | 47 | { | 52 | { |
412 | @@ -276,8 +281,9 @@ | |||
413 | 276 | throw *this; | 281 | throw *this; |
414 | 277 | } | 282 | } |
415 | 278 | 283 | ||
417 | 279 | ResourceException::ResourceException(QString const& error_message) | 284 | ResourceException::ResourceException(QString const& error_message, int error_code) |
418 | 280 | : StorageException("ResourceException", error_message) | 285 | : StorageException("ResourceException", error_message) |
419 | 286 | , error_code_(error_code) | ||
420 | 281 | { | 287 | { |
421 | 282 | } | 288 | } |
422 | 283 | 289 | ||
423 | @@ -293,6 +299,11 @@ | |||
424 | 293 | throw *this; | 299 | throw *this; |
425 | 294 | } | 300 | } |
426 | 295 | 301 | ||
427 | 302 | int ResourceException::error_code() const noexcept | ||
428 | 303 | { | ||
429 | 304 | return error_code_; | ||
430 | 305 | } | ||
431 | 306 | |||
432 | 296 | } // namespace client | 307 | } // namespace client |
433 | 297 | } // namespace qt | 308 | } // namespace qt |
434 | 298 | } // namespace storage | 309 | } // namespace storage |
435 | 299 | 310 | ||
436 | === modified file 'src/qt/client/Item.cpp' | |||
437 | --- src/qt/client/Item.cpp 2016-07-14 00:25:40 +0000 | |||
438 | +++ src/qt/client/Item.cpp 2016-07-29 05:58:49 +0000 | |||
439 | @@ -51,7 +51,7 @@ | |||
440 | 51 | return p_->name(); | 51 | return p_->name(); |
441 | 52 | } | 52 | } |
442 | 53 | 53 | ||
444 | 54 | Root* Item::root() const | 54 | shared_ptr<Root> Item::root() const |
445 | 55 | { | 55 | { |
446 | 56 | return p_->root(); | 56 | return p_->root(); |
447 | 57 | } | 57 | } |
448 | 58 | 58 | ||
449 | === modified file 'src/qt/client/Root.cpp' | |||
450 | --- src/qt/client/Root.cpp 2016-07-12 02:22:05 +0000 | |||
451 | +++ src/qt/client/Root.cpp 2016-07-29 05:58:49 +0000 | |||
452 | @@ -30,6 +30,7 @@ | |||
453 | 30 | { | 30 | { |
454 | 31 | 31 | ||
455 | 32 | using namespace internal; | 32 | using namespace internal; |
456 | 33 | using namespace std; | ||
457 | 33 | 34 | ||
458 | 34 | Root::Root(RootBase* p) | 35 | Root::Root(RootBase* p) |
459 | 35 | : Folder(p) | 36 | : Folder(p) |
460 | @@ -38,7 +39,7 @@ | |||
461 | 38 | 39 | ||
462 | 39 | Root::~Root() = default; | 40 | Root::~Root() = default; |
463 | 40 | 41 | ||
465 | 41 | Account* Root::account() const | 42 | shared_ptr<Account> Root::account() const |
466 | 42 | { | 43 | { |
467 | 43 | return dynamic_cast<RootBase*>(p_.get())->account(); | 44 | return dynamic_cast<RootBase*>(p_.get())->account(); |
468 | 44 | } | 45 | } |
469 | 45 | 46 | ||
470 | === modified file 'src/qt/client/internal/AccountBase.cpp' | |||
471 | --- src/qt/client/internal/AccountBase.cpp 2016-07-14 04:50:36 +0000 | |||
472 | +++ src/qt/client/internal/AccountBase.cpp 2016-07-29 05:58:49 +0000 | |||
473 | @@ -19,6 +19,8 @@ | |||
474 | 19 | #include <unity/storage/qt/client/internal/AccountBase.h> | 19 | #include <unity/storage/qt/client/internal/AccountBase.h> |
475 | 20 | 20 | ||
476 | 21 | #include <unity/storage/qt/client/Exceptions.h> | 21 | #include <unity/storage/qt/client/Exceptions.h> |
477 | 22 | #include <unity/storage/qt/client/internal/RuntimeBase.h> | ||
478 | 23 | #include <unity/storage/qt/client/Runtime.h> | ||
479 | 22 | 24 | ||
480 | 23 | #include <cassert> | 25 | #include <cassert> |
481 | 24 | 26 | ||
482 | @@ -42,13 +44,18 @@ | |||
483 | 42 | assert(runtime.lock()); | 44 | assert(runtime.lock()); |
484 | 43 | } | 45 | } |
485 | 44 | 46 | ||
487 | 45 | Runtime* AccountBase::runtime() const | 47 | shared_ptr<Runtime> AccountBase::runtime() const |
488 | 46 | { | 48 | { |
489 | 47 | if (auto runtime = runtime_.lock()) | 49 | if (auto runtime = runtime_.lock()) |
490 | 48 | { | 50 | { |
492 | 49 | return runtime.get(); | 51 | auto runtime_base = runtime->p_; |
493 | 52 | if (runtime_base->destroyed_) | ||
494 | 53 | { | ||
495 | 54 | throw RuntimeDestroyedException("Account::runtime()"); | ||
496 | 55 | } | ||
497 | 56 | return runtime; | ||
498 | 50 | } | 57 | } |
500 | 51 | throw RuntimeDestroyedException("AccountBase::runtime()"); | 58 | throw RuntimeDestroyedException("Account::runtime()"); |
501 | 52 | } | 59 | } |
502 | 53 | 60 | ||
503 | 54 | void AccountBase::set_public_instance(weak_ptr<Account> const& p) | 61 | void AccountBase::set_public_instance(weak_ptr<Account> const& p) |
504 | 55 | 62 | ||
505 | === modified file 'src/qt/client/internal/ItemBase.cpp' | |||
506 | --- src/qt/client/internal/ItemBase.cpp 2016-07-14 04:50:36 +0000 | |||
507 | +++ src/qt/client/internal/ItemBase.cpp 2016-07-29 05:58:49 +0000 | |||
508 | @@ -18,7 +18,9 @@ | |||
509 | 18 | 18 | ||
510 | 19 | #include <unity/storage/qt/client/internal/ItemBase.h> | 19 | #include <unity/storage/qt/client/internal/ItemBase.h> |
511 | 20 | 20 | ||
512 | 21 | #include <unity/storage/qt/client/Account.h> | ||
513 | 21 | #include <unity/storage/qt/client/Exceptions.h> | 22 | #include <unity/storage/qt/client/Exceptions.h> |
514 | 23 | #include <unity/storage/qt/client/Root.h> | ||
515 | 22 | 24 | ||
516 | 23 | #include <cassert> | 25 | #include <cassert> |
517 | 24 | 26 | ||
518 | @@ -54,13 +56,14 @@ | |||
519 | 54 | return type_; | 56 | return type_; |
520 | 55 | } | 57 | } |
521 | 56 | 58 | ||
523 | 57 | Root* ItemBase::root() const | 59 | shared_ptr<Root> ItemBase::root() const |
524 | 58 | { | 60 | { |
526 | 59 | if (auto r = root_.lock()) | 61 | auto root = get_root(); |
527 | 62 | if (!root) | ||
528 | 60 | { | 63 | { |
530 | 61 | return r.get(); | 64 | throw RuntimeDestroyedException("Item::root()"); |
531 | 62 | } | 65 | } |
533 | 63 | throw RuntimeDestroyedException("Item::root()"); | 66 | return root; |
534 | 64 | } | 67 | } |
535 | 65 | 68 | ||
536 | 66 | void ItemBase::set_root(std::weak_ptr<Root> root) | 69 | void ItemBase::set_root(std::weak_ptr<Root> root) |
537 | @@ -75,6 +78,23 @@ | |||
538 | 75 | public_instance_ = p; | 78 | public_instance_ = p; |
539 | 76 | } | 79 | } |
540 | 77 | 80 | ||
541 | 81 | shared_ptr<Root> ItemBase::get_root() const noexcept | ||
542 | 82 | { | ||
543 | 83 | try | ||
544 | 84 | { | ||
545 | 85 | auto root = root_.lock(); | ||
546 | 86 | if (root) | ||
547 | 87 | { | ||
548 | 88 | root->account(); // Throws if either account or runtime has been destroyed. | ||
549 | 89 | return root; | ||
550 | 90 | } | ||
551 | 91 | } | ||
552 | 92 | catch (RuntimeDestroyedException const&) | ||
553 | 93 | { | ||
554 | 94 | } | ||
555 | 95 | return nullptr; | ||
556 | 96 | } | ||
557 | 97 | |||
558 | 78 | } // namespace internal | 98 | } // namespace internal |
559 | 79 | } // namespace client | 99 | } // namespace client |
560 | 80 | } // namespace qt | 100 | } // namespace qt |
561 | 81 | 101 | ||
562 | === modified file 'src/qt/client/internal/RootBase.cpp' | |||
563 | --- src/qt/client/internal/RootBase.cpp 2016-07-27 02:19:17 +0000 | |||
564 | +++ src/qt/client/internal/RootBase.cpp 2016-07-29 05:58:49 +0000 | |||
565 | @@ -18,6 +18,7 @@ | |||
566 | 18 | 18 | ||
567 | 19 | #include <unity/storage/qt/client/internal/RootBase.h> | 19 | #include <unity/storage/qt/client/internal/RootBase.h> |
568 | 20 | 20 | ||
569 | 21 | #include <unity/storage/qt/client/Account.h> | ||
570 | 21 | #include <unity/storage/qt/client/Exceptions.h> | 22 | #include <unity/storage/qt/client/Exceptions.h> |
571 | 22 | 23 | ||
572 | 23 | #include <cassert> | 24 | #include <cassert> |
573 | @@ -43,11 +44,19 @@ | |||
574 | 43 | assert(account.lock()); | 44 | assert(account.lock()); |
575 | 44 | } | 45 | } |
576 | 45 | 46 | ||
578 | 46 | Account* RootBase::account() const | 47 | shared_ptr<Account> RootBase::account() const |
579 | 47 | { | 48 | { |
580 | 48 | if (auto acc = account_.lock()) | 49 | if (auto acc = account_.lock()) |
581 | 49 | { | 50 | { |
583 | 50 | return acc.get(); | 51 | try |
584 | 52 | { | ||
585 | 53 | acc->runtime(); | ||
586 | 54 | } | ||
587 | 55 | catch (RuntimeDestroyedException const&) | ||
588 | 56 | { | ||
589 | 57 | throw RuntimeDestroyedException("Root::account()"); | ||
590 | 58 | } | ||
591 | 59 | return acc; | ||
592 | 51 | } | 60 | } |
593 | 52 | throw RuntimeDestroyedException("Root::account()"); | 61 | throw RuntimeDestroyedException("Root::account()"); |
594 | 53 | } | 62 | } |
595 | 54 | 63 | ||
596 | === modified file 'src/qt/client/internal/RuntimeBase.cpp' | |||
597 | --- src/qt/client/internal/RuntimeBase.cpp 2016-07-12 02:22:05 +0000 | |||
598 | +++ src/qt/client/internal/RuntimeBase.cpp 2016-07-29 05:58:49 +0000 | |||
599 | @@ -34,11 +34,6 @@ | |||
600 | 34 | namespace internal | 34 | namespace internal |
601 | 35 | { | 35 | { |
602 | 36 | 36 | ||
603 | 37 | RuntimeBase::RuntimeBase() | ||
604 | 38 | : destroyed_(false) | ||
605 | 39 | { | ||
606 | 40 | } | ||
607 | 41 | |||
608 | 42 | void RuntimeBase::set_public_instance(weak_ptr<Runtime> p) | 37 | void RuntimeBase::set_public_instance(weak_ptr<Runtime> p) |
609 | 43 | { | 38 | { |
610 | 44 | assert(p.lock()); | 39 | assert(p.lock()); |
611 | 45 | 40 | ||
612 | === modified file 'src/qt/client/internal/local_client/AccountImpl.cpp' | |||
613 | --- src/qt/client/internal/local_client/AccountImpl.cpp 2016-07-14 04:50:36 +0000 | |||
614 | +++ src/qt/client/internal/local_client/AccountImpl.cpp 2016-07-29 05:58:49 +0000 | |||
615 | @@ -67,7 +67,7 @@ | |||
616 | 67 | if (ec) | 67 | if (ec) |
617 | 68 | { | 68 | { |
618 | 69 | QString msg = "Account::roots(): Cannot stat " + QString(dir) + ": " + QString::fromStdString(ec.message()); | 69 | QString msg = "Account::roots(): Cannot stat " + QString(dir) + ": " + QString::fromStdString(ec.message()); |
620 | 70 | throw ResourceException(msg); | 70 | throw ResourceException(msg, errno); |
621 | 71 | } | 71 | } |
622 | 72 | if (!is_dir) | 72 | if (!is_dir) |
623 | 73 | { | 73 | { |
624 | @@ -85,7 +85,7 @@ | |||
625 | 85 | { | 85 | { |
626 | 86 | QString msg = "Account::roots(): Cannot create " + QString(dir) + ": " | 86 | QString msg = "Account::roots(): Cannot create " + QString(dir) + ": " |
627 | 87 | + QString::fromStdString(ec.message()); | 87 | + QString::fromStdString(ec.message()); |
629 | 88 | throw ResourceException(msg); | 88 | throw ResourceException(msg, ec.value()); |
630 | 89 | } | 89 | } |
631 | 90 | } | 90 | } |
632 | 91 | return data_dir; | 91 | return data_dir; |
633 | @@ -109,22 +109,32 @@ | |||
634 | 109 | 109 | ||
635 | 110 | QString AccountImpl::owner() const | 110 | QString AccountImpl::owner() const |
636 | 111 | { | 111 | { |
637 | 112 | runtime(); // Throws RuntimeDestroyedException if runtime was destroyed. | ||
638 | 112 | return owner_; | 113 | return owner_; |
639 | 113 | } | 114 | } |
640 | 114 | 115 | ||
641 | 115 | QString AccountImpl::owner_id() const | 116 | QString AccountImpl::owner_id() const |
642 | 116 | { | 117 | { |
643 | 118 | runtime(); // Throws RuntimeDestroyedException if runtime was destroyed. | ||
644 | 117 | return owner_id_; | 119 | return owner_id_; |
645 | 118 | } | 120 | } |
646 | 119 | 121 | ||
647 | 120 | QString AccountImpl::description() const | 122 | QString AccountImpl::description() const |
648 | 121 | { | 123 | { |
649 | 124 | runtime(); // Throws RuntimeDestroyedException if runtime was destroyed. | ||
650 | 122 | return description_; | 125 | return description_; |
651 | 123 | } | 126 | } |
652 | 124 | 127 | ||
653 | 125 | QFuture<QVector<Root::SPtr>> AccountImpl::roots() | 128 | QFuture<QVector<Root::SPtr>> AccountImpl::roots() |
654 | 126 | { | 129 | { |
656 | 127 | using namespace boost::filesystem; | 130 | try |
657 | 131 | { | ||
658 | 132 | runtime(); // Throws RuntimeDestroyedException if runtime was destroyed. | ||
659 | 133 | } | ||
660 | 134 | catch (RuntimeDestroyedException const& e) | ||
661 | 135 | { | ||
662 | 136 | return make_exceptional_future<QVector<Root::SPtr>>(e); | ||
663 | 137 | } | ||
664 | 128 | 138 | ||
665 | 129 | if (!roots_.isEmpty()) | 139 | if (!roots_.isEmpty()) |
666 | 130 | { | 140 | { |
667 | @@ -132,6 +142,9 @@ | |||
668 | 132 | } | 142 | } |
669 | 133 | 143 | ||
670 | 134 | // Create the root on first access. | 144 | // Create the root on first access. |
671 | 145 | |||
672 | 146 | using namespace boost::filesystem; | ||
673 | 147 | |||
674 | 135 | auto rpath = canonical(get_data_dir()).native(); | 148 | auto rpath = canonical(get_data_dir()).native(); |
675 | 136 | auto root = RootImpl::make_root(QString::fromStdString(rpath), public_instance_); | 149 | auto root = RootImpl::make_root(QString::fromStdString(rpath), public_instance_); |
676 | 137 | roots_.append(root); | 150 | roots_.append(root); |
677 | 138 | 151 | ||
678 | === modified file 'src/qt/client/internal/local_client/DownloaderImpl.cpp' | |||
679 | --- src/qt/client/internal/local_client/DownloaderImpl.cpp 2016-07-22 00:17:24 +0000 | |||
680 | +++ src/qt/client/internal/local_client/DownloaderImpl.cpp 2016-07-29 05:58:49 +0000 | |||
681 | @@ -79,8 +79,10 @@ | |||
682 | 79 | input_file_.reset(new QFile(filename_)); | 79 | input_file_.reset(new QFile(filename_)); |
683 | 80 | if (!input_file_->open(QIODevice::ReadOnly)) | 80 | if (!input_file_->open(QIODevice::ReadOnly)) |
684 | 81 | { | 81 | { |
686 | 82 | handle_error("cannot open " + filename_ + ": " + input_file_->errorString()); | 82 | // LCOV_EXCL_START |
687 | 83 | handle_error("cannot open " + filename_ + ": " + input_file_->errorString(), input_file_->error()); | ||
688 | 83 | return; | 84 | return; |
689 | 85 | // LCOV_EXCL_STOP | ||
690 | 84 | } | 86 | } |
691 | 85 | bytes_to_write_ = input_file_->size(); | 87 | bytes_to_write_ = input_file_->size(); |
692 | 86 | 88 | ||
693 | @@ -136,7 +138,7 @@ | |||
694 | 136 | } | 138 | } |
695 | 137 | case error: | 139 | case error: |
696 | 138 | { | 140 | { |
698 | 139 | make_exceptional_future(qf_, ResourceException(error_msg_)); | 141 | make_exceptional_future(qf_, ResourceException(error_msg_, error_code_)); |
699 | 140 | break; | 142 | break; |
700 | 141 | } | 143 | } |
701 | 142 | default: | 144 | default: |
702 | @@ -189,7 +191,8 @@ | |||
703 | 189 | 191 | ||
704 | 190 | void DownloadWorker::on_error() | 192 | void DownloadWorker::on_error() |
705 | 191 | { | 193 | { |
707 | 192 | handle_error(write_socket_->errorString()); | 194 | disconnect(write_socket_.get(), nullptr, this, nullptr); |
708 | 195 | handle_error(write_socket_->errorString(), write_socket_->error()); | ||
709 | 193 | } | 196 | } |
710 | 194 | 197 | ||
711 | 195 | // Read the next chunk of data from the input file and write it to the socket. | 198 | // Read the next chunk of data from the input file and write it to the socket. |
712 | @@ -203,25 +206,31 @@ | |||
713 | 203 | auto bytes_read = input_file_->read(buf.data(), buf.size()); | 206 | auto bytes_read = input_file_->read(buf.data(), buf.size()); |
714 | 204 | if (bytes_read == -1) | 207 | if (bytes_read == -1) |
715 | 205 | { | 208 | { |
717 | 206 | handle_error(filename_ + ": read error: " + input_file_->errorString()); | 209 | // LCOV_EXCL_START |
718 | 210 | handle_error(filename_ + ": read error: " + input_file_->errorString(), input_file_->error()); | ||
719 | 207 | return; | 211 | return; |
720 | 212 | // LCOV_EXCL_STOP | ||
721 | 208 | } | 213 | } |
722 | 209 | buf.resize(bytes_read); | 214 | buf.resize(bytes_read); |
723 | 210 | 215 | ||
724 | 211 | auto bytes_written = write_socket_->write(buf); | 216 | auto bytes_written = write_socket_->write(buf); |
725 | 212 | if (bytes_written == -1) | 217 | if (bytes_written == -1) |
726 | 213 | { | 218 | { |
728 | 214 | handle_error(filename_ + ": socket error: " + write_socket_->errorString()); | 219 | // LCOV_EXCL_START |
729 | 220 | handle_error(filename_ + ": socket error: " + write_socket_->errorString(), write_socket_->error()); | ||
730 | 221 | // LCOV_EXCL_STOP | ||
731 | 215 | } | 222 | } |
732 | 216 | else if (bytes_written != bytes_read) | 223 | else if (bytes_written != bytes_read) |
733 | 217 | { | 224 | { |
734 | 225 | // LCOV_EXCL_START | ||
735 | 218 | QString msg = filename_ + ": write error, requested " + bytes_read + " B, but wrote only " | 226 | QString msg = filename_ + ": write error, requested " + bytes_read + " B, but wrote only " |
736 | 219 | + bytes_written + " B."; | 227 | + bytes_written + " B."; |
738 | 220 | handle_error(msg); | 228 | handle_error(msg, 0); |
739 | 229 | // LCOV_EXCL_STOP | ||
740 | 221 | } | 230 | } |
741 | 222 | } | 231 | } |
742 | 223 | 232 | ||
744 | 224 | void DownloadWorker::handle_error(QString const& msg) | 233 | void DownloadWorker::handle_error(QString const& msg, int error_code) |
745 | 225 | { | 234 | { |
746 | 226 | if (state_ == in_progress) | 235 | if (state_ == in_progress) |
747 | 227 | { | 236 | { |
748 | @@ -229,6 +238,7 @@ | |||
749 | 229 | } | 238 | } |
750 | 230 | state_ = error; | 239 | state_ = error; |
751 | 231 | error_msg_ = "Downloader: " + msg; | 240 | error_msg_ = "Downloader: " + msg; |
752 | 241 | error_code_ = error_code; | ||
753 | 232 | do_finish(); | 242 | do_finish(); |
754 | 233 | } | 243 | } |
755 | 234 | 244 | ||
756 | @@ -255,7 +265,7 @@ | |||
757 | 255 | // LCOV_EXCL_START | 265 | // LCOV_EXCL_START |
758 | 256 | QString msg = "Downloader: cannot create socket pair: " | 266 | QString msg = "Downloader: cannot create socket pair: " |
759 | 257 | + QString::fromStdString(storage::internal::safe_strerror(errno)); | 267 | + QString::fromStdString(storage::internal::safe_strerror(errno)); |
761 | 258 | make_exceptional_future(qf_, ResourceException(msg)); | 268 | make_exceptional_future(qf_, ResourceException(msg, errno)); |
762 | 259 | return; | 269 | return; |
763 | 260 | // LCOV_EXCL_STOP | 270 | // LCOV_EXCL_STOP |
764 | 261 | } | 271 | } |
765 | 262 | 272 | ||
766 | === modified file 'src/qt/client/internal/local_client/FileImpl.cpp' | |||
767 | --- src/qt/client/internal/local_client/FileImpl.cpp 2016-07-22 01:45:39 +0000 | |||
768 | +++ src/qt/client/internal/local_client/FileImpl.cpp 2016-07-29 05:58:49 +0000 | |||
769 | @@ -50,38 +50,52 @@ | |||
770 | 50 | 50 | ||
771 | 51 | QString FileImpl::name() const | 51 | QString FileImpl::name() const |
772 | 52 | { | 52 | { |
774 | 53 | lock_guard<mutex> guard(mutex_); | 53 | lock_guard<decltype(mutex_)> guard(mutex_); |
775 | 54 | 54 | ||
776 | 55 | if (deleted_) | 55 | if (deleted_) |
777 | 56 | { | 56 | { |
778 | 57 | throw deleted_ex("File::name()"); | 57 | throw deleted_ex("File::name()"); |
779 | 58 | } | 58 | } |
780 | 59 | if (!get_root()) | ||
781 | 60 | { | ||
782 | 61 | throw RuntimeDestroyedException("File::name()"); | ||
783 | 62 | } | ||
784 | 59 | return name_; | 63 | return name_; |
785 | 60 | } | 64 | } |
786 | 61 | 65 | ||
787 | 62 | int64_t FileImpl::size() const | 66 | int64_t FileImpl::size() const |
788 | 63 | { | 67 | { |
790 | 64 | lock_guard<mutex> guard(mutex_); | 68 | lock_guard<decltype(mutex_)> guard(mutex_); |
791 | 65 | 69 | ||
792 | 66 | if (deleted_) | 70 | if (deleted_) |
793 | 67 | { | 71 | { |
794 | 68 | throw deleted_ex("File::size()"); | 72 | throw deleted_ex("File::size()"); |
795 | 69 | } | 73 | } |
796 | 74 | if (!get_root()) | ||
797 | 75 | { | ||
798 | 76 | throw RuntimeDestroyedException("File::size()"); | ||
799 | 77 | } | ||
800 | 70 | 78 | ||
801 | 71 | try | 79 | try |
802 | 72 | { | 80 | { |
803 | 73 | boost::filesystem::path p = identity_.toStdString(); | 81 | boost::filesystem::path p = identity_.toStdString(); |
804 | 74 | return file_size(p); | 82 | return file_size(p); |
805 | 75 | } | 83 | } |
806 | 84 | catch (boost::filesystem::filesystem_error const& e) | ||
807 | 85 | { | ||
808 | 86 | throw ResourceException(e.what(), e.code().value()); | ||
809 | 87 | } | ||
810 | 88 | // LCOV_EXCL_START | ||
811 | 76 | catch (std::exception const& e) | 89 | catch (std::exception const& e) |
812 | 77 | { | 90 | { |
814 | 78 | throw ResourceException(e.what()); | 91 | throw ResourceException(e.what(), 0); |
815 | 79 | } | 92 | } |
816 | 93 | // LCOV_EXCL_STOP | ||
817 | 80 | } | 94 | } |
818 | 81 | 95 | ||
819 | 82 | QFuture<Uploader::SPtr> FileImpl::create_uploader(ConflictPolicy policy, int64_t size) | 96 | QFuture<Uploader::SPtr> FileImpl::create_uploader(ConflictPolicy policy, int64_t size) |
820 | 83 | { | 97 | { |
822 | 84 | lock_guard<mutex> guard(mutex_); | 98 | lock_guard<decltype(mutex_)> guard(mutex_); |
823 | 85 | 99 | ||
824 | 86 | if (deleted_) | 100 | if (deleted_) |
825 | 87 | { | 101 | { |
826 | @@ -92,6 +106,11 @@ | |||
827 | 92 | QString msg = "File::create_uploader(): size must be >= 0"; | 106 | QString msg = "File::create_uploader(): size must be >= 0"; |
828 | 93 | return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); | 107 | return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); |
829 | 94 | } | 108 | } |
830 | 109 | auto root = get_root(); | ||
831 | 110 | if (!root) | ||
832 | 111 | { | ||
833 | 112 | return make_exceptional_future<Uploader::SPtr>(RuntimeDestroyedException("File::create_uploader()")); | ||
834 | 113 | } | ||
835 | 95 | 114 | ||
836 | 96 | auto file = dynamic_pointer_cast<File>(public_instance_.lock()); | 115 | auto file = dynamic_pointer_cast<File>(public_instance_.lock()); |
837 | 97 | assert(file); | 116 | assert(file); |
838 | @@ -102,12 +121,16 @@ | |||
839 | 102 | 121 | ||
840 | 103 | QFuture<Downloader::SPtr> FileImpl::create_downloader() | 122 | QFuture<Downloader::SPtr> FileImpl::create_downloader() |
841 | 104 | { | 123 | { |
843 | 105 | lock_guard<mutex> guard(mutex_); | 124 | lock_guard<decltype(mutex_)> guard(mutex_); |
844 | 106 | 125 | ||
845 | 107 | if (deleted_) | 126 | if (deleted_) |
846 | 108 | { | 127 | { |
847 | 109 | return make_exceptional_future<Downloader::SPtr>(deleted_ex("File::create_downloader()")); | 128 | return make_exceptional_future<Downloader::SPtr>(deleted_ex("File::create_downloader()")); |
848 | 110 | } | 129 | } |
849 | 130 | if (!get_root()) | ||
850 | 131 | { | ||
851 | 132 | throw RuntimeDestroyedException("File::create_downloader()"); | ||
852 | 133 | } | ||
853 | 111 | 134 | ||
854 | 112 | auto pi = public_instance_.lock(); | 135 | auto pi = public_instance_.lock(); |
855 | 113 | assert(pi); | 136 | assert(pi); |
856 | 114 | 137 | ||
857 | === modified file 'src/qt/client/internal/local_client/FolderImpl.cpp' | |||
858 | --- src/qt/client/internal/local_client/FolderImpl.cpp 2016-07-22 01:45:39 +0000 | |||
859 | +++ src/qt/client/internal/local_client/FolderImpl.cpp 2016-07-29 05:58:49 +0000 | |||
860 | @@ -62,16 +62,45 @@ | |||
861 | 62 | { | 62 | { |
862 | 63 | } | 63 | } |
863 | 64 | 64 | ||
864 | 65 | QString FolderImpl::name() const | ||
865 | 66 | { | ||
866 | 67 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
867 | 68 | |||
868 | 69 | if (deleted_) | ||
869 | 70 | { | ||
870 | 71 | throw deleted_ex("Folder::name()"); | ||
871 | 72 | } | ||
872 | 73 | if (!get_root()) | ||
873 | 74 | { | ||
874 | 75 | throw RuntimeDestroyedException("Folder::name()"); | ||
875 | 76 | } | ||
876 | 77 | return name_; | ||
877 | 78 | } | ||
878 | 79 | |||
879 | 65 | QFuture<QVector<Item::SPtr>> FolderImpl::list() const | 80 | QFuture<QVector<Item::SPtr>> FolderImpl::list() const |
880 | 66 | { | 81 | { |
881 | 82 | if (deleted_) | ||
882 | 83 | { | ||
883 | 84 | return make_exceptional_future<QVector<Item::SPtr>>(deleted_ex("Folder::list()")); | ||
884 | 85 | } | ||
885 | 86 | if (!get_root()) | ||
886 | 87 | { | ||
887 | 88 | return make_exceptional_future<QVector<Item::SPtr>>(RuntimeDestroyedException("Folder::list()")); | ||
888 | 89 | } | ||
889 | 90 | |||
890 | 67 | auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive. | 91 | auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive. |
891 | 68 | auto list = [This]() | 92 | auto list = [This]() |
892 | 69 | { | 93 | { |
894 | 70 | lock_guard<mutex> guard(This->mutex_); | 94 | lock_guard<decltype(mutex_)> guard(This->mutex_); |
895 | 71 | 95 | ||
896 | 72 | if (This->deleted_) | 96 | if (This->deleted_) |
897 | 73 | { | 97 | { |
899 | 74 | throw This->deleted_ex("Folder::list()"); | 98 | throw This->deleted_ex("Folder::list()"); // LCOV_EXCL_LINE |
900 | 99 | } | ||
901 | 100 | auto root = This->get_root(); | ||
902 | 101 | if (!root) | ||
903 | 102 | { | ||
904 | 103 | throw RuntimeDestroyedException("Folder::list()"); // LCOV_EXCL_LINE | ||
905 | 75 | } | 104 | } |
906 | 76 | 105 | ||
907 | 77 | try | 106 | try |
908 | @@ -90,11 +119,11 @@ | |||
909 | 90 | QString path = QString::fromStdString(dirent.path().native()); | 119 | QString path = QString::fromStdString(dirent.path().native()); |
910 | 91 | if (is_directory(s)) | 120 | if (is_directory(s)) |
911 | 92 | { | 121 | { |
913 | 93 | results.append(make_folder(path, This->root_)); | 122 | results.append(make_folder(path, root)); |
914 | 94 | } | 123 | } |
915 | 95 | else if (is_regular_file(s)) | 124 | else if (is_regular_file(s)) |
916 | 96 | { | 125 | { |
918 | 97 | results.append(FileImpl::make_file(path, This->root_)); | 126 | results.append(FileImpl::make_file(path, root)); |
919 | 98 | } | 127 | } |
920 | 99 | else | 128 | else |
921 | 100 | { | 129 | { |
922 | @@ -103,24 +132,48 @@ | |||
923 | 103 | } | 132 | } |
924 | 104 | return results; | 133 | return results; |
925 | 105 | } | 134 | } |
926 | 135 | // LCOV_EXCL_START | ||
927 | 136 | catch (StorageException const&) | ||
928 | 137 | { | ||
929 | 138 | throw; | ||
930 | 139 | } | ||
931 | 140 | catch (boost::filesystem::filesystem_error const& e) | ||
932 | 141 | { | ||
933 | 142 | throw ResourceException(QString("Folder::list(): ") + e.what(), e.code().value()); | ||
934 | 143 | } | ||
935 | 106 | catch (std::exception const& e) | 144 | catch (std::exception const& e) |
936 | 107 | { | 145 | { |
938 | 108 | throw ResourceException(QString("Folder::list(): ") + e.what()); | 146 | throw ResourceException(QString("Folder::list(): ") + e.what(), errno); |
939 | 109 | } | 147 | } |
940 | 148 | // LCOV_EXCL_STOP | ||
941 | 110 | }; | 149 | }; |
942 | 111 | return QtConcurrent::run(list); | 150 | return QtConcurrent::run(list); |
943 | 112 | } | 151 | } |
944 | 113 | 152 | ||
945 | 114 | QFuture<QVector<Item::SPtr>> FolderImpl::lookup(QString const& name) const | 153 | QFuture<QVector<Item::SPtr>> FolderImpl::lookup(QString const& name) const |
946 | 115 | { | 154 | { |
947 | 155 | if (deleted_) | ||
948 | 156 | { | ||
949 | 157 | return make_exceptional_future<QVector<Item::SPtr>>(deleted_ex("Folder::lookup()")); | ||
950 | 158 | } | ||
951 | 159 | if (!get_root()) | ||
952 | 160 | { | ||
953 | 161 | return make_exceptional_future<QVector<Item::SPtr>>(RuntimeDestroyedException("Folder::lookup()")); | ||
954 | 162 | } | ||
955 | 163 | |||
956 | 116 | auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive. | 164 | auto This = dynamic_pointer_cast<FolderImpl const>(shared_from_this()); // Keep this folder alive while the lambda is alive. |
957 | 117 | auto lookup = [This, name]() -> QVector<Item::SPtr> | 165 | auto lookup = [This, name]() -> QVector<Item::SPtr> |
958 | 118 | { | 166 | { |
960 | 119 | lock_guard<mutex> guard(This->mutex_); | 167 | lock_guard<decltype(mutex_)> guard(This->mutex_); |
961 | 120 | 168 | ||
962 | 121 | if (This->deleted_) | 169 | if (This->deleted_) |
963 | 122 | { | 170 | { |
965 | 123 | throw This->deleted_ex("Folder::lookup()"); | 171 | throw This->deleted_ex("Folder::lookup()"); // LCOV_EXCL_LINE |
966 | 172 | } | ||
967 | 173 | auto root = This->get_root(); | ||
968 | 174 | if (!root) | ||
969 | 175 | { | ||
970 | 176 | throw RuntimeDestroyedException("Folder::lookup()"); // LCOV_EXCL_LINE | ||
971 | 124 | } | 177 | } |
972 | 125 | 178 | ||
973 | 126 | try | 179 | try |
974 | @@ -131,45 +184,56 @@ | |||
975 | 131 | auto sanitized_name = sanitize(name, "Folder::lookup()"); | 184 | auto sanitized_name = sanitize(name, "Folder::lookup()"); |
976 | 132 | if (is_reserved_path(sanitized_name)) | 185 | if (is_reserved_path(sanitized_name)) |
977 | 133 | { | 186 | { |
979 | 134 | throw NotExistsException("Folder::lookup(): no such item: " + name, name); | 187 | throw NotExistsException("Folder::lookup(): no such item: \"" + name + "\"", name); |
980 | 135 | } | 188 | } |
981 | 136 | p /= sanitized_name; | 189 | p /= sanitized_name; |
982 | 137 | file_status s = status(p); | 190 | file_status s = status(p); |
983 | 138 | if (is_directory(s)) | 191 | if (is_directory(s)) |
984 | 139 | { | 192 | { |
985 | 140 | QVector<Item::SPtr> v; | 193 | QVector<Item::SPtr> v; |
987 | 141 | v.append(make_folder(QString::fromStdString(p.native()), This->root_)); | 194 | v.append(make_folder(QString::fromStdString(p.native()), root)); |
988 | 142 | return v; | 195 | return v; |
989 | 143 | } | 196 | } |
990 | 144 | if (is_regular_file(s)) | 197 | if (is_regular_file(s)) |
991 | 145 | { | 198 | { |
992 | 146 | QVector<Item::SPtr> v; | 199 | QVector<Item::SPtr> v; |
994 | 147 | v.append(FileImpl::make_file(QString::fromStdString(p.native()), This->root_)); | 200 | v.append(FileImpl::make_file(QString::fromStdString(p.native()), root)); |
995 | 148 | return v; | 201 | return v; |
996 | 149 | } | 202 | } |
998 | 150 | throw NotExistsException("Folder::lookup(): no such item: " + name, name); | 203 | throw NotExistsException("Folder::lookup(): no such item: \"" + name + "\"", name); |
999 | 151 | } | 204 | } |
1001 | 152 | catch (StorageException const&) | 205 | catch (StorageException const& e) |
1002 | 153 | { | 206 | { |
1003 | 154 | throw; | 207 | throw; |
1004 | 155 | } | 208 | } |
1005 | 209 | // LCOV_EXCL_START | ||
1006 | 210 | catch (boost::filesystem::filesystem_error const& e) | ||
1007 | 211 | { | ||
1008 | 212 | throw ResourceException(QString("Folder::lookup(): ") + e.what(), e.code().value()); | ||
1009 | 213 | } | ||
1010 | 156 | catch (std::exception const& e) | 214 | catch (std::exception const& e) |
1011 | 157 | { | 215 | { |
1013 | 158 | throw ResourceException(QString("Folder::lookup(): ") + e.what()); | 216 | throw ResourceException(QString("Folder::lookup(): ") + e.what(), errno); |
1014 | 159 | } | 217 | } |
1015 | 218 | // LCOV_EXCL_STOP | ||
1016 | 160 | }; | 219 | }; |
1017 | 161 | return QtConcurrent::run(lookup); | 220 | return QtConcurrent::run(lookup); |
1018 | 162 | } | 221 | } |
1019 | 163 | 222 | ||
1020 | 164 | QFuture<Folder::SPtr> FolderImpl::create_folder(QString const& name) | 223 | QFuture<Folder::SPtr> FolderImpl::create_folder(QString const& name) |
1021 | 165 | { | 224 | { |
1023 | 166 | lock_guard<mutex> guard(mutex_); | 225 | lock_guard<decltype(mutex_)> guard(mutex_); |
1024 | 167 | 226 | ||
1025 | 168 | QFutureInterface<Folder::SPtr> qf; | 227 | QFutureInterface<Folder::SPtr> qf; |
1026 | 169 | if (deleted_) | 228 | if (deleted_) |
1027 | 170 | { | 229 | { |
1028 | 171 | return make_exceptional_future<Folder::SPtr>(deleted_ex("Folder::create_folder()")); | 230 | return make_exceptional_future<Folder::SPtr>(deleted_ex("Folder::create_folder()")); |
1029 | 172 | } | 231 | } |
1030 | 232 | auto root = get_root(); | ||
1031 | 233 | if (!root) | ||
1032 | 234 | { | ||
1033 | 235 | return make_exceptional_future<Folder::SPtr>(RuntimeDestroyedException("Folder::create_folder()")); | ||
1034 | 236 | } | ||
1035 | 173 | 237 | ||
1036 | 174 | try | 238 | try |
1037 | 175 | { | 239 | { |
1038 | @@ -179,22 +243,39 @@ | |||
1039 | 179 | auto sanitized_name = sanitize(name, "Folder::create_folder()"); | 243 | auto sanitized_name = sanitize(name, "Folder::create_folder()"); |
1040 | 180 | if (is_reserved_path(sanitized_name)) | 244 | if (is_reserved_path(sanitized_name)) |
1041 | 181 | { | 245 | { |
1044 | 182 | QString msg = "Folder::create_folder(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved"; | 246 | QString msg = "Folder::create_folder(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved"; |
1045 | 183 | return make_exceptional_future<Folder::SPtr>(InvalidArgumentException(msg)); | 247 | throw InvalidArgumentException(msg); |
1046 | 184 | } | 248 | } |
1047 | 185 | p /= sanitized_name; | 249 | p /= sanitized_name; |
1048 | 250 | if (exists(p)) | ||
1049 | 251 | { | ||
1050 | 252 | QString msg = "Folder::create_folder(): item with name \"" + name + "\" exists already"; | ||
1051 | 253 | throw ExistsException(msg, native_identity() + "/" + name, name); | ||
1052 | 254 | } | ||
1053 | 186 | create_directory(p); | 255 | create_directory(p); |
1056 | 187 | return make_ready_future(make_folder(QString::fromStdString(p.native()), root_)); | 256 | return make_ready_future(make_folder(QString::fromStdString(p.native()), root)); |
1057 | 188 | } | 257 | } |
1058 | 258 | catch (StorageException const& e) | ||
1059 | 259 | { | ||
1060 | 260 | return make_exceptional_future<Folder::SPtr>(e); | ||
1061 | 261 | } | ||
1062 | 262 | catch (boost::filesystem::filesystem_error const& e) | ||
1063 | 263 | { | ||
1064 | 264 | return make_exceptional_future<Folder::SPtr>(ResourceException(QString("Folder::create_folder(): ") + e.what(), | ||
1065 | 265 | e.code().value())); | ||
1066 | 266 | } | ||
1067 | 267 | // LCOV_EXCL_START | ||
1068 | 189 | catch (std::exception const& e) | 268 | catch (std::exception const& e) |
1069 | 190 | { | 269 | { |
1071 | 191 | return make_exceptional_future<Folder::SPtr>(ResourceException(QString("Folder::create_folder: ") + e.what())); | 270 | return make_exceptional_future<Folder::SPtr>(ResourceException(QString("Folder::create_folder(): ") + e.what(), |
1072 | 271 | errno)); | ||
1073 | 192 | } | 272 | } |
1074 | 273 | // LCOV_EXCL_STOP | ||
1075 | 193 | } | 274 | } |
1076 | 194 | 275 | ||
1077 | 195 | QFuture<shared_ptr<Uploader>> FolderImpl::create_file(QString const& name, int64_t size) | 276 | QFuture<shared_ptr<Uploader>> FolderImpl::create_file(QString const& name, int64_t size) |
1078 | 196 | { | 277 | { |
1080 | 197 | unique_lock<mutex> guard(mutex_); | 278 | lock_guard<decltype(mutex_)> guard(mutex_); |
1081 | 198 | 279 | ||
1082 | 199 | if (deleted_) | 280 | if (deleted_) |
1083 | 200 | { | 281 | { |
1084 | @@ -205,6 +286,11 @@ | |||
1085 | 205 | QString msg = "Folder::create_file(): size must be >= 0"; | 286 | QString msg = "Folder::create_file(): size must be >= 0"; |
1086 | 206 | return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); | 287 | return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); |
1087 | 207 | } | 288 | } |
1088 | 289 | auto root = get_root(); | ||
1089 | 290 | if (!root) | ||
1090 | 291 | { | ||
1091 | 292 | return make_exceptional_future<Uploader::SPtr>(RuntimeDestroyedException("Folder::create_file()")); | ||
1092 | 293 | } | ||
1093 | 208 | 294 | ||
1094 | 209 | try | 295 | try |
1095 | 210 | { | 296 | { |
1096 | @@ -214,27 +300,39 @@ | |||
1097 | 214 | auto sanitized_name = sanitize(name, "Folder::create_file()"); | 300 | auto sanitized_name = sanitize(name, "Folder::create_file()"); |
1098 | 215 | if (is_reserved_path(sanitized_name)) | 301 | if (is_reserved_path(sanitized_name)) |
1099 | 216 | { | 302 | { |
1102 | 217 | QString msg = "Folder::create_file(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved"; | 303 | QString msg = "Folder::create_file(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved"; |
1103 | 218 | return make_exceptional_future<Uploader::SPtr>(InvalidArgumentException(msg)); | 304 | throw InvalidArgumentException(msg); |
1104 | 219 | } | 305 | } |
1105 | 220 | p /= sanitized_name; | 306 | p /= sanitized_name; |
1106 | 221 | if (exists(p)) | 307 | if (exists(p)) |
1107 | 222 | { | 308 | { |
1108 | 223 | QString msg = "Folder::create_file(): item with name \"" + name + "\" exists already"; | 309 | QString msg = "Folder::create_file(): item with name \"" + name + "\" exists already"; |
1110 | 224 | return make_exceptional_future<Uploader::SPtr>(ExistsException(msg, native_identity(), name)); | 310 | throw ExistsException(msg, native_identity() + "/" + name, name); |
1111 | 225 | } | 311 | } |
1112 | 226 | auto impl = new UploaderImpl(shared_ptr<File>(), | 312 | auto impl = new UploaderImpl(shared_ptr<File>(), |
1113 | 227 | size, | 313 | size, |
1114 | 228 | QString::fromStdString(p.native()), | 314 | QString::fromStdString(p.native()), |
1115 | 229 | ConflictPolicy::error_if_conflict, | 315 | ConflictPolicy::error_if_conflict, |
1117 | 230 | root_); | 316 | root); |
1118 | 231 | Uploader::SPtr uploader(new Uploader(impl)); | 317 | Uploader::SPtr uploader(new Uploader(impl)); |
1119 | 232 | return make_ready_future(uploader); | 318 | return make_ready_future(uploader); |
1120 | 233 | } | 319 | } |
1121 | 320 | catch (StorageException const& e) | ||
1122 | 321 | { | ||
1123 | 322 | return make_exceptional_future<Uploader::SPtr>(e); | ||
1124 | 323 | } | ||
1125 | 324 | catch (boost::filesystem::filesystem_error const& e) | ||
1126 | 325 | { | ||
1127 | 326 | return make_exceptional_future<Uploader::SPtr>(ResourceException(QString("Folder::create_file(): ") + e.what(), | ||
1128 | 327 | e.code().value())); | ||
1129 | 328 | } | ||
1130 | 329 | // LCOV_EXCL_START | ||
1131 | 234 | catch (std::exception const& e) | 330 | catch (std::exception const& e) |
1132 | 235 | { | 331 | { |
1134 | 236 | return make_exceptional_future<Uploader::SPtr>(ResourceException(QString("Folder::create_file: ") + e.what())); | 332 | return make_exceptional_future<Uploader::SPtr>(ResourceException(QString("Folder::create_file(): ") + e.what(), |
1135 | 333 | errno)); | ||
1136 | 237 | } | 334 | } |
1137 | 335 | // LCOV_EXCL_STOP | ||
1138 | 238 | } | 336 | } |
1139 | 239 | 337 | ||
1140 | 240 | Folder::SPtr FolderImpl::make_folder(QString const& identity, weak_ptr<Root> root) | 338 | Folder::SPtr FolderImpl::make_folder(QString const& identity, weak_ptr<Root> root) |
1141 | 241 | 339 | ||
1142 | === modified file 'src/qt/client/internal/local_client/ItemImpl.cpp' | |||
1143 | --- src/qt/client/internal/local_client/ItemImpl.cpp 2016-07-22 00:17:24 +0000 | |||
1144 | +++ src/qt/client/internal/local_client/ItemImpl.cpp 2016-07-29 05:58:49 +0000 | |||
1145 | @@ -64,102 +64,86 @@ | |||
1146 | 64 | 64 | ||
1147 | 65 | ItemImpl::~ItemImpl() = default; | 65 | ItemImpl::~ItemImpl() = default; |
1148 | 66 | 66 | ||
1149 | 67 | QString ItemImpl::name() const | ||
1150 | 68 | { | ||
1151 | 69 | lock_guard<mutex> guard(mutex_); | ||
1152 | 70 | |||
1153 | 71 | if (deleted_) | ||
1154 | 72 | { | ||
1155 | 73 | throw deleted_ex("Item::name()"); | ||
1156 | 74 | } | ||
1157 | 75 | return name_; | ||
1158 | 76 | } | ||
1159 | 77 | |||
1160 | 78 | QString ItemImpl::etag() const | 67 | QString ItemImpl::etag() const |
1161 | 79 | { | 68 | { |
1163 | 80 | lock_guard<mutex> guard(mutex_); | 69 | lock_guard<decltype(mutex_)> guard(mutex_); |
1164 | 81 | 70 | ||
1165 | 82 | if (deleted_) | 71 | if (deleted_) |
1166 | 83 | { | 72 | { |
1167 | 84 | throw deleted_ex("Item::etag()"); | 73 | throw deleted_ex("Item::etag()"); |
1168 | 85 | } | 74 | } |
1169 | 75 | if (!get_root()) | ||
1170 | 76 | { | ||
1171 | 77 | throw RuntimeDestroyedException("Item::etag()"); | ||
1172 | 78 | } | ||
1173 | 86 | return etag_; | 79 | return etag_; |
1174 | 87 | } | 80 | } |
1175 | 88 | 81 | ||
1176 | 89 | QVariantMap ItemImpl::metadata() const | 82 | QVariantMap ItemImpl::metadata() const |
1177 | 90 | { | 83 | { |
1179 | 91 | lock_guard<mutex> guard(mutex_); | 84 | lock_guard<decltype(mutex_)> guard(mutex_); |
1180 | 92 | 85 | ||
1181 | 93 | if (deleted_) | 86 | if (deleted_) |
1182 | 94 | { | 87 | { |
1183 | 95 | throw deleted_ex("Item::metadata()"); | 88 | throw deleted_ex("Item::metadata()"); |
1184 | 96 | } | 89 | } |
1185 | 90 | if (!get_root()) | ||
1186 | 91 | { | ||
1187 | 92 | throw RuntimeDestroyedException("Item::metadata()"); | ||
1188 | 93 | } | ||
1189 | 97 | return metadata_; | 94 | return metadata_; |
1190 | 98 | } | 95 | } |
1191 | 99 | 96 | ||
1192 | 100 | QDateTime ItemImpl::last_modified_time() const | 97 | QDateTime ItemImpl::last_modified_time() const |
1193 | 101 | { | 98 | { |
1195 | 102 | lock_guard<mutex> guard(mutex_); | 99 | lock_guard<decltype(mutex_)> guard(mutex_); |
1196 | 103 | 100 | ||
1197 | 104 | if (deleted_) | 101 | if (deleted_) |
1198 | 105 | { | 102 | { |
1199 | 106 | throw deleted_ex("Item::last_modified_time()"); | 103 | throw deleted_ex("Item::last_modified_time()"); |
1200 | 107 | } | 104 | } |
1201 | 105 | if (!get_root()) | ||
1202 | 106 | { | ||
1203 | 107 | throw RuntimeDestroyedException("Item::last_modified_time()"); | ||
1204 | 108 | } | ||
1205 | 108 | return modified_time_; | 109 | return modified_time_; |
1206 | 109 | } | 110 | } |
1207 | 110 | 111 | ||
1208 | 111 | namespace | ||
1209 | 112 | { | ||
1210 | 113 | |||
1211 | 114 | using namespace boost::filesystem; | ||
1212 | 115 | |||
1213 | 116 | void copy_recursively(path const& source, path const& target) | ||
1214 | 117 | { | ||
1215 | 118 | auto s = status(source); | ||
1216 | 119 | if (is_regular_file(s)) | ||
1217 | 120 | { | ||
1218 | 121 | copy_file(source, target); | ||
1219 | 122 | return; | ||
1220 | 123 | } | ||
1221 | 124 | else if (is_directory(s)) | ||
1222 | 125 | { | ||
1223 | 126 | copy_directory(source, target); // Poorly named in boost; this creates the target dir without recursion | ||
1224 | 127 | for (directory_iterator it(source); it != directory_iterator(); ++it) | ||
1225 | 128 | { | ||
1226 | 129 | path source_entry = it->path(); | ||
1227 | 130 | path target_entry = target; | ||
1228 | 131 | target_entry /= source_entry.filename(); | ||
1229 | 132 | copy_recursively(source_entry, target_entry); | ||
1230 | 133 | } | ||
1231 | 134 | } | ||
1232 | 135 | else | ||
1233 | 136 | { | ||
1234 | 137 | // Ignore everything that's not a directory or file. | ||
1235 | 138 | } | ||
1236 | 139 | } | ||
1237 | 140 | |||
1238 | 141 | } // namespace | ||
1239 | 142 | |||
1240 | 143 | QFuture<shared_ptr<Item>> ItemImpl::copy(shared_ptr<Folder> const& new_parent, QString const& new_name) | 112 | QFuture<shared_ptr<Item>> ItemImpl::copy(shared_ptr<Folder> const& new_parent, QString const& new_name) |
1241 | 144 | { | 113 | { |
1242 | 114 | if (!new_parent) | ||
1243 | 115 | { | ||
1244 | 116 | QString msg = "Item::copy(): new_parent cannot be nullptr"; | ||
1245 | 117 | return make_exceptional_future<shared_ptr<Item>>(InvalidArgumentException(msg)); | ||
1246 | 118 | } | ||
1247 | 119 | if (!get_root()) | ||
1248 | 120 | { | ||
1249 | 121 | return make_exceptional_future<shared_ptr<Item>>(RuntimeDestroyedException("Item::copy()")); | ||
1250 | 122 | } | ||
1251 | 123 | |||
1252 | 145 | auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive. | 124 | auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive. |
1253 | 146 | auto copy = [This, new_parent, new_name]() -> Item::SPtr | 125 | auto copy = [This, new_parent, new_name]() -> Item::SPtr |
1254 | 147 | { | 126 | { |
1255 | 148 | auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); | 127 | auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
1256 | 149 | 128 | ||
1257 | 150 | lock(This->mutex_, new_parent_impl->mutex_); | 129 | lock(This->mutex_, new_parent_impl->mutex_); |
1267 | 151 | lock_guard<mutex> this_guard(This->mutex_, std::adopt_lock); | 130 | lock_guard<decltype(mutex_)> this_guard(This->mutex_, std::adopt_lock); |
1268 | 152 | lock_guard<mutex> other_guard(new_parent_impl->mutex_, adopt_lock); | 131 | lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock); |
1269 | 153 | 132 | ||
1270 | 154 | if (This->deleted_ || new_parent_impl->deleted_) | 133 | if (This->deleted_) |
1271 | 155 | { | 134 | { |
1272 | 156 | throw This->deleted_ex("Item::copy"); | 135 | throw This->deleted_ex("Item::copy()"); |
1273 | 157 | } | 136 | } |
1274 | 158 | 137 | if (new_parent_impl->deleted_) | |
1275 | 159 | if (This->root()->account() != new_parent->root()->account()) | 138 | { |
1276 | 139 | throw new_parent_impl->deleted_ex("Item::copy()"); | ||
1277 | 140 | } | ||
1278 | 141 | |||
1279 | 142 | // TODO: This needs to deeply compare account identity because the client may have refreshed the accounts list. | ||
1280 | 143 | if (This->root()->account() != new_parent->root()->account()) // Throws if account or runtime were destroyed. | ||
1281 | 160 | { | 144 | { |
1282 | 161 | // Can't do cross-account copy. | 145 | // Can't do cross-account copy. |
1284 | 162 | QString msg = QString("Item::copy(): Source (") + This->name_ + ") and target (" | 146 | QString msg = QString("Item::copy(): source (") + This->name_ + ") and target (" |
1285 | 163 | + new_name + ") must belong to the same account"; | 147 | + new_name + ") must belong to the same account"; |
1286 | 164 | throw LogicException(msg); | 148 | throw LogicException(msg); |
1287 | 165 | } | 149 | } |
1288 | @@ -175,22 +159,22 @@ | |||
1289 | 175 | target_path /= sanitized_name; | 159 | target_path /= sanitized_name; |
1290 | 176 | if (is_reserved_path(target_path)) | 160 | if (is_reserved_path(target_path)) |
1291 | 177 | { | 161 | { |
1293 | 178 | QString msg = "Item::copy(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved"; | 162 | QString msg = "Item::copy(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved"; |
1294 | 179 | throw InvalidArgumentException(msg); | 163 | throw InvalidArgumentException(msg); |
1295 | 180 | } | 164 | } |
1296 | 181 | 165 | ||
1297 | 166 | if (exists(target_path)) | ||
1298 | 167 | { | ||
1299 | 168 | QString msg = "Item::copy(): item with name \"" + new_name + "\" exists already"; | ||
1300 | 169 | throw ExistsException(msg, This->identity_, This->name_); | ||
1301 | 170 | } | ||
1302 | 171 | |||
1303 | 182 | if (This->type_ == ItemType::file) | 172 | if (This->type_ == ItemType::file) |
1304 | 183 | { | 173 | { |
1305 | 184 | copy_file(source_path, target_path); | 174 | copy_file(source_path, target_path); |
1306 | 185 | return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_); | 175 | return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_); |
1307 | 186 | } | 176 | } |
1308 | 187 | 177 | ||
1309 | 188 | if (exists(target_path)) | ||
1310 | 189 | { | ||
1311 | 190 | QString msg = "Item::copy(): item with name \"" + new_name + "\" exists already"; | ||
1312 | 191 | throw ExistsException(msg, This->identity_, This->name_); | ||
1313 | 192 | } | ||
1314 | 193 | |||
1315 | 194 | // For recursive copy, we create a temporary directory in lieu of target_path and recursively copy | 178 | // For recursive copy, we create a temporary directory in lieu of target_path and recursively copy |
1316 | 195 | // everything into the temporary directory. This ensures that we don't invalidate directory iterators | 179 | // everything into the temporary directory. This ensures that we don't invalidate directory iterators |
1317 | 196 | // by creating things while we are iterating, potentially getting trapped in an infinite loop. | 180 | // by creating things while we are iterating, potentially getting trapped in an infinite loop. |
1318 | @@ -199,7 +183,7 @@ | |||
1319 | 199 | create_directories(tmp_path); | 183 | create_directories(tmp_path); |
1320 | 200 | for (directory_iterator it(source_path); it != directory_iterator(); ++it) | 184 | for (directory_iterator it(source_path); it != directory_iterator(); ++it) |
1321 | 201 | { | 185 | { |
1323 | 202 | if (tmp_path.compare(canonical(it->path())) == 0) | 186 | if (is_reserved_path(it->path())) |
1324 | 203 | { | 187 | { |
1325 | 204 | continue; // Don't recurse into the temporary directory | 188 | continue; // Don't recurse into the temporary directory |
1326 | 205 | } | 189 | } |
1327 | @@ -209,47 +193,72 @@ | |||
1328 | 209 | path source_entry = it->path(); | 193 | path source_entry = it->path(); |
1329 | 210 | path target_entry = tmp_path; | 194 | path target_entry = tmp_path; |
1330 | 211 | target_entry /= source_entry.filename(); | 195 | target_entry /= source_entry.filename(); |
1332 | 212 | copy_recursively(source_entry, target_entry); | 196 | ItemImpl::copy_recursively(source_entry, target_entry); |
1333 | 213 | } | 197 | } |
1334 | 214 | } | 198 | } |
1335 | 215 | rename(tmp_path, target_path); | 199 | rename(tmp_path, target_path); |
1336 | 216 | return FolderImpl::make_folder(QString::fromStdString(target_path.native()), new_parent_impl->root_); | 200 | return FolderImpl::make_folder(QString::fromStdString(target_path.native()), new_parent_impl->root_); |
1337 | 217 | } | 201 | } |
1338 | 202 | catch (StorageException const&) | ||
1339 | 203 | { | ||
1340 | 204 | throw; | ||
1341 | 205 | } | ||
1342 | 206 | catch (boost::filesystem::filesystem_error const& e) | ||
1343 | 207 | { | ||
1344 | 208 | throw ResourceException(QString("Item::copy(): ") + e.what(), e.code().value()); | ||
1345 | 209 | } | ||
1346 | 210 | // LCOV_EXCL_START | ||
1347 | 218 | catch (std::exception const& e) | 211 | catch (std::exception const& e) |
1348 | 219 | { | 212 | { |
1350 | 220 | throw ResourceException(QString("Item::copy(): ") + e.what()); | 213 | throw ResourceException(QString("Item::copy(): ") + e.what(), errno); |
1351 | 221 | } | 214 | } |
1352 | 215 | // LCOV_EXCL_STOP | ||
1353 | 222 | }; | 216 | }; |
1354 | 223 | return QtConcurrent::run(copy); | 217 | return QtConcurrent::run(copy); |
1355 | 224 | } | 218 | } |
1356 | 225 | 219 | ||
1357 | 226 | QFuture<shared_ptr<Item>> ItemImpl::move(shared_ptr<Folder> const& new_parent, QString const& new_name) | 220 | QFuture<shared_ptr<Item>> ItemImpl::move(shared_ptr<Folder> const& new_parent, QString const& new_name) |
1358 | 227 | { | 221 | { |
1359 | 222 | if (!new_parent) | ||
1360 | 223 | { | ||
1361 | 224 | QString msg = "Item::move(): new_parent cannot be nullptr"; | ||
1362 | 225 | return make_exceptional_future<shared_ptr<Item>>(InvalidArgumentException(msg)); | ||
1363 | 226 | } | ||
1364 | 227 | if (!get_root()) | ||
1365 | 228 | { | ||
1366 | 229 | return make_exceptional_future<shared_ptr<Item>>(RuntimeDestroyedException("Item::move()")); | ||
1367 | 230 | } | ||
1368 | 231 | |||
1369 | 228 | auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive. | 232 | auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive. |
1370 | 229 | auto move = [This, new_parent, new_name]() -> Item::SPtr | 233 | auto move = [This, new_parent, new_name]() -> Item::SPtr |
1371 | 230 | { | 234 | { |
1372 | 231 | auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); | 235 | auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
1373 | 232 | 236 | ||
1374 | 233 | lock(This->mutex_, new_parent_impl->mutex_); | 237 | lock(This->mutex_, new_parent_impl->mutex_); |
1384 | 234 | lock_guard<mutex> this_guard(This->mutex_, std::adopt_lock); | 238 | lock_guard<decltype(mutex_)> this_guard(This->mutex_, std::adopt_lock); |
1385 | 235 | lock_guard<mutex> other_guard(new_parent_impl->mutex_, adopt_lock); | 239 | lock_guard<decltype(mutex_)> other_guard(new_parent_impl->mutex_, adopt_lock); |
1386 | 236 | 240 | ||
1387 | 237 | if (This->deleted_ || new_parent_impl->deleted_) | 241 | if (This->deleted_) |
1388 | 238 | { | 242 | { |
1389 | 239 | throw This->deleted_ex("Item::move"); | 243 | throw This->deleted_ex("Item::move()"); |
1390 | 240 | } | 244 | } |
1391 | 241 | 245 | if (new_parent_impl->deleted_) | |
1392 | 242 | if (This->root()->account() != new_parent->root()->account()) | 246 | { |
1393 | 247 | throw new_parent_impl->deleted_ex("Item::move()"); | ||
1394 | 248 | } | ||
1395 | 249 | |||
1396 | 250 | // TODO: This needs to deeply compare account identity because the client may have refreshed the accounts list. | ||
1397 | 251 | if (This->root()->account() != new_parent->root()->account()) // Throws if account or runtime were destroyed. | ||
1398 | 243 | { | 252 | { |
1399 | 244 | // Can't do cross-account move. | 253 | // Can't do cross-account move. |
1401 | 245 | QString msg = QString("Item::move(): Source (") + This->name_ + ") and target (" | 254 | QString msg = QString("Item::move(): source (") + This->name_ + ") and target (" |
1402 | 246 | + new_name + ") must belong to the same account"; | 255 | + new_name + ") must belong to the same account"; |
1403 | 247 | throw LogicException(msg); | 256 | throw LogicException(msg); |
1404 | 248 | } | 257 | } |
1405 | 249 | if (This->type_ == ItemType::root) | 258 | if (This->type_ == ItemType::root) |
1406 | 250 | { | 259 | { |
1407 | 251 | // Can't move a root. | 260 | // Can't move a root. |
1409 | 252 | throw LogicException("Item::move(): Cannot move root folder"); | 261 | throw LogicException("Item::move(): cannot move root folder"); |
1410 | 253 | } | 262 | } |
1411 | 254 | 263 | ||
1412 | 255 | try | 264 | try |
1413 | @@ -265,7 +274,7 @@ | |||
1414 | 265 | } | 274 | } |
1415 | 266 | if (is_reserved_path(target_path)) | 275 | if (is_reserved_path(target_path)) |
1416 | 267 | { | 276 | { |
1418 | 268 | QString msg = "Item::move(): names beginning with " + QString(TMPFILE_PREFIX) + " are reserved"; | 277 | QString msg = "Item::move(): names beginning with \"" + QString(TMPFILE_PREFIX) + "\" are reserved"; |
1419 | 269 | throw InvalidArgumentException(msg); | 278 | throw InvalidArgumentException(msg); |
1420 | 270 | } | 279 | } |
1421 | 271 | rename(This->native_identity().toStdString(), target_path); | 280 | rename(This->native_identity().toStdString(), target_path); |
1422 | @@ -276,25 +285,34 @@ | |||
1423 | 276 | } | 285 | } |
1424 | 277 | return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_); | 286 | return FileImpl::make_file(QString::fromStdString(target_path.native()), new_parent_impl->root_); |
1425 | 278 | } | 287 | } |
1426 | 288 | catch (StorageException const&) | ||
1427 | 289 | { | ||
1428 | 290 | throw; | ||
1429 | 291 | } | ||
1430 | 292 | catch (boost::filesystem::filesystem_error const& e) | ||
1431 | 293 | { | ||
1432 | 294 | throw ResourceException(QString("Item::move(): ") + e.what(), e.code().value()); | ||
1433 | 295 | } | ||
1434 | 296 | // LCOV_EXCL_START | ||
1435 | 279 | catch (std::exception const& e) | 297 | catch (std::exception const& e) |
1436 | 280 | { | 298 | { |
1438 | 281 | throw ResourceException(QString("Item::move(): ") + e.what()); | 299 | throw ResourceException(QString("Item::move(): ") + e.what(), errno); |
1439 | 282 | } | 300 | } |
1440 | 301 | // LCOV_EXCL_STOP | ||
1441 | 283 | }; | 302 | }; |
1442 | 284 | return QtConcurrent::run(move); | 303 | return QtConcurrent::run(move); |
1443 | 285 | } | 304 | } |
1444 | 286 | 305 | ||
1445 | 287 | QFuture<QVector<Folder::SPtr>> ItemImpl::parents() const | 306 | QFuture<QVector<Folder::SPtr>> ItemImpl::parents() const |
1446 | 288 | { | 307 | { |
1448 | 289 | lock_guard<mutex> guard(mutex_); | 308 | lock_guard<decltype(mutex_)> guard(mutex_); |
1449 | 290 | 309 | ||
1450 | 291 | QFutureInterface<QVector<Folder::SPtr>> qf; | 310 | QFutureInterface<QVector<Folder::SPtr>> qf; |
1451 | 292 | if (deleted_) | 311 | if (deleted_) |
1452 | 293 | { | 312 | { |
1453 | 294 | return make_exceptional_future<QVector<Folder::SPtr>>(deleted_ex("Item::parents()")); | 313 | return make_exceptional_future<QVector<Folder::SPtr>>(deleted_ex("Item::parents()")); |
1454 | 295 | } | 314 | } |
1457 | 296 | 315 | auto root = get_root(); | |
1456 | 297 | Root::SPtr root = root_.lock(); | ||
1458 | 298 | if (!root) | 316 | if (!root) |
1459 | 299 | { | 317 | { |
1460 | 300 | return make_exceptional_future<QVector<Folder::SPtr>>(RuntimeDestroyedException("Item::parents()")); | 318 | return make_exceptional_future<QVector<Folder::SPtr>>(RuntimeDestroyedException("Item::parents()")); |
1461 | @@ -309,7 +327,7 @@ | |||
1462 | 309 | QVector<Folder::SPtr> results; | 327 | QVector<Folder::SPtr> results; |
1463 | 310 | if (parent_path != root->native_identity()) | 328 | if (parent_path != root->native_identity()) |
1464 | 311 | { | 329 | { |
1466 | 312 | results.append(FolderImpl::make_folder(parent_path, root_)); | 330 | results.append(FolderImpl::make_folder(parent_path, root)); |
1467 | 313 | } | 331 | } |
1468 | 314 | else | 332 | else |
1469 | 315 | { | 333 | { |
1470 | @@ -320,12 +338,16 @@ | |||
1471 | 320 | 338 | ||
1472 | 321 | QVector<QString> ItemImpl::parent_ids() const | 339 | QVector<QString> ItemImpl::parent_ids() const |
1473 | 322 | { | 340 | { |
1475 | 323 | lock_guard<mutex> guard(mutex_); | 341 | lock_guard<decltype(mutex_)> guard(mutex_); |
1476 | 324 | 342 | ||
1477 | 325 | if (deleted_) | 343 | if (deleted_) |
1478 | 326 | { | 344 | { |
1479 | 327 | throw deleted_ex("Item::parent_ids()"); | 345 | throw deleted_ex("Item::parent_ids()"); |
1480 | 328 | } | 346 | } |
1481 | 347 | if (!get_root()) | ||
1482 | 348 | { | ||
1483 | 349 | throw RuntimeDestroyedException("Item::parent_ids()"); | ||
1484 | 350 | } | ||
1485 | 329 | 351 | ||
1486 | 330 | using namespace boost::filesystem; | 352 | using namespace boost::filesystem; |
1487 | 331 | 353 | ||
1488 | @@ -343,33 +365,63 @@ | |||
1489 | 343 | auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive. | 365 | auto This = dynamic_pointer_cast<ItemImpl>(shared_from_this()); // Keep this item alive while the lambda is alive. |
1490 | 344 | auto destroy = [This]() | 366 | auto destroy = [This]() |
1491 | 345 | { | 367 | { |
1493 | 346 | lock_guard<mutex> guard(This->mutex_); | 368 | lock_guard<decltype(mutex_)> guard(This->mutex_); |
1494 | 347 | 369 | ||
1495 | 348 | if (This->deleted_) | 370 | if (This->deleted_) |
1496 | 349 | { | 371 | { |
1497 | 350 | throw This->deleted_ex("Item::delete_item()"); | 372 | throw This->deleted_ex("Item::delete_item()"); |
1498 | 351 | } | 373 | } |
1499 | 374 | if (!This->get_root()) | ||
1500 | 375 | { | ||
1501 | 376 | throw RuntimeDestroyedException("Item::delete_item()"); | ||
1502 | 377 | } | ||
1503 | 352 | 378 | ||
1504 | 353 | try | 379 | try |
1505 | 354 | { | 380 | { |
1506 | 355 | boost::filesystem::remove_all(This->native_identity().toStdString()); | 381 | boost::filesystem::remove_all(This->native_identity().toStdString()); |
1507 | 356 | This->deleted_ = true; | 382 | This->deleted_ = true; |
1508 | 357 | } | 383 | } |
1509 | 384 | catch (boost::filesystem::filesystem_error const& e) | ||
1510 | 385 | { | ||
1511 | 386 | throw ResourceException(QString("Item::delete_item(): ") + e.what(), e.code().value()); | ||
1512 | 387 | } | ||
1513 | 388 | // LCOV_EXCL_START | ||
1514 | 358 | catch (std::exception const& e) | 389 | catch (std::exception const& e) |
1515 | 359 | { | 390 | { |
1517 | 360 | throw ResourceException(QString("Item::delete_item(): ") + e.what()); | 391 | throw ResourceException(QString("Item::delete_item(): ") + e.what(), errno); |
1518 | 361 | } | 392 | } |
1519 | 393 | // LCOV_EXCL_STOP | ||
1520 | 362 | }; | 394 | }; |
1521 | 363 | return QtConcurrent::run(destroy); | 395 | return QtConcurrent::run(destroy); |
1522 | 364 | } | 396 | } |
1523 | 365 | 397 | ||
1524 | 366 | QDateTime ItemImpl::creation_time() const | 398 | QDateTime ItemImpl::creation_time() const |
1525 | 367 | { | 399 | { |
1526 | 400 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
1527 | 401 | |||
1528 | 402 | if (deleted_) | ||
1529 | 403 | { | ||
1530 | 404 | throw deleted_ex("Item::creation_time()"); | ||
1531 | 405 | } | ||
1532 | 406 | if (!get_root()) | ||
1533 | 407 | { | ||
1534 | 408 | throw RuntimeDestroyedException("Item::creation_time()"); | ||
1535 | 409 | } | ||
1536 | 368 | return QDateTime(); | 410 | return QDateTime(); |
1537 | 369 | } | 411 | } |
1538 | 370 | 412 | ||
1539 | 371 | MetadataMap ItemImpl::native_metadata() const | 413 | MetadataMap ItemImpl::native_metadata() const |
1540 | 372 | { | 414 | { |
1541 | 415 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
1542 | 416 | |||
1543 | 417 | if (deleted_) | ||
1544 | 418 | { | ||
1545 | 419 | throw deleted_ex("Item::native_metadata()"); | ||
1546 | 420 | } | ||
1547 | 421 | if (!get_root()) | ||
1548 | 422 | { | ||
1549 | 423 | throw RuntimeDestroyedException("Item::native_metadata()"); | ||
1550 | 424 | } | ||
1551 | 373 | return MetadataMap(); | 425 | return MetadataMap(); |
1552 | 374 | } | 426 | } |
1553 | 375 | 427 | ||
1554 | @@ -383,8 +435,8 @@ | |||
1555 | 383 | } | 435 | } |
1556 | 384 | 436 | ||
1557 | 385 | lock(mutex_, other_impl->mutex_); | 437 | lock(mutex_, other_impl->mutex_); |
1560 | 386 | lock_guard<mutex> this_guard(mutex_, std::adopt_lock); | 438 | lock_guard<decltype(mutex_)> this_guard(mutex_, std::adopt_lock); |
1561 | 387 | lock_guard<mutex> other_guard(other_impl->mutex_, adopt_lock); | 439 | lock_guard<decltype(mutex_)> other_guard(other_impl->mutex_, adopt_lock); |
1562 | 388 | 440 | ||
1563 | 389 | if (deleted_ || other_impl->deleted_) | 441 | if (deleted_ || other_impl->deleted_) |
1564 | 390 | { | 442 | { |
1565 | @@ -395,7 +447,7 @@ | |||
1566 | 395 | 447 | ||
1567 | 396 | void ItemImpl::set_timestamps() noexcept | 448 | void ItemImpl::set_timestamps() noexcept |
1568 | 397 | { | 449 | { |
1570 | 398 | lock_guard<mutex> guard(mutex_); | 450 | lock_guard<decltype(mutex_)> guard(mutex_); |
1571 | 399 | 451 | ||
1572 | 400 | string id = identity_.toStdString(); | 452 | string id = identity_.toStdString(); |
1573 | 401 | // Use nano-second resolution for the ETag, if the file system supports it. | 453 | // Use nano-second resolution for the ETag, if the file system supports it. |
1574 | @@ -412,7 +464,7 @@ | |||
1575 | 412 | 464 | ||
1576 | 413 | bool ItemImpl::has_conflict() const noexcept | 465 | bool ItemImpl::has_conflict() const noexcept |
1577 | 414 | { | 466 | { |
1579 | 415 | lock_guard<mutex> guard(mutex_); | 467 | lock_guard<decltype(mutex_)> guard(mutex_); |
1580 | 416 | 468 | ||
1581 | 417 | string id = identity_.toStdString(); | 469 | string id = identity_.toStdString(); |
1582 | 418 | struct stat st; | 470 | struct stat st; |
1583 | @@ -425,11 +477,6 @@ | |||
1584 | 425 | return etag_ != new_etag; | 477 | return etag_ != new_etag; |
1585 | 426 | } | 478 | } |
1586 | 427 | 479 | ||
1587 | 428 | unique_lock<mutex> ItemImpl::get_lock() | ||
1588 | 429 | { | ||
1589 | 430 | return unique_lock<mutex>(mutex_); | ||
1590 | 431 | } | ||
1591 | 432 | |||
1592 | 433 | // Throw if name contains more than one path component. | 480 | // Throw if name contains more than one path component. |
1593 | 434 | // Otherwise, return the relative path for the name. | 481 | // Otherwise, return the relative path for the name. |
1594 | 435 | // This is to make sure that calling, say, create_file() | 482 | // This is to make sure that calling, say, create_file() |
1595 | @@ -467,10 +514,41 @@ | |||
1596 | 467 | 514 | ||
1597 | 468 | DeletedException ItemImpl::deleted_ex(QString const& method) const noexcept | 515 | DeletedException ItemImpl::deleted_ex(QString const& method) const noexcept |
1598 | 469 | { | 516 | { |
1600 | 470 | QString msg = method + ": " + identity_ + " was deleted previously"; | 517 | QString msg = method + ": \"" + identity_ + "\" was deleted previously"; |
1601 | 471 | return DeletedException(msg, identity_, name_); | 518 | return DeletedException(msg, identity_, name_); |
1602 | 472 | } | 519 | } |
1603 | 473 | 520 | ||
1604 | 521 | void ItemImpl::copy_recursively(boost::filesystem::path const& source, boost::filesystem::path const& target) | ||
1605 | 522 | { | ||
1606 | 523 | using namespace boost::filesystem; | ||
1607 | 524 | |||
1608 | 525 | if (is_reserved_path(source)) | ||
1609 | 526 | { | ||
1610 | 527 | return; // Don't copy temporary directories. | ||
1611 | 528 | } | ||
1612 | 529 | |||
1613 | 530 | auto s = status(source); | ||
1614 | 531 | if (is_regular_file(s)) | ||
1615 | 532 | { | ||
1616 | 533 | copy_file(source, target); | ||
1617 | 534 | } | ||
1618 | 535 | else if (is_directory(s)) | ||
1619 | 536 | { | ||
1620 | 537 | copy_directory(source, target); // Poorly named in boost; this creates the target dir without recursion | ||
1621 | 538 | for (directory_iterator it(source); it != directory_iterator(); ++it) | ||
1622 | 539 | { | ||
1623 | 540 | path source_entry = it->path(); | ||
1624 | 541 | path target_entry = target; | ||
1625 | 542 | target_entry /= source_entry.filename(); | ||
1626 | 543 | copy_recursively(source_entry, target_entry); | ||
1627 | 544 | } | ||
1628 | 545 | } | ||
1629 | 546 | else | ||
1630 | 547 | { | ||
1631 | 548 | // Ignore everything that's not a directory or file. | ||
1632 | 549 | } | ||
1633 | 550 | } | ||
1634 | 551 | |||
1635 | 474 | } // namespace local_client | 552 | } // namespace local_client |
1636 | 475 | } // namespace internal | 553 | } // namespace internal |
1637 | 476 | } // namespace client | 554 | } // namespace client |
1638 | 477 | 555 | ||
1639 | === modified file 'src/qt/client/internal/local_client/RootImpl.cpp' | |||
1640 | --- src/qt/client/internal/local_client/RootImpl.cpp 2016-07-15 03:34:00 +0000 | |||
1641 | +++ src/qt/client/internal/local_client/RootImpl.cpp 2016-07-29 05:58:49 +0000 | |||
1642 | @@ -68,27 +68,58 @@ | |||
1643 | 68 | 68 | ||
1644 | 69 | QString RootImpl::name() const | 69 | QString RootImpl::name() const |
1645 | 70 | { | 70 | { |
1646 | 71 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
1647 | 72 | |||
1648 | 73 | if (!get_root()) | ||
1649 | 74 | { | ||
1650 | 75 | throw RuntimeDestroyedException("Root::name()"); | ||
1651 | 76 | } | ||
1652 | 71 | return ""; | 77 | return ""; |
1653 | 72 | } | 78 | } |
1654 | 73 | 79 | ||
1655 | 74 | QFuture<QVector<Folder::SPtr>> RootImpl::parents() const | 80 | QFuture<QVector<Folder::SPtr>> RootImpl::parents() const |
1656 | 75 | { | 81 | { |
1657 | 82 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
1658 | 83 | |||
1659 | 84 | if (!get_root()) | ||
1660 | 85 | { | ||
1661 | 86 | throw RuntimeDestroyedException("Root::parents()"); | ||
1662 | 87 | } | ||
1663 | 76 | return make_ready_future(QVector<Folder::SPtr>()); // For the root, we return an empty vector. | 88 | return make_ready_future(QVector<Folder::SPtr>()); // For the root, we return an empty vector. |
1664 | 77 | } | 89 | } |
1665 | 78 | 90 | ||
1666 | 79 | QVector<QString> RootImpl::parent_ids() const | 91 | QVector<QString> RootImpl::parent_ids() const |
1667 | 80 | { | 92 | { |
1668 | 93 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
1669 | 94 | |||
1670 | 95 | if (!get_root()) | ||
1671 | 96 | { | ||
1672 | 97 | throw RuntimeDestroyedException("Root::parent_ids()"); | ||
1673 | 98 | } | ||
1674 | 81 | return QVector<QString>(); // For the root, we return an empty vector. | 99 | return QVector<QString>(); // For the root, we return an empty vector. |
1675 | 82 | } | 100 | } |
1676 | 83 | 101 | ||
1677 | 84 | QFuture<void> RootImpl::delete_item() | 102 | QFuture<void> RootImpl::delete_item() |
1678 | 85 | { | 103 | { |
1679 | 104 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
1680 | 105 | |||
1681 | 106 | if (!get_root()) | ||
1682 | 107 | { | ||
1683 | 108 | throw RuntimeDestroyedException("Root::delete_item()"); | ||
1684 | 109 | } | ||
1685 | 86 | // Cannot delete root. | 110 | // Cannot delete root. |
1686 | 87 | return make_exceptional_future(LogicException("Root::delete_item(): Cannot delete root folder")); | 111 | return make_exceptional_future(LogicException("Root::delete_item(): Cannot delete root folder")); |
1687 | 88 | } | 112 | } |
1688 | 89 | 113 | ||
1689 | 90 | QFuture<int64_t> RootImpl::free_space_bytes() const | 114 | QFuture<int64_t> RootImpl::free_space_bytes() const |
1690 | 91 | { | 115 | { |
1691 | 116 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
1692 | 117 | |||
1693 | 118 | if (!get_root()) | ||
1694 | 119 | { | ||
1695 | 120 | throw RuntimeDestroyedException("Root::free_space_bytes()"); | ||
1696 | 121 | } | ||
1697 | 122 | |||
1698 | 92 | using namespace boost::filesystem; | 123 | using namespace boost::filesystem; |
1699 | 93 | 124 | ||
1700 | 94 | try | 125 | try |
1701 | @@ -96,14 +127,29 @@ | |||
1702 | 96 | space_info si = space(identity_.toStdString()); | 127 | space_info si = space(identity_.toStdString()); |
1703 | 97 | return make_ready_future<int64_t>(si.available); | 128 | return make_ready_future<int64_t>(si.available); |
1704 | 98 | } | 129 | } |
1705 | 130 | // LCOV_EXCL_START | ||
1706 | 131 | catch (boost::filesystem::filesystem_error const& e) | ||
1707 | 132 | { | ||
1708 | 133 | return make_exceptional_future<int64_t>(ResourceException(QString("Root::free_space_bytes(): ") + e.what(), | ||
1709 | 134 | e.code().value())); | ||
1710 | 135 | } | ||
1711 | 99 | catch (std::exception const& e) | 136 | catch (std::exception const& e) |
1712 | 100 | { | 137 | { |
1714 | 101 | return make_exceptional_future<int64_t>(ResourceException(QString("Root::free_space_bytes(): ") + e.what())); | 138 | return make_exceptional_future<int64_t>(ResourceException(QString("Root::free_space_bytes(): ") + e.what(), |
1715 | 139 | errno)); | ||
1716 | 102 | } | 140 | } |
1717 | 141 | // LCOV_EXCL_STOP | ||
1718 | 103 | } | 142 | } |
1719 | 104 | 143 | ||
1720 | 105 | QFuture<int64_t> RootImpl::used_space_bytes() const | 144 | QFuture<int64_t> RootImpl::used_space_bytes() const |
1721 | 106 | { | 145 | { |
1722 | 146 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
1723 | 147 | |||
1724 | 148 | if (!get_root()) | ||
1725 | 149 | { | ||
1726 | 150 | throw RuntimeDestroyedException("Root::used_space_bytes()"); | ||
1727 | 151 | } | ||
1728 | 152 | |||
1729 | 107 | using namespace boost::filesystem; | 153 | using namespace boost::filesystem; |
1730 | 108 | 154 | ||
1731 | 109 | try | 155 | try |
1732 | @@ -111,14 +157,30 @@ | |||
1733 | 111 | space_info si = space(identity_.toStdString()); | 157 | space_info si = space(identity_.toStdString()); |
1734 | 112 | return make_ready_future<int64_t>(si.capacity - si.available); | 158 | return make_ready_future<int64_t>(si.capacity - si.available); |
1735 | 113 | } | 159 | } |
1736 | 160 | // LCOV_EXCL_START | ||
1737 | 161 | catch (boost::filesystem::filesystem_error const& e) | ||
1738 | 162 | { | ||
1739 | 163 | return make_exceptional_future<int64_t>(ResourceException(QString("Root::used_space_bytes(): ") + e.what(), | ||
1740 | 164 | e.code().value())); | ||
1741 | 165 | } | ||
1742 | 114 | catch (std::exception const& e) | 166 | catch (std::exception const& e) |
1743 | 115 | { | 167 | { |
1745 | 116 | return make_exceptional_future<int64_t>(ResourceException(QString("Root::used_space_bytes(): ") + e.what())); | 168 | return make_exceptional_future<int64_t>(ResourceException(QString("Root::used_space_bytes(): ") + e.what(), |
1746 | 169 | errno)); | ||
1747 | 117 | } | 170 | } |
1748 | 171 | // LCOV_EXCL_STOP | ||
1749 | 118 | } | 172 | } |
1750 | 119 | 173 | ||
1751 | 120 | QFuture<Item::SPtr> RootImpl::get(QString native_identity) const | 174 | QFuture<Item::SPtr> RootImpl::get(QString native_identity) const |
1752 | 121 | { | 175 | { |
1753 | 176 | lock_guard<decltype(mutex_)> guard(mutex_); | ||
1754 | 177 | |||
1755 | 178 | auto root = get_root(); | ||
1756 | 179 | if (!root) | ||
1757 | 180 | { | ||
1758 | 181 | return make_exceptional_future<Item::SPtr>(RuntimeDestroyedException("Root::get()")); | ||
1759 | 182 | } | ||
1760 | 183 | |||
1761 | 122 | using namespace boost::filesystem; | 184 | using namespace boost::filesystem; |
1762 | 123 | 185 | ||
1763 | 124 | QFutureInterface<Item::SPtr> qf; | 186 | QFutureInterface<Item::SPtr> qf; |
1764 | @@ -127,13 +189,13 @@ | |||
1765 | 127 | path id_path = native_identity.toStdString(); | 189 | path id_path = native_identity.toStdString(); |
1766 | 128 | if (!id_path.is_absolute()) | 190 | if (!id_path.is_absolute()) |
1767 | 129 | { | 191 | { |
1770 | 130 | QString msg = "Root::get(): identity must be an absolute path"; | 192 | QString msg = "Root::get(): identity \"" + native_identity + "\" must be an absolute path"; |
1771 | 131 | return make_exceptional_future<Item::SPtr>(InvalidArgumentException(msg)); | 193 | throw InvalidArgumentException(msg); |
1772 | 132 | } | 194 | } |
1773 | 133 | 195 | ||
1774 | 134 | // Make sure that native_identity is contained in or equal to the root path. | 196 | // Make sure that native_identity is contained in or equal to the root path. |
1775 | 135 | id_path = canonical(id_path); | 197 | id_path = canonical(id_path); |
1777 | 136 | auto root_path = path(root()->native_identity().toStdString()); | 198 | auto root_path = path(root->native_identity().toStdString()); |
1778 | 137 | auto id_len = std::distance(id_path.begin(), id_path.end()); | 199 | auto id_len = std::distance(id_path.begin(), id_path.end()); |
1779 | 138 | auto root_len = std::distance(root_path.begin(), root_path.end()); | 200 | auto root_len = std::distance(root_path.begin(), root_path.end()); |
1780 | 139 | if (id_len < root_len || !std::equal(root_path.begin(), root_path.end(), id_path.begin())) | 201 | if (id_len < root_len || !std::equal(root_path.begin(), root_path.end(), id_path.begin())) |
1781 | @@ -141,14 +203,14 @@ | |||
1782 | 141 | // Too few components, or wrong path prefix. Therefore, native_identity can't | 203 | // Too few components, or wrong path prefix. Therefore, native_identity can't |
1783 | 142 | // possibly point at something below the root. | 204 | // possibly point at something below the root. |
1784 | 143 | QString msg = QString("Root::get(): identity \"") + native_identity + "\" points outside the root folder"; | 205 | QString msg = QString("Root::get(): identity \"") + native_identity + "\" points outside the root folder"; |
1786 | 144 | return make_exceptional_future<Item::SPtr>(InvalidArgumentException(msg)); | 206 | throw InvalidArgumentException(msg); |
1787 | 145 | } | 207 | } |
1788 | 146 | 208 | ||
1789 | 147 | // Don't allow reserved files to be found. | 209 | // Don't allow reserved files to be found. |
1790 | 148 | if (is_reserved_path(id_path)) | 210 | if (is_reserved_path(id_path)) |
1791 | 149 | { | 211 | { |
1794 | 150 | QString msg = "Root::get(): no such item: " + native_identity; | 212 | QString msg = "Root::get(): no such item: \"" + native_identity + "\""; |
1795 | 151 | return make_exceptional_future<Item::SPtr>(NotExistsException(msg, native_identity)); | 213 | throw NotExistsException(msg, native_identity); |
1796 | 152 | } | 214 | } |
1797 | 153 | 215 | ||
1798 | 154 | file_status s = status(id_path); | 216 | file_status s = status(id_path); |
1799 | @@ -157,21 +219,31 @@ | |||
1800 | 157 | { | 219 | { |
1801 | 158 | if (id_path == root_path) | 220 | if (id_path == root_path) |
1802 | 159 | { | 221 | { |
1804 | 160 | return make_ready_future<Item::SPtr>(make_root(path, account_)); | 222 | return make_ready_future<Item::SPtr>(make_root(path, account())); |
1805 | 161 | } | 223 | } |
1807 | 162 | return make_ready_future<Item::SPtr>(make_folder(path, root_)); | 224 | return make_ready_future<Item::SPtr>(make_folder(path, root)); |
1808 | 163 | } | 225 | } |
1809 | 164 | if (is_regular_file(s)) | 226 | if (is_regular_file(s)) |
1810 | 165 | { | 227 | { |
1812 | 166 | return make_ready_future<Item::SPtr>(FileImpl::make_file(path, root_)); | 228 | return make_ready_future<Item::SPtr>(FileImpl::make_file(path, root)); |
1813 | 167 | } | 229 | } |
1817 | 168 | QString msg = "Root::get(): no such item: " + native_identity; | 230 | QString msg = "Root::get(): no such item: \"" + native_identity + "\""; |
1818 | 169 | return make_exceptional_future<Item::SPtr>(NotExistsException(msg, native_identity)); | 231 | throw NotExistsException(msg, native_identity); |
1819 | 170 | } | 232 | } |
1820 | 233 | catch (StorageException const& e) | ||
1821 | 234 | { | ||
1822 | 235 | return make_exceptional_future<Item::SPtr>(e); | ||
1823 | 236 | } | ||
1824 | 237 | catch (boost::filesystem::filesystem_error const& e) | ||
1825 | 238 | { | ||
1826 | 239 | return make_exceptional_future<Item::SPtr>(QString("Root::get(): ") + e.what(), e, native_identity); | ||
1827 | 240 | } | ||
1828 | 241 | // LCOV_EXCL_START | ||
1829 | 171 | catch (std::exception const& e) | 242 | catch (std::exception const& e) |
1830 | 172 | { | 243 | { |
1832 | 173 | return make_exceptional_future<Item::SPtr>(ResourceException(QString("Root::get(): ") + e.what())); | 244 | return make_exceptional_future<Item::SPtr>(ResourceException(QString("Root::get(): ") + e.what(), errno)); |
1833 | 174 | } | 245 | } |
1834 | 246 | // LCOV_EXCL_STOP | ||
1835 | 175 | } | 247 | } |
1836 | 176 | 248 | ||
1837 | 177 | Root::SPtr RootImpl::make_root(QString const& identity, std::weak_ptr<Account> const& account) | 249 | Root::SPtr RootImpl::make_root(QString const& identity, std::weak_ptr<Account> const& account) |
1838 | 178 | 250 | ||
1839 | === modified file 'src/qt/client/internal/local_client/RuntimeImpl.cpp' | |||
1840 | --- src/qt/client/internal/local_client/RuntimeImpl.cpp 2016-07-12 02:22:05 +0000 | |||
1841 | +++ src/qt/client/internal/local_client/RuntimeImpl.cpp 2016-07-29 05:58:49 +0000 | |||
1842 | @@ -68,14 +68,19 @@ | |||
1843 | 68 | 68 | ||
1844 | 69 | void RuntimeImpl::shutdown() | 69 | void RuntimeImpl::shutdown() |
1845 | 70 | { | 70 | { |
1847 | 71 | if (destroyed_.exchange(true)) | 71 | if (destroyed_) |
1848 | 72 | { | 72 | { |
1849 | 73 | return; | 73 | return; |
1850 | 74 | } | 74 | } |
1851 | 75 | destroyed_ = true; | ||
1852 | 75 | } | 76 | } |
1853 | 76 | 77 | ||
1854 | 77 | QFuture<QVector<Account::SPtr>> RuntimeImpl::accounts() | 78 | QFuture<QVector<Account::SPtr>> RuntimeImpl::accounts() |
1855 | 78 | { | 79 | { |
1856 | 80 | if (destroyed_) | ||
1857 | 81 | { | ||
1858 | 82 | throw RuntimeDestroyedException("Runtime::accounts()"); | ||
1859 | 83 | } | ||
1860 | 79 | 84 | ||
1861 | 80 | char const* user = g_get_user_name(); | 85 | char const* user = g_get_user_name(); |
1862 | 81 | assert(*user != '\0'); | 86 | assert(*user != '\0'); |
1863 | 82 | 87 | ||
1864 | === modified file 'src/qt/client/internal/local_client/UploaderImpl.cpp' | |||
1865 | --- src/qt/client/internal/local_client/UploaderImpl.cpp 2016-07-26 01:51:26 +0000 | |||
1866 | +++ src/qt/client/internal/local_client/UploaderImpl.cpp 2016-07-29 05:58:49 +0000 | |||
1867 | @@ -93,8 +93,6 @@ | |||
1868 | 93 | // Monitor read socket for ready-to-read, disconnected, and error events. | 93 | // Monitor read socket for ready-to-read, disconnected, and error events. |
1869 | 94 | connect(read_socket_.get(), &QLocalSocket::readyRead, this, &UploadWorker::on_bytes_ready); | 94 | connect(read_socket_.get(), &QLocalSocket::readyRead, this, &UploadWorker::on_bytes_ready); |
1870 | 95 | connect(read_socket_.get(), &QIODevice::readChannelFinished, this, &UploadWorker::on_read_channel_finished); | 95 | connect(read_socket_.get(), &QIODevice::readChannelFinished, this, &UploadWorker::on_read_channel_finished); |
1871 | 96 | connect(read_socket_.get(), static_cast<void(QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), | ||
1872 | 97 | this, &UploadWorker::on_error); | ||
1873 | 98 | 96 | ||
1874 | 99 | using namespace boost::filesystem; | 97 | using namespace boost::filesystem; |
1875 | 100 | 98 | ||
1876 | @@ -114,10 +112,11 @@ | |||
1877 | 114 | tmp_fd_.reset(mkstemp(const_cast<char*>(tmpfile.data()))); | 112 | tmp_fd_.reset(mkstemp(const_cast<char*>(tmpfile.data()))); |
1878 | 115 | if (tmp_fd_.get() == -1) | 113 | if (tmp_fd_.get() == -1) |
1879 | 116 | { | 114 | { |
1880 | 115 | int error_code = errno; | ||
1881 | 117 | worker_initialized_.reportFinished(); | 116 | worker_initialized_.reportFinished(); |
1882 | 118 | QString msg = "cannot create temp file \"" + QString::fromStdString(tmpfile) | 117 | QString msg = "cannot create temp file \"" + QString::fromStdString(tmpfile) |
1883 | 119 | + "\": " + QString::fromStdString(storage::internal::safe_strerror(errno)); | 118 | + "\": " + QString::fromStdString(storage::internal::safe_strerror(errno)); |
1885 | 120 | handle_error(msg); | 119 | handle_error(msg, error_code); |
1886 | 121 | return; | 120 | return; |
1887 | 122 | } | 121 | } |
1888 | 123 | output_file_.reset(new QFile(QString::fromStdString(tmpfile))); | 122 | output_file_.reset(new QFile(QString::fromStdString(tmpfile))); |
1889 | @@ -140,11 +139,6 @@ | |||
1890 | 140 | 139 | ||
1891 | 141 | void UploadWorker::do_finish() | 140 | void UploadWorker::do_finish() |
1892 | 142 | { | 141 | { |
1893 | 143 | if (qf_.future().isFinished()) | ||
1894 | 144 | { | ||
1895 | 145 | return; // Future was set previously, no point in continuing. | ||
1896 | 146 | } | ||
1897 | 147 | |||
1898 | 148 | switch (state_) | 142 | switch (state_) |
1899 | 149 | { | 143 | { |
1900 | 150 | case in_progress: | 144 | case in_progress: |
1901 | @@ -165,8 +159,10 @@ | |||
1902 | 165 | } | 159 | } |
1903 | 166 | case error: | 160 | case error: |
1904 | 167 | { | 161 | { |
1906 | 168 | make_exceptional_future(qf_, ResourceException(error_msg_)); | 162 | // LCOV_EXCL_START |
1907 | 163 | make_exceptional_future(qf_, ResourceException(error_msg_, error_code_)); | ||
1908 | 169 | break; | 164 | break; |
1909 | 165 | // LCOV_EXCL_STOP | ||
1910 | 170 | } | 166 | } |
1911 | 171 | default: | 167 | default: |
1912 | 172 | { | 168 | { |
1913 | @@ -201,14 +197,14 @@ | |||
1914 | 201 | auto bytes_written = output_file_->write(buf); | 197 | auto bytes_written = output_file_->write(buf); |
1915 | 202 | if (bytes_written == -1) | 198 | if (bytes_written == -1) |
1916 | 203 | { | 199 | { |
1918 | 204 | handle_error("socket error: " + output_file_->errorString()); // LCOV_EXCL_LINE | 200 | handle_error("socket error: " + output_file_->errorString(), output_file_->error()); // LCOV_EXCL_LINE |
1919 | 205 | } | 201 | } |
1920 | 206 | else if (bytes_written != buf.size()) | 202 | else if (bytes_written != buf.size()) |
1921 | 207 | { | 203 | { |
1922 | 208 | // LCOV_EXCL_START | 204 | // LCOV_EXCL_START |
1923 | 209 | QString msg = "write error, requested " + QString::number(buf.size()) + " B, but wrote only " | 205 | QString msg = "write error, requested " + QString::number(buf.size()) + " B, but wrote only " |
1924 | 210 | + bytes_written + " B."; | 206 | + bytes_written + " B."; |
1926 | 211 | handle_error(msg); | 207 | handle_error(msg, 0); |
1927 | 212 | // LCOV_EXCL_STOP | 208 | // LCOV_EXCL_STOP |
1928 | 213 | } | 209 | } |
1929 | 214 | } | 210 | } |
1930 | @@ -220,11 +216,6 @@ | |||
1931 | 220 | do_finish(); | 216 | do_finish(); |
1932 | 221 | } | 217 | } |
1933 | 222 | 218 | ||
1934 | 223 | void UploadWorker::on_error() | ||
1935 | 224 | { | ||
1936 | 225 | handle_error(read_socket_->errorString()); | ||
1937 | 226 | } | ||
1938 | 227 | |||
1939 | 228 | void UploadWorker::finalize() | 219 | void UploadWorker::finalize() |
1940 | 229 | { | 220 | { |
1941 | 230 | auto file = file_.lock(); | 221 | auto file = file_.lock(); |
1942 | @@ -259,7 +250,7 @@ | |||
1943 | 259 | state_ = error; | 250 | state_ = error; |
1944 | 260 | QString msg = "Uploader::finish_upload(): cannot close tmp file: " | 251 | QString msg = "Uploader::finish_upload(): cannot close tmp file: " |
1945 | 261 | + QString::fromStdString(storage::internal::safe_strerror(errno)); | 252 | + QString::fromStdString(storage::internal::safe_strerror(errno)); |
1947 | 262 | make_exceptional_future(qf_, ResourceException(msg)); | 253 | make_exceptional_future(qf_, ResourceException(msg, errno)); |
1948 | 263 | return; | 254 | return; |
1949 | 264 | // LCOV_EXCL_STOP | 255 | // LCOV_EXCL_STOP |
1950 | 265 | } | 256 | } |
1951 | @@ -273,7 +264,7 @@ | |||
1952 | 273 | // LCOV_EXCL_START | 264 | // LCOV_EXCL_START |
1953 | 274 | state_ = error; | 265 | state_ = error; |
1954 | 275 | QString msg = "Uploader::finish_upload(): cannot flush output file: " + output_file_->errorString(); | 266 | QString msg = "Uploader::finish_upload(): cannot flush output file: " + output_file_->errorString(); |
1956 | 276 | make_exceptional_future(qf_, ResourceException(msg)); | 267 | make_exceptional_future(qf_, ResourceException(msg, output_file_->error())); |
1957 | 277 | return; | 268 | return; |
1958 | 278 | // LCOV_EXCL_STOP | 269 | // LCOV_EXCL_STOP |
1959 | 279 | } | 270 | } |
1960 | @@ -287,11 +278,12 @@ | |||
1961 | 287 | if (linkat(-1, old_path.c_str(), tmp_fd_.get(), new_path.c_str(), AT_SYMLINK_FOLLOW) == -1) | 278 | if (linkat(-1, old_path.c_str(), tmp_fd_.get(), new_path.c_str(), AT_SYMLINK_FOLLOW) == -1) |
1962 | 288 | { | 279 | { |
1963 | 289 | // LCOV_EXCL_START | 280 | // LCOV_EXCL_START |
1964 | 281 | int error_code = errno; | ||
1965 | 290 | state_ = error; | 282 | state_ = error; |
1966 | 291 | QString msg = "Uploader::finish_upload(): linkat \"" + QString::fromStdString(old_path) | 283 | QString msg = "Uploader::finish_upload(): linkat \"" + QString::fromStdString(old_path) |
1967 | 292 | + "\" to \"" + file->native_identity() + "\" failed: " | 284 | + "\" to \"" + file->native_identity() + "\" failed: " |
1968 | 293 | + QString::fromStdString(storage::internal::safe_strerror(errno)); | 285 | + QString::fromStdString(storage::internal::safe_strerror(errno)); |
1970 | 294 | make_exceptional_future(qf_, ResourceException(msg)); | 286 | make_exceptional_future(qf_, ResourceException(msg, error_code)); |
1971 | 295 | return; | 287 | return; |
1972 | 296 | // LCOV_EXCL_STOP | 288 | // LCOV_EXCL_STOP |
1973 | 297 | } | 289 | } |
1974 | @@ -302,11 +294,12 @@ | |||
1975 | 302 | auto old_path = output_file_->fileName().toStdString(); | 294 | auto old_path = output_file_->fileName().toStdString(); |
1976 | 303 | if (rename(old_path.c_str(), new_path.c_str()) == -1) | 295 | if (rename(old_path.c_str(), new_path.c_str()) == -1) |
1977 | 304 | { | 296 | { |
1978 | 297 | int error_code = errno; | ||
1979 | 305 | state_ = error; | 298 | state_ = error; |
1980 | 306 | QString msg = "Uploader::finish_upload(): rename \"" + QString::fromStdString(old_path) | 299 | QString msg = "Uploader::finish_upload(): rename \"" + QString::fromStdString(old_path) |
1981 | 307 | + "\" to \"" + file->native_identity() + "\" failed: " | 300 | + "\" to \"" + file->native_identity() + "\" failed: " |
1982 | 308 | + QString::fromStdString(storage::internal::safe_strerror(errno)); | 301 | + QString::fromStdString(storage::internal::safe_strerror(errno)); |
1984 | 309 | make_exceptional_future(qf_, ResourceException(msg)); | 302 | make_exceptional_future(qf_, ResourceException(msg, error_code)); |
1985 | 310 | return; | 303 | return; |
1986 | 311 | } | 304 | } |
1987 | 312 | // LCOV_EXCL_STOP | 305 | // LCOV_EXCL_STOP |
1988 | @@ -318,7 +311,8 @@ | |||
1989 | 318 | make_ready_future(qf_, file); | 311 | make_ready_future(qf_, file); |
1990 | 319 | } | 312 | } |
1991 | 320 | 313 | ||
1993 | 321 | void UploadWorker::handle_error(QString const& msg) | 314 | // LCOV_EXCL_START |
1994 | 315 | void UploadWorker::handle_error(QString const& msg, int error_code) | ||
1995 | 322 | { | 316 | { |
1996 | 323 | if (state_ == in_progress) | 317 | if (state_ == in_progress) |
1997 | 324 | { | 318 | { |
1998 | @@ -327,8 +321,10 @@ | |||
1999 | 327 | } | 321 | } |
2000 | 328 | state_ = error; | 322 | state_ = error; |
2001 | 329 | error_msg_ = "Uploader: " + msg; | 323 | error_msg_ = "Uploader: " + msg; |
2002 | 324 | error_code_ = error_code; | ||
2003 | 330 | do_finish(); | 325 | do_finish(); |
2004 | 331 | } | 326 | } |
2005 | 327 | // LCOV_EXCL_STOP | ||
2006 | 332 | 328 | ||
2007 | 333 | UploadThread::UploadThread(UploadWorker* worker) | 329 | UploadThread::UploadThread(UploadWorker* worker) |
2008 | 334 | : worker_(worker) | 330 | : worker_(worker) |
2009 | @@ -357,7 +353,7 @@ | |||
2010 | 357 | // LCOV_EXCL_START | 353 | // LCOV_EXCL_START |
2011 | 358 | QString msg = "Uploader: cannot create socket pair: " | 354 | QString msg = "Uploader: cannot create socket pair: " |
2012 | 359 | + QString::fromStdString(storage::internal::safe_strerror(errno)); | 355 | + QString::fromStdString(storage::internal::safe_strerror(errno)); |
2014 | 360 | make_exceptional_future(qf_, ResourceException(msg)); | 356 | make_exceptional_future(qf_, ResourceException(msg, errno)); |
2015 | 361 | return; | 357 | return; |
2016 | 362 | // LCOV_EXCL_STOP | 358 | // LCOV_EXCL_STOP |
2017 | 363 | } | 359 | } |
2018 | @@ -405,6 +401,7 @@ | |||
2019 | 405 | if (write_socket_->state() == QLocalSocket::ConnectedState) | 401 | if (write_socket_->state() == QLocalSocket::ConnectedState) |
2020 | 406 | { | 402 | { |
2021 | 407 | write_socket_->disconnectFromServer(); | 403 | write_socket_->disconnectFromServer(); |
2022 | 404 | write_socket_->close(); | ||
2023 | 408 | } | 405 | } |
2024 | 409 | return qf_.future(); | 406 | return qf_.future(); |
2025 | 410 | } | 407 | } |
2026 | 411 | 408 | ||
2027 | === modified file 'src/qt/client/internal/remote_client/AccountImpl.cpp' | |||
2028 | --- src/qt/client/internal/remote_client/AccountImpl.cpp 2016-07-27 02:19:17 +0000 | |||
2029 | +++ src/qt/client/internal/remote_client/AccountImpl.cpp 2016-07-29 05:58:49 +0000 | |||
2030 | @@ -65,16 +65,19 @@ | |||
2031 | 65 | 65 | ||
2032 | 66 | QString AccountImpl::owner() const | 66 | QString AccountImpl::owner() const |
2033 | 67 | { | 67 | { |
2034 | 68 | runtime(); // Throws if runtime was destroyed. | ||
2035 | 68 | return owner_; | 69 | return owner_; |
2036 | 69 | } | 70 | } |
2037 | 70 | 71 | ||
2038 | 71 | QString AccountImpl::owner_id() const | 72 | QString AccountImpl::owner_id() const |
2039 | 72 | { | 73 | { |
2040 | 74 | runtime(); // Throws if runtime was destroyed. | ||
2041 | 73 | return owner_id_; | 75 | return owner_id_; |
2042 | 74 | } | 76 | } |
2043 | 75 | 77 | ||
2044 | 76 | QString AccountImpl::description() const | 78 | QString AccountImpl::description() const |
2045 | 77 | { | 79 | { |
2046 | 80 | runtime(); // Throws if runtime was destroyed. | ||
2047 | 78 | return description_; | 81 | return description_; |
2048 | 79 | } | 82 | } |
2049 | 80 | 83 | ||
2050 | @@ -84,6 +87,16 @@ | |||
2051 | 84 | 87 | ||
2052 | 85 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<QVector<Root::SPtr>>& qf) | 88 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<QVector<Root::SPtr>>& qf) |
2053 | 86 | { | 89 | { |
2054 | 90 | try | ||
2055 | 91 | { | ||
2056 | 92 | this->runtime(); | ||
2057 | 93 | } | ||
2058 | 94 | catch (RuntimeDestroyedException const& e) | ||
2059 | 95 | { | ||
2060 | 96 | make_exceptional_future(qf, RuntimeDestroyedException("Account::roots()")); | ||
2061 | 97 | return; | ||
2062 | 98 | } | ||
2063 | 99 | |||
2064 | 87 | QVector<shared_ptr<Root>> roots; | 100 | QVector<shared_ptr<Root>> roots; |
2065 | 88 | auto metadata = reply.value(); | 101 | auto metadata = reply.value(); |
2066 | 89 | for (auto const& md : metadata) | 102 | for (auto const& md : metadata) |
2067 | 90 | 103 | ||
2068 | === modified file 'src/qt/client/internal/remote_client/FileImpl.cpp' | |||
2069 | --- src/qt/client/internal/remote_client/FileImpl.cpp 2016-07-22 01:45:39 +0000 | |||
2070 | +++ src/qt/client/internal/remote_client/FileImpl.cpp 2016-07-29 05:58:49 +0000 | |||
2071 | @@ -52,6 +52,10 @@ | |||
2072 | 52 | { | 52 | { |
2073 | 53 | throw deleted_ex("File::size()"); | 53 | throw deleted_ex("File::size()"); |
2074 | 54 | } | 54 | } |
2075 | 55 | if (!get_root()) | ||
2076 | 56 | { | ||
2077 | 57 | throw RuntimeDestroyedException("File::size()"); | ||
2078 | 58 | } | ||
2079 | 55 | return 0; // TODO | 59 | return 0; // TODO |
2080 | 56 | } | 60 | } |
2081 | 57 | 61 | ||
2082 | @@ -66,18 +70,19 @@ | |||
2083 | 66 | QString msg = "File::create_uploader(): size must be >= 0"; | 70 | QString msg = "File::create_uploader(): size must be >= 0"; |
2084 | 67 | return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); | 71 | return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); |
2085 | 68 | } | 72 | } |
2086 | 73 | if (!get_root()) | ||
2087 | 74 | { | ||
2088 | 75 | return make_exceptional_future<shared_ptr<Uploader>>(RuntimeDestroyedException("File::create_uploader()")); | ||
2089 | 76 | } | ||
2090 | 69 | 77 | ||
2091 | 70 | QString old_etag = policy == ConflictPolicy::overwrite ? "" : md_.etag; | 78 | QString old_etag = policy == ConflictPolicy::overwrite ? "" : md_.etag; |
2092 | 71 | auto prov = provider(); | 79 | auto prov = provider(); |
2093 | 72 | if (!prov) | ||
2094 | 73 | { | ||
2095 | 74 | return make_exceptional_future<shared_ptr<Uploader>>(RuntimeDestroyedException("File::create_uploader")); | ||
2096 | 75 | } | ||
2097 | 76 | auto reply = prov->Update(md_.item_id, size, old_etag); | 80 | auto reply = prov->Update(md_.item_id, size, old_etag); |
2098 | 77 | 81 | ||
2100 | 78 | auto process_reply = [this, size, old_etag, prov](decltype(reply) const& reply, QFutureInterface<std::shared_ptr<Uploader>>& qf) | 82 | auto process_reply = [this, size, old_etag, prov](decltype(reply) const& reply, |
2101 | 83 | QFutureInterface<std::shared_ptr<Uploader>>& qf) | ||
2102 | 79 | { | 84 | { |
2104 | 80 | auto root = root_.lock(); | 85 | auto root = get_root(); |
2105 | 81 | if (!root) | 86 | if (!root) |
2106 | 82 | { | 87 | { |
2107 | 83 | make_exceptional_future<shared_ptr<Uploader>>(RuntimeDestroyedException("File::create_uploader()")); | 88 | make_exceptional_future<shared_ptr<Uploader>>(RuntimeDestroyedException("File::create_uploader()")); |
2108 | @@ -107,17 +112,24 @@ | |||
2109 | 107 | { | 112 | { |
2110 | 108 | return make_exceptional_future<shared_ptr<Downloader>>(deleted_ex("File::create_downloader()")); | 113 | return make_exceptional_future<shared_ptr<Downloader>>(deleted_ex("File::create_downloader()")); |
2111 | 109 | } | 114 | } |
2112 | 115 | if (!get_root()) | ||
2113 | 116 | { | ||
2114 | 117 | return make_exceptional_future<shared_ptr<Downloader>>(RuntimeDestroyedException("File::create_downloader()")); | ||
2115 | 118 | } | ||
2116 | 110 | 119 | ||
2117 | 111 | auto prov = provider(); | 120 | auto prov = provider(); |
2118 | 112 | if (!prov) | ||
2119 | 113 | { | ||
2120 | 114 | return make_exceptional_future<shared_ptr<Downloader>>(RuntimeDestroyedException("File::create_downloader")); | ||
2121 | 115 | } | ||
2122 | 116 | auto reply = prov->Download(md_.item_id); | 121 | auto reply = prov->Download(md_.item_id); |
2123 | 117 | 122 | ||
2124 | 118 | auto process_reply = [this, prov](QDBusPendingReply<QString, QDBusUnixFileDescriptor> const& reply, | 123 | auto process_reply = [this, prov](QDBusPendingReply<QString, QDBusUnixFileDescriptor> const& reply, |
2125 | 119 | QFutureInterface<std::shared_ptr<Downloader>>& qf) | 124 | QFutureInterface<std::shared_ptr<Downloader>>& qf) |
2126 | 120 | { | 125 | { |
2127 | 126 | auto root = get_root(); | ||
2128 | 127 | if (!root) | ||
2129 | 128 | { | ||
2130 | 129 | make_exceptional_future<shared_ptr<Uploader>>(RuntimeDestroyedException("File::create_downloader()")); | ||
2131 | 130 | return; | ||
2132 | 131 | } | ||
2133 | 132 | |||
2134 | 121 | auto download_id = reply.argumentAt<0>(); | 133 | auto download_id = reply.argumentAt<0>(); |
2135 | 122 | auto fd = reply.argumentAt<1>(); | 134 | auto fd = reply.argumentAt<1>(); |
2136 | 123 | if (fd.fileDescriptor() < 0) | 135 | if (fd.fileDescriptor() < 0) |
2137 | 124 | 136 | ||
2138 | === modified file 'src/qt/client/internal/remote_client/FolderImpl.cpp' | |||
2139 | --- src/qt/client/internal/remote_client/FolderImpl.cpp 2016-07-27 02:19:17 +0000 | |||
2140 | +++ src/qt/client/internal/remote_client/FolderImpl.cpp 2016-07-29 05:58:49 +0000 | |||
2141 | @@ -61,6 +61,10 @@ | |||
2142 | 61 | { | 61 | { |
2143 | 62 | return make_exceptional_future<QVector<shared_ptr<Item>>>(deleted_ex("Folder::list()")); | 62 | return make_exceptional_future<QVector<shared_ptr<Item>>>(deleted_ex("Folder::list()")); |
2144 | 63 | } | 63 | } |
2145 | 64 | if (!get_root()) | ||
2146 | 65 | { | ||
2147 | 66 | return make_exceptional_future<QVector<shared_ptr<Item>>>(RuntimeDestroyedException("Folder::list()")); | ||
2148 | 67 | } | ||
2149 | 64 | 68 | ||
2150 | 65 | auto prov = provider(); | 69 | auto prov = provider(); |
2151 | 66 | if (!prov) | 70 | if (!prov) |
2152 | @@ -74,7 +78,7 @@ | |||
2153 | 74 | function<void(decltype(reply) const&, QFutureInterface<QVector<shared_ptr<Item>>>&)> process_reply | 78 | function<void(decltype(reply) const&, QFutureInterface<QVector<shared_ptr<Item>>>&)> process_reply |
2154 | 75 | = [this, prov, &process_reply](decltype(reply) const& reply, QFutureInterface<QVector<shared_ptr<Item>>>& qf) | 79 | = [this, prov, &process_reply](decltype(reply) const& reply, QFutureInterface<QVector<shared_ptr<Item>>>& qf) |
2155 | 76 | { | 80 | { |
2157 | 77 | auto root = root_.lock(); | 81 | auto root = get_root(); |
2158 | 78 | if (!root) | 82 | if (!root) |
2159 | 79 | { | 83 | { |
2160 | 80 | make_exceptional_future(qf, RuntimeDestroyedException("Folder::list()")); | 84 | make_exceptional_future(qf, RuntimeDestroyedException("Folder::list()")); |
2161 | @@ -117,17 +121,17 @@ | |||
2162 | 117 | { | 121 | { |
2163 | 118 | return make_exceptional_future<QVector<shared_ptr<Item>>>(deleted_ex("Folder::lookup()")); | 122 | return make_exceptional_future<QVector<shared_ptr<Item>>>(deleted_ex("Folder::lookup()")); |
2164 | 119 | } | 123 | } |
2168 | 120 | 124 | if (!get_root()) | |
2166 | 121 | auto prov = provider(); | ||
2167 | 122 | if (!prov) | ||
2169 | 123 | { | 125 | { |
2170 | 124 | return make_exceptional_future<QVector<shared_ptr<Item>>>(RuntimeDestroyedException("Folder::lookup()")); | 126 | return make_exceptional_future<QVector<shared_ptr<Item>>>(RuntimeDestroyedException("Folder::lookup()")); |
2171 | 125 | } | 127 | } |
2172 | 128 | |||
2173 | 129 | auto prov = provider(); | ||
2174 | 126 | auto reply = prov->Lookup(md_.item_id, name); | 130 | auto reply = prov->Lookup(md_.item_id, name); |
2175 | 127 | 131 | ||
2176 | 128 | auto process_reply = [this, name](decltype(reply) const& reply, QFutureInterface<QVector<shared_ptr<Item>>>& qf) | 132 | auto process_reply = [this, name](decltype(reply) const& reply, QFutureInterface<QVector<shared_ptr<Item>>>& qf) |
2177 | 129 | { | 133 | { |
2179 | 130 | auto root = root_.lock(); | 134 | auto root = get_root(); |
2180 | 131 | if (!root) | 135 | if (!root) |
2181 | 132 | { | 136 | { |
2182 | 133 | make_exceptional_future(qf, RuntimeDestroyedException("Folder::lookup()")); | 137 | make_exceptional_future(qf, RuntimeDestroyedException("Folder::lookup()")); |
2183 | @@ -163,17 +167,17 @@ | |||
2184 | 163 | { | 167 | { |
2185 | 164 | return make_exceptional_future<shared_ptr<Folder>>(deleted_ex("Folder::create_folder()")); | 168 | return make_exceptional_future<shared_ptr<Folder>>(deleted_ex("Folder::create_folder()")); |
2186 | 165 | } | 169 | } |
2190 | 166 | 170 | if (!get_root()) | |
2188 | 167 | auto prov = provider(); | ||
2189 | 168 | if (!prov) | ||
2191 | 169 | { | 171 | { |
2192 | 170 | return make_exceptional_future<shared_ptr<Folder>>(RuntimeDestroyedException("Folder::create_folder()")); | 172 | return make_exceptional_future<shared_ptr<Folder>>(RuntimeDestroyedException("Folder::create_folder()")); |
2193 | 171 | } | 173 | } |
2194 | 174 | |||
2195 | 175 | auto prov = provider(); | ||
2196 | 172 | auto reply = prov->CreateFolder(md_.item_id, name); | 176 | auto reply = prov->CreateFolder(md_.item_id, name); |
2197 | 173 | 177 | ||
2198 | 174 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<shared_ptr<Folder>>& qf) | 178 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<shared_ptr<Folder>>& qf) |
2199 | 175 | { | 179 | { |
2201 | 176 | auto root = root_.lock(); | 180 | auto root = get_root(); |
2202 | 177 | if (!root) | 181 | if (!root) |
2203 | 178 | { | 182 | { |
2204 | 179 | make_exceptional_future(qf, RuntimeDestroyedException("Folder::create_folder()")); | 183 | make_exceptional_future(qf, RuntimeDestroyedException("Folder::create_folder()")); |
2205 | @@ -208,17 +212,17 @@ | |||
2206 | 208 | QString msg = "Folder::create_file(): size must be >= 0"; | 212 | QString msg = "Folder::create_file(): size must be >= 0"; |
2207 | 209 | return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); | 213 | return make_exceptional_future<shared_ptr<Uploader>>(InvalidArgumentException(msg)); |
2208 | 210 | } | 214 | } |
2212 | 211 | 215 | if (!get_root()) | |
2210 | 212 | auto prov = provider(); | ||
2211 | 213 | if (!prov) | ||
2213 | 214 | { | 216 | { |
2214 | 215 | return make_exceptional_future<shared_ptr<Uploader>>(RuntimeDestroyedException("Folder::create_file()")); | 217 | return make_exceptional_future<shared_ptr<Uploader>>(RuntimeDestroyedException("Folder::create_file()")); |
2215 | 216 | } | 218 | } |
2216 | 217 | 219 | ||
2217 | 220 | auto prov = provider(); | ||
2218 | 218 | auto reply = prov->CreateFile(md_.item_id, name, size, "application/octet-stream", false); | 221 | auto reply = prov->CreateFile(md_.item_id, name, size, "application/octet-stream", false); |
2219 | 222 | |||
2220 | 219 | auto process_reply = [this, size](decltype(reply) const& reply, QFutureInterface<shared_ptr<Uploader>>& qf) | 223 | auto process_reply = [this, size](decltype(reply) const& reply, QFutureInterface<shared_ptr<Uploader>>& qf) |
2221 | 220 | { | 224 | { |
2223 | 221 | auto root = root_.lock(); | 225 | auto root = get_root(); |
2224 | 222 | if (!root) | 226 | if (!root) |
2225 | 223 | { | 227 | { |
2226 | 224 | make_exceptional_future(qf, RuntimeDestroyedException("Folder::create_file()")); | 228 | make_exceptional_future(qf, RuntimeDestroyedException("Folder::create_file()")); |
2227 | 225 | 229 | ||
2228 | === modified file 'src/qt/client/internal/remote_client/ItemImpl.cpp' | |||
2229 | --- src/qt/client/internal/remote_client/ItemImpl.cpp 2016-07-27 02:19:17 +0000 | |||
2230 | +++ src/qt/client/internal/remote_client/ItemImpl.cpp 2016-07-29 05:58:49 +0000 | |||
2231 | @@ -54,6 +54,10 @@ | |||
2232 | 54 | { | 54 | { |
2233 | 55 | throw deleted_ex("Item::name()"); | 55 | throw deleted_ex("Item::name()"); |
2234 | 56 | } | 56 | } |
2235 | 57 | if (!get_root()) | ||
2236 | 58 | { | ||
2237 | 59 | throw RuntimeDestroyedException("Item::name()"); | ||
2238 | 60 | } | ||
2239 | 57 | return md_.name; | 61 | return md_.name; |
2240 | 58 | } | 62 | } |
2241 | 59 | 63 | ||
2242 | @@ -63,6 +67,10 @@ | |||
2243 | 63 | { | 67 | { |
2244 | 64 | throw deleted_ex("Item::etag()"); | 68 | throw deleted_ex("Item::etag()"); |
2245 | 65 | } | 69 | } |
2246 | 70 | if (!get_root()) | ||
2247 | 71 | { | ||
2248 | 72 | throw RuntimeDestroyedException("Item::etag()"); | ||
2249 | 73 | } | ||
2250 | 66 | return md_.etag; | 74 | return md_.etag; |
2251 | 67 | } | 75 | } |
2252 | 68 | 76 | ||
2253 | @@ -72,6 +80,10 @@ | |||
2254 | 72 | { | 80 | { |
2255 | 73 | throw deleted_ex("Item::metadata()"); | 81 | throw deleted_ex("Item::metadata()"); |
2256 | 74 | } | 82 | } |
2257 | 83 | if (!get_root()) | ||
2258 | 84 | { | ||
2259 | 85 | throw RuntimeDestroyedException("Item::metadata()"); | ||
2260 | 86 | } | ||
2261 | 75 | // TODO: need to agree on metadata representation | 87 | // TODO: need to agree on metadata representation |
2262 | 76 | return QVariantMap(); | 88 | return QVariantMap(); |
2263 | 77 | } | 89 | } |
2264 | @@ -82,6 +94,10 @@ | |||
2265 | 82 | { | 94 | { |
2266 | 83 | throw deleted_ex("Item::last_modified_time()"); | 95 | throw deleted_ex("Item::last_modified_time()"); |
2267 | 84 | } | 96 | } |
2268 | 97 | if (!get_root()) | ||
2269 | 98 | { | ||
2270 | 99 | throw RuntimeDestroyedException("Item::last_modified_time()"); | ||
2271 | 100 | } | ||
2272 | 85 | // TODO: need to agree on metadata representation | 101 | // TODO: need to agree on metadata representation |
2273 | 86 | return QDateTime(); | 102 | return QDateTime(); |
2274 | 87 | } | 103 | } |
2275 | @@ -92,17 +108,17 @@ | |||
2276 | 92 | { | 108 | { |
2277 | 93 | return make_exceptional_future<shared_ptr<Item>>(deleted_ex("Item::copy()")); | 109 | return make_exceptional_future<shared_ptr<Item>>(deleted_ex("Item::copy()")); |
2278 | 94 | } | 110 | } |
2279 | 111 | if (!get_root()) | ||
2280 | 112 | { | ||
2281 | 113 | return make_exceptional_future<shared_ptr<Item>>(RuntimeDestroyedException("Item::copy()")); | ||
2282 | 114 | } | ||
2283 | 95 | 115 | ||
2284 | 96 | auto prov = provider(); | 116 | auto prov = provider(); |
2285 | 97 | if (!prov) | ||
2286 | 98 | { | ||
2287 | 99 | return make_exceptional_future<shared_ptr<Item>>(RuntimeDestroyedException("Item::copy()")); | ||
2288 | 100 | } | ||
2289 | 101 | auto reply = prov->Copy(md_.item_id, new_parent->native_identity(), new_name); | 117 | auto reply = prov->Copy(md_.item_id, new_parent->native_identity(), new_name); |
2290 | 102 | 118 | ||
2291 | 103 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<std::shared_ptr<Item>>& qf) | 119 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<std::shared_ptr<Item>>& qf) |
2292 | 104 | { | 120 | { |
2294 | 105 | auto root = root_.lock(); | 121 | auto root = get_root(); |
2295 | 106 | if (!root) | 122 | if (!root) |
2296 | 107 | { | 123 | { |
2297 | 108 | make_exceptional_future(qf, RuntimeDestroyedException("Item::copy()")); | 124 | make_exceptional_future(qf, RuntimeDestroyedException("Item::copy()")); |
2298 | @@ -132,6 +148,10 @@ | |||
2299 | 132 | { | 148 | { |
2300 | 133 | return make_exceptional_future<shared_ptr<Item>>(deleted_ex("Item::move()")); | 149 | return make_exceptional_future<shared_ptr<Item>>(deleted_ex("Item::move()")); |
2301 | 134 | } | 150 | } |
2302 | 151 | if (!get_root()) | ||
2303 | 152 | { | ||
2304 | 153 | return make_exceptional_future<shared_ptr<Item>>(RuntimeDestroyedException("Item::copy()")); | ||
2305 | 154 | } | ||
2306 | 135 | 155 | ||
2307 | 136 | auto prov = provider(); | 156 | auto prov = provider(); |
2308 | 137 | if (!prov) | 157 | if (!prov) |
2309 | @@ -142,10 +162,10 @@ | |||
2310 | 142 | 162 | ||
2311 | 143 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<std::shared_ptr<Item>>& qf) | 163 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<std::shared_ptr<Item>>& qf) |
2312 | 144 | { | 164 | { |
2314 | 145 | auto root = root_.lock(); | 165 | auto root = get_root(); |
2315 | 146 | if (!root) | 166 | if (!root) |
2316 | 147 | { | 167 | { |
2318 | 148 | make_exceptional_future(qf, RuntimeDestroyedException("Item::copy()")); | 168 | make_exceptional_future(qf, RuntimeDestroyedException("Item::move()")); |
2319 | 149 | return; | 169 | return; |
2320 | 150 | } | 170 | } |
2321 | 151 | 171 | ||
2322 | @@ -170,6 +190,10 @@ | |||
2323 | 170 | { | 190 | { |
2324 | 171 | return make_exceptional_future<QVector<Folder::SPtr>>(deleted_ex("Item::parents()")); | 191 | return make_exceptional_future<QVector<Folder::SPtr>>(deleted_ex("Item::parents()")); |
2325 | 172 | } | 192 | } |
2326 | 193 | if (!get_root()) | ||
2327 | 194 | { | ||
2328 | 195 | return make_exceptional_future<QVector<Folder::SPtr>>(RuntimeDestroyedException("Item::parents()")); | ||
2329 | 196 | } | ||
2330 | 173 | // TODO, need different metadata representation, affects xml | 197 | // TODO, need different metadata representation, affects xml |
2331 | 174 | return QFuture<QVector<Folder::SPtr>>(); | 198 | return QFuture<QVector<Folder::SPtr>>(); |
2332 | 175 | } | 199 | } |
2333 | @@ -180,6 +204,10 @@ | |||
2334 | 180 | { | 204 | { |
2335 | 181 | throw deleted_ex("Item::parent_ids()"); | 205 | throw deleted_ex("Item::parent_ids()"); |
2336 | 182 | } | 206 | } |
2337 | 207 | if (!get_root()) | ||
2338 | 208 | { | ||
2339 | 209 | RuntimeDestroyedException("Item::parent_ids()"); | ||
2340 | 210 | } | ||
2341 | 183 | // TODO, need different metadata representation, affects xml | 211 | // TODO, need different metadata representation, affects xml |
2342 | 184 | return QVector<QString>(); | 212 | return QVector<QString>(); |
2343 | 185 | } | 213 | } |
2344 | @@ -190,12 +218,12 @@ | |||
2345 | 190 | { | 218 | { |
2346 | 191 | return make_exceptional_future(deleted_ex("Item::delete_item()")); | 219 | return make_exceptional_future(deleted_ex("Item::delete_item()")); |
2347 | 192 | } | 220 | } |
2348 | 221 | if (!get_root()) | ||
2349 | 222 | { | ||
2350 | 223 | return make_exceptional_future(RuntimeDestroyedException("Item::parents()")); | ||
2351 | 224 | } | ||
2352 | 193 | 225 | ||
2353 | 194 | auto prov = provider(); | 226 | auto prov = provider(); |
2354 | 195 | if (!prov) | ||
2355 | 196 | { | ||
2356 | 197 | return make_exceptional_future(RuntimeDestroyedException("Item::delete_item()")); | ||
2357 | 198 | } | ||
2358 | 199 | auto reply = prov->Delete(md_.item_id); | 227 | auto reply = prov->Delete(md_.item_id); |
2359 | 200 | 228 | ||
2360 | 201 | auto process_reply = [this](decltype(reply) const&, QFutureInterface<void>& qf) | 229 | auto process_reply = [this](decltype(reply) const&, QFutureInterface<void>& qf) |
2361 | 202 | 230 | ||
2362 | === modified file 'src/qt/client/internal/remote_client/RootImpl.cpp' | |||
2363 | --- src/qt/client/internal/remote_client/RootImpl.cpp 2016-07-27 02:19:17 +0000 | |||
2364 | +++ src/qt/client/internal/remote_client/RootImpl.cpp 2016-07-29 05:58:49 +0000 | |||
2365 | @@ -50,45 +50,70 @@ | |||
2366 | 50 | 50 | ||
2367 | 51 | QFuture<QVector<Folder::SPtr>> RootImpl::parents() const | 51 | QFuture<QVector<Folder::SPtr>> RootImpl::parents() const |
2368 | 52 | { | 52 | { |
2369 | 53 | if (!get_root()) | ||
2370 | 54 | { | ||
2371 | 55 | return make_exceptional_future<QVector<Folder::SPtr>>(RuntimeDestroyedException("Root::parents()")); | ||
2372 | 56 | } | ||
2373 | 53 | return make_ready_future(QVector<Folder::SPtr>()); // For the root, we return an empty vector. | 57 | return make_ready_future(QVector<Folder::SPtr>()); // For the root, we return an empty vector. |
2374 | 54 | } | 58 | } |
2375 | 55 | 59 | ||
2376 | 56 | QVector<QString> RootImpl::parent_ids() const | 60 | QVector<QString> RootImpl::parent_ids() const |
2377 | 57 | { | 61 | { |
2378 | 62 | if (!get_root()) | ||
2379 | 63 | { | ||
2380 | 64 | return make_exceptional_future<QVector<QString>>(RuntimeDestroyedException("Root::parent_ids()")); | ||
2381 | 65 | } | ||
2382 | 58 | return QVector<QString>(); // For the root, we return an empty vector. | 66 | return QVector<QString>(); // For the root, we return an empty vector. |
2383 | 59 | } | 67 | } |
2384 | 60 | 68 | ||
2385 | 61 | QFuture<void> RootImpl::delete_item() | 69 | QFuture<void> RootImpl::delete_item() |
2386 | 62 | { | 70 | { |
2387 | 71 | if (!get_root()) | ||
2388 | 72 | { | ||
2389 | 73 | return make_exceptional_future(RuntimeDestroyedException("Root::delete_item()")); | ||
2390 | 74 | } | ||
2391 | 63 | // Cannot delete root. | 75 | // Cannot delete root. |
2392 | 64 | return make_exceptional_future(LogicException("Root::delete_item(): root item cannot be deleted")); | 76 | return make_exceptional_future(LogicException("Root::delete_item(): root item cannot be deleted")); |
2393 | 65 | } | 77 | } |
2394 | 66 | 78 | ||
2395 | 67 | QFuture<int64_t> RootImpl::free_space_bytes() const | 79 | QFuture<int64_t> RootImpl::free_space_bytes() const |
2396 | 68 | { | 80 | { |
2397 | 81 | if (!get_root()) | ||
2398 | 82 | { | ||
2399 | 83 | return make_exceptional_future<int64_t>(RuntimeDestroyedException("Root::free_space_bytes()")); | ||
2400 | 84 | } | ||
2401 | 69 | // TODO, need to refresh metadata here instead. | 85 | // TODO, need to refresh metadata here instead. |
2402 | 70 | return make_ready_future(int64_t(1)); | 86 | return make_ready_future(int64_t(1)); |
2403 | 71 | } | 87 | } |
2404 | 72 | 88 | ||
2405 | 73 | QFuture<int64_t> RootImpl::used_space_bytes() const | 89 | QFuture<int64_t> RootImpl::used_space_bytes() const |
2406 | 74 | { | 90 | { |
2407 | 91 | if (!get_root()) | ||
2408 | 92 | { | ||
2409 | 93 | return make_exceptional_future<int64_t>(RuntimeDestroyedException("Root::used_space_bytes()")); | ||
2410 | 94 | } | ||
2411 | 75 | // TODO, need to refresh metadata here instead. | 95 | // TODO, need to refresh metadata here instead. |
2412 | 76 | return make_ready_future(int64_t(1)); | 96 | return make_ready_future(int64_t(1)); |
2413 | 77 | } | 97 | } |
2414 | 78 | 98 | ||
2415 | 79 | QFuture<Item::SPtr> RootImpl::get(QString native_identity) const | 99 | QFuture<Item::SPtr> RootImpl::get(QString native_identity) const |
2416 | 80 | { | 100 | { |
2417 | 101 | if (!get_root()) | ||
2418 | 102 | { | ||
2419 | 103 | return make_exceptional_future<Item::SPtr>(RuntimeDestroyedException("Root::get()")); | ||
2420 | 104 | } | ||
2421 | 105 | |||
2422 | 81 | auto prov = provider(); | 106 | auto prov = provider(); |
2423 | 82 | if (!prov) | ||
2424 | 83 | { | ||
2425 | 84 | return make_exceptional_future<Item::SPtr>(RuntimeDestroyedException("Root::get()")); | ||
2426 | 85 | } | ||
2427 | 86 | auto reply = prov->Metadata(native_identity); | 107 | auto reply = prov->Metadata(native_identity); |
2428 | 87 | 108 | ||
2429 | 88 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<Item::SPtr>& qf) | 109 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<Item::SPtr>& qf) |
2430 | 89 | { | 110 | { |
2433 | 90 | auto account = account_.lock(); | 111 | shared_ptr<Account> acc; |
2434 | 91 | if (!account) | 112 | try |
2435 | 113 | { | ||
2436 | 114 | acc = account(); | ||
2437 | 115 | } | ||
2438 | 116 | catch (RuntimeDestroyedException const&) | ||
2439 | 92 | { | 117 | { |
2440 | 93 | make_exceptional_future<Item::SPtr>(qf, RuntimeDestroyedException("Root::get()")); | 118 | make_exceptional_future<Item::SPtr>(qf, RuntimeDestroyedException("Root::get()")); |
2441 | 94 | return; | 119 | return; |
2442 | @@ -98,11 +123,11 @@ | |||
2443 | 98 | Item::SPtr item; | 123 | Item::SPtr item; |
2444 | 99 | if (md.type == ItemType::root) | 124 | if (md.type == ItemType::root) |
2445 | 100 | { | 125 | { |
2447 | 101 | item = make_root(md, account); | 126 | item = make_root(md, acc); |
2448 | 102 | } | 127 | } |
2449 | 103 | else | 128 | else |
2450 | 104 | { | 129 | { |
2452 | 105 | assert(root_.lock()); // Account owns the root, so it can't go away. | 130 | // acc owns the root, so the root weak_ptr is guaranteed to be lockable. |
2453 | 106 | item = ItemImpl::make_item(md, root_); | 131 | item = ItemImpl::make_item(md, root_); |
2454 | 107 | } | 132 | } |
2455 | 108 | make_ready_future(qf, item); | 133 | make_ready_future(qf, item); |
2456 | 109 | 134 | ||
2457 | === modified file 'src/qt/client/internal/remote_client/RuntimeImpl.cpp' | |||
2458 | --- src/qt/client/internal/remote_client/RuntimeImpl.cpp 2016-07-22 00:17:24 +0000 | |||
2459 | +++ src/qt/client/internal/remote_client/RuntimeImpl.cpp 2016-07-29 05:58:49 +0000 | |||
2460 | @@ -19,7 +19,6 @@ | |||
2461 | 19 | #include <unity/storage/qt/client/internal/remote_client/RuntimeImpl.h> | 19 | #include <unity/storage/qt/client/internal/remote_client/RuntimeImpl.h> |
2462 | 20 | 20 | ||
2463 | 21 | #include <unity/storage/qt/client/Account.h> | 21 | #include <unity/storage/qt/client/Account.h> |
2464 | 22 | #include <unity/storage/qt/client/Exceptions.h> | ||
2465 | 23 | #include <unity/storage/qt/client/internal/make_future.h> | 22 | #include <unity/storage/qt/client/internal/make_future.h> |
2466 | 24 | #include <unity/storage/qt/client/internal/remote_client/AccountImpl.h> | 23 | #include <unity/storage/qt/client/internal/remote_client/AccountImpl.h> |
2467 | 25 | #include <unity/storage/qt/client/internal/remote_client/dbusmarshal.h> | 24 | #include <unity/storage/qt/client/internal/remote_client/dbusmarshal.h> |
2468 | @@ -81,15 +80,21 @@ | |||
2469 | 81 | 80 | ||
2470 | 82 | void RuntimeImpl::shutdown() | 81 | void RuntimeImpl::shutdown() |
2471 | 83 | { | 82 | { |
2473 | 84 | if (destroyed_.exchange(true)) | 83 | if (destroyed_) |
2474 | 85 | { | 84 | { |
2475 | 86 | return; | 85 | return; |
2476 | 87 | } | 86 | } |
2477 | 87 | destroyed_ = true; | ||
2478 | 88 | conn_.disconnectFromBus(conn_.name()); | 88 | conn_.disconnectFromBus(conn_.name()); |
2479 | 89 | } | 89 | } |
2480 | 90 | 90 | ||
2481 | 91 | QFuture<QVector<Account::SPtr>> RuntimeImpl::accounts() | 91 | QFuture<QVector<Account::SPtr>> RuntimeImpl::accounts() |
2482 | 92 | { | 92 | { |
2483 | 93 | if (destroyed_) | ||
2484 | 94 | { | ||
2485 | 95 | return make_exceptional_future(qf_, RuntimeDestroyedException("Runtime::accounts()")); | ||
2486 | 96 | } | ||
2487 | 97 | |||
2488 | 93 | if (!manager_) | 98 | if (!manager_) |
2489 | 94 | { | 99 | { |
2490 | 95 | manager_.reset(new OnlineAccounts::Manager("", conn_)); | 100 | manager_.reset(new OnlineAccounts::Manager("", conn_)); |
2491 | @@ -110,6 +115,12 @@ | |||
2492 | 110 | 115 | ||
2493 | 111 | void RuntimeImpl::manager_ready() | 116 | void RuntimeImpl::manager_ready() |
2494 | 112 | { | 117 | { |
2495 | 118 | if (destroyed_) | ||
2496 | 119 | { | ||
2497 | 120 | make_exceptional_future(qf_, RuntimeDestroyedException("Runtime::accounts()")); | ||
2498 | 121 | return; | ||
2499 | 122 | } | ||
2500 | 123 | |||
2501 | 113 | timer_.stop(); | 124 | timer_.stop(); |
2502 | 114 | try | 125 | try |
2503 | 115 | { | 126 | { |
2504 | @@ -133,7 +144,7 @@ | |||
2505 | 133 | 144 | ||
2506 | 134 | void RuntimeImpl::timeout() | 145 | void RuntimeImpl::timeout() |
2507 | 135 | { | 146 | { |
2509 | 136 | make_exceptional_future(qf_, ResourceException("timeout error")); // TODO | 147 | make_exceptional_future(qf_, ResourceException("Runtime::accounts(): timeout retrieving Online accounts", 0)); |
2510 | 137 | } | 148 | } |
2511 | 138 | 149 | ||
2512 | 139 | } // namespace local_client | 150 | } // namespace local_client |
2513 | 140 | 151 | ||
2514 | === modified file 'src/qt/client/internal/remote_client/UploaderImpl.cpp' | |||
2515 | --- src/qt/client/internal/remote_client/UploaderImpl.cpp 2016-07-22 01:45:39 +0000 | |||
2516 | +++ src/qt/client/internal/remote_client/UploaderImpl.cpp 2016-07-29 05:58:49 +0000 | |||
2517 | @@ -51,14 +51,14 @@ | |||
2518 | 51 | , fd_(fd) | 51 | , fd_(fd) |
2519 | 52 | , size_(size) | 52 | , size_(size) |
2520 | 53 | , old_etag_(old_etag) | 53 | , old_etag_(old_etag) |
2522 | 54 | , root_(root) | 54 | , root_(root.lock()) |
2523 | 55 | , provider_(provider) | 55 | , provider_(provider) |
2524 | 56 | , write_socket_(new QLocalSocket) | 56 | , write_socket_(new QLocalSocket) |
2525 | 57 | { | 57 | { |
2526 | 58 | assert(!upload_id.isEmpty()); | 58 | assert(!upload_id.isEmpty()); |
2527 | 59 | assert(fd.isValid()); | 59 | assert(fd.isValid()); |
2528 | 60 | assert(size >= 0); | 60 | assert(size >= 0); |
2530 | 61 | assert(root_.lock()); | 61 | assert(root_); |
2531 | 62 | assert(provider); | 62 | assert(provider); |
2532 | 63 | assert(fd.isValid()); | 63 | assert(fd.isValid()); |
2533 | 64 | write_socket_->setSocketDescriptor(fd_.fileDescriptor(), QLocalSocket::ConnectedState, QIODevice::WriteOnly); | 64 | write_socket_->setSocketDescriptor(fd_.fileDescriptor(), QLocalSocket::ConnectedState, QIODevice::WriteOnly); |
2534 | @@ -79,13 +79,6 @@ | |||
2535 | 79 | auto reply = provider_->FinishUpload(upload_id_); | 79 | auto reply = provider_->FinishUpload(upload_id_); |
2536 | 80 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<shared_ptr<File>>& qf) | 80 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<shared_ptr<File>>& qf) |
2537 | 81 | { | 81 | { |
2538 | 82 | auto root = root_.lock(); | ||
2539 | 83 | if (!root) | ||
2540 | 84 | { | ||
2541 | 85 | make_exceptional_future(qf, RuntimeDestroyedException("Uploader::finish_upload()")); | ||
2542 | 86 | return; | ||
2543 | 87 | } | ||
2544 | 88 | |||
2545 | 89 | auto md = reply.value(); | 82 | auto md = reply.value(); |
2546 | 90 | if (md.type != ItemType::file) | 83 | if (md.type != ItemType::file) |
2547 | 91 | { | 84 | { |
2548 | @@ -95,7 +88,7 @@ | |||
2549 | 95 | make_exceptional_future(qf, LocalCommsException(msg)); | 88 | make_exceptional_future(qf, LocalCommsException(msg)); |
2550 | 96 | return; | 89 | return; |
2551 | 97 | } | 90 | } |
2553 | 98 | make_ready_future(qf, FileImpl::make_file(md, root)); | 91 | make_ready_future(qf, FileImpl::make_file(md, root_)); |
2554 | 99 | }; | 92 | }; |
2555 | 100 | 93 | ||
2556 | 101 | auto handler = new Handler<shared_ptr<File>>(this, reply, process_reply); | 94 | auto handler = new Handler<shared_ptr<File>>(this, reply, process_reply); |
2557 | 102 | 95 | ||
2558 | === modified file 'tests/local-client/local-client_test.cpp' | |||
2559 | --- tests/local-client/local-client_test.cpp 2016-07-27 02:19:17 +0000 | |||
2560 | +++ tests/local-client/local-client_test.cpp 2016-07-29 05:58:49 +0000 | |||
2561 | @@ -18,7 +18,12 @@ | |||
2562 | 18 | 18 | ||
2563 | 19 | #include <unity/storage/qt/client/client-api.h> | 19 | #include <unity/storage/qt/client/client-api.h> |
2564 | 20 | 20 | ||
2565 | 21 | <<<<<<< TREE | ||
2566 | 21 | #include <unity/storage/qt/client/internal/local_client/boost_filesystem.h> | 22 | #include <unity/storage/qt/client/internal/local_client/boost_filesystem.h> |
2567 | 23 | ======= | ||
2568 | 24 | #include <unity/storage/qt/client/internal/boost_filesystem.h> | ||
2569 | 25 | #include <unity/storage/qt/client/internal/local_client/tmpfile-prefix.h> | ||
2570 | 26 | >>>>>>> MERGE-SOURCE | ||
2571 | 22 | 27 | ||
2572 | 23 | #include <gtest/gtest.h> | 28 | #include <gtest/gtest.h> |
2573 | 24 | #include <QCoreApplication> | 29 | #include <QCoreApplication> |
2574 | @@ -34,6 +39,8 @@ | |||
2575 | 34 | 39 | ||
2576 | 35 | #include <fstream> | 40 | #include <fstream> |
2577 | 36 | 41 | ||
2578 | 42 | Q_DECLARE_METATYPE(QLocalSocket::LocalSocketState) | ||
2579 | 43 | |||
2580 | 37 | using namespace unity::storage; | 44 | using namespace unity::storage; |
2581 | 38 | using namespace unity::storage::qt::client; | 45 | using namespace unity::storage::qt::client; |
2582 | 39 | using namespace std; | 46 | using namespace std; |
2583 | @@ -42,31 +49,61 @@ | |||
2584 | 42 | 49 | ||
2585 | 43 | // Bunch of helper function to reduce the amount of noise in the tests. | 50 | // Bunch of helper function to reduce the amount of noise in the tests. |
2586 | 44 | 51 | ||
2587 | 52 | template<typename T> | ||
2588 | 53 | void wait(T fut) | ||
2589 | 54 | { | ||
2590 | 55 | QFutureWatcher<decltype(fut.result())> w; | ||
2591 | 56 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
2592 | 57 | w.setFuture(fut); | ||
2593 | 58 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
2594 | 59 | } | ||
2595 | 60 | |||
2596 | 61 | template<> | ||
2597 | 62 | void wait(QFuture<void> fut) | ||
2598 | 63 | { | ||
2599 | 64 | QFutureWatcher<void> w; | ||
2600 | 65 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
2601 | 66 | w.setFuture(fut); | ||
2602 | 67 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
2603 | 68 | } | ||
2604 | 69 | |||
2605 | 70 | template <typename T> | ||
2606 | 71 | T call(QFuture<T> fut) | ||
2607 | 72 | { | ||
2608 | 73 | wait(fut); | ||
2609 | 74 | return fut.result(); | ||
2610 | 75 | } | ||
2611 | 76 | |||
2612 | 77 | template <> | ||
2613 | 78 | void call(QFuture<void> fut) | ||
2614 | 79 | { | ||
2615 | 80 | wait(fut); | ||
2616 | 81 | fut.waitForFinished(); | ||
2617 | 82 | } | ||
2618 | 83 | |||
2619 | 45 | Account::SPtr get_account(Runtime::SPtr const& runtime) | 84 | Account::SPtr get_account(Runtime::SPtr const& runtime) |
2620 | 46 | { | 85 | { |
2623 | 47 | auto accounts = runtime->accounts().result(); | 86 | auto accounts = call(runtime->accounts()); |
2622 | 48 | assert(accounts.size() == 1); | ||
2624 | 49 | return accounts[0]; | 87 | return accounts[0]; |
2625 | 50 | } | 88 | } |
2626 | 51 | 89 | ||
2627 | 52 | Root::SPtr get_root(Runtime::SPtr const& runtime) | 90 | Root::SPtr get_root(Runtime::SPtr const& runtime) |
2628 | 53 | { | 91 | { |
2629 | 54 | auto acc = get_account(runtime); | 92 | auto acc = get_account(runtime); |
2632 | 55 | auto roots = acc->roots().result(); | 93 | auto roots = call(acc->roots()); |
2631 | 56 | assert(roots.size() == 1); | ||
2633 | 57 | return roots[0]; | 94 | return roots[0]; |
2634 | 58 | } | 95 | } |
2635 | 59 | 96 | ||
2636 | 60 | Folder::SPtr get_parent(Item::SPtr const& item) | 97 | Folder::SPtr get_parent(Item::SPtr const& item) |
2637 | 61 | { | 98 | { |
2638 | 62 | assert(item->type() != ItemType::root); | 99 | assert(item->type() != ItemType::root); |
2640 | 63 | auto parents = item->parents().result(); | 100 | auto parents = call(item->parents()); |
2641 | 64 | return parents[0]; | 101 | return parents[0]; |
2642 | 65 | } | 102 | } |
2643 | 66 | 103 | ||
2644 | 67 | void clear_folder(Folder::SPtr folder) | 104 | void clear_folder(Folder::SPtr folder) |
2645 | 68 | { | 105 | { |
2647 | 69 | auto items = folder->list().result(); | 106 | auto items = call(folder->list()); |
2648 | 70 | for (auto i : items) | 107 | for (auto i : items) |
2649 | 71 | { | 108 | { |
2650 | 72 | i->delete_item().waitForFinished(); | 109 | i->delete_item().waitForFinished(); |
2651 | @@ -81,7 +118,7 @@ | |||
2652 | 81 | return buf == expected; | 118 | return buf == expected; |
2653 | 82 | } | 119 | } |
2654 | 83 | 120 | ||
2656 | 84 | void write_file(Folder::SPtr const& folder, QString const& name, QByteArray const& contents) | 121 | File::SPtr write_file(Folder::SPtr const& folder, QString const& name, QByteArray const& contents) |
2657 | 85 | { | 122 | { |
2658 | 86 | QString ofile = folder->native_identity() + "/" + name; | 123 | QString ofile = folder->native_identity() + "/" + name; |
2659 | 87 | QFile f(ofile); | 124 | QFile f(ofile); |
2660 | @@ -90,6 +127,23 @@ | |||
2661 | 90 | { | 127 | { |
2662 | 91 | assert(f.write(contents)); | 128 | assert(f.write(contents)); |
2663 | 92 | } | 129 | } |
2664 | 130 | f.close(); | ||
2665 | 131 | auto items = call(folder->lookup(name)); | ||
2666 | 132 | return dynamic_pointer_cast<File>(items[0]); | ||
2667 | 133 | } | ||
2668 | 134 | |||
2669 | 135 | File::SPtr make_deleted_file(Folder::SPtr parent, QString const& name) | ||
2670 | 136 | { | ||
2671 | 137 | auto file = write_file(parent, name, "bytes"); | ||
2672 | 138 | call(file->delete_item()); | ||
2673 | 139 | return file; | ||
2674 | 140 | } | ||
2675 | 141 | |||
2676 | 142 | Folder::SPtr make_deleted_folder(Folder::SPtr parent, QString const& name) | ||
2677 | 143 | { | ||
2678 | 144 | auto folder = call(parent->create_folder(name)); | ||
2679 | 145 | call(folder->delete_item()); | ||
2680 | 146 | return folder; | ||
2681 | 93 | } | 147 | } |
2682 | 94 | 148 | ||
2683 | 95 | TEST(Runtime, lifecycle) | 149 | TEST(Runtime, lifecycle) |
2684 | @@ -104,7 +158,7 @@ | |||
2685 | 104 | auto runtime = Runtime::create(); | 158 | auto runtime = Runtime::create(); |
2686 | 105 | 159 | ||
2687 | 106 | auto acc = get_account(runtime); | 160 | auto acc = get_account(runtime); |
2689 | 107 | EXPECT_EQ(runtime.get(), acc->runtime()); | 161 | EXPECT_EQ(runtime, acc->runtime()); |
2690 | 108 | auto owner = acc->owner(); | 162 | auto owner = acc->owner(); |
2691 | 109 | EXPECT_EQ(QString(g_get_user_name()), owner); | 163 | EXPECT_EQ(QString(g_get_user_name()), owner); |
2692 | 110 | auto owner_id = acc->owner_id(); | 164 | auto owner_id = acc->owner_id(); |
2693 | @@ -118,11 +172,11 @@ | |||
2694 | 118 | auto runtime = Runtime::create(); | 172 | auto runtime = Runtime::create(); |
2695 | 119 | 173 | ||
2696 | 120 | auto acc = get_account(runtime); | 174 | auto acc = get_account(runtime); |
2698 | 121 | auto roots = acc->roots().result(); | 175 | auto roots = call(acc->roots()); |
2699 | 122 | EXPECT_EQ(1, roots.size()); | 176 | EXPECT_EQ(1, roots.size()); |
2700 | 123 | 177 | ||
2701 | 124 | // Get roots again, to get coverage for lazy initialization. | 178 | // Get roots again, to get coverage for lazy initialization. |
2703 | 125 | roots = acc->roots().result(); | 179 | roots = call(acc->roots()); |
2704 | 126 | ASSERT_EQ(1, roots.size()); | 180 | ASSERT_EQ(1, roots.size()); |
2705 | 127 | } | 181 | } |
2706 | 128 | 182 | ||
2707 | @@ -132,28 +186,36 @@ | |||
2708 | 132 | 186 | ||
2709 | 133 | auto acc = get_account(runtime); | 187 | auto acc = get_account(runtime); |
2710 | 134 | auto root = get_root(runtime); | 188 | auto root = get_root(runtime); |
2712 | 135 | EXPECT_EQ(acc.get(), root->account()); | 189 | EXPECT_EQ(acc, root->account()); |
2713 | 136 | EXPECT_EQ(ItemType::root, root->type()); | 190 | EXPECT_EQ(ItemType::root, root->type()); |
2714 | 137 | EXPECT_EQ("", root->name()); | 191 | EXPECT_EQ("", root->name()); |
2715 | 138 | EXPECT_NE("", root->etag()); | 192 | EXPECT_NE("", root->etag()); |
2716 | 139 | 193 | ||
2720 | 140 | auto parents = root->parents().result(); | 194 | { |
2721 | 141 | EXPECT_TRUE(parents.isEmpty()); | 195 | auto parents = call(root->parents()); |
2722 | 142 | EXPECT_TRUE(root->parent_ids().isEmpty()); | 196 | EXPECT_TRUE(parents.isEmpty()); |
2723 | 197 | EXPECT_TRUE(root->parent_ids().isEmpty()); | ||
2724 | 198 | } | ||
2725 | 143 | 199 | ||
2730 | 144 | // get(<root-path>) must return the root. | 200 | { |
2731 | 145 | auto item = root->get(root->native_identity()).result(); | 201 | // get(<root-path>) must return the root. |
2732 | 146 | EXPECT_NE(nullptr, dynamic_pointer_cast<Root>(item)); | 202 | auto item = call(root->get(root->native_identity())); |
2733 | 147 | EXPECT_TRUE(root->equal_to(item)); | 203 | EXPECT_NE(nullptr, dynamic_pointer_cast<Root>(item)); |
2734 | 204 | EXPECT_TRUE(root->equal_to(item)); | ||
2735 | 205 | } | ||
2736 | 148 | 206 | ||
2737 | 149 | // Free and used space can be anything, but must be > 0. | 207 | // Free and used space can be anything, but must be > 0. |
2741 | 150 | auto free_space = root->free_space_bytes().result(); | 208 | { |
2742 | 151 | cerr << "bytes free: " << free_space << endl; | 209 | auto free_space = call(root->free_space_bytes()); |
2743 | 152 | EXPECT_GT(free_space, 0); | 210 | cerr << "bytes free: " << free_space << endl; |
2744 | 211 | EXPECT_GT(free_space, 0); | ||
2745 | 212 | } | ||
2746 | 153 | 213 | ||
2750 | 154 | auto used_space = root->used_space_bytes().result(); | 214 | { |
2751 | 155 | cerr << "bytes used: " << used_space << endl; | 215 | auto used_space = call(root->used_space_bytes()); |
2752 | 156 | EXPECT_GT(used_space, 0); | 216 | cerr << "bytes used: " << used_space << endl; |
2753 | 217 | EXPECT_GT(used_space, 0); | ||
2754 | 218 | } | ||
2755 | 157 | } | 219 | } |
2756 | 158 | 220 | ||
2757 | 159 | TEST(Folder, basic) | 221 | TEST(Folder, basic) |
2758 | @@ -164,31 +226,43 @@ | |||
2759 | 164 | auto root = get_root(runtime); | 226 | auto root = get_root(runtime); |
2760 | 165 | clear_folder(root); | 227 | clear_folder(root); |
2761 | 166 | 228 | ||
2763 | 167 | auto items = root->list().result(); | 229 | auto items = call(root->list()); |
2764 | 168 | EXPECT_TRUE(items.isEmpty()); | 230 | EXPECT_TRUE(items.isEmpty()); |
2765 | 169 | 231 | ||
2766 | 170 | // Create a file and check that it was created with correct type, name, and size 0. | 232 | // Create a file and check that it was created with correct type, name, and size 0. |
2769 | 171 | auto uploader = root->create_file("file1", 0).result(); | 233 | auto uploader = call(root->create_file("file1", 0)); |
2770 | 172 | auto file = uploader->finish_upload().result(); | 234 | auto file = call(uploader->finish_upload()); |
2771 | 173 | EXPECT_EQ(ItemType::file, file->type()); | 235 | EXPECT_EQ(ItemType::file, file->type()); |
2772 | 174 | EXPECT_EQ("file1", file->name()); | 236 | EXPECT_EQ("file1", file->name()); |
2773 | 175 | EXPECT_EQ(0, file->size()); | 237 | EXPECT_EQ(0, file->size()); |
2774 | 176 | EXPECT_EQ(root->native_identity() + "/file1", file->native_identity()); | 238 | EXPECT_EQ(root->native_identity() + "/file1", file->native_identity()); |
2775 | 177 | 239 | ||
2776 | 178 | // Create a folder and check that it was created with correct type and name. | 240 | // Create a folder and check that it was created with correct type and name. |
2778 | 179 | auto folder = root->create_folder("folder1").result(); | 241 | auto folder = call(root->create_folder("folder1")); |
2779 | 180 | EXPECT_EQ(ItemType::folder, folder->type()); | 242 | EXPECT_EQ(ItemType::folder, folder->type()); |
2780 | 181 | EXPECT_EQ("folder1", folder->name()); | 243 | EXPECT_EQ("folder1", folder->name()); |
2781 | 182 | EXPECT_EQ(root->native_identity() + "/folder1", folder->native_identity()); | 244 | EXPECT_EQ(root->native_identity() + "/folder1", folder->native_identity()); |
2782 | 183 | 245 | ||
2783 | 184 | // Check that we can find both file1 and folder1. | 246 | // Check that we can find both file1 and folder1. |
2791 | 185 | auto item = root->lookup("file1").result()[0]; | 247 | auto item = call(root->lookup("file1"))[0]; |
2792 | 186 | file = dynamic_pointer_cast<File>(item); | 248 | file = dynamic_pointer_cast<File>(item); |
2793 | 187 | ASSERT_NE(nullptr, file); | 249 | ASSERT_NE(nullptr, file); |
2794 | 188 | EXPECT_EQ("file1", file->name()); | 250 | EXPECT_EQ("file1", file->name()); |
2795 | 189 | EXPECT_EQ(0, file->size()); | 251 | EXPECT_EQ(0, file->size()); |
2796 | 190 | 252 | ||
2797 | 191 | item = root->lookup("folder1").result()[0]; | 253 | item = call(root->lookup("folder1"))[0]; |
2798 | 254 | folder = dynamic_pointer_cast<Folder>(item); | ||
2799 | 255 | ASSERT_NE(nullptr, folder); | ||
2800 | 256 | ASSERT_EQ(nullptr, dynamic_pointer_cast<Root>(folder)); | ||
2801 | 257 | EXPECT_EQ("folder1", folder->name()); | ||
2802 | 258 | |||
2803 | 259 | item = call(root->get(file->native_identity())); | ||
2804 | 260 | file = dynamic_pointer_cast<File>(item); | ||
2805 | 261 | ASSERT_NE(nullptr, file); | ||
2806 | 262 | EXPECT_EQ("file1", file->name()); | ||
2807 | 263 | EXPECT_EQ(0, file->size()); | ||
2808 | 264 | |||
2809 | 265 | item = call(root->get(folder->native_identity())); | ||
2810 | 192 | folder = dynamic_pointer_cast<Folder>(item); | 266 | folder = dynamic_pointer_cast<Folder>(item); |
2811 | 193 | ASSERT_NE(nullptr, folder); | 267 | ASSERT_NE(nullptr, folder); |
2812 | 194 | ASSERT_EQ(nullptr, dynamic_pointer_cast<Root>(folder)); | 268 | ASSERT_EQ(nullptr, dynamic_pointer_cast<Root>(folder)); |
2813 | @@ -224,8 +298,8 @@ | |||
2814 | 224 | EXPECT_EQ(root->native_identity(), folder->parent_ids()[0]); | 298 | EXPECT_EQ(root->native_identity(), folder->parent_ids()[0]); |
2815 | 225 | 299 | ||
2816 | 226 | // Delete the file and check that only the directory is left. | 300 | // Delete the file and check that only the directory is left. |
2819 | 227 | file->delete_item().waitForFinished(); | 301 | call(file->delete_item()); |
2820 | 228 | items = root->list().result(); | 302 | items = call(root->list()); |
2821 | 229 | ASSERT_EQ(1, items.size()); | 303 | ASSERT_EQ(1, items.size()); |
2822 | 230 | folder = dynamic_pointer_cast<Folder>(items[0]); | 304 | folder = dynamic_pointer_cast<Folder>(items[0]); |
2823 | 231 | ASSERT_NE(nullptr, folder); | 305 | ASSERT_NE(nullptr, folder); |
2824 | @@ -233,7 +307,7 @@ | |||
2825 | 233 | 307 | ||
2826 | 234 | // Delete the folder and check that the root is empty. | 308 | // Delete the folder and check that the root is empty. |
2827 | 235 | folder->delete_item().waitForFinished(); | 309 | folder->delete_item().waitForFinished(); |
2829 | 236 | items = root->list().result(); | 310 | items = call(root->list()); |
2830 | 237 | ASSERT_EQ(0, items.size()); | 311 | ASSERT_EQ(0, items.size()); |
2831 | 238 | } | 312 | } |
2832 | 239 | 313 | ||
2833 | @@ -245,8 +319,8 @@ | |||
2834 | 245 | auto root = get_root(runtime); | 319 | auto root = get_root(runtime); |
2835 | 246 | clear_folder(root); | 320 | clear_folder(root); |
2836 | 247 | 321 | ||
2839 | 248 | auto d1 = root->create_folder("d1").result(); | 322 | auto d1 = call(root->create_folder("d1")); |
2840 | 249 | auto d2 = d1->create_folder("d2").result(); | 323 | auto d2 = call(d1->create_folder("d2")); |
2841 | 250 | 324 | ||
2842 | 251 | // Parent of d2 must be d1. | 325 | // Parent of d2 must be d1. |
2843 | 252 | EXPECT_TRUE(get_parent(d2)->equal_to(d1)); | 326 | EXPECT_TRUE(get_parent(d2)->equal_to(d1)); |
2844 | @@ -254,7 +328,7 @@ | |||
2845 | 254 | 328 | ||
2846 | 255 | // Delete is recursive | 329 | // Delete is recursive |
2847 | 256 | d1->delete_item().waitForFinished(); | 330 | d1->delete_item().waitForFinished(); |
2849 | 257 | auto items = root->list().result(); | 331 | auto items = call(root->list()); |
2850 | 258 | ASSERT_EQ(0, items.size()); | 332 | ASSERT_EQ(0, items.size()); |
2851 | 259 | } | 333 | } |
2852 | 260 | 334 | ||
2853 | @@ -269,91 +343,73 @@ | |||
2854 | 269 | { | 343 | { |
2855 | 270 | // Upload a few bytes. | 344 | // Upload a few bytes. |
2856 | 271 | QByteArray const contents = "Hello\n"; | 345 | QByteArray const contents = "Hello\n"; |
2858 | 272 | auto uploader = root->create_file("new_file", contents.size()).result(); | 346 | auto uploader = call(root->create_file("new_file", contents.size())); |
2859 | 273 | auto written = uploader->socket()->write(contents); | 347 | auto written = uploader->socket()->write(contents); |
2860 | 274 | ASSERT_EQ(contents.size(), written); | 348 | ASSERT_EQ(contents.size(), written); |
2861 | 275 | 349 | ||
2869 | 276 | auto file_fut = uploader->finish_upload(); | 350 | auto file = call(uploader->finish_upload()); |
2863 | 277 | QFutureWatcher<File::SPtr> w; | ||
2864 | 278 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
2865 | 279 | w.setFuture(file_fut); | ||
2866 | 280 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
2867 | 281 | |||
2868 | 282 | auto file = file_fut.result(); | ||
2870 | 283 | EXPECT_EQ(contents.size(), file->size()); | 351 | EXPECT_EQ(contents.size(), file->size()); |
2871 | 284 | ASSERT_TRUE(content_matches(file, contents)); | 352 | ASSERT_TRUE(content_matches(file, contents)); |
2872 | 285 | 353 | ||
2873 | 286 | // Calling finish_upload() more than once must return the original future. | 354 | // Calling finish_upload() more than once must return the original future. |
2875 | 287 | auto file2 = uploader->finish_upload().result(); | 355 | auto file2 = call(uploader->finish_upload()); |
2876 | 288 | EXPECT_TRUE(file2->equal_to(file)); | 356 | EXPECT_TRUE(file2->equal_to(file)); |
2877 | 289 | 357 | ||
2878 | 290 | // Calling cancel() after finish_upload must do nothing. | 358 | // Calling cancel() after finish_upload must do nothing. |
2879 | 291 | uploader->cancel(); | 359 | uploader->cancel(); |
2881 | 292 | file2 = uploader->finish_upload().result(); | 360 | file2 = call(uploader->finish_upload()); |
2882 | 293 | EXPECT_TRUE(file2->equal_to(file)); | 361 | EXPECT_TRUE(file2->equal_to(file)); |
2883 | 294 | 362 | ||
2885 | 295 | file->delete_item().waitForFinished(); | 363 | call(file->delete_item()); |
2886 | 296 | } | 364 | } |
2887 | 297 | 365 | ||
2888 | 298 | { | 366 | { |
2889 | 299 | // Upload exactly 64 KB. | 367 | // Upload exactly 64 KB. |
2890 | 300 | QByteArray const contents(64 * 1024, 'a'); | 368 | QByteArray const contents(64 * 1024, 'a'); |
2892 | 301 | auto uploader = root->create_file("new_file", contents.size()).result(); | 369 | auto uploader = call(root->create_file("new_file", contents.size())); |
2893 | 302 | auto written = uploader->socket()->write(contents); | 370 | auto written = uploader->socket()->write(contents); |
2894 | 303 | ASSERT_EQ(contents.size(), written); | 371 | ASSERT_EQ(contents.size(), written); |
2895 | 304 | 372 | ||
2903 | 305 | auto file_fut = uploader->finish_upload(); | 373 | auto file = call(uploader->finish_upload()); |
2897 | 306 | QFutureWatcher<File::SPtr> w; | ||
2898 | 307 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
2899 | 308 | w.setFuture(file_fut); | ||
2900 | 309 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
2901 | 310 | |||
2902 | 311 | auto file = file_fut.result(); | ||
2904 | 312 | EXPECT_EQ(contents.size(), file->size()); | 374 | EXPECT_EQ(contents.size(), file->size()); |
2905 | 313 | ASSERT_TRUE(content_matches(file, contents)); | 375 | ASSERT_TRUE(content_matches(file, contents)); |
2906 | 314 | 376 | ||
2908 | 315 | file->delete_item().waitForFinished(); | 377 | call(file->delete_item()); |
2909 | 316 | } | 378 | } |
2910 | 317 | 379 | ||
2911 | 318 | { | 380 | { |
2912 | 319 | // Upload 1000 KBj | 381 | // Upload 1000 KBj |
2913 | 320 | QByteArray const contents(1000 * 1024, 'a'); | 382 | QByteArray const contents(1000 * 1024, 'a'); |
2915 | 321 | auto uploader = root->create_file("new_file", contents.size()).result(); | 383 | auto uploader = call(root->create_file("new_file", contents.size())); |
2916 | 322 | auto written = uploader->socket()->write(contents); | 384 | auto written = uploader->socket()->write(contents); |
2917 | 323 | ASSERT_EQ(contents.size(), written); | 385 | ASSERT_EQ(contents.size(), written); |
2918 | 324 | 386 | ||
2926 | 325 | auto file_fut = uploader->finish_upload(); | 387 | auto file = call(uploader->finish_upload()); |
2920 | 326 | QFutureWatcher<File::SPtr> w; | ||
2921 | 327 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
2922 | 328 | w.setFuture(file_fut); | ||
2923 | 329 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
2924 | 330 | |||
2925 | 331 | auto file = file_fut.result(); | ||
2927 | 332 | EXPECT_EQ(contents.size(), file->size()); | 388 | EXPECT_EQ(contents.size(), file->size()); |
2928 | 333 | ASSERT_TRUE(content_matches(file, contents)); | 389 | ASSERT_TRUE(content_matches(file, contents)); |
2929 | 334 | 390 | ||
2931 | 335 | file->delete_item().waitForFinished(); | 391 | call(file->delete_item()); |
2932 | 336 | } | 392 | } |
2933 | 337 | 393 | ||
2934 | 338 | { | 394 | { |
2935 | 339 | // Upload empty file. | 395 | // Upload empty file. |
2938 | 340 | auto uploader = root->create_file("new_file", 0).result(); | 396 | auto uploader = call(root->create_file("new_file", 0)); |
2939 | 341 | auto file = uploader->finish_upload().result(); | 397 | auto file = call(uploader->finish_upload()); |
2940 | 342 | ASSERT_EQ(0, file->size()); | 398 | ASSERT_EQ(0, file->size()); |
2941 | 343 | 399 | ||
2942 | 344 | // Again, and check that the ETag is different. | 400 | // Again, and check that the ETag is different. |
2943 | 345 | auto old_etag = file->etag(); | 401 | auto old_etag = file->etag(); |
2944 | 346 | sleep(1); | 402 | sleep(1); |
2947 | 347 | uploader = file->create_uploader(ConflictPolicy::overwrite, 0).result(); | 403 | uploader = call(file->create_uploader(ConflictPolicy::overwrite, 0)); |
2948 | 348 | file = uploader->finish_upload().result(); | 404 | file = call(uploader->finish_upload()); |
2949 | 349 | EXPECT_NE(old_etag, file->etag()); | 405 | EXPECT_NE(old_etag, file->etag()); |
2950 | 350 | 406 | ||
2952 | 351 | file->delete_item().waitForFinished(); | 407 | call(file->delete_item()); |
2953 | 352 | } | 408 | } |
2954 | 353 | 409 | ||
2955 | 354 | { | 410 | { |
2956 | 355 | // Let the uploader go out of scope and check that the file was not created. | 411 | // Let the uploader go out of scope and check that the file was not created. |
2958 | 356 | root->create_file("new_file", 0).result(); | 412 | call(root->create_file("new_file", 0)); |
2959 | 357 | boost::filesystem::path path(TEST_DIR "/storage-framework/new_file"); | 413 | boost::filesystem::path path(TEST_DIR "/storage-framework/new_file"); |
2960 | 358 | auto status = boost::filesystem::status(path); | 414 | auto status = boost::filesystem::status(path); |
2961 | 359 | ASSERT_FALSE(boost::filesystem::exists(status)); | 415 | ASSERT_FALSE(boost::filesystem::exists(status)); |
2962 | @@ -369,47 +425,25 @@ | |||
2963 | 369 | clear_folder(root); | 425 | clear_folder(root); |
2964 | 370 | 426 | ||
2965 | 371 | // Make a new file first. | 427 | // Make a new file first. |
2975 | 372 | auto uploader = root->create_file("new_file", 0).result(); | 428 | auto uploader = call(root->create_file("new_file", 0)); |
2976 | 373 | auto file_fut = uploader->finish_upload(); | 429 | auto file = call(uploader->finish_upload()); |
2968 | 374 | { | ||
2969 | 375 | QFutureWatcher<File::SPtr> w; | ||
2970 | 376 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
2971 | 377 | w.setFuture(file_fut); | ||
2972 | 378 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
2973 | 379 | } | ||
2974 | 380 | auto file = file_fut.result(); | ||
2977 | 381 | EXPECT_EQ(0, file->size()); | 430 | EXPECT_EQ(0, file->size()); |
2978 | 382 | auto old_etag = file->etag(); | 431 | auto old_etag = file->etag(); |
2979 | 383 | 432 | ||
2980 | 384 | // Create uploader for the file and write nothing. | 433 | // Create uploader for the file and write nothing. |
2990 | 385 | uploader = file->create_uploader(ConflictPolicy::overwrite, 0).result(); | 434 | uploader = call(file->create_uploader(ConflictPolicy::overwrite, 0)); |
2991 | 386 | file_fut = uploader->finish_upload(); | 435 | file = call(uploader->finish_upload()); |
2983 | 387 | { | ||
2984 | 388 | QFutureWatcher<File::SPtr> w; | ||
2985 | 389 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
2986 | 390 | w.setFuture(file_fut); | ||
2987 | 391 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
2988 | 392 | } | ||
2989 | 393 | file = file_fut.result(); | ||
2992 | 394 | EXPECT_EQ(0, file->size()); | 436 | EXPECT_EQ(0, file->size()); |
2993 | 395 | 437 | ||
2994 | 396 | // Same test again, but this time, we write a bunch of data. | 438 | // Same test again, but this time, we write a bunch of data. |
2995 | 397 | std::string s(1000000, 'a'); | 439 | std::string s(1000000, 'a'); |
2997 | 398 | uploader = file->create_uploader(ConflictPolicy::overwrite, s.size()).result(); | 440 | uploader = call(file->create_uploader(ConflictPolicy::overwrite, s.size())); |
2998 | 399 | uploader->socket()->write(&s[0], s.size()); | 441 | uploader->socket()->write(&s[0], s.size()); |
2999 | 400 | 442 | ||
3000 | 401 | // Need to sleep here, otherwise it is possible for the | 443 | // Need to sleep here, otherwise it is possible for the |
3001 | 402 | // upload to finish within the granularity of the file system time stamps. | 444 | // upload to finish within the granularity of the file system time stamps. |
3002 | 403 | sleep(1); | 445 | sleep(1); |
3012 | 404 | file_fut = uploader->finish_upload(); | 446 | file = call(uploader->finish_upload()); |
3004 | 405 | { | ||
3005 | 406 | QFutureWatcher<File::SPtr> w; | ||
3006 | 407 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
3007 | 408 | w.setFuture(file_fut); | ||
3008 | 409 | // Now that we have disconnected, the future must become ready. | ||
3009 | 410 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3010 | 411 | } | ||
3011 | 412 | file = file_fut.result(); | ||
3013 | 413 | EXPECT_EQ(1000000, file->size()); | 447 | EXPECT_EQ(1000000, file->size()); |
3014 | 414 | EXPECT_NE(old_etag, file->etag()); | 448 | EXPECT_NE(old_etag, file->etag()); |
3015 | 415 | 449 | ||
3016 | @@ -425,12 +459,12 @@ | |||
3017 | 425 | clear_folder(root); | 459 | clear_folder(root); |
3018 | 426 | 460 | ||
3019 | 427 | { | 461 | { |
3021 | 428 | auto uploader = root->create_file("new_file", 20).result(); | 462 | auto uploader = call(root->create_file("new_file", 20)); |
3022 | 429 | 463 | ||
3023 | 430 | // We haven't called finish_upload(), so the cancel is guaranteed | 464 | // We haven't called finish_upload(), so the cancel is guaranteed |
3024 | 431 | // to catch the uploader in the in_progress state. | 465 | // to catch the uploader in the in_progress state. |
3025 | 432 | uploader->cancel(); | 466 | uploader->cancel(); |
3027 | 433 | EXPECT_THROW(uploader->finish_upload().result(), CancelledException); | 467 | EXPECT_THROW(call(uploader->finish_upload()), CancelledException); |
3028 | 434 | 468 | ||
3029 | 435 | boost::filesystem::path path(TEST_DIR "/storage-framework/new_file"); | 469 | boost::filesystem::path path(TEST_DIR "/storage-framework/new_file"); |
3030 | 436 | auto status = boost::filesystem::status(path); | 470 | auto status = boost::filesystem::status(path); |
3031 | @@ -440,33 +474,25 @@ | |||
3032 | 440 | { | 474 | { |
3033 | 441 | // Create a file with a few bytes. | 475 | // Create a file with a few bytes. |
3034 | 442 | QByteArray original_contents = "Hello World!\n"; | 476 | QByteArray original_contents = "Hello World!\n"; |
3038 | 443 | write_file(root, "new_file", original_contents); | 477 | auto file = write_file(root, "new_file", original_contents); |
3036 | 444 | auto file = dynamic_pointer_cast<File>(root->lookup("new_file").result()[0]); | ||
3037 | 445 | ASSERT_NE(nullptr, file); | ||
3039 | 446 | 478 | ||
3040 | 447 | // Create an uploader for the file and write a bunch of bytes. | 479 | // Create an uploader for the file and write a bunch of bytes. |
3042 | 448 | auto uploader = file->create_uploader(ConflictPolicy::overwrite, original_contents.size()).result(); | 480 | auto uploader = call(file->create_uploader(ConflictPolicy::overwrite, original_contents.size())); |
3043 | 449 | QByteArray const contents(1024 * 1024, 'a'); | 481 | QByteArray const contents(1024 * 1024, 'a'); |
3044 | 450 | auto written = uploader->socket()->write(contents); | 482 | auto written = uploader->socket()->write(contents); |
3045 | 451 | ASSERT_EQ(contents.size(), written); | 483 | ASSERT_EQ(contents.size(), written); |
3046 | 452 | 484 | ||
3047 | 453 | // No finish_upload() here, so the transfer is still in progress. Now cancel. | 485 | // No finish_upload() here, so the transfer is still in progress. Now cancel. |
3055 | 454 | auto cancel_fut = uploader->cancel(); | 486 | uploader->cancel(); |
3049 | 455 | { | ||
3050 | 456 | QFutureWatcher<void> w; | ||
3051 | 457 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
3052 | 458 | w.setFuture(cancel_fut); | ||
3053 | 459 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3054 | 460 | } | ||
3056 | 461 | 487 | ||
3057 | 462 | // finish_upload() must indicate that the upload was cancelled. | 488 | // finish_upload() must indicate that the upload was cancelled. |
3059 | 463 | EXPECT_THROW(uploader->finish_upload().result(), CancelledException); | 489 | EXPECT_THROW(call(uploader->finish_upload()), CancelledException); |
3060 | 464 | 490 | ||
3061 | 465 | // The original file contents must still be intact. | 491 | // The original file contents must still be intact. |
3062 | 466 | EXPECT_EQ(original_contents.size(), file->size()); | 492 | EXPECT_EQ(original_contents.size(), file->size()); |
3063 | 467 | ASSERT_TRUE(content_matches(file, original_contents)); | 493 | ASSERT_TRUE(content_matches(file, original_contents)); |
3064 | 468 | 494 | ||
3066 | 469 | file->delete_item().waitForFinished(); | 495 | call(file->delete_item()); |
3067 | 470 | } | 496 | } |
3068 | 471 | } | 497 | } |
3069 | 472 | 498 | ||
3070 | @@ -480,10 +506,8 @@ | |||
3071 | 480 | 506 | ||
3072 | 481 | // Make a new file on disk. | 507 | // Make a new file on disk. |
3073 | 482 | QByteArray const contents = ""; | 508 | QByteArray const contents = ""; |
3078 | 483 | write_file(root, "new_file", contents); | 509 | auto file = write_file(root, "new_file", contents); |
3079 | 484 | auto file = dynamic_pointer_cast<File>(root->lookup("new_file").result()[0]); | 510 | auto uploader = call(file->create_uploader(ConflictPolicy::error_if_conflict, contents.size())); |
3076 | 485 | ASSERT_NE(nullptr, file); | ||
3077 | 486 | auto uploader = file->create_uploader(ConflictPolicy::error_if_conflict, contents.size()).result(); | ||
3080 | 487 | 511 | ||
3081 | 488 | // Touch the file on disk to give it a new time stamp. | 512 | // Touch the file on disk to give it a new time stamp. |
3082 | 489 | sleep(1); | 513 | sleep(1); |
3083 | @@ -492,7 +516,7 @@ | |||
3084 | 492 | try | 516 | try |
3085 | 493 | { | 517 | { |
3086 | 494 | // Must get an exception because the time stamps no longer match. | 518 | // Must get an exception because the time stamps no longer match. |
3088 | 495 | uploader->finish_upload().result(); | 519 | call(uploader->finish_upload()); |
3089 | 496 | FAIL(); | 520 | FAIL(); |
3090 | 497 | } | 521 | } |
3091 | 498 | catch (ConflictException const&) | 522 | catch (ConflictException const&) |
3092 | @@ -500,7 +524,52 @@ | |||
3093 | 500 | // TODO: check exception details. | 524 | // TODO: check exception details. |
3094 | 501 | } | 525 | } |
3095 | 502 | 526 | ||
3097 | 503 | file->delete_item().waitForFinished(); | 527 | call(file->delete_item()); |
3098 | 528 | } | ||
3099 | 529 | |||
3100 | 530 | TEST(File, upload_error) | ||
3101 | 531 | { | ||
3102 | 532 | auto runtime = Runtime::create(); | ||
3103 | 533 | |||
3104 | 534 | auto acc = get_account(runtime); | ||
3105 | 535 | auto root = get_root(runtime); | ||
3106 | 536 | clear_folder(root); | ||
3107 | 537 | |||
3108 | 538 | auto uploader = call(root->create_file("new_file", 0)); | ||
3109 | 539 | // Make new_file, so it gets in the way during finish_upload(). | ||
3110 | 540 | write_file(root, "new_file", ""); | ||
3111 | 541 | |||
3112 | 542 | try | ||
3113 | 543 | { | ||
3114 | 544 | call(uploader->finish_upload()); | ||
3115 | 545 | FAIL(); | ||
3116 | 546 | } | ||
3117 | 547 | catch (ExistsException const& e) | ||
3118 | 548 | { | ||
3119 | 549 | EXPECT_TRUE(e.error_message().startsWith("Uploader::finish_upload(): item with name \"")); | ||
3120 | 550 | EXPECT_TRUE(e.error_message().endsWith("\" exists already")); | ||
3121 | 551 | EXPECT_EQ(TEST_DIR "/storage-framework/new_file", e.native_identity()) << e.native_identity().toStdString(); | ||
3122 | 552 | EXPECT_EQ("new_file", e.name()); | ||
3123 | 553 | } | ||
3124 | 554 | } | ||
3125 | 555 | |||
3126 | 556 | TEST(File, create_uploader_bad_arg) | ||
3127 | 557 | { | ||
3128 | 558 | auto runtime = Runtime::create(); | ||
3129 | 559 | |||
3130 | 560 | auto acc = get_account(runtime); | ||
3131 | 561 | auto root = get_root(runtime); | ||
3132 | 562 | clear_folder(root); | ||
3133 | 563 | |||
3134 | 564 | auto file = write_file(root, "new_file", 0); | ||
3135 | 565 | try | ||
3136 | 566 | { | ||
3137 | 567 | call(file->create_uploader(ConflictPolicy::overwrite, -1)); | ||
3138 | 568 | } | ||
3139 | 569 | catch (InvalidArgumentException const& e) | ||
3140 | 570 | { | ||
3141 | 571 | EXPECT_EQ("File::create_uploader(): size must be >= 0", e.error_message()); | ||
3142 | 572 | } | ||
3143 | 504 | } | 573 | } |
3144 | 505 | 574 | ||
3145 | 506 | TEST(File, download) | 575 | TEST(File, download) |
3146 | @@ -514,22 +583,15 @@ | |||
3147 | 514 | { | 583 | { |
3148 | 515 | // Download a few bytes. | 584 | // Download a few bytes. |
3149 | 516 | QByteArray const contents = "Hello\n"; | 585 | QByteArray const contents = "Hello\n"; |
3157 | 517 | write_file(root, "file", contents); | 586 | auto file = write_file(root, "file", contents); |
3158 | 518 | 587 | ||
3159 | 519 | auto item = root->lookup("file").result()[0]; | 588 | auto downloader = call(file->create_downloader()); |
3153 | 520 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3154 | 521 | ASSERT_FALSE(file == nullptr); | ||
3155 | 522 | |||
3156 | 523 | auto downloader = file->create_downloader().result(); | ||
3160 | 524 | EXPECT_TRUE(file->equal_to(downloader->file())); | 589 | EXPECT_TRUE(file->equal_to(downloader->file())); |
3161 | 525 | 590 | ||
3162 | 526 | auto socket = downloader->socket(); | 591 | auto socket = downloader->socket(); |
3163 | 527 | QByteArray buf; | 592 | QByteArray buf; |
3164 | 528 | do | 593 | do |
3165 | 529 | { | 594 | { |
3166 | 530 | // Need to pump the event loop while the socket does its thing. | ||
3167 | 531 | QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); | ||
3168 | 532 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3169 | 533 | auto bytes_to_read = socket->bytesAvailable(); | 595 | auto bytes_to_read = socket->bytesAvailable(); |
3170 | 534 | buf.append(socket->read(bytes_to_read)); | 596 | buf.append(socket->read(bytes_to_read)); |
3171 | 535 | } while (buf.size() < contents.size()); | 597 | } while (buf.size() < contents.size()); |
3172 | @@ -538,7 +600,7 @@ | |||
3173 | 538 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); | 600 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); |
3174 | 539 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | 601 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
3175 | 540 | 602 | ||
3177 | 541 | ASSERT_NO_THROW(downloader->finish_download().waitForFinished()); | 603 | ASSERT_NO_THROW(call(downloader->finish_download())); |
3178 | 542 | 604 | ||
3179 | 543 | // Contents must match. | 605 | // Contents must match. |
3180 | 544 | EXPECT_EQ(contents, buf); | 606 | EXPECT_EQ(contents, buf); |
3181 | @@ -547,13 +609,9 @@ | |||
3182 | 547 | { | 609 | { |
3183 | 548 | // Download exactly 64 KB. | 610 | // Download exactly 64 KB. |
3184 | 549 | QByteArray const contents(64 * 1024, 'a'); | 611 | QByteArray const contents(64 * 1024, 'a'); |
3192 | 550 | write_file(root, "file", contents); | 612 | auto file = write_file(root, "file", contents); |
3193 | 551 | 613 | ||
3194 | 552 | auto item = root->lookup("file").result()[0]; | 614 | auto downloader = call(file->create_downloader()); |
3188 | 553 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3189 | 554 | ASSERT_FALSE(file == nullptr); | ||
3190 | 555 | |||
3191 | 556 | auto downloader = file->create_downloader().result(); | ||
3195 | 557 | EXPECT_TRUE(file->equal_to(downloader->file())); | 615 | EXPECT_TRUE(file->equal_to(downloader->file())); |
3196 | 558 | 616 | ||
3197 | 559 | auto socket = downloader->socket(); | 617 | auto socket = downloader->socket(); |
3198 | @@ -561,9 +619,12 @@ | |||
3199 | 561 | do | 619 | do |
3200 | 562 | { | 620 | { |
3201 | 563 | // Need to pump the event loop while the socket does its thing. | 621 | // Need to pump the event loop while the socket does its thing. |
3202 | 564 | QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); | ||
3203 | 565 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3204 | 566 | auto bytes_to_read = socket->bytesAvailable(); | 622 | auto bytes_to_read = socket->bytesAvailable(); |
3205 | 623 | if (bytes_to_read == 0) | ||
3206 | 624 | { | ||
3207 | 625 | QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); | ||
3208 | 626 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3209 | 627 | } | ||
3210 | 567 | buf.append(socket->read(bytes_to_read)); | 628 | buf.append(socket->read(bytes_to_read)); |
3211 | 568 | } while (buf.size() < contents.size()); | 629 | } while (buf.size() < contents.size()); |
3212 | 569 | 630 | ||
3213 | @@ -571,7 +632,7 @@ | |||
3214 | 571 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); | 632 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); |
3215 | 572 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | 633 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
3216 | 573 | 634 | ||
3218 | 574 | ASSERT_NO_THROW(downloader->finish_download().waitForFinished()); | 635 | ASSERT_NO_THROW(call(downloader->finish_download())); |
3219 | 575 | 636 | ||
3220 | 576 | // Contents must match | 637 | // Contents must match |
3221 | 577 | EXPECT_EQ(contents, buf); | 638 | EXPECT_EQ(contents, buf); |
3222 | @@ -580,13 +641,9 @@ | |||
3223 | 580 | { | 641 | { |
3224 | 581 | // Download 1 MB + 1 bytes. | 642 | // Download 1 MB + 1 bytes. |
3225 | 582 | QByteArray const contents(1024 * 1024 + 1, 'a'); | 643 | QByteArray const contents(1024 * 1024 + 1, 'a'); |
3233 | 583 | write_file(root, "file", contents); | 644 | auto file = write_file(root, "file", contents); |
3234 | 584 | 645 | ||
3235 | 585 | auto item = root->lookup("file").result()[0]; | 646 | auto downloader = call(file->create_downloader()); |
3229 | 586 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3230 | 587 | ASSERT_FALSE(file == nullptr); | ||
3231 | 588 | |||
3232 | 589 | auto downloader = file->create_downloader().result(); | ||
3236 | 590 | EXPECT_TRUE(file->equal_to(downloader->file())); | 647 | EXPECT_TRUE(file->equal_to(downloader->file())); |
3237 | 591 | 648 | ||
3238 | 592 | auto socket = downloader->socket(); | 649 | auto socket = downloader->socket(); |
3239 | @@ -594,17 +651,20 @@ | |||
3240 | 594 | do | 651 | do |
3241 | 595 | { | 652 | { |
3242 | 596 | // Need to pump the event loop while the socket does its thing. | 653 | // Need to pump the event loop while the socket does its thing. |
3243 | 597 | QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); | ||
3244 | 598 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3245 | 599 | auto bytes_to_read = socket->bytesAvailable(); | 654 | auto bytes_to_read = socket->bytesAvailable(); |
3246 | 655 | if (bytes_to_read == 0) | ||
3247 | 656 | { | ||
3248 | 657 | QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); | ||
3249 | 658 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3250 | 659 | } | ||
3251 | 600 | buf.append(socket->read(bytes_to_read)); | 660 | buf.append(socket->read(bytes_to_read)); |
3252 | 601 | } while (buf.size() < contents.size()); | 661 | } while (buf.size() < contents.size()); |
3253 | 602 | 662 | ||
3254 | 603 | // Wait for disconnected signal. | 663 | // Wait for disconnected signal. |
3256 | 604 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); | 664 | QSignalSpy spy(socket.get(), &QLocalSocket::disconnected); |
3257 | 605 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | 665 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
3258 | 606 | 666 | ||
3260 | 607 | ASSERT_NO_THROW(downloader->finish_download().waitForFinished()); | 667 | ASSERT_NO_THROW(call(downloader->finish_download())); |
3261 | 608 | 668 | ||
3262 | 609 | // Contents must match | 669 | // Contents must match |
3263 | 610 | EXPECT_EQ(contents, buf); | 670 | EXPECT_EQ(contents, buf); |
3264 | @@ -613,85 +673,84 @@ | |||
3265 | 613 | { | 673 | { |
3266 | 614 | // Download file containing zero bytes | 674 | // Download file containing zero bytes |
3267 | 615 | QByteArray const contents; | 675 | QByteArray const contents; |
3275 | 616 | write_file(root, "file", contents); | 676 | auto file = write_file(root, "file", contents); |
3276 | 617 | 677 | ||
3277 | 618 | auto item = root->lookup("file").result()[0]; | 678 | auto downloader = call(file->create_downloader()); |
3271 | 619 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3272 | 620 | ASSERT_FALSE(file == nullptr); | ||
3273 | 621 | |||
3274 | 622 | auto downloader = file->create_downloader().result(); | ||
3278 | 623 | EXPECT_TRUE(file->equal_to(downloader->file())); | 679 | EXPECT_TRUE(file->equal_to(downloader->file())); |
3279 | 624 | 680 | ||
3280 | 625 | auto socket = downloader->socket(); | 681 | auto socket = downloader->socket(); |
3281 | 626 | 682 | ||
3285 | 627 | // No readyRead every arrives in this case, just wait for disconnected. | 683 | // No readyRead ever arrives in this case, just wait for disconnected. |
3286 | 628 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); | 684 | if (socket->state() != QLocalSocket::UnconnectedState) |
3287 | 629 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | 685 | { |
3288 | 686 | QSignalSpy spy(socket.get(), &QLocalSocket::disconnected); | ||
3289 | 687 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3290 | 688 | } | ||
3291 | 630 | 689 | ||
3293 | 631 | ASSERT_NO_THROW(downloader->finish_download().waitForFinished()); | 690 | ASSERT_NO_THROW(call(downloader->finish_download())); |
3294 | 632 | } | 691 | } |
3295 | 633 | 692 | ||
3296 | 634 | { | 693 | { |
3297 | 635 | // Don't ever call read on empty file. | 694 | // Don't ever call read on empty file. |
3298 | 636 | QByteArray const contents; | 695 | QByteArray const contents; |
3306 | 637 | write_file(root, "file", contents); | 696 | auto file = write_file(root, "file", contents); |
3307 | 638 | 697 | ||
3308 | 639 | auto item = root->lookup("file").result()[0]; | 698 | auto downloader = call(file->create_downloader()); |
3302 | 640 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3303 | 641 | ASSERT_FALSE(file == nullptr); | ||
3304 | 642 | |||
3305 | 643 | auto downloader = file->create_downloader().result(); | ||
3309 | 644 | EXPECT_TRUE(file->equal_to(downloader->file())); | 699 | EXPECT_TRUE(file->equal_to(downloader->file())); |
3310 | 645 | 700 | ||
3311 | 701 | auto socket = downloader->socket(); | ||
3312 | 702 | |||
3313 | 646 | // No readyRead ever arrives in this case, just wait for disconnected. | 703 | // No readyRead ever arrives in this case, just wait for disconnected. |
3316 | 647 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); | 704 | if (socket->state() != QLocalSocket::UnconnectedState) |
3317 | 648 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | 705 | { |
3318 | 706 | QSignalSpy spy(socket.get(), &QLocalSocket::disconnected); | ||
3319 | 707 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3320 | 708 | } | ||
3321 | 649 | 709 | ||
3322 | 650 | // This succeeds because the provider disconnects as soon | 710 | // This succeeds because the provider disconnects as soon |
3323 | 651 | // as it realizes that there is nothing to write. | 711 | // as it realizes that there is nothing to write. |
3325 | 652 | ASSERT_NO_THROW(downloader->finish_download().waitForFinished()); | 712 | ASSERT_NO_THROW(call(downloader->finish_download())); |
3326 | 653 | } | 713 | } |
3327 | 654 | 714 | ||
3328 | 655 | { | 715 | { |
3329 | 656 | // Don't ever call read on small file. | 716 | // Don't ever call read on small file. |
3330 | 657 | QByteArray const contents("some contents"); | 717 | QByteArray const contents("some contents"); |
3338 | 658 | write_file(root, "file", contents); | 718 | auto file = write_file(root, "file", contents); |
3339 | 659 | 719 | ||
3340 | 660 | auto item = root->lookup("file").result()[0]; | 720 | auto downloader = call(file->create_downloader()); |
3334 | 661 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3335 | 662 | ASSERT_FALSE(file == nullptr); | ||
3336 | 663 | |||
3337 | 664 | auto downloader = file->create_downloader().result(); | ||
3341 | 665 | EXPECT_TRUE(file->equal_to(downloader->file())); | 721 | EXPECT_TRUE(file->equal_to(downloader->file())); |
3342 | 666 | 722 | ||
3343 | 723 | auto socket = downloader->socket(); | ||
3344 | 724 | |||
3345 | 667 | // Wait for disconnected. | 725 | // Wait for disconnected. |
3348 | 668 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); | 726 | if (socket->state() != QLocalSocket::UnconnectedState) |
3349 | 669 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | 727 | { |
3350 | 728 | QSignalSpy spy(socket.get(), &QLocalSocket::disconnected); | ||
3351 | 729 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3352 | 730 | } | ||
3353 | 670 | 731 | ||
3354 | 671 | // This succeeds because the provider has written everything and disconnected. | 732 | // This succeeds because the provider has written everything and disconnected. |
3356 | 672 | ASSERT_NO_THROW(downloader->finish_download().waitForFinished()); | 733 | ASSERT_NO_THROW(call(downloader->finish_download())); |
3357 | 673 | } | 734 | } |
3358 | 674 | 735 | ||
3359 | 675 | { | 736 | { |
3360 | 676 | // Don't ever call read on large file. | 737 | // Don't ever call read on large file. |
3361 | 677 | QByteArray const contents(1024 * 1024, 'a'); | 738 | QByteArray const contents(1024 * 1024, 'a'); |
3369 | 678 | write_file(root, "file", contents); | 739 | auto file = write_file(root, "file", contents); |
3370 | 679 | 740 | ||
3371 | 680 | auto item = root->lookup("file").result()[0]; | 741 | auto downloader = call(file->create_downloader()); |
3365 | 681 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3366 | 682 | ASSERT_FALSE(file == nullptr); | ||
3367 | 683 | |||
3368 | 684 | auto downloader = file->create_downloader().result(); | ||
3372 | 685 | EXPECT_TRUE(file->equal_to(downloader->file())); | 742 | EXPECT_TRUE(file->equal_to(downloader->file())); |
3373 | 686 | 743 | ||
3374 | 744 | auto socket = downloader->socket(); | ||
3375 | 745 | |||
3376 | 687 | // Wait for first readyRead. Not all data fits into the socket buffer. | 746 | // Wait for first readyRead. Not all data fits into the socket buffer. |
3378 | 688 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::readyRead); | 747 | QSignalSpy spy(socket.get(), &QLocalSocket::readyRead); |
3379 | 689 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | 748 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
3380 | 690 | 749 | ||
3381 | 691 | // This fails because the provider still has data left to write. | 750 | // This fails because the provider still has data left to write. |
3382 | 692 | try | 751 | try |
3383 | 693 | { | 752 | { |
3385 | 694 | downloader->finish_download().waitForFinished(); | 753 | call(downloader->finish_download()); |
3386 | 695 | FAIL(); | 754 | FAIL(); |
3387 | 696 | } | 755 | } |
3388 | 697 | catch (StorageException const& e) | 756 | catch (StorageException const& e) |
3389 | @@ -703,25 +762,17 @@ | |||
3390 | 703 | { | 762 | { |
3391 | 704 | // Let downloader go out of scope. | 763 | // Let downloader go out of scope. |
3392 | 705 | QByteArray const contents(1024 * 1024, 'a'); | 764 | QByteArray const contents(1024 * 1024, 'a'); |
3400 | 706 | write_file(root, "file", contents); | 765 | auto file = write_file(root, "file", contents); |
3401 | 707 | 766 | ||
3402 | 708 | auto item = root->lookup("file").result()[0]; | 767 | auto downloader = call(file->create_downloader()); |
3396 | 709 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3397 | 710 | ASSERT_FALSE(file == nullptr); | ||
3398 | 711 | |||
3399 | 712 | auto downloader = file->create_downloader().result(); | ||
3403 | 713 | } | 768 | } |
3404 | 714 | 769 | ||
3405 | 715 | { | 770 | { |
3406 | 716 | // Let downloader future go out of scope. | 771 | // Let downloader future go out of scope. |
3407 | 717 | QByteArray const contents(1024 * 1024, 'a'); | 772 | QByteArray const contents(1024 * 1024, 'a'); |
3415 | 718 | write_file(root, "file", contents); | 773 | auto file = write_file(root, "file", contents); |
3416 | 719 | 774 | ||
3417 | 720 | auto item = root->lookup("file").result()[0]; | 775 | file->create_downloader(); |
3411 | 721 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3412 | 722 | ASSERT_FALSE(file == nullptr); | ||
3413 | 723 | |||
3414 | 724 | auto downloader_fut = file->create_downloader(); | ||
3418 | 725 | } | 776 | } |
3419 | 726 | } | 777 | } |
3420 | 727 | 778 | ||
3421 | @@ -736,65 +787,111 @@ | |||
3422 | 736 | { | 787 | { |
3423 | 737 | // Download enough bytes to prevent a single write in the provider from completing the download. | 788 | // Download enough bytes to prevent a single write in the provider from completing the download. |
3424 | 738 | QByteArray const contents(1024 * 1024, 'a'); | 789 | QByteArray const contents(1024 * 1024, 'a'); |
3439 | 739 | write_file(root, "file", contents); | 790 | auto file = write_file(root, "file", contents); |
3440 | 740 | 791 | ||
3441 | 741 | auto item = root->lookup("file").result()[0]; | 792 | auto downloader = call(file->create_downloader()); |
3428 | 742 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3429 | 743 | ASSERT_FALSE(file == nullptr); | ||
3430 | 744 | |||
3431 | 745 | auto download_fut = file->create_downloader(); | ||
3432 | 746 | { | ||
3433 | 747 | QFutureWatcher<Downloader::SPtr> w; | ||
3434 | 748 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
3435 | 749 | w.setFuture(download_fut); | ||
3436 | 750 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3437 | 751 | } | ||
3438 | 752 | auto downloader = download_fut.result(); | ||
3442 | 753 | 793 | ||
3443 | 754 | // We haven't read anything, so the cancel is guaranteed to catch the | 794 | // We haven't read anything, so the cancel is guaranteed to catch the |
3444 | 755 | // downloader in the in_progress state. | 795 | // downloader in the in_progress state. |
3453 | 756 | auto cancel_fut = downloader->cancel(); | 796 | downloader->cancel(); |
3454 | 757 | { | 797 | ASSERT_THROW(call(downloader->finish_download()), CancelledException); |
3447 | 758 | QFutureWatcher<void> w; | ||
3448 | 759 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
3449 | 760 | w.setFuture(cancel_fut); | ||
3450 | 761 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3451 | 762 | } | ||
3452 | 763 | ASSERT_THROW(downloader->finish_download().waitForFinished(), CancelledException); | ||
3455 | 764 | } | 798 | } |
3456 | 765 | 799 | ||
3457 | 766 | { | 800 | { |
3458 | 767 | // Download a few bytes. | 801 | // Download a few bytes. |
3459 | 768 | QByteArray const contents = "Hello\n"; | 802 | QByteArray const contents = "Hello\n"; |
3465 | 769 | write_file(root, "file", contents); | 803 | auto file = write_file(root, "file", contents); |
3461 | 770 | |||
3462 | 771 | auto item = root->lookup("file").result()[0]; | ||
3463 | 772 | File::SPtr file = dynamic_pointer_cast<File>(item); | ||
3464 | 773 | ASSERT_FALSE(file == nullptr); | ||
3466 | 774 | 804 | ||
3467 | 775 | // Finish the download. | 805 | // Finish the download. |
3469 | 776 | auto downloader = file->create_downloader().result(); | 806 | auto downloader = call(file->create_downloader()); |
3470 | 777 | auto socket = downloader->socket(); | 807 | auto socket = downloader->socket(); |
3471 | 778 | QByteArray buf; | 808 | QByteArray buf; |
3472 | 779 | do | 809 | do |
3473 | 780 | { | 810 | { |
3474 | 781 | // Need to pump the event loop while the socket does its thing. | 811 | // Need to pump the event loop while the socket does its thing. |
3475 | 782 | QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); | ||
3476 | 783 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3477 | 784 | auto bytes_to_read = socket->bytesAvailable(); | 812 | auto bytes_to_read = socket->bytesAvailable(); |
3478 | 813 | if (bytes_to_read == 0) | ||
3479 | 814 | { | ||
3480 | 815 | QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); | ||
3481 | 816 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3482 | 817 | } | ||
3483 | 785 | buf.append(socket->read(bytes_to_read)); | 818 | buf.append(socket->read(bytes_to_read)); |
3484 | 786 | } while (buf.size() < contents.size()); | 819 | } while (buf.size() < contents.size()); |
3485 | 787 | 820 | ||
3486 | 788 | // Wait for disconnected signal. | 821 | // Wait for disconnected signal. |
3489 | 789 | QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); | 822 | if (socket->state() != QLocalSocket::UnconnectedState) |
3490 | 790 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | 823 | { |
3491 | 824 | QSignalSpy spy(socket.get(), &QLocalSocket::disconnected); | ||
3492 | 825 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3493 | 826 | } | ||
3494 | 791 | 827 | ||
3495 | 792 | // Now send the cancel. The download is finished already, and the cancel | 828 | // Now send the cancel. The download is finished already, and the cancel |
3496 | 793 | // is too late, so finish_download() must report that the download | 829 | // is too late, so finish_download() must report that the download |
3497 | 794 | // worked OK. | 830 | // worked OK. |
3498 | 795 | downloader->cancel(); | 831 | downloader->cancel(); |
3501 | 796 | ASSERT_NO_THROW(downloader->finish_download().waitForFinished()); | 832 | ASSERT_NO_THROW(call(downloader->finish_download())); |
3502 | 797 | } | 833 | } |
3503 | 834 | } | ||
3504 | 835 | |||
3505 | 836 | TEST(File, download_error) | ||
3506 | 837 | { | ||
3507 | 838 | auto runtime = Runtime::create(); | ||
3508 | 839 | |||
3509 | 840 | auto acc = get_account(runtime); | ||
3510 | 841 | auto root = get_root(runtime); | ||
3511 | 842 | clear_folder(root); | ||
3512 | 843 | |||
3513 | 844 | QByteArray const contents(1024 * 1024, 'a'); | ||
3514 | 845 | auto file = write_file(root, "file", contents); | ||
3515 | 846 | |||
3516 | 847 | auto downloader = call(file->create_downloader()); | ||
3517 | 848 | EXPECT_TRUE(file->equal_to(downloader->file())); | ||
3518 | 849 | |||
3519 | 850 | auto socket = downloader->socket(); | ||
3520 | 851 | |||
3521 | 852 | { | ||
3522 | 853 | // Wait for first readyRead. Not all data fits into the socket buffer. | ||
3523 | 854 | QSignalSpy spy(socket.get(), &QLocalSocket::readyRead); | ||
3524 | 855 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3525 | 856 | } | ||
3526 | 857 | |||
3527 | 858 | { | ||
3528 | 859 | // Now close the socket, to force an error at the writing end. | ||
3529 | 860 | // This gives us coverage of the error handling logic in the download worker. | ||
3530 | 861 | socket->abort(); | ||
3531 | 862 | // Wait a little, to give the worker a chance to notice the problem. | ||
3532 | 863 | // We don't wait for a signal here because all attempts to disable the | ||
3533 | 864 | // socket (via close(), abort(), or disconnectFromServer() also | ||
3534 | 865 | // stop the stateChanged signal from arriving. | ||
3535 | 866 | QTimer timer; | ||
3536 | 867 | QSignalSpy spy(&timer, &QTimer::timeout); | ||
3537 | 868 | timer.start(1000); | ||
3538 | 869 | spy.wait(); | ||
3539 | 870 | } | ||
3540 | 871 | |||
3541 | 872 | try | ||
3542 | 873 | { | ||
3543 | 874 | call(downloader->finish_download()); | ||
3544 | 875 | FAIL(); | ||
3545 | 876 | } | ||
3546 | 877 | catch (ResourceException const& e) | ||
3547 | 878 | { | ||
3548 | 879 | EXPECT_TRUE(e.error_message().startsWith("Downloader: QLocalSocket: ")); | ||
3549 | 880 | } | ||
3550 | 881 | } | ||
3551 | 882 | |||
3552 | 883 | TEST(File, size_error) | ||
3553 | 884 | { | ||
3554 | 885 | auto runtime = Runtime::create(); | ||
3555 | 886 | |||
3556 | 887 | auto acc = get_account(runtime); | ||
3557 | 888 | auto root = get_root(runtime); | ||
3558 | 889 | clear_folder(root); | ||
3559 | 890 | |||
3560 | 891 | auto file = write_file(root, "file", ""); | ||
3561 | 892 | |||
3562 | 893 | ASSERT_EQ(0, system("rm " TEST_DIR "/storage-framework/file")); | ||
3563 | 894 | EXPECT_THROW(file->size(), ResourceException); | ||
3564 | 798 | } | 895 | } |
3565 | 799 | 896 | ||
3566 | 800 | TEST(Item, move) | 897 | TEST(Item, move) |
3567 | @@ -807,25 +904,22 @@ | |||
3568 | 807 | 904 | ||
3569 | 808 | // Check that rename works within the same folder. | 905 | // Check that rename works within the same folder. |
3570 | 809 | QByteArray const contents = "Hello\n"; | 906 | QByteArray const contents = "Hello\n"; |
3576 | 810 | write_file(root, "f1", contents); | 907 | auto f1 = write_file(root, "f1", contents); |
3577 | 811 | auto f1 = root->lookup("f1").result()[0]; | 908 | auto f2 = call(f1->move(root, "f2")); |
3573 | 812 | auto f2 = f1->move(root, "f2").result(); | ||
3574 | 813 | EXPECT_EQ("f2", f2->name()); | ||
3575 | 814 | EXPECT_THROW(f1->name(), DeletedException); // TODO: check exception details. | ||
3578 | 815 | 909 | ||
3579 | 816 | // File must be found under new name. | 910 | // File must be found under new name. |
3581 | 817 | auto items = root->list().result(); | 911 | auto items = call(root->list()); |
3582 | 818 | ASSERT_EQ(1, items.size()); | 912 | ASSERT_EQ(1, items.size()); |
3583 | 819 | f2 = dynamic_pointer_cast<File>(items[0]); | 913 | f2 = dynamic_pointer_cast<File>(items[0]); |
3584 | 820 | ASSERT_FALSE(f2 == nullptr); | 914 | ASSERT_FALSE(f2 == nullptr); |
3585 | 821 | 915 | ||
3586 | 822 | // Make a folder and move f2 into it. | 916 | // Make a folder and move f2 into it. |
3589 | 823 | auto folder = root->create_folder("folder").result(); | 917 | auto folder = call(root->create_folder("folder")); |
3590 | 824 | f2 = f2->move(folder, "f2").result(); | 918 | f2 = call(f2->move(folder, "f2")); |
3591 | 825 | EXPECT_TRUE(get_parent(f2)->equal_to(folder)); | 919 | EXPECT_TRUE(get_parent(f2)->equal_to(folder)); |
3592 | 826 | 920 | ||
3593 | 827 | // Move the folder | 921 | // Move the folder |
3595 | 828 | auto item = folder->move(root, "folder2").result(); | 922 | auto item = call(folder->move(root, "folder2")); |
3596 | 829 | folder = dynamic_pointer_cast<Folder>(item); | 923 | folder = dynamic_pointer_cast<Folder>(item); |
3597 | 830 | EXPECT_EQ("folder2", folder->name()); | 924 | EXPECT_EQ("folder2", folder->name()); |
3598 | 831 | } | 925 | } |
3599 | @@ -839,10 +933,8 @@ | |||
3600 | 839 | clear_folder(root); | 933 | clear_folder(root); |
3601 | 840 | 934 | ||
3602 | 841 | QByteArray const contents = "hello\n"; | 935 | QByteArray const contents = "hello\n"; |
3607 | 842 | write_file(root, "file", contents); | 936 | auto item = write_file(root, "file", contents); |
3608 | 843 | 937 | auto copied_item = call(item->copy(root, "copy_of_file")); | |
3605 | 844 | auto item = root->lookup("file").result()[0]; | ||
3606 | 845 | auto copied_item = item->copy(root, "copy_of_file").result(); | ||
3609 | 846 | EXPECT_EQ("copy_of_file", copied_item->name()); | 938 | EXPECT_EQ("copy_of_file", copied_item->name()); |
3610 | 847 | File::SPtr copied_file = dynamic_pointer_cast<File>(item); | 939 | File::SPtr copied_file = dynamic_pointer_cast<File>(item); |
3611 | 848 | ASSERT_NE(nullptr, copied_file); | 940 | ASSERT_NE(nullptr, copied_file); |
3612 | @@ -862,7 +954,9 @@ | |||
3613 | 862 | // folder/empty_folder | 954 | // folder/empty_folder |
3614 | 863 | // folder/non_empty_folder | 955 | // folder/non_empty_folder |
3615 | 864 | // folder/non_empty_folder/nested_file | 956 | // folder/non_empty_folder/nested_file |
3616 | 957 | // folder/non_empty_folder/<TMPFILE_PREFIX>1234-1234-1234-1234 | ||
3617 | 865 | // folder/file | 958 | // folder/file |
3618 | 959 | // folder/<TMPFILE_PREFIX>1234-1234-1234-1234 | ||
3619 | 866 | 960 | ||
3620 | 867 | string root_path = root->native_identity().toStdString(); | 961 | string root_path = root->native_identity().toStdString(); |
3621 | 868 | ASSERT_EQ(0, mkdir((root_path + "/folder").c_str(), 0700)); | 962 | ASSERT_EQ(0, mkdir((root_path + "/folder").c_str(), 0700)); |
3622 | @@ -871,23 +965,26 @@ | |||
3623 | 871 | ofstream(root_path + "/folder/non_empty_folder/nested_file"); | 965 | ofstream(root_path + "/folder/non_empty_folder/nested_file"); |
3624 | 872 | ofstream(root_path + "/folder/file"); | 966 | ofstream(root_path + "/folder/file"); |
3625 | 873 | 967 | ||
3626 | 968 | // Add dirs that look like a tmp dirs, to get coverage on skipping those. | ||
3627 | 969 | ASSERT_EQ(0, mkdir((root_path + "/folder/" + TMPFILE_PREFIX "1234-1234-1234-1234").c_str(), 0700)); | ||
3628 | 970 | ASSERT_EQ(0, mkdir((root_path + "/folder/non_empty_folder/" + TMPFILE_PREFIX "1234-1234-1234-1234").c_str(), 0700)); | ||
3629 | 874 | // Copy folder to folder2 | 971 | // Copy folder to folder2 |
3631 | 875 | auto folder = dynamic_pointer_cast<Folder>(root->lookup("folder").result()[0]); | 972 | auto folder = dynamic_pointer_cast<Folder>(call(root->lookup("folder"))[0]); |
3632 | 876 | ASSERT_NE(nullptr, folder); | 973 | ASSERT_NE(nullptr, folder); |
3634 | 877 | auto item = folder->copy(root, "folder2").result(); | 974 | auto item = call(folder->copy(root, "folder2")); |
3635 | 878 | 975 | ||
3636 | 879 | // Verify that folder2 now contains the same structure as folder. | 976 | // Verify that folder2 now contains the same structure as folder. |
3637 | 880 | auto folder2 = dynamic_pointer_cast<Folder>(item); | 977 | auto folder2 = dynamic_pointer_cast<Folder>(item); |
3638 | 881 | ASSERT_NE(nullptr, folder2); | 978 | ASSERT_NE(nullptr, folder2); |
3641 | 882 | EXPECT_NO_THROW(folder2->lookup("empty_folder").result()[0]); | 979 | EXPECT_NO_THROW(call(folder2->lookup("empty_folder"))[0]); |
3642 | 883 | item = folder2->lookup("non_empty_folder").result()[0]; | 980 | item = call(folder2->lookup("non_empty_folder"))[0]; |
3643 | 884 | auto non_empty_folder = dynamic_pointer_cast<Folder>(item); | 981 | auto non_empty_folder = dynamic_pointer_cast<Folder>(item); |
3644 | 885 | ASSERT_NE(nullptr, non_empty_folder); | 982 | ASSERT_NE(nullptr, non_empty_folder); |
3647 | 886 | EXPECT_NO_THROW(non_empty_folder->lookup("nested_file").result()[0]); | 983 | EXPECT_NO_THROW(call(non_empty_folder->lookup("nested_file"))[0]); |
3648 | 887 | EXPECT_NO_THROW(folder2->lookup("file").result()[0]); | 984 | EXPECT_NO_THROW(call(folder2->lookup("file"))[0]); |
3649 | 888 | } | 985 | } |
3650 | 889 | 986 | ||
3652 | 890 | TEST(Item, modified_time) | 987 | TEST(Item, time) |
3653 | 891 | { | 988 | { |
3654 | 892 | auto runtime = Runtime::create(); | 989 | auto runtime = Runtime::create(); |
3655 | 893 | 990 | ||
3656 | @@ -897,19 +994,15 @@ | |||
3657 | 897 | 994 | ||
3658 | 898 | auto now = QDateTime::currentDateTimeUtc(); | 995 | auto now = QDateTime::currentDateTimeUtc(); |
3659 | 899 | sleep(1); | 996 | sleep(1); |
3669 | 900 | auto uploader = root->create_file("file", 0).result(); | 997 | auto uploader = call(root->create_file("file", 0)); |
3670 | 901 | auto file_fut = uploader->finish_upload(); | 998 | auto file = call(uploader->finish_upload()); |
3662 | 902 | { | ||
3663 | 903 | QFutureWatcher<File::SPtr> w; | ||
3664 | 904 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
3665 | 905 | w.setFuture(file_fut); | ||
3666 | 906 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3667 | 907 | } | ||
3668 | 908 | auto file = file_fut.result(); | ||
3671 | 909 | auto t = file->last_modified_time(); | 999 | auto t = file->last_modified_time(); |
3672 | 910 | // Rough check that the time is sane. | 1000 | // Rough check that the time is sane. |
3673 | 911 | EXPECT_LE(now, t); | 1001 | EXPECT_LE(now, t); |
3674 | 912 | EXPECT_LE(t, now.addSecs(5)); | 1002 | EXPECT_LE(t, now.addSecs(5)); |
3675 | 1003 | |||
3676 | 1004 | auto creation_time = file->creation_time(); | ||
3677 | 1005 | EXPECT_FALSE(creation_time.isValid()); | ||
3678 | 913 | } | 1006 | } |
3679 | 914 | 1007 | ||
3680 | 915 | TEST(Item, comparison) | 1008 | TEST(Item, comparison) |
3681 | @@ -921,41 +1014,1436 @@ | |||
3682 | 921 | clear_folder(root); | 1014 | clear_folder(root); |
3683 | 922 | 1015 | ||
3684 | 923 | // Create two files. | 1016 | // Create two files. |
3694 | 924 | auto uploader = root->create_file("file1", 0).result(); | 1017 | auto uploader = call(root->create_file("file1", 0)); |
3695 | 925 | auto file_fut = uploader->finish_upload(); | 1018 | auto file1 = call(uploader->finish_upload()); |
3687 | 926 | { | ||
3688 | 927 | QFutureWatcher<File::SPtr> w; | ||
3689 | 928 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
3690 | 929 | w.setFuture(file_fut); | ||
3691 | 930 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3692 | 931 | } | ||
3693 | 932 | auto file1 = file_fut.result(); | ||
3696 | 933 | 1019 | ||
3706 | 934 | uploader = root->create_file("file2", 0).result(); | 1020 | uploader = call(root->create_file("file2", 0)); |
3707 | 935 | file_fut = uploader->finish_upload(); | 1021 | auto file2 = call(uploader->finish_upload()); |
3699 | 936 | { | ||
3700 | 937 | QFutureWatcher<File::SPtr> w; | ||
3701 | 938 | QSignalSpy spy(&w, &decltype(w)::finished); | ||
3702 | 939 | w.setFuture(file_fut); | ||
3703 | 940 | ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); | ||
3704 | 941 | } | ||
3705 | 942 | auto file2 = file_fut.result(); | ||
3708 | 943 | 1022 | ||
3709 | 944 | EXPECT_FALSE(file1->equal_to(file2)); | 1023 | EXPECT_FALSE(file1->equal_to(file2)); |
3710 | 945 | 1024 | ||
3711 | 946 | // Retrieve file1 via lookup, so we get a different proxy. | 1025 | // Retrieve file1 via lookup, so we get a different proxy. |
3713 | 947 | auto item = root->lookup("file1").result()[0]; | 1026 | auto item = call(root->lookup("file1"))[0]; |
3714 | 948 | auto other_file1 = dynamic_pointer_cast<File>(item); | 1027 | auto other_file1 = dynamic_pointer_cast<File>(item); |
3715 | 949 | EXPECT_NE(file1, other_file1); // Compares shared_ptr values | 1028 | EXPECT_NE(file1, other_file1); // Compares shared_ptr values |
3716 | 950 | EXPECT_TRUE(file1->equal_to(other_file1)); // Deep comparison | 1029 | EXPECT_TRUE(file1->equal_to(other_file1)); // Deep comparison |
3717 | 1030 | |||
3718 | 1031 | // Comparing against a deleted file must return false. | ||
3719 | 1032 | call(file1->delete_item()); | ||
3720 | 1033 | EXPECT_FALSE(file1->equal_to(file2)); | ||
3721 | 1034 | EXPECT_FALSE(file2->equal_to(file1)); | ||
3722 | 1035 | |||
3723 | 1036 | // Delete file2 as well and compare again. | ||
3724 | 1037 | call(file2->delete_item()); | ||
3725 | 1038 | EXPECT_FALSE(file1->equal_to(file2)); | ||
3726 | 1039 | } | ||
3727 | 1040 | |||
3728 | 1041 | TEST(Item, exceptions) | ||
3729 | 1042 | { | ||
3730 | 1043 | auto runtime = Runtime::create(); | ||
3731 | 1044 | |||
3732 | 1045 | auto acc = get_account(runtime); | ||
3733 | 1046 | auto root = get_root(runtime); | ||
3734 | 1047 | clear_folder(root); | ||
3735 | 1048 | |||
3736 | 1049 | try | ||
3737 | 1050 | { | ||
3738 | 1051 | call(root->copy(nullptr, "new name")); | ||
3739 | 1052 | FAIL(); | ||
3740 | 1053 | } | ||
3741 | 1054 | catch (InvalidArgumentException const& e) | ||
3742 | 1055 | { | ||
3743 | 1056 | EXPECT_EQ("Item::copy(): new_parent cannot be nullptr", e.error_message()); | ||
3744 | 1057 | } | ||
3745 | 1058 | |||
3746 | 1059 | auto file = write_file(root, "file", 0); | ||
3747 | 1060 | |||
3748 | 1061 | try | ||
3749 | 1062 | { | ||
3750 | 1063 | call(file->copy(root, TMPFILE_PREFIX "copy_of_file")); | ||
3751 | 1064 | FAIL(); | ||
3752 | 1065 | } | ||
3753 | 1066 | catch (InvalidArgumentException const& e) | ||
3754 | 1067 | { | ||
3755 | 1068 | EXPECT_EQ("Item::copy(): names beginning with \".storage-framework-\" are reserved", e.error_message()); | ||
3756 | 1069 | } | ||
3757 | 1070 | |||
3758 | 1071 | try | ||
3759 | 1072 | { | ||
3760 | 1073 | call(file->copy(root, file->name())); | ||
3761 | 1074 | FAIL(); | ||
3762 | 1075 | } | ||
3763 | 1076 | catch (ExistsException const& e) | ||
3764 | 1077 | { | ||
3765 | 1078 | EXPECT_EQ("Item::copy(): item with name \"file\" exists already", e.error_message()); | ||
3766 | 1079 | EXPECT_EQ("file", e.name()); | ||
3767 | 1080 | EXPECT_EQ(TEST_DIR "/storage-framework/file", e.native_identity()); | ||
3768 | 1081 | } | ||
3769 | 1082 | |||
3770 | 1083 | try | ||
3771 | 1084 | { | ||
3772 | 1085 | auto file = write_file(root, "file", ""); | ||
3773 | 1086 | ASSERT_EQ(0, unlink(file->native_identity().toStdString().c_str())); | ||
3774 | 1087 | |||
3775 | 1088 | call(file->copy(root, file->name())); | ||
3776 | 1089 | FAIL(); | ||
3777 | 1090 | } | ||
3778 | 1091 | catch (ResourceException const& e) | ||
3779 | 1092 | { | ||
3780 | 1093 | EXPECT_TRUE(e.error_message().startsWith("Item::copy(): ")); | ||
3781 | 1094 | } | ||
3782 | 1095 | |||
3783 | 1096 | try | ||
3784 | 1097 | { | ||
3785 | 1098 | auto file = write_file(root, "file", ""); | ||
3786 | 1099 | ASSERT_EQ(0, unlink(file->native_identity().toStdString().c_str())); | ||
3787 | 1100 | |||
3788 | 1101 | call(file->move(root, "new_name")); | ||
3789 | 1102 | FAIL(); | ||
3790 | 1103 | } | ||
3791 | 1104 | catch (ResourceException const& e) | ||
3792 | 1105 | { | ||
3793 | 1106 | EXPECT_TRUE(e.error_message().startsWith("Item::move(): ")); | ||
3794 | 1107 | } | ||
3795 | 1108 | |||
3796 | 1109 | try | ||
3797 | 1110 | { | ||
3798 | 1111 | auto file = write_file(root, "file", ""); | ||
3799 | 1112 | ASSERT_EQ(0, unlink(file->native_identity().toStdString().c_str())); | ||
3800 | 1113 | ASSERT_EQ(0, system("chmod -x " TEST_DIR "/storage-framework")); | ||
3801 | 1114 | |||
3802 | 1115 | call(file->delete_item()); | ||
3803 | 1116 | ASSERT_EQ(0, system("chmod +x " TEST_DIR "/storage-framework")); | ||
3804 | 1117 | FAIL(); | ||
3805 | 1118 | } | ||
3806 | 1119 | catch (ResourceException const& e) | ||
3807 | 1120 | { | ||
3808 | 1121 | ASSERT_EQ(0, system("chmod +x " TEST_DIR "/storage-framework")); | ||
3809 | 1122 | EXPECT_TRUE(e.error_message().startsWith("Item::delete_item(): ")); | ||
3810 | 1123 | } | ||
3811 | 1124 | catch (std::exception const&) | ||
3812 | 1125 | { | ||
3813 | 1126 | ASSERT_EQ(0, system("chmod +x " TEST_DIR "/storage-framework")); | ||
3814 | 1127 | FAIL(); | ||
3815 | 1128 | } | ||
3816 | 1129 | |||
3817 | 1130 | try | ||
3818 | 1131 | { | ||
3819 | 1132 | call(root->move(nullptr, "new name")); | ||
3820 | 1133 | FAIL(); | ||
3821 | 1134 | } | ||
3822 | 1135 | catch (InvalidArgumentException const& e) | ||
3823 | 1136 | { | ||
3824 | 1137 | EXPECT_EQ("Item::move(): new_parent cannot be nullptr", e.error_message()); | ||
3825 | 1138 | } | ||
3826 | 1139 | |||
3827 | 1140 | try | ||
3828 | 1141 | { | ||
3829 | 1142 | call(root->move(root, "new name")); | ||
3830 | 1143 | FAIL(); | ||
3831 | 1144 | } | ||
3832 | 1145 | catch (LogicException const& e) | ||
3833 | 1146 | { | ||
3834 | 1147 | EXPECT_EQ("Item::move(): cannot move root folder", e.error_message()); | ||
3835 | 1148 | } | ||
3836 | 1149 | |||
3837 | 1150 | try | ||
3838 | 1151 | { | ||
3839 | 1152 | auto file = write_file(root, "file", ""); | ||
3840 | 1153 | call(file->move(root, file->name())); | ||
3841 | 1154 | FAIL(); | ||
3842 | 1155 | } | ||
3843 | 1156 | catch (ExistsException const& e) | ||
3844 | 1157 | { | ||
3845 | 1158 | EXPECT_EQ("Item::move(): item with name \"file\" exists already", e.error_message()); | ||
3846 | 1159 | EXPECT_EQ("file", e.name()); | ||
3847 | 1160 | EXPECT_EQ(TEST_DIR "/storage-framework/file", e.native_identity()); | ||
3848 | 1161 | } | ||
3849 | 1162 | |||
3850 | 1163 | try | ||
3851 | 1164 | { | ||
3852 | 1165 | call(file->move(root, TMPFILE_PREFIX "copy_of_file")); | ||
3853 | 1166 | FAIL(); | ||
3854 | 1167 | } | ||
3855 | 1168 | catch (InvalidArgumentException const& e) | ||
3856 | 1169 | { | ||
3857 | 1170 | EXPECT_EQ("Item::move(): names beginning with \".storage-framework-\" are reserved", e.error_message()); | ||
3858 | 1171 | } | ||
3859 | 1172 | |||
3860 | 1173 | try | ||
3861 | 1174 | { | ||
3862 | 1175 | call(root->lookup("abc/def")); | ||
3863 | 1176 | } | ||
3864 | 1177 | catch (InvalidArgumentException const& e) | ||
3865 | 1178 | { | ||
3866 | 1179 | EXPECT_EQ("Folder::lookup(): name \"abc/def\" contains more than one path component", | ||
3867 | 1180 | e.error_message()) << e.what(); | ||
3868 | 1181 | } | ||
3869 | 1182 | |||
3870 | 1183 | try | ||
3871 | 1184 | { | ||
3872 | 1185 | call(root->create_folder("..")); | ||
3873 | 1186 | } | ||
3874 | 1187 | catch (InvalidArgumentException const& e) | ||
3875 | 1188 | { | ||
3876 | 1189 | EXPECT_EQ("Folder::create_folder(): invalid name: \"..\"", e.error_message()) << e.what(); | ||
3877 | 1190 | } | ||
3878 | 1191 | } | ||
3879 | 1192 | |||
3880 | 1193 | TEST(Folder, exceptions) | ||
3881 | 1194 | { | ||
3882 | 1195 | auto runtime = Runtime::create(); | ||
3883 | 1196 | |||
3884 | 1197 | auto acc = get_account(runtime); | ||
3885 | 1198 | auto root = get_root(runtime); | ||
3886 | 1199 | clear_folder(root); | ||
3887 | 1200 | |||
3888 | 1201 | try | ||
3889 | 1202 | { | ||
3890 | 1203 | write_file(root, TMPFILE_PREFIX "file", ""); | ||
3891 | 1204 | call(root->lookup(TMPFILE_PREFIX "file")); | ||
3892 | 1205 | FAIL(); | ||
3893 | 1206 | } | ||
3894 | 1207 | catch (NotExistsException const& e) | ||
3895 | 1208 | { | ||
3896 | 1209 | string cmd = "rm "; | ||
3897 | 1210 | cmd += string(TEST_DIR) + "/storage-framework/" + TMPFILE_PREFIX "file"; | ||
3898 | 1211 | ASSERT_EQ(0, system(cmd.c_str())); | ||
3899 | 1212 | EXPECT_EQ("Folder::lookup(): no such item: \".storage-framework-file\"", e.error_message()); | ||
3900 | 1213 | EXPECT_EQ(".storage-framework-file", e.key()); | ||
3901 | 1214 | } | ||
3902 | 1215 | |||
3903 | 1216 | { | ||
3904 | 1217 | auto fifo_id = root->native_identity() + "/fifo"; | ||
3905 | 1218 | string cmd = "mkfifo " + fifo_id.toStdString(); | ||
3906 | 1219 | ASSERT_EQ(0, system(cmd.c_str())); | ||
3907 | 1220 | |||
3908 | 1221 | try | ||
3909 | 1222 | { | ||
3910 | 1223 | call(root->lookup("fifo")); | ||
3911 | 1224 | FAIL(); | ||
3912 | 1225 | } | ||
3913 | 1226 | catch (NotExistsException const& e) | ||
3914 | 1227 | { | ||
3915 | 1228 | EXPECT_EQ("Folder::lookup(): no such item: \"fifo\"", e.error_message()) << e.what(); | ||
3916 | 1229 | EXPECT_EQ("fifo", e.key()); | ||
3917 | 1230 | } | ||
3918 | 1231 | |||
3919 | 1232 | cmd = "rm " + fifo_id.toStdString(); | ||
3920 | 1233 | ASSERT_EQ(0, system(cmd.c_str())); | ||
3921 | 1234 | } | ||
3922 | 1235 | |||
3923 | 1236 | try | ||
3924 | 1237 | { | ||
3925 | 1238 | call(root->lookup("no_such_file")); | ||
3926 | 1239 | FAIL(); | ||
3927 | 1240 | } | ||
3928 | 1241 | catch (NotExistsException const& e) | ||
3929 | 1242 | { | ||
3930 | 1243 | EXPECT_EQ("Folder::lookup(): no such item: \"no_such_file\"", e.error_message()); | ||
3931 | 1244 | EXPECT_EQ("no_such_file", e.key()); | ||
3932 | 1245 | } | ||
3933 | 1246 | |||
3934 | 1247 | try | ||
3935 | 1248 | { | ||
3936 | 1249 | call(root->create_folder(TMPFILE_PREFIX "folder")); | ||
3937 | 1250 | FAIL(); | ||
3938 | 1251 | } | ||
3939 | 1252 | catch (InvalidArgumentException const& e) | ||
3940 | 1253 | { | ||
3941 | 1254 | EXPECT_EQ("Folder::create_folder(): names beginning with \".storage-framework-\" are reserved", e.error_message()); | ||
3942 | 1255 | } | ||
3943 | 1256 | |||
3944 | 1257 | try | ||
3945 | 1258 | { | ||
3946 | 1259 | EXPECT_NO_THROW(call(root->create_folder("folder"))); | ||
3947 | 1260 | call(root->create_folder("folder")); | ||
3948 | 1261 | FAIL(); | ||
3949 | 1262 | } | ||
3950 | 1263 | catch (ExistsException const& e) | ||
3951 | 1264 | { | ||
3952 | 1265 | EXPECT_EQ("Folder::create_folder(): item with name \"folder\" exists already", e.error_message()); | ||
3953 | 1266 | EXPECT_EQ("folder", e.name()); | ||
3954 | 1267 | EXPECT_EQ(TEST_DIR "/storage-framework/folder", e.native_identity()); | ||
3955 | 1268 | } | ||
3956 | 1269 | |||
3957 | 1270 | try | ||
3958 | 1271 | { | ||
3959 | 1272 | call(root->create_file("new_file", -1)); | ||
3960 | 1273 | FAIL(); | ||
3961 | 1274 | } | ||
3962 | 1275 | catch (InvalidArgumentException const& e) | ||
3963 | 1276 | { | ||
3964 | 1277 | EXPECT_EQ("Folder::create_file(): size must be >= 0", e.error_message()); | ||
3965 | 1278 | } | ||
3966 | 1279 | |||
3967 | 1280 | try | ||
3968 | 1281 | { | ||
3969 | 1282 | call(root->create_file(TMPFILE_PREFIX "new_file", 0)); | ||
3970 | 1283 | FAIL(); | ||
3971 | 1284 | } | ||
3972 | 1285 | catch (InvalidArgumentException const& e) | ||
3973 | 1286 | { | ||
3974 | 1287 | EXPECT_EQ("Folder::create_file(): names beginning with \".storage-framework-\" are reserved", e.error_message()); | ||
3975 | 1288 | } | ||
3976 | 1289 | |||
3977 | 1290 | try | ||
3978 | 1291 | { | ||
3979 | 1292 | write_file(root, "file", ""); | ||
3980 | 1293 | call(root->create_file("file", 0)); | ||
3981 | 1294 | FAIL(); | ||
3982 | 1295 | } | ||
3983 | 1296 | catch (ExistsException const& e) | ||
3984 | 1297 | { | ||
3985 | 1298 | EXPECT_EQ("Folder::create_file(): item with name \"file\" exists already", e.error_message()); | ||
3986 | 1299 | EXPECT_EQ("file", e.name()); | ||
3987 | 1300 | EXPECT_EQ(TEST_DIR "/storage-framework/file", e.native_identity()); | ||
3988 | 1301 | } | ||
3989 | 1302 | |||
3990 | 1303 | ASSERT_EQ(0, system("chmod -x " TEST_DIR "/storage-framework")); | ||
3991 | 1304 | try | ||
3992 | 1305 | { | ||
3993 | 1306 | call(root->create_file("new_file", 0)); | ||
3994 | 1307 | ASSERT_EQ(0, system("chmod +x " TEST_DIR "/storage-framework")); | ||
3995 | 1308 | FAIL(); | ||
3996 | 1309 | } | ||
3997 | 1310 | catch (ResourceException const& e) | ||
3998 | 1311 | { | ||
3999 | 1312 | EXPECT_TRUE(e.error_message().startsWith("Folder::create_file(): ")); | ||
4000 | 1313 | EXPECT_EQ(EACCES, e.error_code()); | ||
4001 | 1314 | ASSERT_EQ(0, system("chmod +x " TEST_DIR "/storage-framework")); | ||
4002 | 1315 | } | ||
4003 | 1316 | catch (std::exception const& e) | ||
4004 | 1317 | { | ||
4005 | 1318 | ASSERT_EQ(0, system("chmod +x " TEST_DIR "/storage-framework")); | ||
4006 | 1319 | FAIL(); | ||
4007 | 1320 | } | ||
4008 | 1321 | |||
4009 | 1322 | ASSERT_EQ(0, system("chmod -x " TEST_DIR "/storage-framework")); | ||
4010 | 1323 | try | ||
4011 | 1324 | { | ||
4012 | 1325 | call(root->create_folder("new_folder")); | ||
4013 | 1326 | ASSERT_EQ(0, system("chmod +x " TEST_DIR "/storage-framework")); | ||
4014 | 1327 | FAIL(); | ||
4015 | 1328 | } | ||
4016 | 1329 | catch (ResourceException const& e) | ||
4017 | 1330 | { | ||
4018 | 1331 | EXPECT_TRUE(e.error_message().startsWith("Folder::create_folder(): ")); | ||
4019 | 1332 | EXPECT_EQ(EACCES, e.error_code()); | ||
4020 | 1333 | ASSERT_EQ(0, system("chmod +x " TEST_DIR "/storage-framework")); | ||
4021 | 1334 | } | ||
4022 | 1335 | catch (std::exception const& e) | ||
4023 | 1336 | { | ||
4024 | 1337 | ASSERT_EQ(0, system("chmod +x " TEST_DIR "/storage-framework")); | ||
4025 | 1338 | FAIL(); | ||
4026 | 1339 | } | ||
4027 | 1340 | |||
4028 | 1341 | try | ||
4029 | 1342 | { | ||
4030 | 1343 | call(root->create_file("new_file", -1)); | ||
4031 | 1344 | } | ||
4032 | 1345 | catch (InvalidArgumentException const& e) | ||
4033 | 1346 | { | ||
4034 | 1347 | EXPECT_EQ("Folder::create_file(): size must be >= 0", e.error_message()); | ||
4035 | 1348 | } | ||
4036 | 1349 | } | ||
4037 | 1350 | |||
4038 | 1351 | TEST(Root, root_exceptions) | ||
4039 | 1352 | { | ||
4040 | 1353 | auto runtime = Runtime::create(); | ||
4041 | 1354 | |||
4042 | 1355 | auto acc = get_account(runtime); | ||
4043 | 1356 | auto root = get_root(runtime); | ||
4044 | 1357 | clear_folder(root); | ||
4045 | 1358 | |||
4046 | 1359 | try | ||
4047 | 1360 | { | ||
4048 | 1361 | call(root->delete_item()); | ||
4049 | 1362 | FAIL(); | ||
4050 | 1363 | } | ||
4051 | 1364 | catch (LogicException const& e) | ||
4052 | 1365 | { | ||
4053 | 1366 | EXPECT_EQ("Root::delete_item(): Cannot delete root folder", e.error_message()); | ||
4054 | 1367 | } | ||
4055 | 1368 | |||
4056 | 1369 | try | ||
4057 | 1370 | { | ||
4058 | 1371 | call(root->get("abc")); | ||
4059 | 1372 | FAIL(); | ||
4060 | 1373 | } | ||
4061 | 1374 | catch (InvalidArgumentException const& e) | ||
4062 | 1375 | { | ||
4063 | 1376 | EXPECT_EQ("Root::get(): identity \"abc\" must be an absolute path", e.error_message()); | ||
4064 | 1377 | } | ||
4065 | 1378 | |||
4066 | 1379 | try | ||
4067 | 1380 | { | ||
4068 | 1381 | call(root->get("/etc")); | ||
4069 | 1382 | FAIL(); | ||
4070 | 1383 | } | ||
4071 | 1384 | catch (InvalidArgumentException const& e) | ||
4072 | 1385 | { | ||
4073 | 1386 | EXPECT_EQ("Root::get(): identity \"/etc\" points outside the root folder", e.error_message()); | ||
4074 | 1387 | } | ||
4075 | 1388 | |||
4076 | 1389 | { | ||
4077 | 1390 | auto folder = call(root->create_folder("folder")); | ||
4078 | 1391 | auto file = write_file(folder, "testfile", "hello"); | ||
4079 | 1392 | |||
4080 | 1393 | // Remove permission from folder. | ||
4081 | 1394 | string cmd = "chmod -x " + folder->native_identity().toStdString(); | ||
4082 | 1395 | ASSERT_EQ(0, system(cmd.c_str())); | ||
4083 | 1396 | |||
4084 | 1397 | try | ||
4085 | 1398 | { | ||
4086 | 1399 | file = dynamic_pointer_cast<File>(call(root->get(file->native_identity()))); | ||
4087 | 1400 | FAIL(); | ||
4088 | 1401 | } | ||
4089 | 1402 | catch (PermissionException const& e) | ||
4090 | 1403 | { | ||
4091 | 1404 | EXPECT_TRUE(e.error_message().startsWith("Root::get(): ")); | ||
4092 | 1405 | EXPECT_TRUE(e.error_message().contains("Permission denied")); | ||
4093 | 1406 | } | ||
4094 | 1407 | |||
4095 | 1408 | cmd = "chmod +x " + folder->native_identity().toStdString(); | ||
4096 | 1409 | ASSERT_EQ(0, system(cmd.c_str())); | ||
4097 | 1410 | |||
4098 | 1411 | clear_folder(root); | ||
4099 | 1412 | } | ||
4100 | 1413 | |||
4101 | 1414 | { | ||
4102 | 1415 | auto file = write_file(root, "testfile", "hello"); | ||
4103 | 1416 | |||
4104 | 1417 | QString id = file->native_identity(); | ||
4105 | 1418 | id.append("_doesnt_exist"); | ||
4106 | 1419 | |||
4107 | 1420 | try | ||
4108 | 1421 | { | ||
4109 | 1422 | file = dynamic_pointer_cast<File>(call(root->get(id))); | ||
4110 | 1423 | FAIL(); | ||
4111 | 1424 | } | ||
4112 | 1425 | catch (NotExistsException const& e) | ||
4113 | 1426 | { | ||
4114 | 1427 | EXPECT_EQ(id, e.key()); | ||
4115 | 1428 | } | ||
4116 | 1429 | |||
4117 | 1430 | clear_folder(root); | ||
4118 | 1431 | } | ||
4119 | 1432 | |||
4120 | 1433 | { | ||
4121 | 1434 | auto fifo_id = root->native_identity() + "/fifo"; | ||
4122 | 1435 | string cmd = "mkfifo " + fifo_id.toStdString(); | ||
4123 | 1436 | ASSERT_EQ(0, system(cmd.c_str())); | ||
4124 | 1437 | |||
4125 | 1438 | try | ||
4126 | 1439 | { | ||
4127 | 1440 | call(root->get(fifo_id)); | ||
4128 | 1441 | FAIL(); | ||
4129 | 1442 | } | ||
4130 | 1443 | catch (NotExistsException const& e) | ||
4131 | 1444 | { | ||
4132 | 1445 | EXPECT_EQ(fifo_id, e.key()); | ||
4133 | 1446 | } | ||
4134 | 1447 | |||
4135 | 1448 | cmd = "rm " + fifo_id.toStdString(); | ||
4136 | 1449 | ASSERT_EQ(0, system(cmd.c_str())); | ||
4137 | 1450 | } | ||
4138 | 1451 | |||
4139 | 1452 | { | ||
4140 | 1453 | string reserved_name = TMPFILE_PREFIX "somefile"; | ||
4141 | 1454 | string full_path = string(TEST_DIR) + "/storage-framework/" + reserved_name; | ||
4142 | 1455 | string cmd = "touch "; | ||
4143 | 1456 | cmd += full_path; | ||
4144 | 1457 | ASSERT_EQ(0, system(cmd.c_str())); | ||
4145 | 1458 | |||
4146 | 1459 | auto reserved_id = QString::fromStdString(full_path); | ||
4147 | 1460 | try | ||
4148 | 1461 | { | ||
4149 | 1462 | call(root->get(reserved_id)); | ||
4150 | 1463 | FAIL(); | ||
4151 | 1464 | } | ||
4152 | 1465 | catch (NotExistsException const& e) | ||
4153 | 1466 | { | ||
4154 | 1467 | EXPECT_EQ(reserved_id, e.key()); | ||
4155 | 1468 | } | ||
4156 | 1469 | |||
4157 | 1470 | clear_folder(root); | ||
4158 | 1471 | } | ||
4159 | 1472 | } | ||
4160 | 1473 | |||
4161 | 1474 | TEST(Item, deleted_exceptions) | ||
4162 | 1475 | { | ||
4163 | 1476 | auto runtime = Runtime::create(); | ||
4164 | 1477 | |||
4165 | 1478 | auto acc = get_account(runtime); | ||
4166 | 1479 | auto root = get_root(runtime); | ||
4167 | 1480 | clear_folder(root); | ||
4168 | 1481 | |||
4169 | 1482 | try | ||
4170 | 1483 | { | ||
4171 | 1484 | auto file = make_deleted_file(root, "file"); | ||
4172 | 1485 | file->etag(); | ||
4173 | 1486 | FAIL(); | ||
4174 | 1487 | } | ||
4175 | 1488 | catch (DeletedException const& e) | ||
4176 | 1489 | { | ||
4177 | 1490 | EXPECT_EQ("file", e.name()); | ||
4178 | 1491 | EXPECT_TRUE(e.error_message().startsWith("Item::etag(): ")); | ||
4179 | 1492 | EXPECT_TRUE(e.error_message().endsWith(" was deleted previously")); | ||
4180 | 1493 | EXPECT_EQ(TEST_DIR "/storage-framework/file", e.native_identity()); | ||
4181 | 1494 | } | ||
4182 | 1495 | |||
4183 | 1496 | try | ||
4184 | 1497 | { | ||
4185 | 1498 | auto file = make_deleted_file(root, "file"); | ||
4186 | 1499 | file->metadata(); | ||
4187 | 1500 | FAIL(); | ||
4188 | 1501 | } | ||
4189 | 1502 | catch (DeletedException const& e) | ||
4190 | 1503 | { | ||
4191 | 1504 | EXPECT_EQ("file", e.name()); | ||
4192 | 1505 | EXPECT_TRUE(e.error_message().startsWith("Item::metadata(): ")); | ||
4193 | 1506 | } | ||
4194 | 1507 | |||
4195 | 1508 | try | ||
4196 | 1509 | { | ||
4197 | 1510 | auto file = make_deleted_file(root, "file"); | ||
4198 | 1511 | file->last_modified_time(); | ||
4199 | 1512 | FAIL(); | ||
4200 | 1513 | } | ||
4201 | 1514 | catch (DeletedException const& e) | ||
4202 | 1515 | { | ||
4203 | 1516 | EXPECT_EQ("file", e.name()); | ||
4204 | 1517 | EXPECT_TRUE(e.error_message().startsWith("Item::last_modified_time(): ")); | ||
4205 | 1518 | } | ||
4206 | 1519 | |||
4207 | 1520 | try | ||
4208 | 1521 | { | ||
4209 | 1522 | // Copying deleted file must fail. | ||
4210 | 1523 | auto file = make_deleted_file(root, "file"); | ||
4211 | 1524 | call(file->copy(root, "copy_of_file")); | ||
4212 | 1525 | FAIL(); | ||
4213 | 1526 | } | ||
4214 | 1527 | catch (DeletedException const& e) | ||
4215 | 1528 | { | ||
4216 | 1529 | EXPECT_EQ("file", e.name()); | ||
4217 | 1530 | EXPECT_TRUE(e.error_message().startsWith("Item::copy(): ")); | ||
4218 | 1531 | } | ||
4219 | 1532 | |||
4220 | 1533 | try | ||
4221 | 1534 | { | ||
4222 | 1535 | // Copying file into deleted folder must fail. | ||
4223 | 1536 | |||
4224 | 1537 | // Make target folder. | ||
4225 | 1538 | auto folder = call(root->create_folder("folder")); | ||
4226 | 1539 | |||
4227 | 1540 | // Make a file in the root. | ||
4228 | 1541 | auto uploader = call(root->create_file("file", 0)); | ||
4229 | 1542 | auto file = call(uploader->finish_upload()); | ||
4230 | 1543 | |||
4231 | 1544 | // Delete folder. | ||
4232 | 1545 | call(folder->delete_item()); | ||
4233 | 1546 | |||
4234 | 1547 | call(file->copy(folder, "file")); | ||
4235 | 1548 | FAIL(); | ||
4236 | 1549 | } | ||
4237 | 1550 | catch (DeletedException const& e) | ||
4238 | 1551 | { | ||
4239 | 1552 | EXPECT_EQ("folder", e.name()); | ||
4240 | 1553 | EXPECT_TRUE(e.error_message().startsWith("Item::copy(): ")); | ||
4241 | 1554 | } | ||
4242 | 1555 | clear_folder(root); | ||
4243 | 1556 | |||
4244 | 1557 | try | ||
4245 | 1558 | { | ||
4246 | 1559 | // Moving deleted file must fail. | ||
4247 | 1560 | auto file = make_deleted_file(root, "file"); | ||
4248 | 1561 | call(file->move(root, "moved_file")); | ||
4249 | 1562 | FAIL(); | ||
4250 | 1563 | } | ||
4251 | 1564 | catch (DeletedException const& e) | ||
4252 | 1565 | { | ||
4253 | 1566 | EXPECT_EQ("file", e.name()); | ||
4254 | 1567 | EXPECT_TRUE(e.error_message().startsWith("Item::move(): ")); | ||
4255 | 1568 | } | ||
4256 | 1569 | |||
4257 | 1570 | try | ||
4258 | 1571 | { | ||
4259 | 1572 | // Moving file into deleted folder must fail. | ||
4260 | 1573 | |||
4261 | 1574 | // Make target folder. | ||
4262 | 1575 | auto folder = call(root->create_folder("folder")); | ||
4263 | 1576 | |||
4264 | 1577 | // Make a file in the root. | ||
4265 | 1578 | auto uploader = call(root->create_file("file", 0)); | ||
4266 | 1579 | auto file = call(uploader->finish_upload()); | ||
4267 | 1580 | |||
4268 | 1581 | // Delete folder. | ||
4269 | 1582 | call(folder->delete_item()); | ||
4270 | 1583 | |||
4271 | 1584 | call(file->move(folder, "file")); | ||
4272 | 1585 | FAIL(); | ||
4273 | 1586 | } | ||
4274 | 1587 | catch (DeletedException const& e) | ||
4275 | 1588 | { | ||
4276 | 1589 | EXPECT_EQ("folder", e.name()); | ||
4277 | 1590 | EXPECT_TRUE(e.error_message().startsWith("Item::move(): ")); | ||
4278 | 1591 | } | ||
4279 | 1592 | clear_folder(root); | ||
4280 | 1593 | |||
4281 | 1594 | try | ||
4282 | 1595 | { | ||
4283 | 1596 | auto file = make_deleted_file(root, "file"); | ||
4284 | 1597 | call(file->parents()); | ||
4285 | 1598 | FAIL(); | ||
4286 | 1599 | } | ||
4287 | 1600 | catch (DeletedException const& e) | ||
4288 | 1601 | { | ||
4289 | 1602 | EXPECT_EQ("file", e.name()); | ||
4290 | 1603 | EXPECT_TRUE(e.error_message().startsWith("Item::parents(): ")); | ||
4291 | 1604 | } | ||
4292 | 1605 | |||
4293 | 1606 | try | ||
4294 | 1607 | { | ||
4295 | 1608 | auto file = make_deleted_file(root, "file"); | ||
4296 | 1609 | file->parent_ids(); | ||
4297 | 1610 | FAIL(); | ||
4298 | 1611 | } | ||
4299 | 1612 | catch (DeletedException const& e) | ||
4300 | 1613 | { | ||
4301 | 1614 | EXPECT_EQ("file", e.name()); | ||
4302 | 1615 | EXPECT_TRUE(e.error_message().startsWith("Item::parent_ids(): ")); | ||
4303 | 1616 | } | ||
4304 | 1617 | |||
4305 | 1618 | try | ||
4306 | 1619 | { | ||
4307 | 1620 | // Deleting a deleted item must fail. | ||
4308 | 1621 | auto file = make_deleted_file(root, "file"); | ||
4309 | 1622 | call(file->delete_item()); | ||
4310 | 1623 | FAIL(); | ||
4311 | 1624 | } | ||
4312 | 1625 | catch (DeletedException const& e) | ||
4313 | 1626 | { | ||
4314 | 1627 | EXPECT_EQ("file", e.name()); | ||
4315 | 1628 | EXPECT_TRUE(e.error_message().startsWith("Item::delete_item(): ")); | ||
4316 | 1629 | } | ||
4317 | 1630 | } | ||
4318 | 1631 | |||
4319 | 1632 | TEST(Folder, deleted_exceptions) | ||
4320 | 1633 | { | ||
4321 | 1634 | auto runtime = Runtime::create(); | ||
4322 | 1635 | |||
4323 | 1636 | auto acc = get_account(runtime); | ||
4324 | 1637 | auto root = get_root(runtime); | ||
4325 | 1638 | clear_folder(root); | ||
4326 | 1639 | |||
4327 | 1640 | try | ||
4328 | 1641 | { | ||
4329 | 1642 | auto folder = make_deleted_folder(root, "folder"); | ||
4330 | 1643 | folder->name(); | ||
4331 | 1644 | FAIL(); | ||
4332 | 1645 | } | ||
4333 | 1646 | catch (DeletedException const& e) | ||
4334 | 1647 | { | ||
4335 | 1648 | EXPECT_EQ("folder", e.name()); | ||
4336 | 1649 | EXPECT_TRUE(e.error_message().startsWith("Folder::name(): ")); | ||
4337 | 1650 | } | ||
4338 | 1651 | |||
4339 | 1652 | try | ||
4340 | 1653 | { | ||
4341 | 1654 | auto folder = make_deleted_folder(root, "folder"); | ||
4342 | 1655 | call(folder->list()); | ||
4343 | 1656 | FAIL(); | ||
4344 | 1657 | } | ||
4345 | 1658 | catch (DeletedException const& e) | ||
4346 | 1659 | { | ||
4347 | 1660 | EXPECT_EQ("folder", e.name()); | ||
4348 | 1661 | EXPECT_TRUE(e.error_message().startsWith("Folder::list(): ")); | ||
4349 | 1662 | } | ||
4350 | 1663 | |||
4351 | 1664 | try | ||
4352 | 1665 | { | ||
4353 | 1666 | auto folder = make_deleted_folder(root, "folder"); | ||
4354 | 1667 | call(folder->lookup("something")); | ||
4355 | 1668 | FAIL(); | ||
4356 | 1669 | } | ||
4357 | 1670 | catch (DeletedException const& e) | ||
4358 | 1671 | { | ||
4359 | 1672 | EXPECT_EQ("folder", e.name()); | ||
4360 | 1673 | EXPECT_TRUE(e.error_message().startsWith("Folder::lookup(): ")); | ||
4361 | 1674 | } | ||
4362 | 1675 | |||
4363 | 1676 | try | ||
4364 | 1677 | { | ||
4365 | 1678 | auto folder = make_deleted_folder(root, "folder"); | ||
4366 | 1679 | call(folder->list()); | ||
4367 | 1680 | FAIL(); | ||
4368 | 1681 | } | ||
4369 | 1682 | catch (DeletedException const& e) | ||
4370 | 1683 | { | ||
4371 | 1684 | EXPECT_EQ("folder", e.name()); | ||
4372 | 1685 | EXPECT_TRUE(e.error_message().startsWith("Folder::list(): ")); | ||
4373 | 1686 | } | ||
4374 | 1687 | |||
4375 | 1688 | try | ||
4376 | 1689 | { | ||
4377 | 1690 | auto folder = make_deleted_folder(root, "folder"); | ||
4378 | 1691 | call(folder->create_folder("nested_folder")); | ||
4379 | 1692 | FAIL(); | ||
4380 | 1693 | } | ||
4381 | 1694 | catch (DeletedException const& e) | ||
4382 | 1695 | { | ||
4383 | 1696 | EXPECT_EQ("folder", e.name()); | ||
4384 | 1697 | EXPECT_TRUE(e.error_message().startsWith("Folder::create_folder(): ")); | ||
4385 | 1698 | } | ||
4386 | 1699 | |||
4387 | 1700 | try | ||
4388 | 1701 | { | ||
4389 | 1702 | auto folder = make_deleted_folder(root, "folder"); | ||
4390 | 1703 | call(folder->create_file("nested_file", 0)); | ||
4391 | 1704 | FAIL(); | ||
4392 | 1705 | } | ||
4393 | 1706 | catch (DeletedException const& e) | ||
4394 | 1707 | { | ||
4395 | 1708 | EXPECT_EQ("folder", e.name()); | ||
4396 | 1709 | EXPECT_TRUE(e.error_message().startsWith("Folder::create_file(): ")); | ||
4397 | 1710 | } | ||
4398 | 1711 | |||
4399 | 1712 | try | ||
4400 | 1713 | { | ||
4401 | 1714 | auto folder = make_deleted_folder(root, "folder"); | ||
4402 | 1715 | folder->creation_time(); | ||
4403 | 1716 | FAIL(); | ||
4404 | 1717 | } | ||
4405 | 1718 | catch (DeletedException const& e) | ||
4406 | 1719 | { | ||
4407 | 1720 | EXPECT_EQ("folder", e.name()); | ||
4408 | 1721 | EXPECT_TRUE(e.error_message().startsWith("Item::creation_time(): ")) << e.what(); | ||
4409 | 1722 | } | ||
4410 | 1723 | |||
4411 | 1724 | try | ||
4412 | 1725 | { | ||
4413 | 1726 | auto folder = make_deleted_folder(root, "folder"); | ||
4414 | 1727 | folder->native_metadata(); | ||
4415 | 1728 | FAIL(); | ||
4416 | 1729 | } | ||
4417 | 1730 | catch (DeletedException const& e) | ||
4418 | 1731 | { | ||
4419 | 1732 | EXPECT_EQ("folder", e.name()); | ||
4420 | 1733 | EXPECT_TRUE(e.error_message().startsWith("Item::native_metadata(): ")) << e.what(); | ||
4421 | 1734 | } | ||
4422 | 1735 | } | ||
4423 | 1736 | |||
4424 | 1737 | TEST(File, deleted_exceptions) | ||
4425 | 1738 | { | ||
4426 | 1739 | auto runtime = Runtime::create(); | ||
4427 | 1740 | |||
4428 | 1741 | auto acc = get_account(runtime); | ||
4429 | 1742 | auto root = get_root(runtime); | ||
4430 | 1743 | clear_folder(root); | ||
4431 | 1744 | |||
4432 | 1745 | try | ||
4433 | 1746 | { | ||
4434 | 1747 | auto file = make_deleted_file(root, "file"); | ||
4435 | 1748 | file->name(); | ||
4436 | 1749 | FAIL(); | ||
4437 | 1750 | } | ||
4438 | 1751 | catch (DeletedException const& e) | ||
4439 | 1752 | { | ||
4440 | 1753 | EXPECT_EQ("file", e.name()); | ||
4441 | 1754 | EXPECT_TRUE(e.error_message().startsWith("File::name(): ")); | ||
4442 | 1755 | EXPECT_TRUE(e.error_message().endsWith(" was deleted previously")); | ||
4443 | 1756 | EXPECT_EQ(TEST_DIR "/storage-framework/file", e.native_identity()); | ||
4444 | 1757 | } | ||
4445 | 1758 | |||
4446 | 1759 | try | ||
4447 | 1760 | { | ||
4448 | 1761 | auto file = make_deleted_file(root, "file"); | ||
4449 | 1762 | file->size(); | ||
4450 | 1763 | FAIL(); | ||
4451 | 1764 | } | ||
4452 | 1765 | catch (DeletedException const& e) | ||
4453 | 1766 | { | ||
4454 | 1767 | EXPECT_EQ("file", e.name()); | ||
4455 | 1768 | EXPECT_TRUE(e.error_message().startsWith("File::size(): ")); | ||
4456 | 1769 | EXPECT_TRUE(e.error_message().endsWith(" was deleted previously")); | ||
4457 | 1770 | EXPECT_EQ(TEST_DIR "/storage-framework/file", e.native_identity()); | ||
4458 | 1771 | } | ||
4459 | 1772 | |||
4460 | 1773 | try | ||
4461 | 1774 | { | ||
4462 | 1775 | auto file = make_deleted_file(root, "file"); | ||
4463 | 1776 | call(file->create_uploader(ConflictPolicy::overwrite, 0)); | ||
4464 | 1777 | FAIL(); | ||
4465 | 1778 | } | ||
4466 | 1779 | catch (DeletedException const& e) | ||
4467 | 1780 | { | ||
4468 | 1781 | EXPECT_EQ("file", e.name()); | ||
4469 | 1782 | EXPECT_TRUE(e.error_message().startsWith("File::create_uploader(): ")); | ||
4470 | 1783 | EXPECT_TRUE(e.error_message().endsWith(" was deleted previously")); | ||
4471 | 1784 | EXPECT_EQ(TEST_DIR "/storage-framework/file", e.native_identity()); | ||
4472 | 1785 | } | ||
4473 | 1786 | |||
4474 | 1787 | try | ||
4475 | 1788 | { | ||
4476 | 1789 | auto file = make_deleted_file(root, "file"); | ||
4477 | 1790 | call(file->create_downloader()); | ||
4478 | 1791 | FAIL(); | ||
4479 | 1792 | } | ||
4480 | 1793 | catch (DeletedException const& e) | ||
4481 | 1794 | { | ||
4482 | 1795 | EXPECT_EQ("file", e.name()); | ||
4483 | 1796 | EXPECT_TRUE(e.error_message().startsWith("File::create_downloader(): ")); | ||
4484 | 1797 | EXPECT_TRUE(e.error_message().endsWith(" was deleted previously")); | ||
4485 | 1798 | EXPECT_EQ(TEST_DIR "/storage-framework/file", e.native_identity()); | ||
4486 | 1799 | } | ||
4487 | 1800 | } | ||
4488 | 1801 | |||
4489 | 1802 | TEST(Runtime, runtime_destroyed_exceptions) | ||
4490 | 1803 | { | ||
4491 | 1804 | // Gettting an account after shutting down the runtime must fail. | ||
4492 | 1805 | { | ||
4493 | 1806 | auto runtime = Runtime::create(); | ||
4494 | 1807 | auto acc = get_account(runtime); | ||
4495 | 1808 | runtime->shutdown(); | ||
4496 | 1809 | try | ||
4497 | 1810 | { | ||
4498 | 1811 | acc->runtime(); | ||
4499 | 1812 | FAIL(); | ||
4500 | 1813 | } | ||
4501 | 1814 | catch (RuntimeDestroyedException const& e) | ||
4502 | 1815 | { | ||
4503 | 1816 | EXPECT_EQ("Account::runtime(): Runtime was destroyed previously", e.error_message()); | ||
4504 | 1817 | } | ||
4505 | 1818 | } | ||
4506 | 1819 | |||
4507 | 1820 | // Getting an account after destroying the runtime must fail. | ||
4508 | 1821 | { | ||
4509 | 1822 | auto runtime = Runtime::create(); | ||
4510 | 1823 | auto acc = get_account(runtime); | ||
4511 | 1824 | runtime.reset(); | ||
4512 | 1825 | try | ||
4513 | 1826 | { | ||
4514 | 1827 | acc->runtime(); | ||
4515 | 1828 | FAIL(); | ||
4516 | 1829 | } | ||
4517 | 1830 | catch (RuntimeDestroyedException const& e) | ||
4518 | 1831 | { | ||
4519 | 1832 | EXPECT_EQ("Account::runtime(): Runtime was destroyed previously", e.error_message()); | ||
4520 | 1833 | } | ||
4521 | 1834 | } | ||
4522 | 1835 | |||
4523 | 1836 | // Getting accounts after shutting down the runtime must fail. | ||
4524 | 1837 | { | ||
4525 | 1838 | auto runtime = Runtime::create(); | ||
4526 | 1839 | runtime->shutdown(); | ||
4527 | 1840 | try | ||
4528 | 1841 | { | ||
4529 | 1842 | runtime->accounts(); | ||
4530 | 1843 | FAIL(); | ||
4531 | 1844 | } | ||
4532 | 1845 | catch (RuntimeDestroyedException const& e) | ||
4533 | 1846 | { | ||
4534 | 1847 | EXPECT_EQ("Runtime::accounts(): Runtime was destroyed previously", e.error_message()); | ||
4535 | 1848 | } | ||
4536 | 1849 | } | ||
4537 | 1850 | |||
4538 | 1851 | // Getting the account from a root with a destroyed runtime must fail. | ||
4539 | 1852 | { | ||
4540 | 1853 | auto runtime = Runtime::create(); | ||
4541 | 1854 | auto acc = get_account(runtime); | ||
4542 | 1855 | auto root = get_root(runtime); | ||
4543 | 1856 | runtime.reset(); | ||
4544 | 1857 | try | ||
4545 | 1858 | { | ||
4546 | 1859 | root->account(); | ||
4547 | 1860 | FAIL(); | ||
4548 | 1861 | } | ||
4549 | 1862 | catch (RuntimeDestroyedException const& e) | ||
4550 | 1863 | { | ||
4551 | 1864 | EXPECT_EQ("Root::account(): Runtime was destroyed previously", e.error_message()); | ||
4552 | 1865 | } | ||
4553 | 1866 | } | ||
4554 | 1867 | |||
4555 | 1868 | // Getting the account from a root with a destroyed account must fail. | ||
4556 | 1869 | { | ||
4557 | 1870 | auto runtime = Runtime::create(); | ||
4558 | 1871 | auto acc = get_account(runtime); | ||
4559 | 1872 | auto root = get_root(runtime); | ||
4560 | 1873 | runtime.reset(); | ||
4561 | 1874 | acc.reset(); | ||
4562 | 1875 | try | ||
4563 | 1876 | { | ||
4564 | 1877 | root->account(); | ||
4565 | 1878 | FAIL(); | ||
4566 | 1879 | } | ||
4567 | 1880 | catch (RuntimeDestroyedException const& e) | ||
4568 | 1881 | { | ||
4569 | 1882 | EXPECT_EQ("Root::account(): Runtime was destroyed previously", e.error_message()); | ||
4570 | 1883 | } | ||
4571 | 1884 | } | ||
4572 | 1885 | |||
4573 | 1886 | // Getting the root from an item with a destroyed runtime must fail. | ||
4574 | 1887 | { | ||
4575 | 1888 | auto runtime = Runtime::create(); | ||
4576 | 1889 | auto acc = get_account(runtime); | ||
4577 | 1890 | auto root = get_root(runtime); | ||
4578 | 1891 | clear_folder(root); | ||
4579 | 1892 | |||
4580 | 1893 | auto file = write_file(root, "file", ""); | ||
4581 | 1894 | runtime.reset(); | ||
4582 | 1895 | try | ||
4583 | 1896 | { | ||
4584 | 1897 | file->root(); | ||
4585 | 1898 | FAIL(); | ||
4586 | 1899 | } | ||
4587 | 1900 | catch (RuntimeDestroyedException const& e) | ||
4588 | 1901 | { | ||
4589 | 1902 | EXPECT_EQ("Item::root(): Runtime was destroyed previously", e.error_message()); | ||
4590 | 1903 | } | ||
4591 | 1904 | } | ||
4592 | 1905 | |||
4593 | 1906 | // Getting the root from an item with a destroyed root must fail. | ||
4594 | 1907 | { | ||
4595 | 1908 | auto runtime = Runtime::create(); | ||
4596 | 1909 | auto acc = get_account(runtime); | ||
4597 | 1910 | auto root = get_root(runtime); | ||
4598 | 1911 | clear_folder(root); | ||
4599 | 1912 | |||
4600 | 1913 | auto file = write_file(root, "file", ""); | ||
4601 | 1914 | runtime.reset(); | ||
4602 | 1915 | acc.reset(); | ||
4603 | 1916 | root.reset(); | ||
4604 | 1917 | try | ||
4605 | 1918 | { | ||
4606 | 1919 | file->root(); | ||
4607 | 1920 | FAIL(); | ||
4608 | 1921 | } | ||
4609 | 1922 | catch (RuntimeDestroyedException const& e) | ||
4610 | 1923 | { | ||
4611 | 1924 | EXPECT_EQ("Item::root(): Runtime was destroyed previously", e.error_message()); | ||
4612 | 1925 | } | ||
4613 | 1926 | } | ||
4614 | 1927 | |||
4615 | 1928 | // etag() with destroyed runtime must fail. | ||
4616 | 1929 | { | ||
4617 | 1930 | auto runtime = Runtime::create(); | ||
4618 | 1931 | auto acc = get_account(runtime); | ||
4619 | 1932 | auto root = get_root(runtime); | ||
4620 | 1933 | clear_folder(root); | ||
4621 | 1934 | |||
4622 | 1935 | auto file = write_file(root, "file", ""); | ||
4623 | 1936 | runtime->shutdown(); | ||
4624 | 1937 | try | ||
4625 | 1938 | { | ||
4626 | 1939 | file->etag(); | ||
4627 | 1940 | FAIL(); | ||
4628 | 1941 | } | ||
4629 | 1942 | catch (RuntimeDestroyedException const& e) | ||
4630 | 1943 | { | ||
4631 | 1944 | EXPECT_EQ("Item::etag(): Runtime was destroyed previously", e.error_message()); | ||
4632 | 1945 | } | ||
4633 | 1946 | } | ||
4634 | 1947 | |||
4635 | 1948 | // metadata() with destroyed runtime must fail. | ||
4636 | 1949 | { | ||
4637 | 1950 | auto runtime = Runtime::create(); | ||
4638 | 1951 | auto acc = get_account(runtime); | ||
4639 | 1952 | auto root = get_root(runtime); | ||
4640 | 1953 | clear_folder(root); | ||
4641 | 1954 | |||
4642 | 1955 | auto file = write_file(root, "file", ""); | ||
4643 | 1956 | runtime->shutdown(); | ||
4644 | 1957 | try | ||
4645 | 1958 | { | ||
4646 | 1959 | file->metadata(); | ||
4647 | 1960 | FAIL(); | ||
4648 | 1961 | } | ||
4649 | 1962 | catch (RuntimeDestroyedException const& e) | ||
4650 | 1963 | { | ||
4651 | 1964 | EXPECT_EQ("Item::metadata(): Runtime was destroyed previously", e.error_message()); | ||
4652 | 1965 | } | ||
4653 | 1966 | } | ||
4654 | 1967 | |||
4655 | 1968 | // last_modified_time() with destroyed runtime must fail. | ||
4656 | 1969 | { | ||
4657 | 1970 | auto runtime = Runtime::create(); | ||
4658 | 1971 | auto acc = get_account(runtime); | ||
4659 | 1972 | auto root = get_root(runtime); | ||
4660 | 1973 | clear_folder(root); | ||
4661 | 1974 | |||
4662 | 1975 | auto file = write_file(root, "file", ""); | ||
4663 | 1976 | runtime->shutdown(); | ||
4664 | 1977 | try | ||
4665 | 1978 | { | ||
4666 | 1979 | file->last_modified_time(); | ||
4667 | 1980 | FAIL(); | ||
4668 | 1981 | } | ||
4669 | 1982 | catch (RuntimeDestroyedException const& e) | ||
4670 | 1983 | { | ||
4671 | 1984 | EXPECT_EQ("Item::last_modified_time(): Runtime was destroyed previously", e.error_message()); | ||
4672 | 1985 | } | ||
4673 | 1986 | } | ||
4674 | 1987 | |||
4675 | 1988 | // copy() with destroyed runtime must fail. | ||
4676 | 1989 | { | ||
4677 | 1990 | auto runtime = Runtime::create(); | ||
4678 | 1991 | auto acc = get_account(runtime); | ||
4679 | 1992 | auto root = get_root(runtime); | ||
4680 | 1993 | clear_folder(root); | ||
4681 | 1994 | |||
4682 | 1995 | auto file = write_file(root, "file", ""); | ||
4683 | 1996 | runtime->shutdown(); | ||
4684 | 1997 | try | ||
4685 | 1998 | { | ||
4686 | 1999 | call(file->copy(root, "file2")); | ||
4687 | 2000 | FAIL(); | ||
4688 | 2001 | } | ||
4689 | 2002 | catch (RuntimeDestroyedException const& e) | ||
4690 | 2003 | { | ||
4691 | 2004 | EXPECT_EQ("Item::copy(): Runtime was destroyed previously", e.error_message()); | ||
4692 | 2005 | } | ||
4693 | 2006 | } | ||
4694 | 2007 | |||
4695 | 2008 | // move() with destroyed runtime must fail. | ||
4696 | 2009 | { | ||
4697 | 2010 | auto runtime = Runtime::create(); | ||
4698 | 2011 | auto acc = get_account(runtime); | ||
4699 | 2012 | auto root = get_root(runtime); | ||
4700 | 2013 | clear_folder(root); | ||
4701 | 2014 | |||
4702 | 2015 | auto file = write_file(root, "file", ""); | ||
4703 | 2016 | runtime->shutdown(); | ||
4704 | 2017 | try | ||
4705 | 2018 | { | ||
4706 | 2019 | call(file->move(root, "file2")); | ||
4707 | 2020 | FAIL(); | ||
4708 | 2021 | } | ||
4709 | 2022 | catch (RuntimeDestroyedException const& e) | ||
4710 | 2023 | { | ||
4711 | 2024 | EXPECT_EQ("Item::move(): Runtime was destroyed previously", e.error_message()); | ||
4712 | 2025 | } | ||
4713 | 2026 | } | ||
4714 | 2027 | |||
4715 | 2028 | // parents() on root with destroyed runtime must fail. | ||
4716 | 2029 | { | ||
4717 | 2030 | auto runtime = Runtime::create(); | ||
4718 | 2031 | auto acc = get_account(runtime); | ||
4719 | 2032 | auto root = get_root(runtime); | ||
4720 | 2033 | clear_folder(root); | ||
4721 | 2034 | |||
4722 | 2035 | auto file = write_file(root, "file", ""); | ||
4723 | 2036 | runtime->shutdown(); | ||
4724 | 2037 | try | ||
4725 | 2038 | { | ||
4726 | 2039 | call(root->parents()); | ||
4727 | 2040 | FAIL(); | ||
4728 | 2041 | } | ||
4729 | 2042 | catch (RuntimeDestroyedException const& e) | ||
4730 | 2043 | { | ||
4731 | 2044 | EXPECT_EQ("Root::parents(): Runtime was destroyed previously", e.error_message()); | ||
4732 | 2045 | } | ||
4733 | 2046 | } | ||
4734 | 2047 | |||
4735 | 2048 | // parents() on file with destroyed runtime must fail. | ||
4736 | 2049 | { | ||
4737 | 2050 | auto runtime = Runtime::create(); | ||
4738 | 2051 | auto acc = get_account(runtime); | ||
4739 | 2052 | auto root = get_root(runtime); | ||
4740 | 2053 | clear_folder(root); | ||
4741 | 2054 | |||
4742 | 2055 | auto file = write_file(root, "file", ""); | ||
4743 | 2056 | runtime->shutdown(); | ||
4744 | 2057 | try | ||
4745 | 2058 | { | ||
4746 | 2059 | call(file->parents()); | ||
4747 | 2060 | FAIL(); | ||
4748 | 2061 | } | ||
4749 | 2062 | catch (RuntimeDestroyedException const& e) | ||
4750 | 2063 | { | ||
4751 | 2064 | EXPECT_EQ("Item::parents(): Runtime was destroyed previously", e.error_message()); | ||
4752 | 2065 | } | ||
4753 | 2066 | } | ||
4754 | 2067 | |||
4755 | 2068 | // parent_ids() with destroyed runtime must fail. | ||
4756 | 2069 | { | ||
4757 | 2070 | auto runtime = Runtime::create(); | ||
4758 | 2071 | auto acc = get_account(runtime); | ||
4759 | 2072 | auto root = get_root(runtime); | ||
4760 | 2073 | clear_folder(root); | ||
4761 | 2074 | |||
4762 | 2075 | auto file = write_file(root, "file", ""); | ||
4763 | 2076 | runtime->shutdown(); | ||
4764 | 2077 | try | ||
4765 | 2078 | { | ||
4766 | 2079 | file->parent_ids(); | ||
4767 | 2080 | FAIL(); | ||
4768 | 2081 | } | ||
4769 | 2082 | catch (RuntimeDestroyedException const& e) | ||
4770 | 2083 | { | ||
4771 | 2084 | EXPECT_EQ("Item::parent_ids(): Runtime was destroyed previously", e.error_message()); | ||
4772 | 2085 | } | ||
4773 | 2086 | } | ||
4774 | 2087 | |||
4775 | 2088 | // parent_ids() on root with destroyed runtime must fail. | ||
4776 | 2089 | { | ||
4777 | 2090 | auto runtime = Runtime::create(); | ||
4778 | 2091 | auto acc = get_account(runtime); | ||
4779 | 2092 | auto root = get_root(runtime); | ||
4780 | 2093 | clear_folder(root); | ||
4781 | 2094 | |||
4782 | 2095 | runtime->shutdown(); | ||
4783 | 2096 | try | ||
4784 | 2097 | { | ||
4785 | 2098 | root->parent_ids(); | ||
4786 | 2099 | FAIL(); | ||
4787 | 2100 | } | ||
4788 | 2101 | catch (RuntimeDestroyedException const& e) | ||
4789 | 2102 | { | ||
4790 | 2103 | EXPECT_EQ("Root::parent_ids(): Runtime was destroyed previously", e.error_message()); | ||
4791 | 2104 | } | ||
4792 | 2105 | } | ||
4793 | 2106 | |||
4794 | 2107 | // delete_item() with destroyed runtime must fail. | ||
4795 | 2108 | { | ||
4796 | 2109 | auto runtime = Runtime::create(); | ||
4797 | 2110 | auto acc = get_account(runtime); | ||
4798 | 2111 | auto root = get_root(runtime); | ||
4799 | 2112 | clear_folder(root); | ||
4800 | 2113 | |||
4801 | 2114 | auto file = write_file(root, "file", ""); | ||
4802 | 2115 | runtime->shutdown(); | ||
4803 | 2116 | try | ||
4804 | 2117 | { | ||
4805 | 2118 | call(file->delete_item()); | ||
4806 | 2119 | FAIL(); | ||
4807 | 2120 | } | ||
4808 | 2121 | catch (RuntimeDestroyedException const& e) | ||
4809 | 2122 | { | ||
4810 | 2123 | EXPECT_EQ("Item::delete_item(): Runtime was destroyed previously", e.error_message()); | ||
4811 | 2124 | } | ||
4812 | 2125 | } | ||
4813 | 2126 | |||
4814 | 2127 | // delete_item() on root with destroyed runtime must fail. | ||
4815 | 2128 | { | ||
4816 | 2129 | auto runtime = Runtime::create(); | ||
4817 | 2130 | auto acc = get_account(runtime); | ||
4818 | 2131 | auto root = get_root(runtime); | ||
4819 | 2132 | clear_folder(root); | ||
4820 | 2133 | |||
4821 | 2134 | runtime->shutdown(); | ||
4822 | 2135 | try | ||
4823 | 2136 | { | ||
4824 | 2137 | call(root->delete_item()); | ||
4825 | 2138 | FAIL(); | ||
4826 | 2139 | } | ||
4827 | 2140 | catch (RuntimeDestroyedException const& e) | ||
4828 | 2141 | { | ||
4829 | 2142 | EXPECT_EQ("Root::delete_item(): Runtime was destroyed previously", e.error_message()); | ||
4830 | 2143 | } | ||
4831 | 2144 | } | ||
4832 | 2145 | |||
4833 | 2146 | // creation_time() with destroyed runtime must fail. | ||
4834 | 2147 | { | ||
4835 | 2148 | auto runtime = Runtime::create(); | ||
4836 | 2149 | auto acc = get_account(runtime); | ||
4837 | 2150 | auto root = get_root(runtime); | ||
4838 | 2151 | clear_folder(root); | ||
4839 | 2152 | |||
4840 | 2153 | auto file = write_file(root, "file", ""); | ||
4841 | 2154 | runtime->shutdown(); | ||
4842 | 2155 | try | ||
4843 | 2156 | { | ||
4844 | 2157 | file->creation_time(); | ||
4845 | 2158 | FAIL(); | ||
4846 | 2159 | } | ||
4847 | 2160 | catch (RuntimeDestroyedException const& e) | ||
4848 | 2161 | { | ||
4849 | 2162 | EXPECT_EQ("Item::creation_time(): Runtime was destroyed previously", e.error_message()); | ||
4850 | 2163 | } | ||
4851 | 2164 | } | ||
4852 | 2165 | |||
4853 | 2166 | // native_metadata() with destroyed runtime must fail. | ||
4854 | 2167 | { | ||
4855 | 2168 | auto runtime = Runtime::create(); | ||
4856 | 2169 | auto acc = get_account(runtime); | ||
4857 | 2170 | auto root = get_root(runtime); | ||
4858 | 2171 | clear_folder(root); | ||
4859 | 2172 | |||
4860 | 2173 | auto file = write_file(root, "file", ""); | ||
4861 | 2174 | runtime->shutdown(); | ||
4862 | 2175 | try | ||
4863 | 2176 | { | ||
4864 | 2177 | file->native_metadata(); | ||
4865 | 2178 | FAIL(); | ||
4866 | 2179 | } | ||
4867 | 2180 | catch (RuntimeDestroyedException const& e) | ||
4868 | 2181 | { | ||
4869 | 2182 | EXPECT_EQ("Item::native_metadata(): Runtime was destroyed previously", e.error_message()); | ||
4870 | 2183 | } | ||
4871 | 2184 | } | ||
4872 | 2185 | |||
4873 | 2186 | // name() on root with destroyed runtime must fail. | ||
4874 | 2187 | { | ||
4875 | 2188 | auto runtime = Runtime::create(); | ||
4876 | 2189 | auto acc = get_account(runtime); | ||
4877 | 2190 | auto root = get_root(runtime); | ||
4878 | 2191 | clear_folder(root); | ||
4879 | 2192 | |||
4880 | 2193 | runtime->shutdown(); | ||
4881 | 2194 | try | ||
4882 | 2195 | { | ||
4883 | 2196 | root->name(); | ||
4884 | 2197 | FAIL(); | ||
4885 | 2198 | } | ||
4886 | 2199 | catch (RuntimeDestroyedException const& e) | ||
4887 | 2200 | { | ||
4888 | 2201 | EXPECT_EQ("Root::name(): Runtime was destroyed previously", e.error_message()); | ||
4889 | 2202 | } | ||
4890 | 2203 | } | ||
4891 | 2204 | |||
4892 | 2205 | // name() on folder with destroyed runtime must fail. | ||
4893 | 2206 | { | ||
4894 | 2207 | auto runtime = Runtime::create(); | ||
4895 | 2208 | auto acc = get_account(runtime); | ||
4896 | 2209 | auto root = get_root(runtime); | ||
4897 | 2210 | clear_folder(root); | ||
4898 | 2211 | |||
4899 | 2212 | auto folder = call(root->create_folder("folder")); | ||
4900 | 2213 | runtime->shutdown(); | ||
4901 | 2214 | try | ||
4902 | 2215 | { | ||
4903 | 2216 | folder->name(); | ||
4904 | 2217 | FAIL(); | ||
4905 | 2218 | } | ||
4906 | 2219 | catch (RuntimeDestroyedException const& e) | ||
4907 | 2220 | { | ||
4908 | 2221 | EXPECT_EQ("Folder::name(): Runtime was destroyed previously", e.error_message()); | ||
4909 | 2222 | } | ||
4910 | 2223 | } | ||
4911 | 2224 | |||
4912 | 2225 | // name() on file with destroyed runtime must fail. | ||
4913 | 2226 | { | ||
4914 | 2227 | auto runtime = Runtime::create(); | ||
4915 | 2228 | auto acc = get_account(runtime); | ||
4916 | 2229 | auto root = get_root(runtime); | ||
4917 | 2230 | clear_folder(root); | ||
4918 | 2231 | |||
4919 | 2232 | auto file = write_file(root, "file", ""); | ||
4920 | 2233 | runtime->shutdown(); | ||
4921 | 2234 | try | ||
4922 | 2235 | { | ||
4923 | 2236 | file->name(); | ||
4924 | 2237 | FAIL(); | ||
4925 | 2238 | } | ||
4926 | 2239 | catch (RuntimeDestroyedException const& e) | ||
4927 | 2240 | { | ||
4928 | 2241 | EXPECT_EQ("File::name(): Runtime was destroyed previously", e.error_message()); | ||
4929 | 2242 | } | ||
4930 | 2243 | } | ||
4931 | 2244 | |||
4932 | 2245 | // list() with destroyed runtime must fail. | ||
4933 | 2246 | { | ||
4934 | 2247 | auto runtime = Runtime::create(); | ||
4935 | 2248 | auto acc = get_account(runtime); | ||
4936 | 2249 | auto root = get_root(runtime); | ||
4937 | 2250 | clear_folder(root); | ||
4938 | 2251 | |||
4939 | 2252 | runtime->shutdown(); | ||
4940 | 2253 | try | ||
4941 | 2254 | { | ||
4942 | 2255 | call(root->list()); | ||
4943 | 2256 | FAIL(); | ||
4944 | 2257 | } | ||
4945 | 2258 | catch (RuntimeDestroyedException const& e) | ||
4946 | 2259 | { | ||
4947 | 2260 | EXPECT_EQ("Folder::list(): Runtime was destroyed previously", e.error_message()); | ||
4948 | 2261 | } | ||
4949 | 2262 | } | ||
4950 | 2263 | |||
4951 | 2264 | // lookup() with destroyed runtime must fail. | ||
4952 | 2265 | { | ||
4953 | 2266 | auto runtime = Runtime::create(); | ||
4954 | 2267 | auto acc = get_account(runtime); | ||
4955 | 2268 | auto root = get_root(runtime); | ||
4956 | 2269 | clear_folder(root); | ||
4957 | 2270 | |||
4958 | 2271 | runtime->shutdown(); | ||
4959 | 2272 | try | ||
4960 | 2273 | { | ||
4961 | 2274 | call(root->lookup("file")); | ||
4962 | 2275 | FAIL(); | ||
4963 | 2276 | } | ||
4964 | 2277 | catch (RuntimeDestroyedException const& e) | ||
4965 | 2278 | { | ||
4966 | 2279 | EXPECT_EQ("Folder::lookup(): Runtime was destroyed previously", e.error_message()); | ||
4967 | 2280 | } | ||
4968 | 2281 | } | ||
4969 | 2282 | |||
4970 | 2283 | // create_folder() with destroyed runtime must fail. | ||
4971 | 2284 | { | ||
4972 | 2285 | auto runtime = Runtime::create(); | ||
4973 | 2286 | auto acc = get_account(runtime); | ||
4974 | 2287 | auto root = get_root(runtime); | ||
4975 | 2288 | clear_folder(root); | ||
4976 | 2289 | |||
4977 | 2290 | runtime->shutdown(); | ||
4978 | 2291 | try | ||
4979 | 2292 | { | ||
4980 | 2293 | call(root->create_folder("folder")); | ||
4981 | 2294 | FAIL(); | ||
4982 | 2295 | } | ||
4983 | 2296 | catch (RuntimeDestroyedException const& e) | ||
4984 | 2297 | { | ||
4985 | 2298 | EXPECT_EQ("Folder::create_folder(): Runtime was destroyed previously", e.error_message()); | ||
4986 | 2299 | } | ||
4987 | 2300 | } | ||
4988 | 2301 | |||
4989 | 2302 | // create_file() with destroyed runtime must fail. | ||
4990 | 2303 | { | ||
4991 | 2304 | auto runtime = Runtime::create(); | ||
4992 | 2305 | auto acc = get_account(runtime); | ||
4993 | 2306 | auto root = get_root(runtime); | ||
4994 | 2307 | clear_folder(root); | ||
4995 | 2308 | |||
4996 | 2309 | runtime->shutdown(); | ||
4997 | 2310 | try | ||
4998 | 2311 | { | ||
4999 | 2312 | call(root->create_file("file", 0)); | ||
5000 | 2313 | FAIL(); |
FAILED: Continuous integration, rev:71 /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/39/ /jenkins. canonical. com/unity- api-1/job/ build/260/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/268/ console
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/39/rebuild
https:/