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