Merge lp:pay-service/devel into lp:pay-service/14.10
- devel
- Merge into trunk.14.10
Status: | Merged |
---|---|
Merged at revision: | 9 |
Proposed branch: | lp:pay-service/devel |
Merge into: | lp:pay-service/14.10 |
Diff against target: |
1627 lines (+946/-91) 35 files modified
.bzrignore (+3/-1) CMakeLists.txt (+7/-4) MERGE-REVIEW (+14/-0) data/pay-service.conf.in (+3/-1) debian/changelog (+11/-0) debian/control (+4/-0) debian/pay-service.click-hook (+5/-0) debian/rules (+1/-1) libpay/pay-package.cpp (+35/-3) service/CMakeLists.txt (+7/-3) service/dbus-interface.cpp (+7/-1) service/dbus-interface.h (+2/-0) service/item-memory.cpp (+24/-26) service/main.cpp (+20/-19) service/purchase-ual.cpp (+20/-5) service/qtbridge.cpp (+189/-0) service/qtbridge.h (+88/-0) service/token-grabber-u1.cpp (+113/-0) service/token-grabber-u1.h (+41/-0) service/token-grabber.h (+39/-0) service/verification-curl.cpp (+90/-11) service/verification-curl.h (+7/-1) tests/CMakeLists.txt (+20/-4) tests/click-data/com.canonical.payui/0.1/.click/info/com.canonical.payui.manifest (+9/-0) tests/click-data/com.canonical.payui/0.1/test.desktop (+3/-0) tests/click-db/test.conf.in (+2/-0) tests/dbus-interface-tests.cpp (+24/-2) tests/libpay-tests.cpp (+5/-5) tests/manual (+30/-0) tests/purchase-ual-tests.cpp (+9/-2) tests/setup-staging.sh (+19/-0) tests/token-grabber-null.h (+36/-0) tests/verification-curl-endpoints/good/device-id.in (+5/-0) tests/verification-curl-endpoints/package-name.in (+3/-0) tests/verification-curl-tests.cpp (+51/-2) |
To merge this branch: | bzr merge lp:pay-service/devel |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Indicator Applet Developers | Pending | ||
Review via email: mp+223106@code.launchpad.net |
Commit message
Fixes from integration work to make the pay demo come together.
Description of the change
Release prep.
Ted Gould (ted) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:13
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:14
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:15
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:16
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:17
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:18
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2014-05-20 19:06:37 +0000 |
3 | +++ .bzrignore 2014-06-18 18:46:48 +0000 |
4 | @@ -10,7 +10,9 @@ |
5 | item-memory-tests |
6 | pay-service.conf |
7 | verification-curl-tests |
8 | -tests/verification-curl-endpoints/good-simple |
9 | +tests/verification-curl-endpoints/good/simple |
10 | purchase-ual-tests |
11 | +click-db/test.conf |
12 | libpay.so.1.0.0 |
13 | libpay-tests |
14 | +verification-curl-endpoints/package-name |
15 | |
16 | === modified file 'CMakeLists.txt' |
17 | --- CMakeLists.txt 2014-05-26 14:01:00 +0000 |
18 | +++ CMakeLists.txt 2014-06-18 18:46:48 +0000 |
19 | @@ -29,19 +29,22 @@ |
20 | ## Check for prerequisites |
21 | ## |
22 | |
23 | +set(CMAKE_AUTOMOC ON) |
24 | + |
25 | find_package (PkgConfig REQUIRED) |
26 | +find_package (Qt5Core REQUIRED) |
27 | include (FindPkgConfig) |
28 | |
29 | -pkg_check_modules (PROCESS_CPP REQUIRED process-cpp) |
30 | - |
31 | pkg_check_modules (SERVICE_DEPS REQUIRED |
32 | libcurl |
33 | ubuntu-app-launch-2 |
34 | dbustest-1 |
35 | gio-2.0 |
36 | gio-unix-2.0 |
37 | - process-cpp) |
38 | -include_directories (SYSTEM ${PROCESS_CPP_INCLUDE_DIRS} ${SERVICE_DEPS_INCLUDE_DIRS}) |
39 | + process-cpp |
40 | + properties-cpp |
41 | + ubuntuoneauth-2.0) |
42 | +include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS}) |
43 | |
44 | ## |
45 | ## Gdbus |
46 | |
47 | === added file 'MERGE-REVIEW' |
48 | --- MERGE-REVIEW 1970-01-01 00:00:00 +0000 |
49 | +++ MERGE-REVIEW 2014-06-18 18:46:48 +0000 |
50 | @@ -0,0 +1,14 @@ |
51 | + |
52 | +This documents the expections that the project has on what both submitters |
53 | +and reviewers should ensure that they've done for a merge into the project. |
54 | + |
55 | +== Submitter Responsibilities == |
56 | + |
57 | + * Ensure the project compiles and the test suite executes without error |
58 | + * Ensure that non-obvious code has comments explaining it |
59 | + |
60 | +== Reviewer Responsibilities == |
61 | + |
62 | + * Did the Jenkins build compile? Pass? Run unit tests successfully? |
63 | + * Are there appropriate tests to cover any new functionality? |
64 | + |
65 | |
66 | === modified file 'data/pay-service.conf.in' |
67 | --- data/pay-service.conf.in 2014-05-26 10:40:36 +0000 |
68 | +++ data/pay-service.conf.in 2014-06-18 18:46:48 +0000 |
69 | @@ -1,6 +1,8 @@ |
70 | description "Service to process payments" |
71 | |
72 | -start on desktop-start |
73 | +start on desktop-start or started unity8 |
74 | stop on desktop-end |
75 | |
76 | +respawn |
77 | + |
78 | exec @CMAKE_INSTALL_FULL_LIBEXECDIR@/pay-service/pay-service |
79 | |
80 | === modified file 'debian/changelog' |
81 | --- debian/changelog 2014-06-01 21:16:48 +0000 |
82 | +++ debian/changelog 2014-06-18 18:46:48 +0000 |
83 | @@ -1,3 +1,14 @@ |
84 | +pay-service (0.1+14.10.20140601-0ubuntu2) UNRELEASED; urgency=medium |
85 | + |
86 | + * Add acceptance tests and merge commit rules |
87 | + * Fix scoping of root object |
88 | + * Allow purchasing items without verifications |
89 | + * Use proper URLs for verification |
90 | + * Launch Pay UI for finishing payment |
91 | + * Add a dummy click hook to allow for usage in Pay UI |
92 | + |
93 | + -- Ted Gould <ted@ubuntu.com> Wed, 18 Jun 2014 13:44:26 -0500 |
94 | + |
95 | pay-service (0.1+14.10.20140601-0ubuntu1) utopic; urgency=low |
96 | |
97 | [ Ted Gould ] |
98 | |
99 | === modified file 'debian/control' |
100 | --- debian/control 2014-05-28 09:20:54 +0000 |
101 | +++ debian/control 2014-06-18 18:46:48 +0000 |
102 | @@ -3,6 +3,7 @@ |
103 | Priority: optional |
104 | Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> |
105 | Build-Depends: astyle, |
106 | + click-dev, |
107 | cmake, |
108 | dbus, |
109 | dbus-test-runner, |
110 | @@ -10,10 +11,13 @@ |
111 | google-mock, |
112 | libcurl4-gnutls-dev, |
113 | libdbustest1-dev, |
114 | + libglib2.0-dev, |
115 | libgtest-dev, |
116 | libprocess-cpp-dev, |
117 | libubuntu-app-launch2-dev, |
118 | + libubuntuoneauth-2.0-dev, |
119 | python3-dbusmock, |
120 | + qtbase5-dev, |
121 | Standards-Version: 3.9.5 |
122 | Homepage: http://launchpad.net/pay-service |
123 | # If you aren't a member of ~indicator-applet-developers but need to upload |
124 | |
125 | === added file 'debian/pay-service.click-hook' |
126 | --- debian/pay-service.click-hook 1970-01-01 00:00:00 +0000 |
127 | +++ debian/pay-service.click-hook 2014-06-18 18:46:48 +0000 |
128 | @@ -0,0 +1,5 @@ |
129 | +# NOTE: Temporary until trusted sessions land |
130 | +Pattern: ${home}/.local/share/applications/${id}.desktop |
131 | +Exec: /bin/true |
132 | +User-Level: yes |
133 | +Hook-Name: pay-ui |
134 | |
135 | === modified file 'debian/rules' |
136 | --- debian/rules 2014-05-21 03:44:48 +0000 |
137 | +++ debian/rules 2014-06-18 18:46:48 +0000 |
138 | @@ -8,4 +8,4 @@ |
139 | dh_auto_configure -- -DCMAKE_INSTALL_LIBEXECDIR=/usr/lib/$(DEB_HOST_MULTIARCH)/pay-service -DCMAKE_INSTALL_INCLUDEDIR=/usr/include/$(DEB_HOST_MULTIARCH)/ |
140 | |
141 | %: |
142 | - dh $@ --fail-missing |
143 | + dh $@ --fail-missing --with click |
144 | |
145 | === modified file 'libpay/pay-package.cpp' |
146 | --- libpay/pay-package.cpp 2014-05-20 22:12:48 +0000 |
147 | +++ libpay/pay-package.cpp 2014-06-18 18:46:48 +0000 |
148 | @@ -31,6 +31,7 @@ |
149 | class Package |
150 | { |
151 | std::string id; |
152 | + std::string path; |
153 | /* NOTE: Using the shared_ptr here because gcc 4.7 map doesn't have emplace */ |
154 | std::map <std::pair<PayPackageItemObserver, void*>, std::shared_ptr<core::ScopedConnection>> observers; |
155 | core::Signal<std::string, PayPackageItemStatus> itemChanged; |
156 | @@ -46,6 +47,9 @@ |
157 | public: |
158 | Package (const char* packageid) : id(packageid), cancellable(g_cancellable_new()), loop(nullptr) |
159 | { |
160 | + path = std::string("/com/canonical/pay/"); |
161 | + path += encodePath(id); |
162 | + |
163 | /* Keeps item cache up-to-data as we get signals about it */ |
164 | itemChanged.connect([this](std::string itemid, PayPackageItemStatus status) |
165 | { |
166 | @@ -62,13 +66,11 @@ |
167 | g_main_context_push_thread_default(context); |
168 | context_mutex.unlock(); |
169 | |
170 | - std::string path("/com/canonical/pay/"); |
171 | - path += id; /* TODO: encode */ |
172 | proxy = proxy_pay_package_proxy_new_for_bus_sync(G_BUS_TYPE_SESSION, |
173 | G_DBUS_PROXY_FLAGS_NONE, |
174 | "com.canonical.pay", |
175 | path.c_str(), |
176 | - cancellable, |
177 | + NULL, |
178 | &error); |
179 | |
180 | if (error != nullptr) |
181 | @@ -248,6 +250,36 @@ |
182 | { |
183 | return functionCall(proxy_pay_package_call_purchase_item, proxy_pay_package_call_purchase_item_finish, itemid); |
184 | } |
185 | + |
186 | + std::string |
187 | + encodePath (const std::string& input) |
188 | + { |
189 | + std::string output = ""; |
190 | + bool first = true; |
191 | + |
192 | + for (unsigned char c : input) |
193 | + { |
194 | + std::string retval; |
195 | + |
196 | + if ((c >= 'a' && c <= 'z') || |
197 | + (c >= 'A' && c <= 'Z') || |
198 | + (c >= '0' && c <= '9' && !first)) |
199 | + { |
200 | + retval = std::string((char*)&c, 1); |
201 | + } |
202 | + else |
203 | + { |
204 | + char buffer[5] = {0}; |
205 | + std::snprintf(buffer, 4, "_%2X", c); |
206 | + retval = std::string(buffer); |
207 | + } |
208 | + |
209 | + output += retval; |
210 | + first = false; |
211 | + } |
212 | + |
213 | + return output; |
214 | + } |
215 | }; |
216 | |
217 | |
218 | |
219 | === modified file 'service/CMakeLists.txt' |
220 | --- service/CMakeLists.txt 2014-05-15 20:11:25 +0000 |
221 | +++ service/CMakeLists.txt 2014-06-18 18:46:48 +0000 |
222 | @@ -1,5 +1,5 @@ |
223 | |
224 | -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g ${GCOV_FLAGS}") |
225 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -fPIE ${GCOV_FLAGS}") |
226 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) |
227 | |
228 | |
229 | @@ -14,11 +14,16 @@ |
230 | item-null.h |
231 | item-memory.h |
232 | item-memory.cpp |
233 | + qtbridge.h |
234 | + qtbridge.cpp |
235 | purchase-factory.h |
236 | purchase-null.h |
237 | purchase-null.cpp |
238 | purchase-ual.h |
239 | purchase-ual.cpp |
240 | + token-grabber.h |
241 | + token-grabber-u1.h |
242 | + token-grabber-u1.cpp |
243 | verification-curl.cpp |
244 | verification-null.cpp) |
245 | |
246 | @@ -34,8 +39,7 @@ |
247 | |
248 | add_executable(pay-service main.cpp) |
249 | target_link_libraries(pay-service |
250 | - pay-service-lib |
251 | - ${PROCESS_CPP_LIBRARIES}) |
252 | + pay-service-lib) |
253 | |
254 | install(TARGETS pay-service RUNTIME DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}) |
255 | |
256 | |
257 | === modified file 'service/dbus-interface.cpp' |
258 | --- service/dbus-interface.cpp 2014-05-19 22:03:01 +0000 |
259 | +++ service/dbus-interface.cpp 2014-06-18 18:46:48 +0000 |
260 | @@ -51,7 +51,11 @@ |
261 | bus(nullptr), |
262 | serviceProxy(nullptr), |
263 | packageProxy(nullptr), |
264 | - errorQuark(g_quark_from_static_string("dbus-interface-impl")) |
265 | + errorQuark(g_quark_from_static_string("dbus-interface-impl")), |
266 | + subtree_registration(0) |
267 | + { } |
268 | + |
269 | + void run () |
270 | { |
271 | t = std::thread([this]() |
272 | { |
273 | @@ -398,6 +402,8 @@ |
274 | { |
275 | connectionReady(); |
276 | }); |
277 | + |
278 | + impl->run(); |
279 | } |
280 | |
281 | bool |
282 | |
283 | === modified file 'service/dbus-interface.h' |
284 | --- service/dbus-interface.h 2014-05-19 21:03:42 +0000 |
285 | +++ service/dbus-interface.h 2014-06-18 18:46:48 +0000 |
286 | @@ -39,6 +39,8 @@ |
287 | |
288 | core::Signal<> connectionReady; |
289 | |
290 | + typedef std::shared_ptr<DBusInterface> Ptr; |
291 | + |
292 | private: |
293 | std::shared_ptr<DBusInterfaceImpl> impl; |
294 | }; |
295 | |
296 | === modified file 'service/item-memory.cpp' |
297 | --- service/item-memory.cpp 2014-05-08 20:48:54 +0000 |
298 | +++ service/item-memory.cpp 2014-06-18 18:46:48 +0000 |
299 | @@ -105,43 +105,41 @@ |
300 | bool purchase (void) |
301 | { |
302 | /* First check to see if a purchase makes sense */ |
303 | - if (status != NOT_PURCHASED) |
304 | - { |
305 | - return false; |
306 | - } |
307 | - |
308 | - if (pitem != nullptr) |
309 | + if (status == PURCHASED) |
310 | { |
311 | return true; |
312 | } |
313 | |
314 | - pitem = pfactory->purchaseItem(app, id); |
315 | if (pitem == nullptr) |
316 | { |
317 | - /* Uhg, failed */ |
318 | - return false; |
319 | + pitem = pfactory->purchaseItem(app, id); |
320 | + if (pitem == nullptr) |
321 | + { |
322 | + /* Uhg, failed */ |
323 | + return false; |
324 | + } |
325 | + |
326 | + pitem->purchaseComplete.connect([this](Purchase::Item::Status status) |
327 | + { |
328 | + switch (status) |
329 | + { |
330 | + case Purchase::Item::PURCHASED: |
331 | + setStatus(Item::Status::PURCHASED); |
332 | + break; |
333 | + case Purchase::Item::ERROR: |
334 | + case Purchase::Item::NOT_PURCHASED: |
335 | + default: /* Fall through, an error is same as status we don't know */ |
336 | + /* We know we were not purchased before, so let's stay that way */ |
337 | + setStatus(Item::Status::NOT_PURCHASED); |
338 | + break; |
339 | + } |
340 | + return; |
341 | + }); |
342 | } |
343 | |
344 | /* New purchase instance, tell the world! */ |
345 | setStatus(Item::Status::PURCHASING); |
346 | |
347 | - pitem->purchaseComplete.connect([this](Purchase::Item::Status status) |
348 | - { |
349 | - switch (status) |
350 | - { |
351 | - case Purchase::Item::PURCHASED: |
352 | - setStatus(Item::Status::PURCHASED); |
353 | - break; |
354 | - case Purchase::Item::ERROR: |
355 | - case Purchase::Item::NOT_PURCHASED: |
356 | - default: /* Fall through, an error is same as status we don't know */ |
357 | - /* We know we were not purchased before, so let's stay that way */ |
358 | - setStatus(Item::Status::NOT_PURCHASED); |
359 | - break; |
360 | - } |
361 | - return; |
362 | - }); |
363 | - |
364 | return pitem->run(); |
365 | } |
366 | |
367 | |
368 | === modified file 'service/main.cpp' |
369 | --- service/main.cpp 2014-05-14 03:35:25 +0000 |
370 | +++ service/main.cpp 2014-06-18 18:46:48 +0000 |
371 | @@ -17,33 +17,34 @@ |
372 | * Ted Gould <ted.gould@canonical.com> |
373 | */ |
374 | |
375 | -#include <core/posix/signal.h> |
376 | - |
377 | #include "dbus-interface.h" |
378 | #include "item-memory.h" |
379 | #include "verification-curl.h" |
380 | #include "purchase-ual.h" |
381 | +#include "qtbridge.h" |
382 | +#include "token-grabber-u1.h" |
383 | |
384 | int |
385 | main (int argv, char* argc[]) |
386 | { |
387 | - auto trap = core::posix::trap_signals_for_all_subsequent_threads( |
388 | - { |
389 | - core::posix::Signal::sig_int, |
390 | - core::posix::Signal::sig_term |
391 | - }); |
392 | - |
393 | - trap->signal_raised().connect([trap](core::posix::Signal) |
394 | - { |
395 | - trap->stop(); |
396 | - }); |
397 | - |
398 | - auto vfactory = std::make_shared<Verification::CurlFactory>(); |
399 | - auto pfactory = std::make_shared<Purchase::UalFactory>(); |
400 | - auto items = std::make_shared<Item::MemoryStore>(vfactory, pfactory); |
401 | - auto dbus = std::make_shared<DBusInterface>(items); |
402 | - |
403 | - trap->run(); |
404 | + TokenGrabber::Ptr token; |
405 | + Verification::Factory::Ptr vfactory; |
406 | + Purchase::Factory::Ptr pfactory; |
407 | + Item::Store::Ptr items; |
408 | + DBusInterface::Ptr dbus; |
409 | + |
410 | + qt::core::world::build_and_run(argv, argc, [&token, &vfactory, &pfactory, &items, &dbus]() |
411 | + { |
412 | + /* Initialize the other object after Qt is built */ |
413 | + token = std::make_shared<TokenGrabberU1>(); |
414 | + vfactory = std::make_shared<Verification::CurlFactory>(token); |
415 | + pfactory = std::make_shared<Purchase::UalFactory>(); |
416 | + items = std::make_shared<Item::MemoryStore>(vfactory, pfactory); |
417 | + dbus = std::make_shared<DBusInterface>(items); |
418 | + }); |
419 | + |
420 | + qt::core::world::destroy(); |
421 | |
422 | return EXIT_SUCCESS; |
423 | } |
424 | + |
425 | |
426 | === modified file 'service/purchase-ual.cpp' |
427 | --- service/purchase-ual.cpp 2014-05-26 14:01:00 +0000 |
428 | +++ service/purchase-ual.cpp 2014-06-18 18:46:48 +0000 |
429 | @@ -31,10 +31,20 @@ |
430 | typedef std::shared_ptr<Item> Ptr; |
431 | |
432 | UalItem (std::string& in_appid, std::string& in_itemid) : |
433 | - appid(in_appid), itemid(in_itemid), loop(nullptr), status(Item::ERROR) |
434 | + appid(in_appid), |
435 | + itemid(in_itemid), |
436 | + loop(nullptr), |
437 | + status(Item::ERROR) |
438 | { |
439 | /* TODO: ui_appid needs to be grabbed from the click hook */ |
440 | - ui_appid = "gedit"; |
441 | + gchar* appidc = ubuntu_app_launch_triplet_to_app_id("com.canonical.payui", |
442 | + nullptr, |
443 | + nullptr); |
444 | + if (appidc != nullptr) |
445 | + { |
446 | + ui_appid = appidc; |
447 | + g_free(appidc); |
448 | + } |
449 | } |
450 | |
451 | ~UalItem () |
452 | @@ -79,9 +89,14 @@ |
453 | /* Building a URL so that we can pass this information today without |
454 | using trusted helpers and setting environment vars */ |
455 | /* TODO: Use trusted helpers */ |
456 | - std::string purchase_url = "purchase:///"; |
457 | - purchase_url += appid; |
458 | - purchase_url += "/"; |
459 | + std::string purchase_url = "purchase://"; |
460 | + |
461 | + if (appid != "click-scope") |
462 | + { |
463 | + purchase_url += appid; |
464 | + purchase_url += "/"; |
465 | + } |
466 | + |
467 | purchase_url += itemid; |
468 | const gchar* urls[2] = {0}; |
469 | urls[0] = purchase_url.c_str(); |
470 | |
471 | === added file 'service/qtbridge.cpp' |
472 | --- service/qtbridge.cpp 1970-01-01 00:00:00 +0000 |
473 | +++ service/qtbridge.cpp 2014-06-18 18:46:48 +0000 |
474 | @@ -0,0 +1,189 @@ |
475 | +/* |
476 | + * Copyright © 2014 Canonical Ltd. |
477 | + * |
478 | + * This program is free software: you can redistribute it and/or modify it |
479 | + * under the terms of the GNU Lesser General Public License version 3, |
480 | + * as published by the Free Software Foundation. |
481 | + * |
482 | + * This program is distributed in the hope that it will be useful, |
483 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
484 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
485 | + * GNU Lesser General Public License for more details. |
486 | + * |
487 | + * You should have received a copy of the GNU Lesser General Public License |
488 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
489 | + * |
490 | + * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
491 | + * Thomas Voß <thomas.voss@canonical.com> |
492 | + */ |
493 | + |
494 | +#include "qtbridge.h" |
495 | + |
496 | +#include<QCoreApplication> |
497 | +#include<QNetworkAccessManager> |
498 | +#include<QNetworkRequest> |
499 | +#include<QNetworkReply> |
500 | +#include<QThread> |
501 | +#include<QDebug> |
502 | + |
503 | +#include <iostream> |
504 | + |
505 | +namespace |
506 | +{ |
507 | +QCoreApplication* app = nullptr; |
508 | +} |
509 | + |
510 | +namespace qt |
511 | +{ |
512 | +namespace core |
513 | +{ |
514 | +namespace world |
515 | +{ |
516 | +namespace detail |
517 | +{ |
518 | +QEvent::Type qt_core_world_task_event_type() |
519 | +{ |
520 | + static QEvent::Type event_type = static_cast<QEvent::Type>(QEvent::registerEventType()); |
521 | + return event_type; |
522 | +} |
523 | + |
524 | +class TaskEvent : public QEvent |
525 | +{ |
526 | +public: |
527 | + TaskEvent(const std::function<void()>& task) |
528 | + : QEvent(qt_core_world_task_event_type()), |
529 | + task(task) |
530 | + { |
531 | + } |
532 | + |
533 | + void run() |
534 | + { |
535 | + try |
536 | + { |
537 | + task(); |
538 | + promise.set_value(); |
539 | + } |
540 | + catch (...) |
541 | + { |
542 | + promise.set_exception(std::current_exception()); |
543 | + } |
544 | + } |
545 | + |
546 | + std::future<void> get_future() |
547 | + { |
548 | + return promise.get_future(); |
549 | + } |
550 | + |
551 | +private: |
552 | + std::function<void()> task; |
553 | + std::promise<void> promise; |
554 | +}; |
555 | + |
556 | +class TaskHandler : public QObject |
557 | +{ |
558 | + Q_OBJECT |
559 | + |
560 | +public: |
561 | + TaskHandler(QObject* parent) : QObject(parent) |
562 | + { |
563 | + } |
564 | + |
565 | + bool event(QEvent* e); |
566 | +}; |
567 | + |
568 | + |
569 | + |
570 | +void createCoreApplicationInstanceWithArgs(int argc, char** argv) |
571 | +{ |
572 | + app = new QCoreApplication(argc, argv); |
573 | +} |
574 | + |
575 | +void destroyCoreApplicationInstace() |
576 | +{ |
577 | + delete app; |
578 | +} |
579 | + |
580 | +QCoreApplication* coreApplicationInstance() |
581 | +{ |
582 | + return app; |
583 | +} |
584 | + |
585 | +TaskHandler* task_handler() |
586 | +{ |
587 | + static TaskHandler* instance = new TaskHandler(coreApplicationInstance()); |
588 | + return instance; |
589 | +} |
590 | + |
591 | +bool TaskHandler::event(QEvent* e) |
592 | +{ |
593 | + if (e->type() != qt_core_world_task_event_type()) |
594 | + { |
595 | + return QObject::event(e); |
596 | + } |
597 | + |
598 | + auto te = dynamic_cast<TaskEvent*>(e); |
599 | + if (te) |
600 | + { |
601 | + te->run(); |
602 | + return true; |
603 | + } |
604 | + |
605 | + return false; |
606 | +} |
607 | +} |
608 | + |
609 | +void build_and_run(int argc, char** argv, const std::function<void()>& ready) |
610 | +{ |
611 | + QThread::currentThread(); |
612 | + if (QCoreApplication::instance() != nullptr) |
613 | + throw std::runtime_error( |
614 | + "qt::core::world::build_and_run: " |
615 | + "There is already a QCoreApplication running."); |
616 | + |
617 | + detail::createCoreApplicationInstanceWithArgs(argc, argv); |
618 | + |
619 | + detail::task_handler()->moveToThread( |
620 | + detail::coreApplicationInstance()->thread()); |
621 | + |
622 | + // Signal to other worlds that we are good to go. |
623 | + ready(); |
624 | + |
625 | + detail::coreApplicationInstance()->exec(); |
626 | + |
627 | + // Someone has called quit and we clean up on the correct thread here. |
628 | + detail::destroyCoreApplicationInstace(); |
629 | +} |
630 | + |
631 | +void destroy() |
632 | +{ |
633 | + enter_with_task([]() |
634 | + { |
635 | + // We make sure that all tasks have completed before quitting the app. |
636 | + QEventLoopLocker locker; |
637 | + }).wait_for(std::chrono::seconds {1}); |
638 | +} |
639 | + |
640 | +std::future<void> enter_with_task(const std::function<void()>& task) |
641 | +{ |
642 | + QCoreApplication* instance = QCoreApplication::instance(); |
643 | + |
644 | + if (!instance) |
645 | + { |
646 | + throw std::runtime_error("Qt world has not been built before calling this function."); |
647 | + } |
648 | + |
649 | + detail::TaskEvent* te = new detail::TaskEvent(task); |
650 | + auto future = te->get_future(); |
651 | + |
652 | + // We hand over ownership of te here. The event is deleted later after it has |
653 | + // been processed by the event loop. |
654 | + instance->postEvent(detail::task_handler(), te); |
655 | + |
656 | + return future; |
657 | +} |
658 | + |
659 | +} |
660 | +} |
661 | +} |
662 | + |
663 | +#include "qtbridge.moc" |
664 | |
665 | === added file 'service/qtbridge.h' |
666 | --- service/qtbridge.h 1970-01-01 00:00:00 +0000 |
667 | +++ service/qtbridge.h 2014-06-18 18:46:48 +0000 |
668 | @@ -0,0 +1,88 @@ |
669 | +/* |
670 | + * Copyright © 2014 Canonical Ltd. |
671 | + * |
672 | + * This program is free software: you can redistribute it and/or modify it |
673 | + * under the terms of the GNU Lesser General Public License version 3, |
674 | + * as published by the Free Software Foundation. |
675 | + * |
676 | + * This program is distributed in the hope that it will be useful, |
677 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
678 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
679 | + * GNU Lesser General Public License for more details. |
680 | + * |
681 | + * You should have received a copy of the GNU Lesser General Public License |
682 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
683 | + * |
684 | + * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
685 | + * Thomas Voß <thomas.voss@canonical.com> |
686 | + */ |
687 | + |
688 | +#ifndef QT_CORE_WORLD_BRIDGE_H_ |
689 | +#define QT_CORE_WORLD_BRIDGE_H_ |
690 | + |
691 | +#include <QObject> |
692 | + |
693 | +#include <functional> |
694 | +#include <future> |
695 | +#include <iostream> |
696 | + |
697 | +namespace qt |
698 | +{ |
699 | +namespace core |
700 | +{ |
701 | +namespace world |
702 | +{ |
703 | +/** |
704 | + * @brief Sets up the Qt core world and executes its event loop. Blocks until destroy() is called. |
705 | + * @param argc Number of arguments in argv. |
706 | + * @param argv Array of command-line arguments. |
707 | + * @param ready Functor be called when the world has been setup and is about to be executed. |
708 | + * @throw std::runtime_error in case of errors. |
709 | + */ |
710 | +void build_and_run(int argc, char** argv, const std::function<void()>& ready); |
711 | + |
712 | +/** |
713 | + * @brief Destroys the Qt core world and quits its event loop. |
714 | + */ |
715 | +void destroy(); |
716 | + |
717 | +/** |
718 | + * @brief Enters the Qt core world and schedules the given task for execution. |
719 | + * @param task The task to be executed in the Qt core world. |
720 | + * @return A std::future that can be waited for to synchronize to the world's internal event loop. |
721 | + */ |
722 | +std::future<void> enter_with_task(const std::function<void()>& task); |
723 | + |
724 | + |
725 | +/** |
726 | + * @brief Enters the Qt core world and schedules the given task for execution. |
727 | + * @param task The task to be executed in the Qt core world. |
728 | + * @return A std::future that can be waited for to get hold of the result of the task. |
729 | + */ |
730 | +template<typename T> |
731 | +inline std::future<T> enter_with_task_and_expect_result(const std::function<T()>& task) |
732 | +{ |
733 | + std::shared_ptr<std::promise<T>> promise = std::make_shared<std::promise<T>>(); |
734 | + std::future<T> future = promise->get_future(); |
735 | + |
736 | + auto t = [promise, task]() |
737 | + { |
738 | + try |
739 | + { |
740 | + promise->set_value(task()); |
741 | + } |
742 | + catch (...) |
743 | + { |
744 | + promise->set_exception(std::current_exception()); |
745 | + } |
746 | + }; |
747 | + |
748 | + enter_with_task(t); |
749 | + |
750 | + return future; |
751 | +} |
752 | +} |
753 | +} |
754 | +} |
755 | + |
756 | +#endif // QT_CORE_WORLD_BRIDGE_H_ |
757 | |
758 | === added file 'service/token-grabber-u1.cpp' |
759 | --- service/token-grabber-u1.cpp 1970-01-01 00:00:00 +0000 |
760 | +++ service/token-grabber-u1.cpp 2014-06-18 18:46:48 +0000 |
761 | @@ -0,0 +1,113 @@ |
762 | +/* |
763 | + * Copyright © 2014 Canonical Ltd. |
764 | + * |
765 | + * This program is free software: you can redistribute it and/or modify it |
766 | + * under the terms of the GNU General Public License version 3, as published |
767 | + * by the Free Software Foundation. |
768 | + * |
769 | + * This program is distributed in the hope that it will be useful, but |
770 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
771 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
772 | + * PURPOSE. See the GNU General Public License for more details. |
773 | + * |
774 | + * You should have received a copy of the GNU General Public License along |
775 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
776 | + * |
777 | + * Authors: |
778 | + * Ted Gould <ted.gould@canonical.com> |
779 | + */ |
780 | + |
781 | +#include "token-grabber-u1.h" |
782 | +#include "qtbridge.h" |
783 | + |
784 | +#include <ssoservice.h> |
785 | +#include <token.h> |
786 | + |
787 | +class TokenGrabberU1Qt: public QObject |
788 | +{ |
789 | + Q_OBJECT |
790 | + |
791 | +public: |
792 | + explicit TokenGrabberU1Qt (QObject* parent = 0); |
793 | + void run (void); |
794 | + std::string signUrl(std::string url, std::string type); |
795 | + |
796 | +private Q_SLOTS: |
797 | + void handleCredentialsFound(const UbuntuOne::Token& token); |
798 | + void handleCredentialsNotFound(); |
799 | + |
800 | +private: |
801 | + UbuntuOne::Token token; |
802 | + UbuntuOne::SSOService service; |
803 | +}; |
804 | + |
805 | +TokenGrabberU1Qt::TokenGrabberU1Qt (QObject* parent) : |
806 | + QObject(parent) |
807 | +{ |
808 | + std::cout << "Token grabber built" << std::endl; |
809 | +} |
810 | + |
811 | +void TokenGrabberU1Qt::run (void) |
812 | +{ |
813 | + std::cout << "Token grabber running" << std::endl; |
814 | + |
815 | + QObject::connect(&service, |
816 | + &UbuntuOne::SSOService::credentialsFound, |
817 | + this, |
818 | + &TokenGrabberU1Qt::handleCredentialsFound); |
819 | + QObject::connect(&service, |
820 | + &UbuntuOne::SSOService::credentialsNotFound, |
821 | + this, |
822 | + &TokenGrabberU1Qt::handleCredentialsNotFound); |
823 | + |
824 | + service.getCredentials(); |
825 | +} |
826 | + |
827 | +void TokenGrabberU1Qt::handleCredentialsFound(const UbuntuOne::Token& in_token) |
828 | +{ |
829 | + token = in_token; |
830 | + std::cout << "Got a Token" << std::endl; |
831 | +} |
832 | + |
833 | +void TokenGrabberU1Qt::handleCredentialsNotFound() |
834 | +{ |
835 | + std::cout << "No Token :-(" << std::endl; |
836 | +} |
837 | + |
838 | +std::string TokenGrabberU1Qt::signUrl (std::string url, std::string type) |
839 | +{ |
840 | + std::string retval; |
841 | + |
842 | + auto qretval = token.signUrl(url.c_str(), type.c_str()); |
843 | + retval = std::string(qretval.toUtf8()); |
844 | + |
845 | + return retval; |
846 | +} |
847 | + |
848 | +TokenGrabberU1::TokenGrabberU1 (void) |
849 | +{ |
850 | + //qt = std::make_shared<TokenGrabberU1Qt>(); |
851 | + qtfuture = qt::core::world::enter_with_task_and_expect_result<std::shared_ptr<TokenGrabberU1Qt>>([]() |
852 | + { |
853 | + auto qtgrabber = std::make_shared<TokenGrabberU1Qt>(); |
854 | + qtgrabber->run(); |
855 | + return qtgrabber; |
856 | + }); |
857 | +} |
858 | + |
859 | +TokenGrabberU1::~TokenGrabberU1 (void) |
860 | +{ |
861 | +} |
862 | + |
863 | +std::string TokenGrabberU1::signUrl (std::string url, std::string type) |
864 | +{ |
865 | + if (qtfuture.valid()) |
866 | + { |
867 | + return qtfuture.get()->signUrl(url, type); |
868 | + } |
869 | + |
870 | + std::string retval; |
871 | + return retval; |
872 | +} |
873 | + |
874 | +#include "token-grabber-u1.moc" |
875 | |
876 | === added file 'service/token-grabber-u1.h' |
877 | --- service/token-grabber-u1.h 1970-01-01 00:00:00 +0000 |
878 | +++ service/token-grabber-u1.h 2014-06-18 18:46:48 +0000 |
879 | @@ -0,0 +1,41 @@ |
880 | +/* |
881 | + * Copyright © 2014 Canonical Ltd. |
882 | + * |
883 | + * This program is free software: you can redistribute it and/or modify it |
884 | + * under the terms of the GNU General Public License version 3, as published |
885 | + * by the Free Software Foundation. |
886 | + * |
887 | + * This program is distributed in the hope that it will be useful, but |
888 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
889 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
890 | + * PURPOSE. See the GNU General Public License for more details. |
891 | + * |
892 | + * You should have received a copy of the GNU General Public License along |
893 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
894 | + * |
895 | + * Authors: |
896 | + * Ted Gould <ted.gould@canonical.com> |
897 | + */ |
898 | + |
899 | +#ifndef TOKEN_GRABBER_U1_HPP__ |
900 | +#define TOKEN_GRABBER_U1_HPP__ 1 |
901 | + |
902 | +#include <future> |
903 | +#include "token-grabber.h" |
904 | + |
905 | +class TokenGrabberU1Qt; |
906 | + |
907 | +class TokenGrabberU1 : public TokenGrabber |
908 | +{ |
909 | +public: |
910 | + TokenGrabberU1 (void); |
911 | + virtual ~TokenGrabberU1 (void); |
912 | + |
913 | + virtual std::string signUrl(std::string url, std::string type); |
914 | + |
915 | +private: |
916 | + std::future<std::shared_ptr<TokenGrabberU1Qt>> qtfuture; |
917 | +}; |
918 | + |
919 | + |
920 | +#endif /* TOKEN_GRABBER_U1_HPP__ */ |
921 | |
922 | === added file 'service/token-grabber.h' |
923 | --- service/token-grabber.h 1970-01-01 00:00:00 +0000 |
924 | +++ service/token-grabber.h 2014-06-18 18:46:48 +0000 |
925 | @@ -0,0 +1,39 @@ |
926 | +/* |
927 | + * Copyright © 2014 Canonical Ltd. |
928 | + * |
929 | + * This program is free software: you can redistribute it and/or modify it |
930 | + * under the terms of the GNU General Public License version 3, as published |
931 | + * by the Free Software Foundation. |
932 | + * |
933 | + * This program is distributed in the hope that it will be useful, but |
934 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
935 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
936 | + * PURPOSE. See the GNU General Public License for more details. |
937 | + * |
938 | + * You should have received a copy of the GNU General Public License along |
939 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
940 | + * |
941 | + * Authors: |
942 | + * Ted Gould <ted.gould@canonical.com> |
943 | + */ |
944 | + |
945 | +#ifndef TOKEN_GRABBER_HPP__ |
946 | +#define TOKEN_GRABBER_HPP__ 1 |
947 | + |
948 | +#include <string> |
949 | +#include <memory> |
950 | + |
951 | +#include <core/signal.h> |
952 | + |
953 | +class TokenGrabber |
954 | +{ |
955 | +public: |
956 | + virtual std::string signUrl(std::string url, std::string type) = 0; |
957 | + |
958 | + typedef std::shared_ptr<TokenGrabber> Ptr; |
959 | + |
960 | + /* Signals */ |
961 | + core::Signal<bool> tokenUpdated; |
962 | +}; |
963 | + |
964 | +#endif /* TOKEN_GRABBER_HPP__ */ |
965 | |
966 | === modified file 'service/verification-curl.cpp' |
967 | --- service/verification-curl.cpp 2014-05-14 03:35:34 +0000 |
968 | +++ service/verification-curl.cpp 2014-06-18 18:46:48 +0000 |
969 | @@ -30,9 +30,39 @@ |
970 | class CurlItem : public Item |
971 | { |
972 | public: |
973 | - CurlItem (std::string& app, std::string& item, std::string& endpoint) : exec(nullptr) |
974 | + CurlItem (std::string& app, |
975 | + std::string& item, |
976 | + std::string& endpoint, |
977 | + std::string& device, |
978 | + TokenGrabber::Ptr token) : |
979 | + stop(false), |
980 | + handle(nullptr), |
981 | + curlHeaders(nullptr) |
982 | { |
983 | - url = (endpoint + "/" + app + "-" + item); |
984 | + url = endpoint; |
985 | + |
986 | + if (app != "click-scope") |
987 | + { |
988 | + url += "/" + app; |
989 | + } |
990 | + url += "/" + item; |
991 | + if (!device.empty()) |
992 | + { |
993 | + url += "?device=" + device; |
994 | + } |
995 | + |
996 | + /* Sign the request */ |
997 | + auto auth = token->signUrl(url, "GET"); |
998 | + if (!auth.empty()) |
999 | + { |
1000 | + std::string header("Authorization: "); |
1001 | + header += auth; |
1002 | + curlHeaders = curl_slist_append(curlHeaders, auth.c_str()); |
1003 | + } |
1004 | + |
1005 | + /* Ensure we get JSON back */ |
1006 | + curlHeaders = curl_slist_append(curlHeaders, "Accept: application/json"); |
1007 | + |
1008 | handle = curl_easy_init(); |
1009 | |
1010 | /* Helps with threads */ |
1011 | @@ -40,16 +70,28 @@ |
1012 | curl_easy_setopt(handle, CURLOPT_URL, url.c_str()); |
1013 | curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlWrite); |
1014 | curl_easy_setopt(handle, CURLOPT_WRITEDATA, this); |
1015 | + if (curlHeaders != nullptr) |
1016 | + { |
1017 | + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, curlHeaders); |
1018 | + } |
1019 | } |
1020 | |
1021 | ~CurlItem (void) |
1022 | { |
1023 | - if (exec->joinable()) |
1024 | + stop = true; |
1025 | + |
1026 | + if (exec.joinable()) |
1027 | { |
1028 | - exec->join(); |
1029 | + exec.join(); |
1030 | } |
1031 | |
1032 | curl_easy_cleanup(handle); |
1033 | + |
1034 | + if (curlHeaders != nullptr) |
1035 | + { |
1036 | + curl_slist_free_all (curlHeaders) ; |
1037 | + curlHeaders = nullptr; |
1038 | + } |
1039 | } |
1040 | |
1041 | virtual bool run (void) |
1042 | @@ -58,14 +100,23 @@ |
1043 | |
1044 | /* Do the execution in another thread so we can wait on the |
1045 | network socket. */ |
1046 | - exec = std::make_shared<std::thread>([this]() |
1047 | + exec = std::thread([this]() |
1048 | { |
1049 | auto status = curl_easy_perform(handle); |
1050 | |
1051 | if (status == CURLE_OK) |
1052 | { |
1053 | - /* TODO: Clearly we need to be a bit more sophisticated here */ |
1054 | - verificationComplete(Status::NOT_PURCHASED); |
1055 | + long responsecode = 0; |
1056 | + curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &responsecode); |
1057 | + |
1058 | + if (responsecode == 200) |
1059 | + { |
1060 | + verificationComplete(Status::PURCHASED); |
1061 | + } |
1062 | + else |
1063 | + { |
1064 | + verificationComplete(Status::NOT_PURCHASED); |
1065 | + } |
1066 | } |
1067 | else |
1068 | { |
1069 | @@ -79,8 +130,10 @@ |
1070 | private: |
1071 | CURL* handle; |
1072 | std::string transferBuffer; |
1073 | - std::shared_ptr<std::thread> exec; |
1074 | + std::thread exec; |
1075 | std::string url; |
1076 | + bool stop; |
1077 | + struct curl_slist* curlHeaders; |
1078 | |
1079 | /* This is the callback from cURL as it does the transfer. We're |
1080 | pretty simple in that we're just putting it into a string. */ |
1081 | @@ -89,14 +142,33 @@ |
1082 | auto datasize = size * nmemb; |
1083 | //std::cout << "Got data: " << datasize << std::endl; |
1084 | CurlItem* item = static_cast<CurlItem*>(user_data); |
1085 | + if (item->stop) |
1086 | + { |
1087 | + std::cout << "cURL transaction stopped prematurely" << std::endl; |
1088 | + return 0; |
1089 | + } |
1090 | item->transferBuffer.append(static_cast<char*>(buffer), datasize); |
1091 | return datasize; |
1092 | } |
1093 | }; |
1094 | |
1095 | -CurlFactory::CurlFactory () : |
1096 | - endpoint("https://launchpad.net") |
1097 | +/********************* |
1098 | + * CurlFactory |
1099 | + *********************/ |
1100 | + |
1101 | +CurlFactory::CurlFactory (TokenGrabber::Ptr token) : |
1102 | + endpoint("https://sc.ubuntu.com/api/2.0/click/purchases"), |
1103 | + tokenGrabber(token) |
1104 | { |
1105 | + /* This is how we enable staging */ |
1106 | + const char* envendpoint(getenv("PAY_BASE_URL")); |
1107 | + if (envendpoint != nullptr) |
1108 | + { |
1109 | + endpoint = envendpoint; |
1110 | + /* Our endpoint is slightly more specific */ |
1111 | + endpoint += "/purchases"; |
1112 | + } |
1113 | + |
1114 | /* TODO: We should check to see if we have networking someday */ |
1115 | curl_global_init(CURL_GLOBAL_SSL); |
1116 | } |
1117 | @@ -116,7 +188,7 @@ |
1118 | Item::Ptr |
1119 | CurlFactory::verifyItem (std::string& appid, std::string& itemid) |
1120 | { |
1121 | - return std::make_shared<CurlItem>(appid, itemid, endpoint); |
1122 | + return std::make_shared<CurlItem>(appid, itemid, endpoint, device, tokenGrabber); |
1123 | } |
1124 | |
1125 | void |
1126 | @@ -125,4 +197,11 @@ |
1127 | endpoint = in_endpoint; |
1128 | } |
1129 | |
1130 | +void |
1131 | +CurlFactory::setDevice (std::string& in_device) |
1132 | +{ |
1133 | + device = in_device; |
1134 | +} |
1135 | + |
1136 | } // ns Verification |
1137 | + |
1138 | |
1139 | === modified file 'service/verification-curl.h' |
1140 | --- service/verification-curl.h 2014-05-07 21:01:52 +0000 |
1141 | +++ service/verification-curl.h 2014-06-18 18:46:48 +0000 |
1142 | @@ -18,6 +18,9 @@ |
1143 | */ |
1144 | |
1145 | #include "verification-factory.h" |
1146 | +#include "token-grabber.h" |
1147 | + |
1148 | +#include <memory> |
1149 | |
1150 | #ifndef VERIFICATION_CURL_HPP__ |
1151 | #define VERIFICATION_CURL_HPP__ 1 |
1152 | @@ -26,7 +29,7 @@ |
1153 | |
1154 | class CurlFactory : public Factory { |
1155 | public: |
1156 | - CurlFactory (); |
1157 | + CurlFactory (TokenGrabber::Ptr token); |
1158 | CurlFactory (const std::string& endpoint); |
1159 | ~CurlFactory (); |
1160 | |
1161 | @@ -34,9 +37,12 @@ |
1162 | virtual Item::Ptr verifyItem (std::string& appid, std::string& itemid); |
1163 | |
1164 | void setEndpoint (std::string& endpoint); |
1165 | + void setDevice (std::string& device); |
1166 | |
1167 | private: |
1168 | std::string endpoint; |
1169 | + std::string device; |
1170 | + TokenGrabber::Ptr tokenGrabber; |
1171 | }; |
1172 | |
1173 | } // ns Verification |
1174 | |
1175 | === modified file 'tests/CMakeLists.txt' |
1176 | --- tests/CMakeLists.txt 2014-05-20 19:06:37 +0000 |
1177 | +++ tests/CMakeLists.txt 2014-06-18 18:46:48 +0000 |
1178 | @@ -18,7 +18,6 @@ |
1179 | |
1180 | ${GMOCK_INCLUDE_DIR} |
1181 | ${GTEST_INCLUDE_DIR} |
1182 | - ${PROCESS_CPP_INCLUDE_DIRS} |
1183 | ) |
1184 | |
1185 | ############################# |
1186 | @@ -36,7 +35,6 @@ |
1187 | pay-service-lib |
1188 | |
1189 | ${SERVICE_DEPS_LIBRARIES} |
1190 | - ${PROCESS_CPP_LIBRARIES} |
1191 | ${CMAKE_THREAD_LIBS_INIT} |
1192 | ${GMOCK_BOTH_LIBRARIES} |
1193 | ) |
1194 | @@ -84,8 +82,14 @@ |
1195 | ) |
1196 | |
1197 | configure_file( |
1198 | - ${CMAKE_CURRENT_SOURCE_DIR}/verification-curl-endpoints/good-simple.in |
1199 | - ${CMAKE_CURRENT_BINARY_DIR}/verification-curl-endpoints/good-simple @ONLY) |
1200 | + ${CMAKE_CURRENT_SOURCE_DIR}/verification-curl-endpoints/good/simple.in |
1201 | + ${CMAKE_CURRENT_BINARY_DIR}/verification-curl-endpoints/good/simple @ONLY) |
1202 | +configure_file( |
1203 | + ${CMAKE_CURRENT_SOURCE_DIR}/verification-curl-endpoints/good/device-id.in |
1204 | + ${CMAKE_CURRENT_BINARY_DIR}/verification-curl-endpoints/good/device-id @ONLY) |
1205 | +configure_file( |
1206 | + ${CMAKE_CURRENT_SOURCE_DIR}/verification-curl-endpoints/package-name.in |
1207 | + ${CMAKE_CURRENT_BINARY_DIR}/verification-curl-endpoints/package-name @ONLY) |
1208 | |
1209 | add_test(verification-curl-tests ${CMAKE_CURRENT_BINARY_DIR}/verification-curl-tests) |
1210 | |
1211 | @@ -93,6 +97,13 @@ |
1212 | # Purchase UAL |
1213 | ############################# |
1214 | |
1215 | +configure_file( |
1216 | + ${CMAKE_CURRENT_SOURCE_DIR}/click-db/test.conf.in |
1217 | + ${CMAKE_CURRENT_BINARY_DIR}/click-db/test.conf @ONLY) |
1218 | + |
1219 | +add_definitions(-DCMAKE_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}") |
1220 | +add_definitions(-DCMAKE_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") |
1221 | + |
1222 | add_executable( |
1223 | purchase-ual-tests |
1224 | purchase-ual-tests.cpp |
1225 | @@ -126,3 +137,8 @@ |
1226 | |
1227 | add_test(libpay-tests ${CMAKE_CURRENT_BINARY_DIR}/libpay-tests) |
1228 | |
1229 | +############################# |
1230 | +# staging script |
1231 | +############################# |
1232 | + |
1233 | +install(PROGRAMS setup-staging.sh DESTINATION ${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}) |
1234 | |
1235 | === added directory 'tests/click-data' |
1236 | === added directory 'tests/click-data/.click' |
1237 | === added directory 'tests/click-data/.click/users' |
1238 | === added directory 'tests/click-data/.click/users/test-user' |
1239 | === added symlink 'tests/click-data/.click/users/test-user/com.canonical.payui' |
1240 | === target is u'../../../com.canonical.payui/0.1/' |
1241 | === added directory 'tests/click-data/com.canonical.payui' |
1242 | === added directory 'tests/click-data/com.canonical.payui/0.1' |
1243 | === added directory 'tests/click-data/com.canonical.payui/0.1/.click' |
1244 | === added directory 'tests/click-data/com.canonical.payui/0.1/.click/info' |
1245 | === added file 'tests/click-data/com.canonical.payui/0.1/.click/info/com.canonical.payui.manifest' |
1246 | --- tests/click-data/com.canonical.payui/0.1/.click/info/com.canonical.payui.manifest 1970-01-01 00:00:00 +0000 |
1247 | +++ tests/click-data/com.canonical.payui/0.1/.click/info/com.canonical.payui.manifest 2014-06-18 18:46:48 +0000 |
1248 | @@ -0,0 +1,9 @@ |
1249 | +{ |
1250 | + "version": "0.1", |
1251 | + "name": "com.canonical.payui", |
1252 | + "hooks": { |
1253 | + "app1": { |
1254 | + "desktop": "test.desktop" |
1255 | + } |
1256 | + } |
1257 | +} |
1258 | |
1259 | === added file 'tests/click-data/com.canonical.payui/0.1/test.desktop' |
1260 | --- tests/click-data/com.canonical.payui/0.1/test.desktop 1970-01-01 00:00:00 +0000 |
1261 | +++ tests/click-data/com.canonical.payui/0.1/test.desktop 2014-06-18 18:46:48 +0000 |
1262 | @@ -0,0 +1,3 @@ |
1263 | +[Desktop Entry] |
1264 | +Name=Test |
1265 | +Exec=test |
1266 | |
1267 | === added directory 'tests/click-db' |
1268 | === added file 'tests/click-db/test.conf.in' |
1269 | --- tests/click-db/test.conf.in 1970-01-01 00:00:00 +0000 |
1270 | +++ tests/click-db/test.conf.in 2014-06-18 18:46:48 +0000 |
1271 | @@ -0,0 +1,2 @@ |
1272 | +[Click Database] |
1273 | +root = @CMAKE_CURRENT_SOURCE_DIR@/click-data |
1274 | |
1275 | === modified file 'tests/dbus-interface-tests.cpp' |
1276 | --- tests/dbus-interface-tests.cpp 2014-05-28 14:57:59 +0000 |
1277 | +++ tests/dbus-interface-tests.cpp 2014-06-18 18:46:48 +0000 |
1278 | @@ -143,10 +143,18 @@ |
1279 | |
1280 | void signalAppend (GObject* obj, const gchar* itemid, const gchar* status, std::vector<std::string>& list) |
1281 | { |
1282 | + std::cout << "Signal append: " << itemid << ", " << status << std::endl; |
1283 | ASSERT_STREQ("fooitem", itemid); |
1284 | list.push_back(status); |
1285 | } |
1286 | |
1287 | +int loop_quit (void* data) |
1288 | +{ |
1289 | + auto loop = reinterpret_cast<GMainLoop*>(data); |
1290 | + g_main_loop_quit(loop); |
1291 | + return G_SOURCE_REMOVE; |
1292 | +} |
1293 | + |
1294 | TEST_F(DbusInterfaceTests, ItemSignalTests) |
1295 | { |
1296 | core::testing::CrossProcessSync cps1; |
1297 | @@ -178,6 +186,9 @@ |
1298 | titem->test_setStatus(Item::Item::NOT_PURCHASED, true); |
1299 | titem->test_setStatus(Item::Item::PURCHASED, true); |
1300 | |
1301 | + /* Let the signals escape before we shut things down */ |
1302 | + usleep(100000); |
1303 | + |
1304 | /* Force deallocation so we can catch stuff from it */ |
1305 | test_store.reset(); |
1306 | pay_service.reset(); |
1307 | @@ -185,7 +196,7 @@ |
1308 | return ::testing::Test::HasFailure() ? core::posix::exit::Status::failure : core::posix::exit::Status::success; |
1309 | }; |
1310 | |
1311 | - auto client = [this, &cps1, &cps2]() |
1312 | + auto client = [this, &cps1, &cps2]() -> core::posix::exit::Status |
1313 | { |
1314 | GMainContext* context = g_main_context_new(); |
1315 | g_main_context_push_thread_default(context); |
1316 | @@ -220,8 +231,19 @@ |
1317 | trap->run(); |
1318 | |
1319 | /* Pull the events through */ |
1320 | - while (g_main_context_iteration(context, FALSE)) {} |
1321 | + auto loop = g_main_loop_new(context, FALSE); |
1322 | + auto timeout = g_timeout_source_new(200); |
1323 | + g_source_set_callback(timeout, loop_quit, loop, nullptr); |
1324 | + g_source_attach(timeout, context); |
1325 | + g_main_loop_run(loop); |
1326 | + g_main_loop_unref(loop); |
1327 | |
1328 | + /* Can't use assert in lambdas */ |
1329 | + if (4 != itemsignals.size()) |
1330 | + { |
1331 | + std::cerr << "ERROR: Item signals isn't correct size (4): " << itemsignals.size() << std::endl; |
1332 | + throw; |
1333 | + } |
1334 | EXPECT_EQ("verifying", itemsignals[0]); |
1335 | EXPECT_EQ("purchasing", itemsignals[1]); |
1336 | EXPECT_EQ("not purchased", itemsignals[2]); |
1337 | |
1338 | === modified file 'tests/libpay-tests.cpp' |
1339 | --- tests/libpay-tests.cpp 2014-05-29 06:51:32 +0000 |
1340 | +++ tests/libpay-tests.cpp 2014-06-18 18:46:48 +0000 |
1341 | @@ -44,10 +44,10 @@ |
1342 | "ListPackages", |
1343 | nullptr, |
1344 | G_VARIANT_TYPE("ao"), /* out */ |
1345 | - "ret = [ dbus.ObjectPath('/com/canonical/pay/package') ]", /* python */ |
1346 | + "ret = [ dbus.ObjectPath('/com/canonical/pay/package_2Dname') ]", /* python */ |
1347 | nullptr); /* error */ |
1348 | |
1349 | - pkgobj = dbus_test_dbus_mock_get_object(mock, "/com/canonical/pay/package", "com.canonical.pay.package", nullptr); |
1350 | + pkgobj = dbus_test_dbus_mock_get_object(mock, "/com/canonical/pay/package_2Dname", "com.canonical.pay.package", nullptr); |
1351 | |
1352 | dbus_test_dbus_mock_object_add_method(mock, pkgobj, |
1353 | "VerifyItem", |
1354 | @@ -94,13 +94,13 @@ |
1355 | |
1356 | TEST_F(LibPayTests, InitTest) |
1357 | { |
1358 | - auto package = pay_package_new("package"); |
1359 | + auto package = pay_package_new("package-name"); |
1360 | pay_package_delete(package); |
1361 | } |
1362 | |
1363 | TEST_F(LibPayTests, ItemLifecycle) |
1364 | { |
1365 | - auto package = pay_package_new("package"); |
1366 | + auto package = pay_package_new("package-name"); |
1367 | |
1368 | EXPECT_EQ(PAY_PACKAGE_ITEM_STATUS_UNKNOWN, pay_package_item_status(package, "item")); |
1369 | |
1370 | @@ -187,7 +187,7 @@ |
1371 | { |
1372 | GError* error = nullptr; |
1373 | guint callcount = 0; |
1374 | - auto package = pay_package_new("package"); |
1375 | + auto package = pay_package_new("package-name"); |
1376 | |
1377 | EXPECT_TRUE(pay_package_item_start_verification(package, "item")); |
1378 | |
1379 | |
1380 | === added file 'tests/manual' |
1381 | --- tests/manual 1970-01-01 00:00:00 +0000 |
1382 | +++ tests/manual 2014-06-18 18:46:48 +0000 |
1383 | @@ -0,0 +1,30 @@ |
1384 | +Test-case pay-service/setup-staging-account |
1385 | +<dl> |
1386 | + <dt>Ensure that no U1 accounts are configured on the device</dt> |
1387 | + <dd>Going to System Settings → Accounts shouldn't have any "Ubuntu One" entries shown</dd> |
1388 | + <dd>Delete the account if there is one shown and exit system settings</dd> |
1389 | + <dt>Set up the device to use the staging servers for Ubuntu One</dt> |
1390 | + <dd>Execute the script: /usr/lib/*/pay-service/setup-staging.sh</dd> |
1391 | + <dd>It should run to completion without error</dd> |
1392 | + <dt>Create an Ubuntu One account: ${your name}+${unique number}@canonical.com</dt> |
1393 | + <dd>NOTE: This is only currently available to Canonical employees. There is work underway to make it more widely available but it is not complete yet.</dd> |
1394 | + <dd>The System Settings app should allow creating the account and the account show show up in the list of accounts on the device</dd> |
1395 | + <dt>Add a testing credit card to your account</dt> |
1396 | + <dd>The System Settings pane for Payment Options should allow for setting up the testing credit cards (numbers not listed here)</dd> |
1397 | +</dl> |
1398 | + |
1399 | +Test-case pay-service/purchase-application |
1400 | +<dl> |
1401 | + <dt>Create a new account with no previously purchased items</dt> |
1402 | + <dd>The instructions in <tt>pay-service/setup-staging-account</tt> pass without error</dd> |
1403 | + <dt>Find the "QR-Code" app in the application scope</dt> |
1404 | + <dd>By searching for "QR-Code" an app should be listed and clicking on it show its preview</dd> |
1405 | + <dt>Ensure that the QR-Code app has not been previously purchased</dt> |
1406 | + <dd>The button in the preview should show the price of the app and not "Open" or "Install"</dd> |
1407 | + <dt>Wait 10 minutes for the token to expire</dt> |
1408 | + <dd>Take a nice walk on a sunny day</dd> |
1409 | + <dt>Select the "Purchase" button for the "QR-Code" application</dt> |
1410 | + <dd>The button should depress and a window should appear asking for your Ubuntu One password</dd> |
1411 | + <dt>Enter your password and confirm the purchase</dt> |
1412 | + <dd>The window should close and the application should begin downloading and install</dd> |
1413 | +</dl> |
1414 | |
1415 | === modified file 'tests/purchase-ual-tests.cpp' |
1416 | --- tests/purchase-ual-tests.cpp 2014-05-26 14:01:00 +0000 |
1417 | +++ tests/purchase-ual-tests.cpp 2014-06-18 18:46:48 +0000 |
1418 | @@ -33,6 +33,13 @@ |
1419 | GDBusConnection * bus = NULL; |
1420 | |
1421 | virtual void SetUp() { |
1422 | + g_setenv("TEST_CLICK_DB", "click-db", TRUE); |
1423 | + g_setenv("TEST_CLICK_USER", "test-user", TRUE); |
1424 | + |
1425 | + gchar * linkfarm = g_build_filename(CMAKE_SOURCE_DIR, "ual-link-farm", NULL); |
1426 | + g_setenv("UPSTART_APP_LAUNCH_LINK_FARM", linkfarm, TRUE); |
1427 | + g_free(linkfarm); |
1428 | + |
1429 | service = dbus_test_service_new(NULL); |
1430 | |
1431 | mock = dbus_test_dbus_mock_new("com.ubuntu.Upstart"); |
1432 | @@ -107,7 +114,7 @@ |
1433 | EXPECT_TRUE(item->run()); |
1434 | usleep(20 * 1000); |
1435 | |
1436 | - dbus_test_dbus_mock_object_emit_signal(mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), g_variant_new_parsed("('stopped', ['JOB=application-legacy', 'INSTANCE=gedit-'])"), NULL); |
1437 | + dbus_test_dbus_mock_object_emit_signal(mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), g_variant_new_parsed("('stopped', ['JOB=application-click', 'INSTANCE=com.canonical.payui_app1_0.1'])"), NULL); |
1438 | usleep(20 * 1000); |
1439 | |
1440 | EXPECT_EQ(Purchase::Item::Status::PURCHASED, status); |
1441 | @@ -128,7 +135,7 @@ |
1442 | usleep(20 * 1000); |
1443 | |
1444 | GError * error = NULL; |
1445 | - g_spawn_command_line_async("gdbus emit --session --object-path / --signal com.canonical.UbuntuAppLaunch.ApplicationFailed gedit crash", &error); |
1446 | + g_spawn_command_line_async("gdbus emit --session --object-path / --signal com.canonical.UbuntuAppLaunch.ApplicationFailed com.canonical.payui_app1_0.1 crash", &error); |
1447 | ASSERT_EQ(nullptr, error); |
1448 | |
1449 | usleep(100 * 1000); |
1450 | |
1451 | === added file 'tests/setup-staging.sh' |
1452 | --- tests/setup-staging.sh 1970-01-01 00:00:00 +0000 |
1453 | +++ tests/setup-staging.sh 2014-06-18 18:46:48 +0000 |
1454 | @@ -0,0 +1,19 @@ |
1455 | +#!/bin/bash -e |
1456 | +# This small script sets up the variables needed for acceptance |
1457 | +# testing of the pay-service and pay related things. |
1458 | + |
1459 | +echo "Setting up staging environment variables" |
1460 | + |
1461 | +initctl set-env --global SSO_AUTH_BASE_URL=https://login.staging.ubuntu.com |
1462 | +initctl set-env --global SSO_UONE_BASE_URL=https://staging.one.ubuntu.com |
1463 | +initctl set-env --global PAY_BASE_URL=https://sc.staging.ubuntu.com/api/2.0/click/ |
1464 | +initctl set-env --global URL_PACKAGE_INFO=https://search.apps.staging.ubuntu.com/api/v1/package/ |
1465 | +initctl set-env --global ACCOUNT_CREDS_URL=https://login.staging.ubuntu.com/api/v2/tokens/oauth |
1466 | +initctl set-env --global ADD_PAYMENT_URL=https://sc.staging.ubuntu.com/api/2.0/click/paymentmethods/add/ |
1467 | +initctl set-env --global U1_SEARCH_BASE_URL=https://search.apps.staging.ubuntu.com/ |
1468 | + |
1469 | +echo "Restarting scope registry" |
1470 | +restart scope-registry |
1471 | + |
1472 | +echo "Restarting pay service" |
1473 | +restart pay-service |
1474 | |
1475 | === added file 'tests/token-grabber-null.h' |
1476 | --- tests/token-grabber-null.h 1970-01-01 00:00:00 +0000 |
1477 | +++ tests/token-grabber-null.h 2014-06-18 18:46:48 +0000 |
1478 | @@ -0,0 +1,36 @@ |
1479 | +/* |
1480 | + * Copyright © 2014 Canonical Ltd. |
1481 | + * |
1482 | + * This program is free software: you can redistribute it and/or modify it |
1483 | + * under the terms of the GNU General Public License version 3, as published |
1484 | + * by the Free Software Foundation. |
1485 | + * |
1486 | + * This program is distributed in the hope that it will be useful, but |
1487 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1488 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1489 | + * PURPOSE. See the GNU General Public License for more details. |
1490 | + * |
1491 | + * You should have received a copy of the GNU General Public License along |
1492 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1493 | + * |
1494 | + * Authors: |
1495 | + * Ted Gould <ted.gould@canonical.com> |
1496 | + */ |
1497 | + |
1498 | +#ifndef TOKEN_GRABBER_NULL_HPP__ |
1499 | +#define TOKEN_GRABBER_NULL_HPP__ 1 |
1500 | + |
1501 | +#include "service/token-grabber.h" |
1502 | + |
1503 | +class TokenGrabberNull : public TokenGrabber |
1504 | +{ |
1505 | +public: |
1506 | + virtual std::string signUrl (std::string url, std::string type) |
1507 | + { |
1508 | + std::string retval; |
1509 | + return retval; |
1510 | + } |
1511 | +}; |
1512 | + |
1513 | +#endif /* TOKEN_GRABBER_NULL_HPP__ */ |
1514 | + |
1515 | |
1516 | === added directory 'tests/ual-link-farm' |
1517 | === added file 'tests/ual-link-farm/com.canonical.payui_app1_0.1.desktop' |
1518 | === added directory 'tests/verification-curl-endpoints/good' |
1519 | === added file 'tests/verification-curl-endpoints/good/device-id.in' |
1520 | --- tests/verification-curl-endpoints/good/device-id.in 1970-01-01 00:00:00 +0000 |
1521 | +++ tests/verification-curl-endpoints/good/device-id.in 2014-06-18 18:46:48 +0000 |
1522 | @@ -0,0 +1,5 @@ |
1523 | +{ |
1524 | + /* Not sure of all the detail here, but making it simple to get started */ |
1525 | + good: "simple", |
1526 | + device: "1234" |
1527 | +} |
1528 | |
1529 | === renamed file 'tests/verification-curl-endpoints/good-simple.in' => 'tests/verification-curl-endpoints/good/simple.in' |
1530 | === added file 'tests/verification-curl-endpoints/package-name.in' |
1531 | --- tests/verification-curl-endpoints/package-name.in 1970-01-01 00:00:00 +0000 |
1532 | +++ tests/verification-curl-endpoints/package-name.in 2014-06-18 18:46:48 +0000 |
1533 | @@ -0,0 +1,3 @@ |
1534 | +{ |
1535 | + "item": "package-name" |
1536 | +} |
1537 | |
1538 | === modified file 'tests/verification-curl-tests.cpp' |
1539 | --- tests/verification-curl-tests.cpp 2014-05-19 14:47:16 +0000 |
1540 | +++ tests/verification-curl-tests.cpp 2014-06-18 18:46:48 +0000 |
1541 | @@ -19,6 +19,7 @@ |
1542 | |
1543 | #include <gtest/gtest.h> |
1544 | #include "service/verification-curl.h" |
1545 | +#include "token-grabber-null.h" |
1546 | |
1547 | struct VerificationCurlTests : public ::testing::Test |
1548 | { |
1549 | @@ -26,16 +27,20 @@ |
1550 | virtual void SetUp() { |
1551 | endpoint = "file://"; |
1552 | endpoint += VERIFICATION_CURL_ENDPOINTS_DIR; |
1553 | + |
1554 | + device = "1234"; |
1555 | } |
1556 | |
1557 | virtual void TearDown() { |
1558 | } |
1559 | |
1560 | std::string endpoint; |
1561 | + std::string device; |
1562 | }; |
1563 | |
1564 | TEST_F(VerificationCurlTests, InitTest) { |
1565 | - auto verify = std::make_shared<Verification::CurlFactory>(); |
1566 | + auto token = std::make_shared<TokenGrabberNull>(); |
1567 | + auto verify = std::make_shared<Verification::CurlFactory>(token); |
1568 | EXPECT_NE(nullptr, verify); |
1569 | verify->setEndpoint(endpoint); |
1570 | verify.reset(); |
1571 | @@ -43,7 +48,8 @@ |
1572 | } |
1573 | |
1574 | TEST_F(VerificationCurlTests, PurchaseItem) { |
1575 | - auto verify = std::make_shared<Verification::CurlFactory>(); |
1576 | + auto token = std::make_shared<TokenGrabberNull>(); |
1577 | + auto verify = std::make_shared<Verification::CurlFactory>(token); |
1578 | ASSERT_NE(nullptr, verify); |
1579 | verify->setEndpoint(endpoint); |
1580 | |
1581 | @@ -73,3 +79,46 @@ |
1582 | |
1583 | EXPECT_EQ(Verification::Item::Status::ERROR, badstatus); |
1584 | } |
1585 | + |
1586 | +TEST_F(VerificationCurlTests, ClickScope) { |
1587 | + auto token = std::make_shared<TokenGrabberNull>(); |
1588 | + auto verify = std::make_shared<Verification::CurlFactory>(token); |
1589 | + ASSERT_NE(nullptr, verify); |
1590 | + verify->setEndpoint(endpoint); |
1591 | + |
1592 | + std::string appid("click-scope"); |
1593 | + std::string itemid("package-name"); |
1594 | + |
1595 | + auto item = verify->verifyItem(appid, itemid); |
1596 | + ASSERT_NE(nullptr, item); |
1597 | + |
1598 | + Verification::Item::Status status = Verification::Item::Status::ERROR; |
1599 | + item->verificationComplete.connect([&status] (Verification::Item::Status in_status) { status = in_status; }); |
1600 | + |
1601 | + ASSERT_TRUE(item->run()); |
1602 | + usleep(20 * 1000); |
1603 | + |
1604 | + EXPECT_EQ(Verification::Item::Status::NOT_PURCHASED, status); |
1605 | +} |
1606 | + |
1607 | +TEST_F(VerificationCurlTests, DeviceId) { |
1608 | + auto token = std::make_shared<TokenGrabberNull>(); |
1609 | + auto verify = std::make_shared<Verification::CurlFactory>(token); |
1610 | + ASSERT_NE(nullptr, verify); |
1611 | + verify->setEndpoint(endpoint); |
1612 | + verify->setDevice(device); |
1613 | + |
1614 | + std::string appid("good"); |
1615 | + std::string itemid("device-id"); |
1616 | + |
1617 | + auto item = verify->verifyItem(appid, itemid); |
1618 | + ASSERT_NE(nullptr, item); |
1619 | + |
1620 | + Verification::Item::Status status = Verification::Item::Status::ERROR; |
1621 | + item->verificationComplete.connect([&status] (Verification::Item::Status in_status) { status = in_status; }); |
1622 | + |
1623 | + ASSERT_TRUE(item->run()); |
1624 | + usleep(20 * 1000); |
1625 | + |
1626 | + EXPECT_EQ(Verification::Item::Status::NOT_PURCHASED, status); |
1627 | +} |
Marking for review to get Jenkin's opinion. Needs a acceptance test branch before fully ready.