Merge lp:~michihenning/storage-framework/copy-and-move into lp:storage-framework/devel
- copy-and-move
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Michi Henning |
Approved revision: | 93 |
Merged at revision: | 75 |
Proposed branch: | lp:~michihenning/storage-framework/copy-and-move |
Merge into: | lp:storage-framework/devel |
Prerequisite: | lp:~michihenning/storage-framework/parents |
Diff against target: |
925 lines (+656/-65) 7 files modified
include/unity/storage/qt/internal/ItemImpl.h (+61/-1) include/unity/storage/qt/internal/ItemJobImpl.h (+9/-0) src/qt/internal/AccountImpl.cpp (+1/-3) src/qt/internal/ItemImpl.cpp (+66/-26) src/qt/internal/ItemJobImpl.cpp (+21/-0) tests/remote-client/MockProvider.cpp (+37/-2) tests/remote-client/remote-client_test.cpp (+461/-33) |
To merge this branch: | bzr merge lp:~michihenning/storage-framework/copy-and-move |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
unity-api-1-bot | continuous-integration | Approve | |
James Henstridge | Approve | ||
Review via email:
|
Commit message
Added copy and move implementations.
Description of the change
Added copy and move implementations. Re-factored semantic checks for ItemImpl operations into two templates, to avoid endlessly repeating almost identical code.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
unity-api-1-bot (unity-api-1-bot) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:91
https:/
Executed test runs:
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:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
James Henstridge (jamesh) wrote : | # |
Looks good. Again, one issue that is more of a suggestion for possible improvement than a bug, so I'm marking the branch approved and leaving it up to you to top approve it when you're ready.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Michi Henning (michihenning) wrote : | # |
Simplified ItemImpl template methods, thanks!
- 91. By Michi Henning
-
Merged dependent branch.
- 92. By Michi Henning
-
Simplified ItemImpl template methods for checking preconditions.
- 93. By Michi Henning
-
Merged parent branch and resolved conflicts.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:93
https:/
Executed test runs:
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 'include/unity/storage/qt/internal/ItemImpl.h' |
2 | --- include/unity/storage/qt/internal/ItemImpl.h 2016-10-10 02:14:34 +0000 |
3 | +++ include/unity/storage/qt/internal/ItemImpl.h 2016-10-10 02:14:34 +0000 |
4 | @@ -20,6 +20,9 @@ |
5 | |
6 | #include <unity/storage/internal/ItemMetadata.h> |
7 | #include <unity/storage/qt/Account.h> |
8 | +#include <unity/storage/qt/internal/AccountImpl.h> |
9 | +#include <unity/storage/qt/internal/RuntimeImpl.h> |
10 | +#include <unity/storage/qt/internal/StorageErrorImpl.h> |
11 | #include <unity/storage/qt/Item.h> |
12 | |
13 | namespace unity |
14 | @@ -82,9 +85,16 @@ |
15 | std::shared_ptr<AccountImpl> const& account); |
16 | |
17 | std::shared_ptr<RuntimeImpl> runtime() const; |
18 | + std::shared_ptr<AccountImpl> account_impl() const; |
19 | |
20 | private: |
21 | - //std::shared_ptr<RuntimeImpl> get_runtime(QString const& method) const; |
22 | + template<typename T> |
23 | + decltype(T::make_job(StorageError())) check_invalid_or_destroyed(QString const& method) const; |
24 | + |
25 | + template<typename T> |
26 | + decltype(T::make_job(StorageError())) check_copy_move_precondition(QString const& method, |
27 | + Item const& newParent, |
28 | + QString const& newName) const; |
29 | |
30 | bool is_valid_; |
31 | storage::internal::ItemMetadata md_; |
32 | @@ -93,6 +103,56 @@ |
33 | friend class unity::storage::qt::Item; |
34 | }; |
35 | |
36 | +template<typename T> |
37 | +decltype(T::make_job(StorageError())) ItemImpl::check_invalid_or_destroyed(QString const& method) const |
38 | +{ |
39 | + if (!is_valid_) |
40 | + { |
41 | + auto e = StorageErrorImpl::logic_error(method + ": cannot create job from invalid item"); |
42 | + return T::make_job(e); |
43 | + } |
44 | + auto runtime = account_->runtime(); |
45 | + if (!runtime || !runtime->isValid()) |
46 | + { |
47 | + auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously"); |
48 | + return T::make_job(e); |
49 | + } |
50 | + return nullptr; |
51 | +} |
52 | + |
53 | +template<typename T> |
54 | +decltype(T::make_job(StorageError())) ItemImpl::check_copy_move_precondition(QString const& method, |
55 | + Item const& newParent, |
56 | + QString const& newName) const |
57 | +{ |
58 | + auto invalid_job = check_invalid_or_destroyed<T>(method); |
59 | + if (invalid_job) |
60 | + { |
61 | + return invalid_job; |
62 | + } |
63 | + if (!newParent.isValid()) |
64 | + { |
65 | + auto e = StorageErrorImpl::invalid_argument_error(method + ": newParent is invalid"); |
66 | + return T::make_job(e); |
67 | + } |
68 | + if (newName.isEmpty()) |
69 | + { |
70 | + auto e = StorageErrorImpl::invalid_argument_error(method + ": newName cannot be empty"); |
71 | + return T::make_job(e); |
72 | + } |
73 | + if (account() != newParent.account()) |
74 | + { |
75 | + auto e = StorageErrorImpl::logic_error(method + ": source and target must belong to the same account"); |
76 | + return T::make_job(e); |
77 | + } |
78 | + if (newParent.type() == Item::File) |
79 | + { |
80 | + auto e = StorageErrorImpl::logic_error(method + ": newParent cannot be a file"); |
81 | + return T::make_job(e); |
82 | + } |
83 | + return nullptr; |
84 | +} |
85 | + |
86 | } // namespace internal |
87 | } // namespace qt |
88 | } // namespace storage |
89 | |
90 | === modified file 'include/unity/storage/qt/internal/ItemJobImpl.h' |
91 | --- include/unity/storage/qt/internal/ItemJobImpl.h 2016-10-10 02:14:34 +0000 |
92 | +++ include/unity/storage/qt/internal/ItemJobImpl.h 2016-10-10 02:14:34 +0000 |
93 | @@ -57,6 +57,10 @@ |
94 | QString const& method, |
95 | QDBusPendingReply<storage::internal::ItemMetadata> const& reply, |
96 | std::function<void(storage::internal::ItemMetadata const&)> const& validate); |
97 | + static ItemJob* make_job(std::shared_ptr<ItemImpl> const&, |
98 | + QString const& method, |
99 | + QDBusPendingReply<storage::internal::ItemMetadata> const& reply, |
100 | + std::function<void(storage::internal::ItemMetadata const&)> const& validate); |
101 | static ItemJob* make_job(StorageError const& e); |
102 | |
103 | private: |
104 | @@ -64,6 +68,10 @@ |
105 | QString const& method, |
106 | QDBusPendingReply<storage::internal::ItemMetadata> const& reply, |
107 | std::function<void(storage::internal::ItemMetadata const&)> const& validate); |
108 | + ItemJobImpl(std::shared_ptr<ItemImpl> const& item, |
109 | + QString const& method, |
110 | + QDBusPendingReply<storage::internal::ItemMetadata> const& reply, |
111 | + std::function<void(storage::internal::ItemMetadata const&)> const& validate); |
112 | ItemJobImpl(StorageError const& e); |
113 | |
114 | ItemJob* public_instance_; |
115 | @@ -71,6 +79,7 @@ |
116 | StorageError error_; |
117 | QString method_; |
118 | std::shared_ptr<AccountImpl> account_; |
119 | + std::shared_ptr<ItemImpl> item_impl_; |
120 | std::function<void(storage::internal::ItemMetadata const&)> validate_; |
121 | Item item_; |
122 | }; |
123 | |
124 | === modified file 'src/qt/internal/AccountImpl.cpp' |
125 | --- src/qt/internal/AccountImpl.cpp 2016-10-10 02:14:34 +0000 |
126 | +++ src/qt/internal/AccountImpl.cpp 2016-10-10 02:14:34 +0000 |
127 | @@ -102,7 +102,7 @@ |
128 | if (md.type != ItemType::root) |
129 | { |
130 | QString msg = method + ": provider returned non-root item type: " + QString::number(int(md.type)); |
131 | - qCritical() << msg; |
132 | + qCritical().noquote() << msg; |
133 | throw StorageErrorImpl::local_comms_error(msg); |
134 | } |
135 | }; |
136 | @@ -128,11 +128,9 @@ |
137 | return ItemJobImpl::make_job(e); |
138 | } |
139 | |
140 | - // LCOV_EXCL_START |
141 | auto validate = [](storage::internal::ItemMetadata const&) |
142 | { |
143 | }; |
144 | - // LCOV_EXCL_STOP |
145 | |
146 | auto reply = provider_->Metadata(itemId); |
147 | auto This = const_pointer_cast<AccountImpl>(shared_from_this()); |
148 | |
149 | === modified file 'src/qt/internal/ItemImpl.cpp' |
150 | --- src/qt/internal/ItemImpl.cpp 2016-10-10 02:14:34 +0000 |
151 | +++ src/qt/internal/ItemImpl.cpp 2016-10-10 02:14:34 +0000 |
152 | @@ -20,12 +20,9 @@ |
153 | |
154 | #include "ProviderInterface.h" |
155 | #include <unity/storage/provider/metadata_keys.h> |
156 | -#include <unity/storage/qt/internal/AccountImpl.h> |
157 | #include <unity/storage/qt/internal/ItemJobImpl.h> |
158 | #include <unity/storage/qt/internal/ItemListJobImpl.h> |
159 | #include <unity/storage/qt/internal/MultiItemJobImpl.h> |
160 | -#include <unity/storage/qt/internal/RuntimeImpl.h> |
161 | -#include <unity/storage/qt/internal/StorageErrorImpl.h> |
162 | #include <unity/storage/qt/internal/VoidJobImpl.h> |
163 | #include <unity/storage/qt/internal/validate.h> |
164 | |
165 | @@ -119,16 +116,10 @@ |
166 | { |
167 | QString const method = "Item::parents()"; |
168 | |
169 | - if (!is_valid_) |
170 | - { |
171 | - auto e = StorageErrorImpl::logic_error(method + ": cannot create job from invalid item"); |
172 | - return ListJobImplBase::make_job(e); |
173 | - } |
174 | - auto runtime = account_->runtime(); |
175 | - if (!runtime || !runtime->isValid()) |
176 | - { |
177 | - auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously"); |
178 | - return ListJobImplBase::make_job(e); |
179 | + auto invalid_job = check_invalid_or_destroyed<ItemListJobImpl>(method); |
180 | + if (invalid_job) |
181 | + { |
182 | + return invalid_job; |
183 | } |
184 | |
185 | if (md_.type == storage::ItemType::root) |
186 | @@ -150,7 +141,7 @@ |
187 | if (md.type == ItemType::file) |
188 | { |
189 | QString msg = method + ": provider returned a file as a parent"; |
190 | - qCritical() << msg; |
191 | + qCritical().noquote() << msg; |
192 | throw StorageErrorImpl::local_comms_error(msg); |
193 | } |
194 | }; |
195 | @@ -160,28 +151,72 @@ |
196 | |
197 | ItemJob* ItemImpl::copy(Item const& newParent, QString const& newName) const |
198 | { |
199 | - return nullptr; // TODO |
200 | + QString const method = "Item::copy()"; |
201 | + |
202 | + auto invalid_job = check_copy_move_precondition<ItemJobImpl>(method, newParent, newName); |
203 | + if (invalid_job) |
204 | + { |
205 | + return invalid_job; |
206 | + } |
207 | + |
208 | + auto validate = [this, method](storage::internal::ItemMetadata const& md) |
209 | + { |
210 | + if ((md_.type == ItemType::file && md.type != ItemType::file) |
211 | + || |
212 | + (md_.type != ItemType::file && md.type == ItemType::file)) |
213 | + { |
214 | + QString msg = method + ": source and target item type differ"; |
215 | + qCritical().noquote() << msg; |
216 | + throw StorageErrorImpl::local_comms_error(msg); |
217 | + } |
218 | + }; |
219 | + |
220 | + auto reply = account_->provider()->Copy(md_.item_id, newParent.itemId(), newName); |
221 | + auto This = const_pointer_cast<ItemImpl>(shared_from_this()); |
222 | + return ItemJobImpl::make_job(This, method, reply, validate); |
223 | } |
224 | |
225 | ItemJob* ItemImpl::move(Item const& newParent, QString const& newName) const |
226 | { |
227 | - return nullptr; // TODO |
228 | + QString const method = "Item::move()"; |
229 | + |
230 | + auto invalid_job = check_copy_move_precondition<ItemJobImpl>(method, newParent, newName); |
231 | + if (invalid_job) |
232 | + { |
233 | + return invalid_job; |
234 | + } |
235 | + |
236 | + auto validate = [this, method](storage::internal::ItemMetadata const& md) |
237 | + { |
238 | + if (md.type == ItemType::root) |
239 | + { |
240 | + QString msg = method + ": impossible root item returned by server"; |
241 | + qCritical().noquote() << msg; |
242 | + throw StorageErrorImpl::local_comms_error(msg); |
243 | + } |
244 | + if ((md_.type == ItemType::file && md.type != ItemType::file) |
245 | + || |
246 | + (md_.type != ItemType::file && md.type == ItemType::file)) |
247 | + { |
248 | + QString msg = method + ": source and target item type differ"; |
249 | + qCritical().noquote() << msg; |
250 | + throw StorageErrorImpl::local_comms_error(msg); |
251 | + } |
252 | + }; |
253 | + |
254 | + auto reply = account_->provider()->Move(md_.item_id, newParent.itemId(), newName); |
255 | + auto This = const_pointer_cast<ItemImpl>(shared_from_this()); |
256 | + return ItemJobImpl::make_job(This, method, reply, validate); |
257 | } |
258 | |
259 | VoidJob* ItemImpl::deleteItem() const |
260 | { |
261 | QString const method = "Item::deleteItem()"; |
262 | |
263 | - if (!is_valid_) |
264 | - { |
265 | - auto e = StorageErrorImpl::logic_error(method + ": cannot create job from invalid item"); |
266 | - return VoidJobImpl::make_job(e); |
267 | - } |
268 | - auto runtime = account_->runtime(); |
269 | - if (!runtime || !runtime->isValid()) |
270 | - { |
271 | - auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously"); |
272 | - return VoidJobImpl::make_job(e); |
273 | + auto invalid_job = check_invalid_or_destroyed<VoidJobImpl>(method); |
274 | + if (invalid_job) |
275 | + { |
276 | + return invalid_job; |
277 | } |
278 | if (md_.type == storage::ItemType::root) |
279 | { |
280 | @@ -313,6 +348,11 @@ |
281 | return account_->runtime(); |
282 | } |
283 | |
284 | +shared_ptr<AccountImpl> ItemImpl::account_impl() const |
285 | +{ |
286 | + return account_; |
287 | +} |
288 | + |
289 | } // namespace internal |
290 | } // namespace qt |
291 | } // namespace storage |
292 | |
293 | === modified file 'src/qt/internal/ItemJobImpl.cpp' |
294 | --- src/qt/internal/ItemJobImpl.cpp 2016-10-10 02:14:34 +0000 |
295 | +++ src/qt/internal/ItemJobImpl.cpp 2016-10-10 02:14:34 +0000 |
296 | @@ -86,6 +86,16 @@ |
297 | new Handler<storage::internal::ItemMetadata>(this, reply, process_reply, process_error); |
298 | } |
299 | |
300 | +ItemJobImpl::ItemJobImpl(shared_ptr<ItemImpl> const& item, |
301 | + QString const& method, |
302 | + QDBusPendingReply<storage::internal::ItemMetadata> const& reply, |
303 | + std::function<void(storage::internal::ItemMetadata const&)> const& validate) |
304 | + : ItemJobImpl(item->account_impl(), method, reply, validate) |
305 | +{ |
306 | + assert(item); |
307 | + item_impl_= item; |
308 | +} |
309 | + |
310 | ItemJobImpl::ItemJobImpl(StorageError const& error) |
311 | : status_(ItemJob::Error) |
312 | , error_(error) |
313 | @@ -123,6 +133,17 @@ |
314 | return job; |
315 | } |
316 | |
317 | +ItemJob* ItemJobImpl::make_job(shared_ptr<ItemImpl> const& item, |
318 | + QString const& method, |
319 | + QDBusPendingReply<storage::internal::ItemMetadata> const& reply, |
320 | + std::function<void(storage::internal::ItemMetadata const&)> const& validate) |
321 | +{ |
322 | + unique_ptr<ItemJobImpl> impl(new ItemJobImpl(item, method, reply, validate)); |
323 | + auto job = new ItemJob(move(impl)); |
324 | + job->p_->public_instance_ = job; |
325 | + return job; |
326 | +} |
327 | + |
328 | ItemJob* ItemJobImpl::make_job(StorageError const& error) |
329 | { |
330 | unique_ptr<ItemJobImpl> impl(new ItemJobImpl(error)); |
331 | |
332 | === modified file 'tests/remote-client/MockProvider.cpp' |
333 | --- tests/remote-client/MockProvider.cpp 2016-10-10 02:14:34 +0000 |
334 | +++ tests/remote-client/MockProvider.cpp 2016-10-10 02:14:34 +0000 |
335 | @@ -248,7 +248,29 @@ |
336 | string const& item_id, string const& new_parent_id, |
337 | string const& new_name, Context const&) |
338 | { |
339 | - Item metadata{item_id, { new_parent_id }, new_name, "etag", ItemType::file, {}}; |
340 | + if (cmd_ == "move_returns_root") |
341 | + { |
342 | + Item metadata |
343 | + { |
344 | + "root_id", { new_parent_id }, new_name, "etag", ItemType::root, |
345 | + { { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
346 | + }; |
347 | + return make_ready_future(metadata); |
348 | + } |
349 | + if (cmd_ == "move_type_mismatch") |
350 | + { |
351 | + Item metadata |
352 | + { |
353 | + item_id, { new_parent_id }, new_name, "etag", ItemType::folder, |
354 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
355 | + }; |
356 | + return make_ready_future(metadata); |
357 | + } |
358 | + Item metadata |
359 | + { |
360 | + item_id, { new_parent_id }, new_name, "etag", ItemType::file, |
361 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
362 | + }; |
363 | return make_ready_future(metadata); |
364 | } |
365 | |
366 | @@ -256,7 +278,20 @@ |
367 | string const&, string const& new_parent_id, |
368 | string const& new_name, Context const&) |
369 | { |
370 | - Item metadata{"new_item_id", { new_parent_id }, new_name, "etag", ItemType::file, {}}; |
371 | + if (cmd_ == "copy_type_mismatch") |
372 | + { |
373 | + Item metadata |
374 | + { |
375 | + "new_item_id", { new_parent_id }, new_name, "etag", ItemType::folder, |
376 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
377 | + }; |
378 | + return make_ready_future(metadata); |
379 | + } |
380 | + Item metadata |
381 | + { |
382 | + "new_item_id", { new_parent_id }, new_name, "etag", ItemType::file, |
383 | + { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } } |
384 | + }; |
385 | return make_ready_future(metadata); |
386 | } |
387 | |
388 | |
389 | === modified file 'tests/remote-client/remote-client_test.cpp' |
390 | --- tests/remote-client/remote-client_test.cpp 2016-10-10 02:14:34 +0000 |
391 | +++ tests/remote-client/remote-client_test.cpp 2016-10-10 02:14:34 +0000 |
392 | @@ -55,9 +55,11 @@ |
393 | }; |
394 | |
395 | class AccountTest : public RemoteClientTest {}; |
396 | +class CopyTest : public RemoteClientTest {}; |
397 | class DeleteTest : public RemoteClientTest {}; |
398 | class GetTest : public RemoteClientTest {}; |
399 | class ItemTest : public RemoteClientTest {}; |
400 | +class MoveTest : public RemoteClientTest {}; |
401 | class ParentsTest : public RemoteClientTest {}; |
402 | class RootsTest : public RemoteClientTest {}; |
403 | class RuntimeTest : public ProviderFixture {}; |
404 | @@ -774,7 +776,7 @@ |
405 | EXPECT_EQ("Item::deleteItem(): cannot create job from invalid item", j->error().message()); |
406 | |
407 | // Signal must be received. |
408 | - QSignalSpy spy(j.get(), &unity::storage::qt::VoidJob::statusChanged); |
409 | + QSignalSpy spy(j.get(), &VoidJob::statusChanged); |
410 | spy.wait(SIGNAL_WAIT_TIME); |
411 | ASSERT_EQ(1, spy.count()); |
412 | auto arg = spy.takeFirst(); |
413 | @@ -1125,39 +1127,37 @@ |
414 | } |
415 | |
416 | QList<Item> parents; |
417 | + unique_ptr<ItemListJob> j(child.parents()); |
418 | + EXPECT_TRUE(j->isValid()); |
419 | + |
420 | + QSignalSpy ready_spy(j.get(), &ItemListJob::itemsReady); |
421 | + QSignalSpy status_spy(j.get(), &ItemListJob::statusChanged); |
422 | + |
423 | + ready_spy.wait(SIGNAL_WAIT_TIME); |
424 | + auto list_arg = ready_spy.takeFirst(); |
425 | + auto this_parent = qvariant_cast<QList<Item>>(list_arg.at(0)); |
426 | + parents.append(this_parent); |
427 | + while (ready_spy.count() < 1) |
428 | { |
429 | - unique_ptr<ItemListJob> j(child.parents()); |
430 | - EXPECT_TRUE(j->isValid()); |
431 | - |
432 | - QSignalSpy ready_spy(j.get(), &ItemListJob::itemsReady); |
433 | - QSignalSpy status_spy(j.get(), &ItemListJob::statusChanged); |
434 | - |
435 | ready_spy.wait(SIGNAL_WAIT_TIME); |
436 | - auto list_arg = ready_spy.takeFirst(); |
437 | - auto this_parent = qvariant_cast<QList<Item>>(list_arg.at(0)); |
438 | - parents.append(this_parent); |
439 | - while (ready_spy.count() < 1) |
440 | - { |
441 | - ready_spy.wait(SIGNAL_WAIT_TIME); |
442 | - } |
443 | - list_arg = ready_spy.takeFirst(); |
444 | - this_parent = qvariant_cast<QList<Item>>(list_arg.at(0)); |
445 | - parents.append(this_parent); |
446 | - |
447 | - // Finished signal must be received. |
448 | - if (status_spy.count() == 0) |
449 | - { |
450 | - status_spy.wait(SIGNAL_WAIT_TIME); |
451 | - } |
452 | - ASSERT_EQ(1, status_spy.count()); |
453 | - auto status_arg = status_spy.takeFirst(); |
454 | - EXPECT_EQ(ItemListJob::Finished, qvariant_cast<ItemListJob::Status>(status_arg.at(0))); |
455 | - |
456 | - // Child must have two parents. |
457 | - ASSERT_EQ(2, parents.size()); |
458 | - EXPECT_EQ("root_id", parents[0].itemId()); |
459 | - EXPECT_EQ("child_folder_id", parents[1].itemId()); |
460 | - } |
461 | + } |
462 | + list_arg = ready_spy.takeFirst(); |
463 | + this_parent = qvariant_cast<QList<Item>>(list_arg.at(0)); |
464 | + parents.append(this_parent); |
465 | + |
466 | + // Finished signal must be received. |
467 | + if (status_spy.count() == 0) |
468 | + { |
469 | + status_spy.wait(SIGNAL_WAIT_TIME); |
470 | + } |
471 | + ASSERT_EQ(1, status_spy.count()); |
472 | + auto status_arg = status_spy.takeFirst(); |
473 | + EXPECT_EQ(ItemListJob::Finished, qvariant_cast<ItemListJob::Status>(status_arg.at(0))); |
474 | + |
475 | + // Child must have two parents. |
476 | + ASSERT_EQ(2, parents.size()); |
477 | + EXPECT_EQ("root_id", parents[0].itemId()); |
478 | + EXPECT_EQ("child_folder_id", parents[1].itemId()); |
479 | } |
480 | |
481 | TEST_F(ParentsTest, two_parents_throw) |
482 | @@ -1305,7 +1305,6 @@ |
483 | child = j->item(); |
484 | } |
485 | |
486 | - QList<Item> parents; |
487 | { |
488 | unique_ptr<ItemListJob> j(child.parents()); |
489 | EXPECT_TRUE(j->isValid()); |
490 | @@ -1322,6 +1321,435 @@ |
491 | } |
492 | } |
493 | |
494 | +TEST_F(CopyTest, basic) |
495 | +{ |
496 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
497 | + |
498 | + Item root; |
499 | + { |
500 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
501 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
502 | + spy.wait(SIGNAL_WAIT_TIME); |
503 | + root = j->item(); |
504 | + } |
505 | + |
506 | + Item child; |
507 | + { |
508 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
509 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
510 | + spy.wait(SIGNAL_WAIT_TIME); |
511 | + child = j->item(); |
512 | + } |
513 | + |
514 | + unique_ptr<ItemJob> j(child.copy(root, "copied_item")); |
515 | + EXPECT_TRUE(j->isValid()); |
516 | + EXPECT_EQ(ItemJob::Loading, j->status()); |
517 | + EXPECT_EQ(StorageError::NoError, j->error().type()); |
518 | + |
519 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
520 | + spy.wait(SIGNAL_WAIT_TIME); |
521 | + ASSERT_EQ(1, spy.count()); |
522 | + auto arg = spy.takeFirst(); |
523 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
524 | + EXPECT_EQ(ItemJob::Finished, status); |
525 | + |
526 | + EXPECT_TRUE(j->isValid()); |
527 | + EXPECT_EQ(ItemJob::Finished, j->status()); |
528 | + EXPECT_EQ(StorageError::NoError, j->error().type()); |
529 | + auto copied_file = j->item(); |
530 | + EXPECT_EQ("new_item_id", copied_file.itemId()); |
531 | + EXPECT_EQ(root.itemId(), copied_file.parentIds()[0]); |
532 | + EXPECT_EQ("copied_item", copied_file.name()); |
533 | +} |
534 | + |
535 | +TEST_F(CopyTest, invalid) |
536 | +{ |
537 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
538 | + |
539 | + Item root; |
540 | + { |
541 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
542 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
543 | + spy.wait(SIGNAL_WAIT_TIME); |
544 | + root = j->item(); |
545 | + } |
546 | + |
547 | + Item child; |
548 | + unique_ptr<ItemJob> j(child.copy(root, "copied_item")); |
549 | + EXPECT_FALSE(j->isValid()); |
550 | + EXPECT_EQ(ItemJob::Error, j->status()); |
551 | + EXPECT_EQ(StorageError::LogicError, j->error().type()); |
552 | + EXPECT_EQ("LogicError", j->error().name()); |
553 | + EXPECT_EQ("LogicError: Item::copy(): cannot create job from invalid item", j->error().errorString()); |
554 | + |
555 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
556 | + spy.wait(SIGNAL_WAIT_TIME); |
557 | + ASSERT_EQ(1, spy.count()); |
558 | + auto arg = spy.takeFirst(); |
559 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
560 | + EXPECT_EQ(ItemJob::Error, status); |
561 | + |
562 | + EXPECT_FALSE(j->isValid()); |
563 | + EXPECT_EQ(ItemJob::Error, j->status()); |
564 | + EXPECT_EQ(StorageError::LogicError, j->error().type()); |
565 | + EXPECT_EQ("LogicError", j->error().name()); |
566 | + EXPECT_EQ("LogicError: Item::copy(): cannot create job from invalid item", j->error().errorString()); |
567 | +} |
568 | + |
569 | +TEST_F(CopyTest, invalid_parent) |
570 | +{ |
571 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
572 | + |
573 | + Item root; |
574 | + { |
575 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
576 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
577 | + spy.wait(SIGNAL_WAIT_TIME); |
578 | + root = j->item(); |
579 | + } |
580 | + |
581 | + Item child; |
582 | + { |
583 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
584 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
585 | + spy.wait(SIGNAL_WAIT_TIME); |
586 | + child = j->item(); |
587 | + } |
588 | + |
589 | + Item invalid_parent; |
590 | + unique_ptr<ItemJob> j(child.copy(invalid_parent, "copied_item")); |
591 | + EXPECT_FALSE(j->isValid()); |
592 | + EXPECT_EQ(ItemJob::Error, j->status()); |
593 | + EXPECT_EQ(StorageError::InvalidArgument, j->error().type()); |
594 | + EXPECT_EQ("InvalidArgument: Item::copy(): newParent is invalid", j->error().errorString()); |
595 | + |
596 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
597 | + spy.wait(SIGNAL_WAIT_TIME); |
598 | + ASSERT_EQ(1, spy.count()); |
599 | + auto arg = spy.takeFirst(); |
600 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
601 | + EXPECT_EQ(ItemJob::Error, status); |
602 | + |
603 | + EXPECT_FALSE(j->isValid()); |
604 | + EXPECT_EQ(ItemJob::Error, j->status()); |
605 | + EXPECT_EQ(StorageError::InvalidArgument, j->error().type()); |
606 | + EXPECT_EQ("InvalidArgument: Item::copy(): newParent is invalid", j->error().errorString()); |
607 | +} |
608 | + |
609 | +TEST_F(CopyTest, empty_name) |
610 | +{ |
611 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
612 | + |
613 | + Item root; |
614 | + { |
615 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
616 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
617 | + spy.wait(SIGNAL_WAIT_TIME); |
618 | + root = j->item(); |
619 | + } |
620 | + |
621 | + Item child; |
622 | + { |
623 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
624 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
625 | + spy.wait(SIGNAL_WAIT_TIME); |
626 | + child = j->item(); |
627 | + } |
628 | + |
629 | + unique_ptr<ItemJob> j(child.copy(root, "")); |
630 | + EXPECT_FALSE(j->isValid()); |
631 | + EXPECT_EQ(ItemJob::Error, j->status()); |
632 | + EXPECT_EQ(StorageError::InvalidArgument, j->error().type()); |
633 | + EXPECT_EQ("InvalidArgument: Item::copy(): newName cannot be empty", j->error().errorString()); |
634 | + |
635 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
636 | + spy.wait(SIGNAL_WAIT_TIME); |
637 | + ASSERT_EQ(1, spy.count()); |
638 | + auto arg = spy.takeFirst(); |
639 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
640 | + EXPECT_EQ(ItemJob::Error, status); |
641 | + |
642 | + EXPECT_FALSE(j->isValid()); |
643 | + EXPECT_EQ(ItemJob::Error, j->status()); |
644 | + EXPECT_EQ(StorageError::InvalidArgument, j->error().type()); |
645 | + EXPECT_EQ("InvalidArgument: Item::copy(): newName cannot be empty", j->error().errorString()); |
646 | +} |
647 | + |
648 | +TEST_F(CopyTest, wrong_account) |
649 | +{ |
650 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
651 | + |
652 | + auto test_account = runtime_->make_test_account(service_connection_->baseService(), object_path(), "test_account"); |
653 | + |
654 | + Item root1; |
655 | + { |
656 | + unique_ptr<ItemJob> j(test_account.get("root_id")); |
657 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
658 | + spy.wait(SIGNAL_WAIT_TIME); |
659 | + root1 = j->item(); |
660 | + EXPECT_TRUE(root1.isValid()); |
661 | + } |
662 | + |
663 | + Item root2; |
664 | + { |
665 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
666 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
667 | + spy.wait(SIGNAL_WAIT_TIME); |
668 | + root2 = j->item(); |
669 | + EXPECT_TRUE(root2.isValid()); |
670 | + } |
671 | + |
672 | + Item child; |
673 | + { |
674 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
675 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
676 | + spy.wait(SIGNAL_WAIT_TIME); |
677 | + child = j->item(); |
678 | + EXPECT_TRUE(child.isValid()); |
679 | + } |
680 | + |
681 | + unique_ptr<ItemJob> j(child.copy(root1, "copied_Item")); |
682 | + EXPECT_FALSE(j->isValid()); |
683 | + EXPECT_EQ(ItemJob::Error, j->status()); |
684 | + EXPECT_EQ(StorageError::LogicError, j->error().type()); |
685 | + EXPECT_EQ("LogicError: Item::copy(): source and target must belong to the same account", j->error().errorString()); |
686 | + |
687 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
688 | + spy.wait(SIGNAL_WAIT_TIME); |
689 | + ASSERT_EQ(1, spy.count()); |
690 | + auto arg = spy.takeFirst(); |
691 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
692 | + EXPECT_EQ(ItemJob::Error, status); |
693 | + |
694 | + EXPECT_FALSE(j->isValid()); |
695 | + EXPECT_EQ(ItemJob::Error, j->status()); |
696 | + EXPECT_EQ(StorageError::LogicError, j->error().type()); |
697 | + EXPECT_EQ("LogicError: Item::copy(): source and target must belong to the same account", j->error().errorString()); |
698 | +} |
699 | + |
700 | +TEST_F(CopyTest, wrong_type) |
701 | +{ |
702 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
703 | + |
704 | + Item root; |
705 | + { |
706 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
707 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
708 | + spy.wait(SIGNAL_WAIT_TIME); |
709 | + root = j->item(); |
710 | + } |
711 | + |
712 | + Item child; |
713 | + { |
714 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
715 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
716 | + spy.wait(SIGNAL_WAIT_TIME); |
717 | + child = j->item(); |
718 | + } |
719 | + |
720 | + unique_ptr<ItemJob> j(child.copy(child, "copied_Item")); |
721 | + EXPECT_FALSE(j->isValid()); |
722 | + EXPECT_EQ(ItemJob::Error, j->status()); |
723 | + EXPECT_EQ(StorageError::LogicError, j->error().type()); |
724 | + EXPECT_EQ("LogicError: Item::copy(): newParent cannot be a file", j->error().errorString()) << j->error().errorString().toStdString(); |
725 | + |
726 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
727 | + spy.wait(SIGNAL_WAIT_TIME); |
728 | + ASSERT_EQ(1, spy.count()); |
729 | + auto arg = spy.takeFirst(); |
730 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
731 | + EXPECT_EQ(ItemJob::Error, status); |
732 | + |
733 | + EXPECT_FALSE(j->isValid()); |
734 | + EXPECT_EQ(ItemJob::Error, j->status()); |
735 | + EXPECT_EQ(StorageError::LogicError, j->error().type()); |
736 | + EXPECT_EQ("LogicError: Item::copy(): newParent cannot be a file", j->error().errorString()); |
737 | +} |
738 | + |
739 | +TEST_F(CopyTest, type_mismatch) |
740 | +{ |
741 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("copy_type_mismatch"))); |
742 | + |
743 | + Item root; |
744 | + { |
745 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
746 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
747 | + spy.wait(SIGNAL_WAIT_TIME); |
748 | + root = j->item(); |
749 | + } |
750 | + |
751 | + Item child; |
752 | + { |
753 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
754 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
755 | + spy.wait(SIGNAL_WAIT_TIME); |
756 | + child = j->item(); |
757 | + } |
758 | + |
759 | + unique_ptr<ItemJob> j(child.copy(root, "copied_Item")); |
760 | + EXPECT_TRUE(j->isValid()); |
761 | + |
762 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
763 | + spy.wait(SIGNAL_WAIT_TIME); |
764 | + ASSERT_EQ(1, spy.count()); |
765 | + auto arg = spy.takeFirst(); |
766 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
767 | + EXPECT_EQ(ItemJob::Error, status); |
768 | + |
769 | + EXPECT_FALSE(j->isValid()); |
770 | + EXPECT_EQ(ItemJob::Error, j->status()); |
771 | + EXPECT_EQ(StorageError::LocalCommsError, j->error().type()); |
772 | + EXPECT_EQ("LocalCommsError: Item::copy(): source and target item type differ", j->error().errorString()); |
773 | +} |
774 | + |
775 | +TEST_F(MoveTest, basic) |
776 | +{ |
777 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
778 | + |
779 | + Item root; |
780 | + { |
781 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
782 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
783 | + spy.wait(SIGNAL_WAIT_TIME); |
784 | + root = j->item(); |
785 | + } |
786 | + |
787 | + Item child; |
788 | + { |
789 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
790 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
791 | + spy.wait(SIGNAL_WAIT_TIME); |
792 | + child = j->item(); |
793 | + } |
794 | + |
795 | + unique_ptr<ItemJob> j(child.move(root, "moved_item")); |
796 | + EXPECT_TRUE(j->isValid()); |
797 | + EXPECT_EQ(ItemJob::Loading, j->status()); |
798 | + EXPECT_EQ(StorageError::NoError, j->error().type()); |
799 | + |
800 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
801 | + spy.wait(SIGNAL_WAIT_TIME); |
802 | + ASSERT_EQ(1, spy.count()); |
803 | + auto arg = spy.takeFirst(); |
804 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
805 | + EXPECT_EQ(ItemJob::Finished, status); |
806 | + |
807 | + EXPECT_TRUE(j->isValid()); |
808 | + EXPECT_EQ(ItemJob::Finished, j->status()); |
809 | + EXPECT_EQ(StorageError::NoError, j->error().type()); |
810 | + auto moved_file = j->item(); |
811 | + EXPECT_EQ("child_id", moved_file.itemId()); |
812 | + EXPECT_EQ(root.itemId(), moved_file.parentIds()[0]); |
813 | + EXPECT_EQ("moved_item", moved_file.name()); |
814 | +} |
815 | + |
816 | +TEST_F(MoveTest, invalid) |
817 | +{ |
818 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider())); |
819 | + |
820 | + Item root; |
821 | + { |
822 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
823 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
824 | + spy.wait(SIGNAL_WAIT_TIME); |
825 | + root = j->item(); |
826 | + } |
827 | + |
828 | + Item child; |
829 | + unique_ptr<ItemJob> j(child.move(root, "moved_item")); |
830 | + EXPECT_FALSE(j->isValid()); |
831 | + EXPECT_EQ(ItemJob::Error, j->status()); |
832 | + EXPECT_EQ(StorageError::LogicError, j->error().type()); |
833 | + EXPECT_EQ("LogicError", j->error().name()); |
834 | + EXPECT_EQ("LogicError: Item::move(): cannot create job from invalid item", j->error().errorString()); |
835 | + |
836 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
837 | + spy.wait(SIGNAL_WAIT_TIME); |
838 | + ASSERT_EQ(1, spy.count()); |
839 | + auto arg = spy.takeFirst(); |
840 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
841 | + EXPECT_EQ(ItemJob::Error, status); |
842 | + |
843 | + EXPECT_FALSE(j->isValid()); |
844 | + EXPECT_EQ(ItemJob::Error, j->status()); |
845 | + EXPECT_EQ(StorageError::LogicError, j->error().type()); |
846 | + EXPECT_EQ("LogicError", j->error().name()); |
847 | + EXPECT_EQ("LogicError: Item::move(): cannot create job from invalid item", j->error().errorString()); |
848 | +} |
849 | + |
850 | +TEST_F(MoveTest, root_returned) |
851 | +{ |
852 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("move_returns_root"))); |
853 | + |
854 | + Item root; |
855 | + { |
856 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
857 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
858 | + spy.wait(SIGNAL_WAIT_TIME); |
859 | + root = j->item(); |
860 | + } |
861 | + |
862 | + Item child; |
863 | + { |
864 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
865 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
866 | + spy.wait(SIGNAL_WAIT_TIME); |
867 | + child = j->item(); |
868 | + } |
869 | + |
870 | + unique_ptr<ItemJob> j(child.move(root, "moved_item")); |
871 | + EXPECT_TRUE(j->isValid()); |
872 | + |
873 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
874 | + spy.wait(SIGNAL_WAIT_TIME); |
875 | + ASSERT_EQ(1, spy.count()); |
876 | + auto arg = spy.takeFirst(); |
877 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
878 | + EXPECT_EQ(ItemJob::Error, status); |
879 | + |
880 | + EXPECT_FALSE(j->isValid()); |
881 | + EXPECT_EQ(ItemJob::Error, j->status()); |
882 | + EXPECT_EQ(StorageError::LocalCommsError, j->error().type()); |
883 | + EXPECT_EQ("LocalCommsError", j->error().name()); |
884 | + EXPECT_EQ("LocalCommsError: Item::move(): impossible root item returned by server", j->error().errorString()); |
885 | +} |
886 | + |
887 | +TEST_F(MoveTest, type_mismatch) |
888 | +{ |
889 | + set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("move_type_mismatch"))); |
890 | + |
891 | + Item root; |
892 | + { |
893 | + unique_ptr<ItemJob> j(acc_.get("root_id")); |
894 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
895 | + spy.wait(SIGNAL_WAIT_TIME); |
896 | + root = j->item(); |
897 | + } |
898 | + |
899 | + Item child; |
900 | + { |
901 | + unique_ptr<ItemJob> j(acc_.get("child_id")); |
902 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
903 | + spy.wait(SIGNAL_WAIT_TIME); |
904 | + child = j->item(); |
905 | + } |
906 | + |
907 | + unique_ptr<ItemJob> j(child.move(root, "moved_Item")); |
908 | + EXPECT_TRUE(j->isValid()); |
909 | + |
910 | + QSignalSpy spy(j.get(), &ItemJob::statusChanged); |
911 | + spy.wait(SIGNAL_WAIT_TIME); |
912 | + ASSERT_EQ(1, spy.count()); |
913 | + auto arg = spy.takeFirst(); |
914 | + auto status = qvariant_cast<ItemJob::Status>(arg.at(0)); |
915 | + EXPECT_EQ(ItemJob::Error, status); |
916 | + |
917 | + EXPECT_FALSE(j->isValid()); |
918 | + EXPECT_EQ(ItemJob::Error, j->status()); |
919 | + EXPECT_EQ(StorageError::LocalCommsError, j->error().type()); |
920 | + EXPECT_EQ("LocalCommsError: Item::move(): source and target item type differ", j->error().errorString()); |
921 | +} |
922 | + |
923 | #if 0 |
924 | TEST_F(RootTest, basic) |
925 | { |
PASSED: Continuous integration, rev:90 /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/133/ /jenkins. canonical. com/unity- api-1/job/ build/797 /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/803 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 610 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 610/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 610 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 610/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 610 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 610/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 610 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 610/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 610 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 610/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 610 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 610/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 610 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 610/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 610 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 610/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 610 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 610/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
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: /jenkins. canonical. com/unity- api-1/job/ lp-storage- framework- ci/133/ rebuild
https:/