Merge lp:~michihenning/storage-framework/parents into lp:storage-framework/devel

Proposed by Michi Henning
Status: Merged
Approved by: Michi Henning
Approved revision: 92
Merged at revision: 74
Proposed branch: lp:~michihenning/storage-framework/parents
Merge into: lp:storage-framework/devel
Prerequisite: lp:~michihenning/storage-framework/more-tests
Diff against target: 1841 lines (+1086/-153)
26 files modified
include/unity/storage/internal/ItemMetadata.h (+1/-3)
include/unity/storage/qt/Item.h (+2/-2)
include/unity/storage/qt/ItemListJob.h (+8/-4)
include/unity/storage/qt/internal/Handler.h (+3/-2)
include/unity/storage/qt/internal/ItemImpl.h (+1/-2)
include/unity/storage/qt/internal/ItemJobImpl.h (+5/-5)
include/unity/storage/qt/internal/ItemListJobImpl.h (+8/-20)
include/unity/storage/qt/internal/ListJobImplBase.h (+76/-0)
include/unity/storage/qt/internal/MultiItemJobImpl.h (+68/-0)
include/unity/storage/qt/internal/StorageErrorImpl.h (+2/-0)
include/unity/storage/qt/internal/VoidJobImpl.h (+4/-4)
src/qt/CMakeLists.txt (+4/-0)
src/qt/Item.cpp (+2/-9)
src/qt/ItemListJob.cpp (+2/-1)
src/qt/client/internal/remote_client/ItemImpl.cpp (+8/-1)
src/qt/internal/AccountImpl.cpp (+14/-4)
src/qt/internal/ItemImpl.cpp (+55/-8)
src/qt/internal/ItemJobImpl.cpp (+5/-5)
src/qt/internal/ItemListJobImpl.cpp (+9/-45)
src/qt/internal/ListJobImplBase.cpp (+111/-0)
src/qt/internal/MultiItemJobImpl.cpp (+135/-0)
src/qt/internal/StorageErrorImpl.cpp (+37/-24)
src/qt/internal/VoidJobImpl.cpp (+4/-4)
tests/provider-ProviderInterface/ProviderInterface_test.cpp (+7/-7)
tests/remote-client/MockProvider.cpp (+43/-2)
tests/remote-client/remote-client_test.cpp (+472/-1)
To merge this branch: bzr merge lp:~michihenning/storage-framework/parents
Reviewer Review Type Date Requested Status
unity-api-1-bot continuous-integration Approve
James Henstridge Approve
Review via email: mp+306986@code.launchpad.net

Commit message

Changed ItemMetadata for parent_ids to QList (from QVector).
Added parents() implementation.
Refactored ItemListJobImpl and MultiItemJobImpl to use a base class that does most of the work, so we can create an ItemListJob from both a single invocation that returns a list, and from multiple invocations that return a single item each.
Minor renaming of the make_* factory methods for brevity.
A few minor bug fixes here and there.
Lots more tests.

Description of the change

Changed ItemMetadata for parent_ids to QList (from QVector).
Added parents() implementation.
Refactored ItemListJobImpl and MultiItemJobImpl to use a base class that does most of the work, so we can create an ItemListJob from both a single invocation that returns a list, and from multiple invocations that return a single item each.
Minor renaming of the make_* factory methods for brevity.
A few minor bug fixes here and there.
Lots more tests.

To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:89
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/130/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/781
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/787
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/595
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/595/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/595
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/595/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/595
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/595/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/595
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/595/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/595
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/595/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/595
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/595/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/595
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/595/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/595
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/595/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/595
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/595/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/130/rebuild

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

PASSED: Continuous integration, rev:91
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/136/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/806
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/812
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/618
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/618/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/618
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/618/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/618
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/618/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/618
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/618/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/618
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/618/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/618
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/618/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/618
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/618/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/618
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/618/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/618
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/618/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/136/rebuild

review: Approve (continuous-integration)
Revision history for this message
James Henstridge (jamesh) wrote :

This looks good. I've left a few minor comments that are mostly stylistic in nature rather than issues with the branch. So I'm approving the branch but will leave it up to you to top-approve when you're ready.

review: Approve
Revision history for this message
Michi Henning (michihenning) wrote :

Thanks for the review! I've commented in-line.

Revision history for this message
Michi Henning (michihenning) wrote :

Thanks for the review! I've commented in-line.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:92
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/142/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/847
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/854
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/661
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/661/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/661
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/661/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/661
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/661/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/661
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/661/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/661
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/661/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/661
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/661/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/661
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/661/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/661
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/661/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/661
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/661/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-ci/142/rebuild

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

