Merge lp:~mvo/unity-scope-click/lp1292645-use-libclick2 into lp:unity-scope-click/devel
- lp1292645-use-libclick2
- Merge into devel
Status: | Work in progress |
---|---|
Proposed branch: | lp:~mvo/unity-scope-click/lp1292645-use-libclick2 |
Merge into: | lp:unity-scope-click/devel |
Diff against target: | 988 lines (+447/-221) 14 files modified debian/control (+1/-0) debian/tests/control (+2/-0) libclickscope/click/CMakeLists.txt (+3/-0) scope/click/CMakeLists.txt (+9/-0) scope/click/configuration.cpp (+2/-20) scope/click/configuration.h (+1/-5) scope/click/interface.cpp (+47/-56) scope/click/interface.h (+8/-5) scope/click/libclick.cpp (+123/-0) scope/click/libclick.h (+58/-0) scope/tests/CMakeLists.txt (+10/-0) scope/tests/test_configuration.cpp (+8/-56) scope/tests/test_interface.cpp (+91/-79) scope/tests/test_libclick.cpp (+84/-0) |
To merge this branch: | bzr merge lp:~mvo/unity-scope-click/lp1292645-use-libclick2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
dobey (community) | Needs Fixing | ||
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Review via email: |
Commit message
Use libclick to gather information about installed frameworks/
Description of the change
Another attempt to start using libclick instead of spawning the click commandline client.
This branch addresses the feedback from from Alejandro, Rodney and Thomas in https:/
Based on https:/

PS Jenkins bot (ps-jenkins) wrote : | # |
- 271. By Michael Vogt
-
add missing click libs to libclickscope/
click/

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:271
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 272. By Michael Vogt
-
add missing ubuntu-sdk-libs to test control

PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:272
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://

