Merge lp:~dobey/unity-scope-click/check-purchased into lp:unity-scope-click/devel

Proposed by dobey
Status: Merged
Approved by: Alejandro J. Cura
Approved revision: 333
Merged at revision: 343
Proposed branch: lp:~dobey/unity-scope-click/check-purchased
Merge into: lp:unity-scope-click/devel
Diff against target: 876 lines (+517/-39)
13 files modified
debian/control (+2/-0)
libclickscope/click/preview.cpp (+2/-1)
scope/clickstore/CMakeLists.txt (+4/-0)
scope/clickstore/pay.cpp (+150/-0)
scope/clickstore/pay.h (+67/-0)
scope/clickstore/store-query.cpp (+30/-11)
scope/clickstore/store-query.h (+9/-12)
scope/clickstore/store-scope.cpp (+3/-1)
scope/clickstore/store-scope.h (+3/-0)
scope/tests/CMakeLists.txt (+1/-0)
scope/tests/mock_pay.h (+57/-0)
scope/tests/test_pay.cpp (+56/-0)
scope/tests/test_query.cpp (+133/-14)
To merge this branch: bzr merge lp:~dobey/unity-scope-click/check-purchased
Reviewer Review Type Date Requested Status
Alejandro J. Cura (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+227111@code.launchpad.net

Commit message

Check for already purchased apps in search results in the store scope.

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

Merge tip of devel branch.
Move mock pay code to mock_pay.h.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Jenkins is crashing on this test:
QueryTest.testAddAvailableAppsCallsClickIndex

it seems to need some extra mocking in the bootstrap code.

review: Needs Fixing
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Please check in the test that the values for these keys are the expected ones:

            res[click::Query::ResultKeys::PURCHASED] = true;
            res[click::Query::ResultKeys::INSTALLED] = false;
            res["subtitle"] = _("✔ PURCHASED");

To do this, the Property matcher used in line 682 of the diff should be replaced by a custom matcher, like used in some other tests in our codebase.

---

I couldn't find any unit test for pay.cpp. Perhaps you forgot to bzr add some test file?

review: Needs Fixing
330. By dobey

Refactor to avoid dbus in tests.

331. By dobey

Add direct tests for pay::Package.

332. By dobey

Add more tests to verify that purchased/installed flags are correctly set.

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)
333. By dobey

