Merge lp:~ted/url-dispatcher/testability into lp:url-dispatcher/13.10

Proposed by Ted Gould
Status: Merged
Approved by: Charles Kerr
Approved revision: 49
Merged at revision: 30
Proposed branch: lp:~ted/url-dispatcher/testability
Merge into: lp:url-dispatcher/13.10
Diff against target: 571 lines (+373/-29)
11 files modified
CMakeLists.txt (+15/-4)
debian/control (+1/-0)
service/CMakeLists.txt (+17/-2)
service/dispatcher.c (+42/-23)
service/dispatcher.h (+31/-0)
service/service.c (+39/-0)
tests/CMakeLists.txt (+40/-0)
tests/dispatcher-test.cc (+87/-0)
tests/recoverable-problem-mock.c (+28/-0)
tests/upstart-app-launch-mock.c (+43/-0)
tests/upstart-app-launch-mock.h (+30/-0)
To merge this branch: bzr merge lp:~ted/url-dispatcher/testability
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+187835@code.launchpad.net

Commit message

Make dispatcher more testable and add some application:/// tests

Description of the change

Creates a couple of small library mocks instead of relying on needing a DBus mock which was difficult and on another branch. Breaks things out so we can use those and then adds some tests for the application:/// URL.

And, it found a bug! The bug is fixed as well.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~ted/url-dispatcher/testability updated
48. By Ted Gould

Make sure to get gtest too

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~ted/url-dispatcher/testability updated
49. By Ted Gould

Cherry pick r43 from the app-id-url branch to make cancelling better

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) wrote :

These tests smell a little like indicator-session.

Looks good even despite that ;)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2013-09-18 14:58:19 +0000
3+++ CMakeLists.txt 2013-09-26 20:54:42 +0000
4@@ -1,6 +1,9 @@
5-project(url-dispatcher C)
6+project(url-dispatcher C CXX)
7 cmake_minimum_required(VERSION 2.8.9)
8
9+option (enable_tests "Build tests" ON)
10+option (enable_lcov "Generate Coverage Reports" ON)
11+
12 set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}")
13
14 set(PACKAGE ${CMAKE_PROJECT_NAME})
15@@ -65,7 +68,15 @@
16 add_subdirectory(liburl-dispatcher)
17 add_subdirectory(tools)
18
19-# TODO
20-# enable_testing()
21-# add_subdirectory(tests)
22+# testing & coverage
23+if (${enable_tests})
24+ set (GTEST_SOURCE_DIR /usr/src/gtest/src)
25+ set (GTEST_INCLUDE_DIR ${GTEST_SOURCE_DIR}/..)
26+ set (GTEST_LIBS -lpthread)
27+ enable_testing ()
28+ if (${enable_lcov})
29+# include(GCov)
30+ endif ()
31+ add_subdirectory(tests)
32+endif ()
33
34
35=== modified file 'debian/control'
36--- debian/control 2013-09-18 14:58:19 +0000
37+++ debian/control 2013-09-26 20:54:42 +0000
38@@ -10,6 +10,7 @@
39 intltool,
40 libdbus-1-dev,
41 libglib2.0-dev,
42+ libgtest-dev,
43 libupstart-app-launch1-dev,
44 python,
45 Standards-Version: 3.9.4
46
47=== modified file 'service/CMakeLists.txt'
48--- service/CMakeLists.txt 2013-09-20 01:15:27 +0000
49+++ service/CMakeLists.txt 2013-09-26 20:54:42 +0000
50@@ -28,16 +28,31 @@
51 )
52
53 ###########################
54+# Dispatcher Lib
55+###########################
56+
57+add_library(dispatcher-lib STATIC
58+ dispatcher.h
59+ dispatcher.c)
60+
61+target_link_libraries(dispatcher-lib
62+ service-generated
63+ ${GLIB2_LIBRARIES}
64+ ${GOBJECT2_LIBRARIES}
65+ ${GIO2_LIBRARIES}
66+)
67+
68+###########################
69 # Service Executable
70 ###########################
71
72 include_directories(${CMAKE_CURRENT_BINARY_DIR})
73
74-add_executable(service-exec dispatcher.c recoverable-problem.h recoverable-problem.c)
75+add_executable(service-exec service.c recoverable-problem.h recoverable-problem.c)
76
77 set_target_properties(service-exec PROPERTIES OUTPUT_NAME "url-dispatcher")
78
79-target_link_libraries(service-exec service-generated ${UPSTART_APP_LAUNCH_LIBRARIES})
80+target_link_libraries(service-exec dispatcher-lib ${UPSTART_APP_LAUNCH_LIBRARIES})
81
82 ###########################
83 # Installation
84
85=== modified file 'service/dispatcher.c'
86--- service/dispatcher.c 2013-09-20 01:15:27 +0000
87+++ service/dispatcher.c 2013-09-26 20:54:42 +0000
88@@ -17,11 +17,11 @@
89
90 #include <gio/gio.h>
91 #include <upstart-app-launch.h>
92+#include "dispatcher.h"
93 #include "service-iface.h"
94 #include "recoverable-problem.h"
95
96 /* Globals */
97-static GMainLoop * mainloop = NULL;
98 static GCancellable * cancellable = NULL;
99 static ServiceIfaceComCanonicalURLDispatcher * skel = NULL;
100 static GRegex * applicationre = NULL;
101@@ -200,7 +200,7 @@
102
103 /* Get a URL off of the bus */
104 static gboolean
105-dispatch_url (GObject * skel, GDBusMethodInvocation * invocation, const gchar * url, gpointer user_data)
106+dispatch_url_cb (GObject * skel, GDBusMethodInvocation * invocation, const gchar * url, gpointer user_data)
107 {
108 g_debug("Dispatching URL: %s", url);
109
110@@ -208,6 +208,19 @@
111 return bad_url(invocation, url);
112 }
113
114+ if (dispatch_url(url)) {
115+ g_dbus_method_invocation_return_value(invocation, NULL);
116+ } else {
117+ bad_url(invocation, url);
118+ }
119+
120+ return TRUE;
121+}
122+
123+/* The core of the URL handling */
124+gboolean
125+dispatch_url (const gchar * url)
126+{
127 /* Special case the application URL */
128 GMatchInfo * appmatch = NULL;
129 if (g_regex_match(applicationre, url, 0, &appmatch)) {
130@@ -217,7 +230,6 @@
131 g_free(appid);
132 g_match_info_free(appmatch);
133
134- g_dbus_method_invocation_return_value(invocation, NULL);
135 return TRUE;
136 }
137 g_match_info_free(appmatch);
138@@ -231,19 +243,19 @@
139 if (g_regex_match(url_types[i].regex_object, url, 0, NULL)) {
140 pass_url_to_app(url_types[i].app_id, url);
141
142- g_dbus_method_invocation_return_value(invocation, NULL);
143 return TRUE;
144 }
145 }
146
147- return bad_url(invocation, url);
148+ return FALSE;
149 }
150
151 /* We're goin' down cap'n */
152 static void
153 name_lost (GDBusConnection * con, const gchar * name, gpointer user_data)
154 {
155- g_error("Unable to get name '%s'", name);
156+ GMainLoop * mainloop = (GMainLoop *)user_data;
157+ g_warning("Unable to get name '%s'", name);
158 g_main_loop_quit(mainloop);
159 return;
160 }
161@@ -252,14 +264,18 @@
162 static void
163 bus_got (GObject * obj, GAsyncResult * res, gpointer user_data)
164 {
165+ GMainLoop * mainloop = (GMainLoop *)user_data;
166 GDBusConnection * bus = NULL;
167 GError * error = NULL;
168
169 bus = g_bus_get_finish(res, &error);
170
171 if (error != NULL) {
172- g_error("Unable to connect to D-Bus: %s", error->message);
173- g_main_loop_quit(mainloop);
174+ if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
175+ g_error("Unable to connect to D-Bus: %s", error->message);
176+ g_main_loop_quit(mainloop);
177+ }
178+ g_error_free(error);
179 return;
180 }
181
182@@ -277,31 +293,34 @@
183 G_BUS_NAME_OWNER_FLAGS_NONE, /* flags */
184 NULL, /* name acquired */
185 name_lost,
186- NULL, NULL); /* user data */
187+ user_data, NULL); /* user data */
188
189 g_object_unref(bus);
190
191 return;
192 }
193
194-/* Where it all begins */
195-int
196-main (int argc, char * argv[])
197+/* Initialize all the globals */
198+gboolean
199+dispatcher_init (GMainLoop * mainloop)
200 {
201- mainloop = g_main_loop_new(NULL, FALSE);
202 cancellable = g_cancellable_new();
203- applicationre = g_regex_new("^application:///([a-zA-Z0-9_-]*)\\.desktop$", 0, 0, NULL);
204+ applicationre = g_regex_new("^application:///([a-zA-Z0-9_\\.-]*)\\.desktop$", 0, 0, NULL);
205
206- g_bus_get(G_BUS_TYPE_SESSION, cancellable, bus_got, NULL);
207+ g_bus_get(G_BUS_TYPE_SESSION, cancellable, bus_got, mainloop);
208
209 skel = service_iface_com_canonical_urldispatcher_skeleton_new();
210- g_signal_connect(skel, "handle-dispatch-url", G_CALLBACK(dispatch_url), NULL);
211-
212- /* Run Main */
213- g_main_loop_run(mainloop);
214-
215- /* Clean up globals */
216- g_main_loop_unref(mainloop);
217+ g_signal_connect(skel, "handle-dispatch-url", G_CALLBACK(dispatch_url_cb), NULL);
218+
219+ return TRUE;
220+}
221+
222+/* Clean up all the globals */
223+gboolean
224+dispatcher_shutdown (void)
225+{
226+ g_cancellable_cancel(cancellable);
227+
228 g_object_unref(cancellable);
229 g_object_unref(skel);
230 g_regex_unref(applicationre);
231@@ -311,5 +330,5 @@
232 g_clear_pointer(&url_types[i].regex_object, g_regex_unref);
233 }
234
235- return 0;
236+ return TRUE;
237 }
238
239=== added file 'service/dispatcher.h'
240--- service/dispatcher.h 1970-01-01 00:00:00 +0000
241+++ service/dispatcher.h 2013-09-26 20:54:42 +0000
242@@ -0,0 +1,31 @@
243+/**
244+ * Copyright (C) 2013 Canonical, Ltd.
245+ *
246+ * This program is free software: you can redistribute it and/or modify it under
247+ * the terms of the GNU Lesser General Public License version 3, as published by
248+ * the Free Software Foundation.
249+ *
250+ * This program is distributed in the hope that it will be useful, but WITHOUT
251+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
252+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
253+ * Lesser General Public License for more details.
254+ *
255+ * You should have received a copy of the GNU Lesser General Public License
256+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
257+ *
258+ */
259+
260+#include <glib.h>
261+
262+#ifndef __DISPATCHER_H__
263+#define __DISPATCHER_H__ 1
264+
265+G_BEGIN_DECLS
266+
267+gboolean dispatcher_init (GMainLoop * mainloop);
268+gboolean dispatcher_shutdown (void);
269+gboolean dispatch_url (const gchar * url);
270+
271+G_END_DECLS
272+
273+#endif /* __DISPATCHER_H__ */
274
275=== added file 'service/service.c'
276--- service/service.c 1970-01-01 00:00:00 +0000
277+++ service/service.c 2013-09-26 20:54:42 +0000
278@@ -0,0 +1,39 @@
279+/**
280+ * Copyright (C) 2013 Canonical, Ltd.
281+ *
282+ * This program is free software: you can redistribute it and/or modify it under
283+ * the terms of the GNU Lesser General Public License version 3, as published by
284+ * the Free Software Foundation.
285+ *
286+ * This program is distributed in the hope that it will be useful, but WITHOUT
287+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
288+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
289+ * Lesser General Public License for more details.
290+ *
291+ * You should have received a copy of the GNU Lesser General Public License
292+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
293+ *
294+ */
295+
296+#include <glib.h>
297+#include "dispatcher.h"
298+
299+GMainLoop * mainloop = NULL;
300+
301+/* Where it all begins */
302+int
303+main (int argc, char * argv[])
304+{
305+ mainloop = g_main_loop_new(NULL, FALSE);
306+
307+ dispatcher_init(mainloop);
308+
309+ /* Run Main */
310+ g_main_loop_run(mainloop);
311+
312+ /* Clean up globals */
313+ dispatcher_shutdown();
314+ g_main_loop_unref(mainloop);
315+
316+ return 0;
317+}
318
319=== added directory 'tests'
320=== added file 'tests/CMakeLists.txt'
321--- tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
322+++ tests/CMakeLists.txt 2013-09-26 20:54:42 +0000
323@@ -0,0 +1,40 @@
324+
325+###########################
326+# Google Test
327+###########################
328+
329+include_directories(${GTEST_INCLUDE_DIR})
330+
331+add_library (gtest STATIC
332+ ${GTEST_SOURCE_DIR}/gtest-all.cc
333+ ${GTEST_SOURCE_DIR}/gtest_main.cc)
334+
335+
336+###########################
337+# Mock Lib
338+###########################
339+
340+add_library(mock-lib STATIC
341+ recoverable-problem-mock.c
342+ upstart-app-launch-mock.h
343+ upstart-app-launch-mock.c)
344+
345+target_link_libraries(mock-lib
346+ ${GLIB2_LIBRARIES}
347+)
348+
349+###########################
350+# App ID URL test
351+###########################
352+
353+include_directories("${CMAKE_SOURCE_DIR}/service")
354+
355+add_executable (dispatcher-test dispatcher-test.cc)
356+target_link_libraries (dispatcher-test
357+ dispatcher-lib
358+ mock-lib
359+ gtest
360+ ${GTEST_LIBS})
361+
362+add_test (dispatcher-test dispatcher-test)
363+
364
365=== added file 'tests/dispatcher-test.cc'
366--- tests/dispatcher-test.cc 1970-01-01 00:00:00 +0000
367+++ tests/dispatcher-test.cc 2013-09-26 20:54:42 +0000
368@@ -0,0 +1,87 @@
369+/**
370+ * Copyright (C) 2013 Canonical, Ltd.
371+ *
372+ * This program is free software: you can redistribute it and/or modify it under
373+ * the terms of the GNU Lesser General Public License version 3, as published by
374+ * the Free Software Foundation.
375+ *
376+ * This program is distributed in the hope that it will be useful, but WITHOUT
377+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
378+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
379+ * Lesser General Public License for more details.
380+ *
381+ * You should have received a copy of the GNU Lesser General Public License
382+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
383+ *
384+ */
385+
386+
387+#include <gio/gio.h>
388+#include <gtest/gtest.h>
389+#include "dispatcher.h"
390+#include "upstart-app-launch-mock.h"
391+
392+class DispatcherTest : public ::testing::Test
393+{
394+ private:
395+ GTestDBus * testbus = NULL;
396+ GMainLoop * mainloop = NULL;
397+
398+ protected:
399+ virtual void SetUp() {
400+ testbus = g_test_dbus_new(G_TEST_DBUS_NONE);
401+ g_test_dbus_up(testbus);
402+
403+ mainloop = g_main_loop_new(NULL, FALSE);
404+ dispatcher_init(mainloop);
405+
406+ return;
407+ }
408+
409+ virtual void TearDown() {
410+ dispatcher_shutdown();
411+
412+ /* Clean up queued events */
413+ while (g_main_pending()) {
414+ g_main_iteration(TRUE);
415+ }
416+
417+ g_main_loop_unref(mainloop);
418+
419+ upstart_app_launch_mock_clear_last_app_id();
420+
421+ g_test_dbus_down(testbus);
422+ g_object_unref(testbus);
423+ return;
424+ }
425+};
426+
427+TEST_F(DispatcherTest, ApplicationTest)
428+{
429+ /* Good sanity check */
430+ dispatch_url("application:///foo.desktop");
431+ ASSERT_STREQ("foo", upstart_app_launch_mock_get_last_app_id());
432+ upstart_app_launch_mock_clear_last_app_id();
433+
434+ /* No .desktop */
435+ dispatch_url("application:///foo");
436+ ASSERT_TRUE(NULL == upstart_app_launch_mock_get_last_app_id());
437+ upstart_app_launch_mock_clear_last_app_id();
438+
439+ /* Missing a / */
440+ dispatch_url("application://foo.desktop");
441+ ASSERT_TRUE(NULL == upstart_app_launch_mock_get_last_app_id());
442+ upstart_app_launch_mock_clear_last_app_id();
443+
444+ /* Good with hyphens */
445+ dispatch_url("application:///my-really-cool-app.desktop");
446+ ASSERT_STREQ("my-really-cool-app", upstart_app_launch_mock_get_last_app_id());
447+ upstart_app_launch_mock_clear_last_app_id();
448+
449+ /* Good Click Style */
450+ dispatch_url("application:///com.test.foo_bar-app_0.3.4.desktop");
451+ ASSERT_STREQ("com.test.foo_bar-app_0.3.4", upstart_app_launch_mock_get_last_app_id());
452+ upstart_app_launch_mock_clear_last_app_id();
453+
454+ return;
455+}
456
457=== added file 'tests/recoverable-problem-mock.c'
458--- tests/recoverable-problem-mock.c 1970-01-01 00:00:00 +0000
459+++ tests/recoverable-problem-mock.c 2013-09-26 20:54:42 +0000
460@@ -0,0 +1,28 @@
461+/*
462+ * Copyright 2013 Canonical Ltd.
463+ *
464+ * This program is free software: you can redistribute it and/or modify it
465+ * under the terms of the GNU General Public License version 3, as published
466+ * by the Free Software Foundation.
467+ *
468+ * This program is distributed in the hope that it will be useful, but
469+ * WITHOUT ANY WARRANTY; without even the implied warranties of
470+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
471+ * PURPOSE. See the GNU General Public License for more details.
472+ *
473+ * You should have received a copy of the GNU General Public License along
474+ * with this program. If not, see <http://www.gnu.org/licenses/>.
475+ *
476+ * Authors:
477+ * Ted Gould <ted.gould@canonical.com>
478+ */
479+
480+#include <gio/gio.h>
481+#include "recoverable-problem.h"
482+
483+void
484+report_recoverable_problem (const gchar * signature, GPid report_pid, gboolean wait, gchar * additional_properties[])
485+{
486+
487+ return;
488+}
489
490=== added file 'tests/upstart-app-launch-mock.c'
491--- tests/upstart-app-launch-mock.c 1970-01-01 00:00:00 +0000
492+++ tests/upstart-app-launch-mock.c 2013-09-26 20:54:42 +0000
493@@ -0,0 +1,43 @@
494+/**
495+ * Copyright (C) 2013 Canonical, Ltd.
496+ *
497+ * This program is free software: you can redistribute it and/or modify it under
498+ * the terms of the GNU Lesser General Public License version 3, as published by
499+ * the Free Software Foundation.
500+ *
501+ * This program is distributed in the hope that it will be useful, but WITHOUT
502+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
503+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
504+ * Lesser General Public License for more details.
505+ *
506+ * You should have received a copy of the GNU Lesser General Public License
507+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
508+ *
509+ */
510+
511+#include <upstart-app-launch.h>
512+#include "upstart-app-launch-mock.h"
513+
514+static gchar * last_appid = NULL;
515+
516+gboolean
517+upstart_app_launch_start_application (const gchar * appid, const gchar * const * uris)
518+{
519+ upstart_app_launch_mock_clear_last_app_id();
520+ last_appid = g_strdup(appid);
521+ return TRUE;
522+}
523+
524+void
525+upstart_app_launch_mock_clear_last_app_id (void)
526+{
527+ g_free(last_appid);
528+ last_appid = NULL;
529+ return;
530+}
531+
532+gchar *
533+upstart_app_launch_mock_get_last_app_id (void)
534+{
535+ return last_appid;
536+}
537
538=== added file 'tests/upstart-app-launch-mock.h'
539--- tests/upstart-app-launch-mock.h 1970-01-01 00:00:00 +0000
540+++ tests/upstart-app-launch-mock.h 2013-09-26 20:54:42 +0000
541@@ -0,0 +1,30 @@
542+/**
543+ * Copyright (C) 2013 Canonical, Ltd.
544+ *
545+ * This program is free software: you can redistribute it and/or modify it under
546+ * the terms of the GNU Lesser General Public License version 3, as published by
547+ * the Free Software Foundation.
548+ *
549+ * This program is distributed in the hope that it will be useful, but WITHOUT
550+ * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
551+ * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
552+ * Lesser General Public License for more details.
553+ *
554+ * You should have received a copy of the GNU Lesser General Public License
555+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
556+ *
557+ */
558+
559+#include <glib.h>
560+
561+#ifndef __UPSTART_APP_LAUNCH_MOCK__
562+#define __UPSTART_APP_LAUNCH_MOCK__ 1
563+
564+G_BEGIN_DECLS
565+
566+void upstart_app_launch_mock_clear_last_app_id (void);
567+gchar * upstart_app_launch_mock_get_last_app_id (void);
568+
569+G_END_DECLS
570+
571+#endif /* __UPSTART_APP_LAUNCH_MOCK__ */

Subscribers

People subscribed via source and target branches