Merge lp:~michihenning/storage-framework/exception-marshaling into lp:storage-framework/devel
- exception-marshaling
- Merge into devel
Status: | Merged |
---|---|
Approved by: | James Henstridge |
Approved revision: | 87 |
Merged at revision: | 47 |
Proposed branch: | lp:~michihenning/storage-framework/exception-marshaling |
Merge into: | lp:storage-framework/devel |
Prerequisite: | lp:~michihenning/storage-framework/upload-download-fixes |
Diff against target: |
3501 lines (+1403/-899) 27 files modified
demo/provider_test/provider-test.cpp (+13/-2) include/unity/storage/internal/dbus_error.h (+32/-0) include/unity/storage/provider/Exceptions.h (+187/-0) include/unity/storage/provider/internal/Handler.h (+2/-0) include/unity/storage/qt/client/Exceptions.h (+1/-1) include/unity/storage/qt/client/internal/ItemBase.h (+1/-1) include/unity/storage/qt/client/internal/remote_client/Handler.h (+19/-2) include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h (+20/-2) src/provider/CMakeLists.txt (+1/-0) src/provider/Exceptions.cpp (+157/-0) src/provider/internal/Handler.cpp (+61/-14) src/qt/client/Exceptions.cpp (+1/-1) src/qt/client/internal/local_client/FolderImpl.cpp (+1/-1) src/qt/client/internal/local_client/RootImpl.cpp (+12/-5) src/qt/client/internal/local_client/RuntimeImpl.cpp (+1/-1) src/qt/client/internal/remote_client/AccountImpl.cpp (+9/-0) src/qt/client/internal/remote_client/FileImpl.cpp (+11/-9) src/qt/client/internal/remote_client/FolderImpl.cpp (+0/-4) src/qt/client/internal/remote_client/ItemImpl.cpp (+12/-5) src/qt/client/internal/remote_client/RootImpl.cpp (+38/-21) src/qt/client/internal/remote_client/RuntimeImpl.cpp (+0/-1) src/qt/client/internal/remote_client/dbusmarshal.cpp (+102/-7) tests/local-client/local-client_test.cpp (+37/-92) tests/provider-ProviderInterface/CMakeLists.txt (+2/-0) tests/provider-ProviderInterface/ProviderInterface_test.cpp (+10/-9) tests/provider-ProviderInterface/TestProvider.cpp (+1/-0) tests/remote-client/remote-client_test.cpp (+672/-721) |
To merge this branch: | bzr merge lp:~michihenning/storage-framework/exception-marshaling |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
James Henstridge | Approve | ||
unity-api-1-bot | continuous-integration | Approve | |
Review via email: mp+302116@code.launchpad.net |
Commit message
Added exception hierarchy for server side, plus marshaling/
for exceptions. Some coverage in the remote client to show that this works
(but more coverage is needed).
Description of the change
Added exception hierarchy for server side, plus marshaling/
for exceptions. Some coverage in the remote client to show that this works
(but more coverage is needed).
unity-api-1-bot (unity-api-1-bot) wrote : | # |
James Henstridge (jamesh) wrote : | # |
This looks pretty good. I've left comments about a few minor issues inline.
- 85. By Michi Henning
-
Merged devel and resolved conflicts.
- 86. By Michi Henning
-
Addressed review comments from James.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:86
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 87. By Michi Henning
-
Instrumented failing test.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:87
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'demo/provider_test/provider-test.cpp' |
2 | --- demo/provider_test/provider-test.cpp 2016-07-22 03:48:19 +0000 |
3 | +++ demo/provider_test/provider-test.cpp 2016-08-11 02:49:47 +0000 |
4 | @@ -17,6 +17,7 @@ |
5 | */ |
6 | |
7 | #include <unity/storage/provider/DownloadJob.h> |
8 | +#include <unity/storage/provider/Exceptions.h> |
9 | #include <unity/storage/provider/ProviderBase.h> |
10 | #include <unity/storage/provider/Server.h> |
11 | #include <unity/storage/provider/TempfileUploadJob.h> |
12 | @@ -193,7 +194,12 @@ |
13 | Item metadata{"child_id", "root_id", "Child", "etag", ItemType::file, {}}; |
14 | return make_ready_future<Item>(metadata); |
15 | } |
16 | - return make_exceptional_future<Item>(runtime_error("no such file")); |
17 | + else if (item_id == "child_folder_id") |
18 | + { |
19 | + Item metadata{"child_folder_id", "root_id", "Child_Folder", "etag", ItemType::folder, {}}; |
20 | + return make_ready_future<Item>(metadata); |
21 | + } |
22 | + return make_exceptional_future<Item>(NotExistsException("metadata(): no such item: " + item_id, item_id)); |
23 | } |
24 | |
25 | boost::future<Item> MyProvider::create_folder( |
26 | @@ -234,7 +240,12 @@ |
27 | |
28 | unique_ptr<DownloadJob> job(new MyDownloadJob(make_job_id())); |
29 | const char contents[] = "Hello world"; |
30 | - write(job->write_socket(), contents, sizeof(contents)); |
31 | + if (write(job->write_socket(), contents, sizeof(contents)) != sizeof(contents)) |
32 | + { |
33 | + ResourceException e("download(): write failed", errno); |
34 | + job->report_error(make_exception_ptr(e)); |
35 | + return make_exceptional_future<unique_ptr<DownloadJob>>(e); |
36 | + } |
37 | job->report_complete(); |
38 | return make_ready_future(std::move(job)); |
39 | } |
40 | |
41 | === added file 'include/unity/storage/internal/dbus_error.h' |
42 | --- include/unity/storage/internal/dbus_error.h 1970-01-01 00:00:00 +0000 |
43 | +++ include/unity/storage/internal/dbus_error.h 2016-08-11 02:49:47 +0000 |
44 | @@ -0,0 +1,32 @@ |
45 | +/* |
46 | + * Copyright (C) 2016 Canonical Ltd |
47 | + * |
48 | + * This program is free software: you can redistribute it and/or modify |
49 | + * it under the terms of the GNU Lesser General Public License version 3 as |
50 | + * published by the Free Software Foundation. |
51 | + * |
52 | + * This program is distributed in the hope that it will be useful, |
53 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
54 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
55 | + * GNU Lesser General Public License for more details. |
56 | + * |
57 | + * You should have received a copy of the GNU Lesser General Public License |
58 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
59 | + * |
60 | + * Authors: Michi Henning <michi.henning@canonical.com> |
61 | + */ |
62 | + |
63 | +#pragma once |
64 | + |
65 | +namespace unity |
66 | +{ |
67 | +namespace storage |
68 | +{ |
69 | +namespace internal |
70 | +{ |
71 | + |
72 | +constexpr char DBUS_ERROR_PREFIX[] = "com.canonical.StorageFramework."; |
73 | + |
74 | +} // namespace internal |
75 | +} // namespace storage |
76 | +} // namespace unity |
77 | |
78 | === added file 'include/unity/storage/provider/Exceptions.h' |
79 | --- include/unity/storage/provider/Exceptions.h 1970-01-01 00:00:00 +0000 |
80 | +++ include/unity/storage/provider/Exceptions.h 2016-08-11 02:49:47 +0000 |
81 | @@ -0,0 +1,187 @@ |
82 | +/* |
83 | + * Copyright (C) 2016 Canonical Ltd |
84 | + * |
85 | + * This program is free software: you can redistribute it and/or modify |
86 | + * it under the terms of the GNU Lesser General Public License version 3 as |
87 | + * published by the Free Software Foundation. |
88 | + * |
89 | + * This program is distributed in the hope that it will be useful, |
90 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
91 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
92 | + * GNU Lesser General Public License for more details. |
93 | + * |
94 | + * You should have received a copy of the GNU Lesser General Public License |
95 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
96 | + * |
97 | + * Authors: Michi Henning <michi.henning@canonical.com> |
98 | + */ |
99 | + |
100 | +#pragma once |
101 | + |
102 | +#include <unity/storage/visibility.h> |
103 | + |
104 | +#include <string> |
105 | + |
106 | +namespace unity |
107 | +{ |
108 | +namespace storage |
109 | +{ |
110 | +namespace provider |
111 | +{ |
112 | + |
113 | +// Note: Adding new exception types also requires updating the marshaling and |
114 | +// unmarshaling code for exceptions in the client and server APIs. |
115 | + |
116 | +/** |
117 | +\brief Base exception class for all server-side exceptions. |
118 | +*/ |
119 | +class UNITY_STORAGE_EXPORT StorageException : public std::exception |
120 | +{ |
121 | +public: |
122 | + StorageException(std::string const& exception_type, std::string const& error_message); |
123 | + ~StorageException(); |
124 | + |
125 | + virtual char const* what() const noexcept override; |
126 | + |
127 | + std::string type() const; |
128 | + std::string error_message() const; |
129 | + |
130 | +private: |
131 | + std::string what_string_; |
132 | + std::string type_; |
133 | + std::string error_message_; |
134 | +}; |
135 | + |
136 | +/** |
137 | +\brief Indicates errors in the communication between the storage provider and the cloud service. |
138 | +*/ |
139 | +class UNITY_STORAGE_EXPORT RemoteCommsException : public StorageException |
140 | +{ |
141 | +public: |
142 | + RemoteCommsException(std::string const& error_message); |
143 | + ~RemoteCommsException(); |
144 | +}; |
145 | + |
146 | +/** |
147 | +\brief Indicates that an item does not exist or could not be found. |
148 | +*/ |
149 | +class UNITY_STORAGE_EXPORT NotExistsException : public StorageException |
150 | +{ |
151 | +public: |
152 | + NotExistsException(std::string const& error_message, std::string const& key); |
153 | + ~NotExistsException(); |
154 | + |
155 | + std::string key() const; |
156 | + |
157 | +private: |
158 | + std::string key_; |
159 | +}; |
160 | + |
161 | +/** |
162 | +\brief Indicates that an item cannot be created because it exists already. |
163 | +*/ |
164 | +class UNITY_STORAGE_EXPORT ExistsException : public StorageException |
165 | +{ |
166 | +public: |
167 | + ExistsException(std::string const& error_message, std::string const& identity, std::string const& name); |
168 | + ~ExistsException(); |
169 | + |
170 | + std::string native_identity() const; |
171 | + std::string name() const; |
172 | + |
173 | +private: |
174 | + std::string identity_; |
175 | + std::string name_; |
176 | +}; |
177 | + |
178 | +/** |
179 | +\brief Indicates that an upload detected a version mismatch. |
180 | +*/ |
181 | +class UNITY_STORAGE_EXPORT ConflictException : public StorageException |
182 | +{ |
183 | +public: |
184 | + ConflictException(std::string const& error_message); |
185 | + ~ConflictException(); |
186 | +}; |
187 | + |
188 | +/** |
189 | +\brief Indicates that an operation failed because of a permission problem. |
190 | +*/ |
191 | +class UNITY_STORAGE_EXPORT PermissionException : public StorageException |
192 | +{ |
193 | +public: |
194 | + PermissionException(std::string const& error_message); |
195 | + ~PermissionException(); |
196 | +}; |
197 | + |
198 | +/** |
199 | +\brief Indicates that an update failed because the provider ran out of space. |
200 | +*/ |
201 | +class UNITY_STORAGE_EXPORT QuotaException : public StorageException |
202 | +{ |
203 | +public: |
204 | + QuotaException(std::string const& error_message); |
205 | + ~QuotaException(); |
206 | +}; |
207 | + |
208 | +/** |
209 | +\brief Indicates that an upload or download was cancelled before it could complete. |
210 | +*/ |
211 | +class UNITY_STORAGE_EXPORT CancelledException : public StorageException |
212 | +{ |
213 | +public: |
214 | + CancelledException(std::string const& error_message); |
215 | + ~CancelledException(); |
216 | +}; |
217 | + |
218 | +/** |
219 | +\brief Indicates incorrect use of the API, such as calling methods in the wrong order. |
220 | +*/ |
221 | +class UNITY_STORAGE_EXPORT LogicException : public StorageException |
222 | +{ |
223 | +public: |
224 | + LogicException(std::string const& error_message); |
225 | + ~LogicException(); |
226 | +}; |
227 | + |
228 | +/** |
229 | +\brief Indicates an invalid parameter, such as a negative value when a positive one was |
230 | +expected, or a string that does not parse correctly or is empty when it should be non-empty. |
231 | +*/ |
232 | +class UNITY_STORAGE_EXPORT InvalidArgumentException : public StorageException |
233 | +{ |
234 | +public: |
235 | + InvalidArgumentException(std::string const& error_message); |
236 | + ~InvalidArgumentException(); |
237 | +}; |
238 | + |
239 | +/** |
240 | +\brief Indicates a system error, such as failure to create a file or folder, |
241 | +or any other (usually non-recoverable) kind of error that should not arise during normal operation. |
242 | +*/ |
243 | +class UNITY_STORAGE_EXPORT ResourceException : public StorageException |
244 | +{ |
245 | +public: |
246 | + ResourceException(std::string const& error_message, int error_code); |
247 | + ~ResourceException(); |
248 | + |
249 | + int error_code() const noexcept; |
250 | + |
251 | +private: |
252 | + int error_code_; |
253 | +}; |
254 | + |
255 | +/** |
256 | +\brief Indicates that the server side caught an exception that does not derive from |
257 | +StorageException, such as a std::exception, or caught some other unknown type (such as `int`). |
258 | +*/ |
259 | +class UNITY_STORAGE_EXPORT UnknownException : public StorageException |
260 | +{ |
261 | +public: |
262 | + UnknownException(std::string const& error_message); |
263 | + ~UnknownException(); |
264 | +}; |
265 | + |
266 | +} // namespace provider |
267 | +} // namespace storage |
268 | +} // namespace unity |
269 | |
270 | === modified file 'include/unity/storage/provider/internal/Handler.h' |
271 | --- include/unity/storage/provider/internal/Handler.h 2016-07-19 07:08:50 +0000 |
272 | +++ include/unity/storage/provider/internal/Handler.h 2016-08-11 02:49:47 +0000 |
273 | @@ -63,6 +63,8 @@ |
274 | void finished(); |
275 | |
276 | private: |
277 | + void marshal_exception(std::exception_ptr ep); |
278 | + |
279 | std::shared_ptr<AccountData> const account_; |
280 | Callback const callback_; |
281 | QDBusConnection const bus_; |
282 | |
283 | === modified file 'include/unity/storage/qt/client/Exceptions.h' |
284 | --- include/unity/storage/qt/client/Exceptions.h 2016-08-02 04:29:06 +0000 |
285 | +++ include/unity/storage/qt/client/Exceptions.h 2016-08-11 02:49:47 +0000 |
286 | @@ -228,7 +228,7 @@ |
287 | }; |
288 | |
289 | /** |
290 | -\brief Indicates a system error, such as failure to to create a file or folder, |
291 | +\brief Indicates a system error, such as failure to create a file or folder, |
292 | or any other (usually non-recoverable) kind of error that should not arise during normal operation. |
293 | */ |
294 | class UNITY_STORAGE_EXPORT ResourceException : public StorageException |
295 | |
296 | === modified file 'include/unity/storage/qt/client/internal/ItemBase.h' |
297 | --- include/unity/storage/qt/client/internal/ItemBase.h 2016-08-02 04:29:06 +0000 |
298 | +++ include/unity/storage/qt/client/internal/ItemBase.h 2016-08-11 02:49:47 +0000 |
299 | @@ -20,10 +20,10 @@ |
300 | |
301 | #include <unity/storage/common.h> |
302 | |
303 | -#include <QDateTime> |
304 | #pragma GCC diagnostic push |
305 | #pragma GCC diagnostic ignored "-Wcast-align" |
306 | #pragma GCC diagnostic ignored "-Wctor-dtor-privacy" |
307 | +#include <QDateTime> |
308 | #include <QFuture> |
309 | #pragma GCC diagnostic pop |
310 | #include <QVariantMap> |
311 | |
312 | === modified file 'include/unity/storage/qt/client/internal/remote_client/Handler.h' |
313 | --- include/unity/storage/qt/client/internal/remote_client/Handler.h 2016-08-02 03:02:15 +0000 |
314 | +++ include/unity/storage/qt/client/internal/remote_client/Handler.h 2016-08-11 02:49:47 +0000 |
315 | @@ -20,10 +20,13 @@ |
316 | |
317 | #include <unity/storage/qt/client/Exceptions.h> |
318 | #include <unity/storage/qt/client/internal/make_future.h> |
319 | +#include <unity/storage/qt/client/internal/remote_client/dbusmarshal.h> |
320 | #include <unity/storage/qt/client/internal/remote_client/HandlerBase.h> |
321 | |
322 | #include <QDBusPendingReply> |
323 | |
324 | +#include <cassert> |
325 | + |
326 | namespace unity |
327 | { |
328 | namespace storage |
329 | @@ -72,8 +75,22 @@ |
330 | { |
331 | if (call.isError()) |
332 | { |
333 | - int err = call.error().type(); |
334 | - make_exceptional_future<T>(ResourceException("DBus error return", err)); |
335 | + try |
336 | + { |
337 | + auto ep = unmarshal_exception(call); |
338 | + std::rethrow_exception(ep); |
339 | + } |
340 | + catch (StorageException const& e) |
341 | + { |
342 | + make_exceptional_future<T>(qf_, e); |
343 | + return; |
344 | + } |
345 | + // LCOV_EXCL_START |
346 | + catch (...) |
347 | + { |
348 | + abort(); // Impossible. |
349 | + } |
350 | + // LCOV_EXCL_STOP |
351 | return; |
352 | } |
353 | // TODO: See HACK above. Should just be closure(call, qf_); |
354 | |
355 | === modified file 'include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h' |
356 | --- include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h 2016-07-12 02:22:05 +0000 |
357 | +++ include/unity/storage/qt/client/internal/remote_client/dbusmarshal.h 2016-08-11 02:49:47 +0000 |
358 | @@ -24,6 +24,8 @@ |
359 | #include <QMetaType> |
360 | #include <QVariant> |
361 | |
362 | +class QDBusPendingCallWatcher; |
363 | + |
364 | namespace unity |
365 | { |
366 | namespace storage |
367 | @@ -39,8 +41,24 @@ |
368 | QDBusArgument const& operator>>(QDBusArgument const& argument, QList<storage::internal::ItemMetadata>& md_list); |
369 | |
370 | } // namespace internal |
371 | -} // namespace storage |
372 | -} // namespace unity |
373 | + |
374 | +namespace qt |
375 | +{ |
376 | +namespace client |
377 | +{ |
378 | +namespace internal |
379 | +{ |
380 | +namespace remote_client |
381 | +{ |
382 | + |
383 | +std::exception_ptr unmarshal_exception(QDBusPendingCallWatcher const& call); |
384 | + |
385 | +} // namespace remote_client |
386 | +} // namespace internal |
387 | +} // client |
388 | +} // qt |
389 | +} // storage |
390 | +} // unity |
391 | |
392 | Q_DECLARE_METATYPE(unity::storage::internal::ItemMetadata) |
393 | Q_DECLARE_METATYPE(QList<unity::storage::internal::ItemMetadata>) |
394 | |
395 | === modified file 'src/provider/CMakeLists.txt' |
396 | --- src/provider/CMakeLists.txt 2016-08-03 03:49:49 +0000 |
397 | +++ src/provider/CMakeLists.txt 2016-08-11 02:49:47 +0000 |
398 | @@ -14,6 +14,7 @@ |
399 | |
400 | add_library(sf-provider-objects OBJECT |
401 | DownloadJob.cpp |
402 | + Exceptions.cpp |
403 | ProviderBase.cpp |
404 | Server.cpp |
405 | TempfileUploadJob.cpp |
406 | |
407 | === added file 'src/provider/Exceptions.cpp' |
408 | --- src/provider/Exceptions.cpp 1970-01-01 00:00:00 +0000 |
409 | +++ src/provider/Exceptions.cpp 2016-08-11 02:49:47 +0000 |
410 | @@ -0,0 +1,157 @@ |
411 | +/* |
412 | + * Copyright (C) 2016 Canonical Ltd |
413 | + * |
414 | + * This program is free software: you can redistribute it and/or modify |
415 | + * it under the terms of the GNU Lesser General Public License version 3 as |
416 | + * published by the Free Software Foundation. |
417 | + * |
418 | + * This program is distributed in the hope that it will be useful, |
419 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
420 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
421 | + * GNU Lesser General Public License for more details. |
422 | + * |
423 | + * You should have received a copy of the GNU Lesser General Public License |
424 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
425 | + * |
426 | + * Authors: Michi Henning <michi.henning@canonical.com> |
427 | + */ |
428 | + |
429 | +#include <unity/storage/provider/Exceptions.h> |
430 | + |
431 | +using namespace std; |
432 | + |
433 | +namespace unity |
434 | +{ |
435 | +namespace storage |
436 | +{ |
437 | +namespace provider |
438 | +{ |
439 | + |
440 | +StorageException::StorageException(std::string const& exception_type, string const& error_message) |
441 | + : what_string_(string(exception_type) + ": " + error_message) |
442 | + , type_(exception_type) |
443 | + , error_message_(error_message) |
444 | +{ |
445 | +} |
446 | + |
447 | +StorageException::~StorageException() = default; |
448 | + |
449 | +char const* StorageException::what() const noexcept |
450 | +{ |
451 | + return what_string_.c_str(); |
452 | +} |
453 | + |
454 | +string StorageException::type() const |
455 | +{ |
456 | + return type_; |
457 | +} |
458 | + |
459 | +string StorageException::error_message() const |
460 | +{ |
461 | + return error_message_; |
462 | +} |
463 | + |
464 | +RemoteCommsException::RemoteCommsException(string const& error_message) |
465 | + : StorageException("RemoteCommsException", error_message) |
466 | +{ |
467 | +} |
468 | + |
469 | +RemoteCommsException::~RemoteCommsException() = default; |
470 | + |
471 | +NotExistsException::NotExistsException(string const& error_message, string const& key) |
472 | + : StorageException("NotExistsException", error_message) |
473 | + , key_(key) |
474 | +{ |
475 | +} |
476 | + |
477 | +NotExistsException::~NotExistsException() = default; |
478 | + |
479 | +string NotExistsException::key() const |
480 | +{ |
481 | + return key_; |
482 | +} |
483 | + |
484 | +ExistsException::ExistsException(string const& error_message, string const& identity, string const& name) |
485 | + : StorageException("ExistsException", error_message) |
486 | + , identity_(identity) |
487 | + , name_(name) |
488 | +{ |
489 | +} |
490 | + |
491 | +ExistsException::~ExistsException() = default; |
492 | + |
493 | +string ExistsException::native_identity() const |
494 | +{ |
495 | + return identity_; |
496 | +} |
497 | + |
498 | +string ExistsException::name() const |
499 | +{ |
500 | + return name_; |
501 | +} |
502 | + |
503 | +ConflictException::ConflictException(string const& error_message) |
504 | + : StorageException("ConflictException", error_message) |
505 | +{ |
506 | +} |
507 | + |
508 | +ConflictException::~ConflictException() = default; |
509 | + |
510 | +PermissionException::PermissionException(string const& error_message) |
511 | + : StorageException("PermissionException", error_message) |
512 | +{ |
513 | +} |
514 | + |
515 | +PermissionException::~PermissionException() = default; |
516 | + |
517 | +QuotaException::QuotaException(string const& error_message) |
518 | + : StorageException("QuotaException", error_message) |
519 | +{ |
520 | +} |
521 | + |
522 | +QuotaException::~QuotaException() = default; |
523 | + |
524 | +CancelledException::CancelledException(string const& error_message) |
525 | + : StorageException("CancelledException", error_message) |
526 | +{ |
527 | +} |
528 | + |
529 | +CancelledException::~CancelledException() = default; |
530 | + |
531 | +LogicException::LogicException(string const& error_message) |
532 | + : StorageException("LogicException", error_message) |
533 | +{ |
534 | +} |
535 | + |
536 | +LogicException::~LogicException() = default; |
537 | + |
538 | +InvalidArgumentException::InvalidArgumentException(string const& error_message) |
539 | + : StorageException("InvalidArgumentException", error_message) |
540 | +{ |
541 | +} |
542 | + |
543 | +InvalidArgumentException::~InvalidArgumentException() = default; |
544 | + |
545 | +ResourceException::ResourceException(string const& error_message, int error_code) |
546 | + : StorageException("ResourceException", error_message) |
547 | + , error_code_(error_code) |
548 | +{ |
549 | +} |
550 | + |
551 | +ResourceException::~ResourceException() = default; |
552 | + |
553 | +int ResourceException::error_code() const noexcept |
554 | +{ |
555 | + return error_code_; |
556 | +} |
557 | + |
558 | +UnknownException::UnknownException(string const& error_message) |
559 | + : StorageException("UnknownException", error_message) |
560 | +{ |
561 | +} |
562 | + |
563 | +UnknownException::~UnknownException() = default; |
564 | + |
565 | +} // namespace provider |
566 | +} // namespace storage |
567 | +} // namespace unity |
568 | |
569 | === modified file 'src/provider/internal/Handler.cpp' |
570 | --- src/provider/internal/Handler.cpp 2016-07-20 02:20:53 +0000 |
571 | +++ src/provider/internal/Handler.cpp 2016-08-11 02:49:47 +0000 |
572 | @@ -17,20 +17,20 @@ |
573 | */ |
574 | |
575 | #include <unity/storage/provider/internal/Handler.h> |
576 | + |
577 | +#include <unity/storage/internal/dbus_error.h> |
578 | #include <unity/storage/provider/internal/AccountData.h> |
579 | +#include <unity/storage/provider/internal/dbusmarshal.h> |
580 | #include <unity/storage/provider/internal/DBusPeerCache.h> |
581 | #include <unity/storage/provider/internal/MainLoopExecutor.h> |
582 | #include <unity/storage/provider/ProviderBase.h> |
583 | +#include <unity/storage/provider/Exceptions.h> |
584 | |
585 | #include <stdexcept> |
586 | |
587 | +using namespace unity::storage::internal; |
588 | using namespace std; |
589 | |
590 | -namespace |
591 | -{ |
592 | -char const ERROR[] = "com.canonical.StorageFramework.Provider.Error"; |
593 | -} |
594 | - |
595 | namespace unity |
596 | { |
597 | namespace storage |
598 | @@ -53,7 +53,8 @@ |
599 | auto peer_future = account_->dbus_peer().get(message_.service()); |
600 | creds_future_ = peer_future.then( |
601 | EXEC_IN_MAIN |
602 | - [this](decltype(peer_future) f) { |
603 | + [this](decltype(peer_future) f) |
604 | + { |
605 | auto info = f.get(); |
606 | if (info.valid) |
607 | { |
608 | @@ -64,8 +65,8 @@ |
609 | } |
610 | else |
611 | { |
612 | - reply_ = message_.createErrorReply( |
613 | - ERROR, "Handler::begin(): could not retrieve credentials"); |
614 | + auto ep = make_exception_ptr(PermissionException("Handler::begin(): could not retrieve credentials")); |
615 | + marshal_exception(ep); |
616 | QMetaObject::invokeMethod(this, "send_reply", |
617 | Qt::QueuedConnection); |
618 | } |
619 | @@ -75,23 +76,27 @@ |
620 | void Handler::credentials_received() |
621 | { |
622 | boost::future<QDBusMessage> msg_future; |
623 | - try { |
624 | + try |
625 | + { |
626 | msg_future = callback_(account_, context_, message_); |
627 | - } catch (std::exception const& e) { |
628 | - reply_ = message_.createErrorReply(ERROR, e.what()); |
629 | + } |
630 | + catch (std::exception const& e) |
631 | + { |
632 | + marshal_exception(current_exception()); |
633 | QMetaObject::invokeMethod(this, "send_reply", Qt::QueuedConnection); |
634 | return; |
635 | } |
636 | reply_future_ = msg_future.then( |
637 | EXEC_IN_MAIN |
638 | - [this](decltype(msg_future) f) { |
639 | + [this](decltype(msg_future) f) |
640 | + { |
641 | try |
642 | { |
643 | reply_ = f.get(); |
644 | } |
645 | - catch (std::exception const& e) |
646 | + catch (std::exception const&) |
647 | { |
648 | - reply_ = message_.createErrorReply(ERROR, e.what()); |
649 | + marshal_exception(current_exception()); |
650 | } |
651 | QMetaObject::invokeMethod(this, "send_reply", Qt::QueuedConnection); |
652 | }); |
653 | @@ -103,6 +108,48 @@ |
654 | Q_EMIT finished(); |
655 | } |
656 | |
657 | +void Handler::marshal_exception(exception_ptr ep) |
658 | +{ |
659 | + try |
660 | + { |
661 | + rethrow_exception(ep); |
662 | + } |
663 | + catch (StorageException const& e) |
664 | + { |
665 | + reply_ = message_.createErrorReply(QString(DBUS_ERROR_PREFIX) + QString::fromStdString(e.type()), |
666 | + QString::fromStdString(e.error_message())); |
667 | + try |
668 | + { |
669 | + throw; |
670 | + } |
671 | + catch (NotExistsException const& e) |
672 | + { |
673 | + reply_ << QVariant(QString::fromStdString(e.key())); |
674 | + } |
675 | + catch (ExistsException const& e) |
676 | + { |
677 | + reply_ << QVariant(QString::fromStdString(e.native_identity())); |
678 | + reply_ << QVariant(QString::fromStdString(e.name())); |
679 | + } |
680 | + catch (ResourceException const& e) |
681 | + { |
682 | + reply_ << QVariant(e.error_code()); |
683 | + } |
684 | + catch (StorageException const&) |
685 | + { |
686 | + // Some other sub-type of StorageException without additional data members. |
687 | + } |
688 | + } |
689 | + catch (std::exception const& e) |
690 | + { |
691 | + reply_ = message_.createErrorReply(QString(DBUS_ERROR_PREFIX) + "UnknownException", e.what()); |
692 | + } |
693 | + catch (...) |
694 | + { |
695 | + reply_ = message_.createErrorReply(QString(DBUS_ERROR_PREFIX) + "UnknownException", "unknown exception type"); |
696 | + } |
697 | +} |
698 | + |
699 | } |
700 | } |
701 | } |
702 | |
703 | === modified file 'src/qt/client/Exceptions.cpp' |
704 | --- src/qt/client/Exceptions.cpp 2016-08-02 04:29:06 +0000 |
705 | +++ src/qt/client/Exceptions.cpp 2016-08-11 02:49:47 +0000 |
706 | @@ -105,7 +105,7 @@ |
707 | } |
708 | |
709 | RuntimeDestroyedException::RuntimeDestroyedException(QString const& method) |
710 | - : StorageException("RuntimeDestroyedException", method + ": Runtime was destroyed previously") |
711 | + : StorageException("RuntimeDestroyedException", method + ": runtime was destroyed previously") |
712 | { |
713 | } |
714 | |
715 | |
716 | === modified file 'src/qt/client/internal/local_client/FolderImpl.cpp' |
717 | --- src/qt/client/internal/local_client/FolderImpl.cpp 2016-08-02 05:27:00 +0000 |
718 | +++ src/qt/client/internal/local_client/FolderImpl.cpp 2016-08-11 02:49:47 +0000 |
719 | @@ -67,7 +67,7 @@ |
720 | { |
721 | lock_guard<decltype(mutex_)> guard(mutex_); |
722 | |
723 | - throw_if_destroyed("Folder::name()"); |
724 | + throw_if_destroyed("Item::name()"); |
725 | return name_; |
726 | } |
727 | |
728 | |
729 | === modified file 'src/qt/client/internal/local_client/RootImpl.cpp' |
730 | --- src/qt/client/internal/local_client/RootImpl.cpp 2016-08-03 06:09:59 +0000 |
731 | +++ src/qt/client/internal/local_client/RootImpl.cpp 2016-08-11 02:49:47 +0000 |
732 | @@ -71,7 +71,7 @@ |
733 | { |
734 | lock_guard<decltype(mutex_)> guard(mutex_); |
735 | |
736 | - throw_if_destroyed("Root::name()"); |
737 | + throw_if_destroyed("Item::name()"); |
738 | return ""; |
739 | } |
740 | |
741 | @@ -79,7 +79,14 @@ |
742 | { |
743 | lock_guard<decltype(mutex_)> guard(mutex_); |
744 | |
745 | - throw_if_destroyed("Root::parents()"); |
746 | + try |
747 | + { |
748 | + throw_if_destroyed("Item::parents()"); |
749 | + } |
750 | + catch (StorageException const& e) |
751 | + { |
752 | + return internal::make_exceptional_future<QVector<Folder::SPtr>>(e); |
753 | + } |
754 | return make_ready_future(QVector<Folder::SPtr>()); // For the root, we return an empty vector. |
755 | } |
756 | |
757 | @@ -87,7 +94,7 @@ |
758 | { |
759 | lock_guard<decltype(mutex_)> guard(mutex_); |
760 | |
761 | - throw_if_destroyed("Root::parent_ids()"); |
762 | + throw_if_destroyed("Item::parent_ids()"); |
763 | return QVector<QString>(); // For the root, we return an empty vector. |
764 | } |
765 | |
766 | @@ -97,14 +104,14 @@ |
767 | |
768 | try |
769 | { |
770 | - throw_if_destroyed("Root::delete_item()"); |
771 | + throw_if_destroyed("Item::delete_item()"); |
772 | } |
773 | catch (StorageException const& e) |
774 | { |
775 | return internal::make_exceptional_future(e); |
776 | } |
777 | // Cannot delete root. |
778 | - return internal::make_exceptional_future(LogicException("Root::delete_item(): Cannot delete root folder")); |
779 | + return internal::make_exceptional_future(LogicException("Item::delete_item(): cannot delete root folder")); |
780 | } |
781 | |
782 | QFuture<int64_t> RootImpl::free_space_bytes() const |
783 | |
784 | === modified file 'src/qt/client/internal/local_client/RuntimeImpl.cpp' |
785 | --- src/qt/client/internal/local_client/RuntimeImpl.cpp 2016-08-02 03:02:15 +0000 |
786 | +++ src/qt/client/internal/local_client/RuntimeImpl.cpp 2016-08-11 02:49:47 +0000 |
787 | @@ -80,7 +80,7 @@ |
788 | { |
789 | if (destroyed_) |
790 | { |
791 | - throw RuntimeDestroyedException("Runtime::accounts()"); |
792 | + return internal::make_exceptional_future<QVector<Account::SPtr>>(RuntimeDestroyedException("Runtime::accounts()")); |
793 | } |
794 | |
795 | char const* user = g_get_user_name(); |
796 | |
797 | === modified file 'src/qt/client/internal/remote_client/AccountImpl.cpp' |
798 | --- src/qt/client/internal/remote_client/AccountImpl.cpp 2016-08-02 03:02:15 +0000 |
799 | +++ src/qt/client/internal/remote_client/AccountImpl.cpp 2016-08-11 02:49:47 +0000 |
800 | @@ -83,6 +83,15 @@ |
801 | |
802 | QFuture<QVector<Root::SPtr>> AccountImpl::roots() |
803 | { |
804 | + try |
805 | + { |
806 | + runtime(); // Throws if runtime was destroyed. |
807 | + } |
808 | + catch (RuntimeDestroyedException const& e) |
809 | + { |
810 | + return make_exceptional_future<QVector<Root::SPtr>>(e); |
811 | + } |
812 | + |
813 | auto reply = provider_->Roots(); |
814 | |
815 | auto process_reply = [this](decltype(reply) const& reply, QFutureInterface<QVector<Root::SPtr>>& qf) |
816 | |
817 | === modified file 'src/qt/client/internal/remote_client/FileImpl.cpp' |
818 | --- src/qt/client/internal/remote_client/FileImpl.cpp 2016-08-02 04:29:06 +0000 |
819 | +++ src/qt/client/internal/remote_client/FileImpl.cpp 2016-08-11 02:49:47 +0000 |
820 | @@ -56,7 +56,7 @@ |
821 | { |
822 | try |
823 | { |
824 | - throw_if_destroyed("File::create_uploader()()"); |
825 | + throw_if_destroyed("File::create_uploader()"); |
826 | } |
827 | catch (StorageException const& e) |
828 | { |
829 | @@ -78,7 +78,7 @@ |
830 | auto root = get_root(); |
831 | if (!root) |
832 | { |
833 | - make_exceptional_future<shared_ptr<Uploader>>(RuntimeDestroyedException("File::create_uploader()")); |
834 | + make_exceptional_future(qf, RuntimeDestroyedException("File::create_uploader()")); |
835 | return; |
836 | } |
837 | |
838 | @@ -89,7 +89,7 @@ |
839 | // TODO: log server error here |
840 | QString msg = "File::create_uploader(): impossible file descriptor returned by server: " |
841 | + QString::number(fd.fileDescriptor()); |
842 | - make_exceptional_future<shared_ptr<Uploader>>(qf, LocalCommsException(msg)); |
843 | + make_exceptional_future(qf, LocalCommsException(msg)); |
844 | return; |
845 | } |
846 | auto uploader = UploaderImpl::make_uploader(upload_id, fd, size, old_etag, root, prov); |
847 | @@ -103,7 +103,7 @@ |
848 | { |
849 | try |
850 | { |
851 | - throw_if_destroyed("File::create_downloader()()"); |
852 | + throw_if_destroyed("File::create_downloader()"); |
853 | } |
854 | catch (StorageException const& e) |
855 | { |
856 | @@ -116,11 +116,13 @@ |
857 | auto process_reply = [this, prov](QDBusPendingReply<QString, QDBusUnixFileDescriptor> const& reply, |
858 | QFutureInterface<std::shared_ptr<Downloader>>& qf) |
859 | { |
860 | - auto root = get_root(); |
861 | - if (!root) |
862 | - { |
863 | - make_exceptional_future<shared_ptr<Uploader>>(RuntimeDestroyedException("File::create_downloader()")); |
864 | - return; |
865 | + try |
866 | + { |
867 | + throw_if_destroyed("File::create_downloader()"); |
868 | + } |
869 | + catch (StorageException const& e) |
870 | + { |
871 | + make_exceptional_future(qf, e); |
872 | } |
873 | |
874 | auto download_id = reply.argumentAt<0>(); |
875 | |
876 | === modified file 'src/qt/client/internal/remote_client/FolderImpl.cpp' |
877 | --- src/qt/client/internal/remote_client/FolderImpl.cpp 2016-08-02 04:29:06 +0000 |
878 | +++ src/qt/client/internal/remote_client/FolderImpl.cpp 2016-08-11 02:49:47 +0000 |
879 | @@ -67,10 +67,6 @@ |
880 | } |
881 | |
882 | auto prov = provider(); |
883 | - if (!prov) |
884 | - { |
885 | - return make_exceptional_future<QVector<shared_ptr<Item>>>(RuntimeDestroyedException("Folder::list()")); |
886 | - } |
887 | auto reply = prov->List(md_.item_id, ""); |
888 | |
889 | // Sorry for the mess, but we can't use auto for the lambda because it calls itself, |
890 | |
891 | === modified file 'src/qt/client/internal/remote_client/ItemImpl.cpp' |
892 | --- src/qt/client/internal/remote_client/ItemImpl.cpp 2016-08-02 04:29:06 +0000 |
893 | +++ src/qt/client/internal/remote_client/ItemImpl.cpp 2016-08-11 02:49:47 +0000 |
894 | @@ -82,16 +82,16 @@ |
895 | return internal::make_exceptional_future<shared_ptr<Item>>(InvalidArgumentException(msg)); |
896 | } |
897 | |
898 | + auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
899 | try |
900 | { |
901 | throw_if_destroyed("Item::copy()"); |
902 | + new_parent_impl->throw_if_destroyed("Item::copy()"); |
903 | } |
904 | catch (StorageException const& e) |
905 | { |
906 | return make_exceptional_future<shared_ptr<Item>>(e); |
907 | } |
908 | - auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
909 | - new_parent_impl->throw_if_destroyed("Item::copy()"); |
910 | |
911 | auto prov = provider(); |
912 | auto reply = prov->Copy(md_.item_id, new_parent->native_identity(), new_name); |
913 | @@ -130,16 +130,16 @@ |
914 | return internal::make_exceptional_future<shared_ptr<Item>>(InvalidArgumentException(msg)); |
915 | } |
916 | |
917 | + auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
918 | try |
919 | { |
920 | throw_if_destroyed("Item::move()"); |
921 | + new_parent_impl->throw_if_destroyed("Item::move()"); |
922 | } |
923 | catch (StorageException const& e) |
924 | { |
925 | return make_exceptional_future<shared_ptr<Item>>(e); |
926 | } |
927 | - auto new_parent_impl = dynamic_pointer_cast<FolderImpl>(new_parent->p_); |
928 | - new_parent_impl->throw_if_destroyed("Item::move()"); |
929 | |
930 | auto prov = provider(); |
931 | if (!prov) |
932 | @@ -195,7 +195,14 @@ |
933 | |
934 | QFuture<void> ItemImpl::delete_item() |
935 | { |
936 | - throw_if_destroyed("Item::delete_item()"); |
937 | + try |
938 | + { |
939 | + throw_if_destroyed("Item::delete_item()"); |
940 | + } |
941 | + catch (StorageException const& e) |
942 | + { |
943 | + return internal::make_exceptional_future(e); |
944 | + } |
945 | |
946 | auto prov = provider(); |
947 | auto reply = prov->Delete(md_.item_id); |
948 | |
949 | === modified file 'src/qt/client/internal/remote_client/RootImpl.cpp' |
950 | --- src/qt/client/internal/remote_client/RootImpl.cpp 2016-08-02 03:02:15 +0000 |
951 | +++ src/qt/client/internal/remote_client/RootImpl.cpp 2016-08-11 02:49:47 +0000 |
952 | @@ -50,37 +50,46 @@ |
953 | |
954 | QFuture<QVector<Folder::SPtr>> RootImpl::parents() const |
955 | { |
956 | - if (!get_root()) |
957 | - { |
958 | - return make_exceptional_future<QVector<Folder::SPtr>>(RuntimeDestroyedException("Root::parents()")); |
959 | + try |
960 | + { |
961 | + throw_if_destroyed("Root::parents()"); |
962 | + } |
963 | + catch (StorageException const& e) |
964 | + { |
965 | + return make_exceptional_future<QVector<Folder::SPtr>>(e); |
966 | } |
967 | return make_ready_future(QVector<Folder::SPtr>()); // For the root, we return an empty vector. |
968 | } |
969 | |
970 | QVector<QString> RootImpl::parent_ids() const |
971 | { |
972 | - if (!get_root()) |
973 | - { |
974 | - return make_exceptional_future<QVector<QString>>(RuntimeDestroyedException("Root::parent_ids()")); |
975 | - } |
976 | + throw_if_destroyed("Root::parent_ids()"); |
977 | return QVector<QString>(); // For the root, we return an empty vector. |
978 | } |
979 | |
980 | QFuture<void> RootImpl::delete_item() |
981 | { |
982 | - if (!get_root()) |
983 | - { |
984 | - return make_exceptional_future(RuntimeDestroyedException("Root::delete_item()")); |
985 | + try |
986 | + { |
987 | + throw_if_destroyed("Item::delete_item()"); |
988 | + } |
989 | + catch (StorageException const& e) |
990 | + { |
991 | + return make_exceptional_future<QVector<Folder::SPtr>>(e); |
992 | } |
993 | // Cannot delete root. |
994 | - return make_exceptional_future(LogicException("Root::delete_item(): root item cannot be deleted")); |
995 | + return make_exceptional_future(LogicException("Item::delete_item(): cannot delete root folder")); |
996 | } |
997 | |
998 | QFuture<int64_t> RootImpl::free_space_bytes() const |
999 | { |
1000 | - if (!get_root()) |
1001 | - { |
1002 | - return make_exceptional_future<int64_t>(RuntimeDestroyedException("Root::free_space_bytes()")); |
1003 | + try |
1004 | + { |
1005 | + throw_if_destroyed("Root::free_space_bytes()"); |
1006 | + } |
1007 | + catch (StorageException const& e) |
1008 | + { |
1009 | + return make_exceptional_future<int64_t>(e); |
1010 | } |
1011 | // TODO, need to refresh metadata here instead. |
1012 | return make_ready_future(int64_t(1)); |
1013 | @@ -88,9 +97,13 @@ |
1014 | |
1015 | QFuture<int64_t> RootImpl::used_space_bytes() const |
1016 | { |
1017 | - if (!get_root()) |
1018 | - { |
1019 | - return make_exceptional_future<int64_t>(RuntimeDestroyedException("Root::used_space_bytes()")); |
1020 | + try |
1021 | + { |
1022 | + throw_if_destroyed("Root::used_space_bytes()"); |
1023 | + } |
1024 | + catch (StorageException const& e) |
1025 | + { |
1026 | + return make_exceptional_future<int64_t>(e); |
1027 | } |
1028 | // TODO, need to refresh metadata here instead. |
1029 | return make_ready_future(int64_t(1)); |
1030 | @@ -98,9 +111,13 @@ |
1031 | |
1032 | QFuture<Item::SPtr> RootImpl::get(QString native_identity) const |
1033 | { |
1034 | - if (!get_root()) |
1035 | - { |
1036 | - return make_exceptional_future<Item::SPtr>(RuntimeDestroyedException("Root::get()")); |
1037 | + try |
1038 | + { |
1039 | + throw_if_destroyed("Root::get()"); |
1040 | + } |
1041 | + catch (StorageException const& e) |
1042 | + { |
1043 | + return make_exceptional_future<Item::SPtr>(e); |
1044 | } |
1045 | |
1046 | auto prov = provider(); |
1047 | @@ -115,7 +132,7 @@ |
1048 | } |
1049 | catch (RuntimeDestroyedException const&) |
1050 | { |
1051 | - make_exceptional_future<Item::SPtr>(qf, RuntimeDestroyedException("Root::get()")); |
1052 | + make_exceptional_future(qf, RuntimeDestroyedException("Root::get()")); |
1053 | return; |
1054 | } |
1055 | |
1056 | |
1057 | === modified file 'src/qt/client/internal/remote_client/RuntimeImpl.cpp' |
1058 | --- src/qt/client/internal/remote_client/RuntimeImpl.cpp 2016-08-02 03:02:15 +0000 |
1059 | +++ src/qt/client/internal/remote_client/RuntimeImpl.cpp 2016-08-11 02:49:47 +0000 |
1060 | @@ -128,7 +128,6 @@ |
1061 | QVector<Account::SPtr> accounts; |
1062 | for (auto const& a : manager_->availableAccounts("google-drive-scope")) |
1063 | { |
1064 | - qDebug() << "got account:" << a->displayName() << a->serviceId() << a->id(); |
1065 | auto impl = new AccountImpl(public_instance_, a->id(), "", a->serviceId(), a->displayName()); |
1066 | Account::SPtr acc(new Account(impl)); |
1067 | impl->set_public_instance(acc); |
1068 | |
1069 | === modified file 'src/qt/client/internal/remote_client/dbusmarshal.cpp' |
1070 | --- src/qt/client/internal/remote_client/dbusmarshal.cpp 2016-07-12 02:22:05 +0000 |
1071 | +++ src/qt/client/internal/remote_client/dbusmarshal.cpp 2016-08-11 02:49:47 +0000 |
1072 | @@ -18,8 +18,19 @@ |
1073 | |
1074 | #include <unity/storage/qt/client/internal/remote_client/dbusmarshal.h> |
1075 | |
1076 | +#include <unity/storage/internal/dbus_error.h> |
1077 | +#include <unity/storage/qt/client/Exceptions.h> |
1078 | +#include <unity/storage/qt/client/internal/make_future.h> |
1079 | + |
1080 | +#include <QDBusPendingCallWatcher> |
1081 | +#include <QDBusPendingReply> |
1082 | #include <QDebug> |
1083 | |
1084 | +#include <cassert> |
1085 | +#include <functional> |
1086 | +#include <map> |
1087 | + |
1088 | +using namespace unity::storage::internal; |
1089 | using namespace std; |
1090 | |
1091 | namespace unity |
1092 | @@ -117,10 +128,94 @@ |
1093 | { |
1094 | namespace remote_client |
1095 | { |
1096 | - |
1097 | -} // remote_client |
1098 | -} // internal |
1099 | -} // client |
1100 | -} // qt |
1101 | -} // storage |
1102 | -} // unity |
1103 | +namespace |
1104 | +{ |
1105 | + |
1106 | +template<typename T> |
1107 | +exception_ptr make_exception(QDBusPendingCallWatcher const& call) |
1108 | +{ |
1109 | + QDBusPendingReply<QString> reply = call; |
1110 | + auto msg = reply.argumentAt<0>(); |
1111 | + return make_exception_ptr(T(msg)); |
1112 | +} |
1113 | + |
1114 | +template<> |
1115 | +exception_ptr make_exception<NotExistsException>(QDBusPendingCallWatcher const& call) |
1116 | +{ |
1117 | + QDBusPendingReply<QString, QString> reply = call; |
1118 | + auto msg = reply.argumentAt<0>(); |
1119 | + auto key = reply.argumentAt<1>(); |
1120 | + return make_exception_ptr(NotExistsException(msg, key)); |
1121 | +} |
1122 | + |
1123 | +template<> |
1124 | +exception_ptr make_exception<ExistsException>(QDBusPendingCallWatcher const& call) |
1125 | +{ |
1126 | + QDBusPendingReply<QString, QString, QString> reply = call; |
1127 | + auto msg = reply.argumentAt<0>(); |
1128 | + auto id = reply.argumentAt<1>(); |
1129 | + auto name = reply.argumentAt<2>(); |
1130 | + return make_exception_ptr(ExistsException(msg, id, name)); |
1131 | +} |
1132 | + |
1133 | +template<> |
1134 | +exception_ptr make_exception<ResourceException>(QDBusPendingCallWatcher const& call) |
1135 | +{ |
1136 | + QDBusPendingReply<QString, int> reply = call; |
1137 | + auto msg = reply.argumentAt<0>(); |
1138 | + auto error_code = reply.argumentAt<1>(); |
1139 | + return make_exception_ptr(ResourceException(msg, error_code)); |
1140 | +} |
1141 | + |
1142 | +static const map<QString, function<exception_ptr(QDBusPendingCallWatcher const& call)>> exception_factories = |
1143 | +{ |
1144 | + { "NotExistsException", make_exception<NotExistsException> }, |
1145 | + { "ExistsException", make_exception<ExistsException> }, |
1146 | + { "ResourceException", make_exception<ResourceException> }, |
1147 | + { "RemoteCommsException", make_exception<RemoteCommsException> }, |
1148 | + { "ConflictException", make_exception<ConflictException> }, |
1149 | + { "PermissionException", make_exception<PermissionException> }, |
1150 | + { "QuotaException", make_exception<QuotaException> }, |
1151 | + { "CancelledException", make_exception<CancelledException> }, |
1152 | + { "LogicException", make_exception<LogicException> }, |
1153 | + { "InvalidArgumentException", make_exception<InvalidArgumentException> }, |
1154 | + { "UnknownException", make_exception<LocalCommsException> } // Yes, LocalCommsException is intentional |
1155 | +}; |
1156 | + |
1157 | +} // namespace |
1158 | + |
1159 | +std::exception_ptr unmarshal_exception(QDBusPendingCallWatcher const& call) |
1160 | +{ |
1161 | + assert(call.isError()); |
1162 | + |
1163 | + int err = call.error().type(); |
1164 | + if (err != QDBusError::Other) |
1165 | + { |
1166 | + return make_exception_ptr(LocalCommsException(call.error().message())); |
1167 | + } |
1168 | + |
1169 | + auto exception_type = call.error().name(); |
1170 | + if (!exception_type.startsWith(DBUS_ERROR_PREFIX)) |
1171 | + { |
1172 | + QString msg = "unmarshal_exception(): unknown exception type received from server: " + exception_type |
1173 | + + ": " + call.error().message(); |
1174 | + return make_exception_ptr(LocalCommsException(msg)); |
1175 | + } |
1176 | + exception_type = exception_type.remove(0, strlen(DBUS_ERROR_PREFIX)); |
1177 | + |
1178 | + auto factory_it = exception_factories.find(exception_type); |
1179 | + if (factory_it == exception_factories.end()) |
1180 | + { |
1181 | + QString msg = "unmarshal_exception(): unknown exception type received from server: " + exception_type |
1182 | + + ": " + call.error().message(); |
1183 | + return make_exception_ptr(LocalCommsException(msg)); |
1184 | + } |
1185 | + return factory_it->second(call); |
1186 | +} |
1187 | + |
1188 | +} // namespace remote_client |
1189 | +} // namespace internal |
1190 | +} // namespace client |
1191 | +} // namespace qt |
1192 | +} // namespace storage |
1193 | +} // namespace unity |
1194 | |
1195 | === modified file 'tests/local-client/local-client_test.cpp' |
1196 | --- tests/local-client/local-client_test.cpp 2016-08-03 03:54:44 +0000 |
1197 | +++ tests/local-client/local-client_test.cpp 2016-08-11 02:49:47 +0000 |
1198 | @@ -43,7 +43,7 @@ |
1199 | |
1200 | static constexpr int SIGNAL_WAIT_TIME = 1000; |
1201 | |
1202 | -// Bunch of helper function to reduce the amount of noise in the tests. |
1203 | +// Bunch of helper functions to reduce the amount of noise in the tests. |
1204 | |
1205 | template<typename T> |
1206 | void wait(T fut) |
1207 | @@ -218,7 +218,6 @@ |
1208 | { |
1209 | auto runtime = Runtime::create(); |
1210 | |
1211 | - auto acc = get_account(runtime); |
1212 | auto root = get_root(runtime); |
1213 | clear_folder(root); |
1214 | |
1215 | @@ -311,7 +310,6 @@ |
1216 | { |
1217 | auto runtime = Runtime::create(); |
1218 | |
1219 | - auto acc = get_account(runtime); |
1220 | auto root = get_root(runtime); |
1221 | clear_folder(root); |
1222 | |
1223 | @@ -332,7 +330,6 @@ |
1224 | { |
1225 | auto runtime = Runtime::create(); |
1226 | |
1227 | - auto acc = get_account(runtime); |
1228 | auto root = get_root(runtime); |
1229 | clear_folder(root); |
1230 | |
1231 | @@ -416,7 +413,6 @@ |
1232 | { |
1233 | auto runtime = Runtime::create(); |
1234 | |
1235 | - auto acc = get_account(runtime); |
1236 | auto root = get_root(runtime); |
1237 | clear_folder(root); |
1238 | |
1239 | @@ -452,7 +448,6 @@ |
1240 | { |
1241 | auto runtime = Runtime::create(); |
1242 | |
1243 | - auto acc = get_account(runtime); |
1244 | auto root = get_root(runtime); |
1245 | clear_folder(root); |
1246 | |
1247 | @@ -498,7 +493,6 @@ |
1248 | { |
1249 | auto runtime = Runtime::create(); |
1250 | |
1251 | - auto acc = get_account(runtime); |
1252 | auto root = get_root(runtime); |
1253 | clear_folder(root); |
1254 | |
1255 | @@ -529,7 +523,6 @@ |
1256 | { |
1257 | auto runtime = Runtime::create(); |
1258 | |
1259 | - auto acc = get_account(runtime); |
1260 | auto root = get_root(runtime); |
1261 | clear_folder(root); |
1262 | |
1263 | @@ -555,7 +548,6 @@ |
1264 | { |
1265 | auto runtime = Runtime::create(); |
1266 | |
1267 | - auto acc = get_account(runtime); |
1268 | auto root = get_root(runtime); |
1269 | clear_folder(root); |
1270 | |
1271 | @@ -618,7 +610,6 @@ |
1272 | { |
1273 | auto runtime = Runtime::create(); |
1274 | |
1275 | - auto acc = get_account(runtime); |
1276 | auto root = get_root(runtime); |
1277 | clear_folder(root); |
1278 | |
1279 | @@ -637,7 +628,6 @@ |
1280 | { |
1281 | auto runtime = Runtime::create(); |
1282 | |
1283 | - auto acc = get_account(runtime); |
1284 | auto root = get_root(runtime); |
1285 | clear_folder(root); |
1286 | |
1287 | @@ -847,7 +837,6 @@ |
1288 | { |
1289 | auto runtime = Runtime::create(); |
1290 | |
1291 | - auto acc = get_account(runtime); |
1292 | auto root = get_root(runtime); |
1293 | clear_folder(root); |
1294 | |
1295 | @@ -904,7 +893,6 @@ |
1296 | { |
1297 | auto runtime = Runtime::create(); |
1298 | |
1299 | - auto acc = get_account(runtime); |
1300 | auto root = get_root(runtime); |
1301 | clear_folder(root); |
1302 | |
1303 | @@ -951,7 +939,6 @@ |
1304 | { |
1305 | auto runtime = Runtime::create(); |
1306 | |
1307 | - auto acc = get_account(runtime); |
1308 | auto root = get_root(runtime); |
1309 | clear_folder(root); |
1310 | |
1311 | @@ -965,7 +952,6 @@ |
1312 | { |
1313 | auto runtime = Runtime::create(); |
1314 | |
1315 | - auto acc = get_account(runtime); |
1316 | auto root = get_root(runtime); |
1317 | clear_folder(root); |
1318 | |
1319 | @@ -995,7 +981,6 @@ |
1320 | { |
1321 | auto runtime = Runtime::create(); |
1322 | |
1323 | - auto acc = get_account(runtime); |
1324 | auto root = get_root(runtime); |
1325 | clear_folder(root); |
1326 | |
1327 | @@ -1012,7 +997,6 @@ |
1328 | { |
1329 | auto runtime = Runtime::create(); |
1330 | |
1331 | - auto acc = get_account(runtime); |
1332 | auto root = get_root(runtime); |
1333 | clear_folder(root); |
1334 | |
1335 | @@ -1055,7 +1039,6 @@ |
1336 | { |
1337 | auto runtime = Runtime::create(); |
1338 | |
1339 | - auto acc = get_account(runtime); |
1340 | auto root = get_root(runtime); |
1341 | clear_folder(root); |
1342 | |
1343 | @@ -1076,7 +1059,6 @@ |
1344 | { |
1345 | auto runtime = Runtime::create(); |
1346 | |
1347 | - auto acc = get_account(runtime); |
1348 | auto root = get_root(runtime); |
1349 | clear_folder(root); |
1350 | |
1351 | @@ -1109,7 +1091,6 @@ |
1352 | { |
1353 | auto runtime = Runtime::create(); |
1354 | |
1355 | - auto acc = get_account(runtime); |
1356 | auto root = get_root(runtime); |
1357 | clear_folder(root); |
1358 | |
1359 | @@ -1261,7 +1242,6 @@ |
1360 | { |
1361 | auto runtime = Runtime::create(); |
1362 | |
1363 | - auto acc = get_account(runtime); |
1364 | auto root = get_root(runtime); |
1365 | clear_folder(root); |
1366 | |
1367 | @@ -1417,7 +1397,6 @@ |
1368 | { |
1369 | auto runtime = Runtime::create(); |
1370 | |
1371 | - auto acc = get_account(runtime); |
1372 | auto root = get_root(runtime); |
1373 | clear_folder(root); |
1374 | |
1375 | @@ -1428,7 +1407,7 @@ |
1376 | } |
1377 | catch (LogicException const& e) |
1378 | { |
1379 | - EXPECT_EQ("Root::delete_item(): Cannot delete root folder", e.error_message()); |
1380 | + EXPECT_EQ("Item::delete_item(): cannot delete root folder", e.error_message()); |
1381 | } |
1382 | |
1383 | try |
1384 | @@ -1545,7 +1524,6 @@ |
1385 | { |
1386 | auto runtime = Runtime::create(); |
1387 | |
1388 | - auto acc = get_account(runtime); |
1389 | auto root = get_root(runtime); |
1390 | clear_folder(root); |
1391 | |
1392 | @@ -1693,7 +1671,6 @@ |
1393 | { |
1394 | auto runtime = Runtime::create(); |
1395 | |
1396 | - auto acc = get_account(runtime); |
1397 | auto root = get_root(runtime); |
1398 | clear_folder(root); |
1399 | |
1400 | @@ -1705,7 +1682,7 @@ |
1401 | } |
1402 | catch (DeletedException const& e) |
1403 | { |
1404 | - EXPECT_TRUE(e.error_message().startsWith("Folder::name(): ")); |
1405 | + EXPECT_TRUE(e.error_message().startsWith("Item::name(): ")); |
1406 | } |
1407 | |
1408 | try |
1409 | @@ -1790,7 +1767,6 @@ |
1410 | { |
1411 | auto runtime = Runtime::create(); |
1412 | |
1413 | - auto acc = get_account(runtime); |
1414 | auto root = get_root(runtime); |
1415 | clear_folder(root); |
1416 | |
1417 | @@ -1861,7 +1837,7 @@ |
1418 | } |
1419 | catch (RuntimeDestroyedException const& e) |
1420 | { |
1421 | - EXPECT_EQ("Account::runtime(): Runtime was destroyed previously", e.error_message()); |
1422 | + EXPECT_EQ("Account::runtime(): runtime was destroyed previously", e.error_message()); |
1423 | } |
1424 | } |
1425 | |
1426 | @@ -1877,7 +1853,7 @@ |
1427 | } |
1428 | catch (RuntimeDestroyedException const& e) |
1429 | { |
1430 | - EXPECT_EQ("Account::runtime(): Runtime was destroyed previously", e.error_message()); |
1431 | + EXPECT_EQ("Account::runtime(): runtime was destroyed previously", e.error_message()); |
1432 | } |
1433 | } |
1434 | |
1435 | @@ -1887,19 +1863,18 @@ |
1436 | runtime->shutdown(); |
1437 | try |
1438 | { |
1439 | - runtime->accounts(); |
1440 | + call(runtime->accounts()); |
1441 | FAIL(); |
1442 | } |
1443 | catch (RuntimeDestroyedException const& e) |
1444 | { |
1445 | - EXPECT_EQ("Runtime::accounts(): Runtime was destroyed previously", e.error_message()); |
1446 | + EXPECT_EQ("Runtime::accounts(): runtime was destroyed previously", e.error_message()); |
1447 | } |
1448 | } |
1449 | |
1450 | // Getting the account from a root with a destroyed runtime must fail. |
1451 | { |
1452 | auto runtime = Runtime::create(); |
1453 | - auto acc = get_account(runtime); |
1454 | auto root = get_root(runtime); |
1455 | runtime.reset(); |
1456 | try |
1457 | @@ -1909,7 +1884,7 @@ |
1458 | } |
1459 | catch (RuntimeDestroyedException const& e) |
1460 | { |
1461 | - EXPECT_EQ("Root::account(): Runtime was destroyed previously", e.error_message()); |
1462 | + EXPECT_EQ("Root::account(): runtime was destroyed previously", e.error_message()); |
1463 | } |
1464 | } |
1465 | |
1466 | @@ -1927,14 +1902,13 @@ |
1467 | } |
1468 | catch (RuntimeDestroyedException const& e) |
1469 | { |
1470 | - EXPECT_EQ("Root::account(): Runtime was destroyed previously", e.error_message()); |
1471 | + EXPECT_EQ("Root::account(): runtime was destroyed previously", e.error_message()); |
1472 | } |
1473 | } |
1474 | |
1475 | // Getting the root from an item with a destroyed runtime must fail. |
1476 | { |
1477 | auto runtime = Runtime::create(); |
1478 | - auto acc = get_account(runtime); |
1479 | auto root = get_root(runtime); |
1480 | clear_folder(root); |
1481 | |
1482 | @@ -1947,20 +1921,18 @@ |
1483 | } |
1484 | catch (RuntimeDestroyedException const& e) |
1485 | { |
1486 | - EXPECT_EQ("Item::root(): Runtime was destroyed previously", e.error_message()); |
1487 | + EXPECT_EQ("Item::root(): runtime was destroyed previously", e.error_message()); |
1488 | } |
1489 | } |
1490 | |
1491 | // Getting the root from an item with a destroyed root must fail. |
1492 | { |
1493 | auto runtime = Runtime::create(); |
1494 | - auto acc = get_account(runtime); |
1495 | auto root = get_root(runtime); |
1496 | clear_folder(root); |
1497 | |
1498 | auto file = write_file(root, "file", ""); |
1499 | runtime.reset(); |
1500 | - acc.reset(); |
1501 | root.reset(); |
1502 | try |
1503 | { |
1504 | @@ -1969,14 +1941,13 @@ |
1505 | } |
1506 | catch (RuntimeDestroyedException const& e) |
1507 | { |
1508 | - EXPECT_EQ("Item::root(): Runtime was destroyed previously", e.error_message()); |
1509 | + EXPECT_EQ("Item::root(): runtime was destroyed previously", e.error_message()); |
1510 | } |
1511 | } |
1512 | |
1513 | // etag() with destroyed runtime must fail. |
1514 | { |
1515 | auto runtime = Runtime::create(); |
1516 | - auto acc = get_account(runtime); |
1517 | auto root = get_root(runtime); |
1518 | clear_folder(root); |
1519 | |
1520 | @@ -1989,14 +1960,13 @@ |
1521 | } |
1522 | catch (RuntimeDestroyedException const& e) |
1523 | { |
1524 | - EXPECT_EQ("Item::etag(): Runtime was destroyed previously", e.error_message()); |
1525 | + EXPECT_EQ("Item::etag(): runtime was destroyed previously", e.error_message()); |
1526 | } |
1527 | } |
1528 | |
1529 | // metadata() with destroyed runtime must fail. |
1530 | { |
1531 | auto runtime = Runtime::create(); |
1532 | - auto acc = get_account(runtime); |
1533 | auto root = get_root(runtime); |
1534 | clear_folder(root); |
1535 | |
1536 | @@ -2009,14 +1979,13 @@ |
1537 | } |
1538 | catch (RuntimeDestroyedException const& e) |
1539 | { |
1540 | - EXPECT_EQ("Item::metadata(): Runtime was destroyed previously", e.error_message()); |
1541 | + EXPECT_EQ("Item::metadata(): runtime was destroyed previously", e.error_message()); |
1542 | } |
1543 | } |
1544 | |
1545 | // last_modified_time() with destroyed runtime must fail. |
1546 | { |
1547 | auto runtime = Runtime::create(); |
1548 | - auto acc = get_account(runtime); |
1549 | auto root = get_root(runtime); |
1550 | clear_folder(root); |
1551 | |
1552 | @@ -2029,14 +1998,13 @@ |
1553 | } |
1554 | catch (RuntimeDestroyedException const& e) |
1555 | { |
1556 | - EXPECT_EQ("Item::last_modified_time(): Runtime was destroyed previously", e.error_message()); |
1557 | + EXPECT_EQ("Item::last_modified_time(): runtime was destroyed previously", e.error_message()); |
1558 | } |
1559 | } |
1560 | |
1561 | // copy() with destroyed runtime must fail. |
1562 | { |
1563 | auto runtime = Runtime::create(); |
1564 | - auto acc = get_account(runtime); |
1565 | auto root = get_root(runtime); |
1566 | clear_folder(root); |
1567 | |
1568 | @@ -2049,14 +2017,13 @@ |
1569 | } |
1570 | catch (RuntimeDestroyedException const& e) |
1571 | { |
1572 | - EXPECT_EQ("Item::copy(): Runtime was destroyed previously", e.error_message()); |
1573 | + EXPECT_EQ("Item::copy(): runtime was destroyed previously", e.error_message()); |
1574 | } |
1575 | } |
1576 | |
1577 | // move() with destroyed runtime must fail. |
1578 | { |
1579 | auto runtime = Runtime::create(); |
1580 | - auto acc = get_account(runtime); |
1581 | auto root = get_root(runtime); |
1582 | clear_folder(root); |
1583 | |
1584 | @@ -2069,18 +2036,16 @@ |
1585 | } |
1586 | catch (RuntimeDestroyedException const& e) |
1587 | { |
1588 | - EXPECT_EQ("Item::move(): Runtime was destroyed previously", e.error_message()); |
1589 | + EXPECT_EQ("Item::move(): runtime was destroyed previously", e.error_message()); |
1590 | } |
1591 | } |
1592 | |
1593 | // parents() on root with destroyed runtime must fail. |
1594 | { |
1595 | auto runtime = Runtime::create(); |
1596 | - auto acc = get_account(runtime); |
1597 | auto root = get_root(runtime); |
1598 | clear_folder(root); |
1599 | |
1600 | - auto file = write_file(root, "file", ""); |
1601 | runtime->shutdown(); |
1602 | try |
1603 | { |
1604 | @@ -2089,14 +2054,13 @@ |
1605 | } |
1606 | catch (RuntimeDestroyedException const& e) |
1607 | { |
1608 | - EXPECT_EQ("Root::parents(): Runtime was destroyed previously", e.error_message()); |
1609 | + EXPECT_EQ("Item::parents(): runtime was destroyed previously", e.error_message()); |
1610 | } |
1611 | } |
1612 | |
1613 | // parents() on file with destroyed runtime must fail. |
1614 | { |
1615 | auto runtime = Runtime::create(); |
1616 | - auto acc = get_account(runtime); |
1617 | auto root = get_root(runtime); |
1618 | clear_folder(root); |
1619 | |
1620 | @@ -2109,14 +2073,13 @@ |
1621 | } |
1622 | catch (RuntimeDestroyedException const& e) |
1623 | { |
1624 | - EXPECT_EQ("Item::parents(): Runtime was destroyed previously", e.error_message()); |
1625 | + EXPECT_EQ("Item::parents(): runtime was destroyed previously", e.error_message()); |
1626 | } |
1627 | } |
1628 | |
1629 | // parent_ids() with destroyed runtime must fail. |
1630 | { |
1631 | auto runtime = Runtime::create(); |
1632 | - auto acc = get_account(runtime); |
1633 | auto root = get_root(runtime); |
1634 | clear_folder(root); |
1635 | |
1636 | @@ -2129,14 +2092,13 @@ |
1637 | } |
1638 | catch (RuntimeDestroyedException const& e) |
1639 | { |
1640 | - EXPECT_EQ("Item::parent_ids(): Runtime was destroyed previously", e.error_message()); |
1641 | + EXPECT_EQ("Item::parent_ids(): runtime was destroyed previously", e.error_message()); |
1642 | } |
1643 | } |
1644 | |
1645 | // parent_ids() on root with destroyed runtime must fail. |
1646 | { |
1647 | auto runtime = Runtime::create(); |
1648 | - auto acc = get_account(runtime); |
1649 | auto root = get_root(runtime); |
1650 | clear_folder(root); |
1651 | |
1652 | @@ -2148,14 +2110,13 @@ |
1653 | } |
1654 | catch (RuntimeDestroyedException const& e) |
1655 | { |
1656 | - EXPECT_EQ("Root::parent_ids(): Runtime was destroyed previously", e.error_message()); |
1657 | + EXPECT_EQ("Item::parent_ids(): runtime was destroyed previously", e.error_message()); |
1658 | } |
1659 | } |
1660 | |
1661 | // delete_item() with destroyed runtime must fail. |
1662 | { |
1663 | auto runtime = Runtime::create(); |
1664 | - auto acc = get_account(runtime); |
1665 | auto root = get_root(runtime); |
1666 | clear_folder(root); |
1667 | |
1668 | @@ -2168,14 +2129,13 @@ |
1669 | } |
1670 | catch (RuntimeDestroyedException const& e) |
1671 | { |
1672 | - EXPECT_EQ("Item::delete_item(): Runtime was destroyed previously", e.error_message()); |
1673 | + EXPECT_EQ("Item::delete_item(): runtime was destroyed previously", e.error_message()); |
1674 | } |
1675 | } |
1676 | |
1677 | // delete_item() on root with destroyed runtime must fail. |
1678 | { |
1679 | auto runtime = Runtime::create(); |
1680 | - auto acc = get_account(runtime); |
1681 | auto root = get_root(runtime); |
1682 | clear_folder(root); |
1683 | |
1684 | @@ -2187,14 +2147,13 @@ |
1685 | } |
1686 | catch (RuntimeDestroyedException const& e) |
1687 | { |
1688 | - EXPECT_EQ("Root::delete_item(): Runtime was destroyed previously", e.error_message()); |
1689 | + EXPECT_EQ("Item::delete_item(): runtime was destroyed previously", e.error_message()); |
1690 | } |
1691 | } |
1692 | |
1693 | // creation_time() with destroyed runtime must fail. |
1694 | { |
1695 | auto runtime = Runtime::create(); |
1696 | - auto acc = get_account(runtime); |
1697 | auto root = get_root(runtime); |
1698 | clear_folder(root); |
1699 | |
1700 | @@ -2207,14 +2166,13 @@ |
1701 | } |
1702 | catch (RuntimeDestroyedException const& e) |
1703 | { |
1704 | - EXPECT_EQ("Item::creation_time(): Runtime was destroyed previously", e.error_message()); |
1705 | + EXPECT_EQ("Item::creation_time(): runtime was destroyed previously", e.error_message()); |
1706 | } |
1707 | } |
1708 | |
1709 | // native_metadata() with destroyed runtime must fail. |
1710 | { |
1711 | auto runtime = Runtime::create(); |
1712 | - auto acc = get_account(runtime); |
1713 | auto root = get_root(runtime); |
1714 | clear_folder(root); |
1715 | |
1716 | @@ -2227,14 +2185,13 @@ |
1717 | } |
1718 | catch (RuntimeDestroyedException const& e) |
1719 | { |
1720 | - EXPECT_EQ("Item::native_metadata(): Runtime was destroyed previously", e.error_message()); |
1721 | + EXPECT_EQ("Item::native_metadata(): runtime was destroyed previously", e.error_message()); |
1722 | } |
1723 | } |
1724 | |
1725 | // name() on root with destroyed runtime must fail. |
1726 | { |
1727 | auto runtime = Runtime::create(); |
1728 | - auto acc = get_account(runtime); |
1729 | auto root = get_root(runtime); |
1730 | clear_folder(root); |
1731 | |
1732 | @@ -2246,14 +2203,13 @@ |
1733 | } |
1734 | catch (RuntimeDestroyedException const& e) |
1735 | { |
1736 | - EXPECT_EQ("Root::name(): Runtime was destroyed previously", e.error_message()); |
1737 | + EXPECT_EQ("Item::name(): runtime was destroyed previously", e.error_message()); |
1738 | } |
1739 | } |
1740 | |
1741 | // name() on folder with destroyed runtime must fail. |
1742 | { |
1743 | auto runtime = Runtime::create(); |
1744 | - auto acc = get_account(runtime); |
1745 | auto root = get_root(runtime); |
1746 | clear_folder(root); |
1747 | |
1748 | @@ -2266,14 +2222,13 @@ |
1749 | } |
1750 | catch (RuntimeDestroyedException const& e) |
1751 | { |
1752 | - EXPECT_EQ("Folder::name(): Runtime was destroyed previously", e.error_message()); |
1753 | + EXPECT_EQ("Item::name(): runtime was destroyed previously", e.error_message()); |
1754 | } |
1755 | } |
1756 | |
1757 | // name() on file with destroyed runtime must fail. |
1758 | { |
1759 | auto runtime = Runtime::create(); |
1760 | - auto acc = get_account(runtime); |
1761 | auto root = get_root(runtime); |
1762 | clear_folder(root); |
1763 | |
1764 | @@ -2286,14 +2241,13 @@ |
1765 | } |
1766 | catch (RuntimeDestroyedException const& e) |
1767 | { |
1768 | - EXPECT_EQ("File::name(): Runtime was destroyed previously", e.error_message()); |
1769 | + EXPECT_EQ("File::name(): runtime was destroyed previously", e.error_message()); |
1770 | } |
1771 | } |
1772 | |
1773 | // list() with destroyed runtime must fail. |
1774 | { |
1775 | auto runtime = Runtime::create(); |
1776 | - auto acc = get_account(runtime); |
1777 | auto root = get_root(runtime); |
1778 | clear_folder(root); |
1779 | |
1780 | @@ -2305,14 +2259,13 @@ |
1781 | } |
1782 | catch (RuntimeDestroyedException const& e) |
1783 | { |
1784 | - EXPECT_EQ("Folder::list(): Runtime was destroyed previously", e.error_message()); |
1785 | + EXPECT_EQ("Folder::list(): runtime was destroyed previously", e.error_message()); |
1786 | } |
1787 | } |
1788 | |
1789 | // lookup() with destroyed runtime must fail. |
1790 | { |
1791 | auto runtime = Runtime::create(); |
1792 | - auto acc = get_account(runtime); |
1793 | auto root = get_root(runtime); |
1794 | clear_folder(root); |
1795 | |
1796 | @@ -2324,14 +2277,13 @@ |
1797 | } |
1798 | catch (RuntimeDestroyedException const& e) |
1799 | { |
1800 | - EXPECT_EQ("Folder::lookup(): Runtime was destroyed previously", e.error_message()); |
1801 | + EXPECT_EQ("Folder::lookup(): runtime was destroyed previously", e.error_message()); |
1802 | } |
1803 | } |
1804 | |
1805 | // create_folder() with destroyed runtime must fail. |
1806 | { |
1807 | auto runtime = Runtime::create(); |
1808 | - auto acc = get_account(runtime); |
1809 | auto root = get_root(runtime); |
1810 | clear_folder(root); |
1811 | |
1812 | @@ -2343,14 +2295,13 @@ |
1813 | } |
1814 | catch (RuntimeDestroyedException const& e) |
1815 | { |
1816 | - EXPECT_EQ("Folder::create_folder(): Runtime was destroyed previously", e.error_message()); |
1817 | + EXPECT_EQ("Folder::create_folder(): runtime was destroyed previously", e.error_message()); |
1818 | } |
1819 | } |
1820 | |
1821 | // create_file() with destroyed runtime must fail. |
1822 | { |
1823 | auto runtime = Runtime::create(); |
1824 | - auto acc = get_account(runtime); |
1825 | auto root = get_root(runtime); |
1826 | clear_folder(root); |
1827 | |
1828 | @@ -2362,14 +2313,13 @@ |
1829 | } |
1830 | catch (RuntimeDestroyedException const& e) |
1831 | { |
1832 | - EXPECT_EQ("Folder::create_file(): Runtime was destroyed previously", e.error_message()); |
1833 | + EXPECT_EQ("Folder::create_file(): runtime was destroyed previously", e.error_message()); |
1834 | } |
1835 | } |
1836 | |
1837 | // size() with destroyed runtime must fail. |
1838 | { |
1839 | auto runtime = Runtime::create(); |
1840 | - auto acc = get_account(runtime); |
1841 | auto root = get_root(runtime); |
1842 | clear_folder(root); |
1843 | |
1844 | @@ -2382,14 +2332,13 @@ |
1845 | } |
1846 | catch (RuntimeDestroyedException const& e) |
1847 | { |
1848 | - EXPECT_EQ("File::size(): Runtime was destroyed previously", e.error_message()); |
1849 | + EXPECT_EQ("File::size(): runtime was destroyed previously", e.error_message()); |
1850 | } |
1851 | } |
1852 | |
1853 | // create_uploader() with destroyed runtime must fail. |
1854 | { |
1855 | auto runtime = Runtime::create(); |
1856 | - auto acc = get_account(runtime); |
1857 | auto root = get_root(runtime); |
1858 | clear_folder(root); |
1859 | |
1860 | @@ -2402,14 +2351,13 @@ |
1861 | } |
1862 | catch (RuntimeDestroyedException const& e) |
1863 | { |
1864 | - EXPECT_EQ("File::create_uploader(): Runtime was destroyed previously", e.error_message()); |
1865 | + EXPECT_EQ("File::create_uploader(): runtime was destroyed previously", e.error_message()); |
1866 | } |
1867 | } |
1868 | |
1869 | // create_downloader() with destroyed runtime must fail. |
1870 | { |
1871 | auto runtime = Runtime::create(); |
1872 | - auto acc = get_account(runtime); |
1873 | auto root = get_root(runtime); |
1874 | clear_folder(root); |
1875 | |
1876 | @@ -2422,14 +2370,13 @@ |
1877 | } |
1878 | catch (RuntimeDestroyedException const& e) |
1879 | { |
1880 | - EXPECT_EQ("File::create_downloader(): Runtime was destroyed previously", e.error_message()); |
1881 | + EXPECT_EQ("File::create_downloader(): runtime was destroyed previously", e.error_message()); |
1882 | } |
1883 | } |
1884 | |
1885 | // free_space_bytes() with destroyed runtime must fail. |
1886 | { |
1887 | auto runtime = Runtime::create(); |
1888 | - auto acc = get_account(runtime); |
1889 | auto root = get_root(runtime); |
1890 | clear_folder(root); |
1891 | |
1892 | @@ -2441,14 +2388,13 @@ |
1893 | } |
1894 | catch (RuntimeDestroyedException const& e) |
1895 | { |
1896 | - EXPECT_EQ("Root::free_space_bytes(): Runtime was destroyed previously", e.error_message()); |
1897 | + EXPECT_EQ("Root::free_space_bytes(): runtime was destroyed previously", e.error_message()); |
1898 | } |
1899 | } |
1900 | |
1901 | // used_space_bytes() with destroyed runtime must fail. |
1902 | { |
1903 | auto runtime = Runtime::create(); |
1904 | - auto acc = get_account(runtime); |
1905 | auto root = get_root(runtime); |
1906 | clear_folder(root); |
1907 | |
1908 | @@ -2460,14 +2406,13 @@ |
1909 | } |
1910 | catch (RuntimeDestroyedException const& e) |
1911 | { |
1912 | - EXPECT_EQ("Root::used_space_bytes(): Runtime was destroyed previously", e.error_message()); |
1913 | + EXPECT_EQ("Root::used_space_bytes(): runtime was destroyed previously", e.error_message()); |
1914 | } |
1915 | } |
1916 | |
1917 | // get() with destroyed runtime must fail. |
1918 | { |
1919 | auto runtime = Runtime::create(); |
1920 | - auto acc = get_account(runtime); |
1921 | auto root = get_root(runtime); |
1922 | clear_folder(root); |
1923 | |
1924 | @@ -2479,7 +2424,7 @@ |
1925 | } |
1926 | catch (RuntimeDestroyedException const& e) |
1927 | { |
1928 | - EXPECT_EQ("Root::get(): Runtime was destroyed previously", e.error_message()); |
1929 | + EXPECT_EQ("Root::get(): runtime was destroyed previously", e.error_message()); |
1930 | } |
1931 | } |
1932 | } |
1933 | |
1934 | === modified file 'tests/provider-ProviderInterface/CMakeLists.txt' |
1935 | --- tests/provider-ProviderInterface/CMakeLists.txt 2016-08-05 10:53:57 +0000 |
1936 | +++ tests/provider-ProviderInterface/CMakeLists.txt 2016-08-11 02:49:47 +0000 |
1937 | @@ -18,11 +18,13 @@ |
1938 | ../../src/qt/client/internal/remote_client/dbusmarshal.cpp |
1939 | ${generated_files} |
1940 | ) |
1941 | +add_dependencies(provider-ProviderInterface_test storage-framework-provider) |
1942 | set_target_properties(provider-ProviderInterface_test PROPERTIES |
1943 | AUTOMOC TRUE |
1944 | ) |
1945 | target_link_libraries(provider-ProviderInterface_test |
1946 | storage-framework-provider-static |
1947 | + storage-framework-qt-client |
1948 | Qt5::Test |
1949 | testutils |
1950 | gtest |
1951 | |
1952 | === modified file 'tests/provider-ProviderInterface/ProviderInterface_test.cpp' |
1953 | --- tests/provider-ProviderInterface/ProviderInterface_test.cpp 2016-08-09 06:19:48 +0000 |
1954 | +++ tests/provider-ProviderInterface/ProviderInterface_test.cpp 2016-08-11 02:49:47 +0000 |
1955 | @@ -16,6 +16,7 @@ |
1956 | * Authors: James Henstridge <james.henstridge@canonical.com> |
1957 | */ |
1958 | |
1959 | +#include <unity/storage/internal/dbus_error.h> |
1960 | #include <unity/storage/provider/ProviderBase.h> |
1961 | #include <unity/storage/provider/internal/DBusPeerCache.h> |
1962 | #include <unity/storage/provider/internal/AccountData.h> |
1963 | @@ -54,7 +55,7 @@ |
1964 | const auto SERVICE_CONNECTION_NAME = QStringLiteral("service-session-bus"); |
1965 | const auto BUS_PATH = QStringLiteral("/provider"); |
1966 | const auto PROVIDER_IFACE = QStringLiteral("com.canonical.StorageFramework.Provider"); |
1967 | -const char PROVIDER_ERROR[] = "com.canonical.StorageFramework.Provider.Error"; |
1968 | +const QString PROVIDER_ERROR = unity::storage::internal::DBUS_ERROR_PREFIX; |
1969 | |
1970 | } |
1971 | |
1972 | @@ -165,13 +166,13 @@ |
1973 | reply = client_->List("root_id", "bad_page_token"); |
1974 | wait_for(reply); |
1975 | EXPECT_TRUE(reply.isError()); |
1976 | - EXPECT_EQ(PROVIDER_ERROR, reply.error().name()); |
1977 | - EXPECT_EQ("Unknown page token", reply.error().message()); |
1978 | + EXPECT_EQ(PROVIDER_ERROR + "UnknownException", reply.error().name()) << reply.error().name().toStdString(); |
1979 | + EXPECT_EQ("Unknown page token", reply.error().message()) << reply.error().message().toStdString(); |
1980 | |
1981 | reply = client_->List("no_such_folder_id", ""); |
1982 | wait_for(reply); |
1983 | EXPECT_TRUE(reply.isError()); |
1984 | - EXPECT_EQ(PROVIDER_ERROR, reply.error().name()); |
1985 | + EXPECT_EQ(PROVIDER_ERROR + "UnknownException", reply.error().name()); |
1986 | EXPECT_EQ("Unknown folder", reply.error().message()); |
1987 | } |
1988 | |
1989 | @@ -260,7 +261,7 @@ |
1990 | |
1991 | auto reply = client_->FinishUpload(upload_id); |
1992 | wait_for(reply); |
1993 | - ASSERT_TRUE(reply.isValid()); |
1994 | + ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString(); |
1995 | auto item = reply.value(); |
1996 | EXPECT_EQ("new_file_id", item.item_id); |
1997 | EXPECT_EQ("parent_id", item.parent_id); |
1998 | @@ -329,7 +330,7 @@ |
1999 | auto reply = client_->FinishUpload(upload_id); |
2000 | wait_for(reply); |
2001 | ASSERT_TRUE(reply.isError()); |
2002 | - EXPECT_EQ(PROVIDER_ERROR, reply.error().name()); |
2003 | + EXPECT_EQ(PROVIDER_ERROR + "UnknownException", reply.error().name()); |
2004 | EXPECT_EQ("wrong number of bytes written", reply.error().message()); |
2005 | } |
2006 | |
2007 | @@ -403,7 +404,7 @@ |
2008 | auto reply = client_->FinishUpload("no-such-upload"); |
2009 | wait_for(reply); |
2010 | ASSERT_TRUE(reply.isError()); |
2011 | - EXPECT_EQ(PROVIDER_ERROR, reply.error().name()); |
2012 | + EXPECT_EQ(PROVIDER_ERROR + "UnknownException", reply.error().name()); |
2013 | EXPECT_EQ("map::at", reply.error().message()); |
2014 | } |
2015 | |
2016 | @@ -466,7 +467,7 @@ |
2017 | auto reply = client_->FinishDownload(download_id); |
2018 | wait_for(reply); |
2019 | ASSERT_TRUE(reply.isError()); |
2020 | - EXPECT_EQ(PROVIDER_ERROR, reply.error().name()); |
2021 | + EXPECT_EQ(PROVIDER_ERROR + "UnknownException", reply.error().name()); |
2022 | EXPECT_EQ("Not all data read", reply.error().message()); |
2023 | } |
2024 | |
2025 | @@ -477,7 +478,7 @@ |
2026 | auto reply = client_->FinishDownload("no-such-download"); |
2027 | wait_for(reply); |
2028 | ASSERT_TRUE(reply.isError()); |
2029 | - EXPECT_EQ(PROVIDER_ERROR, reply.error().name()); |
2030 | + EXPECT_EQ(PROVIDER_ERROR + "UnknownException", reply.error().name()); |
2031 | EXPECT_EQ("map::at", reply.error().message()); |
2032 | } |
2033 | |
2034 | |
2035 | === modified file 'tests/provider-ProviderInterface/TestProvider.cpp' |
2036 | --- tests/provider-ProviderInterface/TestProvider.cpp 2016-08-09 06:47:45 +0000 |
2037 | +++ tests/provider-ProviderInterface/TestProvider.cpp 2016-08-11 02:49:47 +0000 |
2038 | @@ -18,6 +18,7 @@ |
2039 | |
2040 | #include "TestProvider.h" |
2041 | #include <unity/storage/provider/DownloadJob.h> |
2042 | +#include <unity/storage/provider/Exceptions.h> |
2043 | #include <unity/storage/provider/UploadJob.h> |
2044 | |
2045 | #include <QSocketNotifier> |
2046 | |
2047 | === modified file 'tests/remote-client/remote-client_test.cpp' |
2048 | --- tests/remote-client/remote-client_test.cpp 2016-08-03 03:20:39 +0000 |
2049 | +++ tests/remote-client/remote-client_test.cpp 2016-08-11 02:49:47 +0000 |
2050 | @@ -40,8 +40,6 @@ |
2051 | |
2052 | static constexpr int SIGNAL_WAIT_TIME = 1000; |
2053 | |
2054 | -// Bunch of helper function to reduce the amount of noise in the tests. |
2055 | - |
2056 | class RemoteClientTest : public ::testing::Test |
2057 | { |
2058 | public: |
2059 | @@ -73,6 +71,40 @@ |
2060 | class FileTest : public RemoteClientTest {}; |
2061 | class ItemTest : public RemoteClientTest {}; |
2062 | |
2063 | +// Bunch of helper functions to reduce the amount of noise in the tests. |
2064 | + |
2065 | +template<typename T> |
2066 | +void wait(T fut) |
2067 | +{ |
2068 | + QFutureWatcher<decltype(fut.result())> w; |
2069 | + QSignalSpy spy(&w, &decltype(w)::finished); |
2070 | + w.setFuture(fut); |
2071 | + ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2072 | +} |
2073 | + |
2074 | +template<> |
2075 | +void wait(QFuture<void> fut) |
2076 | +{ |
2077 | + QFutureWatcher<void> w; |
2078 | + QSignalSpy spy(&w, &decltype(w)::finished); |
2079 | + w.setFuture(fut); |
2080 | + ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2081 | +} |
2082 | + |
2083 | +template <typename T> |
2084 | +T call(QFuture<T> fut) |
2085 | +{ |
2086 | + wait(fut); |
2087 | + return fut.result(); |
2088 | +} |
2089 | + |
2090 | +template <> |
2091 | +void call(QFuture<void> fut) |
2092 | +{ |
2093 | + wait(fut); |
2094 | + fut.waitForFinished(); |
2095 | +} |
2096 | + |
2097 | Account::SPtr get_account(Runtime::SPtr const& runtime) |
2098 | { |
2099 | auto accounts_fut = runtime->accounts(); |
2100 | @@ -142,25 +174,6 @@ |
2101 | } |
2102 | } |
2103 | |
2104 | -bool content_matches(File::SPtr const& file, QByteArray const& expected) |
2105 | -{ |
2106 | - QFile f(file->native_identity()); |
2107 | - assert(f.open(QIODevice::ReadOnly)); |
2108 | - QByteArray buf = f.readAll(); |
2109 | - return buf == expected; |
2110 | -} |
2111 | - |
2112 | -void write_file(Folder::SPtr const& folder, QString const& name, QByteArray const& contents) |
2113 | -{ |
2114 | - QString ofile = folder->native_identity() + "/" + name; |
2115 | - QFile f(ofile); |
2116 | - assert(f.open(QIODevice::Truncate | QIODevice::WriteOnly)); |
2117 | - if (!contents.isEmpty()) |
2118 | - { |
2119 | - assert(f.write(contents)); |
2120 | - } |
2121 | -} |
2122 | - |
2123 | TEST_F(RuntimeTest, lifecycle) |
2124 | { |
2125 | auto runtime = Runtime::create(connection()); |
2126 | @@ -174,9 +187,9 @@ |
2127 | |
2128 | auto acc = get_account(runtime); |
2129 | EXPECT_EQ(runtime, acc->runtime()); |
2130 | - qDebug() << "owner: " << acc->owner(); |
2131 | - qDebug() << "owner ID: " << acc->owner_id(); |
2132 | - qDebug() << "description:" << acc->description(); |
2133 | + EXPECT_EQ("", acc->owner()); |
2134 | + EXPECT_EQ("google-drive-scope", acc->owner_id()) << acc->owner_id().toStdString(); |
2135 | + EXPECT_EQ("Fake google account", acc->description()) << acc->description().toStdString(); |
2136 | } |
2137 | |
2138 | TEST_F(RuntimeTest, roots) |
2139 | @@ -253,7 +266,6 @@ |
2140 | { |
2141 | auto runtime = Runtime::create(connection()); |
2142 | |
2143 | - auto acc = get_account(runtime); |
2144 | auto root = get_root(runtime); |
2145 | clear_folder(root); |
2146 | |
2147 | @@ -301,105 +313,12 @@ |
2148 | file = dynamic_pointer_cast<File>(get_fut.result()); |
2149 | EXPECT_EQ("child_id", file->native_identity()); |
2150 | EXPECT_EQ("Child", file->name()); |
2151 | - |
2152 | -#if 0 |
2153 | - // Create a folder and check that it was created with correct type and name. |
2154 | - auto create_folder_fut = root->create_folder("folder1"); |
2155 | - { |
2156 | - QFutureWatcher<Folder::SPtr> w; |
2157 | - QSignalSpy spy(&w, &decltype(w)::finished); |
2158 | - w.setFuture(create_folder_fut); |
2159 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2160 | - } |
2161 | - EXPECT_EQ(ItemType::folder, folder->type()); |
2162 | - EXPECT_EQ("folder1", folder->name()); |
2163 | - EXPECT_EQ(root->native_identity() + "/folder1", folder->native_identity()); |
2164 | - |
2165 | - // Check that we can find both file1 and folder1. |
2166 | - auto item = root->lookup("file1").result(); |
2167 | - file = dynamic_pointer_cast<File>(item); |
2168 | - ASSERT_NE(nullptr, file); |
2169 | - EXPECT_EQ("file1", file->name()); |
2170 | - EXPECT_EQ(0, file->size()); |
2171 | - |
2172 | - item = root->lookup("folder1").result(); |
2173 | - folder = dynamic_pointer_cast<Folder>(item); |
2174 | - ASSERT_NE(nullptr, folder); |
2175 | - ASSERT_EQ(nullptr, dynamic_pointer_cast<Root>(folder)); |
2176 | - EXPECT_EQ("folder1", folder->name()); |
2177 | - |
2178 | - // Check that list() returns file1 and folder1. |
2179 | - items = root->list(); |
2180 | - ASSERT_EQ(2, items.size()); |
2181 | - auto left = items[0]; |
2182 | - auto right = items[1]; |
2183 | - ASSERT_TRUE((dynamic_pointer_cast<File>(left) && dynamic_pointer_cast<Folder>(right)) |
2184 | - || |
2185 | - (dynamic_pointer_cast<File>(right) && dynamic_pointer_cast<Folder>(left))); |
2186 | - if (dynamic_pointer_cast<File>(left)) |
2187 | - { |
2188 | - file = dynamic_pointer_cast<File>(left); |
2189 | - folder = dynamic_pointer_cast<Folder>(right); |
2190 | - } |
2191 | - else |
2192 | - { |
2193 | - file = dynamic_pointer_cast<File>(right); |
2194 | - folder = dynamic_pointer_cast<Folder>(left); |
2195 | - } |
2196 | - EXPECT_EQ("file1", file->name()); |
2197 | - EXPECT_EQ("folder1", folder->name()); |
2198 | - EXPECT_TRUE(file->root()->equal_to(root)); |
2199 | - EXPECT_TRUE(folder->root()->equal_to(root)); |
2200 | - |
2201 | - // Parent of both file and folder must be the root. |
2202 | - EXPECT_TRUE(root->equal_to(get_parent(file))); |
2203 | - EXPECT_TRUE(root->equal_to(get_parent(folder))); |
2204 | - EXPECT_EQ(root->native_identity(), file->parent_ids()[0]); |
2205 | - EXPECT_EQ(root->native_identity(), folder->parent_ids()[0]); |
2206 | - |
2207 | - // Destroy the file and check that only the directory is left. |
2208 | - file->delete_item().waitForFinished(); |
2209 | - items = root->list().result(); |
2210 | - ASSERT_EQ(1, items.size()); |
2211 | - folder = dynamic_pointer_cast<Folder>(items[0]); |
2212 | - ASSERT_NE(nullptr, folder); |
2213 | - EXPECT_EQ("folder1", folder->name());; |
2214 | - |
2215 | - // Destroy the folder and check that the root is empty. |
2216 | - folder->delete_item().waitForFinished(); |
2217 | - items = root->list().result(); |
2218 | - ASSERT_EQ(0, items.size()); |
2219 | -#endif |
2220 | -} |
2221 | - |
2222 | -#if 0 |
2223 | -TEST_F(FolderTest, nested) |
2224 | -{ |
2225 | - auto runtime = Runtime::create(connection()); |
2226 | - |
2227 | - auto acc = get_account(runtime); |
2228 | - auto root = get_root(runtime); |
2229 | - clear_folder(root); |
2230 | - |
2231 | - auto d1 = root->create_folder("d1").result(); |
2232 | - auto d2 = d1->create_folder("d2").result(); |
2233 | - |
2234 | - // Parent of d2 must be d1. |
2235 | - EXPECT_TRUE(get_parent(d2)->equal_to(d1)); |
2236 | - EXPECT_TRUE(d2->parent_ids()[0] == d1->native_identity()); |
2237 | - |
2238 | - // Destroy is recursive |
2239 | - d1->delete_item().waitForFinished(); |
2240 | - auto items = root->list().result(); |
2241 | - ASSERT_EQ(0, items.size()); |
2242 | -} |
2243 | -#endif |
2244 | +} |
2245 | |
2246 | TEST_F(FileTest, upload) |
2247 | { |
2248 | auto runtime = Runtime::create(connection()); |
2249 | |
2250 | - auto acc = get_account(runtime); |
2251 | auto root = get_root(runtime); |
2252 | clear_folder(root); |
2253 | |
2254 | @@ -437,613 +356,645 @@ |
2255 | auto uploaded_file = finish_upload_fut.result(); |
2256 | EXPECT_EQ("some_id", uploaded_file->native_identity()); |
2257 | EXPECT_EQ("some_upload", uploaded_file->name()); |
2258 | - |
2259 | -#if 0 |
2260 | - QByteArray const contents = "Hello\n"; |
2261 | - auto written = uploader->socket()->write(contents); |
2262 | - ASSERT_EQ(contents.size(), written); |
2263 | - |
2264 | - auto finish_upload_fut = uploader->finish_upload(); |
2265 | - { |
2266 | - QFutureWatcher<File::SPtr> w; |
2267 | - QSignalSpy spy(&w, &decltype(w)::finished); |
2268 | - w.setFuture(finish_upload_fut); |
2269 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2270 | - } |
2271 | - auto file = finish_upload_fut.result(); |
2272 | - } |
2273 | - |
2274 | - { |
2275 | - // Don't upload anything. |
2276 | - auto uploader = root->create_file("new_file").result(); |
2277 | - auto file = uploader->file(); |
2278 | - uploader->socket()->disconnectFromServer(); |
2279 | - |
2280 | - // We never write anything, so there is no disconnected signal from the socket. |
2281 | - |
2282 | - auto state = uploader->finish_upload().result(); |
2283 | - EXPECT_EQ(TransferState::ok, state); |
2284 | - ASSERT_EQ(0, uploader->file()->size()); |
2285 | - |
2286 | - file->delete_item().waitForFinished(); |
2287 | - } |
2288 | - |
2289 | - { |
2290 | - // Let the uploader go out of scope and check |
2291 | - // that the file was created regardless. |
2292 | - auto file = root->create_file("new_file").result()->file(); |
2293 | - ASSERT_EQ(0, file->size()); |
2294 | - |
2295 | - file->delete_item().waitForFinished(); |
2296 | - } |
2297 | -#endif |
2298 | -} |
2299 | -#if 0 |
2300 | - |
2301 | -TEST_F(FileTest, create_uploader) |
2302 | -{ |
2303 | - auto runtime = Runtime::create(connection()); |
2304 | - |
2305 | - auto acc = get_account(runtime); |
2306 | - auto root = get_root(runtime); |
2307 | - clear_folder(root); |
2308 | - |
2309 | - auto file = root->create_file("new_file").result()->file(); |
2310 | - |
2311 | - { |
2312 | - auto uploader = file->create_uploader(ConflictPolicy::overwrite).result(); |
2313 | - |
2314 | - auto finish_fut = uploader->finish_upload(); |
2315 | - { |
2316 | - QFutureWatcher<TransferState> w; |
2317 | - QSignalSpy spy(&w, &decltype(w)::finished); |
2318 | - w.setFuture(finish_fut); |
2319 | - // We never disconnected from the socket, so the transfer is still in progress. |
2320 | - ASSERT_FALSE(spy.wait(SIGNAL_WAIT_TIME)); |
2321 | - } |
2322 | - uploader->socket()->disconnectFromServer(); |
2323 | - { |
2324 | - QFutureWatcher<TransferState> w; |
2325 | - QSignalSpy spy(&w, &decltype(w)::finished); |
2326 | - w.setFuture(finish_fut); |
2327 | - // Now that we have disconnected, the future must become ready. |
2328 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2329 | - } |
2330 | - EXPECT_EQ(TransferState::ok, finish_fut.result()); |
2331 | - } |
2332 | - |
2333 | - // Same test again, but this time we write a bunch of data and don't disconnect. |
2334 | - { |
2335 | - auto uploader = file->create_uploader(ConflictPolicy::overwrite).result(); |
2336 | - |
2337 | - std::string s(1000000, 'a'); |
2338 | - uploader->socket()->write(&s[0], s.size()); |
2339 | - |
2340 | - auto finish_fut = uploader->finish_upload(); |
2341 | - { |
2342 | - QFutureWatcher<TransferState> w; |
2343 | - QSignalSpy spy(&w, &decltype(w)::finished); |
2344 | - w.setFuture(finish_fut); |
2345 | - // We never disconnected from the socket, so the transfer is still in progress. |
2346 | - ASSERT_FALSE(spy.wait(SIGNAL_WAIT_TIME)); |
2347 | - } |
2348 | - uploader->socket()->disconnectFromServer(); |
2349 | - { |
2350 | - QFutureWatcher<TransferState> w; |
2351 | - QSignalSpy spy(&w, &decltype(w)::finished); |
2352 | - w.setFuture(finish_fut); |
2353 | - // Now that we have disconnected, the future must become ready. |
2354 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2355 | - } |
2356 | - EXPECT_EQ(TransferState::ok, finish_fut.result()); |
2357 | - } |
2358 | - |
2359 | - file->delete_item().waitForFinished(); |
2360 | -} |
2361 | - |
2362 | -TEST_F(FileTest, cancel_upload) |
2363 | -{ |
2364 | - auto runtime = Runtime::create(connection()); |
2365 | - |
2366 | - auto acc = get_account(runtime); |
2367 | - auto root = get_root(runtime); |
2368 | - clear_folder(root); |
2369 | - |
2370 | - { |
2371 | - // Upload a few bytes. |
2372 | - auto uploader = root->create_file("new_file").result(); |
2373 | - |
2374 | - // We haven't written anything and haven't pumped the event loop, |
2375 | - // so the cancel is guaranteed to catch the uploader in the in_progress state. |
2376 | - uploader->cancel(); |
2377 | - EXPECT_EQ(TransferState::cancelled, uploader->finish_upload().result()); |
2378 | - |
2379 | - auto file = uploader->file(); |
2380 | - EXPECT_EQ(0, file->size()); |
2381 | - |
2382 | - file->delete_item().waitForFinished(); |
2383 | - } |
2384 | - |
2385 | - { |
2386 | - // Create a file with a few bytes. |
2387 | - QByteArray original_contents = "Hello World!\n"; |
2388 | - write_file(root, "new_file", original_contents); |
2389 | - auto file = dynamic_pointer_cast<File>(root->lookup("new_file").result()); |
2390 | - ASSERT_NE(nullptr, file); |
2391 | - |
2392 | - // Create an uploader for the file and write a bunch of bytes. |
2393 | - auto uploader = file->create_uploader(ConflictPolicy::overwrite).result(); |
2394 | - QByteArray const contents(1024, 'a'); |
2395 | - auto written = uploader->socket()->write(contents); |
2396 | - ASSERT_EQ(contents.size(), written); |
2397 | - |
2398 | - QSignalSpy spy(uploader->socket().get(), &QLocalSocket::bytesWritten); |
2399 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2400 | - |
2401 | - // No disconnect here, so the transfer is still in progress. Now cancel. |
2402 | - uploader->cancel().waitForFinished(); |
2403 | - |
2404 | - // finish_upload() must indicate that the upload was cancelled. |
2405 | - auto state = uploader->finish_upload().result(); |
2406 | - EXPECT_EQ(TransferState::cancelled, state); |
2407 | - |
2408 | - // The original file contents must still be intact. |
2409 | - EXPECT_EQ(original_contents.size(), uploader->file()->size()); |
2410 | - ASSERT_TRUE(content_matches(uploader->file(), original_contents)); |
2411 | - |
2412 | - file->delete_item().waitForFinished(); |
2413 | - } |
2414 | - |
2415 | - { |
2416 | - // Upload a few bytes. |
2417 | - auto uploader = root->create_file("new_file").result(); |
2418 | - auto file = uploader->file(); |
2419 | - QByteArray const contents = "Hello\n"; |
2420 | - |
2421 | - // Finish the upload. |
2422 | - auto written = uploader->socket()->write(contents); |
2423 | - ASSERT_EQ(contents.size(), written); |
2424 | - uploader->socket()->disconnectFromServer(); |
2425 | - |
2426 | - // Pump the event loop for a bit, so the socket can finish doing its thing. |
2427 | - QTimer timer; |
2428 | - QSignalSpy spy(&timer, &QTimer::timeout); |
2429 | - timer.start(SIGNAL_WAIT_TIME); |
2430 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2431 | - |
2432 | - // Now send the cancel. The upload is finished already, and the cancel |
2433 | - // is too late, so finish_upload() must report that the upload |
2434 | - // worked OK. |
2435 | - uploader->cancel(); |
2436 | - EXPECT_EQ(TransferState::ok, uploader->finish_upload().result()); |
2437 | - |
2438 | - file->delete_item().waitForFinished(); |
2439 | - } |
2440 | -} |
2441 | - |
2442 | -TEST_F(FileTest, upload_conflict) |
2443 | -{ |
2444 | - auto runtime = Runtime::create(connection()); |
2445 | - |
2446 | - auto acc = get_account(runtime); |
2447 | - auto root = get_root(runtime); |
2448 | - clear_folder(root); |
2449 | - |
2450 | - // Make a new file. |
2451 | - auto uploader = root->create_file("new_file").result(); |
2452 | - auto file = uploader->file(); |
2453 | - |
2454 | - // Write a few bytes. |
2455 | - QByteArray const contents = "Hello\n"; |
2456 | - |
2457 | - // Pump the event loop for a bit, so the socket can finish doing its thing. |
2458 | - QTimer timer; |
2459 | - QSignalSpy spy(&timer, &QTimer::timeout); |
2460 | - timer.start(SIGNAL_WAIT_TIME); |
2461 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2462 | - |
2463 | - // Touch the file on disk to give it a new time stamp. |
2464 | - ASSERT_EQ(0, system((string("touch ") + file->native_identity().toStdString()).c_str())); |
2465 | - |
2466 | - // Finish the upload. |
2467 | - uploader->socket()->disconnectFromServer(); |
2468 | +} |
2469 | + |
2470 | +TEST_F(RootTest, root_exceptions) |
2471 | +{ |
2472 | + auto runtime = Runtime::create(connection()); |
2473 | + |
2474 | + auto root = get_root(runtime); |
2475 | + clear_folder(root); |
2476 | |
2477 | try |
2478 | { |
2479 | - // Must get an exception because the time stamps no longer match. |
2480 | - uploader->finish_upload().result(); |
2481 | + call(root->delete_item()); |
2482 | FAIL(); |
2483 | } |
2484 | - catch (ConflictException const&) |
2485 | - { |
2486 | - // TODO: check exception details. |
2487 | - } |
2488 | - |
2489 | - file->delete_item().waitForFinished(); |
2490 | -} |
2491 | - |
2492 | -TEST_F(FileTest, download) |
2493 | -{ |
2494 | - auto runtime = Runtime::create(connection()); |
2495 | - |
2496 | - auto acc = get_account(runtime); |
2497 | - auto root = get_root(runtime); |
2498 | - clear_folder(root); |
2499 | - |
2500 | - { |
2501 | - // Download a few bytes. |
2502 | - QByteArray const contents = "Hello\n"; |
2503 | - write_file(root, "file", contents); |
2504 | - |
2505 | - auto item = root->lookup("file").result(); |
2506 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2507 | - ASSERT_FALSE(file == nullptr); |
2508 | - |
2509 | - auto downloader = file->create_downloader().result(); |
2510 | - EXPECT_TRUE(file->equal_to(downloader->file())); |
2511 | - |
2512 | - auto socket = downloader->socket(); |
2513 | - QByteArray buf; |
2514 | - do |
2515 | - { |
2516 | - // Need to pump the event loop while the socket does its thing. |
2517 | - QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); |
2518 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2519 | - auto bytes_to_read = socket->bytesAvailable(); |
2520 | - buf.append(socket->read(bytes_to_read)); |
2521 | - } while (buf.size() < contents.size()); |
2522 | - |
2523 | - // Wait for disconnected signal. |
2524 | - QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); |
2525 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2526 | - |
2527 | - auto state = downloader->finish_download().result(); |
2528 | - EXPECT_EQ(TransferState::ok, state); |
2529 | - |
2530 | - // Contents must match. |
2531 | - EXPECT_EQ(contents, buf); |
2532 | - } |
2533 | - |
2534 | - { |
2535 | - // Download exactly 64 KB. |
2536 | - QByteArray const contents(64 * 1024, 'a'); |
2537 | - write_file(root, "file", contents); |
2538 | - |
2539 | - auto item = root->lookup("file").result(); |
2540 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2541 | - ASSERT_FALSE(file == nullptr); |
2542 | - |
2543 | - auto downloader = file->create_downloader().result(); |
2544 | - EXPECT_TRUE(file->equal_to(downloader->file())); |
2545 | - |
2546 | - auto socket = downloader->socket(); |
2547 | - QByteArray buf; |
2548 | - do |
2549 | - { |
2550 | - // Need to pump the event loop while the socket does its thing. |
2551 | - QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); |
2552 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2553 | - auto bytes_to_read = socket->bytesAvailable(); |
2554 | - buf.append(socket->read(bytes_to_read)); |
2555 | - } while (buf.size() < contents.size()); |
2556 | - |
2557 | - // Wait for disconnected signal. |
2558 | - QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); |
2559 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2560 | - |
2561 | - auto state = downloader->finish_download().result(); |
2562 | - EXPECT_EQ(TransferState::ok, state); |
2563 | - |
2564 | - // Contents must match |
2565 | - EXPECT_EQ(contents, buf); |
2566 | - } |
2567 | - |
2568 | - { |
2569 | - // Download 1 MB + 1 bytes. |
2570 | - QByteArray const contents(1024 * 1024 + 1, 'a'); |
2571 | - write_file(root, "file", contents); |
2572 | - |
2573 | - auto item = root->lookup("file").result(); |
2574 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2575 | - ASSERT_FALSE(file == nullptr); |
2576 | - |
2577 | - auto downloader = file->create_downloader().result(); |
2578 | - EXPECT_TRUE(file->equal_to(downloader->file())); |
2579 | - |
2580 | - auto socket = downloader->socket(); |
2581 | - QByteArray buf; |
2582 | - do |
2583 | - { |
2584 | - // Need to pump the event loop while the socket does its thing. |
2585 | - QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); |
2586 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2587 | - auto bytes_to_read = socket->bytesAvailable(); |
2588 | - buf.append(socket->read(bytes_to_read)); |
2589 | - } while (buf.size() < contents.size()); |
2590 | - |
2591 | - // Wait for disconnected signal. |
2592 | - QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); |
2593 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2594 | - |
2595 | - auto state = downloader->finish_download().result(); |
2596 | - EXPECT_EQ(TransferState::ok, state); |
2597 | - |
2598 | - // Contents must match |
2599 | - EXPECT_EQ(contents, buf); |
2600 | - } |
2601 | - |
2602 | - { |
2603 | - // Download file containing zero bytes |
2604 | - QByteArray const contents; |
2605 | - write_file(root, "file", contents); |
2606 | - |
2607 | - auto item = root->lookup("file").result(); |
2608 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2609 | - ASSERT_FALSE(file == nullptr); |
2610 | - |
2611 | - auto downloader = file->create_downloader().result(); |
2612 | - EXPECT_TRUE(file->equal_to(downloader->file())); |
2613 | - |
2614 | - auto socket = downloader->socket(); |
2615 | - |
2616 | - // No readyRead every arrives in this case, just wait for disconnected. |
2617 | - QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); |
2618 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2619 | - |
2620 | - auto state = downloader->finish_download().result(); |
2621 | - EXPECT_EQ(TransferState::ok, state); |
2622 | - } |
2623 | - |
2624 | - { |
2625 | - // Don't ever call read on empty file. |
2626 | - QByteArray const contents; |
2627 | - write_file(root, "file", contents); |
2628 | - |
2629 | - auto item = root->lookup("file").result(); |
2630 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2631 | - ASSERT_FALSE(file == nullptr); |
2632 | - |
2633 | - auto downloader = file->create_downloader().result(); |
2634 | - EXPECT_TRUE(file->equal_to(downloader->file())); |
2635 | - |
2636 | - // This succeeds because the provider disconnects as soon |
2637 | - // as it realizes that there is nothing to write. |
2638 | - downloader->finish_download().result(); |
2639 | - } |
2640 | - |
2641 | - { |
2642 | - // Don't ever call read on non-empty file. |
2643 | - QByteArray const contents("some contents"); |
2644 | - write_file(root, "file", contents); |
2645 | - |
2646 | - auto item = root->lookup("file").result(); |
2647 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2648 | - ASSERT_FALSE(file == nullptr); |
2649 | - |
2650 | - auto downloader = file->create_downloader().result(); |
2651 | - EXPECT_TRUE(file->equal_to(downloader->file())); |
2652 | - |
2653 | - try |
2654 | - { |
2655 | - downloader->finish_download().result(); |
2656 | - FAIL(); |
2657 | - } |
2658 | - catch (StorageException const&) |
2659 | - { |
2660 | - // TODO: check exception details |
2661 | - } |
2662 | - } |
2663 | - |
2664 | - { |
2665 | - // Let downloader go out of scope. |
2666 | - QByteArray const contents("some contents"); |
2667 | - write_file(root, "file", contents); |
2668 | - |
2669 | - auto item = root->lookup("file").result(); |
2670 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2671 | - ASSERT_FALSE(file == nullptr); |
2672 | - |
2673 | - auto downloader = file->create_downloader().result(); |
2674 | - } |
2675 | - |
2676 | - { |
2677 | - // Let downloader future go out of scope. |
2678 | - QByteArray const contents("some contents"); |
2679 | - write_file(root, "file", contents); |
2680 | - |
2681 | - auto item = root->lookup("file").result(); |
2682 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2683 | - ASSERT_FALSE(file == nullptr); |
2684 | - |
2685 | - auto downloader_fut = file->create_downloader(); |
2686 | - } |
2687 | -} |
2688 | - |
2689 | -TEST_F(FileTest, cancel_download) |
2690 | -{ |
2691 | - auto runtime = Runtime::create(connection()); |
2692 | - |
2693 | - auto acc = get_account(runtime); |
2694 | - auto root = get_root(runtime); |
2695 | - clear_folder(root); |
2696 | - |
2697 | - { |
2698 | - // Download enough bytes to prevent a single read in the provider from completing the download. |
2699 | - QByteArray const contents(1024 * 1024, 'a'); |
2700 | - write_file(root, "file", contents); |
2701 | - |
2702 | - auto item = root->lookup("file").result(); |
2703 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2704 | - ASSERT_FALSE(file == nullptr); |
2705 | - |
2706 | - auto downloader = file->create_downloader().result(); |
2707 | - // We haven't read anything and haven't pumped the event loop, |
2708 | - // so the cancel is guaranteed to catch the downloader in the in_progress state. |
2709 | - downloader->cancel(); |
2710 | - EXPECT_EQ(TransferState::cancelled, downloader->finish_download().result()); |
2711 | - } |
2712 | - |
2713 | - { |
2714 | - // Download a few bytes. |
2715 | - QByteArray const contents = "Hello\n"; |
2716 | - write_file(root, "file", contents); |
2717 | - |
2718 | - auto item = root->lookup("file").result(); |
2719 | - File::SPtr file = dynamic_pointer_cast<File>(item); |
2720 | - ASSERT_FALSE(file == nullptr); |
2721 | - |
2722 | - // Finish the download. |
2723 | - auto downloader = file->create_downloader().result(); |
2724 | - auto socket = downloader->socket(); |
2725 | - QByteArray buf; |
2726 | - do |
2727 | - { |
2728 | - // Need to pump the event loop while the socket does its thing. |
2729 | - QSignalSpy spy(downloader->socket().get(), &QIODevice::readyRead); |
2730 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2731 | - auto bytes_to_read = socket->bytesAvailable(); |
2732 | - buf.append(socket->read(bytes_to_read)); |
2733 | - } while (buf.size() < contents.size()); |
2734 | - |
2735 | - // Wait for disconnected signal. |
2736 | - QSignalSpy spy(downloader->socket().get(), &QLocalSocket::disconnected); |
2737 | - ASSERT_TRUE(spy.wait(SIGNAL_WAIT_TIME)); |
2738 | - |
2739 | - // Now send the cancel. The download is finished already, and the cancel |
2740 | - // is too late, so finish_download() must report that the download |
2741 | - // worked OK. |
2742 | - downloader->cancel(); |
2743 | - EXPECT_EQ(TransferState::ok, downloader->finish_download().result()); |
2744 | - } |
2745 | -} |
2746 | - |
2747 | -Test_F(ItemTest, move) |
2748 | -{ |
2749 | - auto runtime = Runtime::create(connection()); |
2750 | - |
2751 | - auto acc = get_account(runtime); |
2752 | - auto root = get_root(runtime); |
2753 | - clear_folder(root); |
2754 | - |
2755 | - // Check that rename works within the same folder. |
2756 | - auto f1 = root->create_file("f1").result()->file(); |
2757 | - auto f2 = f1->move(root, "f2").result(); |
2758 | - EXPECT_EQ("f2", f2->name()); |
2759 | - EXPECT_THROW(f1->name(), DestroyedException); // TODO: check exception details. |
2760 | - |
2761 | - // File must be found under new name. |
2762 | - auto items = root->list().result(); |
2763 | - ASSERT_EQ(1, items.size()); |
2764 | - f2 = dynamic_pointer_cast<File>(items[0]); |
2765 | - ASSERT_FALSE(f2 == nullptr); |
2766 | - |
2767 | - // Make a folder and move f2 into it. |
2768 | - auto folder = root->create_folder("folder").result(); |
2769 | - f2 = f2->move(folder, "f2").result(); |
2770 | - EXPECT_TRUE(get_parent(f2)->equal_to(folder)); |
2771 | - |
2772 | - // Move the folder |
2773 | - auto item = folder->move(root, "folder2").result(); |
2774 | - folder = dynamic_pointer_cast<Folder>(item); |
2775 | - EXPECT_EQ("folder2", folder->name()); |
2776 | -} |
2777 | - |
2778 | -Test_F(ItemTest, copy) |
2779 | -{ |
2780 | - auto runtime = Runtime::create(connection()); |
2781 | - |
2782 | - auto acc = get_account(runtime); |
2783 | - auto root = get_root(runtime); |
2784 | - clear_folder(root); |
2785 | - |
2786 | - QByteArray const contents = "hello\n"; |
2787 | - write_file(root, "file", contents); |
2788 | - |
2789 | - auto item = root->lookup("file").result(); |
2790 | - auto copied_item = item->copy(root, "copy_of_file").result(); |
2791 | - EXPECT_EQ("copy_of_file", copied_item->name()); |
2792 | - File::SPtr copied_file = dynamic_pointer_cast<File>(item); |
2793 | - ASSERT_NE(nullptr, copied_file); |
2794 | - EXPECT_TRUE(content_matches(copied_file, contents)); |
2795 | -} |
2796 | - |
2797 | -Test_F(ItemTest, recursive_copy) |
2798 | -{ |
2799 | - auto runtime = Runtime::create(connection()); |
2800 | - |
2801 | - auto acc = get_account(runtime); |
2802 | - auto root = get_root(runtime); |
2803 | - clear_folder(root); |
2804 | - |
2805 | - // Create the following structure: |
2806 | - // folder |
2807 | - // folder/empty_folder |
2808 | - // folder/non_empty_folder |
2809 | - // folder/non_empty_folder/nested_file |
2810 | - // folder/file |
2811 | - |
2812 | - string root_path = root->native_identity().toStdString(); |
2813 | - ASSERT_EQ(0, mkdir((root_path + "/folder").c_str(), 0700)); |
2814 | - ASSERT_EQ(0, mkdir((root_path + "/folder/empty_folder").c_str(), 0700)); |
2815 | - ASSERT_EQ(0, mkdir((root_path + "/folder/non_empty_folder").c_str(), 0700)); |
2816 | - ofstream(root_path + "/folder/non_empty_folder/nested_file"); |
2817 | - ofstream(root_path + "/folder/file"); |
2818 | - |
2819 | - // Copy folder to folder2 |
2820 | - auto folder = dynamic_pointer_cast<Folder>(root->lookup("folder").result()); |
2821 | - ASSERT_NE(nullptr, folder); |
2822 | - auto item = folder->copy(root, "folder2").result(); |
2823 | - |
2824 | - // Verify that folder2 now contains the same structure as folder. |
2825 | - auto folder2 = dynamic_pointer_cast<Folder>(item); |
2826 | - ASSERT_NE(nullptr, folder2); |
2827 | - EXPECT_NO_THROW(folder2->lookup("empty_folder").result()); |
2828 | - item = folder2->lookup("non_empty_folder").result(); |
2829 | - auto non_empty_folder = dynamic_pointer_cast<Folder>(item); |
2830 | - ASSERT_NE(nullptr, non_empty_folder); |
2831 | - EXPECT_NO_THROW(non_empty_folder->lookup("nested_file").result()); |
2832 | - EXPECT_NO_THROW(folder2->lookup("file").result()); |
2833 | -} |
2834 | - |
2835 | -Test_F(ItemTest, modified_time) |
2836 | -{ |
2837 | - auto runtime = Runtime::create(connection()); |
2838 | - |
2839 | - auto acc = get_account(runtime); |
2840 | - auto root = get_root(runtime); |
2841 | - clear_folder(root); |
2842 | - |
2843 | - auto now = QDateTime::currentDateTimeUtc(); |
2844 | - // Need to sleep because time_t provides only 1-second resolution. |
2845 | - sleep(1); |
2846 | - auto file = root->create_file("file").result()->file(); |
2847 | - auto t = file->last_modified_time(); |
2848 | - // Rough check that the time is sane. |
2849 | - EXPECT_LE(now, t); |
2850 | - EXPECT_LE(t, now.addSecs(5)); |
2851 | -} |
2852 | - |
2853 | -Test_F(ItemTest, comparison) |
2854 | -{ |
2855 | - auto runtime = Runtime::create(connection()); |
2856 | - |
2857 | - auto acc = get_account(runtime); |
2858 | - auto root = get_root(runtime); |
2859 | - clear_folder(root); |
2860 | - |
2861 | - // Create two files. |
2862 | - auto file1 = root->create_file("file1").result()->file(); |
2863 | - auto file2 = root->create_file("file2").result()->file(); |
2864 | - |
2865 | - EXPECT_FALSE(file1->equal_to(file2)); |
2866 | - |
2867 | - // Retrieve file1 via lookup, so we get a different proxy. |
2868 | - auto item = root->lookup("file1").result(); |
2869 | - auto other_file1 = dynamic_pointer_cast<File>(item); |
2870 | - EXPECT_NE(file1, other_file1); // Compares shared_ptr values |
2871 | - EXPECT_TRUE(file1->equal_to(other_file1)); // Deep comparison |
2872 | -} |
2873 | -#endif |
2874 | + catch (LogicException const& e) |
2875 | + { |
2876 | + EXPECT_EQ("Item::delete_item(): cannot delete root folder", e.error_message()) << e.what(); |
2877 | + } |
2878 | + |
2879 | + { |
2880 | + try |
2881 | + { |
2882 | + call(root->get("no_such_file_id")); |
2883 | + FAIL(); |
2884 | + } |
2885 | + catch (NotExistsException const& e) |
2886 | + { |
2887 | + EXPECT_EQ("no_such_file_id", e.key()); |
2888 | + } |
2889 | + } |
2890 | +} |
2891 | + |
2892 | +TEST_F(RuntimeTest, runtime_destroyed_exceptions) |
2893 | +{ |
2894 | + // Gettting an account after shutting down the runtime must fail. |
2895 | + { |
2896 | + auto runtime = Runtime::create(connection()); |
2897 | + auto acc = get_account(runtime); |
2898 | + runtime->shutdown(); |
2899 | + try |
2900 | + { |
2901 | + acc->runtime(); |
2902 | + FAIL(); |
2903 | + } |
2904 | + catch (RuntimeDestroyedException const& e) |
2905 | + { |
2906 | + EXPECT_EQ("Account::runtime(): runtime was destroyed previously", e.error_message()); |
2907 | + } |
2908 | + } |
2909 | + |
2910 | + // Getting an account after destroying the runtime must fail. |
2911 | + { |
2912 | + auto runtime = Runtime::create(connection()); |
2913 | + auto acc = get_account(runtime); |
2914 | + runtime.reset(); |
2915 | + try |
2916 | + { |
2917 | + acc->runtime(); |
2918 | + FAIL(); |
2919 | + } |
2920 | + catch (RuntimeDestroyedException const& e) |
2921 | + { |
2922 | + EXPECT_EQ("Account::runtime(): runtime was destroyed previously", e.error_message()); |
2923 | + } |
2924 | + } |
2925 | + |
2926 | + // Getting accounts after shutting down the runtime must fail. |
2927 | + { |
2928 | + auto runtime = Runtime::create(connection()); |
2929 | + runtime->shutdown(); |
2930 | + try |
2931 | + { |
2932 | + call(runtime->accounts()); |
2933 | + FAIL(); |
2934 | + } |
2935 | + catch (RuntimeDestroyedException const& e) |
2936 | + { |
2937 | + EXPECT_EQ("Runtime::accounts(): runtime was destroyed previously", e.error_message()); |
2938 | + } |
2939 | + } |
2940 | + |
2941 | + // Getting the account from a root with a destroyed runtime must fail. |
2942 | + { |
2943 | + auto runtime = Runtime::create(connection()); |
2944 | + auto root = get_root(runtime); |
2945 | + runtime.reset(); |
2946 | + try |
2947 | + { |
2948 | + root->account(); |
2949 | + FAIL(); |
2950 | + } |
2951 | + catch (RuntimeDestroyedException const& e) |
2952 | + { |
2953 | + EXPECT_EQ("Root::account(): runtime was destroyed previously", e.error_message()); |
2954 | + } |
2955 | + } |
2956 | + |
2957 | + // Getting the account from a root with a destroyed account must fail. |
2958 | + { |
2959 | + auto runtime = Runtime::create(connection()); |
2960 | + auto acc = get_account(runtime); |
2961 | + auto root = get_root(runtime); |
2962 | + runtime.reset(); |
2963 | + acc.reset(); |
2964 | + try |
2965 | + { |
2966 | + root->account(); |
2967 | + FAIL(); |
2968 | + } |
2969 | + catch (RuntimeDestroyedException const& e) |
2970 | + { |
2971 | + EXPECT_EQ("Root::account(): runtime was destroyed previously", e.error_message()); |
2972 | + } |
2973 | + } |
2974 | + |
2975 | + // Getting the root from an item with a destroyed runtime must fail. |
2976 | + { |
2977 | + auto runtime = Runtime::create(connection()); |
2978 | + auto root = get_root(runtime); |
2979 | + clear_folder(root); |
2980 | + |
2981 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
2982 | + runtime.reset(); |
2983 | + try |
2984 | + { |
2985 | + file->root(); |
2986 | + FAIL(); |
2987 | + } |
2988 | + catch (RuntimeDestroyedException const& e) |
2989 | + { |
2990 | + EXPECT_EQ("Item::root(): runtime was destroyed previously", e.error_message()); |
2991 | + } |
2992 | + } |
2993 | + |
2994 | + // Getting the root from an item with a destroyed root must fail. |
2995 | + { |
2996 | + auto runtime = Runtime::create(connection()); |
2997 | + auto acc = get_account(runtime); |
2998 | + auto root = get_root(runtime); |
2999 | + clear_folder(root); |
3000 | + |
3001 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3002 | + runtime.reset(); |
3003 | + acc.reset(); |
3004 | + root.reset(); |
3005 | + try |
3006 | + { |
3007 | + file->root(); |
3008 | + FAIL(); |
3009 | + } |
3010 | + catch (RuntimeDestroyedException const& e) |
3011 | + { |
3012 | + EXPECT_EQ("Item::root(): runtime was destroyed previously", e.error_message()); |
3013 | + } |
3014 | + } |
3015 | + |
3016 | + // etag() with destroyed runtime must fail. |
3017 | + { |
3018 | + auto runtime = Runtime::create(connection()); |
3019 | + auto root = get_root(runtime); |
3020 | + clear_folder(root); |
3021 | + |
3022 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3023 | + runtime->shutdown(); |
3024 | + try |
3025 | + { |
3026 | + file->etag(); |
3027 | + FAIL(); |
3028 | + } |
3029 | + catch (RuntimeDestroyedException const& e) |
3030 | + { |
3031 | + EXPECT_EQ("Item::etag(): runtime was destroyed previously", e.error_message()); |
3032 | + } |
3033 | + } |
3034 | + |
3035 | + // metadata() with destroyed runtime must fail. |
3036 | + { |
3037 | + auto runtime = Runtime::create(connection()); |
3038 | + auto root = get_root(runtime); |
3039 | + clear_folder(root); |
3040 | + |
3041 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3042 | + runtime->shutdown(); |
3043 | + try |
3044 | + { |
3045 | + file->metadata(); |
3046 | + FAIL(); |
3047 | + } |
3048 | + catch (RuntimeDestroyedException const& e) |
3049 | + { |
3050 | + EXPECT_EQ("Item::metadata(): runtime was destroyed previously", e.error_message()); |
3051 | + } |
3052 | + } |
3053 | + |
3054 | + // last_modified_time() with destroyed runtime must fail. |
3055 | + { |
3056 | + auto runtime = Runtime::create(connection()); |
3057 | + auto root = get_root(runtime); |
3058 | + clear_folder(root); |
3059 | + |
3060 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3061 | + runtime->shutdown(); |
3062 | + try |
3063 | + { |
3064 | + file->last_modified_time(); |
3065 | + FAIL(); |
3066 | + } |
3067 | + catch (RuntimeDestroyedException const& e) |
3068 | + { |
3069 | + EXPECT_EQ("Item::last_modified_time(): runtime was destroyed previously", e.error_message()); |
3070 | + } |
3071 | + } |
3072 | + |
3073 | + // copy() with destroyed runtime must fail. |
3074 | + { |
3075 | + auto runtime = Runtime::create(connection()); |
3076 | + auto root = get_root(runtime); |
3077 | + clear_folder(root); |
3078 | + |
3079 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3080 | + runtime->shutdown(); |
3081 | + try |
3082 | + { |
3083 | + call(file->copy(root, "file2")); |
3084 | + FAIL(); |
3085 | + } |
3086 | + catch (RuntimeDestroyedException const& e) |
3087 | + { |
3088 | + EXPECT_EQ("Item::copy(): runtime was destroyed previously", e.error_message()); |
3089 | + } |
3090 | + } |
3091 | + |
3092 | + // move() with destroyed runtime must fail. |
3093 | + { |
3094 | + auto runtime = Runtime::create(connection()); |
3095 | + auto root = get_root(runtime); |
3096 | + clear_folder(root); |
3097 | + |
3098 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3099 | + runtime->shutdown(); |
3100 | + try |
3101 | + { |
3102 | + call(file->move(root, "file2")); |
3103 | + FAIL(); |
3104 | + } |
3105 | + catch (RuntimeDestroyedException const& e) |
3106 | + { |
3107 | + EXPECT_EQ("Item::move(): runtime was destroyed previously", e.error_message()); |
3108 | + } |
3109 | + } |
3110 | + |
3111 | + // parents() on root with destroyed runtime must fail. |
3112 | + { |
3113 | + auto runtime = Runtime::create(connection()); |
3114 | + auto root = get_root(runtime); |
3115 | + clear_folder(root); |
3116 | + |
3117 | + runtime->shutdown(); |
3118 | + try |
3119 | + { |
3120 | + call(root->parents()); |
3121 | + FAIL(); |
3122 | + } |
3123 | + catch (RuntimeDestroyedException const& e) |
3124 | + { |
3125 | + EXPECT_EQ("Root::parents(): runtime was destroyed previously", e.error_message()); |
3126 | + } |
3127 | + } |
3128 | + |
3129 | + // parents() on file with destroyed runtime must fail. |
3130 | + { |
3131 | + auto runtime = Runtime::create(connection()); |
3132 | + auto root = get_root(runtime); |
3133 | + clear_folder(root); |
3134 | + |
3135 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3136 | + runtime->shutdown(); |
3137 | + try |
3138 | + { |
3139 | + call(file->parents()); |
3140 | + FAIL(); |
3141 | + } |
3142 | + catch (RuntimeDestroyedException const& e) |
3143 | + { |
3144 | + EXPECT_EQ("Item::parents(): runtime was destroyed previously", e.error_message()); |
3145 | + } |
3146 | + } |
3147 | + |
3148 | + // parent_ids() with destroyed runtime must fail. |
3149 | + { |
3150 | + auto runtime = Runtime::create(connection()); |
3151 | + auto root = get_root(runtime); |
3152 | + clear_folder(root); |
3153 | + |
3154 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3155 | + runtime->shutdown(); |
3156 | + try |
3157 | + { |
3158 | + file->parent_ids(); |
3159 | + FAIL(); |
3160 | + } |
3161 | + catch (RuntimeDestroyedException const& e) |
3162 | + { |
3163 | + EXPECT_EQ("Item::parent_ids(): runtime was destroyed previously", e.error_message()); |
3164 | + } |
3165 | + } |
3166 | + |
3167 | + // parent_ids() on root with destroyed runtime must fail. |
3168 | + { |
3169 | + auto runtime = Runtime::create(connection()); |
3170 | + auto root = get_root(runtime); |
3171 | + clear_folder(root); |
3172 | + |
3173 | + runtime->shutdown(); |
3174 | + try |
3175 | + { |
3176 | + root->parent_ids(); |
3177 | + FAIL(); |
3178 | + } |
3179 | + catch (RuntimeDestroyedException const& e) |
3180 | + { |
3181 | + EXPECT_EQ("Root::parent_ids(): runtime was destroyed previously", e.error_message()); |
3182 | + } |
3183 | + } |
3184 | + |
3185 | + // delete_item() with destroyed runtime must fail. |
3186 | + { |
3187 | + auto runtime = Runtime::create(connection()); |
3188 | + auto root = get_root(runtime); |
3189 | + clear_folder(root); |
3190 | + |
3191 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3192 | + runtime->shutdown(); |
3193 | + try |
3194 | + { |
3195 | + call(file->delete_item()); |
3196 | + FAIL(); |
3197 | + } |
3198 | + catch (RuntimeDestroyedException const& e) |
3199 | + { |
3200 | + EXPECT_EQ("Item::delete_item(): runtime was destroyed previously", e.error_message()); |
3201 | + } |
3202 | + } |
3203 | + |
3204 | + // delete_item() on root with destroyed runtime must fail. |
3205 | + { |
3206 | + auto runtime = Runtime::create(connection()); |
3207 | + auto root = get_root(runtime); |
3208 | + clear_folder(root); |
3209 | + |
3210 | + runtime->shutdown(); |
3211 | + try |
3212 | + { |
3213 | + call(root->delete_item()); |
3214 | + FAIL(); |
3215 | + } |
3216 | + catch (RuntimeDestroyedException const& e) |
3217 | + { |
3218 | + EXPECT_EQ("Item::delete_item(): runtime was destroyed previously", e.error_message()); |
3219 | + } |
3220 | + } |
3221 | + |
3222 | + // creation_time() with destroyed runtime must fail. |
3223 | + { |
3224 | + auto runtime = Runtime::create(connection()); |
3225 | + auto root = get_root(runtime); |
3226 | + clear_folder(root); |
3227 | + |
3228 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3229 | + runtime->shutdown(); |
3230 | + try |
3231 | + { |
3232 | + file->creation_time(); |
3233 | + FAIL(); |
3234 | + } |
3235 | + catch (RuntimeDestroyedException const& e) |
3236 | + { |
3237 | + EXPECT_EQ("Item::creation_time(): runtime was destroyed previously", e.error_message()); |
3238 | + } |
3239 | + } |
3240 | + |
3241 | + // native_metadata() with destroyed runtime must fail. |
3242 | + { |
3243 | + auto runtime = Runtime::create(connection()); |
3244 | + auto root = get_root(runtime); |
3245 | + clear_folder(root); |
3246 | + |
3247 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3248 | + runtime->shutdown(); |
3249 | + try |
3250 | + { |
3251 | + file->native_metadata(); |
3252 | + FAIL(); |
3253 | + } |
3254 | + catch (RuntimeDestroyedException const& e) |
3255 | + { |
3256 | + EXPECT_EQ("Item::native_metadata(): runtime was destroyed previously", e.error_message()); |
3257 | + } |
3258 | + } |
3259 | + |
3260 | + // name() on root with destroyed runtime must fail. |
3261 | + { |
3262 | + auto runtime = Runtime::create(connection()); |
3263 | + auto root = get_root(runtime); |
3264 | + clear_folder(root); |
3265 | + |
3266 | + runtime->shutdown(); |
3267 | + try |
3268 | + { |
3269 | + root->name(); |
3270 | + FAIL(); |
3271 | + } |
3272 | + catch (RuntimeDestroyedException const& e) |
3273 | + { |
3274 | + EXPECT_EQ("Item::name(): runtime was destroyed previously", e.error_message()); |
3275 | + } |
3276 | + } |
3277 | + |
3278 | + // name() on folder with destroyed runtime must fail. |
3279 | + { |
3280 | + auto runtime = Runtime::create(connection()); |
3281 | + auto root = get_root(runtime); |
3282 | + clear_folder(root); |
3283 | + |
3284 | + auto folder = dynamic_pointer_cast<Folder>(call(root->get("child_folder_id"))); |
3285 | + runtime->shutdown(); |
3286 | + try |
3287 | + { |
3288 | + folder->name(); |
3289 | + FAIL(); |
3290 | + } |
3291 | + catch (RuntimeDestroyedException const& e) |
3292 | + { |
3293 | + EXPECT_EQ("Item::name(): runtime was destroyed previously", e.error_message()); |
3294 | + } |
3295 | + } |
3296 | + |
3297 | + // name() on file with destroyed runtime must fail. |
3298 | + { |
3299 | + auto runtime = Runtime::create(connection()); |
3300 | + auto root = get_root(runtime); |
3301 | + clear_folder(root); |
3302 | + |
3303 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3304 | + runtime->shutdown(); |
3305 | + try |
3306 | + { |
3307 | + file->name(); |
3308 | + FAIL(); |
3309 | + } |
3310 | + catch (RuntimeDestroyedException const& e) |
3311 | + { |
3312 | + EXPECT_EQ("Item::name(): runtime was destroyed previously", e.error_message()); |
3313 | + } |
3314 | + } |
3315 | + |
3316 | + // list() with destroyed runtime must fail. |
3317 | + { |
3318 | + auto runtime = Runtime::create(connection()); |
3319 | + auto root = get_root(runtime); |
3320 | + clear_folder(root); |
3321 | + |
3322 | + runtime->shutdown(); |
3323 | + try |
3324 | + { |
3325 | + call(root->list()); |
3326 | + FAIL(); |
3327 | + } |
3328 | + catch (RuntimeDestroyedException const& e) |
3329 | + { |
3330 | + EXPECT_EQ("Folder::list(): runtime was destroyed previously", e.error_message()); |
3331 | + } |
3332 | + } |
3333 | + |
3334 | + // lookup() with destroyed runtime must fail. |
3335 | + { |
3336 | + auto runtime = Runtime::create(connection()); |
3337 | + auto root = get_root(runtime); |
3338 | + clear_folder(root); |
3339 | + |
3340 | + runtime->shutdown(); |
3341 | + try |
3342 | + { |
3343 | + call(root->lookup("file")); |
3344 | + FAIL(); |
3345 | + } |
3346 | + catch (RuntimeDestroyedException const& e) |
3347 | + { |
3348 | + EXPECT_EQ("Folder::lookup(): runtime was destroyed previously", e.error_message()); |
3349 | + } |
3350 | + } |
3351 | + |
3352 | + // create_folder() with destroyed runtime must fail. |
3353 | + { |
3354 | + auto runtime = Runtime::create(connection()); |
3355 | + auto root = get_root(runtime); |
3356 | + clear_folder(root); |
3357 | + |
3358 | + runtime->shutdown(); |
3359 | + try |
3360 | + { |
3361 | + call(root->create_folder("folder")); |
3362 | + FAIL(); |
3363 | + } |
3364 | + catch (RuntimeDestroyedException const& e) |
3365 | + { |
3366 | + EXPECT_EQ("Folder::create_folder(): runtime was destroyed previously", e.error_message()); |
3367 | + } |
3368 | + } |
3369 | + |
3370 | + // create_file() with destroyed runtime must fail. |
3371 | + { |
3372 | + auto runtime = Runtime::create(connection()); |
3373 | + auto root = get_root(runtime); |
3374 | + clear_folder(root); |
3375 | + |
3376 | + runtime->shutdown(); |
3377 | + try |
3378 | + { |
3379 | + call(root->create_file("file", 0)); |
3380 | + FAIL(); |
3381 | + } |
3382 | + catch (RuntimeDestroyedException const& e) |
3383 | + { |
3384 | + EXPECT_EQ("Folder::create_file(): runtime was destroyed previously", e.error_message()); |
3385 | + } |
3386 | + } |
3387 | + |
3388 | + // size() with destroyed runtime must fail. |
3389 | + { |
3390 | + auto runtime = Runtime::create(connection()); |
3391 | + auto root = get_root(runtime); |
3392 | + clear_folder(root); |
3393 | + |
3394 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3395 | + runtime->shutdown(); |
3396 | + try |
3397 | + { |
3398 | + file->size(); |
3399 | + FAIL(); |
3400 | + } |
3401 | + catch (RuntimeDestroyedException const& e) |
3402 | + { |
3403 | + EXPECT_EQ("File::size(): runtime was destroyed previously", e.error_message()); |
3404 | + } |
3405 | + } |
3406 | + |
3407 | + // create_uploader() with destroyed runtime must fail. |
3408 | + { |
3409 | + auto runtime = Runtime::create(connection()); |
3410 | + auto root = get_root(runtime); |
3411 | + clear_folder(root); |
3412 | + |
3413 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3414 | + runtime->shutdown(); |
3415 | + try |
3416 | + { |
3417 | + call(file->create_uploader(ConflictPolicy::overwrite, 0)); |
3418 | + FAIL(); |
3419 | + } |
3420 | + catch (RuntimeDestroyedException const& e) |
3421 | + { |
3422 | + EXPECT_EQ("File::create_uploader(): runtime was destroyed previously", e.error_message()) << e.what(); |
3423 | + } |
3424 | + } |
3425 | + |
3426 | + // create_downloader() with destroyed runtime must fail. |
3427 | + { |
3428 | + auto runtime = Runtime::create(connection()); |
3429 | + auto root = get_root(runtime); |
3430 | + clear_folder(root); |
3431 | + |
3432 | + auto file = dynamic_pointer_cast<File>(call(root->get("child_id"))); |
3433 | + runtime->shutdown(); |
3434 | + try |
3435 | + { |
3436 | + call(file->create_downloader()); |
3437 | + FAIL(); |
3438 | + } |
3439 | + catch (RuntimeDestroyedException const& e) |
3440 | + { |
3441 | + EXPECT_EQ("File::create_downloader(): runtime was destroyed previously", e.error_message()); |
3442 | + } |
3443 | + } |
3444 | + |
3445 | + // free_space_bytes() with destroyed runtime must fail. |
3446 | + { |
3447 | + auto runtime = Runtime::create(connection()); |
3448 | + auto root = get_root(runtime); |
3449 | + clear_folder(root); |
3450 | + |
3451 | + runtime->shutdown(); |
3452 | + try |
3453 | + { |
3454 | + call(root->free_space_bytes()); |
3455 | + FAIL(); |
3456 | + } |
3457 | + catch (RuntimeDestroyedException const& e) |
3458 | + { |
3459 | + EXPECT_EQ("Root::free_space_bytes(): runtime was destroyed previously", e.error_message()); |
3460 | + } |
3461 | + } |
3462 | + |
3463 | + // used_space_bytes() with destroyed runtime must fail. |
3464 | + { |
3465 | + auto runtime = Runtime::create(connection()); |
3466 | + auto root = get_root(runtime); |
3467 | + clear_folder(root); |
3468 | + |
3469 | + runtime->shutdown(); |
3470 | + try |
3471 | + { |
3472 | + call(root->used_space_bytes()); |
3473 | + FAIL(); |
3474 | + } |
3475 | + catch (RuntimeDestroyedException const& e) |
3476 | + { |
3477 | + EXPECT_EQ("Root::used_space_bytes(): runtime was destroyed previously", e.error_message()); |
3478 | + } |
3479 | + } |
3480 | + |
3481 | + // get() with destroyed runtime must fail. |
3482 | + { |
3483 | + auto runtime = Runtime::create(connection()); |
3484 | + auto root = get_root(runtime); |
3485 | + clear_folder(root); |
3486 | + |
3487 | + runtime->shutdown(); |
3488 | + try |
3489 | + { |
3490 | + call(root->get("some_id")); |
3491 | + FAIL(); |
3492 | + } |
3493 | + catch (RuntimeDestroyedException const& e) |
3494 | + { |
3495 | + EXPECT_EQ("Root::get(): runtime was destroyed previously", e.error_message()); |
3496 | + } |
3497 | + } |
3498 | +} |
3499 | |
3500 | int main(int argc, char** argv) |
3501 | { |
FAILED: Continuous integration, rev:84 /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/50/ /jenkins. canonical. com/unity- api-1/job/ build/292/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/298 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= vivid+overlay/ 227 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= xenial+ overlay/ 227 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= yakkety/ 227 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 156/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 156/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 156/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 156/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 156/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 156/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 156/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 156/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 156/console
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: /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/50/rebuild
https:/