Add pay-service as a binary dep now that we're using libpay.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Looks good now, thanks for adding moar testz!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2014-07-11 21:56:59 +0000
3+++ debian/control 2014-07-17 20:26:32 +0000
4@@ -9,6 +9,7 @@
5 libboost-locale-dev,
6 libglib2.0-dev (>= 2.32),
7 libjsoncpp-dev,
8+ libpay1-dev,
9 libubuntu-download-manager-client-dev (>= 0.3+14.10.20140430-0ubuntu1),
10 libubuntu-download-manager-common-dev (>= 0.3+14.10.20140430-0ubuntu1),
11 libubuntuoneauth-2.0-dev,
12@@ -27,6 +28,7 @@
13 Architecture: armhf i386 amd64
14 Depends: account-plugin-ubuntuone,
15 packagekit-tools,
16+ pay-service,
17 ubuntu-app-launch-tools,
18 ubuntu-download-manager,
19 ubuntu-sdk-libs,
20
21=== modified file 'libclickscope/click/preview.cpp'
22--- libclickscope/click/preview.cpp 2014-07-14 15:35:10 +0000
23+++ libclickscope/click/preview.cpp 2014-07-17 20:26:32 +0000
24@@ -761,7 +761,8 @@
25 scopes::PreviewWidgetList UninstalledPreview::uninstalledActionButtonWidgets(const PackageDetails &details)
26 {
27 scopes::PreviewWidgetList widgets;
28- if (details.package.price > double(0.00)) {
29+ if (details.package.price > double(0.00)
30+ && result["purchased"].get_bool() == false) {
31 scopes::PreviewWidget payments("purchase", "payments");
32 scopes::VariantMap tuple;
33 tuple["currency"] = "$";
34
35=== modified file 'scope/clickstore/CMakeLists.txt'
36--- scope/clickstore/CMakeLists.txt 2014-07-02 15:24:07 +0000
37+++ scope/clickstore/CMakeLists.txt 2014-07-17 20:26:32 +0000
38@@ -3,6 +3,7 @@
39 find_package (Qt5Core REQUIRED)
40 find_package (Qt5Sql REQUIRED)
41 pkg_check_modules(JSON_CPP REQUIRED jsoncpp)
42+pkg_check_modules(LIBPAY REQUIRED pay-1)
43
44 add_definitions(
45 -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\"
46@@ -10,6 +11,7 @@
47 )
48
49 add_library(${STORE_LIB_UNVERSIONED} SHARED
50+ pay.cpp
51 store-query.cpp
52 store-scope.cpp
53 )
54@@ -18,6 +20,7 @@
55 include_directories(
56 ${CMAKE_SOURCE_DIR}/libclickscope
57 ${JSON_CPP_INCLUDE_DIRS}
58+ ${LIBPAY_INCLUDE_DIRS}
59 )
60
61 qt5_use_modules (${STORE_LIB_UNVERSIONED} Network Sql)
62@@ -27,6 +30,7 @@
63 ${JSON_CPP_LDFLAGS}
64 ${UNITY_SCOPES_LDFLAGS}
65 ${UBUNTUONE_LDFLAGS}
66+ ${LIBPAY_LDFLAGS}
67 ${UBUNTU_DOWNLOAD_MANAGER_CLIENT_LDFLAGS}
68 ${UBUNTU_DOWNLOAD_MANAGER_COMMON_LDFLAGS}
69 )
70
71=== added file 'scope/clickstore/pay.cpp'
72--- scope/clickstore/pay.cpp 1970-01-01 00:00:00 +0000
73+++ scope/clickstore/pay.cpp 2014-07-17 20:26:32 +0000
74@@ -0,0 +1,150 @@
75+/*
76+ * Copyright (C) 2014 Canonical Ltd.
77+ *
78+ * This program is free software: you can redistribute it and/or modify it
79+ * under the terms of the GNU General Public License version 3, as published
80+ * by the Free Software Foundation.
81+ *
82+ * This program is distributed in the hope that it will be useful, but
83+ * WITHOUT ANY WARRANTY; without even the implied warranties of
84+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
85+ * PURPOSE. See the GNU General Public License for more details.
86+ *
87+ * You should have received a copy of the GNU General Public License along
88+ * with this program. If not, see <http://www.gnu.org/licenses/>.
89+ *
90+ * In addition, as a special exception, the copyright holders give
91+ * permission to link the code of portions of this program with the
92+ * OpenSSL library under certain conditions as described in each
93+ * individual source file, and distribute linked combinations
94+ * including the two.
95+ * You must obey the GNU General Public License in all respects
96+ * for all of the code used other than OpenSSL. If you modify
97+ * file(s) with this exception, you may extend this exception to your
98+ * version of the file(s), but you are not obligated to do so. If you
99+ * do not wish to do so, delete this exception statement from your
100+ * version. If you delete this exception statement from all source
101+ * files in the program, then also delete it here.
102+ */
103+
104+#include "pay.h"
105+
106+#include <future>
107+
108+#include <glib.h>
109+#include <libpay/pay-package.h>
110+
111+#include <QDebug>
112+
113+struct pay::Package::Private
114+{
115+ Private()
116+ {
117+ }
118+
119+ virtual ~Private()
120+ {
121+ }
122+
123+ PayPackage *pay_package;
124+};
125+
126+
127+static void pay_verification_observer(PayPackage*,
128+ const char* item_id,
129+ PayPackageItemStatus status,
130+ void* user_data)
131+{
132+ pay::Package* p = static_cast<pay::Package*>(user_data);
133+ if (p->callbacks.count(item_id) == 0) {
134+ // Do nothing if we don't have a callback registered.
135+ return;
136+ }
137+
138+ switch (status) {
139+ case PAY_PACKAGE_ITEM_STATUS_PURCHASED:
140+ p->callbacks[item_id](item_id, true);
141+ break;
142+ case PAY_PACKAGE_ITEM_STATUS_NOT_PURCHASED:
143+ p->callbacks[item_id](item_id, false);
144+ break;
145+ default:
146+ break;
147+ }
148+}
149+
150+
151+namespace pay {
152+
153+Package::Package() :
154+ impl(new Private())
155+{
156+}
157+
158+Package::~Package()
159+{
160+ if (running) {
161+ pay_package_item_observer_uninstall(impl->pay_package,
162+ pay_verification_observer,
163+ this);
164+ pay_package_delete(impl->pay_package);
165+ }
166+}
167+
168+bool Package::verify(const std::string& pkg_name)
169+{
170+ typedef std::pair<std::string, bool> _PurchasedTuple;
171+ std::promise<_PurchasedTuple> purchased_promise;
172+ std::future<_PurchasedTuple> purchased_future = purchased_promise.get_future();
173+ _PurchasedTuple result;
174+
175+ if (callbacks.count(pkg_name) == 0) {
176+ callbacks[pkg_name] = [pkg_name,
177+ &purchased_promise](const std::string& item_id,
178+ bool purchased) {
179+ if (item_id == pkg_name) {
180+ _PurchasedTuple found_purchase{item_id, purchased};
181+ try {
182+ purchased_promise.set_value(found_purchase);
183+ } catch (std::future_error) {
184+ // Just log this to avoid crashing, as it seems that
185+ // sometimes this callback may be called more than once.
186+ qDebug() << "Callback called again for:" << item_id.c_str();
187+ }
188+ }
189+ };
190+ qDebug() << "Checking if " << pkg_name.c_str() << " was purchased.";
191+ pay_package_verify(pkg_name);
192+
193+ result = purchased_future.get();
194+
195+ callbacks.erase(pkg_name);
196+
197+ return result.second;
198+ }
199+ return false;
200+}
201+
202+void Package::setup_pay_service()
203+{
204+ impl->pay_package = pay_package_new(Package::NAME);
205+ pay_package_item_observer_install(impl->pay_package,
206+ pay_verification_observer,
207+ this);
208+ running = true;
209+}
210+
211+void Package::pay_package_verify(const std::string& pkg_name)
212+{
213+ if (!running) {
214+ setup_pay_service();
215+ }
216+
217+ if (callbacks.count(pkg_name) == 0) {
218+ return;
219+ }
220+
221+ pay_package_item_start_verification(impl->pay_package, pkg_name.c_str());
222+}
223+
224+} // namespace pay
225
226=== added file 'scope/clickstore/pay.h'
227--- scope/clickstore/pay.h 1970-01-01 00:00:00 +0000
228+++ scope/clickstore/pay.h 2014-07-17 20:26:32 +0000
229@@ -0,0 +1,67 @@
230+/*
231+ * Copyright (C) 2014 Canonical Ltd.
232+ *
233+ * This program is free software: you can redistribute it and/or modify it
234+ * under the terms of the GNU General Public License version 3, as published
235+ * by the Free Software Foundation.
236+ *
237+ * This program is distributed in the hope that it will be useful, but
238+ * WITHOUT ANY WARRANTY; without even the implied warranties of
239+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
240+ * PURPOSE. See the GNU General Public License for more details.
241+ *
242+ * You should have received a copy of the GNU General Public License along
243+ * with this program. If not, see <http://www.gnu.org/licenses/>.
244+ *
245+ * In addition, as a special exception, the copyright holders give
246+ * permission to link the code of portions of this program with the
247+ * OpenSSL library under certain conditions as described in each
248+ * individual source file, and distribute linked combinations
249+ * including the two.
250+ * You must obey the GNU General Public License in all respects
251+ * for all of the code used other than OpenSSL. If you modify
252+ * file(s) with this exception, you may extend this exception to your
253+ * version of the file(s), but you are not obligated to do so. If you
254+ * do not wish to do so, delete this exception statement from your
255+ * version. If you delete this exception statement from all source
256+ * files in the program, then also delete it here.
257+ */
258+
259+#ifndef _PAY_H_
260+#define _PAY_H_
261+
262+#include <map>
263+#include <memory>
264+
265+
266+namespace pay
267+{
268+ class Package
269+ {
270+ public:
271+ typedef std::function<void(const std::string& item_id,
272+ bool status)> StatusFunction;
273+
274+ constexpr static const char* NAME{"click-scope"};
275+
276+ Package();
277+ virtual ~Package();
278+
279+ virtual bool verify(const std::string& pkg_name);
280+
281+ protected:
282+ virtual void setup_pay_service();
283+ virtual void pay_package_verify(const std::string& pkg_name);
284+
285+ private:
286+ struct Private;
287+ std::shared_ptr<pay::Package::Private> impl;
288+
289+ bool running = false;
290+ public:
291+ std::map<std::string, StatusFunction> callbacks;
292+ };
293+
294+} //namespace pay
295+
296+#endif // _PAY_H_
297
298=== modified file 'scope/clickstore/store-query.cpp'
299--- scope/clickstore/store-query.cpp 2014-07-14 08:49:39 +0000
300+++ scope/clickstore/store-query.cpp 2014-07-17 20:26:32 +0000
301@@ -27,15 +27,15 @@
302 * files in the program, then also delete it here.
303 */
304
305+#include "store-query.h"
306+#include "store-scope.h"
307+
308 #include <click/application.h>
309 #include <click/interface.h>
310-#include "store-query.h"
311-#include "store-scope.h"
312+#include <click/key_file_locator.h>
313 #include <click/qtbridge.h>
314 #include <click/departments-db.h>
315
316-#include <click/key_file_locator.h>
317-
318 #include <unity/scopes/Annotation.h>
319 #include <unity/scopes/CategoryRenderer.h>
320 #include <unity/scopes/CategorisedResult.h>
321@@ -116,12 +116,15 @@
322 {
323 Private(click::Index& index, click::DepartmentLookup& depts,
324 std::shared_ptr<click::DepartmentsDb> depts_db,
325- click::HighlightList& highlights, const scopes::SearchMetadata& metadata)
326+ click::HighlightList& highlights,
327+ const scopes::SearchMetadata& metadata,
328+ pay::Package& in_package)
329 : index(index),
330 department_lookup(depts),
331 depts_db(depts_db),
332 highlights(highlights),
333- meta(metadata)
334+ meta(metadata),
335+ pay_package(in_package)
336 {
337 }
338 click::Index& index;
339@@ -130,14 +133,18 @@
340 click::HighlightList& highlights;
341 scopes::SearchMetadata meta;
342 click::web::Cancellable search_operation;
343+ pay::Package& pay_package;
344 };
345
346-click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& depts,
347- std::shared_ptr<click::DepartmentsDb> depts_db,
348- click::HighlightList& highlights,
349- scopes::SearchMetadata const& metadata)
350+click::Query::Query(unity::scopes::CannedQuery const& query,
351+ click::Index& index,
352+ click::DepartmentLookup& depts,
353+ std::shared_ptr<click::DepartmentsDb> depts_db,
354+ click::HighlightList& highlights,
355+ scopes::SearchMetadata const& metadata,
356+ pay::Package& in_package)
357 : unity::scopes::SearchQueryBase(query, metadata),
358- impl(new Private(index, depts, depts_db, highlights, metadata))
359+ impl(new Private(index, depts, depts_db, highlights, metadata, in_package))
360 {
361 }
362
363@@ -264,12 +271,24 @@
364 res.set_uri(pkg.url);
365 res[click::Query::ResultKeys::NAME] = pkg.name;
366 auto installed = installedPackages.find(pkg);
367+
368+ bool purchased = false;
369+ if (pkg.price > 0.00f) {
370+ // Check if the priced app was already purchased.
371+ purchased = impl->pay_package.verify(pkg.name);
372+ }
373 if (installed != installedPackages.end()) {
374 res[click::Query::ResultKeys::INSTALLED] = true;
375+ res[click::Query::ResultKeys::PURCHASED] = purchased;
376 res["subtitle"] = _("✔ INSTALLED");
377 res[click::Query::ResultKeys::VERSION] = installed->version;
378+ } else if (purchased) {
379+ res[click::Query::ResultKeys::PURCHASED] = true;
380+ res[click::Query::ResultKeys::INSTALLED] = false;
381+ res["subtitle"] = _("✔ PURCHASED");
382 } else {
383 res[click::Query::ResultKeys::INSTALLED] = false;
384+ res[click::Query::ResultKeys::PURCHASED] = false;
385 res["subtitle"] = _("FREE");
386 // TODO: get the real price from the webservice (upcoming branch)
387 }
388
389=== modified file 'scope/clickstore/store-query.h'
390--- scope/clickstore/store-query.h 2014-07-02 15:24:07 +0000
391+++ scope/clickstore/store-query.h 2014-07-17 20:26:32 +0000
392@@ -30,6 +30,7 @@
393 #ifndef STORE_QUERY_H
394 #define STORE_QUERY_H
395
396+#include "pay.h"
397
398 #include <unity/scopes/SearchQueryBase.h>
399 #include <unity/scopes/Department.h>
400@@ -55,16 +56,6 @@
401 class Query : public scopes::SearchQueryBase
402 {
403 public:
404- struct JsonKeys
405- {
406- JsonKeys() = delete;
407-
408- constexpr static const char* RESOURCE_URL{"resource_url"};
409- constexpr static const char* TITLE{"title"};
410- constexpr static const char* ICON_URL{"icon_url"};
411- constexpr static const char* NAME{"name"};
412- };
413-
414 struct ResultKeys
415 {
416 ResultKeys() = delete;
417@@ -73,12 +64,18 @@
418 constexpr static const char* DESCRIPTION{"description"};
419 constexpr static const char* MAIN_SCREENSHOT{"main_screenshot"};
420 constexpr static const char* INSTALLED{"installed"};
421+ constexpr static const char* PURCHASED{"purchased"};
422 constexpr static const char* DOWNLOAD_URL{"download_url"};
423 constexpr static const char* VERSION{"version"};
424 };
425
426- Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& dept_lookup, std::shared_ptr<click::DepartmentsDb> depts_db, click::HighlightList& highlights,
427- scopes::SearchMetadata const& metadata);
428+ Query(unity::scopes::CannedQuery const& query,
429+ click::Index& index,
430+ click::DepartmentLookup& dept_lookup,
431+ std::shared_ptr<click::DepartmentsDb> depts_db,
432+ click::HighlightList& highlights,
433+ scopes::SearchMetadata const& metadata,
434+ pay::Package& in_package);
435 virtual ~Query();
436
437 virtual void cancelled() override;
438
439=== modified file 'scope/clickstore/store-scope.cpp'
440--- scope/clickstore/store-scope.cpp 2014-07-02 15:24:07 +0000
441+++ scope/clickstore/store-scope.cpp 2014-07-17 20:26:32 +0000
442@@ -54,6 +54,8 @@
443 index.reset(new click::Index(client));
444 depts.reset(new click::DepartmentLookup());
445 highlights.reset(new click::HighlightList());
446+ pay_package.reset(new pay::Package());
447+
448 try
449 {
450 depts_db = click::DepartmentsDb::create_db();
451@@ -104,7 +106,7 @@
452
453 scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata)
454 {
455- return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, *depts, depts_db, *highlights, metadata));
456+ return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, *depts, depts_db, *highlights, metadata, *pay_package));
457 }
458
459
460
461=== modified file 'scope/clickstore/store-scope.h'
462--- scope/clickstore/store-scope.h 2014-07-02 15:24:07 +0000
463+++ scope/clickstore/store-scope.h 2014-07-17 20:26:32 +0000
464@@ -30,6 +30,8 @@
465 #ifndef CLICK_SCOPE_H
466 #define CLICK_SCOPE_H
467
468+#include "pay.h"
469+
470 #include <memory>
471 #include <click/network_access_manager.h>
472 #include <click/webclient.h>
473@@ -75,6 +77,7 @@
474 std::shared_ptr<click::DepartmentLookup> depts;
475 std::shared_ptr<click::HighlightList> highlights;
476 std::shared_ptr<click::DepartmentsDb> depts_db;
477+ std::shared_ptr<pay::Package> pay_package;
478
479 std::string installApplication(unity::scopes::Result const& result);
480 static bool old_api;
481
482=== modified file 'scope/tests/CMakeLists.txt'
483--- scope/tests/CMakeLists.txt 2014-07-10 07:51:36 +0000
484+++ scope/tests/CMakeLists.txt 2014-07-17 20:26:32 +0000
485@@ -18,6 +18,7 @@
486 )
487
488 add_executable (${CLICKSCOPE_TESTS_TARGET}
489+ test_pay.cpp
490 test_query.cpp
491 )
492
493
494=== added file 'scope/tests/mock_pay.h'
495--- scope/tests/mock_pay.h 1970-01-01 00:00:00 +0000
496+++ scope/tests/mock_pay.h 2014-07-17 20:26:32 +0000
497@@ -0,0 +1,57 @@
498+/*
499+ * Copyright (C) 2014 Canonical Ltd.
500+ *
501+ * This program is free software: you can redistribute it and/or modify it
502+ * under the terms of the GNU General Public License version 3, as published
503+ * by the Free Software Foundation.
504+ *
505+ * This program is distributed in the hope that it will be useful, but
506+ * WITHOUT ANY WARRANTY; without even the implied warranties of
507+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
508+ * PURPOSE. See the GNU General Public License for more details.
509+ *
510+ * You should have received a copy of the GNU General Public License along
511+ * with this program. If not, see <http://www.gnu.org/licenses/>.
512+ *
513+ * In addition, as a special exception, the copyright holders give
514+ * permission to link the code of portions of this program with the
515+ * OpenSSL library under certain conditions as described in each
516+ * individual source file, and distribute linked combinations
517+ * including the two.
518+ * You must obey the GNU General Public License in all respects
519+ * for all of the code used other than OpenSSL. If you modify
520+ * file(s) with this exception, you may extend this exception to your
521+ * version of the file(s), but you are not obligated to do so. If you
522+ * do not wish to do so, delete this exception statement from your
523+ * version. If you delete this exception statement from all source
524+ * files in the program, then also delete it here.
525+ */
526+
527+#include "clickstore/pay.h"
528+
529+#include <gtest/gtest.h>
530+#include <gmock/gmock.h>
531+
532+
533+namespace
534+{
535+
536+ class MockPayPackage : public pay::Package {
537+ public:
538+ MockPayPackage()
539+ {
540+ }
541+
542+ void pay_package_verify(const std::string& pkg_name)
543+ {
544+ callbacks[pkg_name](pkg_name, purchased);
545+ do_pay_package_verify(pkg_name);
546+ }
547+
548+ MOCK_METHOD0(setup_pay_service, void());
549+ MOCK_METHOD1(do_pay_package_verify, void(const std::string&));
550+
551+ bool purchased = false;
552+};
553+
554+} // namespace
555
556=== added file 'scope/tests/test_pay.cpp'
557--- scope/tests/test_pay.cpp 1970-01-01 00:00:00 +0000
558+++ scope/tests/test_pay.cpp 2014-07-17 20:26:32 +0000
559@@ -0,0 +1,56 @@
560+/*
561+ * Copyright (C) 2014 Canonical Ltd.
562+ *
563+ * This program is free software: you can redistribute it and/or modify it
564+ * under the terms of the GNU General Public License version 3, as published
565+ * by the Free Software Foundation.
566+ *
567+ * This program is distributed in the hope that it will be useful, but
568+ * WITHOUT ANY WARRANTY; without even the implied warranties of
569+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
570+ * PURPOSE. See the GNU General Public License for more details.
571+ *
572+ * You should have received a copy of the GNU General Public License along
573+ * with this program. If not, see <http://www.gnu.org/licenses/>.
574+ *
575+ * In addition, as a special exception, the copyright holders give
576+ * permission to link the code of portions of this program with the
577+ * OpenSSL library under certain conditions as described in each
578+ * individual source file, and distribute linked combinations
579+ * including the two.
580+ * You must obey the GNU General Public License in all respects
581+ * for all of the code used other than OpenSSL. If you modify
582+ * file(s) with this exception, you may extend this exception to your
583+ * version of the file(s), but you are not obligated to do so. If you
584+ * do not wish to do so, delete this exception statement from your
585+ * version. If you delete this exception statement from all source
586+ * files in the program, then also delete it here.
587+ */
588+
589+#include "mock_pay.h"
590+
591+#include <gtest/gtest.h>
592+#include <gmock/gmock.h>
593+
594+
595+TEST(PayTest, testPayPackageVerifyCalled)
596+{
597+ MockPayPackage package;
598+ EXPECT_CALL(package, do_pay_package_verify("foo")).Times(1);
599+ EXPECT_EQ(false, package.verify("foo"));
600+}
601+
602+TEST(PayTest, testPayPackageVerifyNotCalledIfCallbackExists)
603+{
604+ MockPayPackage package;
605+ package.callbacks["foo"] = [](const std::string&, bool) {};
606+ EXPECT_CALL(package, do_pay_package_verify("foo")).Times(0);
607+ EXPECT_EQ(false, package.verify("foo"));
608+}
609+
610+TEST(PayTest, testVerifyReturnsTrueForPurchasedItem)
611+{
612+ MockPayPackage package;
613+ package.purchased = true;
614+ EXPECT_EQ(true, package.verify("foo"));
615+}
616
617=== modified file 'scope/tests/test_query.cpp'
618--- scope/tests/test_query.cpp 2014-07-16 11:53:51 +0000
619+++ scope/tests/test_query.cpp 2014-07-17 20:26:32 +0000
620@@ -27,6 +27,10 @@
621 * files in the program, then also delete it here.
622 */
623
624+#include "mock_pay.h"
625+
626+#include "clickstore/store-query.h"
627+
628 #include <string>
629 #include <memory>
630
631@@ -34,6 +38,7 @@
632 #include <gmock/gmock.h>
633
634 #include "click/qtbridge.h"
635+#include "click/index.h"
636 #include "clickstore/store-query.h"
637 #include "click/application.h"
638 #include "click/departments-db.h"
639@@ -61,9 +66,10 @@
640 click::DepartmentLookup& depts,
641 std::shared_ptr<click::DepartmentsDb> depts_db,
642 click::HighlightList& highlights,
643- scopes::SearchMetadata const& metadata) : click::Query(query, index, depts, depts_db, highlights, metadata)
644+ scopes::SearchMetadata const& metadata,
645+ pay::Package& in_package) :
646+ click::Query(query, index, depts, depts_db, highlights, metadata, in_package)
647 {
648-
649 }
650
651 void run_under_qt(const std::function<void()> &task) {
652@@ -78,9 +84,10 @@
653 click::DepartmentLookup& depts,
654 std::shared_ptr<click::DepartmentsDb> depts_db,
655 click::HighlightList& highlights,
656- scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, depts_db, highlights, metadata)
657+ scopes::SearchMetadata const& metadata,
658+ pay::Package& in_package) :
659+ MockQueryBase(query, index, depts, depts_db, highlights, metadata, in_package)
660 {
661-
662 }
663 void wrap_add_available_apps(const scopes::SearchReplyProxy &searchReply,
664 const PackageSet &installedPackages,
665@@ -105,9 +112,10 @@
666 click::DepartmentLookup& depts,
667 std::shared_ptr<click::DepartmentsDb> depts_db,
668 click::HighlightList& highlights,
669- scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, depts_db, highlights, metadata)
670+ scopes::SearchMetadata const& metadata,
671+ pay::Package& in_package) :
672+ MockQueryBase(query, index, depts, depts_db, highlights, metadata, in_package)
673 {
674-
675 }
676 MOCK_METHOD3(add_available_apps,
677 void(scopes::SearchReplyProxy const&searchReply,
678@@ -126,9 +134,10 @@
679 click::DepartmentLookup dept_lookup;
680 click::HighlightList highlights;
681 scopes::SearchMetadata metadata("en_EN", "phone");
682+ MockPayPackage pay_pkg;
683 PackageSet no_installed_packages;
684 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
685- MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata);
686+ MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
687 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(1);
688
689 scopes::testing::MockSearchReply mock_reply;
690@@ -151,9 +160,10 @@
691 click::DepartmentLookup dept_lookup;
692 click::HighlightList highlights;
693 scopes::SearchMetadata metadata("en_EN", "phone");
694+ MockPayPackage pay_pkg;
695 PackageSet no_installed_packages;
696 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
697- MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata);
698+ MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
699 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
700
701 scopes::CategoryRenderer renderer("{}");
702@@ -180,9 +190,10 @@
703 click::DepartmentLookup dept_lookup;
704 click::HighlightList highlights;
705 scopes::SearchMetadata metadata("en_EN", "phone");
706+ MockPayPackage pay_pkg;
707 PackageSet no_installed_packages;
708 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
709- MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata);
710+ MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
711 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
712
713 scopes::CategoryRenderer renderer("{}");
714@@ -204,9 +215,10 @@
715 click::DepartmentLookup dept_lookup;
716 click::HighlightList highlights;
717 scopes::SearchMetadata metadata("en_EN", "phone");
718+ MockPayPackage pay_pkg;
719 PackageSet no_installed_packages;
720 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
721- MockQueryRun q(query, mock_index, dept_lookup, nullptr, highlights, metadata);
722+ MockQueryRun q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
723 auto reply = scopes::SearchReplyProxy();
724 EXPECT_CALL(q, get_installed_packages()).WillOnce(Return(no_installed_packages));
725 EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _));
726@@ -230,8 +242,9 @@
727 };
728 click::DepartmentLookup dept_lookup;
729 click::HighlightList highlights;
730+ MockPayPackage pay_pkg;
731 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
732- MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata);
733+ MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
734 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
735
736 scopes::CategoryRenderer renderer("{}");
737@@ -260,8 +273,9 @@
738 };
739 click::DepartmentLookup dept_lookup;
740 click::HighlightList highlights;
741+ MockPayPackage pay_pkg;
742 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
743- MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata);
744+ MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
745 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
746
747 scopes::CategoryRenderer renderer("{}");
748@@ -295,8 +309,9 @@
749 };
750 click::DepartmentLookup dept_lookup;
751 click::HighlightList highlights;
752+ MockPayPackage pay_pkg;
753 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
754- MockQuery q(query, mock_index, dept_lookup, depts_db, highlights, metadata);
755+ MockQuery q(query, mock_index, dept_lookup, depts_db, highlights, metadata, pay_pkg);
756 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
757
758 scopes::CategoryRenderer renderer("{}");
759@@ -323,8 +338,9 @@
760 scopes::SearchMetadata metadata("en_EN", "phone");
761 click::DepartmentLookup dept_lookup;
762 click::HighlightList highlights;
763+ MockPayPackage pay_pkg;
764 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
765- MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata);
766+ MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
767 PackageSet installed_packages{{"package_1", "0.1"}};
768
769 FakeInterface fake_interface;
770@@ -336,3 +352,106 @@
771
772 ASSERT_EQ(q.get_installed_packages(), installed_packages);
773 }
774+
775+typedef std::pair<bool, bool> _PurchasedValues;
776+MATCHER_P(PurchasedProperties, b, "") { return arg[click::Query::ResultKeys::PURCHASED].get_bool() == b.first && arg[click::Query::ResultKeys::INSTALLED].get_bool() == b.second; }
777+
778+TEST(QueryTest, testQueryRunCallsPayPackageVerify)
779+{
780+ click::Packages packages {
781+ {"name", "title", 0.99, "icon", "uri"}
782+ };
783+ MockIndex mock_index(packages);
784+ click::DepartmentLookup dept_lookup;
785+ click::HighlightList highlights;
786+ scopes::SearchMetadata metadata("en_EN", "phone");
787+ MockPayPackage pay_pkg;
788+ PackageSet no_installed_packages;
789+ const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
790+ MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
791+ EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
792+
793+ scopes::CategoryRenderer renderer("{}");
794+ auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
795+
796+ ON_CALL(q, register_category(_, _, _, _, _)).WillByDefault(Return(ptrCat));
797+ EXPECT_CALL(q, register_category(_, "appstore", CategoryHasNumberOfResults(1), _, _));
798+ EXPECT_CALL(q, register_category(_, "recommends", _, _, _));
799+
800+ scopes::testing::MockSearchReply mock_reply;
801+ scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
802+
803+ EXPECT_CALL(pay_pkg, do_pay_package_verify(_)).Times(1);
804+ EXPECT_CALL(q, push_result(_, PurchasedProperties(_PurchasedValues{false, false}))).Times(1);
805+ EXPECT_CALL(q, finished(_));
806+
807+ q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);
808+}
809+
810+TEST(QueryTest, testQueryRunPurchased)
811+{
812+ click::Packages packages {
813+ {"name", "title", 0.99, "icon", "uri"}
814+ };
815+ MockIndex mock_index(packages);
816+ click::DepartmentLookup dept_lookup;
817+ click::HighlightList highlights;
818+ scopes::SearchMetadata metadata("en_EN", "phone");
819+ MockPayPackage pay_pkg;
820+ pay_pkg.purchased = true;
821+ PackageSet no_installed_packages;
822+ const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
823+ MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
824+ EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
825+
826+ scopes::CategoryRenderer renderer("{}");
827+ auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
828+
829+ ON_CALL(q, register_category(_, _, _, _, _)).WillByDefault(Return(ptrCat));
830+ EXPECT_CALL(q, register_category(_, "appstore", CategoryHasNumberOfResults(1), _, _));
831+ EXPECT_CALL(q, register_category(_, "recommends", _, _, _));
832+
833+ scopes::testing::MockSearchReply mock_reply;
834+ scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
835+
836+ EXPECT_CALL(pay_pkg, do_pay_package_verify(_)).Times(1);
837+ EXPECT_CALL(q, push_result(_, PurchasedProperties(_PurchasedValues{true, false}))).Times(1);
838+ EXPECT_CALL(q, finished(_));
839+
840+ q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE);
841+}
842+
843+TEST(QueryTest, testQueryRunPurchasedAndInstalled)
844+{
845+ click::Packages packages {
846+ {"name", "title", 0.99, "icon", "uri"}
847+ };
848+ PackageSet one_installed_package {
849+ {"name", "0.2"}
850+ };
851+ MockIndex mock_index(packages);
852+ click::DepartmentLookup dept_lookup;
853+ click::HighlightList highlights;
854+ scopes::SearchMetadata metadata("en_EN", "phone");
855+ MockPayPackage pay_pkg;
856+ pay_pkg.purchased = true;
857+ const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
858+ MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg);
859+ EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
860+
861+ scopes::CategoryRenderer renderer("{}");
862+ auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
863+
864+ ON_CALL(q, register_category(_, _, _, _, _)).WillByDefault(Return(ptrCat));
865+ EXPECT_CALL(q, register_category(_, "appstore", CategoryHasNumberOfResults(1), _, _));
866+ EXPECT_CALL(q, register_category(_, "recommends", _, _, _));
867+
868+ scopes::testing::MockSearchReply mock_reply;
869+ scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
870+
871+ EXPECT_CALL(pay_pkg, do_pay_package_verify(_)).Times(1);
872+ EXPECT_CALL(q, push_result(_, PurchasedProperties(_PurchasedValues{true, true}))).Times(1);
873+ EXPECT_CALL(q, finished(_));
874+
875+ q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE);
876+}

Subscribers

People subscribed via source and target branches

to all changes: