Merge lp:~mhr3/unity-scopes-shell/scopes-ng-tests into lp:unity-scopes-shell

Proposed by Michal Hruby
Status: Merged
Approved by: Michal Hruby
Approved revision: 37
Merged at revision: 31
Proposed branch: lp:~mhr3/unity-scopes-shell/scopes-ng-tests
Merge into: lp:unity-scopes-shell
Diff against target: 810 lines (+479/-47)
18 files modified
src/Unity/CMakeLists.txt (+1/-1)
src/Unity/scopes-ng/CMakeLists.txt (+1/-1)
src/Unity/scopes-ng/categories.cpp (+4/-4)
src/Unity/scopes-ng/categories.h (+2/-2)
src/Unity/scopes-ng/resultsmodel.cpp (+60/-23)
src/Unity/scopes-ng/resultsmodel.h (+18/-6)
src/Unity/scopes-ng/scope.h (+1/-1)
src/Unity/scopes-ng/scopes.cpp (+16/-7)
src/Unity/scopes-ng/scopes.h (+3/-1)
tests/CMakeLists.txt (+13/-1)
tests/data/CMakeLists.txt (+7/-0)
tests/data/Registry.ini.in (+7/-0)
tests/data/Runtime.ini.in (+6/-0)
tests/data/Zmq.ini.in (+3/-0)
tests/data/mock-scope/CMakeLists.txt (+11/-0)
tests/data/mock-scope/mock-scope.cpp (+119/-0)
tests/data/mock-scope/mock-scope.ini.in (+7/-0)
tests/resultstest-ng.cpp (+200/-0)
To merge this branch: bzr merge lp:~mhr3/unity-scopes-shell/scopes-ng-tests
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michael Zanetti (community) Approve
Review via email: mp+198437@code.launchpad.net

Commit message

Updated result model roles and added unit tests for the new scopes framework.

Description of the change

Updated result model roles and added unit tests for the new scopes framework.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

92 + return QVariant(QString::fromStdString(v.get_string()));
107 + return QVariant(QString::fromStdString(result->category()->id()));

You don't need to write the QVariant there (and all the following lines) explicity. Obviously it doesn't really hurt in terms of performance but imho it hurts readability. You don't gain anything in terms of converting anyways by writing it explicitly anyways.

=====
168 +#include <unordered_map>
210 + std::unordered_map<std::string, std::string> m_componentMapping;

unused?

========

379 +#Scope.GroupConfigDir = @CMAKE_CURRENT_BINARY_DIR@/scope-groups

as this is commented I gotta ask: Is this needed at all? in the future? do we perhaps need a FIXME comment?

======
418 === added file 'tests/data/scope-A/scope-A.cpp'

This seems like a mock. calling the directory "mocks" instead of data would make that more obvious imho.

=======
674 + void testTwoSearches()
675 + {
676 + QCOMPARE(m_scope->searchInProgress(), false);
677 + // perform a search
678 + m_scope->setSearchQuery(QString(""));
679 + QCOMPARE(m_scope->searchInProgress(), true);
680 + QTRY_COMPARE(m_scope->searchInProgress(), false);
681 +
682 + // ensure categories have > 0 rows
683 + auto categories = m_scope->categories();
684 + auto categories_count = categories->rowCount();
685 + QVERIFY(categories_count > 0);
686 +
687 + m_scope->setSearchQuery(QString("foo"));
688 + QCOMPARE(m_scope->searchInProgress(), true);
689 + // wait for the search to finish
690 + QTRY_COMPARE(m_scope->searchInProgress(), false);
691 +
692 + // shouldn't create more nor fewer categories
693 + QVERIFY(categories->rowCount() == categories_count);
694 + }

Wouldn't it make sense to use data columns/rows? This way we can just add new rows to test different things like uppercase, lowercase, special chars etc for search strings (and it's even fewer code than what you have now)

Ok. I guess the testTwoSearches is intentionally performing 2 searches in a row to see if it recovers from searches. Still, there might be issues in different search strings and I really think we should have such a data driven test case to easily be able to add new search terms to the tests. Maybe it makes more sense to transform the testBasicResultData into such a thing. Maybe both? You decide.

======

I really don't like the overuse of the "auto" type. Imho it makes code hard to read.

Revision history for this message
Michal Hruby (mhr3) wrote :

> You don't need to write the QVariant there (and all the following lines)
> explicity. Obviously it doesn't really hurt in terms of performance but imho
> it hurts readability. You don't gain anything in terms of converting anyways
> by writing it explicitly anyways.

Changed to do implicit conversions.

>
> =====
> 168 +#include <unordered_map>
> 210 + std::unordered_map<std::string, std::string> m_componentMapping;
>
> unused?

Will be used soon :)

> 379 +#Scope.GroupConfigDir = @CMAKE_CURRENT_BINARY_DIR@/scope-groups
>
> as this is commented I gotta ask: Is this needed at all? in the future? do we
> perhaps need a FIXME comment?

Removed.

> 418 === added file 'tests/data/scope-A/scope-A.cpp'
>
> This seems like a mock. calling the directory "mocks" instead of data would
> make that more obvious imho.

The data dir has all test configuration data files, plus the scope itself is really a "data" provider :) But I at least renamed the scope itself to mock-scope.