FAILED: Autolanding.
Unapproved changes made after approval.
https://jenkins.canonical.com/unity-api-1/job/lp-storage-framework-autoland/49/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/848
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/855
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/662
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/662/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/662
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/662/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/662
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/662/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/662
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/662/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/662
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/662/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/662
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/662/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/662
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/662/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/662
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/662/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/662
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/662/artifact/output/*zip*/output.zip

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/unity/storage/internal/ItemMetadata.h'
--- include/unity/storage/internal/ItemMetadata.h 2016-09-16 06:25:08 +0000
+++ include/unity/storage/internal/ItemMetadata.h 2016-10-10 01:18:55 +0000
@@ -24,9 +24,7 @@
24#pragma GCC diagnostic ignored "-Wcast-align"24#pragma GCC diagnostic ignored "-Wcast-align"
25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"25#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
26#pragma GCC diagnostic ignored "-Wswitch-default"26#pragma GCC diagnostic ignored "-Wswitch-default"
27#include <QMap>
28#include <QVariant>27#include <QVariant>
29#include <QVector>
30#pragma GCC diagnostic pop28#pragma GCC diagnostic pop
3129
32namespace unity30namespace unity
@@ -39,7 +37,7 @@
39struct ItemMetadata37struct ItemMetadata
40{38{
41 QString item_id;39 QString item_id;
42 QVector<QString> parent_ids;40 QList<QString> parent_ids;
43 QString name;41 QString name;
44 QString etag;42 QString etag;
45 ItemType type;43 ItemType type;
4644
=== modified file 'include/unity/storage/qt/Item.h'
--- include/unity/storage/qt/Item.h 2016-09-26 08:57:05 +0000
+++ include/unity/storage/qt/Item.h 2016-10-10 01:18:55 +0000
@@ -60,7 +60,7 @@
60 Q_PROPERTY(unity::storage::qt::Item::Type type READ type FINAL)60 Q_PROPERTY(unity::storage::qt::Item::Type type READ type FINAL)
61 Q_PROPERTY(QVariantMap metadata READ metadata FINAL)61 Q_PROPERTY(QVariantMap metadata READ metadata FINAL)
62 Q_PROPERTY(QDateTime lastModifiedTime READ lastModifiedTime FINAL)62 Q_PROPERTY(QDateTime lastModifiedTime READ lastModifiedTime FINAL)
63 Q_PROPERTY(QVector<QString> parentIds READ parentIds FINAL)63 Q_PROPERTY(QList<QString> parentIds READ parentIds FINAL)
6464
65public:65public:
66 Item();66 Item();
@@ -93,7 +93,7 @@
93 Type type() const;93 Type type() const;
94 QVariantMap metadata() const;94 QVariantMap metadata() const;
95 QDateTime lastModifiedTime() const;95 QDateTime lastModifiedTime() const;
96 QVector<QString> parentIds() const; // TODO: should be QList96 QList<QString> parentIds() const;
9797
98 Q_INVOKABLE ItemListJob* parents() const;98 Q_INVOKABLE ItemListJob* parents() const;
99 Q_INVOKABLE ItemJob* copy(Item const& newParent, QString const& newName) const;99 Q_INVOKABLE ItemJob* copy(Item const& newParent, QString const& newName) const;
100100
=== modified file 'include/unity/storage/qt/ItemListJob.h'
--- include/unity/storage/qt/ItemListJob.h 2016-09-26 02:12:30 +0000
+++ include/unity/storage/qt/ItemListJob.h 2016-10-10 01:18:55 +0000
@@ -34,7 +34,9 @@
34namespace internal34namespace internal
35{35{
3636
37class ListJobImplBase;
37class ItemListJobImpl;38class ItemListJobImpl;
39class MultiItemJobImpl;
3840
39} // namespace internal41} // namespace internal
4042
@@ -63,11 +65,13 @@
63 void itemsReady(QList<unity::storage::qt::Item> const& items) const;65 void itemsReady(QList<unity::storage::qt::Item> const& items) const;
6466
65private:67private:
66 ItemListJob(std::unique_ptr<internal::ItemListJobImpl> p);68 ItemListJob(std::unique_ptr<internal::ListJobImplBase> p);
6769
68 std::unique_ptr<internal::ItemListJobImpl> const p_;70 std::unique_ptr<internal::ListJobImplBase> const p_;
6971
72 friend class internal::ListJobImplBase;
70 friend class internal::ItemListJobImpl;73 friend class internal::ItemListJobImpl;
74 friend class internal::MultiItemJobImpl;
71};75};
7276
73} // namespace qt77} // namespace qt
7478
=== modified file 'include/unity/storage/qt/internal/Handler.h'
--- include/unity/storage/qt/internal/Handler.h 2016-09-16 06:25:08 +0000
+++ include/unity/storage/qt/internal/Handler.h 2016-10-10 01:18:55 +0000
@@ -58,7 +58,7 @@
58 {58 {
59 // LCOV_EXCL_START59 // LCOV_EXCL_START
60 QString msg = "impossible provider exception: " + e.errorString();60 QString msg = "impossible provider exception: " + e.errorString();
61 qCritical() << msg;61 qCritical().noquote() << msg;
62 e = StorageErrorImpl::local_comms_error(msg);62 e = StorageErrorImpl::local_comms_error(msg);
63 break;63 break;
64 // LCOV_EXCL_STOP64 // LCOV_EXCL_STOP
@@ -68,7 +68,8 @@
68 case StorageError::ResourceError:68 case StorageError::ResourceError:
69 {69 {
70 // Log these errors because they are unexpected.70 // Log these errors because they are unexpected.
71 qCritical() << "provider exception:" << e.errorString();71 QString msg = "provider exception: " + e.errorString();
72 qCritical().noquote() << msg;
72 break;73 break;
73 }74 }
74 default:75 default:
7576
=== modified file 'include/unity/storage/qt/internal/ItemImpl.h'
--- include/unity/storage/qt/internal/ItemImpl.h 2016-09-26 08:57:05 +0000
+++ include/unity/storage/qt/internal/ItemImpl.h 2016-10-10 01:18:55 +0000
@@ -53,7 +53,7 @@
53 Item::Type type() const;53 Item::Type type() const;
54 QVariantMap metadata() const;54 QVariantMap metadata() const;
55 QDateTime lastModifiedTime() const;55 QDateTime lastModifiedTime() const;
56 QVector<QString> parentIds() const;56 QList<QString> parentIds() const;
5757
58 ItemListJob* parents() const;58 ItemListJob* parents() const;
59 ItemJob* copy(Item const& newParent, QString const& newName) const;59 ItemJob* copy(Item const& newParent, QString const& newName) const;
@@ -89,7 +89,6 @@
89 bool is_valid_;89 bool is_valid_;
90 storage::internal::ItemMetadata md_;90 storage::internal::ItemMetadata md_;
91 std::shared_ptr<AccountImpl> account_;91 std::shared_ptr<AccountImpl> account_;
92 //std::shared_ptr<RootImpl> root_;
9392
94 friend class unity::storage::qt::Item;93 friend class unity::storage::qt::Item;
95};94};
9695
=== modified file 'include/unity/storage/qt/internal/ItemJobImpl.h'
--- include/unity/storage/qt/internal/ItemJobImpl.h 2016-09-26 08:57:05 +0000
+++ include/unity/storage/qt/internal/ItemJobImpl.h 2016-10-10 01:18:55 +0000
@@ -53,11 +53,11 @@
53 StorageError error() const;53 StorageError error() const;
54 Item item() const;54 Item item() const;
5555
56 static ItemJob* make_item_job(std::shared_ptr<AccountImpl> const& account,56 static ItemJob* make_job(std::shared_ptr<AccountImpl> const& account,
57 QString const& method,57 QString const& method,
58 QDBusPendingReply<storage::internal::ItemMetadata> const& reply,58 QDBusPendingReply<storage::internal::ItemMetadata> const& reply,
59 std::function<void(storage::internal::ItemMetadata const&)> const& validate);59 std::function<void(storage::internal::ItemMetadata const&)> const& validate);
60 static ItemJob* make_item_job(StorageError const& e);60 static ItemJob* make_job(StorageError const& e);
6161
62private:62private:
63 ItemJobImpl(std::shared_ptr<AccountImpl> const& account,63 ItemJobImpl(std::shared_ptr<AccountImpl> const& account,
6464
=== modified file 'include/unity/storage/qt/internal/ItemListJobImpl.h'
--- include/unity/storage/qt/internal/ItemListJobImpl.h 2016-09-26 08:57:05 +0000
+++ include/unity/storage/qt/internal/ItemListJobImpl.h 2016-10-10 01:18:55 +0000
@@ -18,10 +18,9 @@
1818
19#pragma once19#pragma once
2020
21#include <unity/storage/qt/internal/ListJobImplBase.h>
21#include <unity/storage/qt/ItemListJob.h>22#include <unity/storage/qt/ItemListJob.h>
2223
23#include <unity/storage/qt/StorageError.h>
24
25#include <QDBusPendingReply>24#include <QDBusPendingReply>
2625
27namespace unity26namespace unity
@@ -42,35 +41,24 @@
4241
43class AccountImpl;42class AccountImpl;
4443
45class ItemListJobImpl : public QObject44class ItemListJobImpl : public ListJobImplBase
46{45{
47 Q_OBJECT46 Q_OBJECT
48public:47public:
49 virtual ~ItemListJobImpl() = default;48 virtual ~ItemListJobImpl() = default;
5049
51 bool isValid() const;50 static ItemListJob* make_job(std::shared_ptr<AccountImpl> const& account,
52 ItemListJob::Status status() const;51 QString const& method,
53 StorageError error() const;52 QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
5453 std::function<void(storage::internal::ItemMetadata const&)> const& validate);
55 static ItemListJob* make_item_list_job(std::shared_ptr<AccountImpl> const& account,54 static ItemListJob* make_job(StorageError const& error);
56 QString const& method,
57 QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
58 std::function<void(storage::internal::ItemMetadata const&)> const& validate);
59 static ItemListJob* make_item_list_job(StorageError const& error);
6055
61private:56private:
57 ItemListJobImpl() = default;
62 ItemListJobImpl(std::shared_ptr<AccountImpl> const& account,58 ItemListJobImpl(std::shared_ptr<AccountImpl> const& account,
63 QString const& method,59 QString const& method,
64 QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,60 QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
65 std::function<void(storage::internal::ItemMetadata const&)> const& validate);61 std::function<void(storage::internal::ItemMetadata const&)> const& validate);
66 ItemListJobImpl(StorageError const& error);
67
68 ItemListJob* public_instance_;
69 ItemListJob::Status status_;
70 StorageError error_;
71 QString method_;
72 std::shared_ptr<AccountImpl> account_;
73 std::function<void(storage::internal::ItemMetadata const&)> validate_;
74};62};
7563
76} // namespace internal64} // namespace internal
7765
=== added file 'include/unity/storage/qt/internal/ListJobImplBase.h'
--- include/unity/storage/qt/internal/ListJobImplBase.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/qt/internal/ListJobImplBase.h 2016-10-10 01:18:55 +0000
@@ -0,0 +1,76 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <unity/storage/qt/ItemListJob.h>
22#include <unity/storage/qt/StorageError.h>
23
24#include <QDBusPendingReply>
25
26namespace unity
27{
28namespace storage
29{
30namespace internal
31{
32
33class ItemMetadata;
34
35} // namespace internal
36
37namespace qt
38{
39namespace internal
40{
41
42class AccountImpl;
43class MultiItemJobImpl;
44
45class ListJobImplBase : public QObject
46{
47public:
48 ListJobImplBase(); // Makes job in Finished state.
49 ListJobImplBase(std::shared_ptr<AccountImpl> const& account,
50 QString const& method,
51 std::function<void(storage::internal::ItemMetadata const&)> const& validate);
52 ListJobImplBase(StorageError const& error);
53 virtual ~ListJobImplBase() = default;
54
55 bool isValid() const;
56 ItemListJob::Status status() const;
57 StorageError error() const;
58
59 void set_public_instance(ItemListJob* p);
60
61 static ItemListJob* make_job(StorageError const& error);
62 static ItemListJob* make_empty_job();
63
64protected:
65 ItemListJob* public_instance_;
66 ItemListJob::Status status_;
67 StorageError error_;
68 QString method_;
69 std::shared_ptr<AccountImpl> account_;
70 std::function<void(storage::internal::ItemMetadata const&)> validate_;
71};
72
73} // namespace internal
74} // namespace qt
75} // namespace storage
76} // namespace unity
077
=== added file 'include/unity/storage/qt/internal/MultiItemJobImpl.h'
--- include/unity/storage/qt/internal/MultiItemJobImpl.h 1970-01-01 00:00:00 +0000
+++ include/unity/storage/qt/internal/MultiItemJobImpl.h 2016-10-10 01:18:55 +0000
@@ -0,0 +1,68 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#pragma once
20
21#include <unity/storage/qt/internal/ListJobImplBase.h>
22#include <unity/storage/qt/ItemListJob.h>
23
24#include <QDBusPendingReply>
25
26namespace unity
27{
28namespace storage
29{
30namespace internal
31{
32
33class ItemMetadata;
34
35} // namespace internal
36
37namespace qt
38{
39namespace internal
40{
41
42class AccountImpl;
43
44class MultiItemJobImpl : public ListJobImplBase
45{
46 Q_OBJECT
47public:
48 virtual ~MultiItemJobImpl() = default;
49
50 static ItemListJob* make_job(std::shared_ptr<AccountImpl> const& account,
51 QString const& method,
52 QList<QDBusPendingReply<storage::internal::ItemMetadata>> const& replies,
53 std::function<void(storage::internal::ItemMetadata const&)> const& validate);
54
55private:
56 MultiItemJobImpl() = default;
57 MultiItemJobImpl(std::shared_ptr<AccountImpl> const& account,
58 QString const& method,
59 QList<QDBusPendingReply<storage::internal::ItemMetadata>> const& replies,
60 std::function<void(storage::internal::ItemMetadata const&)> const& validate);
61
62 int replies_remaining_;
63};
64
65} // namespace internal
66} // namespace qt
67} // namespace storage
68} // namespace unity
069
=== modified file 'include/unity/storage/qt/internal/StorageErrorImpl.h'
--- include/unity/storage/qt/internal/StorageErrorImpl.h 2016-09-16 06:25:08 +0000
+++ include/unity/storage/qt/internal/StorageErrorImpl.h 2016-10-10 01:18:55 +0000
@@ -70,6 +70,8 @@
70 static StorageError resource_error(QString const& msg, int error_code);70 static StorageError resource_error(QString const& msg, int error_code);
7171
72private:72private:
73 StorageErrorImpl(StorageError::Type type);
74
73 StorageError::Type type_;75 StorageError::Type type_;
74 QString name_;76 QString name_;
75 QString message_;77 QString message_;
7678
=== modified file 'include/unity/storage/qt/internal/VoidJobImpl.h'
--- include/unity/storage/qt/internal/VoidJobImpl.h 2016-09-26 22:22:09 +0000
+++ include/unity/storage/qt/internal/VoidJobImpl.h 2016-10-10 01:18:55 +0000
@@ -45,10 +45,10 @@
45 VoidJob::Status status() const;45 VoidJob::Status status() const;
46 StorageError error() const;46 StorageError error() const;
4747
48 static VoidJob* make_void_job(std::shared_ptr<ItemImpl> const& item,48 static VoidJob* make_job(std::shared_ptr<ItemImpl> const& item,
49 QString const& method,49 QString const& method,
50 QDBusPendingReply<void> const& reply);50 QDBusPendingReply<void> const& reply);
51 static VoidJob* make_void_job(StorageError const& e);51 static VoidJob* make_job(StorageError const& e);
5252
53private:53private:
54 VoidJobImpl(std::shared_ptr<ItemImpl> const& item,54 VoidJobImpl(std::shared_ptr<ItemImpl> const& item,
5555
=== modified file 'src/qt/CMakeLists.txt'
--- src/qt/CMakeLists.txt 2016-09-26 08:57:05 +0000
+++ src/qt/CMakeLists.txt 2016-10-10 01:18:55 +0000
@@ -30,6 +30,8 @@
30 internal/ItemImpl.cpp30 internal/ItemImpl.cpp
31 internal/ItemJobImpl.cpp31 internal/ItemJobImpl.cpp
32 internal/ItemListJobImpl.cpp32 internal/ItemListJobImpl.cpp
33 internal/ListJobImplBase.cpp
34 internal/MultiItemJobImpl.cpp
33 internal/RuntimeImpl.cpp35 internal/RuntimeImpl.cpp
34 internal/StorageErrorImpl.cpp36 internal/StorageErrorImpl.cpp
35 internal/unmarshal_error.cpp37 internal/unmarshal_error.cpp
@@ -46,6 +48,8 @@
46 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/HandlerBase.h48 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/HandlerBase.h
47 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/ItemJobImpl.h49 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/ItemJobImpl.h
48 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/ItemListJobImpl.h50 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/ItemListJobImpl.h
51 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/ListJobImplBase.h
52 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/MultiItemJobImpl.h
49 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/VoidJobImpl.h53 ${CMAKE_SOURCE_DIR}/include/unity/storage/qt/internal/VoidJobImpl.h
50)54)
5155
5256
=== modified file 'src/qt/Item.cpp'
--- src/qt/Item.cpp 2016-09-22 01:52:20 +0000
+++ src/qt/Item.cpp 2016-10-10 01:18:55 +0000
@@ -48,6 +48,7 @@
48}48}
4949
50Item::Item(Item&& other)50Item::Item(Item&& other)
51 : p_(make_shared<internal::ItemImpl>())
51{52{
52 p_->is_valid_ = false;53 p_->is_valid_ = false;
53 swap(p_, other.p_);54 swap(p_, other.p_);
@@ -92,14 +93,6 @@
92 return p_->account();93 return p_->account();
93}94}
9495
95#if 0
96Item Item::root() const
97{
98
99 return p_->root();
100}
101#endif
102
103QString Item::etag() const96QString Item::etag() const
104{97{
105 return p_->etag();98 return p_->etag();
@@ -120,7 +113,7 @@
120 return p_->lastModifiedTime();113 return p_->lastModifiedTime();
121}114}
122115
123QVector<QString> Item::parentIds() const116QList<QString> Item::parentIds() const
124{117{
125 return p_->parentIds();118 return p_->parentIds();
126}119}
127120
=== modified file 'src/qt/ItemListJob.cpp'
--- src/qt/ItemListJob.cpp 2016-09-16 06:25:08 +0000
+++ src/qt/ItemListJob.cpp 2016-10-10 01:18:55 +0000
@@ -19,6 +19,7 @@
19#include <unity/storage/qt/ItemListJob.h>19#include <unity/storage/qt/ItemListJob.h>
2020
21#include <unity/storage/qt/internal/ItemListJobImpl.h>21#include <unity/storage/qt/internal/ItemListJobImpl.h>
22#include <unity/storage/qt/internal/MultiItemJobImpl.h>
2223
23using namespace unity::storage::qt;24using namespace unity::storage::qt;
24using namespace std;25using namespace std;
@@ -30,7 +31,7 @@
30namespace qt31namespace qt
31{32{
3233
33ItemListJob::ItemListJob(unique_ptr<internal::ItemListJobImpl> p)34ItemListJob::ItemListJob(unique_ptr<internal::ListJobImplBase> p)
34 : p_(move(p))35 : p_(move(p))
35{36{
36}37}
3738
=== modified file 'src/qt/client/internal/remote_client/ItemImpl.cpp'
--- src/qt/client/internal/remote_client/ItemImpl.cpp 2016-08-26 04:45:56 +0000
+++ src/qt/client/internal/remote_client/ItemImpl.cpp 2016-10-10 01:18:55 +0000
@@ -217,7 +217,14 @@
217{217{
218 throw_if_destroyed("Item::parent_ids()");218 throw_if_destroyed("Item::parent_ids()");
219 // TODO, need different metadata representation, affects xml219 // TODO, need different metadata representation, affects xml
220 return md_.parent_ids;220 // We changed ItemMetadata to contain a QList for the v2 API,
221 // so we copy here.
222 QVector<QString> ids;
223 for (auto const& id : md_.parent_ids)
224 {
225 ids.append(id);
226 }
227 return ids;
221}228}
222229
223QFuture<void> ItemImpl::delete_item()230QFuture<void> ItemImpl::delete_item()
224231
=== modified file 'src/qt/internal/AccountImpl.cpp'
--- src/qt/internal/AccountImpl.cpp 2016-09-26 08:57:05 +0000
+++ src/qt/internal/AccountImpl.cpp 2016-10-10 01:18:55 +0000
@@ -86,10 +86,15 @@
86 QString const method = "Account::roots()";86 QString const method = "Account::roots()";
8787
88 auto runtime = runtime_.lock();88 auto runtime = runtime_.lock();
89 if (!is_valid_)
90 {
91 auto e = StorageErrorImpl::logic_error(method + ": cannot create job from invalid account");
92 return ItemListJobImpl::make_job(e);
93 }
89 if (!runtime || !runtime->isValid())94 if (!runtime || !runtime->isValid())
90 {95 {
91 auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously");96 auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously");
92 return ItemListJobImpl::make_item_list_job(e);97 return ItemListJobImpl::make_job(e);
93 }98 }
9499
95 auto validate = [method](storage::internal::ItemMetadata const& md)100 auto validate = [method](storage::internal::ItemMetadata const& md)
@@ -104,18 +109,23 @@
104109
105 auto reply = provider_->Roots();110 auto reply = provider_->Roots();
106 auto This = const_pointer_cast<AccountImpl>(shared_from_this());111 auto This = const_pointer_cast<AccountImpl>(shared_from_this());
107 return ItemListJobImpl::make_item_list_job(This, method, reply, validate);112 return ItemListJobImpl::make_job(This, method, reply, validate);
108}113}
109114
110ItemJob* AccountImpl::get(QString const& itemId) const115ItemJob* AccountImpl::get(QString const& itemId) const
111{116{
112 QString const method = "Account::get()";117 QString const method = "Account::get()";
113118
119 if (!is_valid_)
120 {
121 auto e = StorageErrorImpl::logic_error(method + ": cannot create job from invalid account");
122 return ItemJobImpl::make_job(e);
123 }
114 auto runtime = runtime_.lock();124 auto runtime = runtime_.lock();
115 if (!runtime || !runtime->isValid())125 if (!runtime || !runtime->isValid())
116 {126 {
117 auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously");127 auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously");
118 return ItemJobImpl::make_item_job(e);128 return ItemJobImpl::make_job(e);
119 }129 }
120130
121 // LCOV_EXCL_START131 // LCOV_EXCL_START
@@ -126,7 +136,7 @@
126136
127 auto reply = provider_->Metadata(itemId);137 auto reply = provider_->Metadata(itemId);
128 auto This = const_pointer_cast<AccountImpl>(shared_from_this());138 auto This = const_pointer_cast<AccountImpl>(shared_from_this());
129 return ItemJobImpl::make_item_job(This, method, reply, validate);139 return ItemJobImpl::make_job(This, method, reply, validate);
130}140}
131141
132bool AccountImpl::operator==(AccountImpl const& other) const142bool AccountImpl::operator==(AccountImpl const& other) const
133143
=== modified file 'src/qt/internal/ItemImpl.cpp'
--- src/qt/internal/ItemImpl.cpp 2016-09-26 08:57:05 +0000
+++ src/qt/internal/ItemImpl.cpp 2016-10-10 01:18:55 +0000
@@ -22,6 +22,8 @@
22#include <unity/storage/provider/metadata_keys.h>22#include <unity/storage/provider/metadata_keys.h>
23#include <unity/storage/qt/internal/AccountImpl.h>23#include <unity/storage/qt/internal/AccountImpl.h>
24#include <unity/storage/qt/internal/ItemJobImpl.h>24#include <unity/storage/qt/internal/ItemJobImpl.h>
25#include <unity/storage/qt/internal/ItemListJobImpl.h>
26#include <unity/storage/qt/internal/MultiItemJobImpl.h>
25#include <unity/storage/qt/internal/RuntimeImpl.h>27#include <unity/storage/qt/internal/RuntimeImpl.h>
26#include <unity/storage/qt/internal/StorageErrorImpl.h>28#include <unity/storage/qt/internal/StorageErrorImpl.h>
27#include <unity/storage/qt/internal/VoidJobImpl.h>29#include <unity/storage/qt/internal/VoidJobImpl.h>
@@ -104,14 +106,56 @@
104 : QDateTime();106 : QDateTime();
105}107}
106108
107QVector<QString> ItemImpl::parentIds() const109QList<QString> ItemImpl::parentIds() const
108{110{
109 return is_valid_ ? md_.parent_ids : QVector<QString>();111 if (!is_valid_ || md_.type == storage::ItemType::root)
112 {
113 return QList<QString>();
114 }
115 return md_.parent_ids;
110}116}
111117
112ItemListJob* ItemImpl::parents() const118ItemListJob* ItemImpl::parents() const
113{119{
114 return nullptr; // TODO120 QString const method = "Item::parents()";
121
122 if (!is_valid_)
123 {
124 auto e = StorageErrorImpl::logic_error(method + ": cannot create job from invalid item");
125 return ListJobImplBase::make_job(e);
126 }
127 auto runtime = account_->runtime();
128 if (!runtime || !runtime->isValid())
129 {
130 auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously");
131 return ListJobImplBase::make_job(e);
132 }
133
134 if (md_.type == storage::ItemType::root)
135 {
136 return ListJobImplBase::make_empty_job(); // Root has no parents.
137 }
138
139 assert(!md_.parent_ids.isEmpty());
140
141 QList<QDBusPendingReply<storage::internal::ItemMetadata>> replies;
142 for (auto const& id : md_.parent_ids)
143 {
144 auto reply = account_->provider()->Metadata(id);
145 replies.append(reply);
146 }
147
148 auto validate = [method](storage::internal::ItemMetadata const& md)
149 {
150 if (md.type == ItemType::file)
151 {
152 QString msg = method + ": provider returned a file as a parent";
153 qCritical() << msg;
154 throw StorageErrorImpl::local_comms_error(msg);
155 }
156 };
157
158 return MultiItemJobImpl::make_job(account_, method, replies, validate);
115}159}
116160
117ItemJob* ItemImpl::copy(Item const& newParent, QString const& newName) const161ItemJob* ItemImpl::copy(Item const& newParent, QString const& newName) const
@@ -128,23 +172,26 @@
128{172{
129 QString const method = "Item::deleteItem()";173 QString const method = "Item::deleteItem()";
130174
131 assert(account_);175 if (!is_valid_)
176 {
177 auto e = StorageErrorImpl::logic_error(method + ": cannot create job from invalid item");
178 return VoidJobImpl::make_job(e);
179 }
132 auto runtime = account_->runtime();180 auto runtime = account_->runtime();
133 if (!runtime || !runtime->isValid())181 if (!runtime || !runtime->isValid())
134 {182 {
135 auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously");183 auto e = StorageErrorImpl::runtime_destroyed_error(method + ": Runtime was destroyed previously");
136 return VoidJobImpl::make_void_job(e);184 return VoidJobImpl::make_job(e);
137 }185 }
138
139 if (md_.type == storage::ItemType::root)186 if (md_.type == storage::ItemType::root)
140 {187 {
141 auto e = StorageErrorImpl::logic_error(method + ": cannot delete root");188 auto e = StorageErrorImpl::logic_error(method + ": cannot delete root");
142 return VoidJobImpl::make_void_job(e);189 return VoidJobImpl::make_job(e);
143 }190 }
144191
145 auto reply = account_->provider()->Delete(md_.item_id);192 auto reply = account_->provider()->Delete(md_.item_id);
146 auto This = const_pointer_cast<ItemImpl>(shared_from_this());193 auto This = const_pointer_cast<ItemImpl>(shared_from_this());
147 return VoidJobImpl::make_void_job(This, method, reply);194 return VoidJobImpl::make_job(This, method, reply);
148}195}
149196
150Uploader* ItemImpl::createUploader(Item::ConflictPolicy policy, qint64 sizeInBytes) const197Uploader* ItemImpl::createUploader(Item::ConflictPolicy policy, qint64 sizeInBytes) const
151198
=== modified file 'src/qt/internal/ItemJobImpl.cpp'
--- src/qt/internal/ItemJobImpl.cpp 2016-09-26 08:57:05 +0000
+++ src/qt/internal/ItemJobImpl.cpp 2016-10-10 01:18:55 +0000
@@ -112,10 +112,10 @@
112 return item_;112 return item_;
113}113}
114114
115ItemJob* ItemJobImpl::make_item_job(shared_ptr<AccountImpl> const& account,115ItemJob* ItemJobImpl::make_job(shared_ptr<AccountImpl> const& account,
116 QString const& method,116 QString const& method,
117 QDBusPendingReply<storage::internal::ItemMetadata> const& reply,117 QDBusPendingReply<storage::internal::ItemMetadata> const& reply,
118 std::function<void(storage::internal::ItemMetadata const&)> const& validate)118 std::function<void(storage::internal::ItemMetadata const&)> const& validate)
119{119{
120 unique_ptr<ItemJobImpl> impl(new ItemJobImpl(account, method, reply, validate));120 unique_ptr<ItemJobImpl> impl(new ItemJobImpl(account, method, reply, validate));
121 auto job = new ItemJob(move(impl));121 auto job = new ItemJob(move(impl));
@@ -123,7 +123,7 @@
123 return job;123 return job;
124}124}
125125
126ItemJob* ItemJobImpl::make_item_job(StorageError const& error)126ItemJob* ItemJobImpl::make_job(StorageError const& error)
127{127{
128 unique_ptr<ItemJobImpl> impl(new ItemJobImpl(error));128 unique_ptr<ItemJobImpl> impl(new ItemJobImpl(error));
129 auto job = new ItemJob(move(impl));129 auto job = new ItemJob(move(impl));
130130
=== modified file 'src/qt/internal/ItemListJobImpl.cpp'
--- src/qt/internal/ItemListJobImpl.cpp 2016-09-26 08:57:05 +0000
+++ src/qt/internal/ItemListJobImpl.cpp 2016-10-10 01:18:55 +0000
@@ -19,7 +19,6 @@
19#include <unity/storage/qt/internal/ItemListJobImpl.h>19#include <unity/storage/qt/internal/ItemListJobImpl.h>
2020
21#include <unity/storage/internal/dbusmarshal.h>21#include <unity/storage/internal/dbusmarshal.h>
22#include <unity/storage/internal/ItemMetadata.h>
23#include <unity/storage/qt/internal/AccountImpl.h>22#include <unity/storage/qt/internal/AccountImpl.h>
24#include <unity/storage/qt/internal/Handler.h>23#include <unity/storage/qt/internal/Handler.h>
25#include <unity/storage/qt/internal/ItemImpl.h>24#include <unity/storage/qt/internal/ItemImpl.h>
@@ -40,15 +39,8 @@
40 QString const& method,39 QString const& method,
41 QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,40 QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
42 std::function<void(storage::internal::ItemMetadata const&)> const& validate)41 std::function<void(storage::internal::ItemMetadata const&)> const& validate)
43 : status_(ItemListJob::Loading)42 : ListJobImplBase(account, method, validate)
44 , method_(method)
45 , account_(account)
46 , validate_(validate)
47{43{
48 assert(!method.isEmpty());
49 assert(account);
50 assert(validate);
51
52 auto process_reply = [this](decltype(reply)& r)44 auto process_reply = [this](decltype(reply)& r)
53 {45 {
54 auto runtime = account_->runtime();46 auto runtime = account_->runtime();
@@ -82,6 +74,7 @@
8274
83 auto process_error = [this](StorageError const& error)75 auto process_error = [this](StorageError const& error)
84 {76 {
77 // TODO: method name is not being set this way.
85 error_ = error;78 error_ = error;
86 status_ = ItemListJob::Error;79 status_ = ItemListJob::Error;
87 Q_EMIT public_instance_->statusChanged(status_);80 Q_EMIT public_instance_->statusChanged(status_);
@@ -90,49 +83,20 @@
90 new Handler<QList<storage::internal::ItemMetadata>>(this, reply, process_reply, process_error);83 new Handler<QList<storage::internal::ItemMetadata>>(this, reply, process_reply, process_error);
91}84}
9285
93ItemListJobImpl::ItemListJobImpl(StorageError const& error)86ItemListJob* ItemListJobImpl::make_job(shared_ptr<AccountImpl> const& account,
94 : status_(ItemListJob::Error)87 QString const& method,
95 , error_(error)88 QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
96{89 std::function<void(storage::internal::ItemMetadata const&)> const& validate)
97}
98
99bool ItemListJobImpl::isValid() const
100{
101 return status_ != ItemListJob::Status::Error;
102}
103
104ItemListJob::Status ItemListJobImpl::status() const
105{
106 return status_;
107}
108
109StorageError ItemListJobImpl::error() const
110{
111 return error_;
112}
113
114ItemListJob* ItemListJobImpl::make_item_list_job(
115 shared_ptr<AccountImpl> const& account,
116 QString const& method,
117 QDBusPendingReply<QList<storage::internal::ItemMetadata>> const& reply,
118 std::function<void(storage::internal::ItemMetadata const&)> const& validate)
119{90{
120 unique_ptr<ItemListJobImpl> impl(new ItemListJobImpl(account, method, reply, validate));91 unique_ptr<ItemListJobImpl> impl(new ItemListJobImpl(account, method, reply, validate));
121 auto job = new ItemListJob(move(impl));92 auto job = new ItemListJob(move(impl));
122 job->p_->public_instance_ = job;93 job->p_->set_public_instance(job);
123 return job;94 return job;
124}95}
12596
126ItemListJob* ItemListJobImpl::make_item_list_job(StorageError const& error)97ItemListJob* ItemListJobImpl::make_job(StorageError const& error)
127{98{
128 unique_ptr<ItemListJobImpl> impl(new ItemListJobImpl(error));99 return ListJobImplBase::make_job(error);
129 auto job = new ItemListJob(move(impl));
130 job->p_->public_instance_ = job;
131 QMetaObject::invokeMethod(job,
132 "statusChanged",
133 Qt::QueuedConnection,
134 Q_ARG(unity::storage::qt::ItemListJob::Status, job->p_->status_));
135 return job;
136}100}
137101
138} // namespace internal102} // namespace internal
139103
=== added file 'src/qt/internal/ListJobImplBase.cpp'
--- src/qt/internal/ListJobImplBase.cpp 1970-01-01 00:00:00 +0000
+++ src/qt/internal/ListJobImplBase.cpp 2016-10-10 01:18:55 +0000
@@ -0,0 +1,111 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#include <unity/storage/qt/internal/ListJobImplBase.h>
20
21#include <unity/storage/internal/dbusmarshal.h>
22#include <unity/storage/internal/ItemMetadata.h>
23#include <unity/storage/qt/internal/AccountImpl.h>
24#include <unity/storage/qt/internal/Handler.h>
25#include <unity/storage/qt/internal/ItemImpl.h>
26#include <unity/storage/qt/internal/RuntimeImpl.h>
27
28using namespace std;
29
30namespace unity
31{
32namespace storage
33{
34namespace qt
35{
36namespace internal
37{
38
39ListJobImplBase::ListJobImplBase()
40 : status_(ItemListJob::Finished)
41{
42}
43
44ListJobImplBase::ListJobImplBase(shared_ptr<AccountImpl> const& account,
45 QString const& method,
46 std::function<void(storage::internal::ItemMetadata const&)> const& validate)
47 : status_(ItemListJob::Loading)
48 , method_(method)
49 , account_(account)
50 , validate_(validate)
51{
52 assert(!method.isEmpty());
53 assert(account);
54 assert(validate);
55}
56
57ListJobImplBase::ListJobImplBase(StorageError const& error)
58 : status_(ItemListJob::Error)
59 , error_(error)
60{
61}
62
63bool ListJobImplBase::isValid() const
64{
65 return status_ != ItemListJob::Status::Error;
66}
67
68ItemListJob::Status ListJobImplBase::status() const
69{
70 return status_;
71}
72
73StorageError ListJobImplBase::error() const
74{
75 return error_;
76}
77
78void ListJobImplBase::set_public_instance(ItemListJob* p)
79{
80 assert(p);
81 public_instance_ = p;
82}
83
84ItemListJob* ListJobImplBase::make_job(StorageError const& error)
85{
86 unique_ptr<ListJobImplBase> impl(new ListJobImplBase(error));
87 auto job = new ItemListJob(move(impl));
88 job->p_->public_instance_ = job;
89 QMetaObject::invokeMethod(job,
90 "statusChanged",
91 Qt::QueuedConnection,
92 Q_ARG(unity::storage::qt::ItemListJob::Status, job->status()));
93 return job;
94}
95
96ItemListJob* ListJobImplBase::make_empty_job()
97{
98 unique_ptr<ListJobImplBase> impl(new ListJobImplBase());
99 auto job = new ItemListJob(move(impl));
100 job->p_->public_instance_ = job;
101 QMetaObject::invokeMethod(job,
102 "statusChanged",
103 Qt::QueuedConnection,
104 Q_ARG(unity::storage::qt::ItemListJob::Status, job->status()));
105 return job;
106}
107
108} // namespace internal
109} // namespace qt
110} // namespace storage
111} // namespace unity
0112
=== added file 'src/qt/internal/MultiItemJobImpl.cpp'
--- src/qt/internal/MultiItemJobImpl.cpp 1970-01-01 00:00:00 +0000
+++ src/qt/internal/MultiItemJobImpl.cpp 2016-10-10 01:18:55 +0000
@@ -0,0 +1,135 @@
1/*
2 * Copyright (C) 2016 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michi Henning <michi.henning@canonical.com>
17 */
18
19#include <unity/storage/qt/internal/MultiItemJobImpl.h>
20
21#include <unity/storage/internal/dbusmarshal.h>
22#include <unity/storage/qt/internal/AccountImpl.h>
23#include <unity/storage/qt/internal/Handler.h>
24#include <unity/storage/qt/internal/ItemImpl.h>
25#include <unity/storage/qt/internal/RuntimeImpl.h>
26
27using namespace std;
28
29namespace unity
30{
31namespace storage
32{
33namespace qt
34{
35namespace internal
36{
37
38MultiItemJobImpl::MultiItemJobImpl(shared_ptr<AccountImpl> const& account,
39 QString const& method,
40 QList<QDBusPendingReply<storage::internal::ItemMetadata>> const& replies,
41 std::function<void(storage::internal::ItemMetadata const&)> const& validate)
42 : ListJobImplBase(account, method, validate)
43 , replies_remaining_(replies.size())
44{
45 assert(!method.isEmpty());
46 assert(account);
47 assert(validate);
48
49 // We ask the provider for the metadata for each of this item's parents.
50 // As the replies trickle in, we track when the last reply has arrived and
51 // signal that the job is complete.
52 // If anything goes wrong at all, we report the first error and then ignore all
53 // other replies.
54
55 auto process_reply = [this](QDBusPendingReply<storage::internal::ItemMetadata> const& r)
56 {
57 assert(status_ != ItemListJob::Finished);
58
59 --replies_remaining_;
60
61 if (status_ == ItemListJob::Error)
62 {
63 return;
64 }
65
66 auto runtime = account_->runtime();
67 if (!runtime || !runtime->isValid())
68 {
69 error_ = StorageErrorImpl::runtime_destroyed_error(method_ + ": Runtime was destroyed previously");
70 status_ = ItemListJob::Error;
71 Q_EMIT public_instance_->statusChanged(status_);
72 return;
73 }
74
75 auto metadata = r.value();
76 Item item;
77 try
78 {
79 validate_(metadata);
80 item = ItemImpl::make_item(method_, metadata, account_);
81 }
82 catch (StorageError const& e)
83 {
84 // Bad metadata received from provider, validate_() or make_item() have logged it.
85 status_ = ItemListJob::Error;
86 error_ = e;
87 Q_EMIT public_instance_->statusChanged(status_);
88 return;
89 }
90 QList<Item> items;
91 items.append(item);
92 Q_EMIT public_instance_->itemsReady(items);
93
94 if (replies_remaining_ == 0)
95 {
96 status_ = ItemListJob::Finished;
97 Q_EMIT public_instance_->statusChanged(status_);
98 }
99 };
100
101 auto process_error = [this](StorageError const& error)
102 {
103 assert(status_ != ItemListJob::Finished);
104
105 if (status_ == ItemListJob::Error)
106 {
107 return;
108 }
109 // TODO: method name is not being set this way.
110 error_ = error;
111 status_ = ItemListJob::Error;
112 Q_EMIT public_instance_->statusChanged(status_);
113 };
114
115 for (auto const& reply : replies)
116 {
117 new Handler<storage::internal::ItemMetadata>(this, reply, process_reply, process_error);
118 }
119}
120
121ItemListJob* MultiItemJobImpl::make_job(shared_ptr<AccountImpl> const& account,
122 QString const& method,
123 QList<QDBusPendingReply<storage::internal::ItemMetadata>> const& replies,
124 std::function<void(storage::internal::ItemMetadata const&)> const& validate)
125{
126 unique_ptr<MultiItemJobImpl> impl(new MultiItemJobImpl(account, method, replies, validate));
127 auto job = new ItemListJob(move(impl));
128 job->p_->set_public_instance(job);
129 return job;
130}
131
132} // namespace internal
133} // namespace qt
134} // namespace storage
135} // namespace unity
0136
=== modified file 'src/qt/internal/StorageErrorImpl.cpp'
--- src/qt/internal/StorageErrorImpl.cpp 2016-09-16 06:25:08 +0000
+++ src/qt/internal/StorageErrorImpl.cpp 2016-10-10 01:18:55 +0000
@@ -35,27 +35,40 @@
35namespace35namespace
36{36{
3737
38static char const * const ERROR_NAMES[StorageError::__LAST_STORAGE_ERROR] =38static const QString ERROR_NAMES[StorageError::__LAST_STORAGE_ERROR] =
39{39{
40 "NoError", "LocalCommsError", "RemoteCommsError", "Deleted", "RuntimeDestroyed", "NotExists",40 QStringLiteral("NoError"),
41 "Exists", "Conflict", "PermissionDenied", "Cancelled", "LogicError", "InvalidArgument", "ResourceError"41 QStringLiteral("LocalCommsError"),
42 QStringLiteral("RemoteCommsError"),
43 QStringLiteral("Deleted"),
44 QStringLiteral("RuntimeDestroyed"),
45 QStringLiteral("NotExists"),
46 QStringLiteral("Exists"),
47 QStringLiteral("Conflict"),
48 QStringLiteral("PermissionDenied"),
49 QStringLiteral("Cancelled"),
50 QStringLiteral("LogicError"),
51 QStringLiteral("InvalidArgument"),
52 QStringLiteral("ResourceError")
42};53};
4354
44} // namespace55} // namespace
4556
57StorageErrorImpl::StorageErrorImpl(StorageError::Type type)
58 : type_(type)
59 , name_(ERROR_NAMES[type_])
60 , error_code_(0)
61{
62}
63
46StorageErrorImpl::StorageErrorImpl()64StorageErrorImpl::StorageErrorImpl()
47 : type_(StorageError::Type::NoError)65 : StorageErrorImpl(StorageError::Type::NoError)
48 , name_(ERROR_NAMES[type_])
49 , message_("No error")
50 , error_code_(0)
51{66{
67 message_ = "No error";
52}68}
5369
54StorageErrorImpl::StorageErrorImpl(StorageError::Type type, QString const& msg)70StorageErrorImpl::StorageErrorImpl(StorageError::Type type, QString const& msg)
55 : type_(type)71 : StorageErrorImpl(type)
56 , name_(ERROR_NAMES[type_])
57 , message_(msg)
58 , error_code_(0)
59{72{
60 assert( type == StorageError::Type::LocalCommsError73 assert( type == StorageError::Type::LocalCommsError
61 || type == StorageError::Type::RemoteCommsError74 || type == StorageError::Type::RemoteCommsError
@@ -66,18 +79,18 @@
66 || type == StorageError::Type::LogicError79 || type == StorageError::Type::LogicError
67 || type == StorageError::Type::InvalidArgument);80 || type == StorageError::Type::InvalidArgument);
68 assert(!msg.isEmpty());81 assert(!msg.isEmpty());
82
83 message_ = msg;
69}84}
7085
71StorageErrorImpl::StorageErrorImpl(StorageError::Type type, QString const& msg, QString const& key)86StorageErrorImpl::StorageErrorImpl(StorageError::Type type, QString const& msg, QString const& key)
72 : type_(type)87 : StorageErrorImpl(type)
73 , name_(ERROR_NAMES[type_])
74 , message_(msg)
75 , error_code_(0)
76{88{
77 assert( type == StorageError::Type::Deleted89 assert( type == StorageError::Type::Deleted
78 || type == StorageError::Type::NotExists);90 || type == StorageError::Type::NotExists);
79 assert(!msg.isEmpty());91 assert(!msg.isEmpty());
8092
93 message_ = msg;
81 item_id_ = key;94 item_id_ = key;
82 if (type == StorageError::Type::NotExists)95 if (type == StorageError::Type::NotExists)
83 {96 {
@@ -89,26 +102,26 @@
89 QString const& msg,102 QString const& msg,
90 QString const& item_id,103 QString const& item_id,
91 QString const& item_name)104 QString const& item_name)
92 : type_(type)105 : StorageErrorImpl(type)
93 , name_(ERROR_NAMES[type_])
94 , message_(msg)
95 , item_id_(item_id)
96 , item_name_(item_name)
97 , error_code_(0)
98{106{
99 assert(type == StorageError::Type::Exists);107 assert(type == StorageError::Type::Exists);
100 assert(!msg.isEmpty());108 assert(!msg.isEmpty());
101 assert(!item_id.isEmpty());109 assert(!item_id.isEmpty());
102 assert(!item_name.isEmpty());110 assert(!item_name.isEmpty());
111
112 message_ = msg;
113 item_id_ = item_id;
114 item_name_ = item_name;
103}115}
104116
105StorageErrorImpl::StorageErrorImpl(StorageError::Type type, QString const& msg, int error_code)117StorageErrorImpl::StorageErrorImpl(StorageError::Type type, QString const& msg, int error_code)
106 : type_(type)118 : StorageErrorImpl(type)
107 , message_(msg)
108 , error_code_(error_code)
109{119{
110 assert(type == StorageError::Type::ResourceError);120 assert(type == StorageError::Type::ResourceError);
111 assert(!msg.isEmpty());121 assert(!msg.isEmpty());
122
123 message_ = msg;
124 error_code_ = error_code;
112}125}
113126
114StorageError::Type StorageErrorImpl::type() const127StorageError::Type StorageErrorImpl::type() const
115128
=== modified file 'src/qt/internal/VoidJobImpl.cpp'
--- src/qt/internal/VoidJobImpl.cpp 2016-09-26 08:57:05 +0000
+++ src/qt/internal/VoidJobImpl.cpp 2016-10-10 01:18:55 +0000
@@ -89,9 +89,9 @@
89 return error_;89 return error_;
90}90}
9191
92VoidJob* VoidJobImpl::make_void_job(shared_ptr<ItemImpl> const& item,92VoidJob* VoidJobImpl::make_job(shared_ptr<ItemImpl> const& item,
93 QString const& method,93 QString const& method,
94 QDBusPendingReply<void> const& reply)94 QDBusPendingReply<void> const& reply)
95{95{
96 unique_ptr<VoidJobImpl> impl(new VoidJobImpl(item, method, reply));96 unique_ptr<VoidJobImpl> impl(new VoidJobImpl(item, method, reply));
97 auto job = new VoidJob(move(impl));97 auto job = new VoidJob(move(impl));
@@ -99,7 +99,7 @@
99 return job;99 return job;
100}100}
101101
102VoidJob* VoidJobImpl::make_void_job(StorageError const& error)102VoidJob* VoidJobImpl::make_job(StorageError const& error)
103{103{
104 unique_ptr<VoidJobImpl> impl(new VoidJobImpl(error));104 unique_ptr<VoidJobImpl> impl(new VoidJobImpl(error));
105 auto job = new VoidJob(move(impl));105 auto job = new VoidJob(move(impl));
106106
=== modified file 'tests/provider-ProviderInterface/ProviderInterface_test.cpp'
--- tests/provider-ProviderInterface/ProviderInterface_test.cpp 2016-09-26 02:37:03 +0000
+++ tests/provider-ProviderInterface/ProviderInterface_test.cpp 2016-10-10 01:18:55 +0000
@@ -91,7 +91,7 @@
91 EXPECT_EQ(1, reply.value().size());91 EXPECT_EQ(1, reply.value().size());
92 auto root = reply.value()[0];92 auto root = reply.value()[0];
93 EXPECT_EQ("root_id", root.item_id);93 EXPECT_EQ("root_id", root.item_id);
94 EXPECT_EQ(QVector<QString>(), root.parent_ids);94 EXPECT_EQ(QList<QString>(), root.parent_ids);
95 EXPECT_EQ("Root", root.name);95 EXPECT_EQ("Root", root.name);
96 EXPECT_EQ("etag", root.etag);96 EXPECT_EQ("etag", root.etag);
97 EXPECT_EQ(ItemType::root, root.type);97 EXPECT_EQ(ItemType::root, root.type);
@@ -146,7 +146,7 @@
146 ASSERT_EQ(1, items.size());146 ASSERT_EQ(1, items.size());
147 auto item = items[0];147 auto item = items[0];
148 EXPECT_EQ("child_id", item.item_id);148 EXPECT_EQ("child_id", item.item_id);
149 EXPECT_EQ(QVector<QString>{ "root_id"}, item.parent_ids);149 EXPECT_EQ(QList<QString>{ "root_id"}, item.parent_ids);
150 EXPECT_EQ("Filename", item.name);150 EXPECT_EQ("Filename", item.name);
151 EXPECT_EQ(ItemType::file, item.type);151 EXPECT_EQ(ItemType::file, item.type);
152}152}
@@ -160,7 +160,7 @@
160 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();160 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();
161 auto item = reply.value();161 auto item = reply.value();
162 EXPECT_EQ("root_id", item.item_id);162 EXPECT_EQ("root_id", item.item_id);
163 EXPECT_EQ(QVector<QString>(), item.parent_ids);163 EXPECT_EQ(QList<QString>(), item.parent_ids);
164 EXPECT_EQ("Root", item.name);164 EXPECT_EQ("Root", item.name);
165 EXPECT_EQ(ItemType::root, item.type);165 EXPECT_EQ(ItemType::root, item.type);
166}166}
@@ -174,7 +174,7 @@
174 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();174 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();
175 auto item = reply.value();175 auto item = reply.value();
176 EXPECT_EQ("new_folder_id", item.item_id);176 EXPECT_EQ("new_folder_id", item.item_id);
177 EXPECT_EQ(QVector<QString>{ "root_id" }, item.parent_ids);177 EXPECT_EQ(QList<QString>{ "root_id" }, item.parent_ids);
178 EXPECT_EQ("New Folder", item.name);178 EXPECT_EQ("New Folder", item.name);
179 EXPECT_EQ(ItemType::folder, item.type);179 EXPECT_EQ(ItemType::folder, item.type);
180}180}
@@ -224,7 +224,7 @@
224 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();224 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();
225 auto item = reply.value();225 auto item = reply.value();
226 EXPECT_EQ("new_file_id", item.item_id);226 EXPECT_EQ("new_file_id", item.item_id);
227 EXPECT_EQ(QVector<QString>{ "parent_id" }, item.parent_ids);227 EXPECT_EQ(QList<QString>{ "parent_id" }, item.parent_ids);
228 EXPECT_EQ("file name", item.name);228 EXPECT_EQ("file name", item.name);
229}229}
230230
@@ -761,7 +761,7 @@
761 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();761 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();
762 auto item = reply.value();762 auto item = reply.value();
763 EXPECT_EQ("child_id", item.item_id);763 EXPECT_EQ("child_id", item.item_id);
764 EXPECT_EQ(QVector<QString>{ "new_parent_id" }, item.parent_ids);764 EXPECT_EQ(QList<QString>{ "new_parent_id" }, item.parent_ids);
765 EXPECT_EQ("New name", item.name);765 EXPECT_EQ("New name", item.name);
766 EXPECT_EQ(ItemType::file, item.type);766 EXPECT_EQ(ItemType::file, item.type);
767}767}
@@ -775,7 +775,7 @@
775 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();775 ASSERT_TRUE(reply.isValid()) << reply.error().message().toStdString();
776 auto item = reply.value();776 auto item = reply.value();
777 EXPECT_EQ("new_id", item.item_id);777 EXPECT_EQ("new_id", item.item_id);
778 EXPECT_EQ(QVector<QString>{ "new_parent_id" }, item.parent_ids);778 EXPECT_EQ(QList<QString>{ "new_parent_id" }, item.parent_ids);
779 EXPECT_EQ("New name", item.name);779 EXPECT_EQ("New name", item.name);
780 EXPECT_EQ(ItemType::file, item.type);780 EXPECT_EQ(ItemType::file, item.type);
781}781}
782782
=== modified file 'tests/remote-client/MockProvider.cpp'
--- tests/remote-client/MockProvider.cpp 2016-09-26 08:57:05 +0000
+++ tests/remote-client/MockProvider.cpp 2016-10-10 01:18:55 +0000
@@ -58,6 +58,11 @@
58 };58 };
59 return make_ready_future<ItemList>(roots);59 return make_ready_future<ItemList>(roots);
60 }60 }
61 if (cmd_ == "roots_throw")
62 {
63 string msg = "roots(): I'm sorry Dave, I'm afraid I can't do that.";
64 return make_exceptional_future<ItemList>(PermissionException(msg));
65 }
6166
62 ItemList roots =67 ItemList roots =
63 {68 {
@@ -115,6 +120,8 @@
115120
116boost::future<Item> MockProvider::metadata(string const& item_id, Context const&)121boost::future<Item> MockProvider::metadata(string const& item_id, Context const&)
117{122{
123 static int num_calls = 0;
124
118 if (cmd_ == "slow_metadata")125 if (cmd_ == "slow_metadata")
119 {126 {
120 this_thread::sleep_for(chrono::seconds(1));127 this_thread::sleep_for(chrono::seconds(1));
@@ -124,13 +131,47 @@
124 Item metadata{"", {}, "Root", "etag", ItemType::root, {}};131 Item metadata{"", {}, "Root", "etag", ItemType::root, {}};
125 return make_ready_future<Item>(metadata);132 return make_ready_future<Item>(metadata);
126 }133 }
134 if (cmd_== "two_parents_throw")
135 {
136 ++num_calls;
137 switch (num_calls)
138 {
139 case 3:
140 return make_exceptional_future<Item>(ResourceException("metadata(): weird error", 42));
141 case 4:
142 num_calls = 0;
143 return make_exceptional_future<Item>(RemoteCommsException("metadata(): HTTP broken"));
144 default:
145 break;
146 }
147 }
127 if (item_id == "root_id")148 if (item_id == "root_id")
128 {149 {
150 if (cmd_ == "bad_parent_metadata_from_child")
151 {
152 ++num_calls;
153 if (num_calls == 2)
154 {
155 num_calls = 0;
156 // On second call, we return type file for the root.
157 Item metadata{"root_id", {}, "Root", "etag", ItemType::file, {}};
158 return make_ready_future<Item>(metadata);
159 }
160 }
129 Item metadata{"root_id", {}, "Root", "etag", ItemType::root, {}};161 Item metadata{"root_id", {}, "Root", "etag", ItemType::root, {}};
130 return make_ready_future<Item>(metadata);162 return make_ready_future<Item>(metadata);
131 }163 }
132 else if (item_id == "child_id")164 if (item_id == "child_id")
133 {165 {
166 if (cmd_ == "two_parents" || cmd_ == "two_parents_throw")
167 {
168 Item metadata
169 {
170 "child_id", { "root_id", "child_folder_id" }, "Child", "etag", ItemType::file,
171 { { SIZE_IN_BYTES, 0 }, { LAST_MODIFIED_TIME, "2007-04-05T14:30Z" } }
172 };
173 return make_ready_future<Item>(metadata);
174 }
134 Item metadata175 Item metadata
135 {176 {
136 "child_id", { "root_id" }, "Child", "etag", ItemType::file,177 "child_id", { "root_id" }, "Child", "etag", ItemType::file,
@@ -138,7 +179,7 @@
138 };179 };
139 return make_ready_future<Item>(metadata);180 return make_ready_future<Item>(metadata);
140 }181 }
141 else if (item_id == "child_folder_id")182 if (item_id == "child_folder_id")
142 {183 {
143 Item metadata{"child_folder_id", { "root_id" }, "Child_Folder", "etag", ItemType::folder, {}};184 Item metadata{"child_folder_id", { "root_id" }, "Child_Folder", "etag", ItemType::folder, {}};
144 return make_ready_future<Item>(metadata);185 return make_ready_future<Item>(metadata);
145186
=== modified file 'tests/remote-client/remote-client_test.cpp'
--- tests/remote-client/remote-client_test.cpp 2016-09-29 13:09:00 +0000
+++ tests/remote-client/remote-client_test.cpp 2016-10-10 01:18:55 +0000
@@ -58,6 +58,7 @@
58class DeleteTest : public RemoteClientTest {};58class DeleteTest : public RemoteClientTest {};
59class GetTest : public RemoteClientTest {};59class GetTest : public RemoteClientTest {};
60class ItemTest : public RemoteClientTest {};60class ItemTest : public RemoteClientTest {};
61class ParentsTest : public RemoteClientTest {};
61class RootsTest : public RemoteClientTest {};62class RootsTest : public RemoteClientTest {};
62class RuntimeTest : public ProviderFixture {};63class RuntimeTest : public ProviderFixture {};
6364
@@ -397,7 +398,7 @@
397 EXPECT_EQ("root_id", root.itemId());398 EXPECT_EQ("root_id", root.itemId());
398 EXPECT_EQ("Root", root.name());399 EXPECT_EQ("Root", root.name());
399 EXPECT_EQ("etag", root.etag());400 EXPECT_EQ("etag", root.etag());
400 EXPECT_EQ(QVector<QString>(), root.parentIds());401 EXPECT_EQ(QList<QString>(), root.parentIds());
401 EXPECT_FALSE(root.lastModifiedTime().isValid());402 EXPECT_FALSE(root.lastModifiedTime().isValid());
402 EXPECT_EQ(acc_, root.account());403 EXPECT_EQ(acc_, root.account());
403}404}
@@ -441,6 +442,46 @@
441 EXPECT_EQ("Account::roots(): Runtime was destroyed previously", j->error().message());442 EXPECT_EQ("Account::roots(): Runtime was destroyed previously", j->error().message());
442}443}
443444
445TEST_F(RootsTest, invalid_account)
446{
447 Account a;
448 unique_ptr<ItemListJob> j(a.roots());
449 EXPECT_FALSE(j->isValid());
450 EXPECT_EQ(ItemListJob::Error, j->status());
451 EXPECT_EQ(StorageError::LogicError, j->error().type());
452 EXPECT_EQ("Account::roots(): cannot create job from invalid account", j->error().message());
453
454 // Signal must be received.
455 QSignalSpy spy(j.get(), &ItemListJob::statusChanged);
456 spy.wait(SIGNAL_WAIT_TIME);
457 ASSERT_EQ(1, spy.count());
458 auto arg = spy.takeFirst();
459 EXPECT_EQ(ItemListJob::Error, qvariant_cast<ItemListJob::Status>(arg.at(0)));
460
461 EXPECT_EQ("Account::roots(): cannot create job from invalid account", j->error().message());
462}
463
464TEST_F(RootsTest, exception)
465{
466 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("roots_throw")));
467
468 unique_ptr<ItemListJob> j(acc_.roots());
469 EXPECT_TRUE(j->isValid());
470 EXPECT_EQ(ItemListJob::Loading, j->status());
471 EXPECT_EQ(StorageError::NoError, j->error().type());
472 EXPECT_EQ("No error", j->error().message());
473
474 QSignalSpy spy(j.get(), &ItemListJob::statusChanged);
475 spy.wait(SIGNAL_WAIT_TIME);
476 ASSERT_EQ(1, spy.count());
477 auto arg = spy.takeFirst();
478 EXPECT_EQ(ItemListJob::Error, qvariant_cast<ItemListJob::Status>(arg.at(0)));
479
480 EXPECT_EQ(ItemListJob::Error, j->status());
481 EXPECT_EQ(StorageError::PermissionDenied, j->error().type());
482 EXPECT_EQ("PermissionDenied: roots(): I'm sorry Dave, I'm afraid I can't do that.", j->error().errorString());
483}
484
444TEST_F(RootsTest, not_a_root)485TEST_F(RootsTest, not_a_root)
445{486{
446 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("not_a_root")));487 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("not_a_root")));
@@ -534,6 +575,25 @@
534 EXPECT_EQ("Account::get(): Runtime was destroyed previously", j->error().message());575 EXPECT_EQ("Account::get(): Runtime was destroyed previously", j->error().message());
535}576}
536577
578TEST_F(GetTest, invalid_account)
579{
580 Account a;
581 unique_ptr<ItemJob> j(a.get("child_Id"));
582 EXPECT_FALSE(j->isValid());
583 EXPECT_EQ(ItemJob::Error, j->status());
584 EXPECT_EQ(StorageError::LogicError, j->error().type());
585 EXPECT_EQ("Account::get(): cannot create job from invalid account", j->error().message());
586
587 // Signal must be received.
588 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
589 spy.wait(SIGNAL_WAIT_TIME);
590 ASSERT_EQ(1, spy.count());
591 auto arg = spy.takeFirst();
592 EXPECT_EQ(ItemJob::Error, qvariant_cast<ItemJob::Status>(arg.at(0)));
593
594 EXPECT_EQ("Account::get(): cannot create job from invalid account", j->error().message());
595}
596
537TEST_F(GetTest, empty_id_from_provider)597TEST_F(GetTest, empty_id_from_provider)
538{598{
539 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("empty_id")));599 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("empty_id")));
@@ -704,6 +764,25 @@
704 EXPECT_EQ("Item::deleteItem(): Runtime was destroyed previously", j->error().message()) << j->error().message().toStdString();764 EXPECT_EQ("Item::deleteItem(): Runtime was destroyed previously", j->error().message()) << j->error().message().toStdString();
705}765}
706766
767TEST_F(DeleteTest, invalid_item)
768{
769 Item i;
770 unique_ptr<VoidJob> j(i.deleteItem());
771 EXPECT_FALSE(j->isValid());
772 EXPECT_EQ(VoidJob::Error, j->status());
773 EXPECT_EQ(StorageError::LogicError, j->error().type());
774 EXPECT_EQ("Item::deleteItem(): cannot create job from invalid item", j->error().message());
775
776 // Signal must be received.
777 QSignalSpy spy(j.get(), &unity::storage::qt::VoidJob::statusChanged);
778 spy.wait(SIGNAL_WAIT_TIME);
779 ASSERT_EQ(1, spy.count());
780 auto arg = spy.takeFirst();
781 EXPECT_EQ(VoidJob::Error, qvariant_cast<VoidJob::Status>(arg.at(0)));
782
783 EXPECT_EQ("Item::deleteItem(): cannot create job from invalid item", j->error().message());
784}
785
707#if 0786#if 0
708// TODO: need to make internal symbols available for testing.787// TODO: need to make internal symbols available for testing.
709TEST_F(ValidateTest, basic)788TEST_F(ValidateTest, basic)
@@ -716,6 +795,112 @@
716}795}
717#endif796#endif
718797
798TEST_F(ItemTest, basic)
799{
800 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
801
802 {
803 // Default constructor.
804 Item i;
805 EXPECT_FALSE(i.isValid());
806 EXPECT_EQ("", i.itemId());
807 EXPECT_EQ("", i.name());
808 EXPECT_EQ("", i.etag());
809 EXPECT_EQ(Item::File, i.type());
810 auto mtime = i.lastModifiedTime();
811 EXPECT_FALSE(mtime.isValid());
812 auto pids = i.parentIds();
813 EXPECT_EQ(0, pids.size());
814 }
815
816 {
817 unique_ptr<ItemJob> j(acc_.get("child_id"));
818
819 {
820 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
821 spy.wait(SIGNAL_WAIT_TIME);
822 }
823 Item i = j->item();
824 EXPECT_TRUE(i.isValid());
825 EXPECT_EQ("child_id", i.itemId());
826 EXPECT_EQ("Child", i.name());
827 EXPECT_TRUE(i.account().isValid());
828 EXPECT_EQ("etag", i.etag());
829 EXPECT_EQ(Item::File, i.type());
830
831 // Copy constructor
832 Item i2(i);
833 EXPECT_EQ(i, i2);
834
835 // Move constructor
836 Item i3(move(i2));
837 EXPECT_TRUE(i3.isValid());
838 EXPECT_EQ(i, i3);
839
840 // Moved-from object must be invalid
841 EXPECT_FALSE(i2.isValid());
842
843 // Moved-from object must be assignable
844 j.reset(acc_.get("child_id"));
845 {
846 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
847 spy.wait(SIGNAL_WAIT_TIME);
848 }
849 auto i4 = j->item();
850 i2 = i4;
851 EXPECT_EQ(i4, i2);
852 }
853
854 {
855 unique_ptr<ItemJob> j1(acc_.get("child_id"));
856 unique_ptr<ItemJob> j2(acc_.get("root_id"));
857
858 QSignalSpy spy1(j1.get(), &ItemJob::statusChanged);
859 QSignalSpy spy2(j2.get(), &ItemJob::statusChanged);
860 spy2.wait(SIGNAL_WAIT_TIME);
861 ASSERT_EQ(1, spy1.count());
862
863 auto i1 = j1->item();
864 auto i2 = j2->item();
865
866 // Copy assignment
867 i1 = i2;
868 EXPECT_TRUE(i2.isValid());
869 EXPECT_EQ(i2, i1);
870
871 // Self-assignment
872 i2 = i2;
873 EXPECT_TRUE(i2.isValid());
874 EXPECT_EQ("root_id", i2.itemId());
875 EXPECT_EQ("Root", i2.name());
876 EXPECT_TRUE(i2.account().isValid());
877 EXPECT_EQ("etag", i2.etag());
878 EXPECT_EQ(Item::Root, i2.type());
879
880 // Move assignment
881 unique_ptr<ItemJob> j3(acc_.get("child_folder_id"));
882 QSignalSpy spy(j3.get(), &ItemJob::statusChanged);
883 spy.wait(SIGNAL_WAIT_TIME);
884 ASSERT_EQ(1, spy1.count());
885
886 auto i3 = j3->item();
887
888 i1 = move(i3);
889 EXPECT_TRUE(i1.isValid());
890 EXPECT_EQ("child_folder_id", i1.itemId());
891 EXPECT_EQ("Child_Folder", i1.name());
892 EXPECT_EQ(i1.account(), i1.account());
893 EXPECT_EQ("etag", i1.etag());
894 EXPECT_EQ(Item::Folder, i1.type());
895
896 // Moved-from object must be invalid
897 EXPECT_FALSE(i3.isValid());
898
899 // Moved-from object must be assignable
900 i3 = i2;
901 EXPECT_EQ(i2, i3);
902 }
903}
719904
720TEST_F(ItemTest, comparison_and_hash)905TEST_F(ItemTest, comparison_and_hash)
721{906{
@@ -851,6 +1036,292 @@
851 }1036 }
852}1037}
8531038
1039TEST_F(ParentsTest, basic)
1040{
1041 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1042
1043 Item root;
1044 {
1045 unique_ptr<ItemJob> j(acc_.get("root_id"));
1046 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1047 spy.wait(SIGNAL_WAIT_TIME);
1048 root = j->item();
1049 }
1050
1051 {
1052 // Getting parents from root does not call the provider and returns
1053 // no parents immediately.
1054 unique_ptr<ItemListJob> j(root.parents());
1055 EXPECT_TRUE(j->isValid());
1056 EXPECT_EQ(ItemListJob::Finished, j->status());
1057 EXPECT_EQ(StorageError::NoError, j->error().type());
1058
1059 // Signal must be received.
1060 QSignalSpy spy(j.get(), &ItemListJob::statusChanged);
1061 spy.wait(SIGNAL_WAIT_TIME);
1062 ASSERT_EQ(1, spy.count());
1063 auto arg = spy.takeFirst();
1064 EXPECT_EQ(ItemListJob::Finished, qvariant_cast<ItemListJob::Status>(arg.at(0)));
1065 }
1066
1067 Item child;
1068 {
1069 unique_ptr<ItemJob> j(acc_.get("child_id"));
1070 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1071 spy.wait(SIGNAL_WAIT_TIME);
1072 child = j->item();
1073 }
1074
1075 QList<Item> parents;
1076 {
1077 unique_ptr<ItemListJob> j(child.parents());
1078 EXPECT_TRUE(j->isValid());
1079 EXPECT_EQ(ItemListJob::Loading, j->status());
1080 EXPECT_EQ(StorageError::NoError, j->error().type());
1081
1082 QSignalSpy ready_spy(j.get(), &ItemListJob::itemsReady);
1083 QSignalSpy status_spy(j.get(), &ItemListJob::statusChanged);
1084 ready_spy.wait(SIGNAL_WAIT_TIME);
1085 ASSERT_EQ(1, ready_spy.count());
1086 auto list_arg = ready_spy.takeFirst();
1087 parents = qvariant_cast<QList<Item>>(list_arg.at(0));
1088
1089 // When the signal for the final item arrives, status must be Finished.
1090 EXPECT_EQ(ItemListJob::Finished, j->status());
1091
1092 // Finished signal must be received.
1093 if (status_spy.count() == 0)
1094 {
1095 status_spy.wait(SIGNAL_WAIT_TIME);
1096 }
1097 ASSERT_EQ(1, status_spy.count());
1098 auto status_arg = status_spy.takeFirst();
1099 EXPECT_EQ(ItemListJob::Finished, qvariant_cast<ItemListJob::Status>(status_arg.at(0)));
1100
1101 // Child must have one parent, namely the root.
1102 ASSERT_EQ(1, parents.size());
1103 EXPECT_EQ(root, parents[0]);
1104 }
1105}
1106
1107TEST_F(ParentsTest, two_parents)
1108{
1109 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("two_parents")));
1110
1111 Item root;
1112 {
1113 unique_ptr<ItemJob> j(acc_.get("root_id"));
1114 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1115 spy.wait(SIGNAL_WAIT_TIME);
1116 root = j->item();
1117 }
1118
1119 Item child;
1120 {
1121 unique_ptr<ItemJob> j(acc_.get("child_id"));
1122 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1123 spy.wait(SIGNAL_WAIT_TIME);
1124 child = j->item();
1125 }
1126
1127 QList<Item> parents;
1128 {
1129 unique_ptr<ItemListJob> j(child.parents());
1130 EXPECT_TRUE(j->isValid());
1131
1132 QSignalSpy ready_spy(j.get(), &ItemListJob::itemsReady);
1133 QSignalSpy status_spy(j.get(), &ItemListJob::statusChanged);
1134
1135 ready_spy.wait(SIGNAL_WAIT_TIME);
1136 auto list_arg = ready_spy.takeFirst();
1137 auto this_parent = qvariant_cast<QList<Item>>(list_arg.at(0));
1138 parents.append(this_parent);
1139 while (ready_spy.count() < 1)
1140 {
1141 ready_spy.wait(SIGNAL_WAIT_TIME);
1142 }
1143 list_arg = ready_spy.takeFirst();
1144 this_parent = qvariant_cast<QList<Item>>(list_arg.at(0));
1145 parents.append(this_parent);
1146
1147 // Finished signal must be received.
1148 if (status_spy.count() == 0)
1149 {
1150 status_spy.wait(SIGNAL_WAIT_TIME);
1151 }
1152 ASSERT_EQ(1, status_spy.count());
1153 auto status_arg = status_spy.takeFirst();
1154 EXPECT_EQ(ItemListJob::Finished, qvariant_cast<ItemListJob::Status>(status_arg.at(0)));
1155
1156 // Child must have two parents.
1157 ASSERT_EQ(2, parents.size());
1158 EXPECT_EQ("root_id", parents[0].itemId());
1159 EXPECT_EQ("child_folder_id", parents[1].itemId());
1160 }
1161}
1162
1163TEST_F(ParentsTest, two_parents_throw)
1164{
1165 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("two_parents_throw")));
1166
1167 Item root;
1168 {
1169 unique_ptr<ItemJob> j(acc_.get("root_id"));
1170 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1171 spy.wait(SIGNAL_WAIT_TIME);
1172 root = j->item();
1173 }
1174
1175 Item child;
1176 {
1177 unique_ptr<ItemJob> j(acc_.get("child_id"));
1178 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1179 spy.wait(SIGNAL_WAIT_TIME);
1180 child = j->item();
1181 }
1182
1183 QList<Item> parents;
1184 {
1185 unique_ptr<ItemListJob> j(child.parents());
1186 EXPECT_TRUE(j->isValid());
1187
1188 QSignalSpy status_spy(j.get(), &ItemListJob::statusChanged);
1189 QSignalSpy ready_spy(j.get(), &ItemListJob::itemsReady);
1190
1191 status_spy.wait(SIGNAL_WAIT_TIME);
1192 ASSERT_EQ(1, status_spy.count());
1193 auto status_arg = status_spy.takeFirst();
1194 EXPECT_EQ(ItemListJob::Error, qvariant_cast<ItemListJob::Status>(status_arg.at(0)));
1195 EXPECT_EQ(StorageError::ResourceError, j->error().type());
1196 EXPECT_EQ("ResourceError: metadata(): weird error", j->error().errorString());
1197 EXPECT_EQ(42, j->error().errorCode());
1198
1199 // We wait here to allow the error return for the second parent to arrive in MultiItemJobImpl.
1200 // This gives us coverage on the early return in the process_error lambda, when the job is
1201 // already in the error state.
1202 EXPECT_FALSE(ready_spy.wait(1000));
1203 }
1204}
1205
1206TEST_F(ParentsTest, invalid_item)
1207{
1208 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1209
1210 Item invalid;
1211 unique_ptr<ItemListJob> j(invalid.parents());
1212 EXPECT_FALSE(j->isValid());
1213 EXPECT_EQ(ItemListJob::Error, j->status());
1214 EXPECT_EQ(StorageError::LogicError, j->error().type());
1215 EXPECT_EQ("Item::parents(): cannot create job from invalid item", j->error().message());
1216
1217 // Signal must be received.
1218 QSignalSpy spy(j.get(), &ItemListJob::statusChanged);
1219 spy.wait(SIGNAL_WAIT_TIME);
1220 ASSERT_EQ(1, spy.count());
1221 auto arg = spy.takeFirst();
1222 EXPECT_EQ(ItemListJob::Error, qvariant_cast<ItemListJob::Status>(arg.at(0)));
1223}
1224
1225TEST_F(ParentsTest, runtime_destroyed)
1226{
1227 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
1228
1229 Item root;
1230 {
1231 unique_ptr<ItemJob> j(acc_.get("root_id"));
1232 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1233 spy.wait(SIGNAL_WAIT_TIME);
1234 root = j->item();
1235 }
1236
1237 EXPECT_EQ(StorageError::NoError, runtime_->shutdown().type()); // Destroy runtime.
1238
1239 unique_ptr<ItemListJob> j(root.parents());
1240 EXPECT_FALSE(j->isValid());
1241 EXPECT_EQ(ItemJob::Error, j->status());
1242 EXPECT_EQ(StorageError::RuntimeDestroyed, j->error().type());
1243 EXPECT_EQ("Item::parents(): Runtime was destroyed previously", j->error().message());
1244
1245 // Signal must be received.
1246 QSignalSpy spy(j.get(), &ItemListJob::statusChanged);
1247 spy.wait(SIGNAL_WAIT_TIME);
1248 auto arg = spy.takeFirst();
1249 EXPECT_EQ(ItemListJob::Error, qvariant_cast<ItemListJob::Status>(arg.at(0)));
1250
1251 EXPECT_EQ("Item::parents(): Runtime was destroyed previously", j->error().message());
1252}
1253
1254TEST_F(ParentsTest, runtime_destroyed_while_item_list_job_running)
1255{
1256 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("slow_metadata")));
1257
1258 Item root;
1259 {
1260 unique_ptr<ItemJob> j(acc_.get("root_id"));
1261 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1262 spy.wait(SIGNAL_WAIT_TIME);
1263 root = j->item();
1264 }
1265
1266 Item child;
1267 {
1268 unique_ptr<ItemJob> j(acc_.get("child_id"));
1269 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1270 spy.wait(SIGNAL_WAIT_TIME);
1271 child = j->item();
1272 }
1273
1274 unique_ptr<ItemListJob> j(child.parents());
1275
1276 EXPECT_EQ(StorageError::NoError, runtime_->shutdown().type()); // Destroy runtime, provider still sleeping
1277
1278 // Signal must be received.
1279 QSignalSpy spy(j.get(), &ItemListJob::statusChanged);
1280 spy.wait(SIGNAL_WAIT_TIME);
1281 ASSERT_EQ(1, spy.count());
1282 auto arg = spy.takeFirst();
1283 EXPECT_EQ(ItemListJob::Error, qvariant_cast<ItemListJob::Status>(arg.at(0)));
1284
1285 EXPECT_EQ("Item::parents(): Runtime was destroyed previously", j->error().message());
1286}
1287
1288TEST_F(ParentsTest, bad_metadata)
1289{
1290 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider("bad_parent_metadata_from_child")));
1291
1292 Item root;
1293 {
1294 unique_ptr<ItemJob> j(acc_.get("root_id"));
1295 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1296 spy.wait(SIGNAL_WAIT_TIME);
1297 root = j->item();
1298 }
1299
1300 Item child;
1301 {
1302 unique_ptr<ItemJob> j(acc_.get("child_id"));
1303 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
1304 spy.wait(SIGNAL_WAIT_TIME);
1305 child = j->item();
1306 }
1307
1308 QList<Item> parents;
1309 {
1310 unique_ptr<ItemListJob> j(child.parents());
1311 EXPECT_TRUE(j->isValid());
1312 EXPECT_EQ(ItemListJob::Loading, j->status());
1313 EXPECT_EQ(StorageError::NoError, j->error().type());
1314
1315 QSignalSpy spy(j.get(), &ItemListJob::statusChanged);
1316 spy.wait(SIGNAL_WAIT_TIME);
1317 ASSERT_EQ(1, spy.count());
1318 auto arg = spy.takeFirst();
1319 EXPECT_EQ(ItemListJob::Error, qvariant_cast<ItemListJob::Status>(arg.at(0)));
1320
1321 EXPECT_EQ("Item::parents(): provider returned a file as a parent", j->error().message());
1322 }
1323}
1324
854#if 01325#if 0
855TEST_F(RootTest, basic)1326TEST_F(RootTest, basic)
856{1327{

Subscribers

People subscribed via source and target branches

to all changes: