Merge lp:~dobey/unity-scope-click/departments into lp:unity-scope-click/devel
- departments
- Merge into devel
Proposed by
dobey
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 299 | ||||
Proposed branch: | lp:~dobey/unity-scope-click/departments | ||||
Merge into: | lp:unity-scope-click/devel | ||||
Prerequisite: | lp:~dobey/unity-scope-click/search-haljson | ||||
Diff against target: |
1375 lines (+808/-62) 18 files modified
scope/click/CMakeLists.txt (+2/-0) scope/click/department-lookup.cpp (+84/-0) scope/click/department-lookup.h (+58/-0) scope/click/departments.cpp (+152/-0) scope/click/departments.h (+78/-0) scope/click/index.cpp (+39/-5) scope/click/index.h (+5/-2) scope/click/query.cpp (+89/-5) scope/click/query.h (+5/-1) scope/click/scope.cpp (+3/-1) scope/click/scope.h (+5/-0) scope/tests/CMakeLists.txt (+2/-1) scope/tests/fake_json.h (+96/-0) scope/tests/integration/webclient_integration.cpp (+3/-1) scope/tests/mock_webclient.h (+2/-2) scope/tests/test_departments.cpp (+108/-0) scope/tests/test_index.cpp (+10/-10) scope/tests/test_query.cpp (+67/-34) |
||||
To merge this branch: | bzr merge lp:~dobey/unity-scope-click/departments | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Unity Team | Pending | ||
Review via email: mp+219593@code.launchpad.net |
Commit message
Add support for departments.
Description of the change
To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : | # |
review:
Needs Fixing
(continuous-integration)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'scope/click/CMakeLists.txt' |
2 | --- scope/click/CMakeLists.txt 2014-05-13 19:32:29 +0000 |
3 | +++ scope/click/CMakeLists.txt 2014-05-14 20:14:25 +0000 |
4 | @@ -9,6 +9,8 @@ |
5 | ) |
6 | |
7 | add_library(${SCOPE_LIB_UNVERSIONED} SHARED |
8 | + departments.cpp |
9 | + department-lookup.cpp |
10 | configuration.cpp |
11 | download-manager.cpp |
12 | index.cpp |
13 | |
14 | === added file 'scope/click/department-lookup.cpp' |
15 | --- scope/click/department-lookup.cpp 1970-01-01 00:00:00 +0000 |
16 | +++ scope/click/department-lookup.cpp 2014-05-14 20:14:25 +0000 |
17 | @@ -0,0 +1,84 @@ |
18 | +/* |
19 | + * Copyright (C) 2014 Canonical Ltd. |
20 | + * |
21 | + * This program is free software: you can redistribute it and/or modify it |
22 | + * under the terms of the GNU General Public License version 3, as published |
23 | + * by the Free Software Foundation. |
24 | + * |
25 | + * This program is distributed in the hope that it will be useful, but |
26 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
27 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
28 | + * PURPOSE. See the GNU General Public License for more details. |
29 | + * |
30 | + * You should have received a copy of the GNU General Public License along |
31 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
32 | + * |
33 | + * In addition, as a special exception, the copyright holders give |
34 | + * permission to link the code of portions of this program with the |
35 | + * OpenSSL library under certain conditions as described in each |
36 | + * individual source file, and distribute linked combinations |
37 | + * including the two. |
38 | + * You must obey the GNU General Public License in all respects |
39 | + * for all of the code used other than OpenSSL. If you modify |
40 | + * file(s) with this exception, you may extend this exception to your |
41 | + * version of the file(s), but you are not obligated to do so. If you |
42 | + * do not wish to do so, delete this exception statement from your |
43 | + * version. If you delete this exception statement from all source |
44 | + * files in the program, then also delete it here. |
45 | + */ |
46 | + |
47 | +#include "department-lookup.h" |
48 | + |
49 | +namespace click |
50 | +{ |
51 | + |
52 | +DepartmentLookup::DepartmentLookup() |
53 | +{ |
54 | +} |
55 | + |
56 | +void DepartmentLookup::rebuild(const Department::SPtr& dept) |
57 | +{ |
58 | + departments[dept->id()] = dept; |
59 | + for (auto const& subdep: dept->sub_departments()) |
60 | + { |
61 | + parent_lut[subdep->id()] = dept; |
62 | + rebuild(subdep); |
63 | + } |
64 | +} |
65 | + |
66 | +void DepartmentLookup::rebuild(const std::list<Department::SPtr>& root_departments) |
67 | +{ |
68 | + parent_lut.clear(); |
69 | + departments.clear(); |
70 | + for (auto const& dep: root_departments) |
71 | + { |
72 | + rebuild(dep); |
73 | + } |
74 | +} |
75 | + |
76 | +Department::SPtr DepartmentLookup::get_parent(const std::string& department_id) const |
77 | +{ |
78 | + auto it = parent_lut.find(department_id); |
79 | + if (it != parent_lut.end()) |
80 | + { |
81 | + return it->second; |
82 | + } |
83 | + return Department::SPtr(nullptr); |
84 | +} |
85 | + |
86 | +Department::SPtr DepartmentLookup::get_department_info(const std::string& department_id) const |
87 | +{ |
88 | + auto it = departments.find(department_id); |
89 | + if (it != departments.end()) |
90 | + { |
91 | + return it->second; |
92 | + } |
93 | + return nullptr; |
94 | +} |
95 | + |
96 | +int DepartmentLookup::size() const |
97 | +{ |
98 | + return parent_lut.size(); |
99 | +} |
100 | + |
101 | +} |
102 | |
103 | === added file 'scope/click/department-lookup.h' |
104 | --- scope/click/department-lookup.h 1970-01-01 00:00:00 +0000 |
105 | +++ scope/click/department-lookup.h 2014-05-14 20:14:25 +0000 |
106 | @@ -0,0 +1,58 @@ |
107 | +/* |
108 | + * Copyright (C) 2014 Canonical Ltd. |
109 | + * |
110 | + * This program is free software: you can redistribute it and/or modify it |
111 | + * under the terms of the GNU General Public License version 3, as published |
112 | + * by the Free Software Foundation. |
113 | + * |
114 | + * This program is distributed in the hope that it will be useful, but |
115 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
116 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
117 | + * PURPOSE. See the GNU General Public License for more details. |
118 | + * |
119 | + * You should have received a copy of the GNU General Public License along |
120 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
121 | + * |
122 | + * In addition, as a special exception, the copyright holders give |
123 | + * permission to link the code of portions of this program with the |
124 | + * OpenSSL library under certain conditions as described in each |
125 | + * individual source file, and distribute linked combinations |
126 | + * including the two. |
127 | + * You must obey the GNU General Public License in all respects |
128 | + * for all of the code used other than OpenSSL. If you modify |
129 | + * file(s) with this exception, you may extend this exception to your |
130 | + * version of the file(s), but you are not obligated to do so. If you |
131 | + * do not wish to do so, delete this exception statement from your |
132 | + * version. If you delete this exception statement from all source |
133 | + * files in the program, then also delete it here. |
134 | + */ |
135 | + |
136 | +#ifndef CLICK_DEPARTMENT_LOOKUP_H |
137 | +#define CLICK_DEPARTMENT_LOOKUP_H |
138 | + |
139 | +#include "departments.h" |
140 | +#include <string> |
141 | +#include <memory> |
142 | +#include <map> |
143 | + |
144 | +namespace click |
145 | +{ |
146 | + |
147 | +class DepartmentLookup |
148 | +{ |
149 | + public: |
150 | + DepartmentLookup(); |
151 | + void rebuild(const std::list<Department::SPtr>& root_departments); |
152 | + Department::SPtr get_parent(const std::string& department_id) const; |
153 | + Department::SPtr get_department_info(const std::string& department_id) const; |
154 | + int size() const; |
155 | + |
156 | + private: |
157 | + void rebuild(const Department::SPtr& dept); |
158 | + std::map<std::string, Department::SPtr> parent_lut; |
159 | + std::map<std::string, Department::SPtr> departments; |
160 | +}; |
161 | + |
162 | +} |
163 | + |
164 | +#endif |
165 | |
166 | === added file 'scope/click/departments.cpp' |
167 | --- scope/click/departments.cpp 1970-01-01 00:00:00 +0000 |
168 | +++ scope/click/departments.cpp 2014-05-14 20:14:25 +0000 |
169 | @@ -0,0 +1,152 @@ |
170 | +/* |
171 | + * Copyright (C) 2014 Canonical Ltd. |
172 | + * |
173 | + * This program is free software: you can redistribute it and/or modify it |
174 | + * under the terms of the GNU General Public License version 3, as published |
175 | + * by the Free Software Foundation. |
176 | + * |
177 | + * This program is distributed in the hope that it will be useful, but |
178 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
179 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
180 | + * PURPOSE. See the GNU General Public License for more details. |
181 | + * |
182 | + * You should have received a copy of the GNU General Public License along |
183 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
184 | + * |
185 | + * In addition, as a special exception, the copyright holders give |
186 | + * permission to link the code of portions of this program with the |
187 | + * OpenSSL library under certain conditions as described in each |
188 | + * individual source file, and distribute linked combinations |
189 | + * including the two. |
190 | + * You must obey the GNU General Public License in all respects |
191 | + * for all of the code used other than OpenSSL. If you modify |
192 | + * file(s) with this exception, you may extend this exception to your |
193 | + * version of the file(s), but you are not obligated to do so. If you |
194 | + * do not wish to do so, delete this exception statement from your |
195 | + * version. If you delete this exception statement from all source |
196 | + * files in the program, then also delete it here. |
197 | + */ |
198 | + |
199 | +#include "departments.h" |
200 | +#include <iostream> |
201 | + |
202 | +namespace click |
203 | +{ |
204 | + |
205 | +Department::Department(const std::string& id, const std::string& name) |
206 | + : id_(id), |
207 | + name_(name), |
208 | + has_children_flag_(false) |
209 | +{ |
210 | +} |
211 | + |
212 | +Department::Department(const std::string& id, const std::string &name, bool has_children) |
213 | + : id_(id), |
214 | + name_(name), |
215 | + has_children_flag_(has_children) |
216 | +{ |
217 | +} |
218 | + |
219 | +std::string Department::id() const |
220 | +{ |
221 | + return id_; |
222 | +} |
223 | + |
224 | +std::string Department::name() const |
225 | +{ |
226 | + return name_; |
227 | +} |
228 | + |
229 | +bool Department::has_children_flag() const |
230 | +{ |
231 | + return has_children_flag_; |
232 | +} |
233 | + |
234 | +void Department::set_subdepartments(const std::list<Department::SPtr>& deps) |
235 | +{ |
236 | + sub_departments_ = deps; |
237 | +} |
238 | + |
239 | +std::list<Department::SPtr> Department::sub_departments() const |
240 | +{ |
241 | + return sub_departments_; |
242 | +} |
243 | + |
244 | +std::list<Department::SPtr> Department::from_json_node(const Json::Value& node) |
245 | +{ |
246 | + std::list<Department::SPtr> deps; |
247 | + |
248 | + for (uint i = 0; i < node.size(); i++) |
249 | + { |
250 | + auto const item = node[i]; |
251 | + if (item.isObject() && item.isMember(Department::JsonKeys::name)) |
252 | + { |
253 | + auto name = item[Department::JsonKeys::name].asString(); |
254 | + const bool has_children = item.isMember(Department::JsonKeys::has_children) ? item[Department::JsonKeys::has_children].asBool() : false; |
255 | + auto dep = std::make_shared<Department>(name, name, has_children); //FIXME: id |
256 | + if (item.isObject() && item.isMember(Department::JsonKeys::embedded)) |
257 | + { |
258 | + auto const emb = item[Department::JsonKeys::embedded]; |
259 | + if (emb.isObject() && emb.isMember(Department::JsonKeys::department)) |
260 | + { |
261 | + auto const ditem = emb[Department::JsonKeys::department]; |
262 | + auto const subdeps = from_json_node(ditem); |
263 | + dep->set_subdepartments(subdeps); |
264 | + } |
265 | + } |
266 | + deps.push_back(dep); |
267 | + } |
268 | + } |
269 | + |
270 | + return deps; |
271 | +} |
272 | + |
273 | +std::list<Department::SPtr> Department::from_json_root_node(const Json::Value& root) |
274 | +{ |
275 | + if (root.isObject() && root.isMember(Department::JsonKeys::embedded)) |
276 | + { |
277 | + auto const emb = root[Department::JsonKeys::embedded]; |
278 | + if (emb.isObject() && emb.isMember(Department::JsonKeys::department)) |
279 | + { |
280 | + auto const ditem = emb[Department::JsonKeys::department]; |
281 | + return from_json_node(ditem); |
282 | + } |
283 | + } |
284 | + |
285 | + return std::list<Department::SPtr>(); |
286 | +} |
287 | + |
288 | +std::list<Department::SPtr> Department::from_json(const std::string& json) |
289 | +{ |
290 | + Json::Reader reader; |
291 | + Json::Value root; |
292 | + |
293 | + try |
294 | + { |
295 | + if (!reader.parse(json, root)) { |
296 | + throw std::runtime_error(reader.getFormattedErrorMessages()); |
297 | + } |
298 | + |
299 | + if (root.isObject() && root.isMember(Department::JsonKeys::embedded)) |
300 | + { |
301 | + auto const emb = root[Department::JsonKeys::embedded]; |
302 | + if (emb.isObject() && emb.isMember(Department::JsonKeys::department)) |
303 | + { |
304 | + auto const ditem = emb[Department::JsonKeys::department]; |
305 | + return from_json_node(ditem); |
306 | + } |
307 | + } |
308 | + } |
309 | + catch (const std::exception& e) |
310 | + { |
311 | + std::cerr << "Error parsing departments: " << e.what() << std::endl; |
312 | + } |
313 | + catch (...) |
314 | + { |
315 | + std::cerr << "Unknown error when parsing departments" << std::endl; |
316 | + } |
317 | + |
318 | + return std::list<Department::SPtr>(); |
319 | +} |
320 | + |
321 | +} |
322 | |
323 | === added file 'scope/click/departments.h' |
324 | --- scope/click/departments.h 1970-01-01 00:00:00 +0000 |
325 | +++ scope/click/departments.h 2014-05-14 20:14:25 +0000 |
326 | @@ -0,0 +1,78 @@ |
327 | +/* |
328 | + * Copyright (C) 2014 Canonical Ltd. |
329 | + * |
330 | + * This program is free software: you can redistribute it and/or modify it |
331 | + * under the terms of the GNU General Public License version 3, as published |
332 | + * by the Free Software Foundation. |
333 | + * |
334 | + * This program is distributed in the hope that it will be useful, but |
335 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
336 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
337 | + * PURPOSE. See the GNU General Public License for more details. |
338 | + * |
339 | + * You should have received a copy of the GNU General Public License along |
340 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
341 | + * |
342 | + * In addition, as a special exception, the copyright holders give |
343 | + * permission to link the code of portions of this program with the |
344 | + * OpenSSL library under certain conditions as described in each |
345 | + * individual source file, and distribute linked combinations |
346 | + * including the two. |
347 | + * You must obey the GNU General Public License in all respects |
348 | + * for all of the code used other than OpenSSL. If you modify |
349 | + * file(s) with this exception, you may extend this exception to your |
350 | + * version of the file(s), but you are not obligated to do so. If you |
351 | + * do not wish to do so, delete this exception statement from your |
352 | + * version. If you delete this exception statement from all source |
353 | + * files in the program, then also delete it here. |
354 | + */ |
355 | + |
356 | +#ifndef CLICK_DEPARTMENTS_H |
357 | +#define CLICK_DEPARTMENTS_H |
358 | + |
359 | +#include <string> |
360 | +#include <list> |
361 | +#include <memory> |
362 | +#include <json/json.h> |
363 | + |
364 | +namespace click |
365 | +{ |
366 | + |
367 | +class Department |
368 | +{ |
369 | + public: |
370 | + typedef std::shared_ptr<Department> SPtr; |
371 | + typedef std::shared_ptr<Department const> SCPtr; |
372 | + |
373 | + struct JsonKeys |
374 | + { |
375 | + JsonKeys() = delete; |
376 | + constexpr static const char* name {"name"}; |
377 | + constexpr static const char* embedded {"_embedded"}; |
378 | + constexpr static const char* department {"clickindex:department"}; |
379 | + constexpr static const char* has_children {"has_children"}; |
380 | + }; |
381 | + |
382 | + Department(const std::string &id, const std::string &name); |
383 | + Department(const std::string &id, const std::string &name, bool has_children); |
384 | + std::string id() const; |
385 | + std::string name() const; |
386 | + bool has_children_flag() const; |
387 | + void set_subdepartments(const std::list<Department::SPtr>& deps); |
388 | + std::list<Department::SPtr> sub_departments() const; |
389 | + static std::list<Department::SPtr> from_json(const std::string& json); |
390 | + static std::list<Department::SPtr> from_json_root_node(const Json::Value& val); |
391 | + |
392 | + private: |
393 | + static std::list<Department::SPtr> from_json_node(const Json::Value& val); |
394 | + std::string id_; |
395 | + std::string name_; |
396 | + bool has_children_flag_; |
397 | + std::list<Department::SPtr> sub_departments_; |
398 | +}; |
399 | + |
400 | +typedef std::list<Department::SPtr> DepartmentList; |
401 | + |
402 | +} |
403 | + |
404 | +#endif |
405 | |
406 | === modified file 'scope/click/index.cpp' |
407 | --- scope/click/index.cpp 2014-05-14 20:14:25 +0000 |
408 | +++ scope/click/index.cpp 2014-05-14 20:14:25 +0000 |
409 | @@ -87,11 +87,15 @@ |
410 | |
411 | } |
412 | |
413 | -std::string Index::build_index_query(const std::string& query) |
414 | +std::string Index::build_index_query(const std::string& query, const std::string& department) |
415 | { |
416 | std::stringstream result; |
417 | |
418 | result << query; |
419 | + if (!department.empty()) { |
420 | + result << ",department:" << department; |
421 | + } |
422 | + |
423 | return result.str(); |
424 | } |
425 | |
426 | @@ -109,10 +113,10 @@ |
427 | }; |
428 | } |
429 | |
430 | -click::web::Cancellable Index::search (const std::string& query, std::function<void(click::PackageList)> callback) |
431 | +click::web::Cancellable Index::search (const std::string& query, const std::string& department, std::function<void(click::PackageList, click::DepartmentList)> callback) |
432 | { |
433 | click::web::CallParams params; |
434 | - const std::string built_query(build_index_query(query)); |
435 | + const std::string built_query(build_index_query(query, department)); |
436 | params.add(click::QUERY_ARGNAME, built_query.c_str()); |
437 | QSharedPointer<click::web::Response> response(client->call( |
438 | get_base_url() + click::SEARCH_PATH, "GET", false, build_headers(), "", params)); |
439 | @@ -122,22 +126,52 @@ |
440 | Json::Value root; |
441 | |
442 | click::PackageList pl; |
443 | + click::DepartmentList depts; |
444 | if (reader.parse(reply.toUtf8().constData(), root)) { |
445 | pl = click::package_list_from_json_node(root); |
446 | qDebug() << "found packages:" << pl.size(); |
447 | + depts = click::Department::from_json_root_node(root); |
448 | } |
449 | - callback(pl); |
450 | + callback(pl, depts); |
451 | }); |
452 | QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) { |
453 | qDebug() << "No packages found due to network error"; |
454 | click::PackageList pl; |
455 | + click::DepartmentList depts; //TODO |
456 | qDebug() << "calling callback"; |
457 | - callback(pl); |
458 | + callback(pl, depts); |
459 | qDebug() << " ...Done!"; |
460 | }); |
461 | return click::web::Cancellable(response); |
462 | } |
463 | |
464 | +click::web::Cancellable Index::bootstrap(std::function<void(const click::DepartmentList&, Error)> callback) |
465 | +{ |
466 | + click::web::CallParams params; |
467 | + QSharedPointer<click::web::Response> response(client->call( |
468 | + get_base_url() + click::BOOTSTRAP_PATH, "GET", false, build_headers(), "", params)); |
469 | + |
470 | + QObject::connect(response.data(), &click::web::Response::finished, [=](QString reply) { |
471 | + qDebug() << "bootstrap request finished"; |
472 | + Json::Reader reader; |
473 | + Json::Value root; |
474 | + |
475 | + click::DepartmentList depts; |
476 | + if (reader.parse(reply.toUtf8().constData(), root)) { |
477 | + depts = Department::from_json_root_node(root); |
478 | + // TODO: highlights |
479 | + } |
480 | + callback(depts, click::Index::Error::NoError); |
481 | + }); |
482 | + QObject::connect(response.data(), &click::web::Response::error, [=](QString /*description*/) { |
483 | + qWarning() << "bootstrap call failed due to network error"; |
484 | + const click::DepartmentList depts; |
485 | + qDebug() << "bootstrap: calling callback"; |
486 | + callback(depts, click::Index::Error::NetworkError); |
487 | + }); |
488 | + return click::web::Cancellable(response); |
489 | +} |
490 | + |
491 | click::web::Cancellable Index::get_details (const std::string& package_name, std::function<void(PackageDetails, click::Index::Error)> callback) |
492 | { |
493 | QSharedPointer<click::web::Response> response = client->call |
494 | |
495 | === modified file 'scope/click/index.h' |
496 | --- scope/click/index.h 2014-05-14 20:14:25 +0000 |
497 | +++ scope/click/index.h 2014-05-14 20:14:25 +0000 |
498 | @@ -37,6 +37,7 @@ |
499 | #include "configuration.h" |
500 | #include "package.h" |
501 | #include "webclient.h" |
502 | +#include "departments.h" |
503 | |
504 | |
505 | namespace click { |
506 | @@ -46,6 +47,7 @@ |
507 | const std::string SEARCH_BASE_URL_ENVVAR = "U1_SEARCH_BASE_URL"; |
508 | const std::string SEARCH_BASE_URL = "https://search.apps.ubuntu.com/"; |
509 | const std::string SEARCH_PATH = "api/v1/search"; |
510 | +const std::string BOOTSTRAP_PATH = "api/v1/departments"; |
511 | const std::string SUPPORTED_FRAMEWORKS = "framework:ubuntu-sdk-13.10"; |
512 | const std::string QUERY_ARGNAME = "q"; |
513 | const std::string ARCHITECTURE = "architecture:"; |
514 | @@ -63,15 +65,16 @@ |
515 | protected: |
516 | QSharedPointer<web::Client> client; |
517 | QSharedPointer<Configuration> configuration; |
518 | - virtual std::string build_index_query(const std::string& query); |
519 | + virtual std::string build_index_query(const std::string& query, const std::string& department); |
520 | virtual std::map<std::string, std::string> build_headers(); |
521 | |
522 | public: |
523 | enum class Error {NoError, CredentialsError, NetworkError}; |
524 | Index(const QSharedPointer<click::web::Client>& client, |
525 | const QSharedPointer<Configuration> configuration=QSharedPointer<Configuration>(new Configuration())); |
526 | - virtual click::web::Cancellable search (const std::string& query, std::function<void(PackageList)> callback); |
527 | + virtual click::web::Cancellable search (const std::string& query, const std::string& department, std::function<void(PackageList, DepartmentList)> callback); |
528 | virtual click::web::Cancellable get_details(const std::string& package_name, std::function<void(PackageDetails, Error)> callback); |
529 | + virtual click::web::Cancellable bootstrap(std::function<void(const DepartmentList&, Error)> callback); |
530 | virtual ~Index(); |
531 | |
532 | static std::string get_base_url (); |
533 | |
534 | === modified file 'scope/click/query.cpp' |
535 | --- scope/click/query.cpp 2014-05-14 20:14:25 +0000 |
536 | +++ scope/click/query.cpp 2014-05-14 20:14:25 +0000 |
537 | @@ -37,6 +37,7 @@ |
538 | #include <unity/scopes/Annotation.h> |
539 | #include <unity/scopes/CategoryRenderer.h> |
540 | #include <unity/scopes/CategorisedResult.h> |
541 | +#include <unity/scopes/Department.h> |
542 | #include <unity/scopes/CannedQuery.h> |
543 | #include <unity/scopes/SearchReply.h> |
544 | #include <unity/scopes/SearchMetadata.h> |
545 | @@ -117,20 +118,22 @@ |
546 | |
547 | struct click::Query::Private |
548 | { |
549 | - Private(const unity::scopes::CannedQuery& query, click::Index& index, const scopes::SearchMetadata& metadata) |
550 | + Private(const unity::scopes::CannedQuery& query, click::Index& index, click::DepartmentLookup& depts, const scopes::SearchMetadata& metadata) |
551 | : query(query), |
552 | index(index), |
553 | + department_lookup(depts), |
554 | meta(metadata) |
555 | { |
556 | } |
557 | unity::scopes::CannedQuery query; |
558 | click::Index& index; |
559 | + click::DepartmentLookup& department_lookup; |
560 | scopes::SearchMetadata meta; |
561 | click::web::Cancellable search_operation; |
562 | }; |
563 | |
564 | -click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata) |
565 | - : impl(new Private(query, index, metadata)) |
566 | +click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& depts, scopes::SearchMetadata const& metadata) |
567 | + : impl(new Private(query, index, depts, metadata)) |
568 | { |
569 | } |
570 | |
571 | @@ -183,6 +186,57 @@ |
572 | }); |
573 | } |
574 | |
575 | +unity::scopes::DepartmentList click::Query::populate_departments(const click::DepartmentList& depts, const std::string& current_dep_id) |
576 | +{ |
577 | + unity::scopes::DepartmentList departments; |
578 | + |
579 | + // create a list of subdepartments of current department |
580 | + foreach (auto d, depts) |
581 | + { |
582 | + unity::scopes::Department department(d->id(), impl->query, d->name()); |
583 | + if (d->has_children_flag()) |
584 | + { |
585 | + department.set_has_subdepartments(); |
586 | + } |
587 | + departments.push_back(department); |
588 | + } |
589 | + |
590 | + if (current_dep_id != "") |
591 | + { |
592 | + auto curr_dpt = impl->department_lookup.get_department_info(current_dep_id); |
593 | + if (curr_dpt != nullptr) |
594 | + { |
595 | + unity::scopes::Department cur(current_dep_id, impl->query, curr_dpt->name()); |
596 | + if (departments.size() > 0) // this may be a leaf department |
597 | + { |
598 | + cur.set_subdepartments(departments); |
599 | + } |
600 | + |
601 | + auto parent_info = impl->department_lookup.get_parent(current_dep_id); |
602 | + if (parent_info != nullptr) |
603 | + { |
604 | + unity::scopes::Department parent_dept(parent_info->id(), impl->query, parent_info->name()); |
605 | + parent_dept.set_subdepartments({cur}); |
606 | + return {parent_dept}; |
607 | + } |
608 | + else |
609 | + { |
610 | + unity::scopes::Department root_dept("", impl->query, _("All departments")); |
611 | + root_dept.set_subdepartments({cur}); |
612 | + return {root_dept}; |
613 | + } |
614 | + } |
615 | + else |
616 | + { |
617 | + qWarning() << "Unknown department:" << QString::fromStdString(current_dep_id); |
618 | + } |
619 | + } |
620 | + |
621 | + unity::scopes::Department root_dept("", impl->query, _("All departments")); |
622 | + root_dept.set_subdepartments(departments); |
623 | + return unity::scopes::DepartmentList({root_dept}); |
624 | +} |
625 | + |
626 | void click::Query::add_available_apps(scopes::SearchReplyProxy const& searchReply, |
627 | const std::set<std::string>& locallyInstalledApps, |
628 | const std::string& categoryTemplate) |
629 | @@ -195,11 +249,20 @@ |
630 | return; |
631 | } |
632 | |
633 | + assert(searchReply); |
634 | + |
635 | run_under_qt([=]() |
636 | { |
637 | - auto search_cb = [this, searchReply, category, locallyInstalledApps](PackageList packages) { |
638 | + auto search_cb = [this, searchReply, category, locallyInstalledApps](PackageList packages, DepartmentList depts) { |
639 | qDebug("search callback"); |
640 | |
641 | + // handle departments data |
642 | + auto click_depts = populate_departments(depts, impl->query.department_id()); |
643 | + if (click_depts.size() > 0) |
644 | + { |
645 | + searchReply->register_departments(click_depts, impl->query.department_id()); |
646 | + } |
647 | + |
648 | // handle packages data |
649 | foreach (auto p, packages) { |
650 | qDebug() << "pushing result" << QString::fromStdString(p.name); |
651 | @@ -226,8 +289,29 @@ |
652 | this->finished(searchReply); |
653 | }; |
654 | |
655 | + if (impl->department_lookup.size() == 0) |
656 | + { |
657 | + qDebug() << "performing bootstrap request"; |
658 | + impl->search_operation = impl->index.bootstrap([this, search_cb, searchReply](const DepartmentList& deps, click::Index::Error error) { |
659 | + if (error == click::Index::Error::NoError) |
660 | + { |
661 | + qDebug() << "bootstrap request completed"; |
662 | + impl->department_lookup.rebuild(deps); |
663 | + qDebug() << "Total number of departments:" << impl->department_lookup.size(); |
664 | + } |
665 | + else |
666 | + { |
667 | + qWarning() << "bootstrap request failed"; |
668 | + } |
669 | + qDebug() << "starting search of" << QString::fromStdString(impl->query.query_string()); |
670 | + impl->search_operation = impl->index.search(impl->query.query_string(), impl->query.department_id(), search_cb); |
671 | + }); |
672 | + } |
673 | + else |
674 | + { |
675 | qDebug() << "starting search of" << QString::fromStdString(impl->query.query_string()); |
676 | - impl->search_operation = impl->index.search(impl->query.query_string(), search_cb); |
677 | + impl->search_operation = impl->index.search(impl->query.query_string(), impl->query.department_id(), search_cb); |
678 | + } |
679 | }); |
680 | } |
681 | |
682 | |
683 | === modified file 'scope/click/query.h' |
684 | --- scope/click/query.h 2014-05-14 20:14:25 +0000 |
685 | +++ scope/click/query.h 2014-05-14 20:14:25 +0000 |
686 | @@ -32,18 +32,21 @@ |
687 | |
688 | |
689 | #include <unity/scopes/SearchQueryBase.h> |
690 | +#include <unity/scopes/Department.h> |
691 | |
692 | namespace scopes = unity::scopes; |
693 | |
694 | #include <QSharedPointer> |
695 | #include <set> |
696 | |
697 | +#include "department-lookup.h" |
698 | |
699 | namespace click |
700 | { |
701 | |
702 | class Application; |
703 | class Index; |
704 | +class DepartmentLookup; |
705 | |
706 | class Query : public scopes::SearchQueryBase |
707 | { |
708 | @@ -70,7 +73,7 @@ |
709 | constexpr static const char* VERSION{"version"}; |
710 | }; |
711 | |
712 | - Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata); |
713 | + Query(unity::scopes::CannedQuery const& query, click::Index& index, click::DepartmentLookup& dept_lookup, scopes::SearchMetadata const& metadata); |
714 | virtual ~Query(); |
715 | |
716 | virtual void cancelled() override; |
717 | @@ -78,6 +81,7 @@ |
718 | virtual void run(scopes::SearchReplyProxy const& reply) override; |
719 | |
720 | protected: |
721 | + virtual unity::scopes::DepartmentList populate_departments(const click::DepartmentList& depts, const std::string& current_department_id); |
722 | virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const std::set<std::string> &locallyInstalledApps, const std::string &category); |
723 | virtual bool push_result(const scopes::SearchReplyProxy &searchReply, scopes::CategorisedResult const& res); |
724 | virtual void finished(const scopes::SearchReplyProxy &searchReply); |
725 | |
726 | === modified file 'scope/click/scope.cpp' |
727 | --- scope/click/scope.cpp 2014-05-14 20:14:25 +0000 |
728 | +++ scope/click/scope.cpp 2014-05-14 20:14:25 +0000 |
729 | @@ -33,6 +33,7 @@ |
730 | #include "preview.h" |
731 | #include "network_access_manager.h" |
732 | #include "interface.h" |
733 | +#include "department-lookup.h" |
734 | #include "scope_activation.h" |
735 | |
736 | #include <QSharedPointer> |
737 | @@ -55,6 +56,7 @@ |
738 | nam.reset(new click::network::AccessManager()); |
739 | client.reset(new click::web::Client(nam)); |
740 | index.reset(new click::Index(client)); |
741 | + depts.reset(new click::DepartmentLookup()); |
742 | } |
743 | |
744 | click::Scope::~Scope() |
745 | @@ -88,7 +90,7 @@ |
746 | |
747 | scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata) |
748 | { |
749 | - return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, metadata)); |
750 | + return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, *depts, metadata)); |
751 | } |
752 | |
753 | |
754 | |
755 | === modified file 'scope/click/scope.h' |
756 | --- scope/click/scope.h 2014-04-29 03:17:38 +0000 |
757 | +++ scope/click/scope.h 2014-05-14 20:14:25 +0000 |
758 | @@ -30,6 +30,7 @@ |
759 | #ifndef CLICK_SCOPE_H |
760 | #define CLICK_SCOPE_H |
761 | |
762 | +#include <memory> |
763 | #include <unity/scopes/ScopeBase.h> |
764 | #include <unity/scopes/QueryBase.h> |
765 | #include <unity/scopes/ActivationQueryBase.h> |
766 | @@ -42,6 +43,9 @@ |
767 | |
768 | namespace click |
769 | { |
770 | + |
771 | +class DepartmentLookup; |
772 | + |
773 | class Scope : public scopes::ScopeBase |
774 | { |
775 | public: |
776 | @@ -63,6 +67,7 @@ |
777 | QSharedPointer<click::network::AccessManager> nam; |
778 | QSharedPointer<click::web::Client> client; |
779 | QSharedPointer<click::Index> index; |
780 | + std::shared_ptr<click::DepartmentLookup> depts; |
781 | |
782 | std::string installApplication(unity::scopes::Result const& result); |
783 | }; |
784 | |
785 | === modified file 'scope/tests/CMakeLists.txt' |
786 | --- scope/tests/CMakeLists.txt 2014-05-13 19:32:29 +0000 |
787 | +++ scope/tests/CMakeLists.txt 2014-05-14 20:14:25 +0000 |
788 | @@ -35,6 +35,7 @@ |
789 | test_reviews.cpp |
790 | test_smartconnect.cpp |
791 | test_webclient.cpp |
792 | + test_departments.cpp |
793 | |
794 | ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp |
795 | ) |
796 | @@ -68,4 +69,4 @@ |
797 | |
798 | add_subdirectory(integration) |
799 | add_subdirectory(download_manager_tool) |
800 | -add_subdirectory(click_interface_tool) |
801 | \ No newline at end of file |
802 | +add_subdirectory(click_interface_tool) |
803 | |
804 | === modified file 'scope/tests/fake_json.h' |
805 | --- scope/tests/fake_json.h 2014-05-14 20:14:25 +0000 |
806 | +++ scope/tests/fake_json.h 2014-05-14 20:14:25 +0000 |
807 | @@ -142,6 +142,102 @@ |
808 | } |
809 | )foo"; |
810 | |
811 | +const std::string FAKE_JSON_DEPARTMENTS_ONLY = R"( |
812 | + { |
813 | + "_links": { |
814 | + "self": { |
815 | + "href": "https://search.apps.ubuntu.com/api/v1/departments" |
816 | + }, |
817 | + "curies": [ |
818 | + { |
819 | + "name": "clickindex", |
820 | + "href": "https://search.apps.ubuntu.com/docs/v1/relations.html{#rel}", |
821 | + "templated": true |
822 | + } |
823 | + ] |
824 | + }, |
825 | + "_embedded": { |
826 | + "clickindex:department": [ |
827 | + { |
828 | + "name": "Games", |
829 | + "_links": { |
830 | + "self": { |
831 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Games" |
832 | + } |
833 | + }, |
834 | + "_embedded": { |
835 | + "clickindex:department": [ |
836 | + { |
837 | + "name": "Board Games", |
838 | + "_links": { |
839 | + "self": { |
840 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Games/Board+Games" |
841 | + } |
842 | + } |
843 | + } |
844 | + ] |
845 | + } |
846 | + }, |
847 | + { |
848 | + "name": "Graphics", |
849 | + "_links": { |
850 | + "self": { |
851 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics" |
852 | + } |
853 | + }, |
854 | + "_embedded": { |
855 | + "clickindex:department": [ |
856 | + { |
857 | + "name": "Drawing", |
858 | + "_links": { |
859 | + "self": { |
860 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Graphics/Drawing" |
861 | + } |
862 | + } |
863 | + } |
864 | + ] |
865 | + } |
866 | + }, |
867 | + { |
868 | + "name": "Internet", |
869 | + "_links": { |
870 | + "self": { |
871 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet" |
872 | + } |
873 | + }, |
874 | + "_embedded": { |
875 | + "clickindex:department": [ |
876 | + { |
877 | + "name": "Chat", |
878 | + "_links": { |
879 | + "self": { |
880 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Chat" |
881 | + } |
882 | + } |
883 | + }, |
884 | + { |
885 | + "name": "Mail", |
886 | + "_links": { |
887 | + "self": { |
888 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Mail" |
889 | + } |
890 | + } |
891 | + }, |
892 | + { |
893 | + "name": "Web Browsers", |
894 | + "_links": { |
895 | + "self": { |
896 | + "href": "https://search.apps.ubuntu.com/api/v1/departments/Internet/Web+Browsers" |
897 | + } |
898 | + } |
899 | + } |
900 | + ] |
901 | + } |
902 | + } |
903 | + ] |
904 | + } |
905 | +})"; |
906 | + |
907 | const std::string FAKE_JSON_MANIFEST_REMOVABLE = R"foo( |
908 | { |
909 | "_removable": 1, |
910 | |
911 | === modified file 'scope/tests/integration/webclient_integration.cpp' |
912 | --- scope/tests/integration/webclient_integration.cpp 2014-04-29 03:17:38 +0000 |
913 | +++ scope/tests/integration/webclient_integration.cpp 2014-05-14 20:14:25 +0000 |
914 | @@ -30,6 +30,7 @@ |
915 | #include <click/network_access_manager.h> |
916 | #include <click/webclient.h> |
917 | #include <click/index.h> |
918 | +#include <click/departments.h> |
919 | |
920 | #include <QCoreApplication> |
921 | #include <QDebug> |
922 | @@ -102,7 +103,8 @@ |
923 | new click::web::Client(namPtr)); |
924 | click::Index index(clientPtr); |
925 | click::PackageList packages; |
926 | - index.search("qr,architecture:armhf", [&, this](click::PackageList found_packages){ |
927 | + index.search("qr,architecture:armhf", "", [&, this](click::PackageList found_packages, click::DepartmentList){ |
928 | + //TODO departments |
929 | packages = found_packages; |
930 | Quit(); |
931 | }); |
932 | |
933 | === modified file 'scope/tests/mock_webclient.h' |
934 | --- scope/tests/mock_webclient.h 2014-04-29 03:17:38 +0000 |
935 | +++ scope/tests/mock_webclient.h 2014-05-14 20:14:25 +0000 |
936 | @@ -86,7 +86,7 @@ |
937 | const click::web::CallParams& params)); |
938 | QSharedPointer<click::web::Response> call( |
939 | const std::string& iri, |
940 | - const click::web::CallParams& params=click::web::CallParams()) { |
941 | + const click::web::CallParams& params=click::web::CallParams()) override { |
942 | return callImpl(iri, "GET", false, |
943 | std::map<std::string, std::string>(), "", params); |
944 | } |
945 | @@ -96,7 +96,7 @@ |
946 | bool sign = false, |
947 | const std::map<std::string, std::string>& headers = std::map<std::string, std::string>(), |
948 | const std::string& data = "", |
949 | - const click::web::CallParams& params=click::web::CallParams()) { |
950 | + const click::web::CallParams& params=click::web::CallParams()) override { |
951 | return callImpl(iri, method, sign, headers, data, params); |
952 | } |
953 | }; |
954 | |
955 | === removed file 'scope/tests/test_data.cpp' |
956 | === added file 'scope/tests/test_departments.cpp' |
957 | --- scope/tests/test_departments.cpp 1970-01-01 00:00:00 +0000 |
958 | +++ scope/tests/test_departments.cpp 2014-05-14 20:14:25 +0000 |
959 | @@ -0,0 +1,108 @@ |
960 | +/* |
961 | + * Copyright (C) 2014 Canonical Ltd. |
962 | + * |
963 | + * This program is free software: you can redistribute it and/or modify it |
964 | + * under the terms of the GNU General Public License version 3, as published |
965 | + * by the Free Software Foundation. |
966 | + * |
967 | + * This program is distributed in the hope that it will be useful, but |
968 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
969 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
970 | + * PURPOSE. See the GNU General Public License for more details. |
971 | + * |
972 | + * You should have received a copy of the GNU General Public License along |
973 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
974 | + * |
975 | + * In addition, as a special exception, the copyright holders give |
976 | + * permission to link the code of portions of this program with the |
977 | + * OpenSSL library under certain conditions as described in each |
978 | + * individual source file, and distribute linked combinations |
979 | + * including the two. |
980 | + * You must obey the GNU General Public License in all respects |
981 | + * for all of the code used other than OpenSSL. If you modify |
982 | + * file(s) with this exception, you may extend this exception to your |
983 | + * version of the file(s), but you are not obligated to do so. If you |
984 | + * do not wish to do so, delete this exception statement from your |
985 | + * version. If you delete this exception statement from all source |
986 | + * files in the program, then also delete it here. |
987 | + */ |
988 | + |
989 | +#include <gtest/gtest.h> |
990 | +#include "fake_json.h" |
991 | +#include "click/departments.h" |
992 | +#include "click/department-lookup.h" |
993 | + |
994 | +class DepartmentsTest : public ::testing::Test |
995 | +{ |
996 | + protected: |
997 | + void SetUp() override |
998 | + { |
999 | + } |
1000 | +}; |
1001 | + |
1002 | +TEST_F(DepartmentsTest, testParsing) |
1003 | +{ |
1004 | + const std::string jsonstr(FAKE_JSON_DEPARTMENTS_ONLY); |
1005 | + auto depts = click::Department::from_json(jsonstr); |
1006 | + EXPECT_EQ(3u, depts.size()); |
1007 | + auto it = depts.cbegin(); |
1008 | + { |
1009 | + auto dep = *it; |
1010 | + EXPECT_EQ("Games", dep->id()); |
1011 | + EXPECT_EQ("Games", dep->name()); |
1012 | + EXPECT_FALSE(dep->has_children_flag()); |
1013 | + auto subdepts = dep->sub_departments(); |
1014 | + EXPECT_EQ(1u, subdepts.size()); |
1015 | + auto sit = subdepts.cbegin(); |
1016 | + EXPECT_EQ("Board Games", (*sit)->name()); |
1017 | + } |
1018 | + { |
1019 | + ++it; |
1020 | + auto dep = *it; |
1021 | + EXPECT_EQ("Graphics", dep->id()); |
1022 | + EXPECT_EQ("Graphics", dep->name()); |
1023 | + EXPECT_FALSE(dep->has_children_flag()); |
1024 | + auto subdepts = dep->sub_departments(); |
1025 | + EXPECT_EQ(1u, subdepts.size()); |
1026 | + auto sit = subdepts.cbegin(); |
1027 | + EXPECT_EQ("Drawing", (*sit)->name()); |
1028 | + } |
1029 | + { |
1030 | + ++it; |
1031 | + auto dep = *it; |
1032 | + EXPECT_EQ("Internet", dep->id()); |
1033 | + EXPECT_EQ("Internet", dep->name()); |
1034 | + EXPECT_FALSE(dep->has_children_flag()); |
1035 | + auto subdepts = dep->sub_departments(); |
1036 | + EXPECT_EQ(3u, subdepts.size()); |
1037 | + auto sit = subdepts.cbegin(); |
1038 | + auto subdep = *sit; |
1039 | + EXPECT_EQ("Chat", subdep->name()); |
1040 | + subdep = *(++sit); |
1041 | + EXPECT_EQ("Mail", subdep->name()); |
1042 | + subdep = *(++sit); |
1043 | + EXPECT_EQ("Web Browsers", subdep->name()); |
1044 | + } |
1045 | +} |
1046 | + |
1047 | +TEST_F(DepartmentsTest, testLookup) |
1048 | +{ |
1049 | + auto dep_games = std::make_shared<click::Department>("games", "Games"); |
1050 | + auto dep_rpg = std::make_shared<click::Department>("rpg", "RPG"); |
1051 | + auto dep_strategy = std::make_shared<click::Department>("strategy", "Strategy"); |
1052 | + const std::list<click::Department::SPtr> departments {dep_rpg, dep_strategy}; |
1053 | + dep_games->set_subdepartments(departments); |
1054 | + |
1055 | + const std::list<click::Department::SPtr> root {dep_games}; |
1056 | + click::DepartmentLookup lut; |
1057 | + lut.rebuild(root); |
1058 | + |
1059 | + EXPECT_EQ(2u, lut.size()); |
1060 | + EXPECT_EQ("games", lut.get_parent("strategy")->id()); |
1061 | + EXPECT_EQ("games", lut.get_parent("rpg")->id()); |
1062 | + EXPECT_EQ(nullptr, lut.get_parent("games")); |
1063 | + |
1064 | + lut.rebuild(root); |
1065 | + EXPECT_EQ(2u, lut.size()); |
1066 | +} |
1067 | + |
1068 | |
1069 | === modified file 'scope/tests/test_index.cpp' |
1070 | --- scope/tests/test_index.cpp 2014-05-14 20:14:25 +0000 |
1071 | +++ scope/tests/test_index.cpp 2014-05-14 20:14:25 +0000 |
1072 | @@ -51,8 +51,8 @@ |
1073 | click::Index(client, configuration) |
1074 | { |
1075 | } |
1076 | - MOCK_METHOD1(build_index_query, std::string(const std::string&)); |
1077 | MOCK_METHOD0(build_headers, std::map<std::string, std::string>()); |
1078 | + MOCK_METHOD2(build_index_query, std::string(const std::string&, const std::string&)); |
1079 | }; |
1080 | |
1081 | class MockConfiguration : public click::Configuration { |
1082 | @@ -99,7 +99,7 @@ |
1083 | .Times(1) |
1084 | .WillOnce(Return(response)); |
1085 | |
1086 | - indexPtr->search("", [](click::PackageList) {}); |
1087 | + indexPtr->search("", "", [](click::PackageList, click::DepartmentList) {}); |
1088 | } |
1089 | |
1090 | TEST_F(IndexTest, testSearchSendsBuiltQueryAsParam) |
1091 | @@ -115,11 +115,11 @@ |
1092 | .Times(1) |
1093 | .WillOnce(Return(response)); |
1094 | |
1095 | - EXPECT_CALL(*indexPtr, build_index_query(FAKE_QUERY)) |
1096 | + EXPECT_CALL(*indexPtr, build_index_query(FAKE_QUERY, "")) |
1097 | .Times(1) |
1098 | .WillOnce(Return(FAKE_BUILT_QUERY)); |
1099 | |
1100 | - indexPtr->search(FAKE_QUERY, [](click::PackageList) {}); |
1101 | + indexPtr->search(FAKE_QUERY, "", [](click::PackageList, click::DepartmentList) {}); |
1102 | } |
1103 | |
1104 | TEST_F(IndexTest, testSearchSendsRightPath) |
1105 | @@ -132,7 +132,7 @@ |
1106 | .Times(1) |
1107 | .WillOnce(Return(response)); |
1108 | |
1109 | - indexPtr->search("", [](click::PackageList) {}); |
1110 | + indexPtr->search("", "", [](click::PackageList, click::DepartmentList) {}); |
1111 | } |
1112 | |
1113 | TEST_F(IndexTest, testSearchCallbackIsCalled) |
1114 | @@ -149,7 +149,7 @@ |
1115 | .WillOnce(Return(response)); |
1116 | EXPECT_CALL(*this, search_callback(_)).Times(1); |
1117 | |
1118 | - indexPtr->search("", [this](click::PackageList packages){ |
1119 | + indexPtr->search("", "", [this](click::PackageList packages, click::DepartmentList){ |
1120 | search_callback(packages); |
1121 | }); |
1122 | response->replyFinished(); |
1123 | @@ -170,7 +170,7 @@ |
1124 | click::PackageList empty_package_list; |
1125 | EXPECT_CALL(*this, search_callback(empty_package_list)).Times(1); |
1126 | |
1127 | - indexPtr->search("", [this](click::PackageList packages){ |
1128 | + indexPtr->search("", "", [this](click::PackageList packages, click::DepartmentList){ |
1129 | search_callback(packages); |
1130 | }); |
1131 | response->replyFinished(); |
1132 | @@ -199,7 +199,7 @@ |
1133 | }; |
1134 | EXPECT_CALL(*this, search_callback(single_package_list)).Times(1); |
1135 | |
1136 | - indexPtr->search("", [this](click::PackageList packages){ |
1137 | + indexPtr->search("", "", [this](click::PackageList packages, click::DepartmentList){ |
1138 | search_callback(packages); |
1139 | }); |
1140 | response->replyFinished(); |
1141 | @@ -214,7 +214,7 @@ |
1142 | .Times(1) |
1143 | .WillOnce(Return(response)); |
1144 | |
1145 | - auto search_operation = indexPtr->search("", [](click::PackageList) {}); |
1146 | + auto search_operation = indexPtr->search("", "", [](click::PackageList, click::DepartmentList) {}); |
1147 | EXPECT_CALL(reply.instance, abort()).Times(1); |
1148 | search_operation.cancel(); |
1149 | } |
1150 | @@ -233,7 +233,7 @@ |
1151 | .Times(1) |
1152 | .WillOnce(Return(response)); |
1153 | EXPECT_CALL(reply.instance, errorString()).Times(1).WillOnce(Return("fake error")); |
1154 | - indexPtr->search("", [this](click::PackageList packages){ |
1155 | + indexPtr->search("", "", [this](click::PackageList packages, click::DepartmentList){ |
1156 | search_callback(packages); |
1157 | }); |
1158 | |
1159 | |
1160 | === modified file 'scope/tests/test_query.cpp' |
1161 | --- scope/tests/test_query.cpp 2014-05-14 20:14:25 +0000 |
1162 | +++ scope/tests/test_query.cpp 2014-05-14 20:14:25 +0000 |
1163 | @@ -45,6 +45,7 @@ |
1164 | #include <unity/scopes/CannedQuery.h> |
1165 | #include <unity/scopes/ScopeBase.h> |
1166 | #include <unity/scopes/SearchReply.h> |
1167 | +#include <unity/scopes/testing/MockSearchReply.h> |
1168 | |
1169 | using namespace ::testing; |
1170 | |
1171 | @@ -56,30 +57,43 @@ |
1172 | |
1173 | class MockIndex : public click::Index { |
1174 | click::PackageList packages; |
1175 | + click::DepartmentList departments; |
1176 | + click::DepartmentList bootstrap_departments; |
1177 | public: |
1178 | - MockIndex(click::PackageList packages = click::PackageList()) |
1179 | + MockIndex(click::PackageList packages = click::PackageList(), |
1180 | + click::DepartmentList departments = click::DepartmentList(), |
1181 | + click::DepartmentList boot_departments = click::DepartmentList()) |
1182 | : Index(QSharedPointer<click::web::Client>()), |
1183 | - packages(packages) |
1184 | - { |
1185 | - |
1186 | - } |
1187 | - |
1188 | - click::web::Cancellable search(const std::string &query, std::function<void (click::PackageList)> callback) override |
1189 | - { |
1190 | - do_search(query, callback); |
1191 | - callback(packages); |
1192 | - return click::web::Cancellable(); |
1193 | - } |
1194 | - |
1195 | - MOCK_METHOD2(do_search, |
1196 | - void(const std::string&, |
1197 | - std::function<void(click::PackageList)>)); |
1198 | + packages(packages), |
1199 | + departments(departments), |
1200 | + bootstrap_departments(boot_departments) |
1201 | + { |
1202 | + |
1203 | + } |
1204 | + |
1205 | + click::web::Cancellable search(const std::string &query, const std::string& department, std::function<void (click::PackageList, click::DepartmentList)> callback) override |
1206 | + { |
1207 | + do_search(query, department, callback); |
1208 | + callback(packages, departments); |
1209 | + return click::web::Cancellable(); |
1210 | + } |
1211 | + |
1212 | + click::web::Cancellable bootstrap(std::function<void(const click::DepartmentList&, Error)> callback) override |
1213 | + { |
1214 | + callback(bootstrap_departments, click::Index::Error::NoError); |
1215 | + return click::web::Cancellable(); |
1216 | + } |
1217 | + |
1218 | + MOCK_METHOD3(do_search, |
1219 | + void(const std::string&, const std::string&, |
1220 | + std::function<void(click::PackageList, click::DepartmentList)>)); |
1221 | }; |
1222 | |
1223 | class MockQueryBase : public click::Query { |
1224 | public: |
1225 | MockQueryBase(const unity::scopes::CannedQuery& query, click::Index& index, |
1226 | - scopes::SearchMetadata const& metadata) : click::Query(query, index, metadata) |
1227 | + click::DepartmentLookup& depts, |
1228 | + scopes::SearchMetadata const& metadata) : click::Query(query, index, depts, metadata) |
1229 | { |
1230 | |
1231 | } |
1232 | @@ -93,7 +107,8 @@ |
1233 | class MockQuery : public MockQueryBase { |
1234 | public: |
1235 | MockQuery(const unity::scopes::CannedQuery& query, click::Index& index, |
1236 | - scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, metadata) |
1237 | + click::DepartmentLookup& depts, |
1238 | + scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, metadata) |
1239 | { |
1240 | |
1241 | } |
1242 | @@ -115,7 +130,8 @@ |
1243 | class MockQueryRun : public MockQueryBase { |
1244 | public: |
1245 | MockQueryRun(const unity::scopes::CannedQuery& query, click::Index& index, |
1246 | - scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, metadata) |
1247 | + click::DepartmentLookup& depts, |
1248 | + scopes::SearchMetadata const& metadata) : MockQueryBase(query, index, depts, metadata) |
1249 | { |
1250 | |
1251 | } |
1252 | @@ -143,12 +159,16 @@ |
1253 | TEST(QueryTest, testAddAvailableAppsCallsClickIndex) |
1254 | { |
1255 | MockIndex mock_index; |
1256 | + click::DepartmentLookup dept_lookup; |
1257 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1258 | std::set<std::string> no_installed_packages; |
1259 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1260 | - MockQuery q(query, mock_index, metadata); |
1261 | - EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(1); |
1262 | - scopes::SearchReplyProxy reply; |
1263 | + MockQuery q(query, mock_index, dept_lookup, metadata); |
1264 | + EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _)).Times(1); |
1265 | + |
1266 | + scopes::testing::MockSearchReply mock_reply; |
1267 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
1268 | + EXPECT_CALL(mock_reply, register_departments(_, _)).Times(1); |
1269 | |
1270 | scopes::CategoryRenderer renderer("{}"); |
1271 | auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1272 | @@ -162,17 +182,21 @@ |
1273 | {"name", "title", 0.0, "", ""} |
1274 | }; |
1275 | MockIndex mock_index(packages); |
1276 | + click::DepartmentLookup dept_lookup; |
1277 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1278 | std::set<std::string> no_installed_packages; |
1279 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1280 | - MockQuery q(query, mock_index, metadata); |
1281 | - EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1282 | + MockQuery q(query, mock_index, dept_lookup, metadata); |
1283 | + EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _)); |
1284 | |
1285 | scopes::CategoryRenderer renderer("{}"); |
1286 | auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1287 | EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
1288 | |
1289 | - scopes::SearchReplyProxy reply; |
1290 | + scopes::testing::MockSearchReply mock_reply; |
1291 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
1292 | + EXPECT_CALL(mock_reply, register_departments(_, _)).Times(1); |
1293 | + |
1294 | auto expected_title = packages.front().title; |
1295 | EXPECT_CALL(q, push_result(_, Property(&scopes::CategorisedResult::title, expected_title))); |
1296 | q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE); |
1297 | @@ -184,17 +208,20 @@ |
1298 | {"name", "title", 0.0, "", ""} |
1299 | }; |
1300 | MockIndex mock_index(packages); |
1301 | + click::DepartmentLookup dept_lookup; |
1302 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1303 | std::set<std::string> no_installed_packages; |
1304 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1305 | - MockQuery q(query, mock_index, metadata); |
1306 | - EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1307 | + MockQuery q(query, mock_index, dept_lookup, metadata); |
1308 | + EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _)); |
1309 | |
1310 | scopes::CategoryRenderer renderer("{}"); |
1311 | auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1312 | EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
1313 | |
1314 | - scopes::SearchReplyProxy reply; |
1315 | + scopes::testing::MockSearchReply mock_reply; |
1316 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
1317 | + EXPECT_CALL(mock_reply, register_departments(_, _)).Times(1); |
1318 | EXPECT_CALL(q, finished(_)); |
1319 | q.wrap_add_available_apps(reply, no_installed_packages, FAKE_CATEGORY_TEMPLATE); |
1320 | } |
1321 | @@ -205,11 +232,12 @@ |
1322 | {"name", "title", 0.0, "", ""} |
1323 | }; |
1324 | MockIndex mock_index(packages); |
1325 | + click::DepartmentLookup dept_lookup; |
1326 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1327 | std::set<std::string> no_installed_packages; |
1328 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1329 | - MockQuery q(query, mock_index, metadata); |
1330 | - EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(0); |
1331 | + MockQuery q(query, mock_index, dept_lookup, metadata); |
1332 | + EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _)).Times(0); |
1333 | |
1334 | EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(nullptr)); |
1335 | |
1336 | @@ -224,10 +252,11 @@ |
1337 | {"name", "title", 0.0, "", ""} |
1338 | }; |
1339 | MockIndex mock_index(packages); |
1340 | + click::DepartmentLookup dept_lookup; |
1341 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1342 | std::set<std::string> no_installed_packages; |
1343 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1344 | - MockQueryRun q(query, mock_index, metadata); |
1345 | + MockQueryRun q(query, mock_index, dept_lookup, metadata); |
1346 | auto reply = scopes::SearchReplyProxy(); |
1347 | EXPECT_CALL(q, push_local_results(_, _, _)); |
1348 | EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _)); |
1349 | @@ -244,19 +273,23 @@ |
1350 | {"org.example.app2", "app title2", 0.0, "", ""} |
1351 | }; |
1352 | MockIndex mock_index(packages); |
1353 | + click::DepartmentLookup dept_lookup; |
1354 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1355 | std::set<std::string> one_installed_package { |
1356 | "org.example.app2" |
1357 | }; |
1358 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1359 | - MockQuery q(query, mock_index, metadata); |
1360 | - EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1361 | + MockQuery q(query, mock_index, dept_lookup, metadata); |
1362 | + EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _, _)); |
1363 | |
1364 | scopes::CategoryRenderer renderer("{}"); |
1365 | auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1366 | EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
1367 | |
1368 | - scopes::SearchReplyProxy reply; |
1369 | + scopes::testing::MockSearchReply mock_reply; |
1370 | + scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
1371 | + EXPECT_CALL(mock_reply, register_departments(_, _)).Times(1); |
1372 | + |
1373 | auto expected_name = packages.front().name; |
1374 | EXPECT_CALL(q, push_result(_, HasPackageName(expected_name))); |
1375 | q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE); |
FAILED: Continuous integration, rev:257 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- ci/59/ jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- amd64-ci/ 34/console jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 33/console jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- i386-ci/ 33/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- team-unity- scope-click- devel-ci/ 59/rebuild
http://