> Wouldn't it make sense to use data columns/rows? This way we can just add new
> rows to test different things like uppercase, lowercase, special chars etc for
> search strings (and it's even fewer code than what you have now)
>
> Ok. I guess the testTwoSearches is intentionally performing 2 searches in a
> row to see if it recovers from searches. Still, there might be issues in
> different search strings and I really think we should have such a data driven
> test case to easily be able to add new search terms to the tests. Maybe it
> makes more sense to transform the testBasicResultData into such a thing. Maybe
> both? You decide.

The thing is, I'm not really using the various search strings to just change the data the scope gives you, it's mostly used to change behaviour of the search.

Maybe the problem really is with the naming of the test file, it's not just testing results (that's really just the last step), it's testing end to end communication with a real scope - that's why these four tiny test methods are able to cover 75% of the entire codebase.

> I really don't like the overuse of the "auto" type. Imho it makes code hard to
> read.

Not sure what to do about that, it's convenient to write it that way :) Maybe it's again a naming issue, the variable name should be expressive enough to convey what it is.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michael Zanetti (mzanetti) wrote :

+1

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michal Hruby (mhr3) wrote :

qmlplugindump crash, retrying...

Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/Unity/CMakeLists.txt'
--- src/Unity/CMakeLists.txt 2013-11-25 18:41:16 +0000
+++ src/Unity/CMakeLists.txt 2013-12-12 12:53:45 +0000
@@ -5,7 +5,7 @@
5include(FindPkgConfig)5include(FindPkgConfig)
6pkg_check_modules(QTDEE REQUIRED libdee-qt5>=3.2)6pkg_check_modules(QTDEE REQUIRED libdee-qt5>=3.2)
7pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0>=7.1.1)7pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0>=7.1.1)
8pkg_check_modules(SCOPESLIB REQUIRED libunity-scopes>=0.1)8pkg_check_modules(SCOPESLIB REQUIRED libunity-scopes>=0.1.3)
99
10include_directories(10include_directories(
11 ${CMAKE_CURRENT_SOURCE_DIR}11 ${CMAKE_CURRENT_SOURCE_DIR}
1212
=== modified file 'src/Unity/scopes-ng/CMakeLists.txt'
--- src/Unity/scopes-ng/CMakeLists.txt 2013-12-05 12:21:23 +0000
+++ src/Unity/scopes-ng/CMakeLists.txt 2013-12-12 12:53:45 +0000
@@ -1,6 +1,6 @@
1# Dependencies1# Dependencies
2include(FindPkgConfig)2include(FindPkgConfig)
3pkg_check_modules(SCOPESLIB REQUIRED libunity-scopes>=0.1.2)3pkg_check_modules(SCOPESLIB REQUIRED libunity-scopes>=0.1.3)
44
5include_directories(5include_directories(
6 ${CMAKE_CURRENT_SOURCE_DIR}6 ${CMAKE_CURRENT_SOURCE_DIR}
77
=== modified file 'src/Unity/scopes-ng/categories.cpp'
--- src/Unity/scopes-ng/categories.cpp 2013-12-06 10:47:26 +0000
+++ src/Unity/scopes-ng/categories.cpp 2013-12-12 12:53:45 +0000
@@ -181,17 +181,17 @@
181181
182 switch (role) {182 switch (role) {
183 case RoleCategoryId:183 case RoleCategoryId:
184 return QVariant(QString::fromStdString(cat->id()));184 return QString::fromStdString(cat->id());
185 case RoleName:185 case RoleName:
186 return QVariant(QString::fromStdString(cat->title()));186 return QString::fromStdString(cat->title());
187 case RoleIcon:187 case RoleIcon:
188 return QVariant(QString::fromStdString(cat->icon()));188 return QString::fromStdString(cat->icon());
189 case RoleRenderer:189 case RoleRenderer:
190 return catData->renderer_template.toVariant();190 return catData->renderer_template.toVariant();
191 case RoleComponents:191 case RoleComponents:
192 return catData->components.toVariant();192 return catData->components.toVariant();
193 case RoleContentType:193 case RoleContentType:
194 return QVariant(QString("default"));194 return QString("default");
195 case RoleRendererHint:195 case RoleRendererHint:
196 return QVariant();196 return QVariant();
197 case RoleProgressSource:197 case RoleProgressSource:
198198
=== modified file 'src/Unity/scopes-ng/categories.h'
--- src/Unity/scopes-ng/categories.h 2013-12-04 17:23:15 +0000
+++ src/Unity/scopes-ng/categories.h 2013-12-12 12:53:45 +0000
@@ -36,7 +36,7 @@
3636
37struct CategoryData;37struct CategoryData;
3838
39class Categories : public QAbstractListModel39class Q_DECL_EXPORT Categories : public QAbstractListModel
40{40{
41 Q_OBJECT41 Q_OBJECT
4242
@@ -60,7 +60,7 @@
6060
61 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;61 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
62 QHash<int, QByteArray> roleNames() const override;62 QHash<int, QByteArray> roleNames() const override;
63 int rowCount(const QModelIndex& parent) const override;63 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
6464
65 ResultsModel* lookupCategory(std::string const& category_id);65 ResultsModel* lookupCategory(std::string const& category_id);
66 void registerCategory(unity::api::scopes::Category::SCPtr category, ResultsModel* model);66 void registerCategory(unity::api::scopes::Category::SCPtr category, ResultsModel* model);
6767
=== modified file 'src/Unity/scopes-ng/resultsmodel.cpp'
--- src/Unity/scopes-ng/resultsmodel.cpp 2013-12-06 10:47:26 +0000
+++ src/Unity/scopes-ng/resultsmodel.cpp 2013-12-12 12:53:45 +0000
@@ -30,13 +30,20 @@
30 : QAbstractListModel(parent)30 : QAbstractListModel(parent)
31{31{
32 m_roles[ResultsModel::RoleUri] = "uri";32 m_roles[ResultsModel::RoleUri] = "uri";
33 m_roles[ResultsModel::RoleIconHint] = "icon";33 m_roles[ResultsModel::RoleCategoryId] = "categoryId";
34 m_roles[ResultsModel::RoleCategory] = "category";
35 m_roles[ResultsModel::RoleTitle] = "title";
36 m_roles[ResultsModel::RoleComment] = "comment";
37 m_roles[ResultsModel::RoleDndUri] = "dndUri";34 m_roles[ResultsModel::RoleDndUri] = "dndUri";
38 m_roles[ResultsModel::RoleMetadata] = "metadata";35 m_roles[ResultsModel::RoleMetadata] = "metadata";
39 m_roles[ResultsModel::RoleRendererHints] = "rendererHints";36 m_roles[ResultsModel::RoleTitle] = "title";
37 m_roles[ResultsModel::RoleArt] = "art";
38 m_roles[ResultsModel::RoleSubtitle] = "subtitle";
39 m_roles[ResultsModel::RoleMascot] = "mascot";
40 m_roles[ResultsModel::RoleEmblem] = "emblem";
41 m_roles[ResultsModel::RoleOldPrice] = "oldPrice";
42 m_roles[ResultsModel::RolePrice] = "price";
43 m_roles[ResultsModel::RoleAltPrice] = "altPrice";
44 m_roles[ResultsModel::RoleRating] = "rating";
45 m_roles[ResultsModel::RoleAltRating] = "altRating";
46 m_roles[ResultsModel::RoleSummary] = "summary";
40}47}
4148
42QString ResultsModel::categoryId() const49QString ResultsModel::categoryId() const
@@ -95,36 +102,66 @@
95}102}
96103
97QVariant104QVariant
105ResultsModel::componentValue(scopes::CategorisedResult* result, std::string const& fieldName) const
106{
107 // FIXME: component field mapping
108 if (!result->has_metadata(fieldName)) {
109 return QVariant();
110 }
111 scopes::Variant const& v = result->metadata(fieldName);
112 if (v.which() != scopes::Variant::Type::String) {
113 return QVariant();
114 }
115
116 return QString::fromStdString(v.get_string());
117}
118
119QVariant
98ResultsModel::data(const QModelIndex& index, int role) const120ResultsModel::data(const QModelIndex& index, int role) const
99{121{
100 scopes::CategorisedResult* result = m_results.at(index.row()).get();122 scopes::CategorisedResult* result = m_results.at(index.row()).get();
101123
102 switch (role) {124 switch (role) {
103 case RoleUri:125 case RoleUri:
104 return QVariant(QString::fromStdString(result->uri()));126 return QString::fromStdString(result->uri());
105 case RoleIconHint: {127 case RoleCategoryId:
106 QString iconHint(QString::fromStdString(result->art()));128 return QString::fromStdString(result->category()->id());
107 if (iconHint.isEmpty()) {129 case RoleDndUri:
130 return QString::fromStdString(result->dnd_uri());
131 case RoleMetadata:
132 return QVariantMap(); // FIXME! would be great to keep it opaque, so it isn't misused
133 case RoleTitle:
134 return QString::fromStdString(result->title());
135 case RoleArt: {
136 QString image(QString::fromStdString(result->art()));
137 if (image.isEmpty()) {
108 QString uri(QString::fromStdString(result->uri()));138 QString uri(QString::fromStdString(result->uri()));
139 // FIXME: what to do about mimetype?
109 QString thumbnailerUri(uriToThumbnailerProviderString(uri, QString(), QVariantHash()));140 QString thumbnailerUri(uriToThumbnailerProviderString(uri, QString(), QVariantHash()));
110 if (!thumbnailerUri.isNull()) {141 if (!thumbnailerUri.isNull()) {
111 return QVariant::fromValue(thumbnailerUri);142 return thumbnailerUri;
112 }143 }
113 }144 }
114 return QVariant(iconHint);145 return image;
115 }146 }
116 case RoleCategory:147 case RoleSubtitle:
117 return QVariant(QString::fromStdString(result->category()->id()));148 return componentValue(result, "subtitle");
118 case RoleTitle:149 case RoleMascot:
119 return QVariant(QString::fromStdString(result->title()));150 return componentValue(result, "mascot");
120 case RoleComment:151 case RoleEmblem:
121 return QVariant();152 return componentValue(result, "emblem");
122 case RoleDndUri:153 case RoleOldPrice:
123 return QVariant(QString::fromStdString(result->dnd_uri()));154 return componentValue(result, "old-price");
124 case RoleMetadata:155 case RolePrice:
125 return QVariant(QVariantMap());156 return componentValue(result, "price");
126 case RoleRendererHints:157 case RoleAltPrice:
127 return QVariant();158 return componentValue(result, "alt-price");
159 case RoleRating:
160 return componentValue(result, "rating");
161 case RoleAltRating:
162 return componentValue(result, "alt-rating");
163 case RoleSummary:
164 return componentValue(result, "summary");
128 default:165 default:
129 return QVariant();166 return QVariant();
130 }167 }
131168
=== modified file 'src/Unity/scopes-ng/resultsmodel.h'
--- src/Unity/scopes-ng/resultsmodel.h 2013-12-05 10:40:44 +0000
+++ src/Unity/scopes-ng/resultsmodel.h 2013-12-12 12:53:45 +0000
@@ -24,6 +24,7 @@
24#include <QAbstractListModel>24#include <QAbstractListModel>
2525
26#include <scopes/CategorisedResult.h>26#include <scopes/CategorisedResult.h>
27#include <unordered_map>
2728
28namespace scopes_ng {29namespace scopes_ng {
2930
@@ -41,16 +42,24 @@
4142
42 enum Roles {43 enum Roles {
43 RoleUri,44 RoleUri,
44 RoleIconHint,45 RoleCategoryId,
45 RoleCategory,
46 RoleTitle,
47 RoleComment,
48 RoleDndUri,46 RoleDndUri,
49 RoleMetadata,47 RoleMetadata,
50 RoleRendererHints48 // card components
49 RoleTitle,
50 RoleArt,
51 RoleSubtitle,
52 RoleMascot,
53 RoleEmblem,
54 RoleOldPrice,
55 RolePrice,
56 RoleAltPrice,
57 RoleRating,
58 RoleAltRating,
59 RoleSummary
51 };60 };
5261
53 int rowCount(const QModelIndex& parent) const override;62 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
54 QHash<int, QByteArray> roleNames() const override;63 QHash<int, QByteArray> roleNames() const override;
55 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;64 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
5665
@@ -69,7 +78,10 @@
69 void countChanged();78 void countChanged();
7079
71private:80private:
81 QVariant componentValue(unity::api::scopes::CategorisedResult* result, std::string const& fieldName) const;
82
72 QHash<int, QByteArray> m_roles;83 QHash<int, QByteArray> m_roles;
84 std::unordered_map<std::string, std::string> m_componentMapping;
73 QList<std::shared_ptr<unity::api::scopes::CategorisedResult>> m_results;85 QList<std::shared_ptr<unity::api::scopes::CategorisedResult>> m_results;
74 QString m_categoryId;86 QString m_categoryId;
75};87};
7688
=== modified file 'src/Unity/scopes-ng/scope.h'
--- src/Unity/scopes-ng/scope.h 2013-12-05 18:05:13 +0000
+++ src/Unity/scopes-ng/scope.h 2013-12-12 12:53:45 +0000
@@ -35,7 +35,7 @@
3535
36class Categories;36class Categories;
3737
38class Scope : public QObject38class Q_DECL_EXPORT Scope : public QObject
39{39{
40 Q_OBJECT40 Q_OBJECT
4141
4242
=== modified file 'src/Unity/scopes-ng/scopes.cpp'
--- src/Unity/scopes-ng/scopes.cpp 2013-12-06 10:47:26 +0000
+++ src/Unity/scopes-ng/scopes.cpp 2013-12-12 12:53:45 +0000
@@ -41,9 +41,8 @@
41{41{
42 try42 try
43 {43 {
44 // FIXME: use proper path for the runtime config44 // m_runtimeConfig should be null in most cases, and empty string is for system-wide fallback
45 // but have libunity-scopes export it first?!45 m_scopesRuntime = scopes::Runtime::create(m_runtimeConfig.toStdString());
46 m_scopesRuntime = scopes::Runtime::create();
47 auto registry = m_scopesRuntime->registry();46 auto registry = m_scopesRuntime->registry();
48 m_metadataMap = registry->list();47 m_metadataMap = registry->list();
49 }48 }
@@ -54,6 +53,11 @@
54 Q_EMIT discoveryFinished();53 Q_EMIT discoveryFinished();
55}54}
5655
56void ScopeListWorker::setRuntimeConfig(QString const& config)
57{
58 m_runtimeConfig = config;
59}
60
57scopes::Runtime::UPtr ScopeListWorker::takeRuntime()61scopes::Runtime::UPtr ScopeListWorker::takeRuntime()
58{62{
59 return std::move(m_scopesRuntime);63 return std::move(m_scopesRuntime);
@@ -63,7 +67,7 @@
63{67{
64 return m_metadataMap;68 return m_metadataMap;
65}69}
66 70
67Scopes::Scopes(QObject *parent)71Scopes::Scopes(QObject *parent)
68 : QAbstractListModel(parent)72 : QAbstractListModel(parent)
69 , m_listThread(nullptr)73 , m_listThread(nullptr)
@@ -102,6 +106,8 @@
102void Scopes::populateScopes()106void Scopes::populateScopes()
103{107{
104 auto thread = new ScopeListWorker;108 auto thread = new ScopeListWorker;
109 QByteArray runtimeConfig = qgetenv("UNITY_SCOPES_RUNTIME_PATH");
110 thread->setRuntimeConfig(QString::fromLocal8Bit(runtimeConfig));
105 QObject::connect(thread, &ScopeListWorker::discoveryFinished, this, &Scopes::discoveryFinished);111 QObject::connect(thread, &ScopeListWorker::discoveryFinished, this, &Scopes::discoveryFinished);
106 QObject::connect(thread, &ScopeListWorker::finished, thread, &QObject::deleteLater);112 QObject::connect(thread, &ScopeListWorker::finished, thread, &QObject::deleteLater);
107113
@@ -138,11 +144,11 @@
138 case Scopes::RoleScope:144 case Scopes::RoleScope:
139 return QVariant::fromValue(scope);145 return QVariant::fromValue(scope);
140 case Scopes::RoleId:146 case Scopes::RoleId:
141 return QVariant::fromValue(scope->id());147 return QString(scope->id());
142 case Scopes::RoleVisible:148 case Scopes::RoleVisible:
143 return QVariant::fromValue(scope->visible());149 return QVariant::fromValue(scope->visible());
144 case Scopes::RoleTitle:150 case Scopes::RoleTitle:
145 return QVariant::fromValue(scope->name());151 return QString(scope->name());
146 default:152 default:
147 return QVariant();153 return QVariant();
148 }154 }
@@ -150,7 +156,10 @@
150156
151QVariant Scopes::get(int row) const157QVariant Scopes::get(int row) const
152{158{
153 return data(QAbstractListModel::index(row), 0);159 if (row >= m_scopes.size() || row < 0) {
160 return QVariant();
161 }
162 return data(QAbstractListModel::index(row), RoleScope);
154}163}
155164
156QVariant Scopes::get(const QString& scope_id) const165QVariant Scopes::get(const QString& scope_id) const
157166
=== modified file 'src/Unity/scopes-ng/scopes.h'
--- src/Unity/scopes-ng/scopes.h 2013-12-04 14:13:45 +0000
+++ src/Unity/scopes-ng/scopes.h 2013-12-12 12:53:45 +0000
@@ -35,7 +35,7 @@
3535
36class Scope;36class Scope;
3737
38class Scopes : public QAbstractListModel38class Q_DECL_EXPORT Scopes : public QAbstractListModel
39{39{
40 Q_OBJECT40 Q_OBJECT
4141
@@ -85,6 +85,7 @@
85 Q_OBJECT85 Q_OBJECT
8686
87public:87public:
88 void setRuntimeConfig(QString const& config);
88 void run() override;89 void run() override;
89 unity::api::scopes::Runtime::UPtr takeRuntime();90 unity::api::scopes::Runtime::UPtr takeRuntime();
90 unity::api::scopes::MetadataMap metadataMap() const;91 unity::api::scopes::MetadataMap metadataMap() const;
@@ -93,6 +94,7 @@
93 void discoveryFinished();94 void discoveryFinished();
9495
95private:96private:
97 QString m_runtimeConfig;
96 unity::api::scopes::Runtime::UPtr m_scopesRuntime;98 unity::api::scopes::Runtime::UPtr m_scopesRuntime;
97 unity::api::scopes::MetadataMap m_metadataMap;99 unity::api::scopes::MetadataMap m_metadataMap;
98};100};
99101
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2013-11-25 15:07:51 +0000
+++ tests/CMakeLists.txt 2013-12-12 12:53:45 +0000
@@ -1,8 +1,15 @@
1include(FindPkgConfig)
1pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0>=7.1.1)2pkg_check_modules(UNITYCORE REQUIRED unity-core-6.0>=7.1.1)
2pkg_check_modules(LIBUNITYPROTO REQUIRED unity-protocol-private)3pkg_check_modules(LIBUNITYPROTO REQUIRED unity-protocol-private)
3pkg_check_modules(LIBUNITY REQUIRED unity)4pkg_check_modules(LIBUNITY REQUIRED unity)
4pkg_check_modules(LIBSIGCPP REQUIRED sigc++-2.0)5pkg_check_modules(LIBSIGCPP REQUIRED sigc++-2.0)
5pkg_check_modules(QTDEE REQUIRED libdee-qt5>=3.2)6pkg_check_modules(QTDEE REQUIRED libdee-qt5>=3.2)
7pkg_check_modules(SCOPESLIB REQUIRED libunity-scopes>=0.1.3)
8
9set(SCOPES_BIN_DIR ${SCOPESLIB_LIBDIR})
10set(SCOPES_TEST_RUNTIME ${CMAKE_CURRENT_BINARY_DIR}/data/Runtime.ini)
11
12add_subdirectory(data)
613
7include_directories(14include_directories(
8 ${Unity-qml_SOURCE_DIR}15 ${Unity-qml_SOURCE_DIR}
@@ -13,6 +20,7 @@
13 ${LIBSIGCPP_INCLUDE_DIRS}20 ${LIBSIGCPP_INCLUDE_DIRS}
14 ${UNITYCORE_INCLUDE_DIRS}21 ${UNITYCORE_INCLUDE_DIRS}
15 ${QTDEE_INCLUDE_DIRS}22 ${QTDEE_INCLUDE_DIRS}
23 ${SCOPESLIB_INCLUDE_DIRS}
16 )24 )
1725
18macro(run_tests)26macro(run_tests)
@@ -27,7 +35,9 @@
27 add_executable(${_test}Exec ${_test}.cpp)35 add_executable(${_test}Exec ${_test}.cpp)
28 qt5_use_modules(${_test}Exec Test Core Qml)36 qt5_use_modules(${_test}Exec Test Core Qml)
29 set_tests_properties(test${CLASSNAME}${_test}37 set_tests_properties(test${CLASSNAME}${_test}
30 PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal;LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Unity:${LIBUNITYPROTO_LIBRARY_DIRS}")38 PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal;LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Unity:${LIBUNITYPROTO_LIBRARY_DIRS};UNITY_SCOPES_RUNTIME_PATH=${SCOPES_TEST_RUNTIME}")
39 set_target_properties(${_test}Exec
40 PROPERTIES COMPILE_FLAGS "-DTEST_SCOPEREGISTRY_BIN='\"${SCOPES_BIN_DIR}/scoperegistry/scoperegistry\"' -DTEST_RUNTIME_CONFIG='\"${SCOPES_TEST_RUNTIME}\"'")
3141
32 target_link_libraries(${_test}Exec42 target_link_libraries(${_test}Exec
33 Unity-qml43 Unity-qml
@@ -36,6 +46,7 @@
36 ${LIBUNITYPROTO_LDFLAGS}46 ${LIBUNITYPROTO_LDFLAGS}
37 ${LIBSIGCPP_LDFLAGS}47 ${LIBSIGCPP_LDFLAGS}
38 ${QTDEE_LDFLAGS}48 ${QTDEE_LDFLAGS}
49 ${SCOPESLIB_LDFLAGS}
39 )50 )
4051
41 set(_test_list "${_test_list};${_test}")52 set(_test_list "${_test_list};${_test}")
@@ -47,4 +58,5 @@
47 previewbindingstest58 previewbindingstest
48 filtersbindingstest59 filtersbindingstest
49 resultstest60 resultstest
61 resultstest-ng
50 )62 )
5163
=== added directory 'tests/data'
=== added file 'tests/data/CMakeLists.txt'
--- tests/data/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/data/CMakeLists.txt 2013-12-12 12:53:45 +0000
@@ -0,0 +1,7 @@
1add_subdirectory(mock-scope)
2
3configure_file(Runtime.ini.in Runtime.ini @ONLY)
4configure_file(Registry.ini.in Registry.ini @ONLY)
5configure_file(Zmq.ini.in Zmq.ini @ONLY)
6
7execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/endpoints)
08
=== added file 'tests/data/Registry.ini.in'
--- tests/data/Registry.ini.in 1970-01-01 00:00:00 +0000
+++ tests/data/Registry.ini.in 2013-12-12 12:53:45 +0000
@@ -0,0 +1,7 @@
1[Registry]
2Middleware = Zmq
3Zmq.Endpoint = ipc:///tmp/scopes-test-endpoints/Registry
4Zmq.EndpointDir = /tmp/scopes-test-endpoints
5Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini
6Scope.InstallDir = @CMAKE_CURRENT_BINARY_DIR@
7Scoperunner.Path = @SCOPES_BIN_DIR@/scoperunner/scoperunner
08
=== added file 'tests/data/Runtime.ini.in'
--- tests/data/Runtime.ini.in 1970-01-01 00:00:00 +0000
+++ tests/data/Runtime.ini.in 2013-12-12 12:53:45 +0000
@@ -0,0 +1,6 @@
1[Runtime]
2Registry.Identity = Registry
3Registry.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Registry.ini
4Default.Middleware = Zmq
5Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini
6Factory.ConfigFile = Factory.ini
07
=== added file 'tests/data/Zmq.ini.in'
--- tests/data/Zmq.ini.in 1970-01-01 00:00:00 +0000
+++ tests/data/Zmq.ini.in 2013-12-12 12:53:45 +0000
@@ -0,0 +1,3 @@
1[Zmq]
2EndpointDir.Public = /tmp/scopes-test-endpoints
3EndpointDir.Private = /tmp/scopes-test-endpoints
04
=== added directory 'tests/data/mock-scope'
=== added file 'tests/data/mock-scope/CMakeLists.txt'
--- tests/data/mock-scope/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/data/mock-scope/CMakeLists.txt 2013-12-12 12:53:45 +0000
@@ -0,0 +1,11 @@
1include(FindPkgConfig)
2pkg_check_modules(SCOPESLIB REQUIRED libunity-scopes>=0.1.2)
3
4set(SCOPES_BIN_DIR ${SCOPESLIB_LIBDIR})
5
6include_directories(${SCOPESLIB_INCLUDE_DIRS})
7
8add_library(mock-scope MODULE mock-scope.cpp)
9target_link_libraries(mock-scope ${SCOPESLIB_LDFLAGS})
10
11configure_file(mock-scope.ini.in mock-scope.ini)
012
=== added file 'tests/data/mock-scope/mock-scope.cpp'
--- tests/data/mock-scope/mock-scope.cpp 1970-01-01 00:00:00 +0000
+++ tests/data/mock-scope/mock-scope.cpp 2013-12-12 12:53:45 +0000
@@ -0,0 +1,119 @@
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
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 General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Michal Hruby <michal.hruby@canonical.com>
18 */
19
20#include <scopes/ScopeBase.h>
21#include <scopes/Reply.h>
22#include <scopes/Category.h>
23#include <scopes/CategorisedResult.h>
24#include <scopes/CategoryRenderer.h>
25
26#include <iostream>
27
28#define EXPORT __attribute__ ((visibility ("default")))
29
30using namespace std;
31using namespace unity::api::scopes;
32
33// Example scope A: replies synchronously to a query. (Replies are returned before returning from the run() method.)
34
35class MyQuery : public QueryBase
36{
37public:
38 MyQuery(string const& query) :
39 query_(query)
40 {
41 }
42
43 ~MyQuery() noexcept
44 {
45 }
46
47 virtual void cancelled() override
48 {
49 }
50
51 virtual void run(ReplyProxy const& reply) override
52 {
53 CategoryRenderer rdr;
54 if (query_ == "metadata")
55 {
56 auto cat = reply->register_category("cat1", "Category 1", "", rdr);
57 CategorisedResult res(cat);
58 res.set_uri("test:uri");
59 res.set_title("result for: \"" + query_ + "\"");
60 res.set_art("art");
61 res.set_dnd_uri("test:dnd_uri");
62 res.add_metadata("subtitle", Variant("subtitle"));
63 res.add_metadata("emblem", Variant("emblem"));
64 reply->push(res);
65 }
66 else
67 {
68 auto cat = reply->register_category("cat1", "Category 1", "", rdr);
69 CategorisedResult res(cat);
70 res.set_uri("test:uri");
71 res.set_title("result for: \"" + query_ + "\"");
72 res.set_art("art");
73 res.set_dnd_uri("test:dnd_uri");
74 reply->push(res);
75 }
76 }
77
78private:
79 string query_;
80};
81
82class MyScope : public ScopeBase
83{
84public:
85 virtual int start(string const&, RegistryProxy const&) override
86 {
87 return VERSION;
88 }
89
90 virtual void stop() override {}
91
92 virtual QueryBase::UPtr create_query(string const& q, VariantMap const&) override
93 {
94 QueryBase::UPtr query(new MyQuery(q));
95 cout << "scope-A: created query: \"" << q << "\"" << endl;
96 return query;
97 }
98};
99
100extern "C"
101{
102
103 EXPORT
104 unity::api::scopes::ScopeBase*
105 // cppcheck-suppress unusedFunction
106 UNITY_API_SCOPE_CREATE_FUNCTION()
107 {
108 return new MyScope;
109 }
110
111 EXPORT
112 void
113 // cppcheck-suppress unusedFunction
114 UNITY_API_SCOPE_DESTROY_FUNCTION(unity::api::scopes::ScopeBase* scope_base)
115 {
116 delete scope_base;
117 }
118
119}
0120
=== added file 'tests/data/mock-scope/mock-scope.ini.in'
--- tests/data/mock-scope/mock-scope.ini.in 1970-01-01 00:00:00 +0000
+++ tests/data/mock-scope/mock-scope.ini.in 2013-12-12 12:53:45 +0000
@@ -0,0 +1,7 @@
1[ScopeConfig]
2DisplayName = mock.DisplayName
3Description = mock.Description
4Art = mock.Art
5Icon = mock.Icon
6SearchHint = mock.SearchHint
7HotKey = mock.HotKey
08
=== added file 'tests/resultstest-ng.cpp'
--- tests/resultstest-ng.cpp 1970-01-01 00:00:00 +0000
+++ tests/resultstest-ng.cpp 2013-12-12 12:53:45 +0000
@@ -0,0 +1,200 @@
1/*
2 * Copyright (C) 2013 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
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 General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Michal Hruby <michal.hruby@canonical.com>
18 */
19
20#include <QObject>
21#include <QTest>
22#include <QFile>
23#include <QFileInfo>
24#include <QDir>
25#include <QProcess>
26#include <QThread>
27#include <QScopedPointer>
28
29#include <scopes-ng/scopes.h>
30#include <scopes-ng/scope.h>
31#include <scopes-ng/categories.h>
32#include <scopes-ng/resultsmodel.h>
33
34#define SCOPES_TMP_ENDPOINT_DIR "/tmp/scopes-test-endpoints"
35
36using namespace scopes_ng;
37
38class ResultsTestNg : public QObject
39{
40 Q_OBJECT
41private:
42 QScopedPointer<Scopes> m_scopes;
43 Scope* m_scope;
44 QScopedPointer<QProcess> m_registry;
45
46private Q_SLOTS:
47 void initTestCase()
48 {
49 QDir endpointdir(QFileInfo(TEST_RUNTIME_CONFIG).dir());
50 endpointdir.cd(QString("endpoints"));
51 QFile::remove(SCOPES_TMP_ENDPOINT_DIR);
52 // symlinking to workaround "File name too long" issue
53 QVERIFY2(QFile::link(endpointdir.absolutePath(), SCOPES_TMP_ENDPOINT_DIR),
54 "Unable to create symlink " SCOPES_TMP_ENDPOINT_DIR);
55 // startup our private scope registry
56 QString registryBin(TEST_SCOPEREGISTRY_BIN);
57 QStringList arguments;
58 arguments << TEST_RUNTIME_CONFIG;
59
60 m_registry.reset(new QProcess(nullptr));
61 m_registry->start(registryBin, arguments);
62 }
63
64 void cleanupTestCase()
65 {
66 if (m_registry) {
67 m_registry->terminate();
68 if (!m_registry->waitForFinished()) {
69 m_registry->kill();
70 }
71 }
72 QFile::remove(SCOPES_TMP_ENDPOINT_DIR);
73 }
74
75 void init()
76 {
77 m_scopes.reset(new Scopes(nullptr));
78 // no scopes on startup
79 QCOMPARE(m_scopes->rowCount(), 0);
80 // wait till the registry spawns
81 QTRY_COMPARE(m_scopes->loaded(), true);
82 // should have one scope now
83 QCOMPARE(m_scopes->rowCount(), 1);
84
85 QVariant scope_var = m_scopes->data(m_scopes->index(0), Scopes::Roles::RoleScope);
86 QVERIFY(scope_var.canConvert<Scope*>());
87
88 // get scope proxy
89 m_scope = scope_var.value<Scope*>();
90 }
91
92 void cleanup()
93 {
94 m_scopes.reset();
95 m_scope = nullptr;
96 }
97
98 void testScopeCommunication()
99 {
100 QCOMPARE(m_scope->searchInProgress(), false);
101 // perform a search
102 m_scope->setSearchQuery(QString(""));
103 QCOMPARE(m_scope->searchInProgress(), true);
104 QTRY_COMPARE(m_scope->searchInProgress(), false);
105
106 // ensure categories have > 0 rows
107 auto categories = m_scope->categories();
108 QVERIFY(categories->rowCount() > 0);
109 QVariant results_var = categories->data(categories->index(0), Categories::Roles::RoleResults);
110 QVERIFY(results_var.canConvert<ResultsModel*>());
111
112 // ensure results have some data
113 auto results = results_var.value<ResultsModel*>();
114 QVERIFY(results->rowCount() > 0);
115 }
116
117 void testScopesGet()
118 {
119 QVariant scope_var = m_scopes->get(0);
120 QVERIFY(scope_var.canConvert<scopes_ng::Scope*>());
121
122 // try incorrect index as well
123 scope_var = m_scopes->get(65536);
124 QVERIFY(scope_var.isNull());
125 scope_var = m_scopes->get(-1);
126 QVERIFY(scope_var.isNull());
127 }
128
129 void testTwoSearches()
130 {
131 QCOMPARE(m_scope->searchInProgress(), false);
132 // perform a search
133 m_scope->setSearchQuery(QString(""));
134 QCOMPARE(m_scope->searchInProgress(), true);
135 QTRY_COMPARE(m_scope->searchInProgress(), false);
136
137 // ensure categories have > 0 rows
138 auto categories = m_scope->categories();
139 auto categories_count = categories->rowCount();
140 QVERIFY(categories_count > 0);
141
142 m_scope->setSearchQuery(QString("foo"));
143 QCOMPARE(m_scope->searchInProgress(), true);
144 // wait for the search to finish
145 QTRY_COMPARE(m_scope->searchInProgress(), false);
146
147 // shouldn't create more nor fewer categories
148 QVERIFY(categories->rowCount() == categories_count);
149 }
150
151 void testBasicResultData()
152 {
153 QCOMPARE(m_scope->searchInProgress(), false);
154 // perform a search
155 m_scope->setSearchQuery(QString(""));
156 QCOMPARE(m_scope->searchInProgress(), true);
157 QTRY_COMPARE(m_scope->searchInProgress(), false);
158
159 // get ResultsModel instance
160 auto categories = m_scope->categories();
161 QVERIFY(categories->rowCount() > 0);
162 QVariant results_var = categories->data(categories->index(0), Categories::Roles::RoleResults);
163 QVERIFY(results_var.canConvert<ResultsModel*>());
164 auto results = results_var.value<ResultsModel*>();
165 QVERIFY(results->rowCount() > 0);
166
167 auto idx = results->index(0);
168 QCOMPARE(results->data(idx, ResultsModel::Roles::RoleUri).toString(), QString("test:uri"));
169 QCOMPARE(results->data(idx, ResultsModel::Roles::RoleDndUri).toString(), QString("test:dnd_uri"));
170 QCOMPARE(results->data(idx, ResultsModel::Roles::RoleTitle).toString(), QString("result for: \"\""));
171 QCOMPARE(results->data(idx, ResultsModel::Roles::RoleArt).toString(), QString("art"));
172 QCOMPARE(results->data(idx, ResultsModel::Roles::RoleCategoryId), categories->data(categories->index(0), Categories::Roles::RoleCategoryId));
173 }
174
175 void testMetadataData()
176 {
177 QCOMPARE(m_scope->searchInProgress(), false);
178 // perform a search
179 m_scope->setSearchQuery(QString("metadata"));
180 QCOMPARE(m_scope->searchInProgress(), true);
181 QTRY_COMPARE(m_scope->searchInProgress(), false);
182
183 // get ResultsModel instance
184 auto categories = m_scope->categories();
185 QVERIFY(categories->rowCount() > 0);
186 QVariant results_var = categories->data(categories->index(0), Categories::Roles::RoleResults);
187 QVERIFY(results_var.canConvert<ResultsModel*>());
188 auto results = results_var.value<ResultsModel*>();
189 QVERIFY(results->rowCount() > 0);
190
191 auto idx = results->index(0);
192 QCOMPARE(results->data(idx, ResultsModel::Roles::RoleTitle).toString(), QString("result for: \"metadata\""));
193 QCOMPARE(results->data(idx, ResultsModel::Roles::RoleSubtitle).toString(), QString("subtitle"));
194 QCOMPARE(results->data(idx, ResultsModel::Roles::RoleEmblem).toString(), QString("emblem"));
195 QCOMPARE(results->data(idx, ResultsModel::Roles::RoleAltRating).toString(), QString());
196 }
197};
198
199QTEST_MAIN(ResultsTestNg)
200#include <resultstest-ng.moc>

Subscribers

People subscribed via source and target branches

to all changes: