Merge lp:~mvo/unity-scope-click/lp1292645-use-libclick2 into lp:unity-scope-click/devel

Proposed by Michael Vogt
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
Reviewer Review Type Date Requested Status
dobey (community) Needs Fixing
PS Jenkins bot (community) continuous-integration Needs Fixing
Review via email: mp+220433@code.launchpad.net

Commit message

Use libclick to gather information about installed frameworks/installed apps. This fixes lp:1292645.

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://code.launchpad.net/~mvo/unity-scope-click/lp1292645-use-libclick/+merge/220061 in a fresh branch as the changes are big compared to the original version.

Based on https://code.launchpad.net/~alecu/unity-scope-click/lp1292645 and lp:~mvo/unity-scope-click/lp1292645-use-libclick.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
271. By Michael Vogt

add missing click libs to libclickscope/click/

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
272. By Michael Vogt

add missing ubuntu-sdk-libs to test control

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
dobey (dobey) wrote :

Thanks for working on this Michael.

You need to update to the tip of /devel. The configuration.{cpp,h} and associated tests have been moved under libclickscope/ now, so you'll need to update and resolve the conflicts by getting your changes under that directory instead.

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_list_from_json(manifests_json);
212 + callback(manifests, ManifestError::NoError);
213 + } catch (...) {
214 + callback(ManifestList(), ManifestError::ParseError);
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_list_from_json(manifests_json);
} catch (...) {
    callback(ManifestList(), ManifestError::ParseError);
    return;
}
callback(manifests, ManifestError::NoError);

This way callback() will only be called once, and any exceptions it throws won't be lost inside the try block.

review: Needs Fixing

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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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+}

Subscribers

People subscribed via source and target branches

to all changes: