Merge lp:~dobey/unity-scope-click/clicksnap into lp:unity-scope-click
- clicksnap
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | dobey |
Proposed branch: | lp:~dobey/unity-scope-click/clicksnap |
Merge into: | lp:unity-scope-click |
Prerequisite: | lp:~dobey/unity-scope-click/ual-apps |
Diff against target: |
1900 lines (+682/-390) 23 files modified
bin/CMakeLists.txt (+4/-1) bin/install-helper (+9/-2) bin/install-snap (+73/-0) debian/control (+6/-3) libclickscope/click/configuration.cpp (+13/-3) libclickscope/click/configuration.h (+1/-0) libclickscope/click/download-manager.cpp (+53/-83) libclickscope/click/download-manager.h (+4/-8) libclickscope/click/index.cpp (+60/-6) libclickscope/click/index.h (+11/-2) libclickscope/click/package.cpp (+4/-0) libclickscope/click/package.h (+4/-0) libclickscope/click/preview.cpp (+16/-5) libclickscope/click/webclient.cpp (+26/-17) libclickscope/click/webclient.h (+2/-0) libclickscope/tests/mock_webclient.h (+11/-7) libclickscope/tests/test_bootstrap.cpp (+2/-2) libclickscope/tests/test_download_manager.cpp (+155/-127) libclickscope/tests/test_index.cpp (+157/-91) libclickscope/tests/test_pay.cpp (+13/-13) libclickscope/tests/test_preview.cpp (+2/-2) libclickscope/tests/test_reviews.cpp (+16/-16) scope/clickstore/store-query.cpp (+40/-2) |
To merge this branch: | bzr merge lp:~dobey/unity-scope-click/clicksnap |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
unity-api-1-bot | continuous-integration | Approve | |
Charles Kerr (community) | Approve | ||
Review via email: mp+303974@code.launchpad.net |
This proposal supersedes a proposal from 2016-08-24.
Commit message
Initial support in store scope for searching and installing snaps.
Description of the change
unity-api-1-bot (unity-api-1-bot) wrote : Posted in a previous version of this proposal | # |
unity-api-1-bot (unity-api-1-bot) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:497
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:497
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:498
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Charles Kerr (charlesk) wrote : | # |
Review pt. 1 of 2, comments inline. About to be in transit and will finish review afterwards
Charles Kerr (charlesk) wrote : | # |
Review pt. 2 of 2 inline. No showstoppers but a few more questions/comments
Charles Kerr (charlesk) : | # |
- 499. By dobey
-
Merge up chagnes from ual-apps.
- 500. By dobey
-
Collapse snapd.socket check to simplify function.
- 501. By dobey
-
Remove the extra check for downloads.size > 1, as it shouldn't happen.
- 502. By dobey
-
Some cleanup in download-
manager. cpp per code review. - 503. By dobey
-
Fixes to index.cpp per code review.
- 504. By dobey
-
Break up mock responseForReply per code review.
- 505. By dobey
-
Refactor index tests perh code review.
- 506. By dobey
-
Use const auto in for loops.
dobey (dobey) wrote : | # |
On Sat, 2016-09-03 at 01:11 +0000, Charles Kerr wrote:
> (optional) when a function reaches two bool arguments it's a
> candidate for an options bitfield a la GBusNameOwnerFlags
This is somewhat temporary. When we only support snaps, this will get
factored back out, as we won't need to know if something is a snap or
not at that point, since we'll only support snaps.
> I get that this isn't a red or green line, but out of curiosity,
> what's the rationale for calling details_callback() twice like this?
> So that showing the rest of the information won't block on the
> screenshot download?
I think maybe you were tired when you read this? Those are two
different branches of an if statement. :)
> 1. Each of the new tests looks at something unique, but they also
> look at get_architecture and get_available_
> same way without any apparent benefit from the duplication. Maybe
> that should be moved into its own test; or if it's necessary for each
> of these tests, at least extracted into a fixture method that all of
> these can call
Refactored this into two different fixture classes.
> (needinfo) Is this correct? Shouldn't we be checking pkg.name or
> pkg.alias for empty() instead of pkg.snap_id?
Did it this way because we specifically only want to use alias for
snaps, and I think there isn't quite any guarantee that alias will
always we empty for clicks. However, this is also quite temporary, as
when we only support snaps, we'll only use what is appropriate for
that, and not worry about supporting clicks.
> (needinfo) Capturing 'this' in lambdas-
> dicey. Are we certain that the lifetime of 'this' is safe s.t. it can
> be used this way?
I think this is fine here, as the outer call returns a pointer which we
store in this's private data, and which when destroyed aborts the
network requests, should prevent the callbacks being called, as the
requests get aborted. There is theoretically a possible race here, but
this will also be reduced back to single level when we stop supporting
clicks.
dobey (dobey) wrote : | # |
On Fri, 2016-09-02 at 21:21 +0000, Charles Kerr wrote:
> (bikeshed) IMO "return (retval == 0) && ((sb.st_mode & S_IFMT) ==
> S_IFSOCK));" is more readable as it boils the function down to a
> single exit point
Thought it might be useful to do something with errno at some point
when I wrote this, but it's not really important here, so changed this
to the simpler return anyway. :)
> (question) when writing code like this I've been favoring
> qPrintable(str) for terseness over QString:
> than code readability, is there any real difference / advantage to
> choosing one over the other?
I was formerly using str.c_str() in most places, but fromStdString()
seems more explicit, and it's consistent with the rest of the code here
for now. Ideally I think we should probably do something else to make
this more readable (and switch to the simple logging hack I wrote a
while back, at some point).
> (minor) QList.size() isn't guaranteed to be constant complexity and
> we call downloadss.size() a few lines above too, suggest a const
> temporary to hold the size
>
> (needinfo) How is this reached??
Just removed this extra if() here, as it should indeed never be
reached, and simpler code is better. This also reduces the calls to
size() to a single call.
> (needinfo / needs fixing) Isn't this a dangling pointer here as
> toUtf8() goes out-of-scope at the end of this line?
>
Not entirely sure of the semantics here and if it would be a dangling
pointer, but after looking at the code, it seems like using
toStdString() would be better anyway, so I've changed this code, and
the bit below it to use that instead.
> (bikeshed) c++11's nested list-initialization lets you do this really
> cleanly, something like
Right, but we're not initializing from an empty map here. We're taking
a const input, and need to insert additional items into it. So we need
to copy the old list, then add the new items. I don't think we can do
that with the braces initializer.
> Seems like 'description' deserves a line in an error log somewhere
Not sure why it wasn't, but fixed here and in the other method this was
copied from.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:506
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Charles Kerr (charlesk) wrote : | # |
> I think maybe you were tired when you read this? Those are two different branches of an if statement. :)
d'oh!
Thanks for the rest of the fixes & answers. Overall, a nice branch
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:507
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 508. By dobey
-
New script to download snap assertions and perform install
- 509. By dobey
-
Fix the snap script to do the right thing.
Add necessary dependencies for the script. - 510. By dobey
-
Check that filename argument is non-empty before continuing.
- 511. By dobey
-
Check if name is alias instead of using snap_id to determine if snap.
- 512. By dobey
-
If frameworks list is empty send "none" instead of empty header.
- 513. By dobey
-
Use a bash function instead of variable for wget, to avoid weird escaping.
Unmerged revisions
- 513. By dobey
-
Use a bash function instead of variable for wget, to avoid weird escaping.
- 512. By dobey
-
If frameworks list is empty send "none" instead of empty header.
- 511. By dobey
-
Check if name is alias instead of using snap_id to determine if snap.
- 510. By dobey
-
Check that filename argument is non-empty before continuing.
- 509. By dobey
-
Fix the snap script to do the right thing.
Add necessary dependencies for the script. - 508. By dobey
-
New script to download snap assertions and perform install
- 507. By dobey
-
Want const references for the for loops here.
- 506. By dobey
-
Use const auto in for loops.
- 505. By dobey
-
Refactor index tests perh code review.
- 504. By dobey
-
Break up mock responseForReply per code review.
Preview Diff
1 | === modified file 'bin/CMakeLists.txt' |
2 | --- bin/CMakeLists.txt 2014-08-14 14:59:57 +0000 |
3 | +++ bin/CMakeLists.txt 2016-09-21 14:55:05 +0000 |
4 | @@ -1,1 +1,4 @@ |
5 | -install(PROGRAMS install-helper enable-purchases DESTINATION lib/unity-scope-click/) |
6 | +install( |
7 | + PROGRAMS install-helper install-snap enable-purchases |
8 | + DESTINATION lib/unity-scope-click/ |
9 | +) |
10 | |
11 | === modified file 'bin/install-helper' |
12 | --- bin/install-helper 2014-06-20 05:09:01 +0000 |
13 | +++ bin/install-helper 2016-09-21 14:55:05 +0000 |
14 | @@ -1,6 +1,6 @@ |
15 | #!/bin/bash |
16 | # |
17 | -# Copyright (C) 2014 Canonical Ltd. |
18 | +# Copyright (C) 2014-2016 Canonical Ltd. |
19 | # |
20 | # This program is free software: you can redistribute it and/or modify it |
21 | # under the terms of the GNU General Public License version 3, as published |
22 | @@ -47,7 +47,14 @@ |
23 | |
24 | function install-package { |
25 | FILE_NAME="$1" |
26 | - pkcon -p install-local "$FILE_NAME" |
27 | + FILE_TYPE="${FILE_NAME##*.}" |
28 | + if [ ${FILE_TYPE} = "click" ]; then |
29 | + pkcon -p install-local "${FILE_NAME}" |
30 | + else |
31 | + SCRIPT_PATH=`dirname $0` |
32 | + SNAP_SCRIPT="${SCRIPT_PATH}/install-snap" |
33 | + pkexec ${SNAP_SCRIPT} "${FILE_NAME}" |
34 | + fi |
35 | } |
36 | |
37 | function app_id-from-package_name { |
38 | |
39 | === added file 'bin/install-snap' |
40 | --- bin/install-snap 1970-01-01 00:00:00 +0000 |
41 | +++ bin/install-snap 2016-09-21 14:55:05 +0000 |
42 | @@ -0,0 +1,73 @@ |
43 | +#!/bin/bash |
44 | +# |
45 | +# Copyright (C) 2016 Canonical Ltd. |
46 | +# |
47 | +# This program is free software: you can redistribute it and/or modify it |
48 | +# under the terms of the GNU General Public License version 3, as published |
49 | +# by the Free Software Foundation. |
50 | +# |
51 | +# This program is distributed in the hope that it will be useful, but |
52 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
53 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
54 | +# PURPOSE. See the GNU General Public License for more details. |
55 | +# |
56 | +# You should have received a copy of the GNU General Public License along |
57 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
58 | +# |
59 | +# In addition, as a special exception, the copyright holders give |
60 | +# permission to link the code of portions of this program with the |
61 | +# OpenSSL library under certain conditions as described in each |
62 | +# individual source file, and distribute linked combinations |
63 | +# including the two. |
64 | +# You must obey the GNU General Public License in all respects |
65 | +# for all of the code used other than OpenSSL. If you modify |
66 | +# file(s) with this exception, you may extend this exception to your |
67 | +# version of the file(s), but you are not obligated to do so. If you |
68 | +# do not wish to do so, delete this exception statement from your |
69 | +# version. If you delete this exception statement from all source |
70 | +# files in the program, then also delete it here. |
71 | +# |
72 | + |
73 | +set -ex |
74 | + |
75 | +if [ -z "$1" ]; then |
76 | + echo "usage: install-snap <filename.snap>" |
77 | + exit -10 |
78 | +fi |
79 | + |
80 | +SNAP_FILE_NAME="$1" |
81 | +SNAP_FILE=$(basename ${SNAP_FILE_NAME}) |
82 | +SNAP_REVID=${SNAP_FILE%%.*} |
83 | +SNAP_ID=${SNAP_REVID%%_*} |
84 | +SNAP_REV=${SNAP_REVID##*_} |
85 | + |
86 | +# We have to get not just the 384 hash, but a "snap-digest" for the snap. |
87 | +# This is a base64-encoded binary hex of the sha3 384 hash |
88 | +SNAP_SHA3SUM=$(sha3sum -a 384 ${SNAP_FILE_NAME} | cut -d ' ' -f1) |
89 | +SNAP_B64SHA=$(echo ${SNAP_SHA3SUM} | python3 -c 'import sys, binascii, base64; print(base64.urlsafe_b64encode(binascii.a2b_hex((sys.stdin.readline().strip().encode("ASCII")))).decode("ASCII").rstrip("="))') |
90 | + |
91 | + |
92 | +# Need to get the assertions to add to snapd |
93 | +ASSERTIONS_BASE_URL="https://assertions.ubuntu.com/v1/assertions" |
94 | +function download { |
95 | + wget --header "Accept: application/x.ubuntu.assertion" -O - $1 > $2 |
96 | +} |
97 | + |
98 | +# The '16' is hard-coded here for series. By the time it changes again, we |
99 | +# should have switched to using snapd for everything anyway. |
100 | +download "${ASSERTIONS_BASE_URL}/snap-declaration/16/${SNAP_ID}" "${SNAP_FILE_NAME}.snap-declaration" |
101 | +download "${ASSERTIONS_BASE_URL}/snap-revision/${SNAP_B64SHA}" "${SNAP_FILE_NAME}.snap-revision" |
102 | + |
103 | +# We have to get the publisher-id to get the account assertion for install |
104 | +AUTHOR_ID=$(grep "publisher-id:" ${SNAP_FILE_NAME}.snap-declaration | cut -d ' ' -f2) |
105 | +download "${ASSERTIONS_BASE_URL}/account/${AUTHOR_ID}" "${SNAP_FILE_NAME}.account" |
106 | + |
107 | +# snap exits with error if assertion already exists, so must ignore errors :-/ |
108 | +snap ack "${SNAP_FILE_NAME}.account" || true |
109 | +snap ack "${SNAP_FILE_NAME}.snap-declaration" || true |
110 | +snap ack "${SNAP_FILE_NAME}.snap-revision" || true |
111 | + |
112 | +# Delete the assertions files after importing them |
113 | +rm -f "${SNAP_FILE_NAME}.*" |
114 | + |
115 | +snap install ${SNAP_FILE_NAME} |
116 | |
117 | === modified file 'debian/control' |
118 | --- debian/control 2016-09-21 14:55:05 +0000 |
119 | +++ debian/control 2016-09-21 14:55:05 +0000 |
120 | @@ -40,16 +40,19 @@ |
121 | Package: unity-scope-click |
122 | Architecture: armhf arm64 i386 amd64 |
123 | Depends: account-plugin-ubuntuone, |
124 | + grep, |
125 | + libdigest-sha3-perl, |
126 | libglib2.0-bin, |
127 | libsqlite3-0 (>= 3.8.5), |
128 | - packagekit, |
129 | - packagekit-tools, |
130 | + snapd | packagekit, |
131 | + snapd | packagekit-tools, |
132 | pay-service, |
133 | ubuntu-app-launch-tools, |
134 | ubuntu-download-manager, |
135 | - ubuntu-sdk-libs, |
136 | + snapd | ubuntu-sdk-libs, |
137 | unity-scope-click-departmentsdb (= ${binary:Version}), |
138 | upstart, |
139 | + wget, |
140 | ${misc:Depends}, |
141 | ${shlibs:Depends}, |
142 | Breaks: unity (<< 7.0), |
143 | |
144 | === modified file 'libclickscope/click/configuration.cpp' |
145 | --- libclickscope/click/configuration.cpp 2016-02-19 03:35:43 +0000 |
146 | +++ libclickscope/click/configuration.cpp 2016-09-21 14:55:05 +0000 |
147 | @@ -1,5 +1,5 @@ |
148 | /* |
149 | - * Copyright (C) 2014-2015 Canonical Ltd. |
150 | + * Copyright (C) 2014-2016 Canonical Ltd. |
151 | * |
152 | * This program is free software: you can redistribute it and/or modify it |
153 | * under the terms of the GNU General Public License version 3, as published |
154 | @@ -27,6 +27,8 @@ |
155 | * files in the program, then also delete it here. |
156 | */ |
157 | |
158 | +#include "configuration.h" |
159 | + |
160 | #include <string> |
161 | #include <vector> |
162 | |
163 | @@ -43,8 +45,9 @@ |
164 | |
165 | #include <boost/algorithm/string.hpp> |
166 | #include <boost/algorithm/string/replace.hpp> |
167 | - |
168 | -#include "configuration.h" |
169 | +#include <sys/stat.h> |
170 | +#include <sys/types.h> |
171 | +#include <unistd.h> |
172 | |
173 | namespace click { |
174 | |
175 | @@ -121,6 +124,13 @@ |
176 | return arch; |
177 | } |
178 | |
179 | +bool Configuration::is_snapd_running() const |
180 | +{ |
181 | + struct stat sb; |
182 | + int retval = stat("/run/snapd.socket", &sb); |
183 | + return retval == 0 && (sb.st_mode & S_IFMT) == S_IFSOCK; |
184 | +} |
185 | + |
186 | bool Configuration::get_purchases_enabled() |
187 | { |
188 | const char* env_value = std::getenv(PURCHASES_ENVVAR); |
189 | |
190 | === modified file 'libclickscope/click/configuration.h' |
191 | --- libclickscope/click/configuration.h 2016-09-21 14:55:05 +0000 |
192 | +++ libclickscope/click/configuration.h 2016-09-21 14:55:05 +0000 |
193 | @@ -54,6 +54,7 @@ |
194 | |
195 | virtual std::vector<std::string> get_available_frameworks(); |
196 | virtual std::string get_architecture(); |
197 | + virtual bool is_snapd_running() const; |
198 | static bool get_purchases_enabled(); |
199 | static std::string get_currency(const std::string& fallback = CURRENCY_DEFAULT); |
200 | |
201 | |
202 | === modified file 'libclickscope/click/download-manager.cpp' |
203 | --- libclickscope/click/download-manager.cpp 2016-05-10 13:42:12 +0000 |
204 | +++ libclickscope/click/download-manager.cpp 2016-09-21 14:55:05 +0000 |
205 | @@ -57,12 +57,6 @@ |
206 | |
207 | static const QString DOWNLOAD_MANAGER_SHA512 = "sha512"; |
208 | |
209 | -const QByteArray& CLICK_TOKEN_HEADER() |
210 | -{ |
211 | - static const QByteArray result("X-Click-Token"); |
212 | - return result; |
213 | -} |
214 | - |
215 | DownloadManager::DownloadManager(const QSharedPointer<click::web::Client>& client, |
216 | const QSharedPointer<udm::Manager>& manager) : |
217 | client(client), |
218 | @@ -86,11 +80,8 @@ |
219 | if (downloads.size() > 0) { |
220 | auto download = downloads.at(0); |
221 | object_path = download->id().toStdString(); |
222 | - } |
223 | - qDebug() << "Found object path" << QString::fromStdString(object_path) |
224 | - << "for package" << QString::fromStdString(package_name); |
225 | - if (downloads.size() > 1) { |
226 | - qWarning() << "More than one download with the same object path"; |
227 | + qDebug() << "Found object path" << QString::fromStdString(object_path) |
228 | + << "for package" << QString::fromStdString(package_name); |
229 | } |
230 | callback(object_path); |
231 | }, [callback, package_name](const QString& /*key*/, const QString& /*value*/, DownloadsList* /*downloads_list*/){ |
232 | @@ -100,78 +91,57 @@ |
233 | }); |
234 | } |
235 | |
236 | -click::web::Cancellable DownloadManager::start(const std::string& url, |
237 | - const std::string& download_sha512, |
238 | - const std::string& package_name, |
239 | - const std::function<void (std::string, Error)>& callback) |
240 | -{ |
241 | - QSharedPointer<click::web::Response> response = client->call |
242 | - (url, "HEAD", true); |
243 | - |
244 | - QObject::connect(response.data(), &click::web::Response::finished, |
245 | - [this, callback, url, download_sha512, package_name, |
246 | - response](QString) { |
247 | - auto status = response->get_status_code(); |
248 | - if (status == 200) { |
249 | - auto clickToken = response->get_header(CLICK_TOKEN_HEADER().data()); |
250 | - qDebug() << "Received click token:" << clickToken.c_str(); |
251 | - QVariantMap metadata; |
252 | - |
253 | - QVariant commandline = QVariant(QStringList() << DOWNLOAD_COMMAND << "$file" << package_name.c_str()); |
254 | - metadata[DOWNLOAD_COMMAND_KEY] = commandline; |
255 | - metadata[DOWNLOAD_APP_ID_KEY] = package_name.c_str(); |
256 | - metadata["package_name"] = package_name.c_str(); |
257 | - |
258 | - QMap<QString, QString> headers; |
259 | - headers[CLICK_TOKEN_HEADER()] = clickToken.c_str(); |
260 | - |
261 | - udm::DownloadStruct downloadStruct(url.c_str(), |
262 | - download_sha512.c_str(), |
263 | - DOWNLOAD_MANAGER_SHA512, |
264 | - metadata, |
265 | - headers); |
266 | - |
267 | - dm->createDownload(downloadStruct, |
268 | - [callback](Download* download) { |
269 | - if (download->isError()) { |
270 | - auto error = download->error()->errorString().toUtf8().data(); |
271 | - qDebug() << "Received error from ubuntu-download-manager:" << error; |
272 | - callback(error, Error::DownloadInstallError); |
273 | - } else { |
274 | - download->start(); |
275 | - callback(download->id().toUtf8().data(), Error::NoError); |
276 | - } |
277 | - }, |
278 | - [callback](Download* download) { |
279 | - callback(download->error()->errorString().toUtf8().data(), |
280 | - Error::DownloadInstallError); |
281 | - }); |
282 | - } else { |
283 | - std::string error{"Unhandled HTTP response code: "}; |
284 | - error += status; |
285 | - callback(error, Error::DownloadInstallError); |
286 | - } |
287 | - }); |
288 | - QObject::connect(response.data(), &click::web::Response::error, |
289 | - [this, callback, package_name](QString error, int error_code) { |
290 | - qWarning() << QStringLiteral("Network error (%1) fetching click token for:").arg(error_code) << package_name.c_str(); |
291 | - switch(error_code) { |
292 | - case 401: |
293 | - case 403: |
294 | - client->invalidateCredentials(); |
295 | - callback(error.toUtf8().data(), Error::CredentialsError); |
296 | - break; |
297 | - default: |
298 | - callback(error.toUtf8().data(), Error::DownloadInstallError); |
299 | - } |
300 | - }); |
301 | - |
302 | - return click::web::Cancellable(response); |
303 | -} |
304 | - |
305 | -void DownloadManager::setCredentialsService(const QSharedPointer<click::CredentialsService>& credentialsService) |
306 | -{ |
307 | - sso = credentialsService; |
308 | +void DownloadManager::start(const std::string& url, |
309 | + const std::string& download_sha512, |
310 | + const std::string& package_name, |
311 | + const std::function<void (std::string, Error)>& callback) |
312 | +{ |
313 | + auto signature = client->signUrl(url, "GET"); |
314 | + |
315 | + QVariantMap metadata; |
316 | + |
317 | + auto commandline = QVariant(QStringList() << DOWNLOAD_COMMAND << "$file" << package_name.c_str()); |
318 | + metadata[DOWNLOAD_COMMAND_KEY] = commandline; |
319 | + metadata[DOWNLOAD_APP_ID_KEY] = package_name.c_str(); |
320 | + metadata["package_name"] = package_name.c_str(); |
321 | + |
322 | + QMap<QString, QString> headers; |
323 | + headers[click::web::AUTHORIZATION_HEADER.c_str()] = signature.c_str(); |
324 | + |
325 | + udm::DownloadStruct downloadStruct(url.c_str(), |
326 | + download_sha512.c_str(), |
327 | + DOWNLOAD_MANAGER_SHA512, |
328 | + metadata, |
329 | + headers); |
330 | + |
331 | + dm->createDownload(downloadStruct, |
332 | + [callback](Download* download) { |
333 | + if (download != nullptr) { |
334 | + if (download->isError()) { |
335 | + auto errorstr = download->error()->errorString(); |
336 | + auto error = errorstr.toStdString(); |
337 | + qDebug() << "Received error from ubuntu-download-manager:" << errorstr; |
338 | + callback(error, Error::DownloadInstallError); |
339 | + } else { |
340 | + download->start(); |
341 | + callback(download->id().toStdString(), |
342 | + Error::NoError); |
343 | + } |
344 | + } else { |
345 | + callback("Received nullptr for download.", |
346 | + Error::DownloadInstallError); |
347 | + } |
348 | + }, |
349 | + [callback](Download* download) { |
350 | + if (download != nullptr) { |
351 | + auto errorstr = download->error()->errorString(); |
352 | + auto error = errorstr.toStdString(); |
353 | + callback(error, Error::DownloadInstallError); |
354 | + } else { |
355 | + callback("Received nullptr for download.", |
356 | + Error::DownloadInstallError); |
357 | + } |
358 | + }); |
359 | } |
360 | |
361 | } // namespace click |
362 | |
363 | === modified file 'libclickscope/click/download-manager.h' |
364 | --- libclickscope/click/download-manager.h 2016-02-26 18:51:22 +0000 |
365 | +++ libclickscope/click/download-manager.h 2016-09-21 14:55:05 +0000 |
366 | @@ -68,18 +68,14 @@ |
367 | |
368 | virtual void get_progress(const std::string& package_name, |
369 | const std::function<void (std::string)>& callback); |
370 | - virtual click::web::Cancellable start(const std::string& url, |
371 | - const std::string& download_sha512, |
372 | - const std::string& package_name, |
373 | - const std::function<void (std::string, |
374 | - Error)>& callback); |
375 | - |
376 | - virtual void setCredentialsService(const QSharedPointer<click::CredentialsService>& credentialsService); |
377 | + virtual void start(const std::string& url, |
378 | + const std::string& download_sha512, |
379 | + const std::string& package_name, |
380 | + const std::function<void (std::string, Error)>& callback); |
381 | |
382 | protected: |
383 | QSharedPointer<click::web::Client> client; |
384 | QSharedPointer<Ubuntu::DownloadManager::Manager> dm; |
385 | - QSharedPointer<click::CredentialsService> sso; |
386 | }; |
387 | |
388 | } |
389 | |
390 | === modified file 'libclickscope/click/index.cpp' |
391 | --- libclickscope/click/index.cpp 2016-04-26 10:56:47 +0000 |
392 | +++ libclickscope/click/index.cpp 2016-09-21 14:55:05 +0000 |
393 | @@ -112,8 +112,13 @@ |
394 | std::map<std::string, std::string> Index::build_headers() |
395 | { |
396 | std::stringstream frameworks; |
397 | - for (auto f: configuration->get_available_frameworks()) { |
398 | - frameworks << "," << f; |
399 | + const auto frameworklist = configuration->get_available_frameworks(); |
400 | + if (frameworklist.empty()) { |
401 | + frameworks << "none"; |
402 | + } else { |
403 | + for (const auto& f: frameworklist) { |
404 | + frameworks << "," << f; |
405 | + } |
406 | } |
407 | |
408 | return std::map<std::string, std::string> { |
409 | @@ -123,6 +128,15 @@ |
410 | }; |
411 | } |
412 | |
413 | +std::map<std::string, std::string> Index::add_snap_headers(const std::map<std::string, std::string>& headers) const |
414 | +{ |
415 | + std::map<std::string, std::string> new_headers{headers}; |
416 | + new_headers["X-Ubuntu-Series"] = "16"; // Need to get from snapd |
417 | + new_headers["X-Ubuntu-Slots"] = "unity8"; // Only want unity8-using snaps |
418 | + |
419 | + return new_headers; |
420 | +} |
421 | + |
422 | std::pair<Packages, Packages> Index::package_lists_from_json(const std::string& json) |
423 | { |
424 | Json::Reader reader; |
425 | @@ -147,6 +161,35 @@ |
426 | return std::pair<Packages, Packages>(pl, recommends); |
427 | } |
428 | |
429 | +click::web::Cancellable Index::search_snaps(const std::string& query, |
430 | + std::function<void(click::Packages search_results, click::Packages recommendations)> callback, |
431 | + bool force_cache) |
432 | +{ |
433 | + click::web::CallParams params; |
434 | + auto built_query = build_index_query(query, "" /* No dept for snaps */); |
435 | + params.add(click::QUERY_ARGNAME, built_query.c_str()); |
436 | + |
437 | + auto headers = add_snap_headers(build_headers()); |
438 | + |
439 | + QSharedPointer<click::web::Response> response |
440 | + (client->call(get_base_url() + click::SNAP_SEARCH_PATH, |
441 | + "GET", true, headers, "", params, force_cache)); |
442 | + |
443 | + QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) { |
444 | + auto package_lists = package_lists_from_json(reply.toUtf8().constData()); |
445 | + callback(package_lists.first, package_lists.second); |
446 | + }); |
447 | + QObject::connect(response.data(), &click::web::Response::error, [=](QString description) { |
448 | + qWarning() << "No packages found due to network error:" << description; |
449 | + click::Packages pl; |
450 | + click::Packages recommends; |
451 | + qDebug() << "calling callback"; |
452 | + callback(pl, recommends); |
453 | + qDebug() << " ...Done!"; |
454 | + }); |
455 | + return click::web::Cancellable(response); |
456 | +} |
457 | + |
458 | click::web::Cancellable Index::search (const std::string& query, const std::string& department, |
459 | std::function<void(click::Packages search_results, click::Packages recommendations)> callback, |
460 | bool force_cache) |
461 | @@ -162,8 +205,8 @@ |
462 | package_lists = package_lists_from_json(reply.toUtf8().constData()); |
463 | callback(package_lists.first, package_lists.second); |
464 | }); |
465 | - QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) { |
466 | - qDebug() << "No packages found due to network error"; |
467 | + QObject::connect(response.data(), &click::web::Response::error, [=](QString description) { |
468 | + qWarning() << "No packages found due to network error:" << description; |
469 | click::Packages pl; |
470 | click::Packages recommends; |
471 | qDebug() << "calling callback"; |
472 | @@ -215,10 +258,21 @@ |
473 | return click::web::Cancellable(response); |
474 | } |
475 | |
476 | -click::web::Cancellable Index::get_details (const std::string& package_name, std::function<void(PackageDetails, click::Index::Error)> callback, bool force_cache) |
477 | +click::web::Cancellable Index::get_details (const std::string& package_name, |
478 | + std::function<void(PackageDetails, |
479 | + click::Index::Error)> callback, |
480 | + bool is_snap, |
481 | + bool force_cache) |
482 | { |
483 | + std::string details_path{click::DETAILS_PATH}; |
484 | + auto headers = build_headers(); |
485 | + if (is_snap) { |
486 | + details_path = click::SNAP_DETAILS_PATH; |
487 | + headers = add_snap_headers(headers); |
488 | + } |
489 | QSharedPointer<click::web::Response> response = client->call |
490 | - (get_base_url() + click::DETAILS_PATH + package_name, |
491 | + (get_base_url() + details_path + package_name, |
492 | + "GET", true, headers, "", |
493 | click::web::CallParams(), |
494 | force_cache); |
495 | qDebug() << "getting details for" << package_name.c_str(); |
496 | |
497 | === modified file 'libclickscope/click/index.h' |
498 | --- libclickscope/click/index.h 2016-04-26 10:56:47 +0000 |
499 | +++ libclickscope/click/index.h 2016-09-21 14:55:05 +0000 |
500 | @@ -1,5 +1,5 @@ |
501 | /* |
502 | - * Copyright (C) 2014 Canonical Ltd. |
503 | + * Copyright (C) 2014-2016 Canonical Ltd. |
504 | * |
505 | * This program is free software: you can redistribute it and/or modify it |
506 | * under the terms of the GNU General Public License version 3, as published |
507 | @@ -49,11 +49,13 @@ |
508 | const std::string SEARCH_BASE_URL_ENVVAR = "U1_SEARCH_BASE_URL"; |
509 | const std::string SEARCH_BASE_URL = "https://search.apps.ubuntu.com/"; |
510 | const std::string SEARCH_PATH = "api/v1/search"; |
511 | +const std::string SNAP_SEARCH_PATH = "api/v1/snaps/search"; |
512 | const std::string BOOTSTRAP_PATH = "api/v1"; |
513 | const std::string SUPPORTED_FRAMEWORKS = "framework:ubuntu-sdk-13.10"; |
514 | const std::string QUERY_ARGNAME = "q"; |
515 | const std::string ARCHITECTURE = "architecture:"; |
516 | const std::string DETAILS_PATH = "api/v1/package/"; |
517 | +const std::string SNAP_DETAILS_PATH = "api/v1/snaps/details/"; |
518 | const std::string CURRENCY_HEADER = "X-Suggested-Currency"; |
519 | |
520 | class PackageManager |
521 | @@ -72,6 +74,7 @@ |
522 | std::string m_suggested_currency; |
523 | virtual std::string build_index_query(const std::string& query, const std::string& department); |
524 | virtual std::map<std::string, std::string> build_headers(); |
525 | + virtual std::map<std::string, std::string> add_snap_headers(const std::map<std::string, std::string>& headers) const; |
526 | |
527 | public: |
528 | enum class Error {NoError, CredentialsError, NetworkError}; |
529 | @@ -79,9 +82,15 @@ |
530 | Index(const QSharedPointer<click::web::Client>& client, |
531 | const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration())); |
532 | virtual std::pair<Packages, Packages> package_lists_from_json(const std::string& json); |
533 | + virtual click::web::Cancellable search_snaps(const std::string& query, |
534 | + std::function<void(click::Packages search_results, click::Packages recommendations)> callback, |
535 | + bool force_cache = false); |
536 | virtual click::web::Cancellable search (const std::string& query, const std::string& department, std::function<void(Packages, Packages)> callback, bool |
537 | force_cache = false); |
538 | - virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback, bool force_cache = false); |
539 | + virtual click::web::Cancellable get_details(const std::string& package_name, |
540 | + std::function<void(PackageDetails, Error)> callback, |
541 | + bool is_snap = false, |
542 | + bool force_cache = false); |
543 | virtual click::web::Cancellable bootstrap(std::function<void(const DepartmentList&, const HighlightList&, Error, int)> callback, bool force_cache = false); |
544 | virtual click::web::Cancellable departments(const std::string& department_href, std::function<void(const DepartmentList&, const HighlightList&, Error, int)> |
545 | callback, bool force_cache = false); |
546 | |
547 | === modified file 'libclickscope/click/package.cpp' |
548 | --- libclickscope/click/package.cpp 2015-11-24 18:23:23 +0000 |
549 | +++ libclickscope/click/package.cpp 2016-09-21 14:55:05 +0000 |
550 | @@ -95,6 +95,10 @@ |
551 | p.publisher = item[Package::JsonKeys::publisher].asString(); |
552 | p.rating = item[Package::JsonKeys::rating].asDouble(); |
553 | p.version = item[Package::JsonKeys::version].asString(); |
554 | + |
555 | + p.snap_id = item[Package::JsonKeys::snap_id].asString(); |
556 | + p.alias = item[Package::JsonKeys::alias].asString(); |
557 | + |
558 | return p; |
559 | } |
560 | |
561 | |
562 | === modified file 'libclickscope/click/package.h' |
563 | --- libclickscope/click/package.h 2015-11-24 18:23:23 +0000 |
564 | +++ libclickscope/click/package.h 2016-09-21 14:55:05 +0000 |
565 | @@ -64,6 +64,8 @@ |
566 | constexpr static const char* publisher{"publisher"}; |
567 | constexpr static const char* rating{"ratings_average"}; |
568 | constexpr static const char* version{"version"}; |
569 | + constexpr static const char* snap_id{"snap_id"}; |
570 | + constexpr static const char* alias{"alias"}; |
571 | |
572 | // NOTE: The "price" field is deprecated in favor of "prices" |
573 | constexpr static const char* prices{"prices"}; |
574 | @@ -107,6 +109,8 @@ |
575 | void matches (std::string query, std::function<bool> callback); |
576 | std::string content; |
577 | std::map<std::string, double> prices; |
578 | + std::string snap_id; |
579 | + std::string alias; |
580 | |
581 | struct hash_name { |
582 | public : |
583 | |
584 | === modified file 'libclickscope/click/preview.cpp' |
585 | --- libclickscope/click/preview.cpp 2016-09-21 14:55:05 +0000 |
586 | +++ libclickscope/click/preview.cpp 2016-09-21 14:55:05 +0000 |
587 | @@ -442,7 +442,11 @@ |
588 | // and code using it does not need to worry about threading/event loop topics. |
589 | run_under_qt([this, details_callback, reviews_callback, app_name, force_cache]() |
590 | { |
591 | - index_operation = index->get_details(app_name, [this, app_name, details_callback, reviews_callback, force_cache](PackageDetails details, click::Index::Error error){ |
592 | + index_operation = index->get_details(app_name, |
593 | + [this, app_name, |
594 | + details_callback, |
595 | + reviews_callback, |
596 | + force_cache](PackageDetails details, click::Index::Error error){ |
597 | if(error == click::Index::Error::NoError) { |
598 | qDebug() << "Got details:" << app_name.c_str(); |
599 | details_callback(details); |
600 | @@ -455,10 +459,17 @@ |
601 | details.main_screenshot_url = get_string_maybe_null(result["main_screenshot"]); |
602 | details_callback(details); |
603 | } |
604 | - reviews_operation = reviews->fetch_reviews(app_name, |
605 | - reviews_callback, |
606 | - force_cache); |
607 | - }, force_cache); |
608 | + // FIXME: No RNR support for v2 snaps yet, so avoid the |
609 | + // network hit if we're showing a snap preview |
610 | + if (app_name.rfind(".") != std::string::npos) { |
611 | + reviews_operation = reviews->fetch_reviews(app_name, |
612 | + reviews_callback, |
613 | + force_cache); |
614 | + } else { |
615 | + reviews_callback(click::ReviewList{}, |
616 | + click::Reviews::Error::NoError); |
617 | + } |
618 | + }, app_name.rfind(".") == std::string::npos, force_cache); |
619 | }); |
620 | } |
621 | } |
622 | |
623 | === modified file 'libclickscope/click/webclient.cpp' |
624 | --- libclickscope/click/webclient.cpp 2016-05-25 16:19:51 +0000 |
625 | +++ libclickscope/click/webclient.cpp 2016-09-21 14:55:05 +0000 |
626 | @@ -78,6 +78,26 @@ |
627 | { |
628 | } |
629 | |
630 | +std::string click::web::Client::signUrl(const std::string& url, |
631 | + const std::string& method) |
632 | +{ |
633 | + QString signature; |
634 | + |
635 | + if (impl->sso.isNull()) { |
636 | + qCritical() << "Unable to sign request without SSO object."; |
637 | + } else { |
638 | + auto token = impl->sso->getToken(); |
639 | + if (token.isValid()) { |
640 | + signature = token.signUrl(QString::fromStdString(url), |
641 | + QString::fromStdString(method)); |
642 | + qDebug() << "Signed URL:" << QString::fromStdString(url); |
643 | + } else { |
644 | + qWarning() << "Signing requested but returned token is invalid."; |
645 | + } |
646 | + } |
647 | + return signature.toStdString(); |
648 | +} |
649 | + |
650 | QSharedPointer<click::web::Response> click::web::Client::call( |
651 | const std::string& iri, |
652 | const click::web::CallParams& params, |
653 | @@ -137,25 +157,14 @@ |
654 | auto deviceId = Configuration().get_device_id(); |
655 | request->setRawHeader(DEVICE_ID_HEADER.c_str(), deviceId.data()); |
656 | |
657 | - if (sign && !impl->sso.isNull()) { |
658 | - auto token = impl->sso->getToken(); |
659 | - if (token.isValid()) { |
660 | - QString auth_header = token.signUrl(url.toString(), |
661 | - method.c_str()); |
662 | - qDebug() << "Signed URL:" << request->url().toString(); |
663 | - request->setRawHeader(AUTHORIZATION_HEADER.c_str(), auth_header.toUtf8()); |
664 | - } else { |
665 | - qWarning() << "Signing reuested but returned token is invalid."; |
666 | - } |
667 | - |
668 | - doConnect(); |
669 | - } else { |
670 | - if (sign && impl->sso.isNull()) { |
671 | - qCritical() << "Unable to sign request without SSO object."; |
672 | - } |
673 | - doConnect(); |
674 | + if (sign) { |
675 | + auto auth_header = signUrl(url.toString().toStdString(), method); |
676 | + if (!auth_header.empty()) |
677 | + request->setRawHeader(AUTHORIZATION_HEADER.c_str(), |
678 | + auth_header.c_str()); |
679 | } |
680 | |
681 | + doConnect(); |
682 | |
683 | return responsePtr; |
684 | } |
685 | |
686 | === modified file 'libclickscope/click/webclient.h' |
687 | --- libclickscope/click/webclient.h 2016-05-25 16:19:51 +0000 |
688 | +++ libclickscope/click/webclient.h 2016-09-21 14:55:05 +0000 |
689 | @@ -115,6 +115,8 @@ |
690 | Client(const QSharedPointer<click::network::AccessManager>& networkAccessManager); |
691 | virtual ~Client(); |
692 | |
693 | + virtual std::string signUrl(const std::string& url, |
694 | + const std::string& method); |
695 | virtual QSharedPointer<Response> call( |
696 | const std::string& iri, |
697 | const CallParams& params = CallParams(), bool force_cache = false); |
698 | |
699 | === modified file 'libclickscope/tests/mock_webclient.h' |
700 | --- libclickscope/tests/mock_webclient.h 2016-05-25 16:19:51 +0000 |
701 | +++ libclickscope/tests/mock_webclient.h 2016-09-21 14:55:05 +0000 |
702 | @@ -61,13 +61,6 @@ |
703 | Mock instance; |
704 | }; |
705 | |
706 | -QSharedPointer<click::web::Response> responseForReply(const QSharedPointer<click::network::Reply>& reply) |
707 | -{ |
708 | - auto response = QSharedPointer<click::web::Response>(new click::web::Response(QSharedPointer<QNetworkRequest>(new QNetworkRequest()), QSharedPointer<QBuffer>(new QBuffer()))); |
709 | - response->setReply(reply); |
710 | - return response; |
711 | -} |
712 | - |
713 | class MockClient : public click::web::Client |
714 | { |
715 | public: |
716 | @@ -76,6 +69,7 @@ |
717 | { |
718 | } |
719 | |
720 | + MOCK_METHOD2(signUrl, std::string(const std::string&, const std::string&)); |
721 | // Mocking default arguments: https://groups.google.com/forum/#!topic/googlemock/XrabW20vV7o |
722 | MOCK_METHOD6(callImpl, QSharedPointer<click::web::Response>( |
723 | const std::string& iri, |
724 | @@ -102,6 +96,16 @@ |
725 | |
726 | MOCK_METHOD1(has_header, bool(const std::string& header)); |
727 | MOCK_METHOD1(get_header, std::string(const std::string&header)); |
728 | + |
729 | + static QSharedPointer<click::web::Response> responseForReply(const QSharedPointer<click::network::Reply>& reply) |
730 | + { |
731 | + auto response = QSharedPointer<click::web::Response> |
732 | + (new click::web::Response(QSharedPointer<QNetworkRequest>(new QNetworkRequest()), |
733 | + QSharedPointer<QBuffer>(new QBuffer()))); |
734 | + response->setReply(reply); |
735 | + return response; |
736 | + } |
737 | + |
738 | }; |
739 | |
740 | } |
741 | |
742 | === modified file 'libclickscope/tests/test_bootstrap.cpp' |
743 | --- libclickscope/tests/test_bootstrap.cpp 2016-06-30 20:42:56 +0000 |
744 | +++ libclickscope/tests/test_bootstrap.cpp 2016-09-21 14:55:05 +0000 |
745 | @@ -70,7 +70,7 @@ |
746 | TEST_F(BootstrapTest, testBootstrapCallsWebservice) |
747 | { |
748 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
749 | - auto response = responseForReply(reply.asSharedPtr()); |
750 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
751 | |
752 | EXPECT_CALL(*clientPtr, callImpl(EndsWith(click::BOOTSTRAP_PATH), "GET", _, _, _, _)) |
753 | .Times(1) |
754 | @@ -81,7 +81,7 @@ |
755 | TEST_F(BootstrapTest, testBootstrapJsonIsParsed) |
756 | { |
757 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
758 | - auto response = responseForReply(reply.asSharedPtr()); |
759 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
760 | |
761 | QByteArray fake_json(FAKE_JSON_BOOTSTRAP.c_str()); |
762 | EXPECT_CALL(reply.instance, readAll()) |
763 | |
764 | === modified file 'libclickscope/tests/test_download_manager.cpp' |
765 | --- libclickscope/tests/test_download_manager.cpp 2016-05-10 13:42:12 +0000 |
766 | +++ libclickscope/tests/test_download_manager.cpp 2016-09-21 14:55:05 +0000 |
767 | @@ -63,6 +63,7 @@ |
768 | |
769 | virtual void SetUp() |
770 | { |
771 | + sdmPtr.reset(new MockSystemDownloadManager()); |
772 | ssoPtr.reset(new MockCredentialsService()); |
773 | namPtr.reset(new MockNetworkAccessManager()); |
774 | clientPtr.reset(new NiceMock<MockClient>(namPtr)); |
775 | @@ -76,138 +77,165 @@ |
776 | |
777 | } |
778 | |
779 | -TEST_F(DownloadManagerTest, testStartCallsWebservice) |
780 | +TEST_F(DownloadManagerTest, testStartCallsSignUrl) |
781 | { |
782 | - LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
783 | - auto response = responseForReply(reply.asSharedPtr()); |
784 | - |
785 | - EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
786 | - .Times(1) |
787 | - .WillOnce(Return(response)); |
788 | - |
789 | + EXPECT_CALL(*clientPtr, signUrl(_, "GET")).Times(1); |
790 | + EXPECT_CALL(*sdmPtr, createDownload(_, _, _)).Times(1); |
791 | dmPtr->start("", "", "", |
792 | [](std::string, click::DownloadManager::Error) {}); |
793 | } |
794 | |
795 | -TEST_F(DownloadManagerTest, testStartCallbackCalled) |
796 | -{ |
797 | - LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
798 | - auto response = responseForReply(reply.asSharedPtr()); |
799 | - |
800 | - EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(0))); |
801 | - EXPECT_CALL(reply.instance, readAll()) |
802 | - .Times(1) |
803 | - .WillOnce(Return("")); |
804 | - EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
805 | - .Times(1) |
806 | - .WillOnce(Return(response)); |
807 | - EXPECT_CALL(*this, start_callback(_, _)).Times(1); |
808 | - |
809 | - dmPtr->start("", "", "", |
810 | - [this](std::string msg, click::DownloadManager::Error err) { |
811 | - start_callback(msg, err); |
812 | - }); |
813 | - response->replyFinished(); |
814 | -} |
815 | - |
816 | -TEST_F(DownloadManagerTest, testStartHTTPForbidden) |
817 | -{ |
818 | - LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
819 | - auto response = responseForReply(reply.asSharedPtr()); |
820 | - |
821 | - EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(403))); |
822 | - EXPECT_CALL(reply.instance, readAll()) |
823 | - .Times(1) |
824 | - .WillOnce(Return("")); |
825 | - EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
826 | - .Times(1) |
827 | - .WillOnce(Return(response)); |
828 | - EXPECT_CALL(*this, start_callback(StartsWith("Unhandled HTTP response code:"), |
829 | - click::DownloadManager::Error::DownloadInstallError)).Times(1); |
830 | - |
831 | - dmPtr->start("", "", "", |
832 | - [this](std::string msg, click::DownloadManager::Error err) { |
833 | - start_callback(msg, err); |
834 | - }); |
835 | - response->replyFinished(); |
836 | -} |
837 | - |
838 | -TEST_F(DownloadManagerTest, testStartHTTPError) |
839 | -{ |
840 | - LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
841 | - auto response = responseForReply(reply.asSharedPtr()); |
842 | - |
843 | - EXPECT_CALL(reply.instance, errorString()) |
844 | - .WillOnce(Return(QString("ERROR"))); |
845 | - EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(404))); |
846 | - EXPECT_CALL(reply.instance, readAll()) |
847 | - .Times(1) |
848 | - .WillOnce(Return("")); |
849 | - EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
850 | - .Times(1) |
851 | - .WillOnce(Return(response)); |
852 | - EXPECT_CALL(*this, start_callback("ERROR (203)", |
853 | - click::DownloadManager::Error::DownloadInstallError)).Times(1); |
854 | - |
855 | - dmPtr->start("", "", "", |
856 | - [this](std::string msg, click::DownloadManager::Error err) { |
857 | - start_callback(msg, err); |
858 | - }); |
859 | - response->errorHandler(QNetworkReply::ContentNotFoundError); |
860 | -} |
861 | - |
862 | -TEST_F(DownloadManagerTest, testStartCredentialsError) |
863 | -{ |
864 | - LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
865 | - auto response = responseForReply(reply.asSharedPtr()); |
866 | - |
867 | - EXPECT_CALL(reply.instance, errorString()) |
868 | - .WillOnce(Return(QString("ERROR"))); |
869 | - EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(401))); |
870 | - EXPECT_CALL(reply.instance, readAll()) |
871 | - .Times(1) |
872 | - .WillOnce(Return("")); |
873 | - EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
874 | - .Times(1) |
875 | - .WillOnce(Return(response)); |
876 | - EXPECT_CALL(*ssoPtr, invalidateCredentials()); |
877 | - EXPECT_CALL(*this, start_callback("ERROR (201)", |
878 | - click::DownloadManager::Error::CredentialsError)).Times(1); |
879 | - |
880 | - dmPtr->start("", "", "test.package", |
881 | - [this](std::string msg, click::DownloadManager::Error err) { |
882 | - start_callback(msg, err); |
883 | - }); |
884 | - response->errorHandler(QNetworkReply::ContentAccessDenied); |
885 | -} |
886 | - |
887 | -// FIXME: createDownload() SEGV under tests |
888 | -TEST_F(DownloadManagerTest, DISABLED_testStartDownloadCreated) |
889 | -{ |
890 | - LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
891 | - auto response = responseForReply(reply.asSharedPtr()); |
892 | - |
893 | - EXPECT_CALL(reply.instance, rawHeader(QByteArray("X-Click-Token"))) |
894 | - .Times(1) |
895 | - .WillOnce(Return(QString("clicktoken"))); |
896 | - EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(200))); |
897 | - EXPECT_CALL(reply.instance, readAll()) |
898 | - .Times(1) |
899 | - .WillOnce(Return("")); |
900 | - EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
901 | - .Times(1) |
902 | - .WillOnce(Return(response)); |
903 | - |
904 | - EXPECT_CALL(*sdmPtr, createDownload(_, _, _)); |
905 | - dmPtr->start("", "", "test.package", |
906 | - [this](std::string msg, click::DownloadManager::Error err) { |
907 | - start_callback(msg, err); |
908 | - }); |
909 | - response->replyFinished(); |
910 | -} |
911 | - |
912 | -// FIXME: getAllDownloadsWithMetadata() SEGV under tests |
913 | -TEST_F(DownloadManagerTest, DISABLED_testGetProgressNoDownloads) |
914 | +TEST_F(DownloadManagerTest, testStartDownloadSuccssIsError) |
915 | +{ |
916 | + auto mockDownload = new MockDownload(); |
917 | + auto mockError = new MockError(); |
918 | + EXPECT_CALL(*mockDownload, isError()) |
919 | + .Times(1) |
920 | + .WillOnce(Return(true)); |
921 | + EXPECT_CALL(*mockDownload, error()) |
922 | + .Times(1) |
923 | + .WillOnce(Return(mockError)); |
924 | + EXPECT_CALL(*mockError, errorString()) |
925 | + .Times(1) |
926 | + .WillOnce(Return(QStringLiteral(""))); |
927 | + |
928 | + EXPECT_CALL(*clientPtr, signUrl(_, "GET")).Times(1); |
929 | + EXPECT_CALL(*sdmPtr, createDownload(_, _, _)) |
930 | + .Times(1) |
931 | + .WillOnce(InvokeArgument<1>(mockDownload)); |
932 | + EXPECT_CALL(*this, start_callback(_, _)).Times(1); |
933 | + |
934 | + dmPtr->start("", "", "", |
935 | + [this](std::string msg, click::DownloadManager::Error err) { |
936 | + start_callback(msg, err); |
937 | + }); |
938 | + |
939 | + delete mockError; |
940 | + delete mockDownload; |
941 | +} |
942 | + |
943 | +TEST_F(DownloadManagerTest, testStartDownloadSuccssCallsStart) |
944 | +{ |
945 | + auto mockDownload = new MockDownload(); |
946 | + EXPECT_CALL(*mockDownload, isError()) |
947 | + .Times(1) |
948 | + .WillOnce(Return(false)); |
949 | + EXPECT_CALL(*mockDownload, start()).Times(1); |
950 | + EXPECT_CALL(*mockDownload, id()) |
951 | + .Times(1) |
952 | + .WillOnce(Return(QStringLiteral("download"))); |
953 | + |
954 | + EXPECT_CALL(*clientPtr, signUrl(_, "GET")).Times(1); |
955 | + EXPECT_CALL(*sdmPtr, createDownload(_, _, _)) |
956 | + .Times(1) |
957 | + .WillOnce(InvokeArgument<1>(mockDownload)); |
958 | + EXPECT_CALL(*this, start_callback(_, _)).Times(1); |
959 | + |
960 | + dmPtr->start("", "", "", |
961 | + [this](std::string msg, click::DownloadManager::Error err) { |
962 | + start_callback(msg, err); |
963 | + }); |
964 | + |
965 | + delete mockDownload; |
966 | +} |
967 | + |
968 | +TEST_F(DownloadManagerTest, testStartErrorCallback) |
969 | +{ |
970 | + auto mockDownload = new MockDownload(); |
971 | + auto mockError = new MockError(); |
972 | + EXPECT_CALL(*mockDownload, error()) |
973 | + .Times(1) |
974 | + .WillOnce(Return(mockError)); |
975 | + EXPECT_CALL(*mockError, errorString()) |
976 | + .Times(1) |
977 | + .WillOnce(Return(QStringLiteral(""))); |
978 | + |
979 | + EXPECT_CALL(*clientPtr, signUrl(_, "GET")).Times(1); |
980 | + EXPECT_CALL(*sdmPtr, createDownload(_, _, _)) |
981 | + .Times(1) |
982 | + .WillOnce(InvokeArgument<2>(mockDownload)); |
983 | + EXPECT_CALL(*this, start_callback(_, _)).Times(1); |
984 | + |
985 | + dmPtr->start("", "", "", |
986 | + [this](std::string msg, click::DownloadManager::Error err) { |
987 | + start_callback(msg, err); |
988 | + }); |
989 | + |
990 | + delete mockError; |
991 | + delete mockDownload; |
992 | +} |
993 | + |
994 | +TEST_F(DownloadManagerTest, testGetProgressDownloadFound) |
995 | +{ |
996 | + auto mockDownloadsList = new MockDownloadsList(); |
997 | + auto mockDownload = QSharedPointer<MockDownload>(new MockDownload()); |
998 | + |
999 | + QList<QSharedPointer<Ubuntu::DownloadManager::Download>> downloads{mockDownload}; |
1000 | + |
1001 | + EXPECT_CALL(*mockDownload, id()) |
1002 | + .Times(1) |
1003 | + .WillOnce(Return("download")); |
1004 | + EXPECT_CALL(*mockDownloadsList, downloads()) |
1005 | + .Times(1) |
1006 | + .WillOnce(Return(downloads)); |
1007 | + EXPECT_CALL(*sdmPtr, getAllDownloadsWithMetadata(_, _, _, _)) |
1008 | + .Times(1) |
1009 | + .WillOnce(InvokeArgument<2>(QStringLiteral(""), QStringLiteral(""), |
1010 | + mockDownloadsList)); |
1011 | + dmPtr->get_progress("com.example.test", |
1012 | + [this](std::string object_path) { |
1013 | + progress_callback(object_path); |
1014 | + }); |
1015 | + |
1016 | + delete mockDownloadsList; |
1017 | +} |
1018 | + |
1019 | +TEST_F(DownloadManagerTest, testGetProgressMultipleDownloadsFound) |
1020 | +{ |
1021 | + auto mockDownloadsList = new MockDownloadsList(); |
1022 | + auto mockDownload = QSharedPointer<MockDownload>(new MockDownload()); |
1023 | + auto mockDownload2 = QSharedPointer<MockDownload>(new MockDownload()); |
1024 | + |
1025 | + QList<QSharedPointer<Ubuntu::DownloadManager::Download>> downloads{mockDownload, mockDownload2}; |
1026 | + |
1027 | + EXPECT_CALL(*mockDownload, id()) |
1028 | + .Times(1) |
1029 | + .WillOnce(Return("download")); |
1030 | + EXPECT_CALL(*mockDownloadsList, downloads()) |
1031 | + .Times(1) |
1032 | + .WillOnce(Return(downloads)); |
1033 | + EXPECT_CALL(*sdmPtr, getAllDownloadsWithMetadata(_, _, _, _)) |
1034 | + .Times(1) |
1035 | + .WillOnce(InvokeArgument<2>(QStringLiteral(""), QStringLiteral(""), |
1036 | + mockDownloadsList)); |
1037 | + dmPtr->get_progress("com.example.test", |
1038 | + [this](std::string object_path) { |
1039 | + progress_callback(object_path); |
1040 | + }); |
1041 | + |
1042 | + delete mockDownloadsList; |
1043 | +} |
1044 | + |
1045 | +TEST_F(DownloadManagerTest, testGetProgressNoDownloadsFound) |
1046 | +{ |
1047 | + auto mockDownloadsList = new MockDownloadsList(); |
1048 | + QList<QSharedPointer<Ubuntu::DownloadManager::Download>> emptyDownloads{}; |
1049 | + EXPECT_CALL(*mockDownloadsList, downloads()) |
1050 | + .Times(1) |
1051 | + .WillOnce(Return(emptyDownloads)); |
1052 | + EXPECT_CALL(*sdmPtr, getAllDownloadsWithMetadata(_, _, _, _)) |
1053 | + .Times(1) |
1054 | + .WillOnce(InvokeArgument<2>(QStringLiteral(""), QStringLiteral(""), |
1055 | + mockDownloadsList)); |
1056 | + dmPtr->get_progress("com.example.test", |
1057 | + [this](std::string object_path) { |
1058 | + progress_callback(object_path); |
1059 | + }); |
1060 | + |
1061 | + delete mockDownloadsList; |
1062 | +} |
1063 | + |
1064 | +TEST_F(DownloadManagerTest, testGetProgressErrorCallback) |
1065 | { |
1066 | EXPECT_CALL(*sdmPtr, getAllDownloadsWithMetadata(_, _, _, _)) |
1067 | .Times(1) |
1068 | |
1069 | === modified file 'libclickscope/tests/test_index.cpp' |
1070 | --- libclickscope/tests/test_index.cpp 2016-05-10 13:42:12 +0000 |
1071 | +++ libclickscope/tests/test_index.cpp 2016-09-21 14:55:05 +0000 |
1072 | @@ -66,7 +66,7 @@ |
1073 | }; |
1074 | |
1075 | |
1076 | -class IndexTest : public ::testing::Test { |
1077 | +class SimpleIndexTest : public ::testing::Test { |
1078 | protected: |
1079 | QSharedPointer<MockClient> clientPtr; |
1080 | QSharedPointer<MockNetworkAccessManager> namPtr; |
1081 | @@ -86,6 +86,18 @@ |
1082 | MOCK_METHOD2(details_callback, void(click::PackageDetails, click::Index::Error)); |
1083 | }; |
1084 | |
1085 | +class IndexTest : public SimpleIndexTest { |
1086 | + virtual void SetUp() { |
1087 | + SimpleIndexTest::SetUp(); |
1088 | + EXPECT_CALL(*configPtr, get_architecture()) |
1089 | + .Times(1) |
1090 | + .WillOnce(Return(fake_arch)); |
1091 | + EXPECT_CALL(*configPtr, get_available_frameworks()) |
1092 | + .Times(1) |
1093 | + .WillOnce(Return(fake_frameworks)); |
1094 | + } |
1095 | +}; |
1096 | + |
1097 | class MockPackageManager : public click::PackageManager, public ::testing::Test |
1098 | { |
1099 | public: |
1100 | @@ -97,14 +109,8 @@ |
1101 | TEST_F(IndexTest, testSearchCallsWebservice) |
1102 | { |
1103 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1104 | - auto response = responseForReply(reply.asSharedPtr()); |
1105 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1106 | |
1107 | - EXPECT_CALL(*configPtr, get_architecture()) |
1108 | - .Times(1) |
1109 | - .WillOnce(Return(fake_arch)); |
1110 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1111 | - .Times(1) |
1112 | - .WillOnce(Return(fake_frameworks)); |
1113 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1114 | .Times(1) |
1115 | .WillOnce(Return(response)); |
1116 | @@ -120,14 +126,8 @@ |
1117 | TEST_F(IndexTest, testSearchQueryIsLowercase) |
1118 | { |
1119 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1120 | - auto response = responseForReply(reply.asSharedPtr()); |
1121 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1122 | |
1123 | - EXPECT_CALL(*configPtr, get_architecture()) |
1124 | - .Times(1) |
1125 | - .WillOnce(Return(fake_arch)); |
1126 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1127 | - .Times(1) |
1128 | - .WillOnce(Return(fake_frameworks)); |
1129 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, QueryContains("foobar"))) |
1130 | .Times(1) |
1131 | .WillOnce(Return(response)); |
1132 | @@ -139,14 +139,8 @@ |
1133 | TEST_F(IndexTest, testSearchSignsCall) |
1134 | { |
1135 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1136 | - auto response = responseForReply(reply.asSharedPtr()); |
1137 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1138 | |
1139 | - EXPECT_CALL(*configPtr, get_architecture()) |
1140 | - .Times(1) |
1141 | - .WillOnce(Return(fake_arch)); |
1142 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1143 | - .Times(1) |
1144 | - .WillOnce(Return(fake_frameworks)); |
1145 | EXPECT_CALL(*clientPtr, callImpl(_, _, true, _, _, _)) |
1146 | .Times(1) |
1147 | .WillOnce(Return(response)); |
1148 | @@ -154,17 +148,119 @@ |
1149 | indexPtr->search("", "", [](click::Packages, click::Packages) {}); |
1150 | } |
1151 | |
1152 | +TEST_F(IndexTest, testSearchSnapsCallsWebservice) |
1153 | +{ |
1154 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1155 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1156 | + |
1157 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1158 | + .Times(1) |
1159 | + .WillOnce(Return(response)); |
1160 | + |
1161 | + indexPtr->search_snaps("", [](click::Packages, click::Packages) {}); |
1162 | +} |
1163 | + |
1164 | +TEST_F(IndexTest, testSearchSnapsSendsRightPath) |
1165 | +{ |
1166 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1167 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1168 | + |
1169 | + EXPECT_CALL(*clientPtr, callImpl(EndsWith(click::SNAP_SEARCH_PATH), |
1170 | + _, _, _, _, _)) |
1171 | + .Times(1) |
1172 | + .WillOnce(Return(response)); |
1173 | + |
1174 | + indexPtr->search_snaps("", [](click::Packages, click::Packages) {}); |
1175 | +} |
1176 | + |
1177 | +TEST_F(IndexTest, testSearchSnapsQueryIsLowercase) |
1178 | +{ |
1179 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1180 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1181 | + |
1182 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, QueryContains("foobar"))) |
1183 | + .Times(1) |
1184 | + .WillOnce(Return(response)); |
1185 | + |
1186 | + indexPtr->search_snaps("FooBar", [](click::Packages, click::Packages) {}); |
1187 | +} |
1188 | + |
1189 | + |
1190 | +TEST_F(IndexTest, testSearchSnapsSignsCall) |
1191 | +{ |
1192 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1193 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1194 | + |
1195 | + EXPECT_CALL(*clientPtr, callImpl(_, _, true, _, _, _)) |
1196 | + .Times(1) |
1197 | + .WillOnce(Return(response)); |
1198 | + |
1199 | + indexPtr->search_snaps("", [](click::Packages, click::Packages) {}); |
1200 | +} |
1201 | + |
1202 | +TEST_F(IndexTest, testSearchSnapsIsCancellable) |
1203 | +{ |
1204 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1205 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1206 | + |
1207 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1208 | + .Times(1) |
1209 | + .WillOnce(Return(response)); |
1210 | + |
1211 | + auto search_operation = indexPtr->search_snaps("", [](click::Packages, |
1212 | + click::Packages) {}); |
1213 | + EXPECT_CALL(reply.instance, abort()).Times(1); |
1214 | + search_operation.cancel(); |
1215 | +} |
1216 | + |
1217 | +TEST_F(IndexTest, testSearchSnapsEmptyJsonIsParsed) |
1218 | +{ |
1219 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1220 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1221 | + |
1222 | + QByteArray fake_json("[]"); |
1223 | + EXPECT_CALL(reply.instance, readAll()) |
1224 | + .Times(1) |
1225 | + .WillOnce(Return(fake_json)); |
1226 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1227 | + .Times(1) |
1228 | + .WillOnce(Return(response)); |
1229 | + click::Packages empty_package_list; |
1230 | + EXPECT_CALL(*this, search_callback(empty_package_list, _)).Times(1); |
1231 | + |
1232 | + indexPtr->search_snaps("", [this](click::Packages packages, |
1233 | + click::Packages recommends){ |
1234 | + search_callback(packages, recommends); |
1235 | + }); |
1236 | + response->replyFinished(); |
1237 | +} |
1238 | + |
1239 | +TEST_F(IndexTest, testSearchSnapsNetworkErrorIgnored) |
1240 | +{ |
1241 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1242 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1243 | + |
1244 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1245 | + .Times(1) |
1246 | + .WillOnce(Return(response)); |
1247 | + EXPECT_CALL(reply.instance, errorString()).Times(1) |
1248 | + .WillOnce(Return("fake error")); |
1249 | + indexPtr->search_snaps("", [this](click::Packages packages, |
1250 | + click::Packages recommends){ |
1251 | + search_callback(packages, recommends); |
1252 | + }); |
1253 | + |
1254 | + click::Packages empty_package_list; |
1255 | + EXPECT_CALL(*this, search_callback(empty_package_list, _)).Times(1); |
1256 | + |
1257 | + emit reply.instance.error(QNetworkReply::UnknownNetworkError); |
1258 | +} |
1259 | + |
1260 | TEST_F(IndexTest, testBootstrapSignsCall) |
1261 | { |
1262 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1263 | - auto response = responseForReply(reply.asSharedPtr()); |
1264 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1265 | |
1266 | - EXPECT_CALL(*configPtr, get_architecture()) |
1267 | - .Times(1) |
1268 | - .WillOnce(Return(fake_arch)); |
1269 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1270 | - .Times(1) |
1271 | - .WillOnce(Return(fake_frameworks)); |
1272 | EXPECT_CALL(*clientPtr, callImpl(_, _, true, _, _, _)) |
1273 | .Times(1) |
1274 | .WillOnce(Return(response)); |
1275 | @@ -175,14 +271,8 @@ |
1276 | TEST_F(IndexTest, testDepartmentsSignsCall) |
1277 | { |
1278 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1279 | - auto response = responseForReply(reply.asSharedPtr()); |
1280 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1281 | |
1282 | - EXPECT_CALL(*configPtr, get_architecture()) |
1283 | - .Times(1) |
1284 | - .WillOnce(Return(fake_arch)); |
1285 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1286 | - .Times(1) |
1287 | - .WillOnce(Return(fake_frameworks)); |
1288 | EXPECT_CALL(*clientPtr, callImpl(_, _, true, _, _, _)) |
1289 | .Times(1) |
1290 | .WillOnce(Return(response)); |
1291 | @@ -193,7 +283,7 @@ |
1292 | TEST_F(IndexTest, testDetailsSignsCall) |
1293 | { |
1294 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1295 | - auto response = responseForReply(reply.asSharedPtr()); |
1296 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1297 | |
1298 | EXPECT_CALL(*clientPtr, callImpl(_, _, true, _, _, _)) |
1299 | .Times(1) |
1300 | @@ -205,14 +295,8 @@ |
1301 | TEST_F(IndexTest, testSearchSendsRightPath) |
1302 | { |
1303 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1304 | - auto response = responseForReply(reply.asSharedPtr()); |
1305 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1306 | |
1307 | - EXPECT_CALL(*configPtr, get_architecture()) |
1308 | - .Times(1) |
1309 | - .WillOnce(Return(fake_arch)); |
1310 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1311 | - .Times(1) |
1312 | - .WillOnce(Return(fake_frameworks)); |
1313 | EXPECT_CALL(*clientPtr, callImpl(EndsWith(click::SEARCH_PATH), |
1314 | _, _, _, _, _)) |
1315 | .Times(1) |
1316 | @@ -224,18 +308,12 @@ |
1317 | TEST_F(IndexTest, testSearchCallbackIsCalled) |
1318 | { |
1319 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1320 | - auto response = responseForReply(reply.asSharedPtr()); |
1321 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1322 | |
1323 | QByteArray fake_json("[]"); |
1324 | EXPECT_CALL(reply.instance, readAll()) |
1325 | .Times(1) |
1326 | .WillOnce(Return(fake_json)); |
1327 | - EXPECT_CALL(*configPtr, get_architecture()) |
1328 | - .Times(1) |
1329 | - .WillOnce(Return(fake_arch)); |
1330 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1331 | - .Times(1) |
1332 | - .WillOnce(Return(fake_frameworks)); |
1333 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1334 | .Times(1) |
1335 | .WillOnce(Return(response)); |
1336 | @@ -251,18 +329,12 @@ |
1337 | TEST_F(IndexTest, testSearchEmptyJsonIsParsed) |
1338 | { |
1339 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1340 | - auto response = responseForReply(reply.asSharedPtr()); |
1341 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1342 | |
1343 | QByteArray fake_json("[]"); |
1344 | EXPECT_CALL(reply.instance, readAll()) |
1345 | .Times(1) |
1346 | .WillOnce(Return(fake_json)); |
1347 | - EXPECT_CALL(*configPtr, get_architecture()) |
1348 | - .Times(1) |
1349 | - .WillOnce(Return(fake_arch)); |
1350 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1351 | - .Times(1) |
1352 | - .WillOnce(Return(fake_frameworks)); |
1353 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1354 | .Times(1) |
1355 | .WillOnce(Return(response)); |
1356 | @@ -279,18 +351,12 @@ |
1357 | TEST_F(IndexTest, testSearchSingleJsonIsParsed) |
1358 | { |
1359 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1360 | - auto response = responseForReply(reply.asSharedPtr()); |
1361 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1362 | |
1363 | QByteArray fake_json(FAKE_JSON_SEARCH_RESULT_ONE.c_str()); |
1364 | EXPECT_CALL(reply.instance, readAll()) |
1365 | .Times(1) |
1366 | .WillOnce(Return(fake_json)); |
1367 | - EXPECT_CALL(*configPtr, get_architecture()) |
1368 | - .Times(1) |
1369 | - .WillOnce(Return(fake_arch)); |
1370 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1371 | - .Times(1) |
1372 | - .WillOnce(Return(fake_frameworks)); |
1373 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1374 | .Times(1) |
1375 | .WillOnce(Return(response)); |
1376 | @@ -315,14 +381,8 @@ |
1377 | TEST_F(IndexTest, testSearchIsCancellable) |
1378 | { |
1379 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1380 | - auto response = responseForReply(reply.asSharedPtr()); |
1381 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1382 | |
1383 | - EXPECT_CALL(*configPtr, get_architecture()) |
1384 | - .Times(1) |
1385 | - .WillOnce(Return(fake_arch)); |
1386 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1387 | - .Times(1) |
1388 | - .WillOnce(Return(fake_frameworks)); |
1389 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1390 | .Times(1) |
1391 | .WillOnce(Return(response)); |
1392 | @@ -341,14 +401,8 @@ |
1393 | TEST_F(IndexTest, testSearchNetworkErrorIgnored) |
1394 | { |
1395 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1396 | - auto response = responseForReply(reply.asSharedPtr()); |
1397 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1398 | |
1399 | - EXPECT_CALL(*configPtr, get_architecture()) |
1400 | - .Times(1) |
1401 | - .WillOnce(Return(fake_arch)); |
1402 | - EXPECT_CALL(*configPtr, get_available_frameworks()) |
1403 | - .Times(1) |
1404 | - .WillOnce(Return(fake_frameworks)); |
1405 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1406 | .Times(1) |
1407 | .WillOnce(Return(response)); |
1408 | @@ -367,7 +421,7 @@ |
1409 | TEST_F(IndexTest, testGetDetailsCallsWebservice) |
1410 | { |
1411 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1412 | - auto response = responseForReply(reply.asSharedPtr()); |
1413 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1414 | |
1415 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1416 | .Times(1) |
1417 | @@ -379,7 +433,7 @@ |
1418 | TEST_F(IndexTest, testGetDetailsSendsPackagename) |
1419 | { |
1420 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1421 | - auto response = responseForReply(reply.asSharedPtr()); |
1422 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1423 | |
1424 | EXPECT_CALL(*clientPtr, callImpl(EndsWith(FAKE_PACKAGENAME), |
1425 | _, _, _, _, _)) |
1426 | @@ -392,7 +446,7 @@ |
1427 | TEST_F(IndexTest, testGetDetailsSendsRightPath) |
1428 | { |
1429 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1430 | - auto response = responseForReply(reply.asSharedPtr()); |
1431 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1432 | |
1433 | EXPECT_CALL(*clientPtr, callImpl(StartsWith(click::SEARCH_BASE_URL + |
1434 | click::DETAILS_PATH), |
1435 | @@ -406,7 +460,7 @@ |
1436 | TEST_F(IndexTest, testGetDetailsCallbackIsCalled) |
1437 | { |
1438 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1439 | - auto response = responseForReply(reply.asSharedPtr()); |
1440 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1441 | |
1442 | QByteArray fake_json(FAKE_JSON_PACKAGE_DETAILS.c_str()); |
1443 | EXPECT_CALL(reply.instance, readAll()) |
1444 | @@ -425,7 +479,7 @@ |
1445 | TEST_F(IndexTest, testGetDetailsJsonIsParsed) |
1446 | { |
1447 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1448 | - auto response = responseForReply(reply.asSharedPtr()); |
1449 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1450 | |
1451 | QByteArray fake_json(FAKE_JSON_PACKAGE_DETAILS.c_str()); |
1452 | EXPECT_CALL(reply.instance, readAll()) |
1453 | @@ -486,7 +540,7 @@ |
1454 | TEST_F(IndexTest, testGetDetailsJsonUtf8) |
1455 | { |
1456 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1457 | - auto response = responseForReply(reply.asSharedPtr()); |
1458 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1459 | |
1460 | QByteArray appname_utf8("\xe5\xb0\x8f\xe6\xb5\xb7"); |
1461 | QByteArray appname_json("\\u5c0f\\u6d77"); |
1462 | @@ -554,7 +608,7 @@ |
1463 | TEST_F(IndexTest, testGetDetailsNetworkErrorReported) |
1464 | { |
1465 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1466 | - auto response = responseForReply(reply.asSharedPtr()); |
1467 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1468 | |
1469 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1470 | .Times(1) |
1471 | @@ -571,7 +625,7 @@ |
1472 | TEST_F(IndexTest, testGetDetailsIsCancellable) |
1473 | { |
1474 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1475 | - auto response = responseForReply(reply.asSharedPtr()); |
1476 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1477 | |
1478 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1479 | .Times(1) |
1480 | @@ -582,7 +636,7 @@ |
1481 | get_details_operation.cancel(); |
1482 | } |
1483 | |
1484 | -TEST_F(IndexTest, testGetBaseUrl) |
1485 | +TEST_F(SimpleIndexTest, testGetBaseUrl) |
1486 | { |
1487 | const char *value = getenv(click::SEARCH_BASE_URL_ENVVAR.c_str()); |
1488 | if (value != NULL) { |
1489 | @@ -592,7 +646,7 @@ |
1490 | |
1491 | } |
1492 | |
1493 | -TEST_F(IndexTest, testGetBaseUrlFromEnv) |
1494 | +TEST_F(SimpleIndexTest, testGetBaseUrlFromEnv) |
1495 | { |
1496 | ASSERT_TRUE(setenv(click::SEARCH_BASE_URL_ENVVAR.c_str(), |
1497 | FAKE_SERVER.c_str(), 1) == 0); |
1498 | @@ -600,14 +654,14 @@ |
1499 | ASSERT_TRUE(unsetenv(click::SEARCH_BASE_URL_ENVVAR.c_str()) == 0); |
1500 | } |
1501 | |
1502 | -TEST_F(IndexTest, testPackageListsFromJsonNodeNoRecommends) |
1503 | +TEST_F(SimpleIndexTest, testPackageListsFromJsonNodeNoRecommends) |
1504 | { |
1505 | auto lists = indexPtr->package_lists_from_json(FAKE_JSON_SEARCH_RESULT_ONE); |
1506 | EXPECT_EQ(1, lists.first.size()); |
1507 | EXPECT_EQ(0, lists.second.size()); |
1508 | } |
1509 | |
1510 | -TEST_F(IndexTest, testPackageListsFromJsonNodeHasRecommends) |
1511 | +TEST_F(SimpleIndexTest, testPackageListsFromJsonNodeHasRecommends) |
1512 | { |
1513 | auto lists = indexPtr->package_lists_from_json(FAKE_JSON_SEARCH_RESULT_RECOMMENDS); |
1514 | EXPECT_EQ(1, lists.second.size()); |
1515 | @@ -668,3 +722,15 @@ |
1516 | EXPECT_NE(std::string::npos, hdrs["X-Ubuntu-Frameworks"].find(fake_fwk_1)); |
1517 | EXPECT_NE(std::string::npos, hdrs["X-Ubuntu-Frameworks"].find(fake_fwk_2)); |
1518 | } |
1519 | + |
1520 | +TEST_F(QueryStringTest, testBuildHeadersFrameworksEmpty) |
1521 | +{ |
1522 | + EXPECT_CALL(*configPtr, get_architecture()).Times(1).WillOnce(Return(fake_arch)); |
1523 | + EXPECT_CALL(*configPtr, get_available_frameworks()) |
1524 | + .Times(1) |
1525 | + .WillOnce(Return(std::vector<std::string>{})); |
1526 | + auto hdrs = indexPtr->build_headers(); |
1527 | + EXPECT_EQ(std::string::npos, hdrs["X-Ubuntu-Frameworks"].find(fake_fwk_1)); |
1528 | + EXPECT_EQ(std::string::npos, hdrs["X-Ubuntu-Frameworks"].find(fake_fwk_2)); |
1529 | + ASSERT_NE(std::string::npos, hdrs["X-Ubuntu-Frameworks"].find("none")); |
1530 | +} |
1531 | |
1532 | === modified file 'libclickscope/tests/test_pay.cpp' |
1533 | --- libclickscope/tests/test_pay.cpp 2016-06-30 20:42:56 +0000 |
1534 | +++ libclickscope/tests/test_pay.cpp 2016-09-21 14:55:05 +0000 |
1535 | @@ -68,7 +68,7 @@ |
1536 | TEST_F(PayTest, testPayPackageRefundCalled) |
1537 | { |
1538 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1539 | - auto response = responseForReply(reply.asSharedPtr()); |
1540 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1541 | |
1542 | EXPECT_CALL(*package, do_pay_package_refund("foo")).Times(1); |
1543 | EXPECT_FALSE(package->refund("foo")); |
1544 | @@ -77,7 +77,7 @@ |
1545 | TEST_F(PayTest, testPayPackageRefundNotCalledIfCallbackExists) |
1546 | { |
1547 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1548 | - auto response = responseForReply(reply.asSharedPtr()); |
1549 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1550 | |
1551 | std::string callback_id = std::string{"foo"} + pay::APPENDAGE_REFUND; |
1552 | package->callbacks[callback_id] = [](const std::string&, bool) {}; |
1553 | @@ -88,7 +88,7 @@ |
1554 | TEST_F(PayTest, testRefundReturnsTrueForPurchasedItem) |
1555 | { |
1556 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1557 | - auto response = responseForReply(reply.asSharedPtr()); |
1558 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1559 | |
1560 | package->success = true; |
1561 | EXPECT_CALL(*package, do_pay_package_refund("foo")).Times(1); |
1562 | @@ -98,7 +98,7 @@ |
1563 | TEST_F(PayTest, testPayPackageVerifyCalled) |
1564 | { |
1565 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1566 | - auto response = responseForReply(reply.asSharedPtr()); |
1567 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1568 | |
1569 | EXPECT_CALL(*package, do_pay_package_verify("foo")).Times(1); |
1570 | EXPECT_FALSE(package->verify("foo")); |
1571 | @@ -107,7 +107,7 @@ |
1572 | TEST_F(PayTest, testPayPackageVerifyNotCalledIfCallbackExists) |
1573 | { |
1574 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1575 | - auto response = responseForReply(reply.asSharedPtr()); |
1576 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1577 | |
1578 | std::string callback_id = std::string{"foo"} + pay::APPENDAGE_VERIFY; |
1579 | package->callbacks[callback_id] = [](const std::string&, bool) {}; |
1580 | @@ -118,7 +118,7 @@ |
1581 | TEST_F(PayTest, testVerifyReturnsTrueForPurchasedItem) |
1582 | { |
1583 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1584 | - auto response = responseForReply(reply.asSharedPtr()); |
1585 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1586 | |
1587 | package->success = true; |
1588 | EXPECT_CALL(*package, do_pay_package_verify("foo")).Times(1); |
1589 | @@ -128,7 +128,7 @@ |
1590 | TEST_F(PayTest, testGetPurchasesCallsWebservice) |
1591 | { |
1592 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1593 | - auto response = responseForReply(reply.asSharedPtr()); |
1594 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1595 | |
1596 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1597 | .Times(1) |
1598 | @@ -140,7 +140,7 @@ |
1599 | TEST_F(PayTest, testGetPurchasesSendsCorrectPath) |
1600 | { |
1601 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1602 | - auto response = responseForReply(reply.asSharedPtr()); |
1603 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1604 | |
1605 | EXPECT_CALL(*clientPtr, callImpl(EndsWith(pay::PURCHASES_API_PATH), |
1606 | _, _, _, _, _)) |
1607 | @@ -153,7 +153,7 @@ |
1608 | TEST_F(PayTest, testGetPurchasesCallbackCalled) |
1609 | { |
1610 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1611 | - auto response = responseForReply(reply.asSharedPtr()); |
1612 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1613 | |
1614 | QByteArray fake_json("[]"); |
1615 | EXPECT_CALL(reply.instance, readAll()) |
1616 | @@ -173,7 +173,7 @@ |
1617 | TEST_F(PayTest, testGetPurchasesEmptyJsonIsParsed) |
1618 | { |
1619 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1620 | - auto response = responseForReply(reply.asSharedPtr()); |
1621 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1622 | |
1623 | QByteArray fake_json("[]"); |
1624 | EXPECT_CALL(reply.instance, readAll()) |
1625 | @@ -194,7 +194,7 @@ |
1626 | TEST_F(PayTest, testGetPurchasesSingleJsonIsParsedNullTimestamp) |
1627 | { |
1628 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1629 | - auto response = responseForReply(reply.asSharedPtr()); |
1630 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1631 | |
1632 | QByteArray fake_json(FAKE_PURCHASES_LIST_JSON_NULL_TIMESTAMP); |
1633 | EXPECT_CALL(reply.instance, readAll()) |
1634 | @@ -215,7 +215,7 @@ |
1635 | TEST_F(PayTest, testGetPurchasesTimestampIsParsed) |
1636 | { |
1637 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1638 | - auto response = responseForReply(reply.asSharedPtr()); |
1639 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1640 | |
1641 | QByteArray fake_json(FAKE_PURCHASES_LIST_JSON); |
1642 | EXPECT_CALL(reply.instance, readAll()) |
1643 | @@ -237,7 +237,7 @@ |
1644 | TEST_F(PayTest, testGetPurchasesIsCancellable) |
1645 | { |
1646 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1647 | - auto response = responseForReply(reply.asSharedPtr()); |
1648 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1649 | |
1650 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1651 | .Times(1) |
1652 | |
1653 | === modified file 'libclickscope/tests/test_preview.cpp' |
1654 | --- libclickscope/tests/test_preview.cpp 2016-07-13 20:30:09 +0000 |
1655 | +++ libclickscope/tests/test_preview.cpp 2016-09-21 14:55:05 +0000 |
1656 | @@ -1,5 +1,5 @@ |
1657 | /* |
1658 | - * Copyright (C) 2014 Canonical Ltd. |
1659 | + * Copyright (C) 2014-2016 Canonical Ltd. |
1660 | * |
1661 | * This program is free software: you can redistribute it and/or modify it |
1662 | * under the terms of the GNU General Public License version 3, as published |
1663 | @@ -64,7 +64,7 @@ |
1664 | FakeIndex() { |
1665 | |
1666 | } |
1667 | - click::web::Cancellable get_details(const std::string& /*package_name*/, std::function<void(click::PackageDetails, Error)> callback, bool) override { |
1668 | + click::web::Cancellable get_details(const std::string& /*package_name*/, std::function<void(click::PackageDetails, Error)> callback, bool, bool) override { |
1669 | callback(click::PackageDetails(), Error::NetworkError); |
1670 | return click::web::Cancellable(); |
1671 | } |
1672 | |
1673 | === modified file 'libclickscope/tests/test_reviews.cpp' |
1674 | --- libclickscope/tests/test_reviews.cpp 2016-05-10 13:42:12 +0000 |
1675 | +++ libclickscope/tests/test_reviews.cpp 2016-09-21 14:55:05 +0000 |
1676 | @@ -140,7 +140,7 @@ |
1677 | TEST_F(ReviewsTest, testFetchReviewsCallsWebservice) |
1678 | { |
1679 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1680 | - auto response = responseForReply(reply.asSharedPtr()); |
1681 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1682 | |
1683 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1684 | .Times(1) |
1685 | @@ -153,7 +153,7 @@ |
1686 | TEST_F(ReviewsTest, testFetchReviewsDoesNotSignCall) |
1687 | { |
1688 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1689 | - auto response = responseForReply(reply.asSharedPtr()); |
1690 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1691 | |
1692 | EXPECT_CALL(*clientPtr, callImpl(_, _, false, _, _, _)) |
1693 | .Times(1) |
1694 | @@ -166,7 +166,7 @@ |
1695 | TEST_F(ReviewsTest, testFetchReviewsSendsQueryAsParam) |
1696 | { |
1697 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1698 | - auto response = responseForReply(reply.asSharedPtr()); |
1699 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1700 | |
1701 | click::web::CallParams params; |
1702 | params.add(click::REVIEWS_QUERY_ARGNAME, FAKE_PACKAGENAME); |
1703 | @@ -181,7 +181,7 @@ |
1704 | TEST_F(ReviewsTest, testFetchReviewsSendsCorrectPath) |
1705 | { |
1706 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1707 | - auto response = responseForReply(reply.asSharedPtr()); |
1708 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1709 | |
1710 | EXPECT_CALL(*clientPtr, callImpl(EndsWith(click::REVIEWS_API_PATH), |
1711 | _, _, _, _, _)) |
1712 | @@ -195,7 +195,7 @@ |
1713 | TEST_F(ReviewsTest, testFetchReviewsCallbackCalled) |
1714 | { |
1715 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1716 | - auto response = responseForReply(reply.asSharedPtr()); |
1717 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1718 | |
1719 | QByteArray fake_json("[]"); |
1720 | EXPECT_CALL(reply.instance, readAll()) |
1721 | @@ -216,7 +216,7 @@ |
1722 | TEST_F(ReviewsTest, testFetchReviewsNot200) |
1723 | { |
1724 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1725 | - auto response = responseForReply(reply.asSharedPtr()); |
1726 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1727 | |
1728 | EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(301))); |
1729 | EXPECT_CALL(reply.instance, readAll()) |
1730 | @@ -238,7 +238,7 @@ |
1731 | TEST_F(ReviewsTest, testFetchReviewsEmptyJsonIsParsed) |
1732 | { |
1733 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1734 | - auto response = responseForReply(reply.asSharedPtr()); |
1735 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1736 | |
1737 | QByteArray fake_json("[]"); |
1738 | EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(200))); |
1739 | @@ -261,7 +261,7 @@ |
1740 | TEST_F(ReviewsTest, testFetchReviewsSingleJsonIsParsed) |
1741 | { |
1742 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1743 | - auto response = responseForReply(reply.asSharedPtr()); |
1744 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1745 | |
1746 | QByteArray fake_json(FAKE_JSON_REVIEWS_RESULT_ONE.c_str()); |
1747 | EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(200))); |
1748 | @@ -295,7 +295,7 @@ |
1749 | TEST_F(ReviewsTest, testFetchReviewsNetworkErrorReported) |
1750 | { |
1751 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1752 | - auto response = responseForReply(reply.asSharedPtr()); |
1753 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1754 | |
1755 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1756 | .Times(1) |
1757 | @@ -318,7 +318,7 @@ |
1758 | TEST_F(ReviewsTest, testFetchReviewsIsCancellable) |
1759 | { |
1760 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1761 | - auto response = responseForReply(reply.asSharedPtr()); |
1762 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1763 | |
1764 | EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1765 | .Times(1) |
1766 | @@ -333,7 +333,7 @@ |
1767 | TEST_F(ReviewsTest, testSubmitReviewIsCancellable) |
1768 | { |
1769 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1770 | - auto response = responseForReply(reply.asSharedPtr()); |
1771 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1772 | |
1773 | click::Review review; |
1774 | review.rating = 3; |
1775 | @@ -354,7 +354,7 @@ |
1776 | TEST_F(ReviewsTest, testSubmitReviewUtf8) |
1777 | { |
1778 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1779 | - auto response = responseForReply(reply.asSharedPtr()); |
1780 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1781 | |
1782 | click::Review review; |
1783 | review.rating = 3; |
1784 | @@ -378,7 +378,7 @@ |
1785 | TEST_F(ReviewsTest, testSubmitReviewLanguageCorrect) |
1786 | { |
1787 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1788 | - auto response = responseForReply(reply.asSharedPtr()); |
1789 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1790 | |
1791 | click::Review review; |
1792 | review.rating = 3; |
1793 | @@ -402,7 +402,7 @@ |
1794 | TEST_F(ReviewsTest, testSubmitReviewLanguageCorrectForFullLangCodes) |
1795 | { |
1796 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1797 | - auto response = responseForReply(reply.asSharedPtr()); |
1798 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1799 | |
1800 | click::Review review; |
1801 | review.rating = 3; |
1802 | @@ -428,7 +428,7 @@ |
1803 | TEST_F(ReviewsTest, testEditReviewUrlHasReviewId) |
1804 | { |
1805 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1806 | - auto response = responseForReply(reply.asSharedPtr()); |
1807 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1808 | |
1809 | click::Review review; |
1810 | review.id = 1234; |
1811 | @@ -448,7 +448,7 @@ |
1812 | TEST_F(ReviewsTest, testEditReviewIsCancellable) |
1813 | { |
1814 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1815 | - auto response = responseForReply(reply.asSharedPtr()); |
1816 | + auto response = MockClient::responseForReply(reply.asSharedPtr()); |
1817 | |
1818 | click::Review review; |
1819 | review.id = 1234; |
1820 | |
1821 | === modified file 'scope/clickstore/store-query.cpp' |
1822 | --- scope/clickstore/store-query.cpp 2016-09-21 14:55:05 +0000 |
1823 | +++ scope/clickstore/store-query.cpp 2016-09-21 14:55:05 +0000 |
1824 | @@ -169,6 +169,7 @@ |
1825 | click::HighlightList& highlights; |
1826 | scopes::SearchMetadata meta; |
1827 | click::web::Cancellable search_operation; |
1828 | + click::web::Cancellable search_snaps_operation; |
1829 | click::web::Cancellable purchases_operation; |
1830 | pay::Package& pay_package; |
1831 | std::shared_future<void> qt_ready_; |
1832 | @@ -196,6 +197,7 @@ |
1833 | { |
1834 | qDebug() << "cancelling search of" << QString::fromStdString(query().query_string()); |
1835 | impl->search_operation.cancel(); |
1836 | + impl->search_snaps_operation.cancel(); |
1837 | } |
1838 | |
1839 | click::Interface& click::Query::clickInterfaceInstance() |
1840 | @@ -290,7 +292,12 @@ |
1841 | res.set_title(pkg.title); |
1842 | res.set_art(pkg.icon_url); |
1843 | res.set_uri(pkg.url); |
1844 | - res[click::Query::ResultKeys::NAME] = pkg.name; |
1845 | + res["snap_id"] = pkg.snap_id; |
1846 | + if (pkg.snap_id.empty()) { |
1847 | + res[click::Query::ResultKeys::NAME] = pkg.name; |
1848 | + } else { |
1849 | + res[click::Query::ResultKeys::NAME] = pkg.alias; |
1850 | + } |
1851 | res["subtitle"] = pkg.publisher; |
1852 | auto installed = installedPackages.find(pkg); |
1853 | |
1854 | @@ -533,6 +540,7 @@ |
1855 | push_package(searchReply, recommendsCategory, |
1856 | installedPackages, r); |
1857 | } |
1858 | + |
1859 | qDebug() << "search completed"; |
1860 | this->finished(searchReply); //FIXME: this shouldn't be needed |
1861 | }; |
1862 | @@ -596,7 +604,37 @@ |
1863 | { |
1864 | qDebug() << "starting search of" << QString::fromStdString(query().query_string()); |
1865 | push_departments(searchReply); |
1866 | - impl->search_operation = impl->index.search(query().query_string(), query().department_id(), search_cb, force_cache); |
1867 | + impl->search_operation = impl->index.search |
1868 | + (query().query_string(), query().department_id(), |
1869 | + [this, search_cb, force_cache](Packages packages, |
1870 | + Packages recommends) { |
1871 | + if (Configuration().is_snapd_running()) { |
1872 | + qDebug() << "Searching for snaps too."; |
1873 | + impl->search_snaps_operation = impl->index.search_snaps |
1874 | + (query().query_string(), |
1875 | + [this, packages, recommends, search_cb](Packages snap_packages, |
1876 | + Packages snap_recommends) { |
1877 | + qDebug() << "In the callback."; |
1878 | + Packages new_packages, new_recommends; |
1879 | + for (const auto& p: packages) { |
1880 | + new_packages.push_back(p); |
1881 | + } |
1882 | + for (const auto& p: snap_packages) { |
1883 | + new_packages.push_back(p); |
1884 | + } |
1885 | + for (const auto& r: recommends) { |
1886 | + new_recommends.push_back(r); |
1887 | + } |
1888 | + for (const auto& r: snap_recommends) { |
1889 | + new_recommends.push_back(r); |
1890 | + } |
1891 | + qDebug() << "Snaps appended."; |
1892 | + search_cb(new_packages, new_recommends); |
1893 | + }, force_cache); |
1894 | + } else { |
1895 | + search_cb(packages, recommends); |
1896 | + } |
1897 | + }, force_cache); |
1898 | } |
1899 | } |
1900 | }); |
PASSED: Continuous integration, rev:496 /jenkins. canonical. com/unity- api-1/job/ lp-unity- scope-click- ci/86/ /jenkins. canonical. com/unity- api-1/job/ build/470 /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/476 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= vivid+overlay/ 381 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= xenial+ overlay/ 381 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= yakkety/ 381 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 311 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 311/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 311 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 311/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 311 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 311/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 311 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 311/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 311 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 311/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 311 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 311/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 311 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 311/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 311 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 311/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 311 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 311/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-unity- scope-click- ci/86/rebuild
https:/