Merge lp:~dobey/unity-scope-click/snap-socketry into lp:unity-scope-click
- snap-socketry
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | dobey |
Proposed branch: | lp:~dobey/unity-scope-click/snap-socketry |
Merge into: | lp:unity-scope-click |
Prerequisite: | lp:~dobey/unity-scope-click/clicksnap |
Diff against target: |
1214 lines (+636/-75) 23 files modified
debian/control (+1/-0) libclickscope/click/CMakeLists.txt (+2/-0) libclickscope/click/index.cpp (+7/-3) libclickscope/click/index.h (+4/-2) libclickscope/click/interface.cpp (+1/-0) libclickscope/click/interface.h (+1/-25) libclickscope/click/manifest.h (+65/-0) libclickscope/click/package.cpp (+4/-1) libclickscope/click/package.h (+1/-1) libclickscope/click/preview.cpp (+9/-2) libclickscope/click/preview.h (+5/-1) libclickscope/click/snapd.cpp (+171/-0) libclickscope/click/snapd.h (+61/-0) libclickscope/tests/CMakeLists.txt (+1/-0) libclickscope/tests/mock_configuration.h (+48/-0) libclickscope/tests/mock_snapd.h (+89/-0) libclickscope/tests/test_index.cpp (+11/-9) libclickscope/tests/test_interface.cpp (+6/-0) libclickscope/tests/test_preview.cpp (+25/-15) libclickscope/tests/test_snapd.cpp (+84/-0) scope/clickstore/store-query.cpp (+27/-8) scope/clickstore/store-query.h (+3/-1) scope/tests/test_query.cpp (+10/-7) |
To merge this branch: | bzr merge lp:~dobey/unity-scope-click/snap-socketry |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
unity-api-1-bot | continuous-integration | Approve | |
Charles Kerr (community) | Approve | ||
Review via email: mp+304420@code.launchpad.net |
Commit message
Add code to get some info from snapd using a boost::asio socket.
Add a dependency on libboost-system-dev for asio.
Move the Manifest struct to its own header, to avoid circular includes.
Description of the change
unity-api-1-bot (unity-api-1-bot) wrote : | # |
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:502
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:503
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:504
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:504
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Charles Kerr (charlesk) wrote : | # |
Looks pretty good.
Included some suggestions and trolling below, but all optional. Feel free to use the suggestions or merge as-is
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:/
Unmerged revisions
- 507. By dobey
-
Get the first app for the snap in the manifest.
- 506. By dobey
-
Take const references in Manifest constructor.
- 505. By dobey
-
Merge clicksnap changes.
- 504. By dobey
-
Some final workarounds to deal with differences between clicks and snaps.
- 503. By dobey
-
Need to pass in configuration and snapd objects to InstalledPreview.
- 502. By dobey
-
Only hit bootstrap and search for clicks if frameworks are available.
Only search snaps if no frameworks and snapd is running. - 501. By dobey
-
Refactor the MockConfiguration out to a separate header.
- 500. By dobey
-
Add code to get some info from snapd using a boost::asio socket.
Add a dependency on libboost-system-dev for asio. - 499. By dobey
-
Move the Manifest struct to its own header, to avoid circular includes.
- 498. By dobey
-
Update dependencies to allow either snaps or clicks to be supported.
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2016-09-21 18:03:39 +0000 |
3 | +++ debian/control 2016-09-21 18:03:39 +0000 |
4 | @@ -11,6 +11,7 @@ |
5 | intltool, |
6 | lcov, |
7 | libboost-locale-dev, |
8 | + libboost-system-dev, |
9 | libclick-0.4-dev, |
10 | libglib2.0-dev (>= 2.32), |
11 | libjsoncpp-dev, |
12 | |
13 | === modified file 'libclickscope/click/CMakeLists.txt' |
14 | --- libclickscope/click/CMakeLists.txt 2016-09-21 18:03:39 +0000 |
15 | +++ libclickscope/click/CMakeLists.txt 2016-09-21 18:03:39 +0000 |
16 | @@ -31,6 +31,7 @@ |
17 | qtbridge.cpp |
18 | scope_activation.cpp |
19 | smartconnect.cpp |
20 | + snapd.cpp |
21 | ubuntuone_credentials.cpp |
22 | utils.cpp |
23 | webclient.cpp |
24 | @@ -58,4 +59,5 @@ |
25 | ${UAL_LDFLAGS} |
26 | ${CLICK_LDFLAGS} |
27 | -lboost_locale |
28 | + -lboost_system |
29 | ) |
30 | |
31 | === modified file 'libclickscope/click/index.cpp' |
32 | --- libclickscope/click/index.cpp 2016-09-21 18:03:39 +0000 |
33 | +++ libclickscope/click/index.cpp 2016-09-21 18:03:39 +0000 |
34 | @@ -40,6 +40,7 @@ |
35 | #include "index.h" |
36 | #include "interface.h" |
37 | #include "application.h" |
38 | +#include "snapd.h" |
39 | |
40 | namespace json = Json; |
41 | |
42 | @@ -89,8 +90,11 @@ |
43 | |
44 | |
45 | Index::Index(const QSharedPointer<click::web::Client>& client, |
46 | - const QSharedPointer<Configuration> configuration) : |
47 | - client(client), configuration(configuration) |
48 | + const QSharedPointer<Configuration> configuration, |
49 | + const std::shared_ptr<click::Snapd>& snapd) |
50 | + : client(client), |
51 | + configuration(configuration), |
52 | + snapd(snapd) |
53 | { |
54 | |
55 | } |
56 | @@ -126,7 +130,7 @@ |
57 | std::map<std::string, std::string> Index::add_snap_headers(const std::map<std::string, std::string>& headers) const |
58 | { |
59 | std::map<std::string, std::string> new_headers{headers}; |
60 | - new_headers["X-Ubuntu-Series"] = "16"; // Need to get from snapd |
61 | + new_headers["X-Ubuntu-Series"] = snapd->get_series(); |
62 | new_headers["X-Ubuntu-Slots"] = "unity8"; // Only want unity8-using snaps |
63 | |
64 | return new_headers; |
65 | |
66 | === modified file 'libclickscope/click/index.h' |
67 | --- libclickscope/click/index.h 2016-09-21 18:03:39 +0000 |
68 | +++ libclickscope/click/index.h 2016-09-21 18:03:39 +0000 |
69 | @@ -38,10 +38,10 @@ |
70 | #include <click/webclient.h> |
71 | |
72 | #include "package.h" |
73 | +#include "snapd.h" |
74 | #include <click/departments.h> |
75 | #include <click/highlights.h> |
76 | |
77 | - |
78 | namespace click { |
79 | |
80 | class Configuration; |
81 | @@ -71,6 +71,7 @@ |
82 | protected: |
83 | QSharedPointer<web::Client> client; |
84 | QSharedPointer<Configuration> configuration; |
85 | + std::shared_ptr<click::Snapd> snapd; |
86 | std::string m_suggested_currency; |
87 | virtual std::string build_index_query(const std::string& query, const std::string& department); |
88 | virtual std::map<std::string, std::string> build_headers(); |
89 | @@ -80,7 +81,8 @@ |
90 | enum class Error {NoError, CredentialsError, NetworkError}; |
91 | Index() {} |
92 | Index(const QSharedPointer<click::web::Client>& client, |
93 | - const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration())); |
94 | + const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration()), |
95 | + const std::shared_ptr<click::Snapd>& snapd = std::shared_ptr<click::Snapd>(new click::Snapd())); |
96 | virtual std::pair<Packages, Packages> package_lists_from_json(const std::string& json); |
97 | virtual click::web::Cancellable search_snaps(const std::string& query, |
98 | std::function<void(click::Packages search_results, click::Packages recommendations)> callback, |
99 | |
100 | === modified file 'libclickscope/click/interface.cpp' |
101 | --- libclickscope/click/interface.cpp 2016-09-21 18:03:39 +0000 |
102 | +++ libclickscope/click/interface.cpp 2016-09-21 18:03:39 +0000 |
103 | @@ -373,6 +373,7 @@ |
104 | p.name = appid.package.value(); |
105 | p.version = appid.version.value(); |
106 | if (!p.name.empty() && !p.version.empty()) { |
107 | + p.url = "appid://" + p.name + "/" + app->appId().appname.value() + "/current-user-version"; |
108 | packages.insert(p); |
109 | } |
110 | } |
111 | |
112 | === modified file 'libclickscope/click/interface.h' |
113 | --- libclickscope/click/interface.h 2016-09-21 18:03:39 +0000 |
114 | +++ libclickscope/click/interface.h 2016-09-21 18:03:39 +0000 |
115 | @@ -31,6 +31,7 @@ |
116 | #define CLICK_INTERFACE_H |
117 | |
118 | #include "application.h" |
119 | +#include "manifest.h" |
120 | #include "package.h" |
121 | |
122 | #include <ubuntu-app-launch/application.h> |
123 | @@ -52,32 +53,7 @@ |
124 | // Hash map of desktop files that are not yet click packages |
125 | const std::unordered_set<std::string>& nonClickDesktopFiles(); |
126 | |
127 | -struct Manifest |
128 | -{ |
129 | - Manifest() = default; |
130 | - Manifest(std::string name, std::string version, std::string first_app_name) : |
131 | - name(name), version(version), first_app_name(first_app_name) |
132 | - { |
133 | - } |
134 | - virtual ~Manifest() = default; |
135 | - |
136 | - std::string name; |
137 | - std::string version; |
138 | - std::string first_app_name; |
139 | - std::string first_scope_id; |
140 | - bool removable = false; |
141 | - bool has_any_apps() const { |
142 | - return !first_app_name.empty(); |
143 | - } |
144 | - bool has_any_scopes() const { |
145 | - return !first_scope_id.empty(); |
146 | - } |
147 | -}; |
148 | - |
149 | enum class InterfaceError {NoError, CallError, ParseError}; |
150 | -typedef std::list<Manifest> ManifestList; |
151 | - |
152 | -Manifest manifest_from_json(const std::string& json); |
153 | |
154 | class Interface |
155 | { |
156 | |
157 | === added file 'libclickscope/click/manifest.h' |
158 | --- libclickscope/click/manifest.h 1970-01-01 00:00:00 +0000 |
159 | +++ libclickscope/click/manifest.h 2016-09-21 18:03:39 +0000 |
160 | @@ -0,0 +1,65 @@ |
161 | +/* |
162 | + * Copyright (C) 2014-2016 Canonical Ltd. |
163 | + * |
164 | + * This program is free software: you can redistribute it and/or modify it |
165 | + * under the terms of the GNU General Public License version 3, as published |
166 | + * by the Free Software Foundation. |
167 | + * |
168 | + * This program is distributed in the hope that it will be useful, but |
169 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
170 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
171 | + * PURPOSE. See the GNU General Public License for more details. |
172 | + * |
173 | + * You should have received a copy of the GNU General Public License along |
174 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
175 | + * |
176 | + * In addition, as a special exception, the copyright holders give |
177 | + * permission to link the code of portions of this program with the |
178 | + * OpenSSL library under certain conditions as described in each |
179 | + * individual source file, and distribute linked combinations |
180 | + * including the two. |
181 | + * You must obey the GNU General Public License in all respects |
182 | + * for all of the code used other than OpenSSL. If you modify |
183 | + * file(s) with this exception, you may extend this exception to your |
184 | + * version of the file(s), but you are not obligated to do so. If you |
185 | + * do not wish to do so, delete this exception statement from your |
186 | + * version. If you delete this exception statement from all source |
187 | + * files in the program, then also delete it here. |
188 | + */ |
189 | + |
190 | +#ifndef CLICK_MANIFEST_H |
191 | +#define CLICK_MANIFEST_H |
192 | + |
193 | +#include <list> |
194 | + |
195 | +namespace click { |
196 | + |
197 | +struct Manifest |
198 | +{ |
199 | + Manifest() = default; |
200 | + Manifest(const std::string& name, const std::string& version, const std::string& first_app_name) : |
201 | + name(name), version(version), first_app_name(first_app_name) |
202 | + { |
203 | + } |
204 | + virtual ~Manifest() = default; |
205 | + |
206 | + std::string name; |
207 | + std::string version; |
208 | + std::string first_app_name; |
209 | + std::string first_scope_id; |
210 | + bool removable = false; |
211 | + bool has_any_apps() const { |
212 | + return !first_app_name.empty(); |
213 | + } |
214 | + bool has_any_scopes() const { |
215 | + return !first_scope_id.empty(); |
216 | + } |
217 | +}; |
218 | + |
219 | +typedef std::list<Manifest> ManifestList; |
220 | + |
221 | +Manifest manifest_from_json(const std::string& json); |
222 | + |
223 | +} // namespace click |
224 | + |
225 | +#endif // CLICK_MANIFEST_H |
226 | |
227 | === modified file 'libclickscope/click/package.cpp' |
228 | --- libclickscope/click/package.cpp 2016-09-21 18:03:39 +0000 |
229 | +++ libclickscope/click/package.cpp 2016-09-21 18:03:39 +0000 |
230 | @@ -45,7 +45,10 @@ |
231 | // We can't include the version in the comparison here, because this |
232 | // comparison is used by the sorted_set, that we use to compare a package |
233 | // installed locally on the device with a (possibly updated) package available in the store. |
234 | - return lhs.name == rhs.name; |
235 | + return lhs.name == rhs.name || |
236 | + lhs.alias == rhs.alias || |
237 | + lhs.name == rhs.alias || |
238 | + lhs.alias == rhs.name; |
239 | |
240 | } |
241 | |
242 | |
243 | === modified file 'libclickscope/click/package.h' |
244 | --- libclickscope/click/package.h 2016-09-21 18:03:39 +0000 |
245 | +++ libclickscope/click/package.h 2016-09-21 18:03:39 +0000 |
246 | @@ -116,7 +116,7 @@ |
247 | public : |
248 | size_t operator()(const Package &package ) const |
249 | { |
250 | - return std::hash<std::string>()(package.name); |
251 | + return std::hash<std::string>()(package.snap_id.empty() ? package.name : package.alias); |
252 | } |
253 | }; |
254 | }; |
255 | |
256 | === modified file 'libclickscope/click/preview.cpp' |
257 | --- libclickscope/click/preview.cpp 2016-09-21 18:03:39 +0000 |
258 | +++ libclickscope/click/preview.cpp 2016-09-21 18:03:39 +0000 |
259 | @@ -825,10 +825,14 @@ |
260 | const unity::scopes::ActionMetadata& metadata, |
261 | const QSharedPointer<click::web::Client>& client, |
262 | const QSharedPointer<pay::Package>& ppackage, |
263 | - const std::shared_ptr<click::DepartmentsDb>& depts) |
264 | + const std::shared_ptr<click::DepartmentsDb>& depts, |
265 | + const std::shared_ptr<click::Configuration>& configuration, |
266 | + const std::shared_ptr<click::Snapd>& snapd) |
267 | : PreviewStrategy(result, client, ppackage), |
268 | DepartmentUpdater(depts), |
269 | - metadata(metadata) |
270 | + metadata(metadata), |
271 | + configuration(configuration), |
272 | + snapd(snapd) |
273 | { |
274 | } |
275 | |
276 | @@ -932,6 +936,9 @@ |
277 | }); |
278 | }); |
279 | manifest = manifest_future.get(); |
280 | + if (manifest.name.empty() && configuration->is_snapd_running()) { |
281 | + manifest = snapd->get_manifest(app_name); |
282 | + } |
283 | if (review.rating > 0) { |
284 | std::promise<bool> submit_promise; |
285 | std::future<bool> submit_future = submit_promise.get_future(); |
286 | |
287 | === modified file 'libclickscope/click/preview.h' |
288 | --- libclickscope/click/preview.h 2016-07-12 19:04:31 +0000 |
289 | +++ libclickscope/click/preview.h 2016-09-21 18:03:39 +0000 |
290 | @@ -255,7 +255,9 @@ |
291 | const unity::scopes::ActionMetadata& metadata, |
292 | const QSharedPointer<click::web::Client>& client, |
293 | const QSharedPointer<pay::Package>& ppackage, |
294 | - const std::shared_ptr<click::DepartmentsDb>& depts); |
295 | + const std::shared_ptr<click::DepartmentsDb>& depts, |
296 | + const std::shared_ptr<click::Configuration>& configuration = std::shared_ptr<click::Configuration>(new click::Configuration()), |
297 | + const std::shared_ptr<click::Snapd>& snapd = std::shared_ptr<click::Snapd>(new click::Snapd())); |
298 | |
299 | virtual ~InstalledPreview(); |
300 | |
301 | @@ -270,6 +272,8 @@ |
302 | scopes::ActionMetadata metadata; |
303 | CachedPreviewWidgets cachedWidgets; |
304 | PackageDetails cachedDetails; |
305 | + std::shared_ptr<click::Configuration> configuration; |
306 | + std::shared_ptr<click::Snapd> snapd; |
307 | }; |
308 | |
309 | class InstalledScopePreview : public PreviewStrategy |
310 | |
311 | === added file 'libclickscope/click/snapd.cpp' |
312 | --- libclickscope/click/snapd.cpp 1970-01-01 00:00:00 +0000 |
313 | +++ libclickscope/click/snapd.cpp 2016-09-21 18:03:39 +0000 |
314 | @@ -0,0 +1,171 @@ |
315 | +/* |
316 | + * Copyright (C) 2016 Canonical Ltd. |
317 | + * |
318 | + * This program is free software: you can redistribute it and/or modify it |
319 | + * under the terms of the GNU General Public License version 3, as published |
320 | + * by the Free Software Foundation. |
321 | + * |
322 | + * This program is distributed in the hope that it will be useful, but |
323 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
324 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
325 | + * PURPOSE. See the GNU General Public License for more details. |
326 | + * |
327 | + * You should have received a copy of the GNU General Public License along |
328 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
329 | + * |
330 | + * In addition, as a special exception, the copyright holders give |
331 | + * permission to link the code of portions of this program with the |
332 | + * OpenSSL library under certain conditions as described in each |
333 | + * individual source file, and distribute linked combinations |
334 | + * including the two. |
335 | + * You must obey the GNU General Public License in all respects |
336 | + * for all of the code used other than OpenSSL. If you modify |
337 | + * file(s) with this exception, you may extend this exception to your |
338 | + * version of the file(s), but you are not obligated to do so. If you |
339 | + * do not wish to do so, delete this exception statement from your |
340 | + * version. If you delete this exception statement from all source |
341 | + * files in the program, then also delete it here. |
342 | + */ |
343 | + |
344 | +#include "snapd.h" |
345 | + |
346 | +#include <iostream> |
347 | +#include <sstream> |
348 | +#include <string> |
349 | + |
350 | +#include <QDebug> |
351 | +#include <boost/asio.hpp> |
352 | +#include <json/json.h> |
353 | + |
354 | +using boost::asio::local::stream_protocol; |
355 | + |
356 | +namespace click { |
357 | + |
358 | +std::string SnapSocket::get(const std::string& path) const { |
359 | + boost::asio::io_service ios; |
360 | + stream_protocol::socket socket{ios}; |
361 | + socket.connect(stream_protocol::endpoint("/run/snapd.socket")); |
362 | + |
363 | + std::stringstream msgstream; |
364 | + msgstream << "GET " << path << " HTTP/1.0\r\n"; |
365 | + msgstream << "Connection: close\r\n"; |
366 | + msgstream << "\r\n"; |
367 | + auto msg = msgstream.str(); |
368 | + boost::asio::write(socket, boost::asio::buffer(msg.c_str(), msg.size())); |
369 | + |
370 | + boost::asio::streambuf response; |
371 | + boost::asio::read_until(socket, response, "\r\n"); |
372 | + |
373 | + // Read the HTTP status line |
374 | + std::istream rstream{&response}; |
375 | + std::string http_version; |
376 | + rstream >> http_version; |
377 | + unsigned int status_code; |
378 | + rstream >> status_code; |
379 | + std::string status_msg; |
380 | + std::getline(rstream, status_msg); |
381 | + if (status_code != 200) { |
382 | + qWarning () << "Error from snapd:" << status_code << QString::fromStdString(status_msg); |
383 | + return ""; |
384 | + } |
385 | + |
386 | + // Read the headers in |
387 | + boost::asio::read_until(socket, response, "\r\n\r\n"); |
388 | + std::string header; |
389 | + while (std::getline(rstream, header) && header != "\r") { |
390 | + // Do nothing, just need to run through them |
391 | + } |
392 | + |
393 | + // Read any more data and return the rest |
394 | + std::stringstream ss; |
395 | + if (response.size() > 0) { |
396 | + ss << &response; |
397 | + } |
398 | + |
399 | + if (socket.available() == 0) { |
400 | + return ss.str(); |
401 | + } |
402 | + |
403 | + boost::system::error_code error = boost::asio::error::no_data; |
404 | + while (boost::asio::read(socket, response, |
405 | + boost::asio::transfer_at_least(1), error)) { |
406 | + ss << &response; |
407 | + if (error != boost::system::errc::success && |
408 | + error != boost::asio::error::eof) { |
409 | + throw boost::system::system_error(error); |
410 | + } else { |
411 | + break; |
412 | + } |
413 | + } |
414 | + return ss.str(); |
415 | +} |
416 | + |
417 | +Snapd::Snapd(const std::shared_ptr<SnapSocket>& socket) |
418 | + : m_socket(socket) |
419 | +{ |
420 | +} |
421 | + |
422 | +std::string Snapd::get_series() const { |
423 | + auto json = m_socket->get("/v2/system-info"); |
424 | + qDebug() << "Got snap system info:" << QString::fromStdString(json); |
425 | + |
426 | + try { |
427 | + Json::Reader reader; |
428 | + Json::Value root; |
429 | + |
430 | + if (!reader.parse(json, root)) { |
431 | + throw std::runtime_error(reader.getFormattedErrorMessages()); |
432 | + } |
433 | + |
434 | + auto node = root["result"]["series"]; |
435 | + if (node.isString()) { |
436 | + return node.asString(); |
437 | + } |
438 | + } catch (...) { |
439 | + auto eptr = std::current_exception(); |
440 | + try { |
441 | + if (eptr) { |
442 | + std::rethrow_exception(eptr); |
443 | + } |
444 | + } catch (const std::exception& e) { |
445 | + qCritical() << "Exception thrown parsing snapd JSON:" << QString::fromStdString(e.what()); |
446 | + } |
447 | + } |
448 | + return ""; |
449 | +} |
450 | + |
451 | +Manifest Snapd::get_manifest(const std::string& package) const { |
452 | + Manifest manifest; |
453 | + |
454 | + auto json = m_socket->get("/v2/snaps/" + package); |
455 | + qDebug() << "Got snap manifest:" << QString::fromStdString(json); |
456 | + |
457 | + try { |
458 | + Json::Reader reader; |
459 | + Json::Value root; |
460 | + |
461 | + if (!reader.parse(json, root)) { |
462 | + throw std::runtime_error(reader.getFormattedErrorMessages()); |
463 | + } |
464 | + |
465 | + manifest.name = root["result"]["name"].asString(); |
466 | + manifest.version = root["result"]["version"].asString(); |
467 | + // FIXME: Need to determine first scope, and if removable |
468 | + if (root["result"].isMember("apps")) { |
469 | + auto appslist = root["result"]["apps"]; |
470 | + manifest.first_app_name = appslist[0]["name"].asString(); |
471 | + } |
472 | + } catch (...) { |
473 | + auto eptr = std::current_exception(); |
474 | + try { |
475 | + if (eptr) { |
476 | + std::rethrow_exception(eptr); |
477 | + } |
478 | + } catch (const std::exception& e) { |
479 | + qCritical() << "Exception parsing snapd JSON:" << QString::fromStdString(e.what()); |
480 | + } |
481 | + } |
482 | + return manifest; |
483 | +} |
484 | + |
485 | +} // namespace click |
486 | |
487 | === added file 'libclickscope/click/snapd.h' |
488 | --- libclickscope/click/snapd.h 1970-01-01 00:00:00 +0000 |
489 | +++ libclickscope/click/snapd.h 2016-09-21 18:03:39 +0000 |
490 | @@ -0,0 +1,61 @@ |
491 | +/* |
492 | + * Copyright (C) 2016 Canonical Ltd. |
493 | + * |
494 | + * This program is free software: you can redistribute it and/or modify it |
495 | + * under the terms of the GNU General Public License version 3, as published |
496 | + * by the Free Software Foundation. |
497 | + * |
498 | + * This program is distributed in the hope that it will be useful, but |
499 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
500 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
501 | + * PURPOSE. See the GNU General Public License for more details. |
502 | + * |
503 | + * You should have received a copy of the GNU General Public License along |
504 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
505 | + * |
506 | + * In addition, as a special exception, the copyright holders give |
507 | + * permission to link the code of portions of this program with the |
508 | + * OpenSSL library under certain conditions as described in each |
509 | + * individual source file, and distribute linked combinations |
510 | + * including the two. |
511 | + * You must obey the GNU General Public License in all respects |
512 | + * for all of the code used other than OpenSSL. If you modify |
513 | + * file(s) with this exception, you may extend this exception to your |
514 | + * version of the file(s), but you are not obligated to do so. If you |
515 | + * do not wish to do so, delete this exception statement from your |
516 | + * version. If you delete this exception statement from all source |
517 | + * files in the program, then also delete it here. |
518 | + */ |
519 | + |
520 | +#ifndef CLICK_SNAPD_H |
521 | +#define CLICK_SNAPD_H |
522 | + |
523 | +#include <memory> |
524 | +#include <string> |
525 | + |
526 | +#include "manifest.h" |
527 | + |
528 | +namespace click { |
529 | + |
530 | + class SnapSocket { |
531 | + public: |
532 | + SnapSocket() = default; |
533 | + virtual ~SnapSocket() = default; |
534 | + |
535 | + virtual std::string get(const std::string& path) const; |
536 | + }; // classs SnapSocket |
537 | + |
538 | + class Snapd { |
539 | + public: |
540 | + Snapd(const std::shared_ptr<SnapSocket>& socket = std::shared_ptr<SnapSocket>(new SnapSocket())); |
541 | + virtual ~Snapd() = default; |
542 | + |
543 | + virtual std::string get_series() const; |
544 | + virtual Manifest get_manifest(const std::string& package) const; |
545 | + private: |
546 | + std::shared_ptr<SnapSocket> m_socket; |
547 | + }; // class Snapd |
548 | + |
549 | +} // namespace click |
550 | + |
551 | +#endif // CLICK_SNAPD_H |
552 | |
553 | === modified file 'libclickscope/tests/CMakeLists.txt' |
554 | --- libclickscope/tests/CMakeLists.txt 2016-09-21 18:03:39 +0000 |
555 | +++ libclickscope/tests/CMakeLists.txt 2016-09-21 18:03:39 +0000 |
556 | @@ -37,6 +37,7 @@ |
557 | test_preview.cpp |
558 | test_reviews.cpp |
559 | test_smartconnect.cpp |
560 | + test_snapd.cpp |
561 | test_utils.cpp |
562 | test_webclient.cpp |
563 | ) |
564 | |
565 | === added file 'libclickscope/tests/mock_configuration.h' |
566 | --- libclickscope/tests/mock_configuration.h 1970-01-01 00:00:00 +0000 |
567 | +++ libclickscope/tests/mock_configuration.h 2016-09-21 18:03:39 +0000 |
568 | @@ -0,0 +1,48 @@ |
569 | +/* |
570 | + * Copyright (C) 2014-2016 Canonical Ltd. |
571 | + * |
572 | + * This program is free software: you can redistribute it and/or modify it |
573 | + * under the terms of the GNU General Public License version 3, as published |
574 | + * by the Free Software Foundation. |
575 | + * |
576 | + * This program is distributed in the hope that it will be useful, but |
577 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
578 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
579 | + * PURPOSE. See the GNU General Public License for more details. |
580 | + * |
581 | + * You should have received a copy of the GNU General Public License along |
582 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
583 | + * |
584 | + * In addition, as a special exception, the copyright holders give |
585 | + * permission to link the code of portions of this program with the |
586 | + * OpenSSL library under certain conditions as described in each |
587 | + * individual source file, and distribute linked combinations |
588 | + * including the two. |
589 | + * You must obey the GNU General Public License in all respects |
590 | + * for all of the code used other than OpenSSL. If you modify |
591 | + * file(s) with this exception, you may extend this exception to your |
592 | + * version of the file(s), but you are not obligated to do so. If you |
593 | + * do not wish to do so, delete this exception statement from your |
594 | + * version. If you delete this exception statement from all source |
595 | + * files in the program, then also delete it here. |
596 | + */ |
597 | + |
598 | +#ifndef MOCK_CONFIGURATION_H |
599 | +#define MOCK_CONFIGURATION_H |
600 | + |
601 | +#include <click/configuration.h> |
602 | + |
603 | +#include <gmock/gmock.h> |
604 | + |
605 | +namespace { |
606 | + |
607 | +class MockConfiguration : public click::Configuration { |
608 | +public: |
609 | + MOCK_METHOD0(get_architecture, std::string()); |
610 | + MOCK_METHOD0(get_available_frameworks, std::vector<std::string>()); |
611 | + MOCK_CONST_METHOD0(is_snapd_running, bool()); |
612 | +}; |
613 | + |
614 | +} // namespace |
615 | + |
616 | +#endif // MOCK_CONFIGURATION_H |
617 | |
618 | === added file 'libclickscope/tests/mock_snapd.h' |
619 | --- libclickscope/tests/mock_snapd.h 1970-01-01 00:00:00 +0000 |
620 | +++ libclickscope/tests/mock_snapd.h 2016-09-21 18:03:39 +0000 |
621 | @@ -0,0 +1,89 @@ |
622 | +/* |
623 | + * Copyright (C) 2014 Canonical Ltd. |
624 | + * |
625 | + * This program is free software: you can redistribute it and/or modify it |
626 | + * under the terms of the GNU General Public License version 3, as published |
627 | + * by the Free Software Foundation. |
628 | + * |
629 | + * This program is distributed in the hope that it will be useful, but |
630 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
631 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
632 | + * PURPOSE. See the GNU General Public License for more details. |
633 | + * |
634 | + * You should have received a copy of the GNU General Public License along |
635 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
636 | + * |
637 | + * In addition, as a special exception, the copyright holders give |
638 | + * permission to link the code of portions of this program with the |
639 | + * OpenSSL library under certain conditions as described in each |
640 | + * individual source file, and distribute linked combinations |
641 | + * including the two. |
642 | + * You must obey the GNU General Public License in all respects |
643 | + * for all of the code used other than OpenSSL. If you modify |
644 | + * file(s) with this exception, you may extend this exception to your |
645 | + * version of the file(s), but you are not obligated to do so. If you |
646 | + * do not wish to do so, delete this exception statement from your |
647 | + * version. If you delete this exception statement from all source |
648 | + * files in the program, then also delete it here. |
649 | + */ |
650 | + |
651 | +#include <click/snapd.h> |
652 | + |
653 | +#include <gmock/gmock.h> |
654 | + |
655 | +namespace { |
656 | + |
657 | + constexpr static const char* FAKE_SYSINFO_JSON{R"foo( |
658 | + { |
659 | + "type": "sync", |
660 | + "status": "OK", |
661 | + "result": { |
662 | + "series": "9999", |
663 | + "version": "2.0.17", |
664 | + "os-release": { |
665 | + "id": "ubuntu", |
666 | + "version-id": "16.04" |
667 | + }, |
668 | + "on-classic": true |
669 | + } |
670 | + } |
671 | + )foo"}; |
672 | + |
673 | + constexpr static const char* FAKE_DETAILS_JSON{R"foo( |
674 | + { |
675 | + "type": "sync", |
676 | + "status": "OK", |
677 | + "result": { |
678 | + "apps": [ |
679 | + { "name": "app-in-a-snap" }, |
680 | + { "name": "another-app-in-this-snap" } |
681 | + ], |
682 | + "summary": "An app in a snap", |
683 | + "description": "App in a snap, not a cat in a hat.", |
684 | + "icon": "/foo/bar/baz.png", |
685 | + "installed-size": 67784704, |
686 | + "install-date": "2016-03-08T11:29:21Z", |
687 | + "name": "app-in-a-snap", |
688 | + "developer": "cat-in-a-hat", |
689 | + "resource": "/v2/snaps/app-in-a-snap", |
690 | + "status": "active", |
691 | + "type": "app", |
692 | + "update-available": 247, |
693 | + "version": "241", |
694 | + "revision": 8, |
695 | + "channel": "stable" |
696 | + } |
697 | + } |
698 | + )foo"}; |
699 | + |
700 | + class MockSnapSocket : public click::SnapSocket { |
701 | + public: |
702 | + MockSnapSocket() |
703 | + : SnapSocket() |
704 | + { |
705 | + } |
706 | + |
707 | + MOCK_CONST_METHOD1(get, std::string(const std::string&)); |
708 | + }; |
709 | + |
710 | +} |
711 | |
712 | === modified file 'libclickscope/tests/test_index.cpp' |
713 | --- libclickscope/tests/test_index.cpp 2016-09-21 18:03:39 +0000 |
714 | +++ libclickscope/tests/test_index.cpp 2016-09-21 18:03:39 +0000 |
715 | @@ -28,10 +28,13 @@ |
716 | */ |
717 | |
718 | #include <click/index.h> |
719 | +#include <click/snapd.h> |
720 | #include <click/utils.h> |
721 | #include <click/webclient.h> |
722 | |
723 | +#include <tests/mock_configuration.h> |
724 | #include <tests/mock_network_access_manager.h> |
725 | +#include <tests/mock_snapd.h> |
726 | #include <tests/mock_ubuntuone_credentials.h> |
727 | #include <tests/mock_webclient.h> |
728 | |
729 | @@ -53,31 +56,30 @@ |
730 | public: |
731 | using click::Index::build_index_query; |
732 | MockableIndex(const QSharedPointer<click::web::Client>& client, |
733 | - const QSharedPointer<click::Configuration> configuration) : |
734 | - click::Index(client, configuration) |
735 | + const QSharedPointer<click::Configuration> configuration, |
736 | + const std::shared_ptr<click::Snapd>& snapd) : |
737 | + click::Index(client, configuration, snapd) |
738 | { |
739 | } |
740 | }; |
741 | |
742 | -class MockConfiguration : public click::Configuration { |
743 | -public: |
744 | - MOCK_METHOD0(get_architecture, std::string()); |
745 | - MOCK_METHOD0(get_available_frameworks, std::vector<std::string>()); |
746 | -}; |
747 | - |
748 | |
749 | class SimpleIndexTest : public ::testing::Test { |
750 | protected: |
751 | QSharedPointer<MockClient> clientPtr; |
752 | QSharedPointer<MockNetworkAccessManager> namPtr; |
753 | QSharedPointer<MockConfiguration> configPtr; |
754 | + std::shared_ptr<MockSnapSocket> socketPtr; |
755 | + std::shared_ptr<click::Snapd> snapdPtr; |
756 | std::shared_ptr<MockableIndex> indexPtr; |
757 | |
758 | virtual void SetUp() { |
759 | namPtr.reset(new MockNetworkAccessManager()); |
760 | clientPtr.reset(new NiceMock<MockClient>(namPtr)); |
761 | configPtr.reset(new MockConfiguration()); |
762 | - indexPtr.reset(new MockableIndex(clientPtr, configPtr)); |
763 | + socketPtr.reset(new MockSnapSocket()); |
764 | + snapdPtr.reset(new click::Snapd(socketPtr)); |
765 | + indexPtr.reset(new MockableIndex(clientPtr, configPtr, snapdPtr)); |
766 | // register default value for build_headers() mock |
767 | DefaultValue<std::map<std::string, std::string>>::Set(std::map<std::string, std::string>()); |
768 | } |
769 | |
770 | === modified file 'libclickscope/tests/test_interface.cpp' |
771 | --- libclickscope/tests/test_interface.cpp 2016-09-21 18:03:39 +0000 |
772 | +++ libclickscope/tests/test_interface.cpp 2016-09-21 18:03:39 +0000 |
773 | @@ -500,6 +500,12 @@ |
774 | }); |
775 | } |
776 | |
777 | +TEST_F(ClickInterfaceTest, testWhatYaGoneDo) |
778 | +{ |
779 | + click::Interface iface; |
780 | + iface.get_manifest_for_app("foo.bar", [](Manifest, InterfaceError) {}); |
781 | +} |
782 | + |
783 | TEST_F(ClickInterfaceTest, testGetManifestForAppIsNotRemovable) |
784 | { |
785 | FakeClickInterface iface; |
786 | |
787 | === modified file 'libclickscope/tests/test_preview.cpp' |
788 | --- libclickscope/tests/test_preview.cpp 2016-09-21 18:03:39 +0000 |
789 | +++ libclickscope/tests/test_preview.cpp 2016-09-21 18:03:39 +0000 |
790 | @@ -33,8 +33,11 @@ |
791 | #include <click/interface.h> |
792 | #include <click/reviews.h> |
793 | #include <fake_json.h> |
794 | +#include <mock_configuration.h> |
795 | #include <mock_pay.h> |
796 | +#include <mock_snapd.h> |
797 | #include <mock_ubuntu_download_manager.h> |
798 | +#include <mock_webclient.h> |
799 | |
800 | #include <QCoreApplication> |
801 | #include <QTimer> |
802 | @@ -544,12 +547,16 @@ |
803 | unity::scopes::testing::Result result; |
804 | unity::scopes::ActionMetadata metadata; |
805 | unity::scopes::VariantMap metadict; |
806 | - QSharedPointer<click::web::Client> client; |
807 | + QSharedPointer<MockClient> client; |
808 | QSharedPointer<MockPayPackage> pay_package; |
809 | std::shared_ptr<click::DepartmentsDb> depts; |
810 | + std::shared_ptr<MockConfiguration> config; |
811 | + std::shared_ptr<click::Snapd> snapd; |
812 | + std::shared_ptr<MockSnapSocket> snapsock; |
813 | |
814 | public: |
815 | InstalledPreviewTest() : metadata("en_EN", "phone") { |
816 | + snapd.reset(new click::Snapd(snapsock)); |
817 | } |
818 | }; |
819 | |
820 | @@ -557,20 +564,23 @@ |
821 | public: |
822 | FakeInstalledRefundablePreview(const unity::scopes::Result& result, |
823 | const unity::scopes::ActionMetadata& metadata, |
824 | - const QSharedPointer<click::web::Client> client, |
825 | - const QSharedPointer<pay::Package> pay_package, |
826 | - const std::shared_ptr<click::DepartmentsDb> depts) |
827 | - : click::InstalledPreview(result, metadata, client, pay_package, depts) { |
828 | + const QSharedPointer<click::web::Client>& client, |
829 | + const QSharedPointer<pay::Package>& pay_package, |
830 | + const std::shared_ptr<click::DepartmentsDb>& depts, |
831 | + const std::shared_ptr<click::Configuration>& config, |
832 | + const std::shared_ptr<click::Snapd>& snapd) |
833 | + : click::InstalledPreview(result, metadata, client, pay_package, depts, config, snapd) { |
834 | |
835 | } |
836 | |
837 | using click::InstalledPreview::createButtons; |
838 | MOCK_METHOD0(isRefundable, bool()); |
839 | + MOCK_METHOD0(get_consumer_key, std::string()); |
840 | }; |
841 | |
842 | TEST_F(InstalledPreviewTest, testIsRefundableButtonShownFromStore) { |
843 | result["price"] = 3.99f; |
844 | - FakeInstalledRefundablePreview preview(result, metadata, client, pay_package, depts); |
845 | + FakeInstalledRefundablePreview preview(result, metadata, client, pay_package, depts, config, snapd); |
846 | EXPECT_CALL(preview, isRefundable()).Times(1) |
847 | .WillOnce(Return(true)); |
848 | click::Manifest manifest; |
849 | @@ -583,7 +593,7 @@ |
850 | } |
851 | |
852 | TEST_F(InstalledPreviewTest, testIsRefundableButtonNotShownFromApps) { |
853 | - FakeInstalledRefundablePreview preview(result, metadata, client, pay_package, depts); |
854 | + FakeInstalledRefundablePreview preview(result, metadata, client, pay_package, depts, config, snapd); |
855 | EXPECT_CALL(preview, isRefundable()).Times(0); |
856 | click::Manifest manifest; |
857 | manifest.removable = true; |
858 | @@ -595,7 +605,7 @@ |
859 | } |
860 | |
861 | TEST_F(InstalledPreviewTest, testIsRefundableButtonNotShown) { |
862 | - FakeInstalledRefundablePreview preview(result, metadata, client, pay_package, depts); |
863 | + FakeInstalledRefundablePreview preview(result, metadata, client, pay_package, depts, config, snapd); |
864 | EXPECT_CALL(preview, isRefundable()).Times(0); |
865 | click::Manifest manifest; |
866 | manifest.removable = true; |
867 | @@ -608,7 +618,7 @@ |
868 | } |
869 | |
870 | TEST_F(InstalledPreviewTest, testReviewWidgetIsNew) { |
871 | - click::InstalledPreview preview(result, metadata, client, pay_package, depts); |
872 | + click::InstalledPreview preview(result, metadata, client, pay_package, depts, config, snapd); |
873 | click::Review existing_review; |
874 | existing_review.id = 0; |
875 | auto widget = preview.createRatingWidget(existing_review); |
876 | @@ -616,7 +626,7 @@ |
877 | } |
878 | |
879 | TEST_F(InstalledPreviewTest, testReviewWidgetIsEdit) { |
880 | - click::InstalledPreview preview(result, metadata, client, pay_package, depts); |
881 | + click::InstalledPreview preview(result, metadata, client, pay_package, depts, config, snapd); |
882 | click::Review existing_review; |
883 | existing_review.id = 123456789; |
884 | existing_review.rating = 2.625f; |
885 | @@ -627,7 +637,7 @@ |
886 | } |
887 | |
888 | TEST_F(InstalledPreviewTest, testGetApplicationURIClick) { |
889 | - click::InstalledPreview preview(result, metadata, client, pay_package, depts); |
890 | + click::InstalledPreview preview(result, metadata, client, pay_package, depts, config, snapd); |
891 | click::Manifest manifest; |
892 | manifest.name = "com.ubuntu.clock"; |
893 | manifest.first_app_name = "clock"; |
894 | @@ -637,7 +647,7 @@ |
895 | TEST_F(InstalledPreviewTest, testGetApplicationURIClickInResult) { |
896 | std::string uri{"appid://com.ubuntu.clock/clock/current-user-version"}; |
897 | result.set_uri(uri); |
898 | - click::InstalledPreview preview(result, metadata, client, pay_package, depts); |
899 | + click::InstalledPreview preview(result, metadata, client, pay_package, depts, config, snapd); |
900 | click::Manifest manifest; |
901 | ASSERT_EQ(preview.getApplicationUri(manifest), uri); |
902 | } |
903 | @@ -645,13 +655,13 @@ |
904 | TEST_F(InstalledPreviewTest, testGetApplicationURINonClick) { |
905 | std::string uri{"application:///web-browser.desktop"}; |
906 | result.set_uri(uri); |
907 | - click::InstalledPreview preview(result, metadata, client, pay_package, depts); |
908 | + click::InstalledPreview preview(result, metadata, client, pay_package, depts, config, snapd); |
909 | click::Manifest manifest; |
910 | ASSERT_EQ(preview.getApplicationUri(manifest), uri); |
911 | } |
912 | |
913 | TEST_F(InstalledPreviewTest, testGetApplicationURIScope) { |
914 | - click::InstalledPreview preview(result, metadata, client, pay_package, depts); |
915 | + click::InstalledPreview preview(result, metadata, client, pay_package, depts, config, snapd); |
916 | click::Manifest manifest; |
917 | manifest.name = "com.ubuntu.nearby"; |
918 | manifest.first_scope_id = "nearby"; |
919 | @@ -660,7 +670,7 @@ |
920 | |
921 | TEST_F(InstalledPreviewTest, testGetApplicationURINotAppOrScope) { |
922 | result.set_uri("https://foo.com"); |
923 | - click::InstalledPreview preview(result, metadata, client, pay_package, depts); |
924 | + click::InstalledPreview preview(result, metadata, client, pay_package, depts, config, snapd); |
925 | click::Manifest manifest; |
926 | ASSERT_EQ(preview.getApplicationUri(manifest), ""); |
927 | } |
928 | |
929 | === added file 'libclickscope/tests/test_snapd.cpp' |
930 | --- libclickscope/tests/test_snapd.cpp 1970-01-01 00:00:00 +0000 |
931 | +++ libclickscope/tests/test_snapd.cpp 2016-09-21 18:03:39 +0000 |
932 | @@ -0,0 +1,84 @@ |
933 | +/* |
934 | + * Copyright (C) 2016 Canonical Ltd. |
935 | + * |
936 | + * This program is free software: you can redistribute it and/or modify it |
937 | + * under the terms of the GNU General Public License version 3, as published |
938 | + * by the Free Software Foundation. |
939 | + * |
940 | + * This program is distributed in the hope that it will be useful, but |
941 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
942 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
943 | + * PURPOSE. See the GNU General Public License for more details. |
944 | + * |
945 | + * You should have received a copy of the GNU General Public License along |
946 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
947 | + * |
948 | + * In addition, as a special exception, the copyright holders give |
949 | + * permission to link the code of portions of this program with the |
950 | + * OpenSSL library under certain conditions as described in each |
951 | + * individual source file, and distribute linked combinations |
952 | + * including the two. |
953 | + * You must obey the GNU General Public License in all respects |
954 | + * for all of the code used other than OpenSSL. If you modify |
955 | + * file(s) with this exception, you may extend this exception to your |
956 | + * version of the file(s), but you are not obligated to do so. If you |
957 | + * do not wish to do so, delete this exception statement from your |
958 | + * version. If you delete this exception statement from all source |
959 | + * files in the program, then also delete it here. |
960 | + */ |
961 | + |
962 | +#include "mock_snapd.h" |
963 | +#include <click/snapd.h> |
964 | + |
965 | +#include <gmock/gmock.h> |
966 | +#include <gtest/gtest.h> |
967 | + |
968 | +using namespace ::testing; |
969 | + |
970 | +class SnapdTest : public ::testing::Test { |
971 | +public: |
972 | + SnapdTest() { |
973 | + mocksock.reset(new MockSnapSocket()); |
974 | + snapd.reset(new click::Snapd(mocksock)); |
975 | + } |
976 | + |
977 | + std::shared_ptr<MockSnapSocket> mocksock; |
978 | + std::shared_ptr<click::Snapd> snapd; |
979 | +}; |
980 | + |
981 | +TEST_F(SnapdTest, testGetSeries) { |
982 | + EXPECT_CALL(*mocksock, get(_)).Times(1) |
983 | + .WillOnce(Return(FAKE_SYSINFO_JSON)); |
984 | + EXPECT_EQ("9999", snapd->get_series()); |
985 | +} |
986 | + |
987 | +TEST_F(SnapdTest, testGetSeriesEmptyBody) { |
988 | + EXPECT_CALL(*mocksock, get(_)).Times(1) |
989 | + .WillOnce(Return("")); |
990 | + ASSERT_EQ("", snapd->get_series()); |
991 | +} |
992 | + |
993 | +TEST_F(SnapdTest, testGetManifest) { |
994 | + EXPECT_CALL(*mocksock, get(_)).Times(1) |
995 | + .WillOnce(Return(FAKE_DETAILS_JSON)); |
996 | + click::Manifest manifest; |
997 | + manifest = snapd->get_manifest("app-in-a-snap"); |
998 | + ASSERT_EQ("241", manifest.version); |
999 | +} |
1000 | + |
1001 | +TEST_F(SnapdTest, testGetManifestFirstApp) { |
1002 | + EXPECT_CALL(*mocksock, get(_)).Times(1) |
1003 | + .WillOnce(Return(FAKE_DETAILS_JSON)); |
1004 | + click::Manifest manifest; |
1005 | + manifest = snapd->get_manifest("app-in-a-snap"); |
1006 | + ASSERT_TRUE(manifest.has_any_apps()); |
1007 | + ASSERT_EQ("app-in-a-snap", manifest.first_app_name); |
1008 | +} |
1009 | + |
1010 | +TEST_F(SnapdTest, testGetManifestEmptyBody) { |
1011 | + EXPECT_CALL(*mocksock, get(_)).Times(1) |
1012 | + .WillOnce(Return("")); |
1013 | + click::Manifest manifest; |
1014 | + manifest = snapd->get_manifest("app-in-a-snap"); |
1015 | + ASSERT_TRUE(manifest.name.empty()); |
1016 | +} |
1017 | |
1018 | === modified file 'scope/clickstore/store-query.cpp' |
1019 | --- scope/clickstore/store-query.cpp 2016-09-21 18:03:39 +0000 |
1020 | +++ scope/clickstore/store-query.cpp 2016-09-21 18:03:39 +0000 |
1021 | @@ -153,14 +153,16 @@ |
1022 | click::HighlightList& highlights, |
1023 | const scopes::SearchMetadata& metadata, |
1024 | pay::Package& in_package, |
1025 | - std::shared_future<void> const& qt_ready) |
1026 | + std::shared_future<void> const& qt_ready, |
1027 | + const std::shared_ptr<click::Configuration>& configuration) |
1028 | : index(index), |
1029 | department_lookup(depts), |
1030 | depts_db(depts_db), |
1031 | highlights(highlights), |
1032 | meta(metadata), |
1033 | pay_package(in_package), |
1034 | - qt_ready_(qt_ready) |
1035 | + qt_ready_(qt_ready), |
1036 | + configuration(configuration) |
1037 | { |
1038 | } |
1039 | click::Index& index; |
1040 | @@ -173,6 +175,7 @@ |
1041 | click::web::Cancellable purchases_operation; |
1042 | pay::Package& pay_package; |
1043 | std::shared_future<void> qt_ready_; |
1044 | + std::shared_ptr<click::Configuration> configuration; |
1045 | }; |
1046 | |
1047 | click::Query::Query(unity::scopes::CannedQuery const& query, |
1048 | @@ -182,9 +185,10 @@ |
1049 | click::HighlightList& highlights, |
1050 | scopes::SearchMetadata const& metadata, |
1051 | pay::Package& in_package, |
1052 | - std::shared_future<void> const& qt_ready) |
1053 | + std::shared_future<void> const& qt_ready, |
1054 | + std::shared_ptr<click::Configuration> const& configuration) |
1055 | : unity::scopes::SearchQueryBase(query, metadata), |
1056 | - impl(new Private(index, depts, depts_db, highlights, metadata, in_package, qt_ready)) |
1057 | + impl(new Private(index, depts, depts_db, highlights, metadata, in_package, qt_ready, configuration)) |
1058 | { |
1059 | } |
1060 | |
1061 | @@ -347,6 +351,7 @@ |
1062 | res["currency_symbol"] = symbol; |
1063 | } |
1064 | if (installed != installedPackages.end()) { |
1065 | + res.set_uri(installed->url); |
1066 | res[click::Query::ResultKeys::INSTALLED] = true; |
1067 | res[click::Query::ResultKeys::PURCHASED] = was_purchased; |
1068 | price = _("✔ INSTALLED"); |
1069 | @@ -514,6 +519,7 @@ |
1070 | const scopes::CategoryRenderer categoryRenderer(categoryTemplate); |
1071 | |
1072 | std::string cat_title(_("Available")); |
1073 | + if (!query().query_string().empty()) |
1074 | { |
1075 | char tmp[512]; |
1076 | unsigned int num_results = static_cast<unsigned int>(packages.size()); |
1077 | @@ -548,8 +554,14 @@ |
1078 | const bool force_cache = (search_metadata().internet_connectivity() == scopes::QueryMetadata::ConnectivityStatus::Disconnected); |
1079 | qDebug() << "search, force_cache=" << force_cache << ", conn status=" << (int)search_metadata().internet_connectivity(); |
1080 | |
1081 | - // this is the case when we do bootstrap for the first time, or it failed last time |
1082 | - if (impl->department_lookup.size() == 0) |
1083 | + // Get list of frameworks to see if clicks are even feasible |
1084 | + auto frameworks = impl->configuration->get_available_frameworks(); |
1085 | + qDebug() << "Found" << frameworks.size() << "frameworks."; |
1086 | + |
1087 | + // this is the case when we do bootstrap for the first time, or |
1088 | + // it failed last time. Also only run bootstrap if there are |
1089 | + // click frameworks available. |
1090 | + if (impl->department_lookup.size() == 0 && frameworks.size() > 0) |
1091 | { |
1092 | qDebug() << "performing bootstrap request"; |
1093 | impl->search_operation = impl->index.bootstrap([this, search_cb, searchReply, installedPackages, force_cache](const DepartmentList& deps, const |
1094 | @@ -596,10 +608,17 @@ |
1095 | } |
1096 | else |
1097 | { |
1098 | - if (query().query_string().empty()) |
1099 | + if (query().query_string().empty() && frameworks.size() > 0) |
1100 | { |
1101 | add_highlights(searchReply, installedPackages); |
1102 | } |
1103 | + else if (frameworks.size() == 0 && |
1104 | + impl->configuration->is_snapd_running()) |
1105 | + { |
1106 | + qDebug() << "Only showing snaps."; |
1107 | + impl->search_snaps_operation = impl->index.search_snaps |
1108 | + (query().query_string(), search_cb, force_cache); |
1109 | + } |
1110 | else // normal search |
1111 | { |
1112 | qDebug() << "starting search of" << QString::fromStdString(query().query_string()); |
1113 | @@ -608,7 +627,7 @@ |
1114 | (query().query_string(), query().department_id(), |
1115 | [this, search_cb, force_cache](Packages packages, |
1116 | Packages recommends) { |
1117 | - if (Configuration().is_snapd_running()) { |
1118 | + if (impl->configuration->is_snapd_running()) { |
1119 | qDebug() << "Searching for snaps too."; |
1120 | impl->search_snaps_operation = impl->index.search_snaps |
1121 | (query().query_string(), |
1122 | |
1123 | === modified file 'scope/clickstore/store-query.h' |
1124 | --- scope/clickstore/store-query.h 2016-05-10 14:56:11 +0000 |
1125 | +++ scope/clickstore/store-query.h 2016-09-21 18:03:39 +0000 |
1126 | @@ -38,6 +38,7 @@ |
1127 | #include <QSharedPointer> |
1128 | #include <set> |
1129 | |
1130 | +#include <click/configuration.h> |
1131 | #include <click/department-lookup.h> |
1132 | #include <click/package.h> |
1133 | #include <click/pay.h> |
1134 | @@ -77,7 +78,8 @@ |
1135 | click::HighlightList& highlights, |
1136 | scopes::SearchMetadata const& metadata, |
1137 | pay::Package& in_package, |
1138 | - std::shared_future<void> const& qt_ready = std::future<void>()); |
1139 | + std::shared_future<void> const& qt_ready = std::future<void>(), |
1140 | + std::shared_ptr<click::Configuration> const& configuration = std::shared_ptr<click::Configuration>(new click::Configuration())); |
1141 | virtual ~Query(); |
1142 | |
1143 | virtual void cancelled() override; |
1144 | |
1145 | === modified file 'scope/tests/test_query.cpp' |
1146 | --- scope/tests/test_query.cpp 2015-12-01 15:39:41 +0000 |
1147 | +++ scope/tests/test_query.cpp 2016-09-21 18:03:39 +0000 |
1148 | @@ -46,6 +46,7 @@ |
1149 | #include "click/package.h" |
1150 | |
1151 | #include <tests/fake_json.h> |
1152 | +#include <tests/mock_configuration.h> |
1153 | #include <tests/mock_network_access_manager.h> |
1154 | |
1155 | #include <unity/scopes/CategoryRenderer.h> |
1156 | @@ -69,9 +70,11 @@ |
1157 | std::shared_ptr<click::DepartmentsDb> depts_db, |
1158 | click::HighlightList& highlights, |
1159 | scopes::SearchMetadata const& metadata, |
1160 | - pay::Package& in_package) : |
1161 | - click::Query(query, index, depts, depts_db, highlights, metadata, in_package) |
1162 | + pay::Package& in_package, |
1163 | + std::shared_ptr<click::Configuration> config = std::shared_ptr<click::Configuration>(new MockConfiguration())) : |
1164 | + click::Query(query, index, depts, depts_db, highlights, metadata, in_package, std::future<void>(), config) |
1165 | { |
1166 | + DefaultValue<std::vector<std::string>>::Set(std::vector<std::string>{"one", "two"}); |
1167 | } |
1168 | |
1169 | void run_under_qt(const std::function<void()> &task) { |
1170 | @@ -247,7 +250,7 @@ |
1171 | MockIndex mock_index(packages); |
1172 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1173 | PackageSet one_installed_package { |
1174 | - {"org.example.app2", "0.2"} |
1175 | + {"org.example.app2", "0.2", 0.0, "icon", "uri"} |
1176 | }; |
1177 | click::DepartmentLookup dept_lookup; |
1178 | click::HighlightList highlights; |
1179 | @@ -279,7 +282,7 @@ |
1180 | MockIndex mock_index(packages); |
1181 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1182 | PackageSet one_installed_package { |
1183 | - {"org.example.app2", "0.2"} |
1184 | + {"org.example.app2", "0.2", 0.0, "icon", "uri"} |
1185 | }; |
1186 | click::DepartmentLookup dept_lookup; |
1187 | click::HighlightList highlights; |
1188 | @@ -318,7 +321,7 @@ |
1189 | MockIndex mock_index(click::Packages(), click::DepartmentList(), init_departments); |
1190 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1191 | PackageSet one_installed_package { |
1192 | - {"org.example.app2", "0.2"} |
1193 | + {"org.example.app2", "0.2", 0.0, "icon", "uri"} |
1194 | }; |
1195 | click::DepartmentLookup dept_lookup; |
1196 | click::HighlightList highlights; |
1197 | @@ -383,7 +386,7 @@ |
1198 | MockPayPackage pay_pkg; |
1199 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1200 | MockQuery q(query, mock_index, dept_lookup, nullptr, highlights, metadata, pay_pkg); |
1201 | - PackageSet installed_packages{{"package_1", "0.1"}}; |
1202 | + PackageSet installed_packages{{"package_1", "0.1", 0.0, "icon", "uri"}}; |
1203 | |
1204 | FakeInterface fake_interface; |
1205 | EXPECT_CALL(q, clickInterfaceInstance()).WillOnce(ReturnRef(fake_interface)); |
1206 | @@ -439,7 +442,7 @@ |
1207 | {"name", "title", 0.99, "icon", "uri"} |
1208 | }; |
1209 | PackageSet one_installed_package { |
1210 | - {"name", "0.2"} |
1211 | + {"name", "0.2", 0.0, "icon", "uri"} |
1212 | }; |
1213 | MockIndex mock_index(packages); |
1214 | click::DepartmentLookup dept_lookup; |
PASSED: Continuous integration, rev:500 /jenkins. canonical. com/unity- api-1/job/ lp-unity- scope-click- ci/92/ /jenkins. canonical. com/unity- api-1/job/ build/526 /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/532 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= vivid+overlay/ 434 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= xenial+ overlay/ 434 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= yakkety/ 434 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 364 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 364/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 364 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 364/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 364 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 364/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 364 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 364/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 364 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 364/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 364 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 364/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 364 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 364/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 364 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 364/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 364 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 364/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/92/rebuild
https:/