dobey (dobey) wrote : | # |
Thanks for working on this Michael.
You need to update to the tip of /devel. The configuration.
The new libclick.{cpp,h} and associated tests should be placed in libclickscope/ instead, as well.
Also, I've noticed this pattern in your changes:
210 + try {
211 + ManifestList manifests = manifest_
212 + callback(manifests, ManifestError:
213 + } catch (...) {
214 + callback(
215 + }
This can be problematic, as any exceptions thrown inside callback() will result in callback() being called a second time with different arguments. I think it would be better to do this instead:
ManifestList manifests;
try {
manifests = manifest_
} catch (...) {
callback(
return;
}
callback(manifests, ManifestError:
This way callback() will only be called once, and any exceptions it throws won't be lost inside the try block.
Unmerged revisions
- 272. By Michael Vogt
-
add missing ubuntu-sdk-libs to test control
- 271. By Michael Vogt
-
add missing click libs to libclickscope/
click/ - 270. By Michael Vogt
-
cleanup uneeded changes
- 269. By Michael Vogt
-
fixes lp:1292645
- 268. By Michael Vogt
-
remove Interface:
:run_process - 267. By Michael Vogt
-
code cleanup
- 266. By Michael Vogt
-
make Interface:
:get_manifest_ for_app( ) use libclick - 265. By Michael Vogt
-
make Interface:
:get_manifests( ) use libclick - 264. By Michael Vogt
-
Add new libclick.{cc,h} that wraps the vala/GObject parts of libclick we need
This is the first step towards fixing bug #1292645 by getting the list
of available frameworks via libclick.This branch is based on the work of Alejandro J. Cura
lp:~alecu/unity-scope-click/lp1292645
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2014-05-16 13:09:36 +0000 |
3 | +++ debian/control 2014-05-21 14:12:22 +0000 |
4 | @@ -6,6 +6,7 @@ |
5 | dh-translations, |
6 | google-mock, |
7 | intltool, |
8 | + libclick-0.4-dev, |
9 | libglib2.0-dev (>= 2.32), |
10 | libjsoncpp-dev, |
11 | libubuntu-download-manager-client-dev (>= 0.3+14.10.20140430-0ubuntu1), |
12 | |
13 | === modified file 'debian/tests/control' |
14 | --- debian/tests/control 2013-12-17 17:56:49 +0000 |
15 | +++ debian/tests/control 2014-05-21 14:12:22 +0000 |
16 | @@ -5,6 +5,7 @@ |
17 | dh-autoreconf, |
18 | gnome-common, |
19 | libaccounts-glib-dev, |
20 | + libclick-0.4-dev, |
21 | libdee-dev (>= 1.2.5), |
22 | libgee-dev, |
23 | libglib2.0-dev (>= 2.32), |
24 | @@ -15,4 +16,5 @@ |
25 | libsoup2.4-dev, |
26 | libunity-dev (>= 7.0.0), |
27 | pkg-config, |
28 | + ubuntu-sdk-libs, |
29 | valac |
30 | |
31 | === modified file 'libclickscope/click/CMakeLists.txt' |
32 | --- libclickscope/click/CMakeLists.txt 2014-05-13 19:32:29 +0000 |
33 | +++ libclickscope/click/CMakeLists.txt 2014-05-21 14:12:22 +0000 |
34 | @@ -2,6 +2,7 @@ |
35 | SET (CMAKE_AUTOMOC ON) |
36 | find_package (Qt5Core REQUIRED) |
37 | pkg_check_modules(JSON_CPP REQUIRED jsoncpp) |
38 | +pkg_check_modules(CLICK REQUIRED click-0.4) |
39 | |
40 | add_definitions( |
41 | -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\" |
42 | @@ -14,6 +15,7 @@ |
43 | |
44 | include_directories( |
45 | ${JSON_CPP_INCLUDE_DIRS} |
46 | + ${CLICK_INCLUDE_DIRS} |
47 | ) |
48 | |
49 | qt5_use_modules (${SCOPE_LIB_NAME} Network) |
50 | @@ -24,4 +26,5 @@ |
51 | ${UBUNTUONE_LDFLAGS} |
52 | ${UBUNTU_DOWNLOAD_MANAGER_CLIENT_LDFLAGS} |
53 | ${UBUNTU_DOWNLOAD_MANAGER_COMMON_LDFLAGS} |
54 | + ${CLICK_LDFLAGS} |
55 | ) |
56 | |
57 | === modified file 'scope/click/CMakeLists.txt' |
58 | --- scope/click/CMakeLists.txt 2014-05-13 19:32:29 +0000 |
59 | +++ scope/click/CMakeLists.txt 2014-05-21 14:12:22 +0000 |
60 | @@ -2,6 +2,9 @@ |
61 | SET (CMAKE_AUTOMOC ON) |
62 | find_package (Qt5Core REQUIRED) |
63 | pkg_check_modules(JSON_CPP REQUIRED jsoncpp) |
64 | +pkg_check_modules(CLICK REQUIRED click-0.4) |
65 | +pkg_check_modules(GLIB REQUIRED glib-2.0) |
66 | +pkg_check_modules(GOBJECT REQUIRED gobject-2.0) |
67 | |
68 | add_definitions( |
69 | -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\" |
70 | @@ -13,6 +16,7 @@ |
71 | download-manager.cpp |
72 | index.cpp |
73 | interface.cpp |
74 | + libclick.cpp |
75 | network_access_manager.cpp |
76 | query.cpp |
77 | reviews.cpp |
78 | @@ -30,6 +34,9 @@ |
79 | include_directories( |
80 | ${CMAKE_SOURCE_DIR}/libclickscope |
81 | ${JSON_CPP_INCLUDE_DIRS} |
82 | + ${CLICK_INCLUDE_DIRS} |
83 | + ${GLIB_INCLUDE_DIRS} |
84 | + ${GOBJECT_INCLUDE_DIRS} |
85 | ) |
86 | |
87 | qt5_use_modules (${SCOPE_LIB_UNVERSIONED} Network) |
88 | @@ -42,6 +49,8 @@ |
89 | ${UBUNTUONE_LDFLAGS} |
90 | ${UBUNTU_DOWNLOAD_MANAGER_CLIENT_LDFLAGS} |
91 | ${UBUNTU_DOWNLOAD_MANAGER_COMMON_LDFLAGS} |
92 | + ${GLIB_LDFLAGS} |
93 | + ${GOBJECT_LDFLAGS} |
94 | ) |
95 | |
96 | install( |
97 | |
98 | === modified file 'scope/click/configuration.cpp' |
99 | --- scope/click/configuration.cpp 2014-05-01 21:04:23 +0000 |
100 | +++ scope/click/configuration.cpp 2014-05-21 14:12:22 +0000 |
101 | @@ -36,32 +36,14 @@ |
102 | #include <boost/algorithm/string.hpp> |
103 | #include <boost/algorithm/string/replace.hpp> |
104 | |
105 | +#include "libclick.h" |
106 | #include "configuration.h" |
107 | |
108 | namespace click { |
109 | |
110 | -std::vector<std::string> Configuration::list_folder(const std::string& folder, const std::string& pattern) |
111 | -{ |
112 | - std::vector<std::string> result; |
113 | - |
114 | - QDir dir(QString::fromStdString(folder), QString::fromStdString(pattern), |
115 | - QDir::Unsorted, QDir::Readable | QDir::Files); |
116 | - QStringList entries = dir.entryList(); |
117 | - for (int i = 0; i < entries.size(); ++i) { |
118 | - QString filename = entries.at(i); |
119 | - result.push_back(filename.toStdString()); |
120 | - } |
121 | - |
122 | - return result; |
123 | -} |
124 | - |
125 | std::vector<std::string> Configuration::get_available_frameworks() |
126 | { |
127 | - std::vector<std::string> result; |
128 | - for (auto f: list_folder(FRAMEWORKS_FOLDER, FRAMEWORKS_PATTERN)) { |
129 | - result.push_back(f.substr(0, f.size()-FRAMEWORKS_EXTENSION_LENGTH)); |
130 | - } |
131 | - return result; |
132 | + return libclick::Framework().get_frameworks(); |
133 | } |
134 | |
135 | std::string Configuration::architectureFromDpkg() |
136 | |
137 | === modified file 'scope/click/configuration.h' |
138 | --- scope/click/configuration.h 2014-05-01 21:04:23 +0000 |
139 | +++ scope/click/configuration.h 2014-05-21 14:12:22 +0000 |
140 | @@ -38,10 +38,7 @@ |
141 | |
142 | class Configuration |
143 | { |
144 | -public: |
145 | - constexpr static const char* FRAMEWORKS_FOLDER {"/usr/share/click/frameworks/"}; |
146 | - constexpr static const char* FRAMEWORKS_PATTERN {"*.framework"}; |
147 | - constexpr static const int FRAMEWORKS_EXTENSION_LENGTH = 10; // strlen(".framework") |
148 | + public: |
149 | constexpr static const char* LANGUAGE_ENVVAR {"LANGUAGE"}; |
150 | |
151 | virtual std::vector<std::string> get_available_frameworks(); |
152 | @@ -53,7 +50,6 @@ |
153 | |
154 | virtual ~Configuration() {} |
155 | protected: |
156 | - virtual std::vector<std::string> list_folder(const std::string &folder, const std::string &pattern); |
157 | virtual std::string architectureFromDpkg(); |
158 | }; |
159 | |
160 | |
161 | === modified file 'scope/click/interface.cpp' |
162 | --- scope/click/interface.cpp 2014-05-13 19:32:29 +0000 |
163 | +++ scope/click/interface.cpp 2014-05-21 14:12:22 +0000 |
164 | @@ -87,12 +87,19 @@ |
165 | static const std::string ONLYSHOWIN_UNITY("Unity"); |
166 | |
167 | Interface::Interface(const QSharedPointer<click::KeyFileLocator>& keyFileLocator) |
168 | - : keyFileLocator(keyFileLocator) |
169 | + : keyFileLocator(keyFileLocator), db(nullptr), user(nullptr) |
170 | +{ |
171 | +} |
172 | + |
173 | +Interface::Interface() |
174 | + : db(nullptr), user(nullptr) |
175 | { |
176 | } |
177 | |
178 | Interface::~Interface() |
179 | { |
180 | + delete db; |
181 | + delete user; |
182 | } |
183 | |
184 | bool Interface::show_desktop_apps() |
185 | @@ -323,39 +330,38 @@ |
186 | |
187 | void Interface::get_manifests(std::function<void(ManifestList, ManifestError)> callback) |
188 | { |
189 | - std::string command = "click list --manifest"; |
190 | - qDebug() << "Running command:" << command.c_str(); |
191 | - run_process(command, [callback](int code, const std::string& stdout_data, const std::string&) { |
192 | - if (code == 0) { |
193 | - try { |
194 | - ManifestList manifests = manifest_list_from_json(stdout_data); |
195 | - callback(manifests, ManifestError::NoError); |
196 | - } catch (...) { |
197 | - callback(ManifestList(), ManifestError::ParseError); |
198 | - } |
199 | - } else { |
200 | - callback(ManifestList(), ManifestError::CallError); |
201 | - } |
202 | - }); |
203 | + std::string manifests_json; |
204 | + try { |
205 | + manifests_json = getClickDatabase()->get_manifests_as_string(); |
206 | + } catch (...) { |
207 | + callback(ManifestList(), ManifestError::CallError); |
208 | + } |
209 | + |
210 | + try { |
211 | + ManifestList manifests = manifest_list_from_json(manifests_json); |
212 | + callback(manifests, ManifestError::NoError); |
213 | + } catch (...) { |
214 | + callback(ManifestList(), ManifestError::ParseError); |
215 | + } |
216 | } |
217 | |
218 | void Interface::get_manifest_for_app(const std::string &app_id, |
219 | std::function<void(Manifest, ManifestError)> callback) |
220 | { |
221 | - std::string command = "click info " + app_id; |
222 | - qDebug() << "Running command:" << command.c_str(); |
223 | - run_process(command, [callback](int code, const std::string& stdout_data, const std::string&) { |
224 | - if (code == 0) { |
225 | - try { |
226 | - Manifest manifest = manifest_from_json(stdout_data); |
227 | - callback(manifest, ManifestError::NoError); |
228 | - } catch (...) { |
229 | - callback(Manifest(), ManifestError::ParseError); |
230 | - } |
231 | - } else { |
232 | - callback(Manifest(), ManifestError::CallError); |
233 | - } |
234 | - }); |
235 | + std::string manifest_json; |
236 | + |
237 | + try { |
238 | + manifest_json = getClickUser()->get_manifest_as_string(app_id); |
239 | + } catch (...) { |
240 | + callback(Manifest(), ManifestError::CallError); |
241 | + } |
242 | + |
243 | + try { |
244 | + Manifest manifest = manifest_from_json(manifest_json); |
245 | + callback(manifest, ManifestError::NoError); |
246 | + } catch (...) { |
247 | + callback(Manifest(), ManifestError::ParseError); |
248 | + } |
249 | } |
250 | |
251 | void Interface::get_dotdesktop_filename(const std::string &app_id, |
252 | @@ -380,33 +386,18 @@ |
253 | }); |
254 | } |
255 | |
256 | -void Interface::run_process(const std::string& command, |
257 | - std::function<void(int code, |
258 | - const std::string& stdout_data, |
259 | - const std::string& stderr_data)> callback) |
260 | -{ |
261 | - QSharedPointer<QProcess> process(new QProcess()); |
262 | - typedef void(QProcess::*QProcessFinished)(int, QProcess::ExitStatus); |
263 | - typedef void(QProcess::*QProcessError)(QProcess::ProcessError); |
264 | - QObject::connect(process.data(), |
265 | - static_cast<QProcessFinished>(&QProcess::finished), |
266 | - [callback, process](int code, QProcess::ExitStatus /*status*/) { |
267 | - qDebug() << "command finished with exit code:" << code; |
268 | - auto data = process.data()->readAllStandardOutput().data(); |
269 | - auto errors = process.data()->readAllStandardError().data(); |
270 | - callback(code, data, errors); |
271 | - } ); |
272 | - |
273 | - QObject::connect(process.data(), |
274 | - static_cast<QProcessError>(&QProcess::error), |
275 | - [callback, process](QProcess::ProcessError error) { |
276 | - qCritical() << "error running command:" << error; |
277 | - auto data = process.data()->readAllStandardOutput().data(); |
278 | - auto errors = process.data()->readAllStandardError().data(); |
279 | - callback(process.data()->exitCode(), data, errors); |
280 | - } ); |
281 | - |
282 | - process->start(command.c_str()); |
283 | +libclick::Database* Interface::getClickDatabase() |
284 | +{ |
285 | + if (db == nullptr) |
286 | + db = new libclick::Database(); |
287 | + return db; |
288 | +} |
289 | + |
290 | +libclick::User* Interface::getClickUser() |
291 | +{ |
292 | + if (user == nullptr) |
293 | + user = new libclick::User(); |
294 | + return user; |
295 | } |
296 | |
297 | } // namespace click |
298 | |
299 | === modified file 'scope/click/interface.h' |
300 | --- scope/click/interface.h 2014-05-06 19:17:30 +0000 |
301 | +++ scope/click/interface.h 2014-05-21 14:12:22 +0000 |
302 | @@ -37,6 +37,7 @@ |
303 | #include <vector> |
304 | #include <unordered_set> |
305 | |
306 | +#include "libclick.h" |
307 | #include "application.h" |
308 | |
309 | namespace click |
310 | @@ -72,7 +73,7 @@ |
311 | { |
312 | public: |
313 | Interface(const QSharedPointer<KeyFileLocator>& keyFileLocator); |
314 | - Interface() = default; |
315 | + Interface(); |
316 | virtual ~Interface(); |
317 | |
318 | virtual std::string get_translated_string(const unity::util::IniParser& keyFile, |
319 | @@ -95,12 +96,14 @@ |
320 | virtual bool is_visible_app(const unity::util::IniParser& keyFile); |
321 | virtual bool show_desktop_apps(); |
322 | |
323 | - virtual void run_process(const std::string& command, |
324 | - std::function<void(int code, |
325 | - const std::string& stdout_data, |
326 | - const std::string& stderr_data)> callback); |
327 | private: |
328 | QSharedPointer<KeyFileLocator> keyFileLocator; |
329 | + |
330 | + // gobject/vala libclick |
331 | + virtual libclick::Database* getClickDatabase(); |
332 | + virtual libclick::User* getClickUser(); |
333 | + libclick::Database *db; |
334 | + libclick::User *user; |
335 | }; |
336 | |
337 | } // namespace click |
338 | |
339 | === added file 'scope/click/libclick.cpp' |
340 | --- scope/click/libclick.cpp 1970-01-01 00:00:00 +0000 |
341 | +++ scope/click/libclick.cpp 2014-05-21 14:12:22 +0000 |
342 | @@ -0,0 +1,123 @@ |
343 | + |
344 | +// the vala/gobject click we need |
345 | +#include <click.h> |
346 | +#include <glib.h> |
347 | + |
348 | +#include <stdexcept> |
349 | +#include <functional> |
350 | + |
351 | +#include "libclick.h" |
352 | + |
353 | +namespace libclick { |
354 | + |
355 | + |
356 | +void throw_exception_on_gerror(GError *error, std::function<void()> body) |
357 | +{ |
358 | + if (error != NULL) |
359 | + { |
360 | + std::string err_msg = error->message; |
361 | + g_error_free(error); |
362 | + body(); |
363 | + throw std::runtime_error(err_msg); |
364 | + } |
365 | +} |
366 | + |
367 | + |
368 | +std::vector<std::string> Framework::get_frameworks() |
369 | +{ |
370 | + std::vector<std::string> result; |
371 | + GList *l = _click_framework_get_frameworks(); |
372 | + while (l != NULL) |
373 | + { |
374 | + gchar *name = nullptr; |
375 | + GObject *framework = (GObject *)l->data; |
376 | + g_object_get(framework, "name", &name, nullptr); |
377 | + if (name == nullptr) |
378 | + { |
379 | + g_object_unref(framework); |
380 | + break; |
381 | + } |
382 | + result.push_back(name); |
383 | + g_free(name); |
384 | + g_object_unref(framework); |
385 | + l = g_list_next(l); |
386 | + } |
387 | + return result; |
388 | +} |
389 | + |
390 | +GList* Framework::_click_framework_get_frameworks() |
391 | +{ |
392 | + return click_framework_get_frameworks(); |
393 | +} |
394 | + |
395 | +std::string Database::get_manifests_as_string() |
396 | +{ |
397 | + gchar *s = _click_db_get_manifests_as_string(); |
398 | + std::string result = s; |
399 | + g_free(s); |
400 | + return result; |
401 | +} |
402 | + |
403 | +Database::Database() |
404 | +{ |
405 | + db = click_db_new(); |
406 | +} |
407 | +Database::~Database() |
408 | +{ |
409 | + g_object_unref(db); |
410 | +} |
411 | + |
412 | +gchar* Database::_click_db_get_manifests_as_string() |
413 | +{ |
414 | + GError *error = NULL; |
415 | + char *s = NULL; |
416 | + |
417 | + s = click_db_get_manifests_as_string(db, false, &error); |
418 | + throw_exception_on_gerror(error); |
419 | + |
420 | + return s; |
421 | +} |
422 | + |
423 | +User::User() |
424 | +{ |
425 | + GError *error = NULL; |
426 | + db = click_db_new(); |
427 | + click_db_read(db, NULL, &error); |
428 | + throw_exception_on_gerror(error, [&]() { |
429 | + g_object_unref(db); |
430 | + }); |
431 | + |
432 | + user = click_user_new_for_user(db, NULL, &error); |
433 | + throw_exception_on_gerror(error, [&]() { |
434 | + g_object_unref(db); |
435 | + g_object_unref(user); |
436 | + }); |
437 | + |
438 | +} |
439 | + |
440 | +User::~User() |
441 | +{ |
442 | + g_object_unref(db); |
443 | + g_object_unref(user); |
444 | +} |
445 | + |
446 | +std::string User::get_manifest_as_string(std::string app_id) |
447 | +{ |
448 | + gchar *s = _click_user_get_manifest_as_string(app_id.c_str()); |
449 | + std::string result = s; |
450 | + g_free(s); |
451 | + return result; |
452 | +} |
453 | + |
454 | +gchar* User::_click_user_get_manifest_as_string(const gchar *app_id) |
455 | +{ |
456 | + GError *error = NULL; |
457 | + char *c_output = NULL; |
458 | + |
459 | + c_output = click_user_get_manifest_as_string (user, app_id, &error); |
460 | + throw_exception_on_gerror(error); |
461 | + |
462 | + return c_output; |
463 | +} |
464 | + |
465 | +} // namespace libclick |
466 | |
467 | === added file 'scope/click/libclick.h' |
468 | --- scope/click/libclick.h 1970-01-01 00:00:00 +0000 |
469 | +++ scope/click/libclick.h 2014-05-21 14:12:22 +0000 |
470 | @@ -0,0 +1,58 @@ |
471 | +#ifndef CLICK_SCOPE_LIBCLICK_H |
472 | +#define CLICK_SCOPE_LIBCLICK_H |
473 | + |
474 | + |
475 | +#include <string> |
476 | +#include <vector> |
477 | + |
478 | +// forward declaring to avoid having to import GLib/libclick here |
479 | +struct _GList; |
480 | +struct _ClickDB; |
481 | +struct _ClickUser; |
482 | +struct _GError; |
483 | + |
484 | +namespace libclick { |
485 | + |
486 | +void throw_exception_on_gerror(_GError *error, std::function<void()> body={}); |
487 | + |
488 | +class Framework { |
489 | +public: |
490 | + std::vector<std::string> get_frameworks(); |
491 | + virtual ~Framework() {}; |
492 | + |
493 | +private: |
494 | + // wrapper around click_framework_get_frameworks() for testability |
495 | + virtual _GList* _click_framework_get_frameworks(); |
496 | + |
497 | +}; |
498 | + |
499 | +class Database { |
500 | + public: |
501 | + Database(); |
502 | + virtual ~Database(); |
503 | + virtual std::string get_manifests_as_string(); |
504 | + |
505 | + private: |
506 | + virtual char* _click_db_get_manifests_as_string(); |
507 | + |
508 | + _ClickDB *db; |
509 | +}; |
510 | + |
511 | +class User { |
512 | + public: |
513 | + User(); |
514 | + virtual ~User(); |
515 | + |
516 | + virtual std::string get_manifest_as_string(std::string app_id); |
517 | + |
518 | + private: |
519 | + virtual char* _click_user_get_manifest_as_string(const char *app_id); |
520 | + |
521 | + _ClickDB *db; |
522 | + _ClickUser *user; |
523 | +}; |
524 | + |
525 | + |
526 | +} // namespace libclick |
527 | + |
528 | +#endif // CLICK_SCOPE_LIBCLICK_H |
529 | |
530 | === modified file 'scope/tests/CMakeLists.txt' |
531 | --- scope/tests/CMakeLists.txt 2014-05-14 21:50:52 +0000 |
532 | +++ scope/tests/CMakeLists.txt 2014-05-21 14:12:22 +0000 |
533 | @@ -1,6 +1,7 @@ |
534 | set (CLICKSCOPE_TESTS_TARGET click-scope-tests) |
535 | find_package(Threads) |
536 | |
537 | + |
538 | # Build with system gmock and embedded gtest |
539 | set (GMOCK_INCLUDE_DIR "/usr/include/gmock/include" CACHE PATH "gmock source include directory") |
540 | set (GMOCK_SOURCE_DIR "/usr/src/gmock" CACHE PATH "gmock source directory") |
541 | @@ -14,12 +15,18 @@ |
542 | |
543 | find_package(Qt5Core REQUIRED) |
544 | |
545 | +# glib |
546 | +pkg_check_modules(GLIB REQUIRED glib-2.0) |
547 | +pkg_check_modules(CLICK REQUIRED click-0.4) |
548 | + |
549 | include_directories ( |
550 | ${CMAKE_SOURCE_DIR}/libclickscope |
551 | ${CMAKE_SOURCE_DIR}/scope |
552 | ${JSON_CPP_INCLUDE_DIRS} |
553 | ${GTEST_INCLUDE_DIR} |
554 | ${GMOCK_INCLUDE_DIR} |
555 | + ${GLIB_INCLUDE_DIRS} |
556 | + ${CLICK_INCLUDE_DIRS} |
557 | ) |
558 | |
559 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test_data.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/test_data.cpp) |
560 | @@ -31,6 +38,7 @@ |
561 | test_download_manager.cpp |
562 | test_index.cpp |
563 | test_interface.cpp |
564 | + test_libclick.cpp |
565 | test_query.cpp |
566 | test_reviews.cpp |
567 | test_smartconnect.cpp |
568 | @@ -49,6 +57,8 @@ |
569 | ${UBUNTU_DOWNLOAD_MANAGER_CLIENT_LDFLAGS} |
570 | ${UBUNTU_DOWNLOAD_MANAGER_COMMON_LDFLAGS} |
571 | ${JSON_CPP_LDFLAGS} |
572 | + ${CLICK_LDFLAGS} |
573 | + ${GLIB_LDFLAGS} |
574 | |
575 | gmock |
576 | gmock_main |
577 | |
578 | === modified file 'scope/tests/test_configuration.cpp' |
579 | --- scope/tests/test_configuration.cpp 2014-05-01 21:04:23 +0000 |
580 | +++ scope/tests/test_configuration.cpp 2014-05-21 14:12:22 +0000 |
581 | @@ -31,65 +31,17 @@ |
582 | #include <gtest/gtest.h> |
583 | |
584 | #include <click/configuration.h> |
585 | +#include <click/libclick.h> |
586 | |
587 | using namespace click; |
588 | |
589 | -namespace |
590 | -{ |
591 | - |
592 | -class FakeConfiguration : public click::Configuration |
593 | -{ |
594 | -public: |
595 | - MOCK_METHOD2(list_folder, std::vector<std::string>( |
596 | - const std::string& folder, const std::string& pattern)); |
597 | -}; |
598 | - |
599 | -} |
600 | - |
601 | - |
602 | -TEST(Configuration, getAvailableFrameworksUsesRightFolder) |
603 | -{ |
604 | - using namespace ::testing; |
605 | - FakeConfiguration locator; |
606 | - EXPECT_CALL(locator, list_folder(Configuration::FRAMEWORKS_FOLDER, _)) |
607 | - .Times(1).WillOnce(Return(std::vector<std::string>())); |
608 | - locator.get_available_frameworks(); |
609 | -} |
610 | - |
611 | -TEST(Configuration, getAvailableFrameworksUsesRightPattern) |
612 | -{ |
613 | - using namespace ::testing; |
614 | - FakeConfiguration locator; |
615 | - EXPECT_CALL(locator, list_folder(_, Configuration::FRAMEWORKS_PATTERN)) |
616 | - .Times(1).WillOnce(Return(std::vector<std::string>())); |
617 | - locator.get_available_frameworks(); |
618 | -} |
619 | - |
620 | -TEST(Configuration, getAvailableFrameworksTwoResults) |
621 | -{ |
622 | - using namespace ::testing; |
623 | - |
624 | - FakeConfiguration locator; |
625 | - std::vector<std::string> response = {"abc.framework", "def.framework"}; |
626 | - EXPECT_CALL(locator, list_folder(_, _)) |
627 | - .Times(1) |
628 | - .WillOnce(Return(response)); |
629 | - auto frameworks = locator.get_available_frameworks(); |
630 | - std::vector<std::string> expected = {"abc", "def"}; |
631 | - EXPECT_EQ(expected, frameworks); |
632 | -} |
633 | - |
634 | -TEST(Configuration, getAvailableFrameworksNoResults) |
635 | -{ |
636 | - using namespace ::testing; |
637 | - |
638 | - FakeConfiguration locator; |
639 | - std::vector<std::string> response = {}; |
640 | - EXPECT_CALL(locator, list_folder(_, _)) |
641 | - .Times(1) |
642 | - .WillOnce(Return(response)); |
643 | - auto frameworks = locator.get_available_frameworks(); |
644 | - EXPECT_EQ(0, frameworks.size()); |
645 | +TEST(Configuration, getAvailableFrameworksSmokeTest) |
646 | +{ |
647 | + using namespace ::testing; |
648 | + |
649 | + click::Configuration configuration; |
650 | + auto frameworks = configuration.get_available_frameworks(); |
651 | + EXPECT_GT(frameworks.size(), 0); |
652 | } |
653 | |
654 | TEST(Configuration, getLanguageCorrect) |
655 | |
656 | === modified file 'scope/tests/test_interface.cpp' |
657 | --- scope/tests/test_interface.cpp 2014-05-06 19:17:30 +0000 |
658 | +++ scope/tests/test_interface.cpp 2014-05-21 14:12:22 +0000 |
659 | @@ -124,13 +124,25 @@ |
660 | |
661 | } |
662 | |
663 | +class FakeClickDatabase : public libclick::Database { |
664 | +public: |
665 | + MOCK_METHOD0(get_manifests_as_string, std::string()); |
666 | +}; |
667 | + |
668 | +class FakeClickUser : public libclick::User { |
669 | +public: |
670 | + MOCK_METHOD1(get_manifest_as_string, std::string(std::string app_id)); |
671 | +}; |
672 | + |
673 | class FakeClickInterface : public click::Interface { |
674 | public: |
675 | FakeClickInterface(const QSharedPointer<KeyFileLocator>& keyFileLocator) : Interface(keyFileLocator) {} |
676 | FakeClickInterface() {} |
677 | |
678 | MOCK_METHOD0(show_desktop_apps, bool()); |
679 | - MOCK_METHOD2(run_process, void(const std::string&, std::function<void(int, const std::string&, const std::string&)>)); |
680 | + |
681 | + MOCK_METHOD0(getClickDatabase, libclick::Database*()); |
682 | + MOCK_METHOD0(getClickUser, libclick::User*()); |
683 | }; |
684 | |
685 | TEST(ClickInterface, testIsNonClickAppFalse) |
686 | @@ -320,25 +332,38 @@ |
687 | EXPECT_FALSE(iface.show_desktop_apps()); |
688 | } |
689 | |
690 | -TEST(ClickInterface, testGetManifestForAppCorrectCommand) |
691 | +TEST(ClickInterface, testGetManifestForAppEmptyJson) |
692 | { |
693 | FakeClickInterface iface; |
694 | - std::string command = "click info " + FAKE_PACKAGENAME; |
695 | - EXPECT_CALL(iface, run_process(command, _)). |
696 | - Times(1); |
697 | - iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest, ManifestError){}); |
698 | + FakeClickUser user; |
699 | + |
700 | + EXPECT_CALL(iface, getClickUser()). |
701 | + Times(1) |
702 | + .WillOnce(Return(&user)); |
703 | + |
704 | + EXPECT_CALL(user, get_manifest_as_string(FAKE_PACKAGENAME)). |
705 | + Times(1) |
706 | + .WillOnce(Return("[]")); |
707 | + |
708 | + iface.get_manifest_for_app(FAKE_PACKAGENAME, |
709 | + [](Manifest, ManifestError error){ |
710 | + ASSERT_TRUE(error == ManifestError::ParseError); |
711 | + }); |
712 | } |
713 | |
714 | TEST_F(ClickInterfaceTest, testGetManifestForAppParseError) |
715 | { |
716 | FakeClickInterface iface; |
717 | - EXPECT_CALL(iface, run_process(_, _)). |
718 | - Times(1). |
719 | - WillOnce(Invoke([&](const std::string&, |
720 | - std::function<void(int, const std::string&, |
721 | - const std::string&)> callback){ |
722 | - callback(0, "INVALID JSON", ""); |
723 | - })); |
724 | + FakeClickUser user; |
725 | + |
726 | + EXPECT_CALL(iface, getClickUser()). |
727 | + Times(1) |
728 | + .WillOnce(Return(&user)); |
729 | + |
730 | + EXPECT_CALL(user, get_manifest_as_string(FAKE_PACKAGENAME)). |
731 | + Times(1) |
732 | + .WillOnce(Return("INVALID JSON")); |
733 | + |
734 | EXPECT_CALL(*this, manifest_callback(_, ManifestError::ParseError)); |
735 | iface.get_manifest_for_app(FAKE_PACKAGENAME, [this](Manifest manifest, |
736 | ManifestError error){ |
737 | @@ -346,33 +371,19 @@ |
738 | }); |
739 | } |
740 | |
741 | -TEST_F(ClickInterfaceTest, testGetManifestForAppCommandFailed) |
742 | -{ |
743 | - FakeClickInterface iface; |
744 | - EXPECT_CALL(iface, run_process(_, _)). |
745 | - Times(1). |
746 | - WillOnce(Invoke([&](const std::string&, |
747 | - std::function<void(int, const std::string&, |
748 | - const std::string&)> callback){ |
749 | - callback(-1, "", "CRITICAL: FAIL"); |
750 | - })); |
751 | - EXPECT_CALL(*this, manifest_callback(_, ManifestError::CallError)); |
752 | - iface.get_manifest_for_app(FAKE_PACKAGENAME, [this](Manifest manifest, |
753 | - ManifestError error){ |
754 | - manifest_callback(manifest, error); |
755 | - }); |
756 | -} |
757 | - |
758 | TEST_F(ClickInterfaceTest, testGetManifestForAppIsRemovable) |
759 | { |
760 | FakeClickInterface iface; |
761 | - EXPECT_CALL(iface, run_process(_, _)). |
762 | - Times(1). |
763 | - WillOnce(Invoke([&](const std::string&, |
764 | - std::function<void(int, const std::string&, |
765 | - const std::string&)> callback){ |
766 | - callback(0, FAKE_JSON_MANIFEST_REMOVABLE, ""); |
767 | - })); |
768 | + FakeClickUser user; |
769 | + |
770 | + EXPECT_CALL(iface, getClickUser()). |
771 | + Times(1) |
772 | + .WillOnce(Return(&user)); |
773 | + |
774 | + EXPECT_CALL(user, get_manifest_as_string(FAKE_PACKAGENAME)). |
775 | + Times(1) |
776 | + .WillOnce(Return(FAKE_JSON_MANIFEST_REMOVABLE)); |
777 | + |
778 | iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest, |
779 | ManifestError error){ |
780 | ASSERT_TRUE(error == ManifestError::NoError); |
781 | @@ -383,13 +394,16 @@ |
782 | TEST_F(ClickInterfaceTest, testGetManifestForAppIsNotRemovable) |
783 | { |
784 | FakeClickInterface iface; |
785 | - EXPECT_CALL(iface, run_process(_, _)). |
786 | - Times(1). |
787 | - WillOnce(Invoke([&](const std::string&, |
788 | - std::function<void(int, const std::string&, |
789 | - const std::string&)> callback){ |
790 | - callback(0, FAKE_JSON_MANIFEST_NONREMOVABLE, ""); |
791 | - })); |
792 | + FakeClickUser user; |
793 | + |
794 | + EXPECT_CALL(iface, getClickUser()). |
795 | + Times(1) |
796 | + .WillOnce(Return(&user)); |
797 | + |
798 | + EXPECT_CALL(user, get_manifest_as_string(FAKE_PACKAGENAME)). |
799 | + Times(1) |
800 | + .WillOnce(Return(FAKE_JSON_MANIFEST_NONREMOVABLE)); |
801 | + |
802 | iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest, |
803 | ManifestError error){ |
804 | ASSERT_TRUE(error == ManifestError::NoError); |
805 | @@ -397,47 +411,43 @@ |
806 | }); |
807 | } |
808 | |
809 | -TEST(ClickInterface, testGetManifestsCorrectCommand) |
810 | + |
811 | +TEST(ClickInterface, testGetManifestsEmptyJson) |
812 | { |
813 | FakeClickInterface iface; |
814 | - std::string command = "click list --manifest"; |
815 | - EXPECT_CALL(iface, run_process(command, _)). |
816 | - Times(1); |
817 | - iface.get_manifests([](ManifestList, ManifestError){}); |
818 | + FakeClickDatabase db; |
819 | + EXPECT_CALL(iface, getClickDatabase()). |
820 | + Times(1) |
821 | + .WillOnce(Return(&db)); |
822 | + |
823 | + EXPECT_CALL(db, get_manifests_as_string()). |
824 | + Times(1) |
825 | + .WillOnce(Return("[]")); |
826 | + |
827 | + iface.get_manifests([](ManifestList manifests, ManifestError error){ |
828 | + ASSERT_TRUE(error == ManifestError::NoError); |
829 | + ASSERT_EQ(0, manifests.size()); |
830 | + }); |
831 | } |
832 | |
833 | TEST_F(ClickInterfaceTest, testGetManifestsParseError) |
834 | { |
835 | FakeClickInterface iface; |
836 | - EXPECT_CALL(iface, run_process(_, _)). |
837 | - Times(1). |
838 | - WillOnce(Invoke([&](const std::string&, |
839 | - std::function<void(int, const std::string&, |
840 | - const std::string&)> callback){ |
841 | - callback(0, "INVALID JSON", ""); |
842 | - })); |
843 | + FakeClickDatabase db; |
844 | + EXPECT_CALL(iface, getClickDatabase()). |
845 | + Times(1) |
846 | + .WillOnce(Return(&db)); |
847 | + |
848 | + EXPECT_CALL(db, get_manifests_as_string()). |
849 | + Times(1) |
850 | + .WillOnce(Return("INVALID JSON")); |
851 | + |
852 | EXPECT_CALL(*this, manifests_callback(_, ManifestError::ParseError)); |
853 | iface.get_manifests([this](ManifestList manifests, ManifestError error){ |
854 | manifests_callback(manifests, error); |
855 | }); |
856 | } |
857 | |
858 | -TEST_F(ClickInterfaceTest, testGetManifestsCommandFailed) |
859 | -{ |
860 | - FakeClickInterface iface; |
861 | - EXPECT_CALL(iface, run_process(_, _)). |
862 | - Times(1). |
863 | - WillOnce(Invoke([&](const std::string&, |
864 | - std::function<void(int, const std::string&, |
865 | - const std::string&)> callback){ |
866 | - callback(-1, "", "CRITICAL: FAIL"); |
867 | - })); |
868 | - EXPECT_CALL(*this, manifests_callback(_, ManifestError::CallError)); |
869 | - iface.get_manifests([this](ManifestList manifests, ManifestError error){ |
870 | - manifests_callback(manifests, error); |
871 | - }); |
872 | -} |
873 | - |
874 | TEST_F(ClickInterfaceTest, testGetManifestsParsed) |
875 | { |
876 | FakeClickInterface iface; |
877 | @@ -445,13 +455,15 @@ |
878 | FAKE_JSON_MANIFEST_REMOVABLE + "]"; |
879 | ManifestList expected = manifest_list_from_json(expected_str); |
880 | |
881 | - EXPECT_CALL(iface, run_process(_, _)). |
882 | - Times(1). |
883 | - WillOnce(Invoke([&](const std::string&, |
884 | - std::function<void(int, const std::string&, |
885 | - const std::string&)> callback){ |
886 | - callback(0, expected_str, ""); |
887 | - })); |
888 | + FakeClickDatabase db; |
889 | + EXPECT_CALL(iface, getClickDatabase()). |
890 | + Times(1) |
891 | + .WillOnce(Return(&db)); |
892 | + |
893 | + EXPECT_CALL(db, get_manifests_as_string()). |
894 | + Times(1) |
895 | + .WillOnce(Return(expected_str)); |
896 | + |
897 | iface.get_manifests([expected](ManifestList manifests, ManifestError error){ |
898 | ASSERT_TRUE(error == ManifestError::NoError); |
899 | ASSERT_TRUE(manifests.size() == expected.size()); |
900 | |
901 | === added file 'scope/tests/test_libclick.cpp' |
902 | --- scope/tests/test_libclick.cpp 1970-01-01 00:00:00 +0000 |
903 | +++ scope/tests/test_libclick.cpp 2014-05-21 14:12:22 +0000 |
904 | @@ -0,0 +1,84 @@ |
905 | +/* |
906 | + * Copyright (C) 2014 Canonical Ltd. |
907 | + * |
908 | + * This program is free software: you can redistribute it and/or modify it |
909 | + * under the terms of the GNU General Public License version 3, as published |
910 | + * by the Free Software Foundation. |
911 | + * |
912 | + * This program is distributed in the hope that it will be useful, but |
913 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
914 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
915 | + * PURPOSE. See the GNU General Public License for more details. |
916 | + * |
917 | + * You should have received a copy of the GNU General Public License along |
918 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
919 | + * |
920 | + * In addition, as a special exception, the copyright holders give |
921 | + * permission to link the code of portions of this program with the |
922 | + * OpenSSL library under certain conditions as described in each |
923 | + * individual source file, and distribute linked combinations |
924 | + * including the two. |
925 | + * You must obey the GNU General Public License in all respects |
926 | + * for all of the code used other than OpenSSL. If you modify |
927 | + * file(s) with this exception, you may extend this exception to your |
928 | + * version of the file(s), but you are not obligated to do so. If you |
929 | + * do not wish to do so, delete this exception statement from your |
930 | + * version. If you delete this exception statement from all source |
931 | + * files in the program, then also delete it here. |
932 | + */ |
933 | + |
934 | +// click framework |
935 | +#include <click.h> |
936 | +#include <glib.h> |
937 | +#include <glib-object.h> |
938 | + |
939 | +#include <gmock/gmock.h> |
940 | +#include <gtest/gtest.h> |
941 | + |
942 | +#include <click/libclick.h> |
943 | + |
944 | +namespace { |
945 | + |
946 | +class FakeFramework : public libclick::Framework |
947 | +{ |
948 | +public: |
949 | + MOCK_METHOD0(_click_framework_get_frameworks, GList*()); |
950 | +}; |
951 | + |
952 | + |
953 | +} |
954 | + |
955 | +TEST(Libclick, getAvailableFrameworksTwoResults) |
956 | +{ |
957 | + using namespace ::testing; |
958 | + |
959 | + FakeFramework fake_framework; |
960 | + GList *response = NULL; |
961 | + |
962 | + GObject *result1 = (GObject*)g_object_new(CLICK_TYPE_FRAMEWORK, "name", "abc", NULL); |
963 | + GObject *result2 = (GObject*)g_object_new(CLICK_TYPE_FRAMEWORK, "name", "def", NULL); |
964 | + response = g_list_append(response, result1); |
965 | + response = g_list_append(response, result2); |
966 | + |
967 | + EXPECT_CALL(fake_framework, _click_framework_get_frameworks()) |
968 | + .Times(1) |
969 | + .WillOnce(Return(response)); |
970 | + auto frameworks = fake_framework.get_frameworks(); |
971 | + std::vector<std::string> expected = {"abc", "def"}; |
972 | + EXPECT_EQ(expected, frameworks); |
973 | + |
974 | + g_list_free(response); |
975 | +} |
976 | + |
977 | +TEST(Libclick, getAvailableFrameworksNoResults) |
978 | +{ |
979 | + using namespace ::testing; |
980 | + |
981 | + FakeFramework fake_framework; |
982 | + GList *response = NULL; |
983 | + EXPECT_CALL(fake_framework, _click_framework_get_frameworks()) |
984 | + .Times(1) |
985 | + .WillOnce(Return(response)); |
986 | + auto frameworks = fake_framework.get_frameworks(); |
987 | + EXPECT_EQ(0, frameworks.size()); |
988 | +} |
FAILED: Continuous integration, rev:270 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- ci/77/ jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- amd64-ci/ 52/console jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 51/console jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- i386-ci/ 51/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/ 77/rebuild
http://