Merge lp:~ted/ubuntu-app-launch/rm-rf-upstart into lp:ubuntu-app-launch
- rm-rf-upstart
- Merge into trunk.17.04
Status: | Merged |
---|---|
Approved by: | Pete Woods |
Approved revision: | 309 |
Merged at revision: | 303 |
Proposed branch: | lp:~ted/ubuntu-app-launch/rm-rf-upstart |
Merge into: | lp:ubuntu-app-launch |
Prerequisite: | lp:~ted/ubuntu-app-launch/jobs-helpers |
Diff against target: |
5635 lines (+762/-4229) 47 files modified
CMakeLists.txt (+0/-61) application-failed.c (+0/-80) application-job.c (+0/-113) cgroup-reap-all.c (+0/-65) debian/control (+2/-7) debian/ubuntu-app-launch.install (+0/-1) docs/index.rst (+2/-28) exec-line-exec-trace.tp (+0/-19) exec-line-exec.c (+0/-170) helpers.c (+0/-126) helpers.h (+0/-12) libubuntu-app-launch/CMakeLists.txt (+0/-2) libubuntu-app-launch/helper.cpp (+468/-0) libubuntu-app-launch/jobs-base.cpp (+4/-15) libubuntu-app-launch/jobs-upstart.cpp (+0/-1178) libubuntu-app-launch/jobs-upstart.h (+0/-100) libubuntu-app-launch/registry-impl.cpp (+0/-1) libubuntu-app-launch/second-exec-core.c (+0/-2) libubuntu-app-launch/ubuntu-app-launch.cpp (+0/-1) tests/CMakeLists.txt (+3/-43) tests/cgroup-reap-test.cc (+0/-145) tests/exec-test-archcolon.sh (+0/-18) tests/exec-test-colon.sh (+0/-18) tests/exec-test-full.sh (+0/-18) tests/exec-test-noarch.sh (+0/-18) tests/exec-test-noinit.sh (+0/-18) tests/exec-test-nullstr.sh (+0/-18) tests/exec-test.sh.in (+0/-62) tests/exec-util-test.cc (+0/-349) tests/failure-test.cc (+0/-165) tests/helper-test.cc (+0/-105) tests/libual-cpp-test.cc (+161/-812) tests/systemd-mock.h (+5/-0) tests/zg-mock.h (+117/-0) untrusted-helper-type-end.c (+0/-66) upstart-jobs/CMakeLists.txt (+0/-71) upstart-jobs/application-click.conf.in (+0/-36) upstart-jobs/application-failed.conf.in (+0/-6) upstart-jobs/application-legacy.conf.in (+0/-36) upstart-jobs/application-logrotate.conf (+0/-15) upstart-jobs/application-snap.conf.in (+0/-37) upstart-jobs/application.conf.in (+0/-17) upstart-jobs/test-conffile.sh (+0/-12) upstart-jobs/untrusted-helper-logrotate.conf (+0/-13) upstart-jobs/untrusted-helper-type-end.conf.in (+0/-9) upstart-jobs/untrusted-helper.conf.in (+0/-33) zg-report-app.c (+0/-108) |
To merge this branch: | bzr merge lp:~ted/ubuntu-app-launch/rm-rf-upstart |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Pete Woods (community) | Approve | ||
unity-api-1-bot | continuous-integration | Needs Fixing | |
Review via email: mp+318039@code.launchpad.net |
This proposal supersedes a proposal from 2017-02-14.
Commit message
Remove Upstart
Description of the change
Removes upstart implementations and dependencies. The tests do not work and are fixed in the rm-rf-click branch. They should be landed together.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:299
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:305
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:306
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:308
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:309
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Pete Woods (pete-woods) : | # |
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2017-03-21 03:20:55 +0000 |
3 | +++ CMakeLists.txt 2017-03-21 03:20:55 +0000 |
4 | @@ -79,9 +79,6 @@ |
5 | pkg_check_modules(CLICK REQUIRED click-0.4>=0.4.18) |
6 | include_directories(${CLICK_INCLUDE_DIRS}) |
7 | |
8 | -pkg_check_modules(LIBUPSTART REQUIRED libupstart) |
9 | -include_directories(${LIBUPSTART_INCLUDE_DIRS}) |
10 | - |
11 | pkg_check_modules(DBUS REQUIRED dbus-1) |
12 | include_directories(${DBUS_INCLUDE_DIRS}) |
13 | |
14 | @@ -130,62 +127,6 @@ |
15 | install(TARGETS desktop-hook RUNTIME DESTINATION "${pkglibexecdir}") |
16 | |
17 | #################### |
18 | -# exec-line-exec |
19 | -#################### |
20 | - |
21 | -add_lttng_gen_tp(NAME exec-line-exec-trace) |
22 | -include_directories(${CMAKE_CURRENT_BINARY_DIR}) |
23 | -add_executable(exec-line-exec exec-line-exec.c "${CMAKE_CURRENT_BINARY_DIR}/exec-line-exec-trace.c") |
24 | -set_target_properties(exec-line-exec PROPERTIES OUTPUT_NAME "exec-line-exec") |
25 | -target_link_libraries(exec-line-exec helpers ${LTTNG_LIBRARIES}) |
26 | -install(TARGETS exec-line-exec RUNTIME DESTINATION "${pkglibexecdir}") |
27 | - |
28 | -#################### |
29 | -# zg-report-app |
30 | -#################### |
31 | - |
32 | -add_executable(zg-report-app zg-report-app.c) |
33 | -set_target_properties(zg-report-app PROPERTIES OUTPUT_NAME "zg-report-app") |
34 | -target_link_libraries(zg-report-app ubuntu-launcher ${ZEITGEIST_LIBRARIES} ${GOBJECT2_LIBRARIES} ${GLIB2_LIBRARIES}) |
35 | -install(TARGETS zg-report-app RUNTIME DESTINATION "${pkglibexecdir}") |
36 | - |
37 | -#################### |
38 | -# application-job |
39 | -#################### |
40 | - |
41 | -add_executable(application-job application-job.c) |
42 | -set_target_properties(application-job PROPERTIES OUTPUT_NAME "application-job") |
43 | -target_link_libraries(application-job ubuntu-launcher) |
44 | -install(TARGETS application-job RUNTIME DESTINATION "${pkglibexecdir}") |
45 | - |
46 | -#################### |
47 | -# application-failed |
48 | -#################### |
49 | - |
50 | -add_executable(application-failed application-failed.c) |
51 | -set_target_properties(application-failed PROPERTIES OUTPUT_NAME "application-failed") |
52 | -target_link_libraries(application-failed ${GIO2_LIBRARIES}) |
53 | -install(TARGETS application-failed RUNTIME DESTINATION "${pkglibexecdir}") |
54 | - |
55 | -#################### |
56 | -# untrusted-helper-type-end |
57 | -#################### |
58 | - |
59 | -add_executable(untrusted-helper-type-end untrusted-helper-type-end.c) |
60 | -set_target_properties(untrusted-helper-type-end PROPERTIES OUTPUT_NAME "untrusted-helper-type-end") |
61 | -target_link_libraries(untrusted-helper-type-end ubuntu-launcher) |
62 | -install(TARGETS untrusted-helper-type-end RUNTIME DESTINATION "${pkglibexecdir}") |
63 | - |
64 | -#################### |
65 | -# cgroup-reap-all |
66 | -#################### |
67 | - |
68 | -add_executable(cgroup-reap-all cgroup-reap-all.c) |
69 | -set_target_properties(cgroup-reap-all PROPERTIES OUTPUT_NAME "cgroup-reap-all") |
70 | -target_link_libraries(cgroup-reap-all helpers) |
71 | -install(TARGETS cgroup-reap-all RUNTIME DESTINATION "${pkglibexecdir}") |
72 | - |
73 | -#################### |
74 | # oom-adjust-setuid-helper |
75 | #################### |
76 | |
77 | @@ -200,7 +141,6 @@ |
78 | configure_file("ubuntu-app-launch-desktop.click-hook.in" "${CMAKE_CURRENT_SOURCE_DIR}/debian/ubuntu-app-launch-desktop.click-hook" @ONLY) |
79 | |
80 | add_subdirectory(libubuntu-app-launch) |
81 | -add_subdirectory(upstart-jobs) |
82 | add_subdirectory(tools) |
83 | add_subdirectory(ubuntu-app-test) |
84 | add_subdirectory(utils) |
85 | @@ -225,7 +165,6 @@ |
86 | TESTS |
87 | application-icon-finder-test |
88 | application-info-desktop-test |
89 | - cgroup-reap-test |
90 | exec-util-test |
91 | failure-test |
92 | helper-test |
93 | |
94 | === removed file 'application-failed.c' |
95 | --- application-failed.c 2016-12-14 21:11:09 +0000 |
96 | +++ application-failed.c 1970-01-01 00:00:00 +0000 |
97 | @@ -1,80 +0,0 @@ |
98 | - |
99 | -/* |
100 | - * Copyright 2013 Canonical Ltd. |
101 | - * |
102 | - * This program is free software: you can redistribute it and/or modify it |
103 | - * under the terms of the GNU General Public License version 3, as published |
104 | - * by the Free Software Foundation. |
105 | - * |
106 | - * This program is distributed in the hope that it will be useful, but |
107 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
108 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
109 | - * PURPOSE. See the GNU General Public License for more details. |
110 | - * |
111 | - * You should have received a copy of the GNU General Public License along |
112 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
113 | - * |
114 | - * Authors: |
115 | - * Ted Gould <ted.gould@canonical.com> |
116 | - */ |
117 | - |
118 | -#include <gio/gio.h> |
119 | - |
120 | -int |
121 | -main (int argc, char * argv[]) |
122 | -{ |
123 | - const gchar * job = g_getenv("JOB"); |
124 | - g_return_val_if_fail(job != NULL, -1); |
125 | - |
126 | - const gchar * instance = g_getenv("INSTANCE"); |
127 | - g_return_val_if_fail(instance != NULL, -1); |
128 | - |
129 | - gboolean crashed = FALSE; |
130 | - if (g_getenv("EXIT_STATUS") != NULL || g_getenv("EXIT_SIGNAL") != NULL) { |
131 | - crashed = TRUE; |
132 | - } |
133 | - |
134 | - gchar * appid = g_strdup(instance); |
135 | - gchar * lasthyphenstanding = NULL; |
136 | - if (g_strcmp0(job, "application-legacy") == 0 |
137 | - || g_strcmp0(job, "application-snap") == 0) { |
138 | - lasthyphenstanding = g_strrstr(appid, "-"); |
139 | - if (lasthyphenstanding != NULL) { |
140 | - lasthyphenstanding[0] = '\0'; |
141 | - } else { |
142 | - g_warning("Legacy job instance '%s' is missing a hyphen", appid); |
143 | - } |
144 | - } |
145 | - |
146 | - if (lasthyphenstanding == NULL) { |
147 | - lasthyphenstanding = ""; |
148 | - } else { |
149 | - lasthyphenstanding++; |
150 | - } |
151 | - |
152 | - GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
153 | - g_return_val_if_fail(bus != NULL, -1); |
154 | - |
155 | - GError * error = NULL; |
156 | - g_dbus_connection_emit_signal(bus, |
157 | - NULL, /* destination */ |
158 | - "/", /* path */ |
159 | - "com.canonical.UbuntuAppLaunch", |
160 | - "ApplicationFailed", |
161 | - g_variant_new("(sss)", appid, lasthyphenstanding, crashed ? "crash" : "start-failure"), |
162 | - &error); |
163 | - |
164 | - g_debug("Emitting failed event '%s' for app '%s'", crashed ? "crash" : "start-failure", appid); |
165 | - |
166 | - if (error != NULL) { |
167 | - g_warning("Unable to emit signal: %s", error->message); |
168 | - g_error_free(error); |
169 | - return -1; |
170 | - } |
171 | - |
172 | - g_dbus_connection_flush_sync(bus, NULL, NULL); |
173 | - g_object_unref(bus); |
174 | - g_free(appid); |
175 | - |
176 | - return 0; |
177 | -} |
178 | |
179 | === removed file 'application-job.c' |
180 | --- application-job.c 2014-04-30 16:34:06 +0000 |
181 | +++ application-job.c 1970-01-01 00:00:00 +0000 |
182 | @@ -1,113 +0,0 @@ |
183 | -/* |
184 | - * Copyright 2013 Canonical Ltd. |
185 | - * |
186 | - * This program is free software: you can redistribute it and/or modify it |
187 | - * under the terms of the GNU General Public License version 3, as published |
188 | - * by the Free Software Foundation. |
189 | - * |
190 | - * This program is distributed in the hope that it will be useful, but |
191 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
192 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
193 | - * PURPOSE. See the GNU General Public License for more details. |
194 | - * |
195 | - * You should have received a copy of the GNU General Public License along |
196 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
197 | - * |
198 | - * Authors: |
199 | - * Ted Gould <ted.gould@canonical.com> |
200 | - */ |
201 | - |
202 | -#include <gio/gio.h> |
203 | -#include "libubuntu-app-launch/ubuntu-app-launch.h" |
204 | - |
205 | -int retval = 0; |
206 | -const gchar * global_appid; |
207 | - |
208 | -static void |
209 | -app_started (const gchar * appid, gpointer user_data) |
210 | -{ |
211 | - if (g_strcmp0(appid, global_appid) != 0) |
212 | - return; |
213 | - g_debug("Application Started: %s", appid); |
214 | - g_main_loop_quit((GMainLoop *)user_data); |
215 | -} |
216 | - |
217 | -static void |
218 | -app_focus (const gchar * appid, gpointer user_data) |
219 | -{ |
220 | - if (g_strcmp0(appid, global_appid) != 0) |
221 | - return; |
222 | - g_debug("Application Focused"); |
223 | - g_main_loop_quit((GMainLoop *)user_data); |
224 | -} |
225 | - |
226 | -static void |
227 | -app_failed (const gchar * appid, UbuntuAppLaunchAppFailed failure_type, gpointer user_data) |
228 | -{ |
229 | - if (g_strcmp0(appid, global_appid) != 0) |
230 | - return; |
231 | - g_warning("Application Startup Failed"); |
232 | - retval = 1; |
233 | - g_main_loop_quit((GMainLoop *)user_data); |
234 | -} |
235 | - |
236 | -/* A fallback so that we can see what is going on. The job can not always signal |
237 | - that it has been started, and thus we wouldn't quit. Which would be a bad thing. */ |
238 | -static gboolean |
239 | -timeout_check (gpointer user_data) |
240 | -{ |
241 | - g_debug("Timeout reached"); |
242 | - g_main_loop_quit((GMainLoop *)user_data); |
243 | - return TRUE; /* Keep the source connected to avoid the disconnect error */ |
244 | -} |
245 | - |
246 | -int |
247 | -main (int argc, char * argv[]) |
248 | -{ |
249 | - GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
250 | - g_return_val_if_fail(con != NULL, 1); |
251 | - |
252 | - global_appid = g_getenv("APP_ID"); |
253 | - g_return_val_if_fail(global_appid != NULL, 1); |
254 | - |
255 | - const gchar * uris_str = g_getenv("APP_URIS"); |
256 | - gchar ** uris = NULL; |
257 | - if (uris_str != NULL) { |
258 | - GError * error = NULL; |
259 | - gint uri_count = 0; |
260 | - g_shell_parse_argv(uris_str, &uri_count, &uris, &error); |
261 | - |
262 | - if (error != NULL) { |
263 | - g_warning("Unable to parse uris '%s': %s", uris_str, error->message); |
264 | - g_error_free(error); |
265 | - } else { |
266 | - g_debug("Got %d URIs", uri_count); |
267 | - } |
268 | - } |
269 | - |
270 | - GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
271 | - |
272 | - ubuntu_app_launch_observer_add_app_started(app_started, mainloop); |
273 | - ubuntu_app_launch_observer_add_app_focus(app_focus, mainloop); |
274 | - ubuntu_app_launch_observer_add_app_failed(app_failed, mainloop); |
275 | - |
276 | - guint timer = g_timeout_add_seconds(1, timeout_check, mainloop); |
277 | - |
278 | - g_debug("Start Application: %s", global_appid); |
279 | - g_return_val_if_fail(ubuntu_app_launch_start_application(global_appid, (const gchar * const *)uris), -1); |
280 | - g_strfreev(uris); |
281 | - |
282 | - g_debug("Wait for results"); |
283 | - g_main_loop_run(mainloop); |
284 | - |
285 | - g_source_remove(timer); |
286 | - |
287 | - ubuntu_app_launch_observer_delete_app_started(app_started, mainloop); |
288 | - ubuntu_app_launch_observer_delete_app_focus(app_focus, mainloop); |
289 | - ubuntu_app_launch_observer_delete_app_failed(app_failed, mainloop); |
290 | - |
291 | - g_main_loop_unref(mainloop); |
292 | - g_object_unref(con); |
293 | - |
294 | - return retval; |
295 | -} |
296 | |
297 | === removed file 'cgroup-reap-all.c' |
298 | --- cgroup-reap-all.c 2014-11-20 20:33:59 +0000 |
299 | +++ cgroup-reap-all.c 1970-01-01 00:00:00 +0000 |
300 | @@ -1,65 +0,0 @@ |
301 | -/* |
302 | - * Copyright © 2014 Canonical Ltd. |
303 | - * |
304 | - * This program is free software: you can redistribute it and/or modify it |
305 | - * under the terms of the GNU General Public License version 3, as published |
306 | - * by the Free Software Foundation. |
307 | - * |
308 | - * This program is distributed in the hope that it will be useful, but |
309 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
310 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
311 | - * PURPOSE. See the GNU General Public License for more details. |
312 | - * |
313 | - * You should have received a copy of the GNU General Public License along |
314 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
315 | - * |
316 | - * Authors: |
317 | - * Ted Gould <ted.gould@canonical.com> |
318 | - */ |
319 | - |
320 | -#include "helpers.h" |
321 | - |
322 | -int kill (pid_t pid, int signal); |
323 | -pid_t getpgid (pid_t); |
324 | - |
325 | -int |
326 | -main (int argc, char * argv[]) |
327 | -{ |
328 | - /* Break off a new process group */ |
329 | - setpgid(0, 0); |
330 | - |
331 | - GDBusConnection * cgmanager = cgroup_manager_connection(); |
332 | - g_return_val_if_fail(cgmanager != NULL, -1); |
333 | - |
334 | - GPid selfpid = getpid(); |
335 | - GPid parentpid = getppid(); |
336 | - |
337 | - /* We're gonna try to kill things forever, literally. It's important |
338 | - enough that we can't consider failure an option. */ |
339 | - gboolean killed = TRUE; |
340 | - while (killed) { |
341 | - GList * pidlist = pids_from_cgroup(cgmanager, NULL, NULL); |
342 | - GList * head; |
343 | - |
344 | - killed = FALSE; |
345 | - |
346 | - for (head = pidlist; head != NULL; head = g_list_next(head)) { |
347 | - GPid pid = GPOINTER_TO_INT(head->data); |
348 | - |
349 | - /* We don't want to kill ourselves, or if we're being executed by |
350 | - a script, that script, either. We also don't want things in our |
351 | - process group which we forked at the opening */ |
352 | - if (pid != selfpid && pid != parentpid && getpgid(pid) != selfpid) { |
353 | - g_debug("Killing pid: %d", pid); |
354 | - kill(pid, SIGKILL); |
355 | - killed = TRUE; |
356 | - } |
357 | - } |
358 | - |
359 | - g_list_free(pidlist); |
360 | - } |
361 | - |
362 | - cgroup_manager_unref(cgmanager); |
363 | - |
364 | - return 0; |
365 | -} |
366 | |
367 | === modified file 'debian/control' |
368 | --- debian/control 2017-03-07 19:03:36 +0000 |
369 | +++ debian/control 2017-03-21 03:20:55 +0000 |
370 | @@ -23,18 +23,14 @@ |
371 | liblibertine-dev, |
372 | liblttng-ust-dev, |
373 | libmirclient-dev (>= 0.5), |
374 | - libnih-dbus-dev, |
375 | - libnih-dev, |
376 | libproperties-cpp-dev, |
377 | # For ABI check to distro version |
378 | # Make sure to set DEB_BUILD_PROFILES when bootstrapping |
379 | libubuntu-app-launch3-dev <!stage1>, |
380 | - libupstart-dev, |
381 | libwhoopsie-dev (>= 0.2.52), |
382 | libzeitgeist-2.0-dev, |
383 | gobject-introspection, |
384 | python3-dbusmock, |
385 | - upstart (>= 1.13), |
386 | Standards-Version: 3.9.4 |
387 | Homepage: http://launchpad.net/ubuntu-app-launch |
388 | # If you aren't a member of ~indicator-applet-developers but need to upload packaging changes, |
389 | @@ -46,10 +42,8 @@ |
390 | Architecture: any |
391 | Depends: ${shlibs:Depends}, |
392 | ${misc:Depends}, |
393 | - cgmanager, |
394 | click-apparmor, |
395 | - libpam-cgfs | libpam-cgm | cgmanager (<< 0.37), |
396 | - upstart (>= 1.13), |
397 | + dbus-user-session, |
398 | xmir [amd64 armhf i386], |
399 | zeitgeist-core, |
400 | Replaces: upstart-app-launch |
401 | @@ -78,6 +72,7 @@ |
402 | Architecture: any |
403 | Depends: ${misc:Depends}, |
404 | ${shlibs:Depends}, |
405 | + ubuntu-app-launch (= ${binary:Version}), |
406 | libertine-tools, |
407 | Pre-Depends: ${misc:Pre-Depends}, |
408 | Multi-Arch: same |
409 | |
410 | === modified file 'debian/ubuntu-app-launch.install' |
411 | --- debian/ubuntu-app-launch.install 2016-11-21 20:54:34 +0000 |
412 | +++ debian/ubuntu-app-launch.install 2017-03-21 03:20:55 +0000 |
413 | @@ -1,3 +1,2 @@ |
414 | -usr/share/upstart/sessions/* |
415 | usr/lib/*/ubuntu-app-launch/* |
416 | usr/bin/snappy-xmir* |
417 | |
418 | === modified file 'docs/index.rst' |
419 | --- docs/index.rst 2017-03-21 03:20:55 +0000 |
420 | +++ docs/index.rst 2017-03-21 03:20:55 +0000 |
421 | @@ -13,10 +13,10 @@ |
422 | managing apps on Ubuntu Touch. It is used by Unity8 and other programs to |
423 | start and stop applications, as well as query which ones are currently open. |
424 | It doesn't have its own service or processes though, it relies on the system |
425 | -init daemon to manage the processes (currently Upstart_) but configures them |
426 | +init daemon to manage the processes (currently systemd_) but configures them |
427 | in a way that they're discoverable and usable by higher level applications. |
428 | |
429 | -.. _Upstart: http://upstart.ubuntu.com/ |
430 | +.. _systemd: http://freedesktop.org/wiki/Software/systemd/ |
431 | |
432 | |
433 | Environment Variables |
434 | @@ -25,12 +25,6 @@ |
435 | There are a few environment variables that can effect the behavior of UAL while |
436 | it is running. |
437 | |
438 | -UBUNTU_APP_LAUNCH_CG_MANAGER_NAME |
439 | - The DBus name that CG Manager registers under if it is on the session bus. |
440 | - |
441 | -UBUNTU_APP_LAUNCH_CG_MANAGER_SESSION_BUS |
442 | - Tell UAL to look on the session bus for CG Manager. |
443 | - |
444 | UBUNTU_APP_LAUNCH_DEMANGLER |
445 | Path to the UAL demangler tool that will get the Mir FD for trusted prompt session. |
446 | |
447 | @@ -275,26 +269,6 @@ |
448 | :private-members: |
449 | :undoc-members: |
450 | |
451 | -Jobs Manager Upstart |
452 | --------------------- |
453 | - |
454 | -.. doxygenclass:: ubuntu::app_launch::jobs::manager::Upstart |
455 | - :project: libubuntu-app-launch |
456 | - :members: |
457 | - :protected-members: |
458 | - :private-members: |
459 | - :undoc-members: |
460 | - |
461 | -Jobs Instance Upstart |
462 | ---------------------- |
463 | - |
464 | -.. doxygenclass:: ubuntu::app_launch::jobs::instance::Upstart |
465 | - :project: libubuntu-app-launch |
466 | - :members: |
467 | - :protected-members: |
468 | - :private-members: |
469 | - :undoc-members: |
470 | - |
471 | Registry Implementation |
472 | ----------------------- |
473 | |
474 | |
475 | === removed file 'exec-line-exec-trace.tp' |
476 | --- exec-line-exec-trace.tp 2014-09-17 14:11:59 +0000 |
477 | +++ exec-line-exec-trace.tp 1970-01-01 00:00:00 +0000 |
478 | @@ -1,19 +0,0 @@ |
479 | - |
480 | -TRACEPOINT_EVENT(ubuntu_app_launch, exec_start, |
481 | - TP_ARGS(const char *, appid), |
482 | - TP_FIELDS( |
483 | - ctf_string(appid, appid) |
484 | - ) |
485 | -) |
486 | -TRACEPOINT_EVENT(ubuntu_app_launch, exec_parse_complete, |
487 | - TP_ARGS(const char *, appid), |
488 | - TP_FIELDS( |
489 | - ctf_string(appid, appid) |
490 | - ) |
491 | -) |
492 | -TRACEPOINT_EVENT(ubuntu_app_launch, exec_pre_exec, |
493 | - TP_ARGS(const char *, appid), |
494 | - TP_FIELDS( |
495 | - ctf_string(appid, appid) |
496 | - ) |
497 | -) |
498 | |
499 | === removed file 'exec-line-exec.c' |
500 | --- exec-line-exec.c 2015-06-30 20:42:24 +0000 |
501 | +++ exec-line-exec.c 1970-01-01 00:00:00 +0000 |
502 | @@ -1,170 +0,0 @@ |
503 | -/* |
504 | - * Copyright 2013 Canonical Ltd. |
505 | - * |
506 | - * This program is free software: you can redistribute it and/or modify it |
507 | - * under the terms of the GNU General Public License version 3, as published |
508 | - * by the Free Software Foundation. |
509 | - * |
510 | - * This program is distributed in the hope that it will be useful, but |
511 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
512 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
513 | - * PURPOSE. See the GNU General Public License for more details. |
514 | - * |
515 | - * You should have received a copy of the GNU General Public License along |
516 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
517 | - * |
518 | - * Authors: |
519 | - * Ted Gould <ted.gould@canonical.com> |
520 | - */ |
521 | - |
522 | -#include <unistd.h> |
523 | -#include <errno.h> |
524 | -#include <string.h> |
525 | - |
526 | -#include <glib.h> |
527 | -#include <glib/gstdio.h> |
528 | - |
529 | -#include "exec-line-exec-trace.h" |
530 | -#include "helpers.h" |
531 | -#include "ual-tracepoint.h" |
532 | - |
533 | -int |
534 | -main (int argc, char * argv[]) |
535 | -{ |
536 | - /* Make sure we have work to do */ |
537 | - /* This string is quoted using desktop file quoting: |
538 | - http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables */ |
539 | - const gchar * app_exec = g_getenv("APP_EXEC"); |
540 | - if (app_exec == NULL) { |
541 | - /* There should be no reason for this, a g_error() so that it gets |
542 | - picked up by Apport and we can track it */ |
543 | - g_error("No exec line given, nothing to do except fail"); |
544 | - return 1; |
545 | - } |
546 | - |
547 | - /* For the tracepoints */ |
548 | - const gchar * app_id = g_getenv("APP_ID"); |
549 | - |
550 | - ual_tracepoint(exec_start, app_id); |
551 | - |
552 | - /* URIs */ |
553 | - const gchar * app_uris = g_getenv("APP_URIS"); |
554 | - |
555 | - /* Look to see if we have a directory defined that we |
556 | - should be using for everything. If so, change to it |
557 | - and add it to the path */ |
558 | - const gchar * appdir = g_getenv("APP_DIR"); |
559 | - |
560 | - if (appdir != NULL) { |
561 | - if (g_chdir(appdir) != 0) { |
562 | - g_warning("Unable to change directory to '%s'", appdir); |
563 | - } |
564 | - } |
565 | - |
566 | - /* Protect against app directories that have ':' in them */ |
567 | - if (appdir != NULL && strchr(appdir, ':') == NULL) { |
568 | - const gchar * path_path = g_getenv("PATH"); |
569 | - if (path_path != NULL && path_path[0] == '\0') |
570 | - path_path = NULL; |
571 | - gchar * path_libpath = NULL; |
572 | - const gchar * path_joinable[4] = { 0 }; |
573 | - |
574 | - const gchar * lib_path = g_getenv("LD_LIBRARY_PATH"); |
575 | - if (lib_path != NULL && lib_path[0] == '\0') |
576 | - lib_path = NULL; |
577 | - gchar * lib_libpath = g_build_filename(appdir, "lib", NULL); |
578 | - const gchar * lib_joinable[4] = { 0 }; |
579 | - |
580 | - const gchar * import_path = g_getenv("QML2_IMPORT_PATH"); |
581 | - if (import_path != NULL && import_path[0] == '\0') |
582 | - import_path = NULL; |
583 | - gchar * import_libpath = NULL; |
584 | - const gchar * import_joinable[4] = { 0 }; |
585 | - |
586 | - /* If we've got an architecture set insert that into the |
587 | - path before everything else */ |
588 | - const gchar * archdir = g_getenv("UBUNTU_APP_LAUNCH_ARCH"); |
589 | - if (archdir != NULL && strchr(archdir, ':') == NULL) { |
590 | - path_libpath = g_build_filename(appdir, "lib", archdir, "bin", NULL); |
591 | - import_libpath = g_build_filename(appdir, "lib", archdir, NULL); |
592 | - |
593 | - path_joinable[0] = path_libpath; |
594 | - path_joinable[1] = appdir; |
595 | - path_joinable[2] = path_path; |
596 | - |
597 | - lib_joinable[0] = import_libpath; |
598 | - lib_joinable[1] = lib_libpath; |
599 | - lib_joinable[2] = lib_path; |
600 | - |
601 | - /* Need to check whether the original is NULL because we're |
602 | - appending instead of prepending */ |
603 | - if (import_path == NULL) { |
604 | - import_joinable[0] = import_libpath; |
605 | - } else { |
606 | - import_joinable[0] = import_path; |
607 | - import_joinable[1] = import_libpath; |
608 | - } |
609 | - } else { |
610 | - path_joinable[0] = appdir; |
611 | - path_joinable[1] = path_path; |
612 | - |
613 | - lib_joinable[0] = lib_libpath; |
614 | - lib_joinable[1] = lib_path; |
615 | - |
616 | - import_joinable[0] = import_path; |
617 | - } |
618 | - |
619 | - gchar * newpath = g_strjoinv(":", (gchar**)path_joinable); |
620 | - g_setenv("PATH", newpath, TRUE); |
621 | - g_free(path_libpath); |
622 | - g_free(newpath); |
623 | - |
624 | - gchar * newlib = g_strjoinv(":", (gchar**)lib_joinable); |
625 | - g_setenv("LD_LIBRARY_PATH", newlib, TRUE); |
626 | - g_free(lib_libpath); |
627 | - g_free(newlib); |
628 | - |
629 | - if (import_joinable[0] != NULL) { |
630 | - gchar * newimport = g_strjoinv(":", (gchar**)import_joinable); |
631 | - g_setenv("QML2_IMPORT_PATH", newimport, TRUE); |
632 | - g_free(newimport); |
633 | - } |
634 | - g_free(import_libpath); |
635 | - } |
636 | - |
637 | - /* Parse the execiness of it all */ |
638 | - GArray * newargv = desktop_exec_parse(app_exec, app_uris); |
639 | - if (newargv == NULL) { |
640 | - g_warning("Unable to parse exec line '%s'", app_exec); |
641 | - return 1; |
642 | - } |
643 | - |
644 | - ual_tracepoint(exec_parse_complete, app_id); |
645 | - |
646 | - if (g_getenv("MIR_SOCKET") != NULL && g_strcmp0(g_getenv("APP_XMIR_ENABLE"), "1") == 0) { |
647 | - g_debug("XMir Helper being used"); |
648 | - |
649 | - /* xmir-helper $(APP_ID) $(COMMAND) */ |
650 | - const gchar * appid = g_getenv("APP_ID"); |
651 | - g_array_prepend_val(newargv, appid); |
652 | - |
653 | - /* Pulling into the heap instead of the code page */ |
654 | - char * xmir_helper = g_strdup(XMIR_HELPER); |
655 | - g_array_prepend_val(newargv, xmir_helper); |
656 | - } |
657 | - |
658 | - /* Now exec */ |
659 | - gchar ** nargv = (gchar**)g_array_free(newargv, FALSE); |
660 | - |
661 | - ual_tracepoint(exec_pre_exec, app_id); |
662 | - |
663 | - int execret = execvp(nargv[0], nargv); |
664 | - |
665 | - if (execret != 0) { |
666 | - gchar * execprint = g_strjoinv(" ", nargv); |
667 | - g_warning("Unable to exec '%s' in '%s': %s", execprint, appdir, strerror(errno)); |
668 | - g_free(execprint); |
669 | - } |
670 | - |
671 | - return execret; |
672 | -} |
673 | |
674 | === modified file 'helpers.c' |
675 | --- helpers.c 2016-12-14 21:23:09 +0000 |
676 | +++ helpers.c 2017-03-21 03:20:55 +0000 |
677 | @@ -19,7 +19,6 @@ |
678 | |
679 | #include <json-glib/json-glib.h> |
680 | #include <click.h> |
681 | -#include <upstart.h> |
682 | #include "helpers.h" |
683 | |
684 | /* Take an app ID and validate it and then break it up |
685 | @@ -423,62 +422,6 @@ |
686 | return newargv; |
687 | } |
688 | |
689 | -/* Set environment various variables to make apps work under |
690 | - * confinement according to: |
691 | - * https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement |
692 | - */ |
693 | -void |
694 | -set_confined_envvars (EnvHandle * handle, const gchar * package, const gchar * app_dir) |
695 | -{ |
696 | - g_return_if_fail(package != NULL); |
697 | - g_return_if_fail(app_dir != NULL); |
698 | - |
699 | - g_debug("Setting 'UBUNTU_APPLICATION_ISOLATION' to '1'"); |
700 | - env_handle_add(handle, "UBUNTU_APPLICATION_ISOLATION", "1"); |
701 | - |
702 | - /* Make sure the XDG base dirs are set for the application using |
703 | - * the user's current values/system defaults. We could set these to |
704 | - * what is expected in the AppArmor profile, but that might be too |
705 | - * brittle if someone uses different base dirs. |
706 | - */ |
707 | - g_debug("Setting 'XDG_CACHE_HOME' using g_get_user_cache_dir()"); |
708 | - env_handle_add(handle, "XDG_CACHE_HOME", g_get_user_cache_dir()); |
709 | - |
710 | - g_debug("Setting 'XDG_CONFIG_HOME' using g_get_user_config_dir()"); |
711 | - env_handle_add(handle, "XDG_CONFIG_HOME", g_get_user_config_dir()); |
712 | - |
713 | - g_debug("Setting 'XDG_DATA_HOME' using g_get_user_data_dir()"); |
714 | - env_handle_add(handle, "XDG_DATA_HOME", g_get_user_data_dir()); |
715 | - |
716 | - g_debug("Setting 'XDG_RUNTIME_DIR' using g_get_user_runtime_dir()"); |
717 | - env_handle_add(handle, "XDG_RUNTIME_DIR", g_get_user_runtime_dir()); |
718 | - |
719 | - /* Add the application's dir to the list of sources for data */ |
720 | - const gchar * basedatadirs = g_getenv("XDG_DATA_DIRS"); |
721 | - if (basedatadirs == NULL || basedatadirs[0] == '\0') { |
722 | - basedatadirs = "/usr/local/share:/usr/share"; |
723 | - } |
724 | - gchar * datadirs = g_strjoin(":", app_dir, basedatadirs, NULL); |
725 | - env_handle_add(handle, "XDG_DATA_DIRS", datadirs); |
726 | - g_free(datadirs); |
727 | - |
728 | - /* Set TMPDIR to something sane and application-specific */ |
729 | - gchar * tmpdir = g_strdup_printf("%s/confined/%s", g_get_user_runtime_dir(), package); |
730 | - g_debug("Setting 'TMPDIR' to '%s'", tmpdir); |
731 | - env_handle_add(handle, "TMPDIR", tmpdir); |
732 | - g_debug("Creating '%s'", tmpdir); |
733 | - g_mkdir_with_parents(tmpdir, 0700); |
734 | - g_free(tmpdir); |
735 | - |
736 | - /* Do the same for nvidia */ |
737 | - gchar * nv_shader_cachedir = g_strdup_printf("%s/%s", g_get_user_cache_dir(), package); |
738 | - g_debug("Setting '__GL_SHADER_DISK_CACHE_PATH' to '%s'", nv_shader_cachedir); |
739 | - env_handle_add(handle, "__GL_SHADER_DISK_CACHE_PATH", nv_shader_cachedir); |
740 | - g_free(nv_shader_cachedir); |
741 | - |
742 | - return; |
743 | -} |
744 | - |
745 | static void |
746 | unity_signal_cb (GDBusConnection * con, const gchar * sender, const gchar * path, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
747 | { |
748 | @@ -568,72 +511,3 @@ |
749 | g_free(handshake); |
750 | } |
751 | |
752 | -EnvHandle * |
753 | -env_handle_start (void) |
754 | -{ |
755 | - GVariantBuilder * builder = g_variant_builder_new(G_VARIANT_TYPE_ARRAY); |
756 | - return (EnvHandle *)builder; |
757 | -} |
758 | - |
759 | -void |
760 | -env_handle_add (EnvHandle * handle, const gchar * variable, const gchar * value) |
761 | -{ |
762 | - g_return_if_fail(handle != NULL); |
763 | - gchar * combinedstr = g_strdup_printf("%s=%s", variable, value); |
764 | - GVariant * env = g_variant_new_take_string(combinedstr); |
765 | - g_variant_builder_add_value((GVariantBuilder*)handle, env); |
766 | -} |
767 | - |
768 | -void |
769 | -env_handle_finish (EnvHandle * handle) |
770 | -{ |
771 | - g_return_if_fail(handle != NULL); |
772 | - /* Check to see if we can get the job environment */ |
773 | - const gchar * job_name = g_getenv("UPSTART_JOB"); |
774 | - const gchar * instance_name = g_getenv("UPSTART_INSTANCE"); |
775 | - g_return_if_fail(job_name != NULL); |
776 | - |
777 | - /* Get a bus, let's go! */ |
778 | - GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
779 | - g_return_if_fail(bus != NULL); |
780 | - |
781 | - GVariantBuilder builder; /* Target: (assb) */ |
782 | - g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); |
783 | - |
784 | - /* Setup the job properties */ |
785 | - g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); |
786 | - g_variant_builder_add_value(&builder, g_variant_new_string(job_name)); |
787 | - if (instance_name != NULL) |
788 | - g_variant_builder_add_value(&builder, g_variant_new_string(instance_name)); |
789 | - g_variant_builder_close(&builder); |
790 | - |
791 | - /* The value itself */ |
792 | - g_variant_builder_add_value(&builder, g_variant_builder_end((GVariantBuilder*)handle)); |
793 | - |
794 | - /* Do we want to replace? Yes, we do! */ |
795 | - g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE)); |
796 | - |
797 | - GError * error = NULL; |
798 | - GVariant * reply = g_dbus_connection_call_sync(bus, |
799 | - DBUS_SERVICE_UPSTART, |
800 | - DBUS_PATH_UPSTART, |
801 | - DBUS_INTERFACE_UPSTART, |
802 | - "SetEnvList", |
803 | - g_variant_builder_end(&builder), |
804 | - NULL, /* reply */ |
805 | - G_DBUS_CALL_FLAGS_NONE, |
806 | - -1, /* timeout */ |
807 | - NULL, /* cancelable */ |
808 | - &error); /* error */ |
809 | - |
810 | - if (reply != NULL) { |
811 | - g_variant_unref(reply); |
812 | - } |
813 | - |
814 | - if (error != NULL) { |
815 | - g_warning("Unable to set environment variables: %s", error->message); |
816 | - g_error_free(error); |
817 | - } |
818 | - |
819 | - g_object_unref(bus); |
820 | -} |
821 | |
822 | === modified file 'helpers.h' |
823 | --- helpers.h 2016-12-14 21:23:09 +0000 |
824 | +++ helpers.h 2017-03-21 03:20:55 +0000 |
825 | @@ -21,8 +21,6 @@ |
826 | |
827 | G_BEGIN_DECLS |
828 | |
829 | -typedef struct _EnvHandle EnvHandle; |
830 | - |
831 | gboolean app_id_to_triplet (const gchar * app_id, |
832 | gchar ** package, |
833 | gchar ** application, |
834 | @@ -35,16 +33,6 @@ |
835 | const gchar * uri_list); |
836 | GKeyFile * keyfile_for_appid (const gchar * appid, |
837 | gchar * * desktopfile); |
838 | -void set_confined_envvars (EnvHandle * handle, |
839 | - const gchar * package, |
840 | - const gchar * app_dir); |
841 | - |
842 | -/* A handle to group environment setting */ |
843 | -EnvHandle * env_handle_start (void); |
844 | -void env_handle_add (EnvHandle * handle, |
845 | - const gchar * variable, |
846 | - const gchar * value); |
847 | -void env_handle_finish (EnvHandle * handle); |
848 | |
849 | typedef struct _handshake_t handshake_t; |
850 | handshake_t * starting_handshake_start (const gchar * app_id, |
851 | |
852 | === modified file 'libubuntu-app-launch/CMakeLists.txt' |
853 | --- libubuntu-app-launch/CMakeLists.txt 2017-03-21 03:20:55 +0000 |
854 | +++ libubuntu-app-launch/CMakeLists.txt 2017-03-21 03:20:55 +0000 |
855 | @@ -74,8 +74,6 @@ |
856 | jobs-base.cpp |
857 | jobs-systemd.h |
858 | jobs-systemd.cpp |
859 | -jobs-upstart.h |
860 | -jobs-upstart.cpp |
861 | ) |
862 | |
863 | set(LAUNCHER_SOURCES |
864 | |
865 | === added file 'libubuntu-app-launch/helper.cpp' |
866 | --- libubuntu-app-launch/helper.cpp 1970-01-01 00:00:00 +0000 |
867 | +++ libubuntu-app-launch/helper.cpp 2017-03-21 03:20:55 +0000 |
868 | @@ -0,0 +1,468 @@ |
869 | +/* |
870 | + * Copyright © 2016-2017 Canonical Ltd. |
871 | + * |
872 | + * This program is free software: you can redistribute it and/or modify it |
873 | + * under the terms of the GNU General Public License version 3, as published |
874 | + * by the Free Software Foundation. |
875 | + * |
876 | + * This program is distributed in the hope that it will be useful, but |
877 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
878 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
879 | + * PURPOSE. See the GNU General Public License for more details. |
880 | + * |
881 | + * You should have received a copy of the GNU General Public License along |
882 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
883 | + * |
884 | + * Authors: |
885 | + * Ted Gould <ted.gould@canonical.com> |
886 | + */ |
887 | + |
888 | +#include <algorithm> |
889 | +#include <list> |
890 | +#include <numeric> |
891 | + |
892 | +#include "helper-impl.h" |
893 | +#include "registry-impl.h" |
894 | + |
895 | +#include "ubuntu-app-launch.h" |
896 | + |
897 | +extern "C" { |
898 | +#include "proxy-socket-demangler.h" |
899 | +#include <gio/gunixfdlist.h> |
900 | +} |
901 | + |
902 | +namespace ubuntu |
903 | +{ |
904 | +namespace app_launch |
905 | +{ |
906 | +namespace helper_impls |
907 | +{ |
908 | + |
909 | +/********************** |
910 | + * Instance |
911 | + **********************/ |
912 | + |
913 | +BaseInstance::BaseInstance(const std::shared_ptr<jobs::instance::Base>& inst) |
914 | + : impl{inst} |
915 | +{ |
916 | +} |
917 | + |
918 | +BaseInstance::BaseInstance(const std::shared_ptr<Application::Instance>& inst) |
919 | + : impl{std::dynamic_pointer_cast<jobs::instance::Base>(inst)} |
920 | +{ |
921 | +} |
922 | + |
923 | +bool BaseInstance::isRunning() |
924 | +{ |
925 | + return impl->isRunning(); |
926 | +} |
927 | + |
928 | +void BaseInstance::stop() |
929 | +{ |
930 | + impl->stop(); |
931 | +} |
932 | + |
933 | +/********************** |
934 | + * Helper Class |
935 | + **********************/ |
936 | + |
937 | +Base::Base(const Helper::Type& type, const AppID& appid, const std::shared_ptr<Registry>& registry) |
938 | + : _type(type) |
939 | + , _appid(appid) |
940 | + , _registry(registry) |
941 | +{ |
942 | +} |
943 | + |
944 | +AppID Base::appId() |
945 | +{ |
946 | + return _appid; |
947 | +} |
948 | + |
949 | +bool Base::hasInstances() |
950 | +{ |
951 | + return instances().size() > 0; |
952 | +} |
953 | + |
954 | +std::vector<std::shared_ptr<Helper::Instance>> Base::instances() |
955 | +{ |
956 | + auto insts = _registry->impl->jobs->instances(_appid, _type.value()); |
957 | + std::vector<std::shared_ptr<Helper::Instance>> wrapped; |
958 | + |
959 | + std::transform(insts.begin(), insts.end(), wrapped.begin(), |
960 | + [](std::shared_ptr<jobs::instance::Base>& inst) { return std::make_shared<BaseInstance>(inst); }); |
961 | + |
962 | + return wrapped; |
963 | +} |
964 | + |
965 | +/** Find an instance that we already know the ID of */ |
966 | +std::shared_ptr<Helper::Instance> Base::existingInstance(const std::string& instanceid) |
967 | +{ |
968 | + auto appinst = _registry->impl->jobs->existing(_appid, _type.value(), instanceid, {}); |
969 | + |
970 | + return std::make_shared<BaseInstance>(appinst); |
971 | +} |
972 | + |
973 | +std::string genInstanceId() |
974 | +{ |
975 | + return std::to_string(g_get_real_time()); |
976 | +} |
977 | + |
978 | +std::vector<Application::URL> appURL(const std::vector<Helper::URL>& in) |
979 | +{ |
980 | + std::vector<Application::URL> out; |
981 | + std::transform(in.begin(), in.end(), out.begin(), |
982 | + [](Helper::URL url) { return Application::URL::from_raw(url.value()); }); |
983 | + return out; |
984 | +} |
985 | + |
986 | +/** Sets up the executable environment variable based on the appid and |
987 | + * the type of helper. We look for the exec-tool, but if we can't find |
988 | + * it we're cool with that and we just execute the helper. If we do find |
989 | + * an exec-tool we'll use that to fill in the parameters. For legacy appid's |
990 | + * we'll allow the exec-tool to set everything. */ |
991 | +std::list<std::pair<std::string, std::string>> Base::defaultEnv() |
992 | +{ |
993 | + std::list<std::pair<std::string, std::string>> envs{}; |
994 | + auto csnapenv = getenv("SNAP"); |
995 | + std::string helperpath; |
996 | + if (csnapenv != nullptr) |
997 | + { |
998 | + helperpath = std::string{csnapenv} + "/" HELPER_EXEC_TOOL_DIR "/" + _type.value() + "/exec-tool"; |
999 | + } |
1000 | + else |
1001 | + { |
1002 | + helperpath = HELPER_EXEC_TOOL_DIR "/" + _type.value() + "/exec-tool"; |
1003 | + } |
1004 | + |
1005 | + std::list<std::string> exec; |
1006 | + /* We have an exec tool that'll give us params */ |
1007 | + if (g_file_test(helperpath.c_str(), G_FILE_TEST_IS_EXECUTABLE)) |
1008 | + { |
1009 | + const char* chelperenv = getenv("UBUNTU_APP_LAUNCH_HELPER_HELPER"); |
1010 | + if (chelperenv == nullptr) |
1011 | + { |
1012 | + chelperenv = HELPER_HELPER_TOOL; |
1013 | + } |
1014 | + |
1015 | + if (csnapenv != nullptr) |
1016 | + { |
1017 | + exec.push_back(std::string{csnapenv} + "/" + chelperenv); |
1018 | + } |
1019 | + else |
1020 | + { |
1021 | + exec.push_back(std::string{"/"} + chelperenv); |
1022 | + } |
1023 | + exec.push_back(helperpath); |
1024 | + } |
1025 | + else |
1026 | + { |
1027 | + if (_appid.package.value().empty()) |
1028 | + { |
1029 | + throw std::runtime_error{ |
1030 | + "Executing a helper that isn't package, but doesn't have an exec-tool. We can't do that. Sorry. Bad " |
1031 | + "things will happen."}; |
1032 | + } |
1033 | + } |
1034 | + |
1035 | + /* This is kinda hard coded for snaps right now, we don't have |
1036 | + * another posibility today other than really custom stuff. But |
1037 | + * if we do, we'll need to abstract this. */ |
1038 | + /* Insert package executable */ |
1039 | + if (!_appid.package.value().empty()) |
1040 | + { |
1041 | + std::string snapdir{"/snap/bin/"}; |
1042 | + |
1043 | + if (_appid.package.value() == _appid.appname.value()) |
1044 | + { |
1045 | + exec.push_back(snapdir + _appid.package.value()); |
1046 | + } |
1047 | + else |
1048 | + { |
1049 | + exec.push_back(snapdir + _appid.package.value() + "." + _appid.appname.value()); |
1050 | + } |
1051 | + } |
1052 | + |
1053 | + exec.push_back("--"); |
1054 | + exec.push_back("%U"); |
1055 | + |
1056 | + envs.emplace_back( |
1057 | + std::make_pair("APP_EXEC", std::accumulate(exec.begin(), exec.end(), std::string{}, |
1058 | + [](const std::string& accum, const std::string& addon) { |
1059 | + return accum.empty() ? addon : accum + " " + addon; |
1060 | + }))); |
1061 | + |
1062 | + return envs; |
1063 | +} |
1064 | + |
1065 | +std::shared_ptr<Helper::Instance> Base::launch(std::vector<Helper::URL> urls) |
1066 | +{ |
1067 | + auto defaultenv = defaultEnv(); |
1068 | + std::function<std::list<std::pair<std::string, std::string>>()> envfunc = [defaultenv]() { return defaultenv; }; |
1069 | + |
1070 | + return std::make_shared<BaseInstance>(_registry->impl->jobs->launch( |
1071 | + _appid, _type.value(), genInstanceId(), appURL(urls), jobs::manager::launchMode::STANDARD, envfunc)); |
1072 | +} |
1073 | + |
1074 | +class MirFDProxy |
1075 | +{ |
1076 | +public: |
1077 | + int mirfd; |
1078 | + std::shared_ptr<proxySocketDemangler> skel; |
1079 | + guint handle; |
1080 | + std::string path; |
1081 | + std::string name; |
1082 | + |
1083 | + MirFDProxy(MirPromptSession* session, const AppID& appid, const std::shared_ptr<Registry>& reg) |
1084 | + : name(g_dbus_connection_get_unique_name(reg->impl->_dbus.get())) |
1085 | + { |
1086 | + if (appid.empty()) |
1087 | + { |
1088 | + throw std::runtime_error{"Invalid AppID"}; |
1089 | + } |
1090 | + |
1091 | + /* Get the Mir FD */ |
1092 | + std::promise<int> promise; |
1093 | + mir_prompt_session_new_fds_for_prompt_providers( |
1094 | + session, 1, |
1095 | + [](MirPromptSession* session, size_t count, int const* fdin, void* user_data) { |
1096 | + auto promise = static_cast<std::promise<int>*>(user_data); |
1097 | + |
1098 | + if (count != 1) |
1099 | + { |
1100 | + g_warning("Mir trusted session returned %d FDs instead of one", (int)count); |
1101 | + promise->set_value(0); |
1102 | + return; |
1103 | + } |
1104 | + |
1105 | + promise->set_value(fdin[0]); |
1106 | + }, |
1107 | + &promise); |
1108 | + |
1109 | + mirfd = promise.get_future().get(); |
1110 | + |
1111 | + if (mirfd == 0) |
1112 | + { |
1113 | + throw std::runtime_error{"Unable to Mir FD from Prompt Session"}; |
1114 | + } |
1115 | + |
1116 | + /* Setup the DBus interface */ |
1117 | + std::tie(skel, handle, path) = |
1118 | + reg->impl->thread.executeOnThread<std::tuple<std::shared_ptr<proxySocketDemangler>, guint, std::string>>( |
1119 | + [this, appid, reg]() { |
1120 | + auto skel = std::shared_ptr<proxySocketDemangler>( |
1121 | + proxy_socket_demangler_skeleton_new(), |
1122 | + [](proxySocketDemangler* skel) { g_clear_object(&skel); }); |
1123 | + auto handle = g_signal_connect(G_OBJECT(skel.get()), "handle-get-mir-socket", |
1124 | + G_CALLBACK(staticProxyCb), this); |
1125 | + |
1126 | + /* Find a path to export on */ |
1127 | + auto dbusAppid = dbusSafe(std::string{appid}); |
1128 | + std::string path; |
1129 | + |
1130 | + while (path.empty()) |
1131 | + { |
1132 | + GError* error = nullptr; |
1133 | + std::string tryname = |
1134 | + "/com/canonical/UbuntuAppLaunch/" + dbusAppid + "/" + std::to_string(rand()); |
1135 | + |
1136 | + g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skel.get()), reg->impl->_dbus.get(), |
1137 | + tryname.c_str(), &error); |
1138 | + |
1139 | + if (error == nullptr) |
1140 | + { |
1141 | + path = tryname; |
1142 | + } |
1143 | + else |
1144 | + { |
1145 | + if (!g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_OBJECT_PATH_IN_USE)) |
1146 | + { |
1147 | + std::string message = |
1148 | + "Unable to export Mir trusted proxy: " + std::string{error->message}; |
1149 | + g_clear_error(&error); |
1150 | + throw std::runtime_error{message}; |
1151 | + } |
1152 | + g_clear_error(&error); |
1153 | + } |
1154 | + } |
1155 | + |
1156 | + return std::make_tuple(skel, handle, path); |
1157 | + }); |
1158 | + } |
1159 | + |
1160 | + ~MirFDProxy() |
1161 | + { |
1162 | + if (mirfd != 0) |
1163 | + { |
1164 | + close(mirfd); |
1165 | + } |
1166 | + |
1167 | + if (handle != 0) |
1168 | + { |
1169 | + g_signal_handler_disconnect(skel.get(), handle); |
1170 | + } |
1171 | + |
1172 | + g_dbus_interface_skeleton_unexport(G_DBUS_INTERFACE_SKELETON(skel.get())); |
1173 | + } |
1174 | + |
1175 | + static std::string dbusSafe(const std::string& in) |
1176 | + { |
1177 | + std::string out = in; |
1178 | + std::transform(out.begin(), out.end(), out.begin(), [](char in) { return std::isalpha(in) ? in : '_'; }); |
1179 | + return out; |
1180 | + } |
1181 | + |
1182 | + bool proxyCb(GDBusMethodInvocation* invocation) |
1183 | + { |
1184 | + if (mirfd == 0) |
1185 | + { |
1186 | + g_warning("Mir FD proxy called with no FDs!"); |
1187 | + return false; |
1188 | + } |
1189 | + |
1190 | + /* Index into fds */ |
1191 | + auto handle = g_variant_new_handle(0); |
1192 | + auto tuple = g_variant_new_tuple(&handle, 1); |
1193 | + |
1194 | + GError* error = nullptr; |
1195 | + GUnixFDList* list = g_unix_fd_list_new(); |
1196 | + g_unix_fd_list_append(list, mirfd, &error); |
1197 | + |
1198 | + if (error == nullptr) |
1199 | + { |
1200 | + g_dbus_method_invocation_return_value_with_unix_fd_list(invocation, tuple, list); |
1201 | + } |
1202 | + else |
1203 | + { |
1204 | + g_variant_ref_sink(tuple); |
1205 | + g_variant_unref(tuple); |
1206 | + } |
1207 | + |
1208 | + g_object_unref(list); |
1209 | + |
1210 | + if (error != nullptr) |
1211 | + { |
1212 | + g_warning("Unable to pass FD %d: %s", mirfd, error->message); |
1213 | + g_error_free(error); |
1214 | + return false; |
1215 | + } |
1216 | + |
1217 | + mirfd = 0; |
1218 | + return true; |
1219 | + } |
1220 | + |
1221 | + static gboolean staticProxyCb(GObject* obj, GDBusMethodInvocation* invocation, gpointer user_data) |
1222 | + { |
1223 | + return static_cast<MirFDProxy*>(user_data)->proxyCb(invocation) ? TRUE : FALSE; |
1224 | + } |
1225 | + |
1226 | + std::string getPath() |
1227 | + { |
1228 | + return path; |
1229 | + } |
1230 | + |
1231 | + std::string getName() |
1232 | + { |
1233 | + return name; |
1234 | + } |
1235 | +}; |
1236 | + |
1237 | +std::shared_ptr<Helper::Instance> Base::launch(MirPromptSession* session, std::vector<Helper::URL> urls) |
1238 | +{ |
1239 | + std::shared_ptr<MirFDProxy> proxy; |
1240 | + try |
1241 | + { |
1242 | + proxy = std::make_shared<MirFDProxy>(session, _appid, _registry); |
1243 | + } |
1244 | + catch (std::runtime_error& e) |
1245 | + { |
1246 | + g_warning("Error setting up Mir FD Proxy: %s", e.what()); |
1247 | + return {}; |
1248 | + } |
1249 | + |
1250 | + auto defaultenvs = defaultEnv(); |
1251 | + std::function<std::list<std::pair<std::string, std::string>>()> envfunc = [defaultenvs, proxy]() { |
1252 | + auto envs = defaultenvs; |
1253 | + |
1254 | + envs.emplace_back(std::make_pair("UBUNTU_APP_LAUNCH_DEMANGLE_PATH", proxy->getPath())); |
1255 | + envs.emplace_back(std::make_pair("UBUNTU_APP_LAUNCH_DEMANGLE_NAME", proxy->getName())); |
1256 | + |
1257 | + return envs; |
1258 | + }; |
1259 | + |
1260 | + /* This will maintain a reference to the proxy for two |
1261 | + seconds. And then it'll be dropped. */ |
1262 | + _registry->impl->thread.timeout(std::chrono::seconds{2}, [proxy]() { g_debug("Mir Proxy Timeout"); }); |
1263 | + |
1264 | + return std::make_shared<BaseInstance>(_registry->impl->jobs->launch( |
1265 | + _appid, _type.value(), genInstanceId(), appURL(urls), jobs::manager::launchMode::STANDARD, envfunc)); |
1266 | +} |
1267 | + |
1268 | +} // namespace helper_impl |
1269 | + |
1270 | +/***************************/ |
1271 | +/* Helper Public Functions */ |
1272 | +/***************************/ |
1273 | + |
1274 | +std::shared_ptr<Helper> Helper::create(Type type, AppID appid, std::shared_ptr<Registry> registry) |
1275 | +{ |
1276 | + /* Only one type today */ |
1277 | + return std::make_shared<helper_impls::Base>(type, appid, registry); |
1278 | +} |
1279 | + |
1280 | +/* Hardcore socket stuff */ |
1281 | +#include <sys/socket.h> |
1282 | +#include <sys/types.h> |
1283 | +#include <sys/un.h> |
1284 | + |
1285 | +void Helper::setExec(std::vector<std::string> exec) |
1286 | +{ |
1287 | + auto cenv = getenv("UBUNTU_APP_LAUNCH_HELPER_EXECTOOL_SETEXEC_SOCKET"); |
1288 | + if (cenv == nullptr) |
1289 | + { |
1290 | + throw std::runtime_error{"Unable to find a socket to write exec information to."}; |
1291 | + } |
1292 | + |
1293 | + class SmartSocket |
1294 | + { |
1295 | + public: |
1296 | + int fd; |
1297 | + SmartSocket() |
1298 | + : fd(socket(AF_UNIX, SOCK_STREAM, 0)) |
1299 | + { |
1300 | + } |
1301 | + ~SmartSocket() |
1302 | + { |
1303 | + close(fd); |
1304 | + } |
1305 | + }; |
1306 | + |
1307 | + SmartSocket sock; |
1308 | + if (sock.fd <= 0) |
1309 | + { |
1310 | + throw std::runtime_error{"Unable to create socket to systemd-helper-helper"}; |
1311 | + } |
1312 | + |
1313 | + struct sockaddr_un socketaddr = {0}; |
1314 | + socketaddr.sun_family = AF_UNIX; |
1315 | + strncpy(socketaddr.sun_path, cenv, sizeof(socketaddr.sun_path) - 1); |
1316 | + socketaddr.sun_path[0] = 0; |
1317 | + |
1318 | + if (connect(sock.fd, (const struct sockaddr*)&socketaddr, sizeof(struct sockaddr_un)) < 0) |
1319 | + { |
1320 | + throw std::runtime_error{"Unable to connecto to socket of systemd-helper-helper"}; |
1321 | + } |
1322 | + |
1323 | + for (const auto& item : exec) |
1324 | + { |
1325 | + auto citem = item.c_str(); |
1326 | + int writesize = write(sock.fd, citem, strlen(citem) + 1); |
1327 | + |
1328 | + if (writesize <= 0) |
1329 | + { |
1330 | + throw std::runtime_error{"Error writing to systemd-helper-helper socket"}; |
1331 | + } |
1332 | + } |
1333 | +} |
1334 | + |
1335 | +} // namespace app_launch |
1336 | +} // namespace ubuntu |
1337 | |
1338 | === modified file 'libubuntu-app-launch/jobs-base.cpp' |
1339 | --- libubuntu-app-launch/jobs-base.cpp 2017-03-21 03:20:55 +0000 |
1340 | +++ libubuntu-app-launch/jobs-base.cpp 2017-03-21 03:20:55 +0000 |
1341 | @@ -26,7 +26,6 @@ |
1342 | #include "helper-impl.h" |
1343 | #include "jobs-base.h" |
1344 | #include "jobs-systemd.h" |
1345 | -#include "jobs-upstart.h" |
1346 | #include "registry-impl.h" |
1347 | |
1348 | namespace ubuntu |
1349 | @@ -62,22 +61,12 @@ |
1350 | dohandle(handle_appResumed); |
1351 | } |
1352 | |
1353 | +/** Should determine which jobs backend to use, but we only have |
1354 | + one right now. */ |
1355 | std::shared_ptr<Base> Base::determineFactory(std::shared_ptr<Registry> registry) |
1356 | { |
1357 | - /* Checking to see if we have a user bus, that is only started |
1358 | - by systemd so we're in good shape if we have one. We're using |
1359 | - the path instead of the RUNTIME variable because we want to work |
1360 | - around the case of being relocated by the snappy environment */ |
1361 | - if (g_file_test(SystemD::userBusPath().c_str(), G_FILE_TEST_EXISTS)) |
1362 | - { |
1363 | - g_debug("Building a systemd jobs manager"); |
1364 | - return std::make_shared<jobs::manager::SystemD>(registry); |
1365 | - } |
1366 | - else |
1367 | - { |
1368 | - g_debug("Building an Upstart jobs manager"); |
1369 | - return std::make_shared<jobs::manager::Upstart>(registry); |
1370 | - } |
1371 | + g_debug("Building a systemd jobs manager"); |
1372 | + return std::make_shared<jobs::manager::SystemD>(registry); |
1373 | } |
1374 | |
1375 | const std::list<std::string>& Base::getAllApplicationJobs() const |
1376 | |
1377 | === removed file 'libubuntu-app-launch/jobs-upstart.cpp' |
1378 | --- libubuntu-app-launch/jobs-upstart.cpp 2017-03-21 03:20:55 +0000 |
1379 | +++ libubuntu-app-launch/jobs-upstart.cpp 1970-01-01 00:00:00 +0000 |
1380 | @@ -1,1178 +0,0 @@ |
1381 | -/* |
1382 | - * Copyright © 2016 Canonical Ltd. |
1383 | - * |
1384 | - * This program is free software: you can redistribute it and/or modify it |
1385 | - * under the terms of the GNU General Public License version 3, as published |
1386 | - * by the Free Software Foundation. |
1387 | - * |
1388 | - * This program is distributed in the hope that it will be useful, but |
1389 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
1390 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1391 | - * PURPOSE. See the GNU General Public License for more details. |
1392 | - * |
1393 | - * You should have received a copy of the GNU General Public License along |
1394 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
1395 | - * |
1396 | - * Authors: |
1397 | - * Ted Gould <ted.gould@canonical.com> |
1398 | - */ |
1399 | - |
1400 | -#include <algorithm> |
1401 | -#include <cerrno> |
1402 | -#include <cstring> |
1403 | -#include <map> |
1404 | -#include <numeric> |
1405 | -#include <regex> |
1406 | - |
1407 | -#include <cgmanager/cgmanager.h> |
1408 | -#include <upstart.h> |
1409 | - |
1410 | -#include "application-impl-base.h" |
1411 | -#include "helpers.h" |
1412 | -#include "registry-impl.h" |
1413 | -#include "second-exec-core.h" |
1414 | - |
1415 | -extern "C" { |
1416 | -#include "ubuntu-app-launch-trace.h" |
1417 | -} |
1418 | - |
1419 | -#include "jobs-upstart.h" |
1420 | - |
1421 | -namespace ubuntu |
1422 | -{ |
1423 | -namespace app_launch |
1424 | -{ |
1425 | -namespace jobs |
1426 | -{ |
1427 | -namespace instance |
1428 | -{ |
1429 | - |
1430 | -/** An object that represents an instance of a job on Upstart. This |
1431 | - then implements everything needed by the instance interface. Most |
1432 | - applications tie into this today and use it as the backend for |
1433 | - their instances. */ |
1434 | -class Upstart : public Base |
1435 | -{ |
1436 | -public: |
1437 | - explicit Upstart(const AppID& appId, |
1438 | - const std::string& job, |
1439 | - const std::string& instance, |
1440 | - const std::vector<Application::URL>& urls, |
1441 | - const std::shared_ptr<Registry>& registry); |
1442 | - |
1443 | - /* Query lifecycle */ |
1444 | - pid_t primaryPid() override; |
1445 | - std::vector<pid_t> pids() override; |
1446 | - |
1447 | - /* Manage lifecycle */ |
1448 | - void stop() override; |
1449 | - void pause() override; |
1450 | - void resume() override; |
1451 | - |
1452 | - /* C Callback */ |
1453 | - static void application_start_cb(GObject* obj, GAsyncResult* res, gpointer user_data); |
1454 | - |
1455 | -private: |
1456 | - std::string upstartJobPath(); |
1457 | - std::string upstartName(); |
1458 | - |
1459 | - static std::vector<pid_t> pids(const std::shared_ptr<Registry>& reg, |
1460 | - const AppID& appid, |
1461 | - const std::string& jobpath); |
1462 | - static std::vector<pid_t> forAllPids(const std::shared_ptr<Registry>& reg, |
1463 | - const AppID& appid, |
1464 | - const std::string& jobpath, |
1465 | - std::function<void(pid_t)> eachPid); |
1466 | -}; |
1467 | - |
1468 | -/** Uses Upstart to get the primary PID of the instance using Upstart's |
1469 | - DBus interface */ |
1470 | -pid_t Upstart::primaryPid() |
1471 | -{ |
1472 | - auto jobpath = upstartJobPath(); |
1473 | - if (jobpath.empty()) |
1474 | - { |
1475 | - g_debug("Unable to get a valid job path"); |
1476 | - return 0; |
1477 | - } |
1478 | - |
1479 | - return registry_->impl->thread.executeOnThread<pid_t>([this, &jobpath]() -> pid_t { |
1480 | - GError* error = nullptr; |
1481 | - |
1482 | - std::string instancename = std::string(appId_); |
1483 | - if (job_ != "application-click") |
1484 | - { |
1485 | - instancename += "-" + instance_; |
1486 | - } |
1487 | - |
1488 | - g_debug("Getting instance by name: %s", instance_.c_str()); |
1489 | - auto vinstance_path = |
1490 | - g_dbus_connection_call_sync(registry_->impl->_dbus.get(), /* connection */ |
1491 | - DBUS_SERVICE_UPSTART, /* service */ |
1492 | - jobpath.c_str(), /* object path */ |
1493 | - DBUS_INTERFACE_UPSTART_JOB, /* iface */ |
1494 | - "GetInstanceByName", /* method */ |
1495 | - g_variant_new("(s)", instancename.c_str()), /* params */ |
1496 | - G_VARIANT_TYPE("(o)"), /* return type */ |
1497 | - G_DBUS_CALL_FLAGS_NONE, /* flags */ |
1498 | - -1, /* timeout: default */ |
1499 | - registry_->impl->thread.getCancellable().get(), /* cancellable */ |
1500 | - &error); |
1501 | - |
1502 | - if (error != nullptr) |
1503 | - { |
1504 | - g_warning("Unable to get instance '%s' of job '%s': %s", instance_.c_str(), job_.c_str(), error->message); |
1505 | - g_error_free(error); |
1506 | - return 0; |
1507 | - } |
1508 | - |
1509 | - /* Jump rope to make this into a C++ type */ |
1510 | - std::string instance_path; |
1511 | - gchar* cinstance_path = nullptr; |
1512 | - g_variant_get(vinstance_path, "(o)", &cinstance_path); |
1513 | - g_variant_unref(vinstance_path); |
1514 | - if (cinstance_path != nullptr) |
1515 | - { |
1516 | - instance_path = cinstance_path; |
1517 | - g_free(cinstance_path); |
1518 | - } |
1519 | - |
1520 | - if (instance_path.empty()) |
1521 | - { |
1522 | - g_debug("No instance object for instance name: %s", instance_.c_str()); |
1523 | - return 0; |
1524 | - } |
1525 | - |
1526 | - auto props_tuple = |
1527 | - g_dbus_connection_call_sync(registry_->impl->_dbus.get(), /* connection */ |
1528 | - DBUS_SERVICE_UPSTART, /* service */ |
1529 | - instance_path.c_str(), /* object path */ |
1530 | - "org.freedesktop.DBus.Properties", /* interface */ |
1531 | - "GetAll", /* method */ |
1532 | - g_variant_new("(s)", DBUS_INTERFACE_UPSTART_INSTANCE), /* params */ |
1533 | - G_VARIANT_TYPE("(a{sv})"), /* return type */ |
1534 | - G_DBUS_CALL_FLAGS_NONE, /* flags */ |
1535 | - -1, /* timeout: default */ |
1536 | - registry_->impl->thread.getCancellable().get(), /* cancellable */ |
1537 | - &error); |
1538 | - |
1539 | - if (error != nullptr) |
1540 | - { |
1541 | - g_warning("Unable to name of properties '%s': %s", instance_path.c_str(), error->message); |
1542 | - g_error_free(error); |
1543 | - error = nullptr; |
1544 | - return 0; |
1545 | - } |
1546 | - |
1547 | - auto props_dict = g_variant_get_child_value(props_tuple, 0); |
1548 | - |
1549 | - pid_t retval = 0; |
1550 | - auto processes = g_variant_lookup_value(props_dict, "processes", G_VARIANT_TYPE("a(si)")); |
1551 | - if (processes != nullptr && g_variant_n_children(processes) > 0) |
1552 | - { |
1553 | - |
1554 | - auto first_entry = g_variant_get_child_value(processes, 0); |
1555 | - auto pidv = g_variant_get_child_value(first_entry, 1); |
1556 | - |
1557 | - retval = g_variant_get_int32(pidv); |
1558 | - |
1559 | - g_variant_unref(pidv); |
1560 | - g_variant_unref(first_entry); |
1561 | - } |
1562 | - else |
1563 | - { |
1564 | - g_debug("Unable to get 'processes' from properties of instance at path: %s", instance_path.c_str()); |
1565 | - } |
1566 | - |
1567 | - g_variant_unref(props_dict); |
1568 | - |
1569 | - return retval; |
1570 | - }); |
1571 | -} |
1572 | - |
1573 | -/** Generate the full name of the Upstart job for the job, the |
1574 | - instance and how all those fit together. |
1575 | - |
1576 | - Handles the special case of application-click which isn't designed |
1577 | - to have multi-instance apps. |
1578 | -*/ |
1579 | -std::string Upstart::upstartName() |
1580 | -{ |
1581 | - std::string path = job_ + "-" + std::string(appId_); |
1582 | - if (job_ != "application-click") |
1583 | - { |
1584 | - path += "-"; |
1585 | - } |
1586 | - if (!instance_.empty()) |
1587 | - { |
1588 | - path += instance_; |
1589 | - } |
1590 | - |
1591 | - return path; |
1592 | -} |
1593 | - |
1594 | -/** Returns all the PIDs that are in the cgroup for this application */ |
1595 | -std::vector<pid_t> Upstart::pids() |
1596 | -{ |
1597 | - auto manager = std::dynamic_pointer_cast<manager::Upstart>(registry_->impl->jobs); |
1598 | - auto pids = manager->pidsFromCgroup(upstartName()); |
1599 | - g_debug("Got %d PIDs for AppID '%s'", int(pids.size()), std::string(appId_).c_str()); |
1600 | - return pids; |
1601 | -} |
1602 | - |
1603 | -/** Stops this instance by asking Upstart to stop it. Upstart will then |
1604 | - send a SIGTERM and five seconds later start killing things. */ |
1605 | -void Upstart::stop() |
1606 | -{ |
1607 | - if (!registry_->impl->thread.executeOnThread<bool>([this]() { |
1608 | - auto manager = std::dynamic_pointer_cast<manager::Upstart>(registry_->impl->jobs); |
1609 | - |
1610 | - g_debug("Stopping job %s app_id %s instance_id %s", job_.c_str(), std::string(appId_).c_str(), |
1611 | - instance_.c_str()); |
1612 | - |
1613 | - auto jobpath = upstartJobPath(); |
1614 | - if (jobpath.empty()) |
1615 | - { |
1616 | - throw new std::runtime_error("Unable to get job path for Upstart job '" + job_ + "'"); |
1617 | - } |
1618 | - |
1619 | - GVariantBuilder builder; |
1620 | - g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); |
1621 | - g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); |
1622 | - |
1623 | - g_variant_builder_add_value( |
1624 | - &builder, g_variant_new_take_string(g_strdup_printf("APP_ID=%s", std::string(appId_).c_str()))); |
1625 | - |
1626 | - if (!instance_.empty()) |
1627 | - { |
1628 | - g_variant_builder_add_value( |
1629 | - &builder, g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instance_.c_str()))); |
1630 | - } |
1631 | - |
1632 | - g_variant_builder_close(&builder); |
1633 | - g_variant_builder_add_value(&builder, g_variant_new_boolean(FALSE)); /* wait */ |
1634 | - |
1635 | - GError* error = nullptr; |
1636 | - auto stop_variant = |
1637 | - g_dbus_connection_call_sync(registry_->impl->_dbus.get(), /* Dbus */ |
1638 | - DBUS_SERVICE_UPSTART, /* Upstart name */ |
1639 | - jobpath.c_str(), /* path */ |
1640 | - DBUS_INTERFACE_UPSTART_JOB, /* interface */ |
1641 | - "Stop", /* method */ |
1642 | - g_variant_builder_end(&builder), /* params */ |
1643 | - nullptr, /* return */ |
1644 | - G_DBUS_CALL_FLAGS_NONE, /* flags */ |
1645 | - -1, /* timeout: default */ |
1646 | - registry_->impl->thread.getCancellable().get(), /* cancellable */ |
1647 | - &error); /* error (hopefully not) */ |
1648 | - |
1649 | - g_clear_pointer(&stop_variant, g_variant_unref); |
1650 | - |
1651 | - if (error != nullptr) |
1652 | - { |
1653 | - g_warning("Unable to stop job %s app_id %s instance_id %s: %s", job_.c_str(), |
1654 | - std::string(appId_).c_str(), instance_.c_str(), error->message); |
1655 | - g_error_free(error); |
1656 | - return false; |
1657 | - } |
1658 | - |
1659 | - return true; |
1660 | - })) |
1661 | - { |
1662 | - g_warning("Unable to stop Upstart instance"); |
1663 | - } |
1664 | -} |
1665 | - |
1666 | -/** Create a new Upstart Instance object that can track the job and |
1667 | - get information about it. |
1668 | - |
1669 | - \param appId Application ID |
1670 | - \param job Upstart job name |
1671 | - \param instance Upstart instance name |
1672 | - \param urls URLs sent to the application (only on launch today) |
1673 | - \param registry Registry of persistent connections to use |
1674 | -*/ |
1675 | -Upstart::Upstart(const AppID& appId, |
1676 | - const std::string& job, |
1677 | - const std::string& instance, |
1678 | - const std::vector<Application::URL>& urls, |
1679 | - const std::shared_ptr<Registry>& registry) |
1680 | - : Base(appId, job, instance, urls, registry) |
1681 | -{ |
1682 | - g_debug("Creating a new Upstart for '%s' instance '%s'", std::string(appId).c_str(), instance.c_str()); |
1683 | -} |
1684 | - |
1685 | -/** Small helper that we can new/delete to work better with C stuff */ |
1686 | -struct StartCHelper |
1687 | -{ |
1688 | - std::shared_ptr<Upstart> ptr; |
1689 | -}; |
1690 | - |
1691 | -/** Callback from starting an application. It checks to see whether the |
1692 | - app is already running. If it is already running then we need to send |
1693 | - the URLs to it via DBus. |
1694 | - |
1695 | - \param obj The GDBusConnection object |
1696 | - \param res Async result object |
1697 | - \param user_data A pointer to a StartCHelper structure |
1698 | -*/ |
1699 | -void Upstart::application_start_cb(GObject* obj, GAsyncResult* res, gpointer user_data) |
1700 | -{ |
1701 | - auto data = static_cast<StartCHelper*>(user_data); |
1702 | - GError* error{nullptr}; |
1703 | - GVariant* result{nullptr}; |
1704 | - |
1705 | - tracepoint(ubuntu_app_launch, libual_start_message_callback, std::string(data->ptr->appId_).c_str()); |
1706 | - |
1707 | - g_debug("Started Message Callback: %s", std::string(data->ptr->appId_).c_str()); |
1708 | - |
1709 | - result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error); |
1710 | - |
1711 | - g_clear_pointer(&result, g_variant_unref); |
1712 | - |
1713 | - if (error != nullptr) |
1714 | - { |
1715 | - if (g_dbus_error_is_remote_error(error)) |
1716 | - { |
1717 | - gchar* remote_error = g_dbus_error_get_remote_error(error); |
1718 | - g_debug("Remote error: %s", remote_error); |
1719 | - if (g_strcmp0(remote_error, "com.ubuntu.Upstart0_6.Error.AlreadyStarted") == 0) |
1720 | - { |
1721 | - auto urls = urlsToStrv(data->ptr->urls_); |
1722 | - second_exec(data->ptr->registry_->impl->_dbus.get(), /* DBus */ |
1723 | - data->ptr->registry_->impl->thread.getCancellable().get(), /* cancellable */ |
1724 | - data->ptr->primaryPid(), /* primary pid */ |
1725 | - std::string(data->ptr->appId_).c_str(), /* appid */ |
1726 | - std::string(data->ptr->instance_).c_str(), /* instance */ |
1727 | - urls.get()); /* urls */ |
1728 | - } |
1729 | - |
1730 | - g_free(remote_error); |
1731 | - } |
1732 | - else |
1733 | - { |
1734 | - g_warning("Unable to emit event to start application: %s", error->message); |
1735 | - } |
1736 | - g_error_free(error); |
1737 | - } |
1738 | - |
1739 | - delete data; |
1740 | -} |
1741 | - |
1742 | -std::string Upstart::upstartJobPath() |
1743 | -{ |
1744 | - auto manager = std::dynamic_pointer_cast<manager::Upstart>(registry_->impl->jobs); |
1745 | - return manager->upstartJobPath(job_); |
1746 | -} |
1747 | - |
1748 | -/** Go through the list of PIDs calling a function and handling |
1749 | - the issue with getting PIDs being a racey condition. |
1750 | - |
1751 | - \param eachPid Function to run on each PID |
1752 | -*/ |
1753 | -std::vector<pid_t> Upstart::forAllPids(const std::shared_ptr<Registry>& reg, |
1754 | - const AppID& appid, |
1755 | - const std::string& jobpath, |
1756 | - std::function<void(pid_t)> eachPid) |
1757 | -{ |
1758 | - std::set<pid_t> seenPids; |
1759 | - bool added = true; |
1760 | - |
1761 | - while (added) |
1762 | - { |
1763 | - added = false; |
1764 | - auto pidlist = pids(reg, appid, jobpath); |
1765 | - for (auto pid : pidlist) |
1766 | - { |
1767 | - if (seenPids.insert(pid).second) |
1768 | - { |
1769 | - eachPid(pid); |
1770 | - added = true; |
1771 | - } |
1772 | - } |
1773 | - } |
1774 | - |
1775 | - return std::vector<pid_t>(seenPids.begin(), seenPids.end()); |
1776 | -} |
1777 | - |
1778 | -/** Pauses this application by sending SIGSTOP to all the PIDs in the |
1779 | - cgroup and tells Zeitgeist that we've left the application. */ |
1780 | -void Upstart::pause() |
1781 | -{ |
1782 | - g_debug("Pausing application: %s", std::string(appId_).c_str()); |
1783 | - |
1784 | - auto registry = registry_; |
1785 | - auto appid = appId_; |
1786 | - auto instance = instance_; |
1787 | - auto jobpath = upstartJobPath(); |
1788 | - |
1789 | - registry->impl->thread.executeOnThread([registry, appid, instance, jobpath] { |
1790 | - auto pids = forAllPids(registry, appid, jobpath, [](pid_t pid) { |
1791 | - auto oomval = oom::paused(); |
1792 | - g_debug("Pausing PID: %d (%d)", pid, int(oomval)); |
1793 | - signalToPid(pid, SIGSTOP); |
1794 | - oomValueToPid(pid, oomval); |
1795 | - }); |
1796 | - |
1797 | - pidListToDbus(registry, appid, instance, pids, "ApplicationPaused"); |
1798 | - }); |
1799 | - |
1800 | - registry_->impl->zgSendEvent(appId_, ZEITGEIST_ZG_LEAVE_EVENT); |
1801 | -} |
1802 | - |
1803 | -/** Resumes this application by sending SIGCONT to all the PIDs in the |
1804 | - cgroup and tells Zeitgeist that we're accessing the application. */ |
1805 | -void Upstart::resume() |
1806 | -{ |
1807 | - g_debug("Resuming application: %s", std::string(appId_).c_str()); |
1808 | - |
1809 | - auto registry = registry_; |
1810 | - auto appid = appId_; |
1811 | - auto instance = instance_; |
1812 | - auto jobpath = upstartJobPath(); |
1813 | - |
1814 | - registry->impl->thread.executeOnThread([registry, appid, instance, jobpath] { |
1815 | - auto pids = forAllPids(registry, appid, jobpath, [](pid_t pid) { |
1816 | - auto oomval = oom::focused(); |
1817 | - g_debug("Resuming PID: %d (%d)", pid, int(oomval)); |
1818 | - signalToPid(pid, SIGCONT); |
1819 | - oomValueToPid(pid, oomval); |
1820 | - }); |
1821 | - |
1822 | - pidListToDbus(registry, appid, instance, pids, "ApplicationResumed"); |
1823 | - }); |
1824 | - |
1825 | - registry_->impl->zgSendEvent(appId_, ZEITGEIST_ZG_ACCESS_EVENT); |
1826 | -} |
1827 | - |
1828 | -std::vector<pid_t> Upstart::pids(const std::shared_ptr<Registry>& reg, const AppID& appid, const std::string& jobpath) |
1829 | -{ |
1830 | - auto manager = std::dynamic_pointer_cast<manager::Upstart>(reg->impl->jobs); |
1831 | - auto pids = manager->pidsFromCgroup(jobpath); |
1832 | - g_debug("Got %d PIDs for AppID '%s'", int(pids.size()), std::string(appid).c_str()); |
1833 | - return pids; |
1834 | -} |
1835 | - |
1836 | -} // namespace instances |
1837 | - |
1838 | -namespace manager |
1839 | -{ |
1840 | - |
1841 | -Upstart::Upstart(std::shared_ptr<Registry> registry) |
1842 | - : Base(registry) |
1843 | -{ |
1844 | -} |
1845 | - |
1846 | -Upstart::~Upstart() |
1847 | -{ |
1848 | - auto dohandle = [&](guint& handle) { |
1849 | - if (handle != 0) |
1850 | - { |
1851 | - g_dbus_connection_signal_unsubscribe(dbus_.get(), handle); |
1852 | - handle = 0; |
1853 | - } |
1854 | - }; |
1855 | - |
1856 | - dohandle(handle_jobStarted); |
1857 | - dohandle(handle_jobStopped); |
1858 | - dohandle(handle_jobFailed); |
1859 | -} |
1860 | - |
1861 | -/** Launch an application and create a new Upstart instance object to track |
1862 | - its progress. |
1863 | - |
1864 | - \param appId Application ID |
1865 | - \param job Upstart job name |
1866 | - \param instance Upstart instance name |
1867 | - \param urls URLs sent to the application (only on launch today) |
1868 | - \param mode Whether or not to setup the environment for testing |
1869 | - \param getenv A function to get additional environment variable when appropriate |
1870 | -*/ |
1871 | -std::shared_ptr<Application::Instance> Upstart::launch( |
1872 | - const AppID& appId, |
1873 | - const std::string& job, |
1874 | - const std::string& instance, |
1875 | - const std::vector<Application::URL>& urls, |
1876 | - launchMode mode, |
1877 | - std::function<std::list<std::pair<std::string, std::string>>(void)>& getenv) |
1878 | -{ |
1879 | - if (appId.empty()) |
1880 | - return {}; |
1881 | - |
1882 | - auto registry = registry_.lock(); |
1883 | - |
1884 | - if (!registry) |
1885 | - { |
1886 | - g_warning("Registry object invalid!"); |
1887 | - return {}; |
1888 | - } |
1889 | - |
1890 | - return registry->impl->thread.executeOnThread<std::shared_ptr<instance::Upstart>>( |
1891 | - [&]() -> std::shared_ptr<instance::Upstart> { |
1892 | - auto manager = std::dynamic_pointer_cast<manager::Upstart>(registry->impl->jobs); |
1893 | - std::string appIdStr{appId}; |
1894 | - g_debug("Initializing params for an new instance::Upstart for: %s", appIdStr.c_str()); |
1895 | - |
1896 | - tracepoint(ubuntu_app_launch, libual_start, appIdStr.c_str()); |
1897 | - |
1898 | - int timeout = 1; |
1899 | - if (ubuntu::app_launch::Registry::Impl::isWatchingAppStarting()) |
1900 | - { |
1901 | - timeout = 0; |
1902 | - } |
1903 | - |
1904 | - auto handshake = starting_handshake_start(appIdStr.c_str(), instance.c_str(), timeout); |
1905 | - if (handshake == nullptr) |
1906 | - { |
1907 | - g_warning("Unable to setup starting handshake"); |
1908 | - } |
1909 | - |
1910 | - /* Figure out the DBus path for the job */ |
1911 | - auto jobpath = manager->upstartJobPath(job); |
1912 | - |
1913 | - /* Build up our environment */ |
1914 | - auto env = getenv(); |
1915 | - |
1916 | - env.emplace_back(std::make_pair("APP_ID", appIdStr)); /* Application ID */ |
1917 | - env.emplace_back(std::make_pair("APP_LAUNCHER_PID", std::to_string(getpid()))); /* Who we are, for bugs */ |
1918 | - |
1919 | - if (!urls.empty()) |
1920 | - { |
1921 | - auto accumfunc = [](const std::string& prev, Application::URL thisurl) -> std::string { |
1922 | - gchar* gescaped = g_shell_quote(thisurl.value().c_str()); |
1923 | - std::string escaped; |
1924 | - if (gescaped != nullptr) |
1925 | - { |
1926 | - escaped = gescaped; |
1927 | - g_free(gescaped); |
1928 | - } |
1929 | - else |
1930 | - { |
1931 | - g_warning("Unable to escape URL: %s", thisurl.value().c_str()); |
1932 | - return prev; |
1933 | - } |
1934 | - |
1935 | - if (prev.empty()) |
1936 | - { |
1937 | - return escaped; |
1938 | - } |
1939 | - else |
1940 | - { |
1941 | - return prev + " " + escaped; |
1942 | - } |
1943 | - }; |
1944 | - auto urlstring = std::accumulate(urls.begin(), urls.end(), std::string{}, accumfunc); |
1945 | - env.emplace_back(std::make_pair("APP_URIS", urlstring)); |
1946 | - } |
1947 | - |
1948 | - if (mode == launchMode::TEST) |
1949 | - { |
1950 | - env.emplace_back(std::make_pair("QT_LOAD_TESTABILITY", "1")); |
1951 | - } |
1952 | - |
1953 | - /* Convert to GVariant */ |
1954 | - GVariantBuilder builder; |
1955 | - g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); |
1956 | - |
1957 | - g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); |
1958 | - |
1959 | - for (const auto& envvar : env) |
1960 | - { |
1961 | - g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf( |
1962 | - "%s=%s", envvar.first.c_str(), envvar.second.c_str()))); |
1963 | - } |
1964 | - |
1965 | - g_variant_builder_close(&builder); |
1966 | - g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE)); |
1967 | - |
1968 | - auto retval = std::make_shared<instance::Upstart>(appId, job, instance, urls, registry); |
1969 | - auto chelper = new instance::StartCHelper{}; |
1970 | - chelper->ptr = retval; |
1971 | - |
1972 | - tracepoint(ubuntu_app_launch, handshake_wait, appIdStr.c_str()); |
1973 | - starting_handshake_wait(handshake); |
1974 | - tracepoint(ubuntu_app_launch, handshake_complete, appIdStr.c_str()); |
1975 | - |
1976 | - /* Call the job start function */ |
1977 | - g_debug("Asking Upstart to start task for: %s", appIdStr.c_str()); |
1978 | - g_dbus_connection_call(registry->impl->_dbus.get(), /* bus */ |
1979 | - DBUS_SERVICE_UPSTART, /* service name */ |
1980 | - jobpath.c_str(), /* Path */ |
1981 | - DBUS_INTERFACE_UPSTART_JOB, /* interface */ |
1982 | - "Start", /* method */ |
1983 | - g_variant_builder_end(&builder), /* params */ |
1984 | - nullptr, /* return */ |
1985 | - G_DBUS_CALL_FLAGS_NONE, /* flags */ |
1986 | - -1, /* default timeout */ |
1987 | - registry->impl->thread.getCancellable().get(), /* cancellable */ |
1988 | - instance::Upstart::application_start_cb, /* callback */ |
1989 | - chelper /* object */ |
1990 | - ); |
1991 | - |
1992 | - tracepoint(ubuntu_app_launch, libual_start_message_sent, appIdStr.c_str()); |
1993 | - |
1994 | - return retval; |
1995 | - }); |
1996 | -} |
1997 | - |
1998 | -/** Special characters that could be an application name that |
1999 | - would activate in a regex */ |
2000 | -const static std::regex regexCharacters("([\\.\\-])"); |
2001 | - |
2002 | -std::shared_ptr<Application::Instance> Upstart::existing(const AppID& appId, |
2003 | - const std::string& job, |
2004 | - const std::string& instance, |
2005 | - const std::vector<Application::URL>& urls) |
2006 | -{ |
2007 | - return std::make_shared<instance::Upstart>(appId, job, instance, urls, registry_.lock()); |
2008 | -} |
2009 | - |
2010 | -std::vector<std::shared_ptr<instance::Base>> Upstart::instances(const AppID& appID, const std::string& job) |
2011 | -{ |
2012 | - std::vector<std::shared_ptr<instance::Base>> vect; |
2013 | - auto startsWith = std::string(appID); |
2014 | - if (job != "application-click") |
2015 | - { |
2016 | - startsWith += "-"; |
2017 | - } |
2018 | - |
2019 | - auto regexstr = |
2020 | - std::string{"^(?:"} + std::regex_replace(startsWith, regexCharacters, "\\$&") + std::string{")(\\d*)$"}; |
2021 | - auto instanceRegex = std::regex(regexstr); |
2022 | - |
2023 | - for (auto instance : upstartInstancesForJob(job)) |
2024 | - { |
2025 | - std::smatch instanceMatch; |
2026 | - g_debug("Looking at job '%s' instance: %s", job.c_str(), instance.c_str()); |
2027 | - if (std::regex_match(instance, instanceMatch, instanceRegex)) |
2028 | - { |
2029 | - auto app = existing(appID, job, instanceMatch[1].str(), {}); |
2030 | - vect.emplace_back(std::dynamic_pointer_cast<instance::Base>(app)); |
2031 | - } |
2032 | - } |
2033 | - |
2034 | - g_debug("App '%s' has %d instances", std::string(appID).c_str(), int(vect.size())); |
2035 | - |
2036 | - return vect; |
2037 | -} |
2038 | - |
2039 | -/** Structure to track the data needed for upstart events. This cleans |
2040 | - up the lifecycle as we're passing this as a pointer through the |
2041 | - GLib calls. */ |
2042 | -struct upstartEventData |
2043 | -{ |
2044 | - /** Keeping a weak pointer because the handle is held by |
2045 | - the registry implementation. */ |
2046 | - std::weak_ptr<Registry> weakReg; |
2047 | -}; |
2048 | - |
2049 | -/** Regex to parse the JOB environment variable from Upstart */ |
2050 | -const std::regex jobenv_regex{"^JOB=(application\\-(?:click|snap|legacy))$"}; |
2051 | -/** Regex to parse the INSTANCE environment variable from Upstart */ |
2052 | -const std::regex instanceenv_regex{"^INSTANCE=(.*?)(?:\\-([0-9]*))?+$"}; |
2053 | - |
2054 | -/** Core of most of the events that come from Upstart directly. Includes parsing of the |
2055 | - Upstart event environment and calling the appropriate signal with the right Application |
2056 | - object and eventually its instance */ |
2057 | -void Upstart::upstartEventEmitted(core::Signal<const std::string&, const std::string&, const std::string&>& signal, |
2058 | - std::shared_ptr<GVariant> params, |
2059 | - const std::shared_ptr<Registry>& reg) |
2060 | -{ |
2061 | - std::string jobname; |
2062 | - std::string sappid; |
2063 | - std::string instance; |
2064 | - |
2065 | - gchar* env = nullptr; |
2066 | - auto envs = g_variant_get_child_value(params.get(), 1); |
2067 | - GVariantIter iter; |
2068 | - g_variant_iter_init(&iter, envs); |
2069 | - |
2070 | - while (g_variant_iter_loop(&iter, "s", &env)) |
2071 | - { |
2072 | - std::smatch match; |
2073 | - std::string senv = env; |
2074 | - |
2075 | - if (std::regex_match(senv, match, jobenv_regex)) |
2076 | - { |
2077 | - jobname = match[1].str(); |
2078 | - } |
2079 | - else if (std::regex_match(senv, match, instanceenv_regex)) |
2080 | - { |
2081 | - sappid = match[1].str(); |
2082 | - instance = match[2].str(); |
2083 | - } |
2084 | - } |
2085 | - |
2086 | - g_variant_unref(envs); |
2087 | - |
2088 | - if (jobname.empty()) |
2089 | - { |
2090 | - return; |
2091 | - } |
2092 | - |
2093 | - g_debug("Upstart Event for job '%s' appid '%s' instance '%s'", jobname.c_str(), sappid.c_str(), instance.c_str()); |
2094 | - |
2095 | - signal(jobname, sappid, instance); |
2096 | -} |
2097 | - |
2098 | -/** Grab the signal object for application startup. If we're not already listing for |
2099 | - those signals this sets up a listener for them. */ |
2100 | -core::Signal<const std::string&, const std::string&, const std::string&>& Upstart::jobStarted() |
2101 | -{ |
2102 | - std::call_once(flag_jobStarted, [this]() { |
2103 | - auto reg = registry_.lock(); |
2104 | - |
2105 | - reg->impl->thread.executeOnThread<bool>([this, reg]() { |
2106 | - upstartEventData* data = new upstartEventData{reg}; |
2107 | - |
2108 | - handle_jobStarted = g_dbus_connection_signal_subscribe( |
2109 | - reg->impl->_dbus.get(), /* bus */ |
2110 | - nullptr, /* sender */ |
2111 | - DBUS_INTERFACE_UPSTART, /* interface */ |
2112 | - "EventEmitted", /* signal */ |
2113 | - DBUS_PATH_UPSTART, /* path */ |
2114 | - "started", /* arg0 */ |
2115 | - G_DBUS_SIGNAL_FLAGS_NONE, |
2116 | - [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, |
2117 | - gpointer user_data) { |
2118 | - auto data = static_cast<upstartEventData*>(user_data); |
2119 | - auto reg = data->weakReg.lock(); |
2120 | - |
2121 | - if (!reg) |
2122 | - { |
2123 | - g_warning("Registry object invalid!"); |
2124 | - return; |
2125 | - } |
2126 | - |
2127 | - auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); |
2128 | - auto upstart = std::dynamic_pointer_cast<Upstart>(reg->impl->jobs); |
2129 | - upstart->upstartEventEmitted(upstart->sig_jobStarted, sparams, reg); |
2130 | - }, /* callback */ |
2131 | - data, /* user data */ |
2132 | - [](gpointer user_data) { |
2133 | - auto data = static_cast<upstartEventData*>(user_data); |
2134 | - delete data; |
2135 | - }); /* user data destroy */ |
2136 | - |
2137 | - return true; |
2138 | - }); |
2139 | - }); |
2140 | - |
2141 | - return sig_jobStarted; |
2142 | -} |
2143 | - |
2144 | -/** Grab the signal object for application stopping. If we're not already listing for |
2145 | - those signals this sets up a listener for them. */ |
2146 | -core::Signal<const std::string&, const std::string&, const std::string&>& Upstart::jobStopped() |
2147 | -{ |
2148 | - std::call_once(flag_jobStopped, [this]() { |
2149 | - auto reg = registry_.lock(); |
2150 | - |
2151 | - reg->impl->thread.executeOnThread<bool>([this, reg]() { |
2152 | - upstartEventData* data = new upstartEventData{reg}; |
2153 | - |
2154 | - handle_jobStopped = g_dbus_connection_signal_subscribe( |
2155 | - reg->impl->_dbus.get(), /* bus */ |
2156 | - nullptr, /* sender */ |
2157 | - DBUS_INTERFACE_UPSTART, /* interface */ |
2158 | - "EventEmitted", /* signal */ |
2159 | - DBUS_PATH_UPSTART, /* path */ |
2160 | - "stopped", /* arg0 */ |
2161 | - G_DBUS_SIGNAL_FLAGS_NONE, |
2162 | - [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, |
2163 | - gpointer user_data) { |
2164 | - auto data = static_cast<upstartEventData*>(user_data); |
2165 | - auto reg = data->weakReg.lock(); |
2166 | - |
2167 | - if (!reg) |
2168 | - { |
2169 | - g_warning("Registry object invalid!"); |
2170 | - return; |
2171 | - } |
2172 | - |
2173 | - auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); |
2174 | - auto upstart = std::dynamic_pointer_cast<Upstart>(reg->impl->jobs); |
2175 | - upstart->upstartEventEmitted(upstart->sig_jobStopped, sparams, reg); |
2176 | - }, /* callback */ |
2177 | - data, /* user data */ |
2178 | - [](gpointer user_data) { |
2179 | - auto data = static_cast<upstartEventData*>(user_data); |
2180 | - delete data; |
2181 | - }); /* user data destroy */ |
2182 | - |
2183 | - return true; |
2184 | - }); |
2185 | - }); |
2186 | - |
2187 | - return sig_jobStopped; |
2188 | -} |
2189 | - |
2190 | -/** Grab the signal object for application failing. If we're not already listing for |
2191 | - those signals this sets up a listener for them. */ |
2192 | -core::Signal<const std::string&, const std::string&, const std::string&, Registry::FailureType>& Upstart::jobFailed() |
2193 | -{ |
2194 | - std::call_once(flag_jobFailed, [this]() { |
2195 | - auto reg = registry_.lock(); |
2196 | - |
2197 | - reg->impl->thread.executeOnThread<bool>([this, reg]() { |
2198 | - upstartEventData* data = new upstartEventData{reg}; |
2199 | - |
2200 | - handle_jobFailed = g_dbus_connection_signal_subscribe( |
2201 | - reg->impl->_dbus.get(), /* bus */ |
2202 | - nullptr, /* sender */ |
2203 | - "com.canonical.UbuntuAppLaunch", /* interface */ |
2204 | - "ApplicationFailed", /* signal */ |
2205 | - "/", /* path */ |
2206 | - nullptr, /* arg0 */ |
2207 | - G_DBUS_SIGNAL_FLAGS_NONE, |
2208 | - [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, |
2209 | - gpointer user_data) { |
2210 | - auto data = static_cast<upstartEventData*>(user_data); |
2211 | - auto reg = data->weakReg.lock(); |
2212 | - |
2213 | - if (!reg) |
2214 | - { |
2215 | - g_warning("Registry object invalid!"); |
2216 | - return; |
2217 | - } |
2218 | - |
2219 | - const gchar* sappid = nullptr; |
2220 | - const gchar* sinstid = nullptr; |
2221 | - const gchar* typestr = nullptr; |
2222 | - |
2223 | - Registry::FailureType type = Registry::FailureType::CRASH; |
2224 | - g_variant_get(params, "(&s&s&s)", &sappid, &sinstid, &typestr); |
2225 | - |
2226 | - if (g_strcmp0("crash", typestr) == 0) |
2227 | - { |
2228 | - type = Registry::FailureType::CRASH; |
2229 | - } |
2230 | - else if (g_strcmp0("start-failure", typestr) == 0) |
2231 | - { |
2232 | - type = Registry::FailureType::START_FAILURE; |
2233 | - } |
2234 | - else |
2235 | - { |
2236 | - g_warning("Application failure type '%s' unknown, reporting as a crash", typestr); |
2237 | - } |
2238 | - |
2239 | - auto upstart = std::dynamic_pointer_cast<Upstart>(reg->impl->jobs); |
2240 | - upstart->sig_jobFailed("application-snap", sappid, sinstid, type); |
2241 | - }, /* callback */ |
2242 | - data, /* user data */ |
2243 | - [](gpointer user_data) { |
2244 | - auto data = static_cast<upstartEventData*>(user_data); |
2245 | - delete data; |
2246 | - }); /* user data destroy */ |
2247 | - |
2248 | - return true; |
2249 | - }); |
2250 | - }); |
2251 | - |
2252 | - return sig_jobFailed; |
2253 | -} |
2254 | - |
2255 | -/** Initialize the CGManager connection, including a timeout to disconnect |
2256 | - as CGManager doesn't free resources entirely well. So it's better if |
2257 | - we connect and disconnect occationally */ |
2258 | -void Upstart::initCGManager() |
2259 | -{ |
2260 | - if (cgManager_) |
2261 | - return; |
2262 | - |
2263 | - auto registry = registry_.lock(); |
2264 | - |
2265 | - cgManager_ = registry->impl->thread.executeOnThread<std::shared_ptr<GDBusConnection>>([this, registry]() { |
2266 | - bool use_session_bus = g_getenv("UBUNTU_APP_LAUNCH_CG_MANAGER_SESSION_BUS") != nullptr; |
2267 | - if (use_session_bus) |
2268 | - { |
2269 | - /* For working dbusmock */ |
2270 | - g_debug("Connecting to CG Manager on session bus"); |
2271 | - return registry->impl->_dbus; |
2272 | - } |
2273 | - |
2274 | - auto cancel = |
2275 | - std::shared_ptr<GCancellable>(g_cancellable_new(), [](GCancellable* cancel) { g_clear_object(&cancel); }); |
2276 | - |
2277 | - /* Ensure that we do not wait for more than a second */ |
2278 | - registry->impl->thread.timeoutSeconds(std::chrono::seconds{1}, |
2279 | - [cancel]() { g_cancellable_cancel(cancel.get()); }); |
2280 | - |
2281 | - GError* error = nullptr; |
2282 | - auto retval = std::shared_ptr<GDBusConnection>( |
2283 | - g_dbus_connection_new_for_address_sync(CGMANAGER_DBUS_PATH, /* cgmanager path */ |
2284 | - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, /* flags */ |
2285 | - nullptr, /* Auth Observer */ |
2286 | - cancel.get(), /* Cancellable */ |
2287 | - &error), |
2288 | - [](GDBusConnection* con) { g_clear_object(&con); }); |
2289 | - |
2290 | - if (error != nullptr) |
2291 | - { |
2292 | - g_warning("Unable to get CGManager connection: %s", error->message); |
2293 | - g_error_free(error); |
2294 | - } |
2295 | - |
2296 | - return retval; |
2297 | - }); |
2298 | - |
2299 | - /* NOTE: This will execute on the thread */ |
2300 | - registry->impl->thread.timeoutSeconds(std::chrono::seconds{10}, [this]() { cgManager_.reset(); }); |
2301 | -} |
2302 | - |
2303 | -/** Get a list of PIDs from a CGroup, uses the CGManager connection to list |
2304 | - all of the PIDs. It is important to note that this is an IPC call, so it can |
2305 | - by its nature, be racy. Once the message has been sent the group can change. |
2306 | - You should take that into account in your usage of it. */ |
2307 | -std::vector<pid_t> Upstart::pidsFromCgroup(const std::string& jobpath) |
2308 | -{ |
2309 | - initCGManager(); |
2310 | - auto lmanager = cgManager_; /* Grab a local copy so we ensure it lasts through our lifetime */ |
2311 | - auto registry = registry_.lock(); |
2312 | - |
2313 | - return registry->impl->thread.executeOnThread<std::vector<pid_t>>([&jobpath, lmanager]() -> std::vector<pid_t> { |
2314 | - GError* error = nullptr; |
2315 | - const gchar* name = g_getenv("UBUNTU_APP_LAUNCH_CG_MANAGER_NAME"); |
2316 | - std::string groupname; |
2317 | - if (!jobpath.empty()) |
2318 | - { |
2319 | - groupname = "upstart/" + jobpath; |
2320 | - } |
2321 | - |
2322 | - g_debug("Looking for cg manager '%s' group '%s'", name, groupname.c_str()); |
2323 | - |
2324 | - auto vtpids = g_dbus_connection_call_sync( |
2325 | - lmanager.get(), /* connection */ |
2326 | - name, /* bus name for direct connection is nullptr */ |
2327 | - "/org/linuxcontainers/cgmanager", /* object */ |
2328 | - "org.linuxcontainers.cgmanager0_0", /* interface */ |
2329 | - "GetTasksRecursive", /* method */ |
2330 | - g_variant_new("(ss)", "freezer", groupname.empty() ? "" : groupname.c_str()), /* params */ |
2331 | - G_VARIANT_TYPE("(ai)"), /* output */ |
2332 | - G_DBUS_CALL_FLAGS_NONE, /* flags */ |
2333 | - -1, /* default timeout */ |
2334 | - nullptr, /* cancellable */ |
2335 | - &error); /* error */ |
2336 | - |
2337 | - if (error != nullptr) |
2338 | - { |
2339 | - g_warning("Unable to get PID list from cgroup manager: %s", error->message); |
2340 | - g_error_free(error); |
2341 | - return {}; |
2342 | - } |
2343 | - |
2344 | - auto vpids = g_variant_get_child_value(vtpids, 0); |
2345 | - GVariantIter iter; |
2346 | - g_variant_iter_init(&iter, vpids); |
2347 | - gint32 pid; |
2348 | - std::vector<pid_t> pids; |
2349 | - |
2350 | - while (g_variant_iter_loop(&iter, "i", &pid)) |
2351 | - { |
2352 | - pids.push_back(pid); |
2353 | - } |
2354 | - |
2355 | - g_variant_unref(vpids); |
2356 | - g_variant_unref(vtpids); |
2357 | - |
2358 | - return pids; |
2359 | - }); |
2360 | -} |
2361 | - |
2362 | -/** Looks to find the Upstart object path for a specific Upstart job. This first |
2363 | - checks the cache, and otherwise does the lookup on DBus. */ |
2364 | -std::string Upstart::upstartJobPath(const std::string& job) |
2365 | -{ |
2366 | - try |
2367 | - { |
2368 | - return upstartJobPathCache_.at(job); |
2369 | - } |
2370 | - catch (std::out_of_range& e) |
2371 | - { |
2372 | - auto registry = registry_.lock(); |
2373 | - auto path = registry->impl->thread.executeOnThread<std::string>([this, &job, ®istry]() -> std::string { |
2374 | - GError* error = nullptr; |
2375 | - auto job_path_variant = |
2376 | - g_dbus_connection_call_sync(registry->impl->_dbus.get(), /* connection */ |
2377 | - DBUS_SERVICE_UPSTART, /* service */ |
2378 | - DBUS_PATH_UPSTART, /* path */ |
2379 | - DBUS_INTERFACE_UPSTART, /* iface */ |
2380 | - "GetJobByName", /* method */ |
2381 | - g_variant_new("(s)", job.c_str()), /* params */ |
2382 | - G_VARIANT_TYPE("(o)"), /* return */ |
2383 | - G_DBUS_CALL_FLAGS_NONE, /* flags */ |
2384 | - -1, /* timeout: default */ |
2385 | - registry->impl->thread.getCancellable().get(), /* cancellable */ |
2386 | - &error); /* error */ |
2387 | - |
2388 | - if (error != nullptr) |
2389 | - { |
2390 | - g_warning("Unable to find job '%s': %s", job.c_str(), error->message); |
2391 | - g_error_free(error); |
2392 | - return {}; |
2393 | - } |
2394 | - |
2395 | - gchar* job_path = nullptr; |
2396 | - g_variant_get(job_path_variant, "(o)", &job_path); |
2397 | - g_variant_unref(job_path_variant); |
2398 | - |
2399 | - if (job_path != nullptr) |
2400 | - { |
2401 | - std::string path(job_path); |
2402 | - g_free(job_path); |
2403 | - return path; |
2404 | - } |
2405 | - else |
2406 | - { |
2407 | - return {}; |
2408 | - } |
2409 | - }); |
2410 | - |
2411 | - upstartJobPathCache_[job] = path; |
2412 | - return path; |
2413 | - } |
2414 | -} |
2415 | - |
2416 | -/** Queries Upstart to get all the instances of a given job. This |
2417 | - can take a while as the number of dbus calls is n+1. It is |
2418 | - rare that apps have many instances though. */ |
2419 | -std::list<std::string> Upstart::upstartInstancesForJob(const std::string& job) |
2420 | -{ |
2421 | - std::string jobpath = upstartJobPath(job); |
2422 | - if (jobpath.empty()) |
2423 | - { |
2424 | - return {}; |
2425 | - } |
2426 | - |
2427 | - auto registry = registry_.lock(); |
2428 | - return registry->impl->thread.executeOnThread<std::list<std::string>>( |
2429 | - [this, &job, &jobpath, ®istry]() -> std::list<std::string> { |
2430 | - GError* error = nullptr; |
2431 | - auto instance_tuple = |
2432 | - g_dbus_connection_call_sync(registry->impl->_dbus.get(), /* connection */ |
2433 | - DBUS_SERVICE_UPSTART, /* service */ |
2434 | - jobpath.c_str(), /* object path */ |
2435 | - DBUS_INTERFACE_UPSTART_JOB, /* iface */ |
2436 | - "GetAllInstances", /* method */ |
2437 | - nullptr, /* params */ |
2438 | - G_VARIANT_TYPE("(ao)"), /* return type */ |
2439 | - G_DBUS_CALL_FLAGS_NONE, /* flags */ |
2440 | - -1, /* timeout: default */ |
2441 | - registry->impl->thread.getCancellable().get(), /* cancellable */ |
2442 | - &error); |
2443 | - |
2444 | - if (error != nullptr) |
2445 | - { |
2446 | - g_warning("Unable to get instances of job '%s': %s", job.c_str(), error->message); |
2447 | - g_error_free(error); |
2448 | - return {}; |
2449 | - } |
2450 | - |
2451 | - if (instance_tuple == nullptr) |
2452 | - { |
2453 | - return {}; |
2454 | - } |
2455 | - |
2456 | - auto instance_list = g_variant_get_child_value(instance_tuple, 0); |
2457 | - g_variant_unref(instance_tuple); |
2458 | - |
2459 | - GVariantIter instance_iter; |
2460 | - g_variant_iter_init(&instance_iter, instance_list); |
2461 | - const gchar* instance_path = nullptr; |
2462 | - std::list<std::string> instances; |
2463 | - |
2464 | - while (g_variant_iter_loop(&instance_iter, "&o", &instance_path)) |
2465 | - { |
2466 | - auto props_tuple = |
2467 | - g_dbus_connection_call_sync(registry->impl->_dbus.get(), /* connection */ |
2468 | - DBUS_SERVICE_UPSTART, /* service */ |
2469 | - instance_path, /* object path */ |
2470 | - "org.freedesktop.DBus.Properties", /* interface */ |
2471 | - "GetAll", /* method */ |
2472 | - g_variant_new("(s)", DBUS_INTERFACE_UPSTART_INSTANCE), /* params */ |
2473 | - G_VARIANT_TYPE("(a{sv})"), /* return type */ |
2474 | - G_DBUS_CALL_FLAGS_NONE, /* flags */ |
2475 | - -1, /* timeout: default */ |
2476 | - registry->impl->thread.getCancellable().get(), /* cancellable */ |
2477 | - &error); |
2478 | - |
2479 | - if (error != nullptr) |
2480 | - { |
2481 | - g_warning("Unable to name of instance '%s': %s", instance_path, error->message); |
2482 | - g_error_free(error); |
2483 | - error = nullptr; |
2484 | - continue; |
2485 | - } |
2486 | - |
2487 | - auto props_dict = g_variant_get_child_value(props_tuple, 0); |
2488 | - |
2489 | - auto namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING); |
2490 | - if (namev != nullptr) |
2491 | - { |
2492 | - auto name = g_variant_get_string(namev, nullptr); |
2493 | - g_debug("Adding instance for job '%s': %s", job.c_str(), name); |
2494 | - instances.push_back(name); |
2495 | - g_variant_unref(namev); |
2496 | - } |
2497 | - |
2498 | - g_variant_unref(props_dict); |
2499 | - g_variant_unref(props_tuple); |
2500 | - } |
2501 | - |
2502 | - g_variant_unref(instance_list); |
2503 | - |
2504 | - return instances; |
2505 | - }); |
2506 | -} |
2507 | - |
2508 | -std::list<std::string> Upstart::runningAppIds(const std::list<std::string>& jobs) |
2509 | -{ |
2510 | - std::list<std::string> instances; |
2511 | - |
2512 | - for (const auto& job : jobs) |
2513 | - { |
2514 | - auto jobinst = upstartInstancesForJob(job); |
2515 | - |
2516 | - if (job != "application-click") |
2517 | - { |
2518 | - /* Remove the instance ID */ |
2519 | - std::transform(jobinst.begin(), jobinst.end(), jobinst.begin(), |
2520 | - [](std::string& instancename) -> std::string { |
2521 | - static const std::regex instanceregex("^(.*)-[0-9]*$"); |
2522 | - std::smatch match; |
2523 | - if (std::regex_match(instancename, match, instanceregex)) |
2524 | - { |
2525 | - return match[1].str(); |
2526 | - } |
2527 | - else |
2528 | - { |
2529 | - g_warning("Unable to match instance name: %s", instancename.c_str()); |
2530 | - return {}; |
2531 | - } |
2532 | - }); |
2533 | - } |
2534 | - |
2535 | - instances.splice(instances.begin(), jobinst); |
2536 | - } |
2537 | - |
2538 | - /* Deduplicate Set */ |
2539 | - std::set<std::string> instanceset; |
2540 | - for (auto instance : instances) |
2541 | - { |
2542 | - if (!instance.empty()) |
2543 | - instanceset.insert(instance); |
2544 | - } |
2545 | - |
2546 | - g_debug("Overall there are %d instances: %s", int(instanceset.size()), |
2547 | - std::accumulate(instanceset.begin(), instanceset.end(), std::string{}, [](const std::string& instr, |
2548 | - std::string instance) { |
2549 | - return instr.empty() ? instance : instr + ", " + instance; |
2550 | - }).c_str()); |
2551 | - |
2552 | - return {instanceset.begin(), instanceset.end()}; |
2553 | -} |
2554 | - |
2555 | -} // namespace manager |
2556 | -} // namespace jobs |
2557 | -} // namespace app_launch |
2558 | -} // namespace ubuntu |
2559 | |
2560 | === removed file 'libubuntu-app-launch/jobs-upstart.h' |
2561 | --- libubuntu-app-launch/jobs-upstart.h 2017-03-21 03:20:55 +0000 |
2562 | +++ libubuntu-app-launch/jobs-upstart.h 1970-01-01 00:00:00 +0000 |
2563 | @@ -1,100 +0,0 @@ |
2564 | -/* |
2565 | - * Copyright © 2016 Canonical Ltd. |
2566 | - * |
2567 | - * This program is free software: you can redistribute it and/or modify it |
2568 | - * under the terms of the GNU General Public License version 3, as published |
2569 | - * by the Free Software Foundation. |
2570 | - * |
2571 | - * This program is distributed in the hope that it will be useful, but |
2572 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
2573 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2574 | - * PURPOSE. See the GNU General Public License for more details. |
2575 | - * |
2576 | - * You should have received a copy of the GNU General Public License along |
2577 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
2578 | - * |
2579 | - * Authors: |
2580 | - * Ted Gould <ted.gould@canonical.com> |
2581 | - */ |
2582 | - |
2583 | -#pragma once |
2584 | - |
2585 | -#include "jobs-base.h" |
2586 | -#include <gio/gio.h> |
2587 | -#include <map> |
2588 | - |
2589 | -namespace ubuntu |
2590 | -{ |
2591 | -namespace app_launch |
2592 | -{ |
2593 | -namespace jobs |
2594 | -{ |
2595 | -namespace manager |
2596 | -{ |
2597 | - |
2598 | -class Upstart : public Base |
2599 | -{ |
2600 | -public: |
2601 | - Upstart(std::shared_ptr<Registry> registry); |
2602 | - virtual ~Upstart(); |
2603 | - |
2604 | - virtual std::shared_ptr<Application::Instance> launch( |
2605 | - const AppID& appId, |
2606 | - const std::string& job, |
2607 | - const std::string& instance, |
2608 | - const std::vector<Application::URL>& urls, |
2609 | - launchMode mode, |
2610 | - std::function<std::list<std::pair<std::string, std::string>>(void)>& getenv) override; |
2611 | - virtual std::shared_ptr<Application::Instance> existing(const AppID& appId, |
2612 | - const std::string& job, |
2613 | - const std::string& instance, |
2614 | - const std::vector<Application::URL>& urls) override; |
2615 | - |
2616 | - virtual std::list<std::string> runningAppIds(const std::list<std::string>& jobs) override; |
2617 | - |
2618 | - virtual std::vector<std::shared_ptr<instance::Base>> instances(const AppID& appID, const std::string& job) override; |
2619 | - |
2620 | - /* Signals to apps */ |
2621 | - virtual core::Signal<const std::string&, const std::string&, const std::string&>& jobStarted() override; |
2622 | - virtual core::Signal<const std::string&, const std::string&, const std::string&>& jobStopped() override; |
2623 | - virtual core::Signal<const std::string&, const std::string&, const std::string&, Registry::FailureType>& jobFailed() |
2624 | - override; |
2625 | - |
2626 | - std::vector<pid_t> pidsFromCgroup(const std::string& jobpath); |
2627 | - |
2628 | - std::list<std::string> upstartInstancesForJob(const std::string& job); |
2629 | - std::string upstartJobPath(const std::string& job); |
2630 | - |
2631 | -private: |
2632 | - void initCGManager(); |
2633 | - |
2634 | - std::shared_ptr<GDBusConnection> cgManager_; |
2635 | - |
2636 | - /** Getting the Upstart job path is relatively expensive in |
2637 | - that it requires a DBus call. Worth keeping a cache of. */ |
2638 | - std::map<std::string, std::string> upstartJobPathCache_; |
2639 | - |
2640 | - core::Signal<const std::string&, const std::string&, const std::string&> sig_jobStarted; |
2641 | - core::Signal<const std::string&, const std::string&, const std::string&> sig_jobStopped; |
2642 | - core::Signal<const std::string&, const std::string&, const std::string&, Registry::FailureType> sig_jobFailed; |
2643 | - |
2644 | - guint handle_jobStarted{0}; /**< GDBus signal watcher handle for app started signal */ |
2645 | - guint handle_jobStopped{0}; /**< GDBus signal watcher handle for app stopped signal */ |
2646 | - guint handle_jobFailed{0}; /**< GDBus signal watcher handle for app failed signal */ |
2647 | - |
2648 | - std::once_flag flag_jobStarted; /**< Variable to track to see if signal handlers are installed for application |
2649 | - started */ |
2650 | - std::once_flag flag_jobStopped; /**< Variable to track to see if signal handlers are installed for application |
2651 | - stopped */ |
2652 | - std::once_flag |
2653 | - flag_jobFailed; /**< Variable to track to see if signal handlers are installed for application failed */ |
2654 | - |
2655 | - void upstartEventEmitted(core::Signal<const std::string&, const std::string&, const std::string&>& signal, |
2656 | - std::shared_ptr<GVariant> params, |
2657 | - const std::shared_ptr<Registry>& reg); |
2658 | -}; |
2659 | - |
2660 | -} // namespace manager |
2661 | -} // namespace jobs |
2662 | -} // namespace app_launch |
2663 | -} // namespace ubuntu |
2664 | |
2665 | === modified file 'libubuntu-app-launch/registry-impl.cpp' |
2666 | --- libubuntu-app-launch/registry-impl.cpp 2017-03-21 03:20:55 +0000 |
2667 | +++ libubuntu-app-launch/registry-impl.cpp 2017-03-21 03:20:55 +0000 |
2668 | @@ -21,7 +21,6 @@ |
2669 | #include "application-icon-finder.h" |
2670 | #include "application-impl-base.h" |
2671 | #include <regex> |
2672 | -#include <upstart.h> |
2673 | |
2674 | namespace ubuntu |
2675 | { |
2676 | |
2677 | === modified file 'libubuntu-app-launch/second-exec-core.c' |
2678 | --- libubuntu-app-launch/second-exec-core.c 2016-12-14 23:03:15 +0000 |
2679 | +++ libubuntu-app-launch/second-exec-core.c 2017-03-21 03:20:55 +0000 |
2680 | @@ -18,8 +18,6 @@ |
2681 | */ |
2682 | |
2683 | #include <gio/gio.h> |
2684 | -#include <nih/alloc.h> |
2685 | -#include <libnih-dbus.h> |
2686 | #include "libubuntu-app-launch/ubuntu-app-launch.h" |
2687 | #include "helpers.h" |
2688 | #include "second-exec-core.h" |
2689 | |
2690 | === modified file 'libubuntu-app-launch/ubuntu-app-launch.cpp' |
2691 | --- libubuntu-app-launch/ubuntu-app-launch.cpp 2017-03-21 03:20:55 +0000 |
2692 | +++ libubuntu-app-launch/ubuntu-app-launch.cpp 2017-03-21 03:20:55 +0000 |
2693 | @@ -19,7 +19,6 @@ |
2694 | |
2695 | extern "C" { |
2696 | #include "ubuntu-app-launch.h" |
2697 | -#include <upstart.h> |
2698 | #include <gio/gio.h> |
2699 | #include <gio/gunixfdlist.h> |
2700 | #include <string.h> |
2701 | |
2702 | === modified file 'tests/CMakeLists.txt' |
2703 | --- tests/CMakeLists.txt 2017-02-15 15:10:07 +0000 |
2704 | +++ tests/CMakeLists.txt 2017-03-21 03:20:55 +0000 |
2705 | @@ -41,13 +41,12 @@ |
2706 | add_executable (libual-test |
2707 | libual-test.cc |
2708 | mir-mock.cpp) |
2709 | -target_link_libraries (libual-test gtest_main ${GTEST_MAIN_LIBRARIES} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} ubuntu-launcher) |
2710 | +target_link_libraries (libual-test gtest_main ${GTEST_MAIN_LIBRARIES} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} launcher-static) |
2711 | |
2712 | add_executable (libual-cpp-test |
2713 | libual-cpp-test.cc |
2714 | - ${CMAKE_SOURCE_DIR}/libubuntu-app-launch/glib-thread.cpp |
2715 | mir-mock.cpp) |
2716 | -target_link_libraries (libual-cpp-test gtest_main ${GTEST_MAIN_LIBRARIES} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} ubuntu-launcher) |
2717 | +target_link_libraries (libual-cpp-test gtest_main ${GTEST_MAIN_LIBRARIES} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} launcher-static) |
2718 | |
2719 | add_executable (data-spew |
2720 | data-spew.c) |
2721 | @@ -123,45 +122,6 @@ |
2722 | |
2723 | file(COPY data DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) |
2724 | |
2725 | -# Failure Test |
2726 | - |
2727 | -add_definitions ( -DAPP_FAILED_TOOL="${CMAKE_BINARY_DIR}/application-failed" ) |
2728 | - |
2729 | -add_executable (failure-test |
2730 | - failure-test.cc) |
2731 | -target_link_libraries (failure-test gtest_main ${GTEST_MAIN_LIBRARIES} ubuntu-launcher) |
2732 | -add_test (failure-test failure-test) |
2733 | - |
2734 | -# ZG Test |
2735 | - |
2736 | -add_definitions ( -DZG_EVENT_TOOL="${CMAKE_BINARY_DIR}/zg-report-app" ) |
2737 | - |
2738 | -add_executable (zg-test |
2739 | - zg-test.cc) |
2740 | -target_link_libraries (zg-test gtest_main ${GTEST_MAIN_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GIO2_LIBRARIES}) |
2741 | -add_test (zg-test zg-test) |
2742 | - |
2743 | -# Exec Line Exec Test |
2744 | - |
2745 | -configure_file("exec-test.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/exec-test.sh" @ONLY) |
2746 | -add_test (exec-test "${CMAKE_CURRENT_BINARY_DIR}/exec-test.sh") |
2747 | - |
2748 | -# Exec Utils |
2749 | - |
2750 | -add_executable (exec-util-test |
2751 | - exec-util-test.cc) |
2752 | -target_link_libraries (exec-util-test gtest_main ubuntu-launcher ${GTEST_MAIN_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GIO2_LIBRARIES}) |
2753 | -add_test (exec-util-test exec-util-test) |
2754 | - |
2755 | -# CGroup Reap Test |
2756 | - |
2757 | -add_definitions ( -DCG_REAP_TOOL="${CMAKE_BINARY_DIR}/cgroup-reap-all" ) |
2758 | - |
2759 | -add_executable (cgroup-reap-test |
2760 | - cgroup-reap-test.cc) |
2761 | -target_link_libraries (cgroup-reap-test gtest_main ${GTEST_MAIN_LIBRARIES} ${DBUSTEST_LIBRARIES} ${GIO2_LIBRARIES}) |
2762 | -add_test (cgroup-reap-test cgroup-reap-test) |
2763 | - |
2764 | # Desktop Hook Test |
2765 | |
2766 | configure_file ("click-desktop-hook-db/test.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/click-desktop-hook-db/test.conf" @ONLY) |
2767 | @@ -182,7 +142,6 @@ |
2768 | |
2769 | add_custom_target(format-tests |
2770 | COMMAND clang-format -i -style=file |
2771 | - failure-test.cc |
2772 | application-info-desktop.cpp |
2773 | libual-cpp-test.cc |
2774 | list-apps.cpp |
2775 | @@ -197,4 +156,5 @@ |
2776 | spew-master.h |
2777 | systemd-mock.h |
2778 | zg-test.cc |
2779 | + zg-mock.h |
2780 | ) |
2781 | |
2782 | === removed file 'tests/cgroup-reap-test.cc' |
2783 | --- tests/cgroup-reap-test.cc 2017-01-11 23:22:52 +0000 |
2784 | +++ tests/cgroup-reap-test.cc 1970-01-01 00:00:00 +0000 |
2785 | @@ -1,145 +0,0 @@ |
2786 | -/* |
2787 | - * Copyright 2014 Canonical Ltd. |
2788 | - * |
2789 | - * This program is free software: you can redistribute it and/or modify it |
2790 | - * under the terms of the GNU General Public License version 3, as published |
2791 | - * by the Free Software Foundation. |
2792 | - * |
2793 | - * This program is distributed in the hope that it will be useful, but |
2794 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
2795 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2796 | - * PURPOSE. See the GNU General Public License for more details. |
2797 | - * |
2798 | - * You should have received a copy of the GNU General Public License along |
2799 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
2800 | - * |
2801 | - * Authors: |
2802 | - * Ted Gould <ted.gould@canonical.com> |
2803 | - */ |
2804 | - |
2805 | -#include <gtest/gtest.h> |
2806 | -#include <gio/gio.h> |
2807 | -#include <libdbustest/dbus-test.h> |
2808 | - |
2809 | -class CGroupReap : public ::testing::Test |
2810 | -{ |
2811 | - protected: |
2812 | - DbusTestService * service = NULL; |
2813 | - DbusTestDbusMock * cgmock = NULL; |
2814 | - GDBusConnection * bus = NULL; |
2815 | - GPid sleeppid = 0; |
2816 | - |
2817 | - virtual void SetUp() { |
2818 | - const gchar * argv[] = { "sleep", "30", NULL }; |
2819 | - g_spawn_async(NULL, |
2820 | - (gchar **)argv, |
2821 | - NULL, /* env */ |
2822 | - G_SPAWN_SEARCH_PATH, |
2823 | - NULL, NULL, /* child setup */ |
2824 | - &sleeppid, |
2825 | - NULL); /* error */ |
2826 | - ASSERT_NE(0, sleeppid); |
2827 | - |
2828 | - service = dbus_test_service_new(NULL); |
2829 | - |
2830 | - /* Create the cgroup manager mock */ |
2831 | - cgmock = dbus_test_dbus_mock_new("org.test.cgmock"); |
2832 | - g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_NAME", "org.test.cgmock", TRUE); |
2833 | - |
2834 | - DbusTestDbusMockObject * cgobject = dbus_test_dbus_mock_get_object(cgmock, "/org/linuxcontainers/cgmanager", "org.linuxcontainers.cgmanager0_0", NULL); |
2835 | - /* This Python code executes in dbusmock and checks to see if the sleeping |
2836 | - process is running. If it is, it returns its PID in the list of PIDs, if |
2837 | - not it doesn't return any PIDs. */ |
2838 | - gchar * pythoncode = g_strdup_printf( |
2839 | - "if os.spawnlp(os.P_WAIT, 'ps', 'ps', '%d') == 0 :\n" |
2840 | - " ret = [ %d ]\n" |
2841 | - "else:\n" |
2842 | - " ret = [ ]", |
2843 | - sleeppid, sleeppid); |
2844 | - dbus_test_dbus_mock_object_add_method(cgmock, cgobject, |
2845 | - "GetTasksRecursive", |
2846 | - G_VARIANT_TYPE("(ss)"), |
2847 | - G_VARIANT_TYPE("ai"), |
2848 | - pythoncode, |
2849 | - NULL); |
2850 | - g_free(pythoncode); |
2851 | - |
2852 | - /* Put it together */ |
2853 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(cgmock)); |
2854 | - dbus_test_service_start_tasks(service); |
2855 | - |
2856 | - bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2857 | - g_dbus_connection_set_exit_on_close(bus, FALSE); |
2858 | - g_object_add_weak_pointer(G_OBJECT(bus), (gpointer *)&bus); |
2859 | - |
2860 | - /* Make sure we pretend the CG manager is just on our bus */ |
2861 | - g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_SESSION_BUS", "YES", TRUE); |
2862 | - } |
2863 | - |
2864 | - virtual void TearDown() { |
2865 | - g_clear_object(&cgmock); |
2866 | - g_clear_object(&service); |
2867 | - |
2868 | - g_object_unref(bus); |
2869 | - |
2870 | - unsigned int cleartry = 0; |
2871 | - while (bus != NULL && cleartry < 100) { |
2872 | - pause(100); |
2873 | - cleartry++; |
2874 | - } |
2875 | - ASSERT_EQ(bus, nullptr); |
2876 | - |
2877 | - g_debug("Killing the sleeper: %d", sleeppid); |
2878 | - kill(sleeppid, SIGKILL); |
2879 | - } |
2880 | - |
2881 | - static gboolean pause_helper (gpointer pmainloop) { |
2882 | - g_main_loop_quit(static_cast<GMainLoop *>(pmainloop)); |
2883 | - return G_SOURCE_REMOVE; |
2884 | - } |
2885 | - |
2886 | - void pause (guint time) { |
2887 | - if (time > 0) { |
2888 | - GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
2889 | - g_timeout_add(time, pause_helper, mainloop); |
2890 | - |
2891 | - g_main_loop_run(mainloop); |
2892 | - |
2893 | - g_main_loop_unref(mainloop); |
2894 | - } |
2895 | - |
2896 | - while (g_main_pending()) { |
2897 | - g_main_iteration(TRUE); |
2898 | - } |
2899 | - } |
2900 | - |
2901 | - bool sleepRunning (void) { |
2902 | - gint status = 1; |
2903 | - gchar * cmdline = g_strdup_printf("ps %d", sleeppid); |
2904 | - |
2905 | - g_spawn_command_line_sync(cmdline, NULL, NULL, &status, NULL); |
2906 | - g_free(cmdline); |
2907 | - |
2908 | - return status == 0; |
2909 | - } |
2910 | -}; |
2911 | - |
2912 | -TEST_F(CGroupReap, KillSleep) |
2913 | -{ |
2914 | - g_setenv("UPSTART_JOB", "foo", TRUE); |
2915 | - g_setenv("UPSTART_INSTANCE", "bar", TRUE); |
2916 | - |
2917 | - ASSERT_TRUE(g_spawn_command_line_sync(CG_REAP_TOOL, NULL, NULL, NULL, NULL)); |
2918 | - EXPECT_FALSE(sleepRunning()); |
2919 | - |
2920 | - DbusTestDbusMockObject * cgobject = dbus_test_dbus_mock_get_object(cgmock, "/org/linuxcontainers/cgmanager", "org.linuxcontainers.cgmanager0_0", NULL); |
2921 | - const DbusTestDbusMockCall * calls = NULL; |
2922 | - guint len = 0; |
2923 | - |
2924 | - calls = dbus_test_dbus_mock_object_get_method_calls(cgmock, cgobject, "GetTasksRecursive", &len, NULL); |
2925 | - EXPECT_EQ(2u, len); |
2926 | - EXPECT_STREQ("GetTasksRecursive", calls->name); |
2927 | - EXPECT_TRUE(g_variant_equal(calls->params, g_variant_new("(ss)", "freezer", ""))); |
2928 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(cgmock, cgobject, NULL)); |
2929 | -} |
2930 | - |
2931 | |
2932 | === removed file 'tests/exec-test-archcolon.sh' |
2933 | --- tests/exec-test-archcolon.sh 2014-04-30 21:43:28 +0000 |
2934 | +++ tests/exec-test-archcolon.sh 1970-01-01 00:00:00 +0000 |
2935 | @@ -1,18 +0,0 @@ |
2936 | -#!/bin/bash -e |
2937 | - |
2938 | -if [ "$PATH" != "$APP_DIR:/path" ] ; then |
2939 | - echo "Bad PATH: $PATH" |
2940 | - exit 1 |
2941 | -fi |
2942 | - |
2943 | -if [ "$LD_LIBRARY_PATH" != "$APP_DIR/lib:/lib" ] ; then |
2944 | - echo "Bad LD_LIBRARY_PATH: $LD_LIBRARY_PATH" |
2945 | - exit 1 |
2946 | -fi |
2947 | - |
2948 | -if [ "$QML2_IMPORT_PATH" != "/bar/qml/import" ] ; then |
2949 | - echo "Bad QML import path: $QML2_IMPORT_PATH" |
2950 | - exit 1 |
2951 | -fi |
2952 | - |
2953 | -exit 0 |
2954 | |
2955 | === removed file 'tests/exec-test-colon.sh' |
2956 | --- tests/exec-test-colon.sh 2014-04-30 21:43:28 +0000 |
2957 | +++ tests/exec-test-colon.sh 1970-01-01 00:00:00 +0000 |
2958 | @@ -1,18 +0,0 @@ |
2959 | -#!/bin/bash -e |
2960 | - |
2961 | -if [ "$PATH" != "/path" ] ; then |
2962 | - echo "Bad PATH: $PATH" |
2963 | - exit 1 |
2964 | -fi |
2965 | - |
2966 | -if [ "$LD_LIBRARY_PATH" != "/lib" ] ; then |
2967 | - echo "Bad LD_LIBRARY_PATH: $LD_LIBRARY_PATH" |
2968 | - exit 1 |
2969 | -fi |
2970 | - |
2971 | -if [ "$QML2_IMPORT_PATH" != "/bar/qml/import" ] ; then |
2972 | - echo "Bad QML import path: $QML2_IMPORT_PATH" |
2973 | - exit 1 |
2974 | -fi |
2975 | - |
2976 | -exit 0 |
2977 | |
2978 | === removed file 'tests/exec-test-full.sh' |
2979 | --- tests/exec-test-full.sh 2014-04-30 21:43:28 +0000 |
2980 | +++ tests/exec-test-full.sh 1970-01-01 00:00:00 +0000 |
2981 | @@ -1,18 +0,0 @@ |
2982 | -#!/bin/bash -e |
2983 | - |
2984 | -if [ "$PATH" != "$APP_DIR/lib/64bit-amazing/bin:$APP_DIR:/path" ] ; then |
2985 | - echo "Bad PATH: $PATH" |
2986 | - exit 1 |
2987 | -fi |
2988 | - |
2989 | -if [ "$LD_LIBRARY_PATH" != "$APP_DIR/lib/64bit-amazing:$APP_DIR/lib:/lib" ] ; then |
2990 | - echo "Bad LD_LIBRARY_PATH: $LD_LIBRARY_PATH" |
2991 | - exit 1 |
2992 | -fi |
2993 | - |
2994 | -if [ "$QML2_IMPORT_PATH" != "/bar/qml/import:$APP_DIR/lib/64bit-amazing" ] ; then |
2995 | - echo "Bad QML import path: $QML2_IMPORT_PATH" |
2996 | - exit 1 |
2997 | -fi |
2998 | - |
2999 | -exit 0 |
3000 | |
3001 | === removed file 'tests/exec-test-noarch.sh' |
3002 | --- tests/exec-test-noarch.sh 2014-04-30 21:43:28 +0000 |
3003 | +++ tests/exec-test-noarch.sh 1970-01-01 00:00:00 +0000 |
3004 | @@ -1,18 +0,0 @@ |
3005 | -#!/bin/bash -e |
3006 | - |
3007 | -if [ "$PATH" != "$APP_DIR:/path" ] ; then |
3008 | - echo "Bad PATH: $PATH" |
3009 | - exit 1 |
3010 | -fi |
3011 | - |
3012 | -if [ "$LD_LIBRARY_PATH" != "$APP_DIR/lib:/lib" ] ; then |
3013 | - echo "Bad LD_LIBRARY_PATH: $LD_LIBRARY_PATH" |
3014 | - exit 1 |
3015 | -fi |
3016 | - |
3017 | -if [ "$QML2_IMPORT_PATH" != "/bar/qml/import" ] ; then |
3018 | - echo "Bad QML import path: $QML2_IMPORT_PATH" |
3019 | - exit 1 |
3020 | -fi |
3021 | - |
3022 | -exit 0 |
3023 | |
3024 | === removed file 'tests/exec-test-noinit.sh' |
3025 | --- tests/exec-test-noinit.sh 2014-04-30 21:43:28 +0000 |
3026 | +++ tests/exec-test-noinit.sh 1970-01-01 00:00:00 +0000 |
3027 | @@ -1,18 +0,0 @@ |
3028 | -#!/bin/bash -e |
3029 | - |
3030 | -if [ "$PATH" != "$APP_DIR/lib/64bit-amazing/bin:$APP_DIR" ] ; then |
3031 | - echo "Bad PATH: $PATH" |
3032 | - exit 1 |
3033 | -fi |
3034 | - |
3035 | -if [ "$LD_LIBRARY_PATH" != "$APP_DIR/lib/64bit-amazing:$APP_DIR/lib" ] ; then |
3036 | - echo "Bad LD_LIBRARY_PATH: $LD_LIBRARY_PATH" |
3037 | - exit 1 |
3038 | -fi |
3039 | - |
3040 | -if [ "$QML2_IMPORT_PATH" != "$APP_DIR/lib/64bit-amazing" ] ; then |
3041 | - echo "Bad QML import path: $QML2_IMPORT_PATH" |
3042 | - exit 1 |
3043 | -fi |
3044 | - |
3045 | -exit 0 |
3046 | |
3047 | === removed file 'tests/exec-test-nullstr.sh' |
3048 | --- tests/exec-test-nullstr.sh 2014-05-01 15:04:19 +0000 |
3049 | +++ tests/exec-test-nullstr.sh 1970-01-01 00:00:00 +0000 |
3050 | @@ -1,18 +0,0 @@ |
3051 | -#!/bin/bash -e |
3052 | - |
3053 | -if [ "$PATH" != "$APP_DIR/lib/64bit-amazing/bin:$APP_DIR" ] ; then |
3054 | - echo "Bad PATH: $PATH" |
3055 | - exit 1 |
3056 | -fi |
3057 | - |
3058 | -if [ "$LD_LIBRARY_PATH" != "$APP_DIR/lib/64bit-amazing:$APP_DIR/lib" ] ; then |
3059 | - echo "Bad LD_LIBRARY_PATH: $LD_LIBRARY_PATH" |
3060 | - exit 1 |
3061 | -fi |
3062 | - |
3063 | -if [ "$QML2_IMPORT_PATH" != "$APP_DIR/lib/64bit-amazing" ] ; then |
3064 | - echo "Bad QML import path: $QML2_IMPORT_PATH" |
3065 | - exit 1 |
3066 | -fi |
3067 | - |
3068 | -exit 0 |
3069 | |
3070 | === removed file 'tests/exec-test.sh.in' |
3071 | --- tests/exec-test.sh.in 2014-06-05 03:21:12 +0000 |
3072 | +++ tests/exec-test.sh.in 1970-01-01 00:00:00 +0000 |
3073 | @@ -1,62 +0,0 @@ |
3074 | -#!/bin/bash -e |
3075 | - |
3076 | -export PATH=/path |
3077 | -export LD_LIBRARY_PATH=/lib |
3078 | -export APP_EXEC=@CMAKE_CURRENT_SOURCE_DIR@/exec-test-full.sh |
3079 | -export APP_DIR=@CMAKE_CURRENT_BINARY_DIR@ |
3080 | -export QML2_IMPORT_PATH=/bar/qml/import |
3081 | -export UBUNTU_APP_LAUNCH_ARCH=64bit-amazing |
3082 | - |
3083 | -echo "Testing Full Test" |
3084 | -@CMAKE_BINARY_DIR@/exec-line-exec |
3085 | - |
3086 | -export PATH=/path |
3087 | -export LD_LIBRARY_PATH=/lib |
3088 | -export APP_EXEC=@CMAKE_CURRENT_SOURCE_DIR@/exec-test-noarch.sh |
3089 | -export APP_DIR=@CMAKE_CURRENT_BINARY_DIR@ |
3090 | -export QML2_IMPORT_PATH=/bar/qml/import |
3091 | -unset UBUNTU_APP_LAUNCH_ARCH |
3092 | - |
3093 | -echo "Testing Noarch Test" |
3094 | -@CMAKE_BINARY_DIR@/exec-line-exec |
3095 | - |
3096 | -unset PATH |
3097 | -unset LD_LIBRARY_PATH |
3098 | -export APP_EXEC=@CMAKE_CURRENT_SOURCE_DIR@/exec-test-noinit.sh |
3099 | -export APP_DIR=@CMAKE_CURRENT_BINARY_DIR@ |
3100 | -unset QML2_IMPORT_PATH |
3101 | -export UBUNTU_APP_LAUNCH_ARCH=64bit-amazing |
3102 | - |
3103 | -echo "Testing Uninitialized Test" |
3104 | -@CMAKE_BINARY_DIR@/exec-line-exec |
3105 | - |
3106 | -export PATH=/path |
3107 | -export LD_LIBRARY_PATH=/lib |
3108 | -export APP_EXEC=@CMAKE_CURRENT_SOURCE_DIR@/exec-test-colon.sh |
3109 | -export APP_DIR=@CMAKE_CURRENT_BINARY_DIR@/foo:bar |
3110 | -export QML2_IMPORT_PATH=/bar/qml/import |
3111 | -export UBUNTU_APP_LAUNCH_ARCH=64bit-amazing |
3112 | - |
3113 | -echo "Testing Colon Test" |
3114 | -@CMAKE_BINARY_DIR@/exec-line-exec |
3115 | - |
3116 | -export PATH=/path |
3117 | -export LD_LIBRARY_PATH=/lib |
3118 | -export APP_EXEC=@CMAKE_CURRENT_SOURCE_DIR@/exec-test-archcolon.sh |
3119 | -export APP_DIR=@CMAKE_CURRENT_BINARY_DIR@ |
3120 | -export QML2_IMPORT_PATH=/bar/qml/import |
3121 | -export UBUNTU_APP_LAUNCH_ARCH=64bit-amazing:amazinger |
3122 | - |
3123 | -echo "Testing Arch Colon Test" |
3124 | -@CMAKE_BINARY_DIR@/exec-line-exec |
3125 | - |
3126 | -export PATH="" |
3127 | -export LD_LIBRARY_PATH="" |
3128 | -export APP_EXEC=@CMAKE_CURRENT_SOURCE_DIR@/exec-test-nullstr.sh |
3129 | -export APP_DIR=@CMAKE_CURRENT_BINARY_DIR@ |
3130 | -export QML2_IMPORT_PATH="" |
3131 | -export UBUNTU_APP_LAUNCH_ARCH=64bit-amazing |
3132 | - |
3133 | -echo "Testing Null string Test" |
3134 | -@CMAKE_BINARY_DIR@/exec-line-exec |
3135 | - |
3136 | |
3137 | === removed file 'tests/exec-util-test.cc' |
3138 | --- tests/exec-util-test.cc 2017-03-06 19:38:17 +0000 |
3139 | +++ tests/exec-util-test.cc 1970-01-01 00:00:00 +0000 |
3140 | @@ -1,349 +0,0 @@ |
3141 | -/* |
3142 | - * Copyright 2013 Canonical Ltd. |
3143 | - * |
3144 | - * This program is free software: you can redistribute it and/or modify it |
3145 | - * under the terms of the GNU General Public License version 3, as published |
3146 | - * by the Free Software Foundation. |
3147 | - * |
3148 | - * This program is distributed in the hope that it will be useful, but |
3149 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
3150 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3151 | - * PURPOSE. See the GNU General Public License for more details. |
3152 | - * |
3153 | - * You should have received a copy of the GNU General Public License along |
3154 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
3155 | - * |
3156 | - * Authors: |
3157 | - * Ted Gould <ted.gould@canonical.com> |
3158 | - */ |
3159 | - |
3160 | -#include <map> |
3161 | -#include <functional> |
3162 | - |
3163 | -#include <gtest/gtest.h> |
3164 | -#include <libdbustest/dbus-test.h> |
3165 | -#include <gio/gio.h> |
3166 | -#include <libubuntu-app-launch/ubuntu-app-launch.h> |
3167 | -#include <libubuntu-app-launch/registry.h> |
3168 | - |
3169 | -#include "eventually-fixture.h" |
3170 | -#include "libertine-service.h" |
3171 | - |
3172 | -class ExecUtil : public EventuallyFixture |
3173 | -{ |
3174 | - protected: |
3175 | - DbusTestService * service = NULL; |
3176 | - DbusTestDbusMock * mock = NULL; |
3177 | - std::shared_ptr<LibertineService> libertine; |
3178 | - GDBusConnection * bus = NULL; |
3179 | - std::string laststarted; |
3180 | - |
3181 | - protected: |
3182 | - static void starting_cb (const gchar * appid, gpointer user_data) { |
3183 | - g_debug("I'm too sexy to callback"); |
3184 | - auto pthis = static_cast<ExecUtil*>(user_data); |
3185 | - pthis->laststarted = appid; |
3186 | - } |
3187 | - |
3188 | - virtual void SetUp() { |
3189 | - g_setenv("UPSTART_JOB", "made-up-job", TRUE); |
3190 | - g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); |
3191 | - g_setenv("XDG_CACHE_HOME", CMAKE_SOURCE_DIR "/libertine-data", TRUE); |
3192 | - g_setenv("XDG_DATA_HOME", CMAKE_SOURCE_DIR "/libertine-home", TRUE); |
3193 | - g_setenv("UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH", "libertine-launch", TRUE); |
3194 | - g_setenv("UBUNTU_APP_LAUNCH_SNAPD_SOCKET", "/this/should/not/exist", TRUE); |
3195 | - g_setenv("UBUNTU_APP_LAUNCH_SYSTEMD_PATH", "/this/should/not/exist", TRUE); |
3196 | - |
3197 | - service = dbus_test_service_new(NULL); |
3198 | - |
3199 | - mock = dbus_test_dbus_mock_new("com.ubuntu.Upstart"); |
3200 | - |
3201 | - DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
3202 | - |
3203 | - dbus_test_dbus_mock_object_add_method(mock, obj, |
3204 | - "GetJobByName", |
3205 | - G_VARIANT_TYPE("s"), |
3206 | - G_VARIANT_TYPE("o"), |
3207 | - "ret = dbus.ObjectPath('/com/test/job')", |
3208 | - NULL); |
3209 | - |
3210 | - DbusTestDbusMockObject * jobobj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL); |
3211 | - |
3212 | - dbus_test_dbus_mock_object_add_method(mock, jobobj, |
3213 | - "Start", |
3214 | - G_VARIANT_TYPE("(asb)"), |
3215 | - NULL, |
3216 | - "", |
3217 | - NULL); |
3218 | - |
3219 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); |
3220 | - |
3221 | - libertine = std::make_shared<LibertineService>(); |
3222 | - dbus_test_service_add_task(service, *libertine); |
3223 | - dbus_test_service_add_task(service, libertine->waitTask()); |
3224 | - |
3225 | - dbus_test_service_start_tasks(service); |
3226 | - |
3227 | - bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
3228 | - g_dbus_connection_set_exit_on_close(bus, FALSE); |
3229 | - g_object_add_weak_pointer(G_OBJECT(bus), (gpointer *)&bus); |
3230 | - |
3231 | - /* Make the handshake clear faster */ |
3232 | - ubuntu_app_launch_observer_add_app_starting(starting_cb, this); |
3233 | - } |
3234 | - |
3235 | - virtual void TearDown() { |
3236 | - ubuntu_app_launch_observer_delete_app_starting(starting_cb, this); |
3237 | - ubuntu::app_launch::Registry::clearDefault(); |
3238 | - |
3239 | - libertine.reset(); |
3240 | - g_clear_object(&mock); |
3241 | - g_clear_object(&service); |
3242 | - |
3243 | - g_object_unref(bus); |
3244 | - |
3245 | - ASSERT_EVENTUALLY_EQ(nullptr, bus); |
3246 | - } |
3247 | - |
3248 | - inline void StartCheckEnv (const std::string& appid, std::map<std::string, std::function<void(const gchar *)>> enums) { |
3249 | - std::map<std::string, bool> env_found; |
3250 | - DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", nullptr); |
3251 | - |
3252 | - g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE); |
3253 | - g_setenv("TEST_CLICK_USER", "test-user", TRUE); |
3254 | - g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", CMAKE_SOURCE_DIR "/link-farm", TRUE); |
3255 | - |
3256 | - laststarted.clear(); |
3257 | - ASSERT_TRUE(ubuntu_app_launch_start_application(appid.c_str(), nullptr)); |
3258 | - ASSERT_EVENTUALLY_EQ(appid, laststarted); |
3259 | - |
3260 | - guint len = 0; |
3261 | - const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, nullptr); |
3262 | - |
3263 | - ASSERT_EQ(1u, len); |
3264 | - ASSERT_NE(nullptr, calls); |
3265 | - ASSERT_STREQ("Start", calls[0].name); |
3266 | - |
3267 | - GVariant * envarray = g_variant_get_child_value(calls[0].params, 0); |
3268 | - GVariantIter iter; |
3269 | - g_variant_iter_init(&iter, envarray); |
3270 | - gchar * envvar = NULL; |
3271 | - |
3272 | - while (g_variant_iter_loop(&iter, "s", &envvar)) { |
3273 | - g_debug("Looking at variable: %s", envvar); |
3274 | - gchar * var = g_strdup(envvar); |
3275 | - |
3276 | - gchar * equal = g_strstr_len(var, -1, "="); |
3277 | - ASSERT_NE(equal, nullptr); |
3278 | - |
3279 | - equal[0] = '\0'; |
3280 | - gchar * value = &(equal[1]); |
3281 | - |
3282 | - /* Test the variable */ |
3283 | - auto varfunc = enums[var]; |
3284 | - EXPECT_NE(nullptr, varfunc); |
3285 | - if (varfunc) { |
3286 | - varfunc(value); |
3287 | - } else { |
3288 | - g_warning("Unable to find function for '%s'", var); |
3289 | - } |
3290 | - |
3291 | - /* Mark it as found */ |
3292 | - env_found[var] = true; |
3293 | - |
3294 | - g_free(var); |
3295 | - } |
3296 | - |
3297 | - g_variant_unref(envarray); |
3298 | - |
3299 | - for(auto enumval : enums) { |
3300 | - EXPECT_TRUE(env_found[enumval.first]); |
3301 | - if (!env_found[enumval.first]) { |
3302 | - g_warning("Unable to find enum %s", enumval.first.c_str()); |
3303 | - } |
3304 | - } |
3305 | - } |
3306 | -}; |
3307 | - |
3308 | -static void |
3309 | -nocheck (const gchar *) |
3310 | -{ |
3311 | -} |
3312 | - |
3313 | -TEST_F(ExecUtil, ClickExec) |
3314 | -{ |
3315 | -#define APP_DIR CMAKE_SOURCE_DIR "/click-root-dir/.click/users/test-user/com.test.good" |
3316 | - |
3317 | - StartCheckEnv("com.test.good_application_1.2.3", { |
3318 | - {"UBUNTU_APPLICATION_ISOLATION", [](const gchar * value) { |
3319 | - EXPECT_STREQ("1", value); }}, |
3320 | - {"XDG_CACHE_HOME", nocheck}, |
3321 | - {"XDG_CONFIG_HOME", nocheck}, |
3322 | - {"XDG_DATA_HOME", nocheck}, |
3323 | - {"XDG_RUNTIME_DIR", nocheck}, |
3324 | - {"XDG_DATA_DIRS", [](const gchar * value) { |
3325 | - EXPECT_TRUE(g_str_has_prefix(value, APP_DIR ":")); }}, |
3326 | - {"TMPDIR", [](const gchar * value) { |
3327 | - EXPECT_TRUE(g_str_has_suffix(value, "com.test.good")); }}, |
3328 | - {"__GL_SHADER_DISK_CACHE_PATH", [](const gchar * value) { |
3329 | - EXPECT_TRUE(g_str_has_suffix(value, "com.test.good")); }}, |
3330 | - {"APP_DIR", [](const gchar * value) { |
3331 | - EXPECT_STREQ(APP_DIR, value); }}, |
3332 | - {"APP_EXEC", [](const gchar * value) { |
3333 | - EXPECT_STREQ("grep", value); }}, |
3334 | - {"APP_ID", [](const gchar * value) { |
3335 | - EXPECT_STREQ("com.test.good_application_1.2.3", value); }}, |
3336 | - {"APP_EXEC_POLICY", [](const gchar * value) { |
3337 | - EXPECT_STREQ("com.test.good_application_1.2.3", value); }}, |
3338 | - {"APP_LAUNCHER_PID", [](const gchar * value) { |
3339 | - EXPECT_EQ(getpid(), atoi(value)); }}, |
3340 | - {"APP_DESKTOP_FILE_PATH", [](const gchar * value) { |
3341 | - EXPECT_STREQ(APP_DIR "/application.desktop", value); }}, |
3342 | - {"APP_XMIR_ENABLE", [](const gchar * value) { |
3343 | - EXPECT_STREQ("0", value); }}, |
3344 | - {"QML2_IMPORT_PATH", nocheck}, |
3345 | - }); |
3346 | - |
3347 | -#undef APP_DIR |
3348 | -} |
3349 | - |
3350 | -TEST_F(ExecUtil, DesktopExec) |
3351 | -{ |
3352 | - StartCheckEnv("foo", { |
3353 | - {"APP_EXEC", [](const gchar * value) { |
3354 | - EXPECT_STREQ("libertine-launch foo", value); }}, |
3355 | - {"APP_DESKTOP_FILE_PATH", [](const gchar * value) { |
3356 | - EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/foo.desktop", value); }}, |
3357 | - {"APP_EXEC_POLICY", [](const gchar * value) { |
3358 | - EXPECT_STREQ("unconfined", value); }}, |
3359 | - {"APP_ID", [](const gchar * value) { |
3360 | - EXPECT_STREQ("foo", value); }}, |
3361 | - {"INSTANCE_ID", nocheck}, |
3362 | - {"APP_LAUNCHER_PID", [](const gchar * value) { |
3363 | - EXPECT_EQ(getpid(), atoi(value)); }}, |
3364 | - {"APP_XMIR_ENABLE", [](const gchar * value) { |
3365 | - EXPECT_STREQ("1", value); }}, |
3366 | - }); |
3367 | -} |
3368 | - |
3369 | -TEST_F(ExecUtil, DesktopMir) |
3370 | -{ |
3371 | - StartCheckEnv("xmir", { |
3372 | - {"APP_EXEC", [](const gchar * value) { |
3373 | - EXPECT_STREQ("libertine-launch xfoo", value); }}, |
3374 | - {"APP_DESKTOP_FILE_PATH", [](const gchar * value) { |
3375 | - EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/xmir.desktop", value); }}, |
3376 | - {"APP_EXEC_POLICY", [](const gchar * value) { |
3377 | - EXPECT_STREQ("unconfined", value); }}, |
3378 | - {"APP_ID", [](const gchar * value) { |
3379 | - EXPECT_STREQ("xmir", value); }}, |
3380 | - {"INSTANCE_ID", nocheck}, |
3381 | - {"APP_LAUNCHER_PID", [](const gchar * value) { |
3382 | - EXPECT_EQ(getpid(), atoi(value)); }}, |
3383 | - {"APP_XMIR_ENABLE", [](const gchar * value) { |
3384 | - EXPECT_STREQ("1", value); }}, |
3385 | - }); |
3386 | -} |
3387 | - |
3388 | -TEST_F(ExecUtil, DesktopNoMir) |
3389 | -{ |
3390 | - StartCheckEnv("noxmir", { |
3391 | - {"APP_EXEC", [](const gchar * value) { |
3392 | - EXPECT_STREQ("noxmir", value); }}, |
3393 | - {"APP_DESKTOP_FILE_PATH", [](const gchar * value) { |
3394 | - EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/noxmir.desktop", value); }}, |
3395 | - {"APP_EXEC_POLICY", [](const gchar * value) { |
3396 | - EXPECT_STREQ("unconfined", value); }}, |
3397 | - {"APP_ID", [](const gchar * value) { |
3398 | - EXPECT_STREQ("noxmir", value); }}, |
3399 | - {"INSTANCE_ID", nocheck}, |
3400 | - {"APP_LAUNCHER_PID", [](const gchar * value) { |
3401 | - EXPECT_EQ(getpid(), atoi(value)); }}, |
3402 | - {"APP_XMIR_ENABLE", [](const gchar * value) { |
3403 | - EXPECT_STREQ("0", value); }}, |
3404 | - }); |
3405 | -} |
3406 | - |
3407 | -TEST_F(ExecUtil, ClickMir) |
3408 | -{ |
3409 | - StartCheckEnv("com.test.mir_mir_1", { |
3410 | - {"UBUNTU_APPLICATION_ISOLATION", nocheck}, |
3411 | - {"XDG_CACHE_HOME", nocheck}, |
3412 | - {"XDG_CONFIG_HOME", nocheck}, |
3413 | - {"XDG_DATA_HOME", nocheck}, |
3414 | - {"XDG_RUNTIME_DIR", nocheck}, |
3415 | - {"XDG_DATA_DIRS", nocheck}, |
3416 | - {"TMPDIR", nocheck}, |
3417 | - {"__GL_SHADER_DISK_CACHE_PATH", nocheck}, |
3418 | - {"APP_DIR", nocheck}, |
3419 | - {"APP_EXEC", nocheck}, |
3420 | - {"APP_ID", [](const gchar * value) { |
3421 | - EXPECT_STREQ("com.test.mir_mir_1", value); }}, |
3422 | - {"APP_EXEC_POLICY", [](const gchar * value) { |
3423 | - EXPECT_STREQ("com.test.mir_mir_1", value); }}, |
3424 | - {"APP_LAUNCHER_PID", nocheck}, |
3425 | - {"APP_DESKTOP_FILE_PATH", nocheck}, |
3426 | - {"APP_XMIR_ENABLE", [](const gchar * value) { |
3427 | - EXPECT_STREQ("1", value); }}, |
3428 | - {"QML2_IMPORT_PATH", nocheck}, |
3429 | - }); |
3430 | -} |
3431 | - |
3432 | -TEST_F(ExecUtil, ClickNoMir) |
3433 | -{ |
3434 | - StartCheckEnv("com.test.mir_nomir_1", { |
3435 | - {"UBUNTU_APPLICATION_ISOLATION", nocheck}, |
3436 | - {"XDG_CACHE_HOME", nocheck}, |
3437 | - {"XDG_CONFIG_HOME", nocheck}, |
3438 | - {"XDG_DATA_HOME", nocheck}, |
3439 | - {"XDG_RUNTIME_DIR", nocheck}, |
3440 | - {"XDG_DATA_DIRS", nocheck}, |
3441 | - {"TMPDIR", nocheck}, |
3442 | - {"__GL_SHADER_DISK_CACHE_PATH", nocheck}, |
3443 | - {"APP_DIR", nocheck}, |
3444 | - {"APP_EXEC", nocheck}, |
3445 | - {"APP_ID", [](const gchar * value) { |
3446 | - EXPECT_STREQ("com.test.mir_nomir_1", value); }}, |
3447 | - {"APP_EXEC_POLICY", [](const gchar * value) { |
3448 | - EXPECT_STREQ("com.test.mir_nomir_1", value); }}, |
3449 | - {"APP_LAUNCHER_PID", nocheck}, |
3450 | - {"APP_DESKTOP_FILE_PATH", nocheck}, |
3451 | - {"APP_XMIR_ENABLE", [](const gchar * value) { |
3452 | - EXPECT_STREQ("0", value); }}, |
3453 | - {"QML2_IMPORT_PATH", nocheck}, |
3454 | - }); |
3455 | -} |
3456 | - |
3457 | -TEST_F(ExecUtil, LibertineExec) |
3458 | -{ |
3459 | - StartCheckEnv("container-name_test_0.0", { |
3460 | - {"APP_EXEC", [](const gchar * value) { |
3461 | - EXPECT_STREQ("libertine-launch \"--id=container-name\" test", value); }}, |
3462 | - {"APP_EXEC_POLICY", [](const gchar * value) { |
3463 | - EXPECT_STREQ("unconfined", value); }}, |
3464 | - {"APP_ID", [](const gchar * value) { |
3465 | - EXPECT_STREQ("container-name_test_0.0", value); }}, |
3466 | - {"APP_LAUNCHER_PID", [](const gchar * value) { |
3467 | - EXPECT_EQ(getpid(), atoi(value)); }}, |
3468 | - {"INSTANCE_ID", nocheck}, |
3469 | - {"APP_XMIR_ENABLE", [](const gchar * value) { |
3470 | - EXPECT_STREQ("1", value); }}, |
3471 | - }); |
3472 | -} |
3473 | - |
3474 | -TEST_F(ExecUtil, LibertineExecUser) |
3475 | -{ |
3476 | - StartCheckEnv("container-name_user-app_0.0", { |
3477 | - {"APP_EXEC", [](const gchar * value) { |
3478 | - EXPECT_STREQ("libertine-launch \"--id=container-name\" user-app", value); }}, |
3479 | - {"APP_EXEC_POLICY", [](const gchar * value) { |
3480 | - EXPECT_STREQ("unconfined", value); }}, |
3481 | - {"APP_ID", [](const gchar * value) { |
3482 | - EXPECT_STREQ("container-name_user-app_0.0", value); }}, |
3483 | - {"APP_LAUNCHER_PID", [](const gchar * value) { |
3484 | - EXPECT_EQ(getpid(), atoi(value)); }}, |
3485 | - {"INSTANCE_ID", nocheck}, |
3486 | - {"APP_XMIR_ENABLE", [](const gchar * value) { |
3487 | - EXPECT_STREQ("1", value); }}, |
3488 | - }); |
3489 | -} |
3490 | |
3491 | === removed file 'tests/failure-test.cc' |
3492 | --- tests/failure-test.cc 2017-01-11 23:48:12 +0000 |
3493 | +++ tests/failure-test.cc 1970-01-01 00:00:00 +0000 |
3494 | @@ -1,165 +0,0 @@ |
3495 | -/* |
3496 | - * Copyright 2013 Canonical Ltd. |
3497 | - * |
3498 | - * This program is free software: you can redistribute it and/or modify it |
3499 | - * under the terms of the GNU General Public License version 3, as published |
3500 | - * by the Free Software Foundation. |
3501 | - * |
3502 | - * This program is distributed in the hope that it will be useful, but |
3503 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
3504 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3505 | - * PURPOSE. See the GNU General Public License for more details. |
3506 | - * |
3507 | - * You should have received a copy of the GNU General Public License along |
3508 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
3509 | - * |
3510 | - * Authors: |
3511 | - * Ted Gould <ted.gould@canonical.com> |
3512 | - */ |
3513 | - |
3514 | -#include "eventually-fixture.h" |
3515 | -#include "registry.h" |
3516 | -#include <gio/gio.h> |
3517 | -#include <glib/gstdio.h> |
3518 | -#include <gtest/gtest.h> |
3519 | - |
3520 | -class FailureTest : public EventuallyFixture |
3521 | -{ |
3522 | -private: |
3523 | - GTestDBus* testbus = NULL; |
3524 | - |
3525 | -protected: |
3526 | - std::shared_ptr<ubuntu::app_launch::Registry> registry; |
3527 | - |
3528 | - virtual void SetUp() override |
3529 | - { |
3530 | - /* Click DB test mode */ |
3531 | - g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE); |
3532 | - g_setenv("TEST_CLICK_USER", "test-user", TRUE); |
3533 | - |
3534 | - gchar* linkfarmpath = g_build_filename(CMAKE_SOURCE_DIR, "link-farm", NULL); |
3535 | - g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", linkfarmpath, TRUE); |
3536 | - g_free(linkfarmpath); |
3537 | - |
3538 | - g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); |
3539 | - g_setenv("XDG_CACHE_HOME", CMAKE_SOURCE_DIR "/libertine-data", TRUE); |
3540 | - g_setenv("XDG_DATA_HOME", CMAKE_SOURCE_DIR "/libertine-home", TRUE); |
3541 | - |
3542 | - g_setenv("UBUNTU_APP_LAUNCH_SYSTEMD_PATH", "/this/should/not/exist", TRUE); |
3543 | - |
3544 | - testbus = g_test_dbus_new(G_TEST_DBUS_NONE); |
3545 | - g_test_dbus_up(testbus); |
3546 | - |
3547 | - registry = std::make_shared<ubuntu::app_launch::Registry>(); |
3548 | - } |
3549 | - |
3550 | - virtual void TearDown() override |
3551 | - { |
3552 | - registry.reset(); |
3553 | - |
3554 | - g_test_dbus_down(testbus); |
3555 | - g_clear_object(&testbus); |
3556 | - } |
3557 | -}; |
3558 | - |
3559 | -TEST_F(FailureTest, CrashTest) |
3560 | -{ |
3561 | - g_setenv("EXIT_STATUS", "-100", TRUE); |
3562 | - g_setenv("JOB", "application-click", TRUE); |
3563 | - g_setenv("INSTANCE", "foo", TRUE); |
3564 | - |
3565 | - std::string last_observer; |
3566 | - ubuntu::app_launch::Registry::appFailed(registry).connect( |
3567 | - [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, |
3568 | - std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
3569 | - ubuntu::app_launch::Registry::FailureType type) { |
3570 | - if (type == ubuntu::app_launch::Registry::FailureType::CRASH) |
3571 | - { |
3572 | - last_observer = app->appId(); |
3573 | - } |
3574 | - }); |
3575 | - |
3576 | - /* Status based */ |
3577 | - ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
3578 | - |
3579 | - EXPECT_EVENTUALLY_EQ("foo", last_observer); |
3580 | - |
3581 | - last_observer.clear(); |
3582 | - g_unsetenv("EXIT_STATUS"); |
3583 | - g_setenv("EXIT_SIGNAL", "KILL", TRUE); |
3584 | - |
3585 | - /* Signal based */ |
3586 | - ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
3587 | - |
3588 | - EXPECT_EVENTUALLY_EQ("foo", last_observer); |
3589 | -} |
3590 | - |
3591 | -TEST_F(FailureTest, LegacyTest) |
3592 | -{ |
3593 | - g_setenv("EXIT_STATUS", "-100", TRUE); |
3594 | - g_setenv("JOB", "application-legacy", TRUE); |
3595 | - g_setenv("INSTANCE", "foo-1234", TRUE); |
3596 | - |
3597 | - std::string last_observer; |
3598 | - ubuntu::app_launch::Registry::appFailed(registry).connect( |
3599 | - [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, |
3600 | - std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
3601 | - ubuntu::app_launch::Registry::FailureType type) { |
3602 | - g_debug("Signal handler called"); |
3603 | - if (type == ubuntu::app_launch::Registry::FailureType::CRASH) |
3604 | - { |
3605 | - last_observer = app->appId(); |
3606 | - } |
3607 | - }); |
3608 | - |
3609 | - /* Status based */ |
3610 | - ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
3611 | - |
3612 | - EXPECT_EVENTUALLY_EQ("foo", last_observer); |
3613 | -} |
3614 | - |
3615 | -TEST_F(FailureTest, SnapTest) |
3616 | -{ |
3617 | - g_setenv("EXIT_STATUS", "-100", TRUE); |
3618 | - g_setenv("JOB", "application-snap", TRUE); |
3619 | - g_setenv("INSTANCE", "com.test.good_application_1.2.3-1234", TRUE); |
3620 | - |
3621 | - std::string last_observer; |
3622 | - ubuntu::app_launch::Registry::appFailed(registry).connect( |
3623 | - [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, |
3624 | - std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
3625 | - ubuntu::app_launch::Registry::FailureType type) { |
3626 | - if (type == ubuntu::app_launch::Registry::FailureType::CRASH) |
3627 | - { |
3628 | - last_observer = app->appId(); |
3629 | - } |
3630 | - }); |
3631 | - |
3632 | - /* Status based */ |
3633 | - ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
3634 | - |
3635 | - EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", last_observer); |
3636 | -} |
3637 | - |
3638 | -TEST_F(FailureTest, StartTest) |
3639 | -{ |
3640 | - g_setenv("JOB", "application-click", TRUE); |
3641 | - g_setenv("INSTANCE", "foo", TRUE); |
3642 | - g_unsetenv("EXIT_STATUS"); |
3643 | - g_unsetenv("EXIT_SIGNAL"); |
3644 | - |
3645 | - std::string last_observer; |
3646 | - ubuntu::app_launch::Registry::appFailed(registry).connect( |
3647 | - [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, |
3648 | - std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
3649 | - ubuntu::app_launch::Registry::FailureType type) { |
3650 | - if (type == ubuntu::app_launch::Registry::FailureType::START_FAILURE) |
3651 | - { |
3652 | - last_observer = app->appId(); |
3653 | - } |
3654 | - }); |
3655 | - |
3656 | - ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
3657 | - |
3658 | - EXPECT_EVENTUALLY_EQ("foo", last_observer); |
3659 | -} |
3660 | |
3661 | === modified file 'tests/helper-test.cc' |
3662 | --- tests/helper-test.cc 2017-01-11 23:22:52 +0000 |
3663 | +++ tests/helper-test.cc 2017-03-21 03:20:55 +0000 |
3664 | @@ -264,111 +264,6 @@ |
3665 | return; |
3666 | } |
3667 | |
3668 | -TEST_F(HelperTest, SetConfinedEnvvars) |
3669 | -{ |
3670 | - g_unsetenv("XDG_DATA_DIRS"); |
3671 | - |
3672 | - DbusTestService * service = dbus_test_service_new(NULL); |
3673 | - DbusTestDbusMock * mock = dbus_test_dbus_mock_new("com.ubuntu.Upstart"); |
3674 | - |
3675 | - DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
3676 | - |
3677 | - dbus_test_dbus_mock_object_add_method(mock, obj, |
3678 | - "SetEnvList", |
3679 | - G_VARIANT_TYPE("(asasb)"), |
3680 | - NULL, |
3681 | - "", |
3682 | - NULL); |
3683 | - |
3684 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); |
3685 | - dbus_test_service_start_tasks(service); |
3686 | - |
3687 | - GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
3688 | - g_dbus_connection_set_exit_on_close(bus, FALSE); |
3689 | - g_object_add_weak_pointer(G_OBJECT(bus), (gpointer *)&bus); |
3690 | - |
3691 | - /* Not a test other than "don't crash" */ |
3692 | - EnvHandle * handle = env_handle_start(); |
3693 | - set_confined_envvars(handle, "foo-app-pkg", "/foo/bar"); |
3694 | - env_handle_finish(handle); |
3695 | - |
3696 | - guint len = 0; |
3697 | - const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "SetEnvList", &len, NULL); |
3698 | - |
3699 | - ASSERT_EQ(guint(1), len); |
3700 | - ASSERT_NE(calls, nullptr); |
3701 | - ASSERT_STREQ("SetEnvList", calls[0].name); |
3702 | - |
3703 | - bool got_app_isolation = false; |
3704 | - bool got_cache_home = false; |
3705 | - bool got_config_home = false; |
3706 | - bool got_data_home = false; |
3707 | - bool got_runtime_dir = false; |
3708 | - bool got_data_dirs = false; |
3709 | - bool got_temp_dir = false; |
3710 | - bool got_shader_dir = false; |
3711 | - |
3712 | - GVariant * envarray = g_variant_get_child_value(calls[0].params, 1); |
3713 | - GVariantIter iter; |
3714 | - g_variant_iter_init(&iter, envarray); |
3715 | - gchar * envvar = NULL; |
3716 | - |
3717 | - while (g_variant_iter_loop(&iter, "s", &envvar)) { |
3718 | - gchar * var = g_strdup(envvar); |
3719 | - |
3720 | - gchar * equal = g_strstr_len(var, -1, "="); |
3721 | - ASSERT_NE(equal, nullptr); |
3722 | - |
3723 | - equal[0] = '\0'; |
3724 | - gchar * value = &(equal[1]); |
3725 | - |
3726 | - if (g_strcmp0(var, "UBUNTU_APPLICATION_ISOLATION") == 0) { |
3727 | - ASSERT_STREQ(value, "1"); |
3728 | - got_app_isolation = true; |
3729 | - } else if (g_strcmp0(var, "XDG_CACHE_HOME") == 0) { |
3730 | - got_cache_home = true; |
3731 | - } else if (g_strcmp0(var, "XDG_CONFIG_HOME") == 0) { |
3732 | - got_config_home = true; |
3733 | - } else if (g_strcmp0(var, "XDG_DATA_HOME") == 0) { |
3734 | - got_data_home = true; |
3735 | - } else if (g_strcmp0(var, "XDG_RUNTIME_DIR") == 0) { |
3736 | - got_runtime_dir = true; |
3737 | - } else if (g_strcmp0(var, "XDG_DATA_DIRS") == 0) { |
3738 | - ASSERT_TRUE(g_str_has_prefix(value, "/foo/bar:")); |
3739 | - ASSERT_TRUE(g_strstr_len(value, -1, "/usr/share") != NULL); |
3740 | - got_data_dirs = true; |
3741 | - } else if (g_strcmp0(var, "TMPDIR") == 0) { |
3742 | - ASSERT_TRUE(g_str_has_suffix(value, "foo-app-pkg")); |
3743 | - got_temp_dir = true; |
3744 | - } else if (g_strcmp0(var, "__GL_SHADER_DISK_CACHE_PATH") == 0) { |
3745 | - ASSERT_TRUE(g_str_has_suffix(value, "foo-app-pkg")); |
3746 | - got_shader_dir = true; |
3747 | - } else { |
3748 | - g_warning("Unknown variable! %s", var); |
3749 | - ASSERT_TRUE(false); |
3750 | - } |
3751 | - |
3752 | - g_free(var); |
3753 | - } |
3754 | - |
3755 | - g_variant_unref(envarray); |
3756 | - |
3757 | - ASSERT_TRUE(got_app_isolation); |
3758 | - ASSERT_TRUE(got_cache_home); |
3759 | - ASSERT_TRUE(got_config_home); |
3760 | - ASSERT_TRUE(got_data_home); |
3761 | - ASSERT_TRUE(got_runtime_dir); |
3762 | - ASSERT_TRUE(got_data_dirs); |
3763 | - ASSERT_TRUE(got_temp_dir); |
3764 | - ASSERT_TRUE(got_shader_dir); |
3765 | - |
3766 | - g_object_unref(bus); |
3767 | - g_object_unref(mock); |
3768 | - g_object_unref(service); |
3769 | - |
3770 | - return; |
3771 | -} |
3772 | - |
3773 | TEST_F(HelperTest, DesktopToExec) |
3774 | { |
3775 | GKeyFile * keyfile = NULL; |
3776 | |
3777 | === modified file 'tests/libual-cpp-test.cc' |
3778 | --- tests/libual-cpp-test.cc 2017-03-09 16:05:36 +0000 |
3779 | +++ tests/libual-cpp-test.cc 2017-03-21 03:20:55 +0000 |
3780 | @@ -32,6 +32,7 @@ |
3781 | #include "application.h" |
3782 | #include "glib-thread.h" |
3783 | #include "helper.h" |
3784 | +#include "jobs-base.h" |
3785 | #include "registry.h" |
3786 | #include "ubuntu-app-launch.h" |
3787 | |
3788 | @@ -39,6 +40,8 @@ |
3789 | #include "libertine-service.h" |
3790 | #include "mir-mock.h" |
3791 | #include "spew-master.h" |
3792 | +#include "systemd-mock.h" |
3793 | +#include "zg-mock.h" |
3794 | |
3795 | #ifdef ENABLE_SNAPPY |
3796 | #include "snapd-mock.h" |
3797 | @@ -46,6 +49,8 @@ |
3798 | #define LOCAL_SNAPD_TEST_SOCKET (SNAPD_TEST_SOCKET "-libual-cpp-test") |
3799 | #endif |
3800 | |
3801 | +#define CGROUP_DIR (CMAKE_BINARY_DIR "/systemd-cgroups") |
3802 | + |
3803 | class LibUAL : public EventuallyFixture |
3804 | { |
3805 | protected: |
3806 | @@ -53,6 +58,7 @@ |
3807 | DbusTestDbusMock* mock = NULL; |
3808 | DbusTestDbusMock* cgmock = NULL; |
3809 | std::shared_ptr<LibertineService> libertine; |
3810 | + std::shared_ptr<SystemdMock> systemd; |
3811 | GDBusConnection* bus = NULL; |
3812 | guint resume_timeout = 0; |
3813 | std::shared_ptr<ubuntu::app_launch::Registry> registry; |
3814 | @@ -160,156 +166,25 @@ |
3815 | g_unlink(LOCAL_SNAPD_TEST_SOCKET); |
3816 | #endif |
3817 | g_setenv("UBUNTU_APP_LAUNCH_SYSTEMD_PATH", "/this/should/not/exist", TRUE); |
3818 | + /* Setting the cgroup temp directory */ |
3819 | + g_setenv("UBUNTU_APP_LAUNCH_SYSTEMD_CGROUP_ROOT", CGROUP_DIR, TRUE); |
3820 | |
3821 | service = dbus_test_service_new(NULL); |
3822 | |
3823 | debugConnection(); |
3824 | |
3825 | - mock = dbus_test_dbus_mock_new("com.ubuntu.Upstart"); |
3826 | - |
3827 | - DbusTestDbusMockObject* obj = |
3828 | - dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
3829 | - |
3830 | - dbus_test_dbus_mock_object_add_method(mock, obj, "EmitEvent", G_VARIANT_TYPE("(sasb)"), NULL, "", NULL); |
3831 | - |
3832 | - dbus_test_dbus_mock_object_add_method(mock, obj, "GetJobByName", G_VARIANT_TYPE("s"), G_VARIANT_TYPE("o"), |
3833 | - "if args[0] == 'application-click':\n" |
3834 | - " ret = dbus.ObjectPath('/com/test/application_click')\n" |
3835 | - "elif args[0] == 'application-snap':\n" |
3836 | - " ret = dbus.ObjectPath('/com/test/application_snap')\n" |
3837 | - "elif args[0] == 'application-legacy':\n" |
3838 | - " ret = dbus.ObjectPath('/com/test/application_legacy')\n" |
3839 | - "elif args[0] == 'untrusted-helper':\n" |
3840 | - " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n", |
3841 | - NULL); |
3842 | - |
3843 | - dbus_test_dbus_mock_object_add_method(mock, obj, "SetEnv", G_VARIANT_TYPE("(assb)"), NULL, "", NULL); |
3844 | - |
3845 | - /* Click App */ |
3846 | - DbusTestDbusMockObject* jobobj = |
3847 | - dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL); |
3848 | - |
3849 | - dbus_test_dbus_mock_object_add_method( |
3850 | - mock, jobobj, "Start", G_VARIANT_TYPE("(asb)"), NULL, |
3851 | - "if 'APP_ID=com.test.good_application_1.2.3' in args[0]:" |
3852 | - " raise dbus.exceptions.DBusException('Foo running', name='com.ubuntu.Upstart0_6.Error.AlreadyStarted')", |
3853 | - NULL); |
3854 | - |
3855 | - dbus_test_dbus_mock_object_add_method(mock, jobobj, "Stop", G_VARIANT_TYPE("(asb)"), NULL, "", NULL); |
3856 | - |
3857 | - dbus_test_dbus_mock_object_add_method(mock, jobobj, "GetAllInstances", NULL, G_VARIANT_TYPE("ao"), |
3858 | - "ret = [ dbus.ObjectPath('/com/test/app_instance') ]", NULL); |
3859 | - |
3860 | - dbus_test_dbus_mock_object_add_method(mock, jobobj, "GetInstanceByName", G_VARIANT_TYPE_STRING, |
3861 | - G_VARIANT_TYPE("o"), "ret = dbus.ObjectPath('/com/test/app_instance')", |
3862 | - NULL); |
3863 | - |
3864 | - DbusTestDbusMockObject* instobj = |
3865 | - dbus_test_dbus_mock_get_object(mock, "/com/test/app_instance", "com.ubuntu.Upstart0_6.Instance", NULL); |
3866 | - dbus_test_dbus_mock_object_add_property(mock, instobj, "name", G_VARIANT_TYPE_STRING, |
3867 | - g_variant_new_string("com.test.good_application_1.2.3"), NULL); |
3868 | - gchar* process_var = g_strdup_printf("[('main', %d)]", getpid()); |
3869 | - dbus_test_dbus_mock_object_add_property(mock, instobj, "processes", G_VARIANT_TYPE("a(si)"), |
3870 | - g_variant_new_parsed(process_var), NULL); |
3871 | - g_free(process_var); |
3872 | - |
3873 | -#ifdef ENABLE_SNAPPY |
3874 | - /* Snap App */ |
3875 | - auto snapjobobj = |
3876 | - dbus_test_dbus_mock_get_object(mock, "/com/test/application_snap", "com.ubuntu.Upstart0_6.Job", NULL); |
3877 | - |
3878 | - dbus_test_dbus_mock_object_add_method( |
3879 | - mock, snapjobobj, "Start", G_VARIANT_TYPE("(asb)"), NULL, |
3880 | - "if args[0][0] == 'APP_ID=unity8-package_foo_x123':" |
3881 | - " raise dbus.exceptions.DBusException('Foo running', name='com.ubuntu.Upstart0_6.Error.AlreadyStarted')", |
3882 | - NULL); |
3883 | - |
3884 | - dbus_test_dbus_mock_object_add_method(mock, snapjobobj, "Stop", G_VARIANT_TYPE("(asb)"), NULL, "", NULL); |
3885 | - |
3886 | - dbus_test_dbus_mock_object_add_method(mock, snapjobobj, "GetAllInstances", NULL, G_VARIANT_TYPE("ao"), |
3887 | - "ret = [ dbus.ObjectPath('/com/test/snapp_instance') ]", NULL); |
3888 | - |
3889 | - dbus_test_dbus_mock_object_add_method(mock, snapjobobj, "GetInstanceByName", G_VARIANT_TYPE_STRING, |
3890 | - G_VARIANT_TYPE("o"), "ret = dbus.ObjectPath('/com/test/snapp_instance')", |
3891 | - NULL); |
3892 | - |
3893 | - auto snapinstobj = |
3894 | - dbus_test_dbus_mock_get_object(mock, "/com/test/snapp_instance", "com.ubuntu.Upstart0_6.Instance", NULL); |
3895 | - dbus_test_dbus_mock_object_add_property(mock, snapinstobj, "name", G_VARIANT_TYPE_STRING, |
3896 | - g_variant_new_string("unity8-package_foo_x123-"), NULL); |
3897 | - gchar* snapprocess_var = g_strdup_printf("[('main', %d)]", getpid()); |
3898 | - dbus_test_dbus_mock_object_add_property(mock, snapinstobj, "processes", G_VARIANT_TYPE("a(si)"), |
3899 | - g_variant_new_parsed(snapprocess_var), NULL); |
3900 | - g_free(snapprocess_var); |
3901 | -#endif |
3902 | - |
3903 | - /* Legacy App */ |
3904 | - DbusTestDbusMockObject* ljobobj = |
3905 | - dbus_test_dbus_mock_get_object(mock, "/com/test/application_legacy", "com.ubuntu.Upstart0_6.Job", NULL); |
3906 | - |
3907 | - dbus_test_dbus_mock_object_add_method(mock, ljobobj, "Start", G_VARIANT_TYPE("(asb)"), NULL, "", NULL); |
3908 | - |
3909 | - dbus_test_dbus_mock_object_add_method(mock, ljobobj, "Stop", G_VARIANT_TYPE("(asb)"), NULL, "", NULL); |
3910 | - |
3911 | - dbus_test_dbus_mock_object_add_method(mock, ljobobj, "GetAllInstances", NULL, G_VARIANT_TYPE("ao"), |
3912 | - "ret = [ dbus.ObjectPath('/com/test/legacy_app_instance'), " |
3913 | - "dbus.ObjectPath('/com/test/legacy_app_instance2') ]", |
3914 | - NULL); |
3915 | - |
3916 | - dbus_test_dbus_mock_object_add_method(mock, ljobobj, "GetInstanceByName", G_VARIANT_TYPE_STRING, |
3917 | - G_VARIANT_TYPE("o"), |
3918 | - "ret = dbus.ObjectPath('/com/test/legacy_app_instance')", NULL); |
3919 | - |
3920 | - DbusTestDbusMockObject* linstobj = dbus_test_dbus_mock_get_object(mock, "/com/test/legacy_app_instance", |
3921 | - "com.ubuntu.Upstart0_6.Instance", NULL); |
3922 | - dbus_test_dbus_mock_object_add_property(mock, linstobj, "name", G_VARIANT_TYPE_STRING, |
3923 | - g_variant_new_string("multiple-2342345"), NULL); |
3924 | - dbus_test_dbus_mock_object_add_property(mock, linstobj, "processes", G_VARIANT_TYPE("a(si)"), |
3925 | - g_variant_new_parsed("[('main', 5678)]"), NULL); |
3926 | - |
3927 | - DbusTestDbusMockObject* linstobj2 = dbus_test_dbus_mock_get_object(mock, "/com/test/legacy_app_instance2", |
3928 | - "com.ubuntu.Upstart0_6.Instance", NULL); |
3929 | - dbus_test_dbus_mock_object_add_property(mock, linstobj2, "name", G_VARIANT_TYPE_STRING, |
3930 | - g_variant_new_string("single-"), NULL); |
3931 | - dbus_test_dbus_mock_object_add_property(mock, linstobj2, "processes", G_VARIANT_TYPE("a(si)"), |
3932 | - g_variant_new_parsed("[('main', 5678)]"), NULL); |
3933 | - |
3934 | - /* Untrusted Helper */ |
3935 | - DbusTestDbusMockObject* uhelperobj = |
3936 | - dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper", "com.ubuntu.Upstart0_6.Job", NULL); |
3937 | - |
3938 | - dbus_test_dbus_mock_object_add_method(mock, uhelperobj, "Start", G_VARIANT_TYPE("(asb)"), NULL, "", NULL); |
3939 | - |
3940 | - dbus_test_dbus_mock_object_add_method(mock, uhelperobj, "Stop", G_VARIANT_TYPE("(asb)"), NULL, "", NULL); |
3941 | - |
3942 | - dbus_test_dbus_mock_object_add_method(mock, uhelperobj, "GetAllInstances", NULL, G_VARIANT_TYPE("ao"), |
3943 | - "ret = [ dbus.ObjectPath('/com/test/untrusted/helper/instance'), " |
3944 | - "dbus.ObjectPath('/com/test/untrusted/helper/multi_instance') ]", |
3945 | - NULL); |
3946 | - |
3947 | - DbusTestDbusMockObject* uhelperinstance = dbus_test_dbus_mock_get_object( |
3948 | - mock, "/com/test/untrusted/helper/instance", "com.ubuntu.Upstart0_6.Instance", NULL); |
3949 | - dbus_test_dbus_mock_object_add_property(mock, uhelperinstance, "name", G_VARIANT_TYPE_STRING, |
3950 | - g_variant_new_string("untrusted-type::com.foo_bar_43.23.12"), NULL); |
3951 | - |
3952 | - DbusTestDbusMockObject* unhelpermulti = dbus_test_dbus_mock_get_object( |
3953 | - mock, "/com/test/untrusted/helper/multi_instance", "com.ubuntu.Upstart0_6.Instance", NULL); |
3954 | - dbus_test_dbus_mock_object_add_property( |
3955 | - mock, unhelpermulti, "name", G_VARIANT_TYPE_STRING, |
3956 | - g_variant_new_string("untrusted-type:24034582324132:com.bar_foo_8432.13.1"), NULL); |
3957 | - |
3958 | - /* Create the cgroup manager mock */ |
3959 | - cgmock = dbus_test_dbus_mock_new("org.test.cgmock"); |
3960 | - g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_NAME", "org.test.cgmock", TRUE); |
3961 | - |
3962 | - DbusTestDbusMockObject* cgobject = dbus_test_dbus_mock_get_object(cgmock, "/org/linuxcontainers/cgmanager", |
3963 | - "org.linuxcontainers.cgmanager0_0", NULL); |
3964 | - dbus_test_dbus_mock_object_add_method(cgmock, cgobject, "GetTasksRecursive", G_VARIANT_TYPE("(ss)"), |
3965 | - G_VARIANT_TYPE("ai"), "ret = [100, 200, 300]", NULL); |
3966 | + systemd = std::make_shared<SystemdMock>( |
3967 | + std::list<SystemdMock::Instance>{ |
3968 | + {"application-click", "com.test.good_application_1.2.3", {}, getpid(), {100, 200, 300}}, |
3969 | + {"application-snap", "unity8-package_foo_x123", {}, getpid(), {100, 200, 300}}, |
3970 | + {"application-legacy", "multiple", "2342345", 5678, {100, 200, 300}}, |
3971 | + {"application-legacy", "single", {}, 5678, {100, 200, 300}}, |
3972 | + {"helper", "com.foo_bar_43.23.12", {}, 1, {100, 200, 300}}, |
3973 | + {"helper", "com.bar_foo_8432.13.1", "24034582324132", 1, {100, 200, 300}}}, |
3974 | + CGROUP_DIR); |
3975 | |
3976 | /* Put it together */ |
3977 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); |
3978 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(cgmock)); |
3979 | + dbus_test_service_add_task(service, *systemd); |
3980 | |
3981 | /* Add in Libertine */ |
3982 | libertine = std::make_shared<LibertineService>(); |
3983 | @@ -343,9 +218,8 @@ |
3984 | // |
3985 | // ubuntu::app_launch::Registry::clearDefault(); |
3986 | |
3987 | + systemd.reset(); |
3988 | libertine.reset(); |
3989 | - g_clear_object(&mock); |
3990 | - g_clear_object(&cgmock); |
3991 | g_clear_object(&service); |
3992 | |
3993 | g_object_unref(bus); |
3994 | @@ -357,63 +231,40 @@ |
3995 | #endif |
3996 | } |
3997 | |
3998 | - GVariant* find_env(GVariant* env_array, const gchar* var) |
3999 | - { |
4000 | - unsigned int i; |
4001 | - GVariant* retval = nullptr; |
4002 | - |
4003 | - for (i = 0; i < g_variant_n_children(env_array); i++) |
4004 | - { |
4005 | - GVariant* child = g_variant_get_child_value(env_array, i); |
4006 | - const gchar* envvar = g_variant_get_string(child, nullptr); |
4007 | - |
4008 | - if (g_str_has_prefix(envvar, var)) |
4009 | - { |
4010 | - if (retval != nullptr) |
4011 | - { |
4012 | - g_warning("Found the env var more than once!"); |
4013 | - g_variant_unref(retval); |
4014 | - return nullptr; |
4015 | - } |
4016 | - |
4017 | - retval = child; |
4018 | - } |
4019 | - else |
4020 | - { |
4021 | - g_variant_unref(child); |
4022 | - } |
4023 | - } |
4024 | - |
4025 | - if (!retval) |
4026 | - { |
4027 | - gchar* envstr = g_variant_print(env_array, FALSE); |
4028 | - g_warning("Unable to find '%s' in '%s'", var, envstr); |
4029 | - g_free(envstr); |
4030 | - } |
4031 | - |
4032 | - return retval; |
4033 | - } |
4034 | - |
4035 | - bool check_env(GVariant* env_array, const gchar* var, const gchar* value) |
4036 | - { |
4037 | - bool found = false; |
4038 | - GVariant* val = find_env(env_array, var); |
4039 | - if (val == nullptr) |
4040 | + static std::string find_env(std::set<std::string>& envs, std::string var) |
4041 | + { |
4042 | + auto iter = |
4043 | + std::find_if(envs.begin(), envs.end(), [var](std::string value) { return split_env(value).first == var; }); |
4044 | + |
4045 | + if (iter == envs.end()) |
4046 | + { |
4047 | + return {}; |
4048 | + } |
4049 | + else |
4050 | + { |
4051 | + return *iter; |
4052 | + } |
4053 | + } |
4054 | + |
4055 | + static std::pair<std::string, std::string> split_env(const std::string& env) |
4056 | + { |
4057 | + auto eq = std::find(env.begin(), env.end(), '='); |
4058 | + if (eq == env.end()) |
4059 | + { |
4060 | + throw std::runtime_error{"Environment value is invalid: " + env}; |
4061 | + } |
4062 | + |
4063 | + return std::make_pair(std::string(env.begin(), eq), std::string(eq + 1, env.end())); |
4064 | + } |
4065 | + |
4066 | + static bool check_env(std::set<std::string>& envs, const std::string& key, const std::string& value) |
4067 | + { |
4068 | + auto val = find_env(envs, key); |
4069 | + if (val.empty()) |
4070 | { |
4071 | return false; |
4072 | } |
4073 | - |
4074 | - const gchar* envvar = g_variant_get_string(val, nullptr); |
4075 | - |
4076 | - gchar* combined = g_strdup_printf("%s=%s", var, value); |
4077 | - if (g_strcmp0(envvar, combined) == 0) |
4078 | - { |
4079 | - found = true; |
4080 | - } |
4081 | - |
4082 | - g_variant_unref(val); |
4083 | - |
4084 | - return found; |
4085 | + return split_env(val).second == value; |
4086 | } |
4087 | }; |
4088 | |
4089 | @@ -423,107 +274,6 @@ |
4090 | [&task] { return dbus_test_task_get_state(DBUS_TEST_TASK(task)); } \ |
4091 | } |
4092 | |
4093 | -TEST_F(LibUAL, StartClickApplication) |
4094 | -{ |
4095 | - DbusTestDbusMockObject* obj = |
4096 | - dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL); |
4097 | - |
4098 | - /* Basic make sure we can send the event */ |
4099 | - auto appid = ubuntu::app_launch::AppID::parse("com.test.multiple_first_1.2.3"); |
4100 | - auto app = ubuntu::app_launch::Application::create(appid, registry); |
4101 | - app->launch(); |
4102 | - |
4103 | - EXPECT_EQ(1, dbus_test_dbus_mock_object_check_method_call(mock, obj, "Start", NULL, NULL)); |
4104 | - |
4105 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4106 | - |
4107 | - /* Now look at the details of the call */ |
4108 | - app->launch(); |
4109 | - |
4110 | - guint len = 0; |
4111 | - const DbusTestDbusMockCall* calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4112 | - EXPECT_NE(nullptr, calls); |
4113 | - ASSERT_EQ(1u, len); |
4114 | - |
4115 | - EXPECT_STREQ("Start", calls->name); |
4116 | - EXPECT_EQ(2u, g_variant_n_children(calls->params)); |
4117 | - |
4118 | - GVariant* block = g_variant_get_child_value(calls->params, 1); |
4119 | - EXPECT_TRUE(g_variant_get_boolean(block)); |
4120 | - g_variant_unref(block); |
4121 | - |
4122 | - GVariant* env = g_variant_get_child_value(calls->params, 0); |
4123 | - EXPECT_TRUE(check_env(env, "APP_ID", "com.test.multiple_first_1.2.3")); |
4124 | - g_variant_unref(env); |
4125 | - |
4126 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4127 | - |
4128 | - /* Let's pass some URLs */ |
4129 | - std::vector<ubuntu::app_launch::Application::URL> urls{ |
4130 | - ubuntu::app_launch::Application::URL::from_raw("http://ubuntu.com/"), |
4131 | - ubuntu::app_launch::Application::URL::from_raw("https://ubuntu.com/"), |
4132 | - ubuntu::app_launch::Application::URL::from_raw("file:///home/phablet/test.txt")}; |
4133 | - |
4134 | - app->launch(urls); |
4135 | - |
4136 | - len = 0; |
4137 | - calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4138 | - EXPECT_NE(nullptr, calls); |
4139 | - ASSERT_EQ(1u, len); |
4140 | - |
4141 | - env = g_variant_get_child_value(calls->params, 0); |
4142 | - EXPECT_TRUE(check_env(env, "APP_ID", "com.test.multiple_first_1.2.3")); |
4143 | - EXPECT_TRUE( |
4144 | - check_env(env, "APP_URIS", "'http://ubuntu.com/' 'https://ubuntu.com/' 'file:///home/phablet/test.txt'")); |
4145 | - g_variant_unref(env); |
4146 | - |
4147 | - return; |
4148 | -} |
4149 | - |
4150 | -TEST_F(LibUAL, StartClickApplicationTest) |
4151 | -{ |
4152 | - DbusTestDbusMockObject* obj = |
4153 | - dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL); |
4154 | - |
4155 | - /* Basic make sure we can send the event */ |
4156 | - auto appid = ubuntu::app_launch::AppID::parse("com.test.multiple_first_1.2.3"); |
4157 | - auto app = ubuntu::app_launch::Application::create(appid, registry); |
4158 | - app->launchTest(); |
4159 | - |
4160 | - guint len = 0; |
4161 | - const DbusTestDbusMockCall* calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4162 | - EXPECT_NE(nullptr, calls); |
4163 | - ASSERT_EQ(1u, len); |
4164 | - |
4165 | - EXPECT_STREQ("Start", calls->name); |
4166 | - EXPECT_EQ(2u, g_variant_n_children(calls->params)); |
4167 | - |
4168 | - GVariant* block = g_variant_get_child_value(calls->params, 1); |
4169 | - EXPECT_TRUE(g_variant_get_boolean(block)); |
4170 | - g_variant_unref(block); |
4171 | - |
4172 | - GVariant* env = g_variant_get_child_value(calls->params, 0); |
4173 | - EXPECT_TRUE(check_env(env, "APP_ID", "com.test.multiple_first_1.2.3")); |
4174 | - EXPECT_TRUE(check_env(env, "QT_LOAD_TESTABILITY", "1")); |
4175 | - g_variant_unref(env); |
4176 | -} |
4177 | - |
4178 | -TEST_F(LibUAL, StopClickApplication) |
4179 | -{ |
4180 | - DbusTestDbusMockObject* obj = |
4181 | - dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL); |
4182 | - |
4183 | - auto appid = ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"); |
4184 | - auto app = ubuntu::app_launch::Application::create(appid, registry); |
4185 | - |
4186 | - ASSERT_TRUE(app->hasInstances()); |
4187 | - ASSERT_EQ(1, int(app->instances().size())); |
4188 | - |
4189 | - app->instances()[0]->stop(); |
4190 | - |
4191 | - ASSERT_EQ(dbus_test_dbus_mock_object_check_method_call(mock, obj, "Stop", NULL, NULL), 1); |
4192 | -} |
4193 | - |
4194 | #ifdef ENABLE_SNAPPY |
4195 | /* Snapd mock data */ |
4196 | static std::pair<std::string, std::string> interfaces{ |
4197 | @@ -617,113 +367,6 @@ |
4198 | FAIL() << "Expected std::runtime_error"; |
4199 | } |
4200 | } |
4201 | - |
4202 | -TEST_F(LibUAL, StartSnapApplication) |
4203 | -{ |
4204 | - SnapdMock snapd{LOCAL_SNAPD_TEST_SOCKET, {u8Package, interfaces, u8Package}}; |
4205 | - registry = std::make_shared<ubuntu::app_launch::Registry>(); |
4206 | - |
4207 | - auto obj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_snap", "com.ubuntu.Upstart0_6.Job", NULL); |
4208 | - |
4209 | - /* Basic make sure we can send the event */ |
4210 | - auto appid = ubuntu::app_launch::AppID::parse("unity8-package_single_x123"); |
4211 | - auto app = ubuntu::app_launch::Application::create(appid, registry); |
4212 | - app->launch(); |
4213 | - |
4214 | - EXPECT_EQ(1, dbus_test_dbus_mock_object_check_method_call(mock, obj, "Start", NULL, NULL)); |
4215 | - |
4216 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4217 | - |
4218 | - /* Now look at the details of the call */ |
4219 | - app->launch(); |
4220 | - |
4221 | - guint len = 0; |
4222 | - const DbusTestDbusMockCall* calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4223 | - EXPECT_NE(nullptr, calls); |
4224 | - EXPECT_EQ(1u, len); |
4225 | - |
4226 | - EXPECT_STREQ("Start", calls->name); |
4227 | - EXPECT_EQ(2u, g_variant_n_children(calls->params)); |
4228 | - |
4229 | - GVariant* block = g_variant_get_child_value(calls->params, 1); |
4230 | - EXPECT_TRUE(g_variant_get_boolean(block)); |
4231 | - g_variant_unref(block); |
4232 | - |
4233 | - GVariant* env = g_variant_get_child_value(calls->params, 0); |
4234 | - EXPECT_TRUE(check_env(env, "APP_ID", "unity8-package_single_x123")); |
4235 | - g_variant_unref(env); |
4236 | - |
4237 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4238 | - |
4239 | - /* Let's pass some URLs */ |
4240 | - std::vector<ubuntu::app_launch::Application::URL> urls{ |
4241 | - ubuntu::app_launch::Application::URL::from_raw("http://ubuntu.com/"), |
4242 | - ubuntu::app_launch::Application::URL::from_raw("https://ubuntu.com/"), |
4243 | - ubuntu::app_launch::Application::URL::from_raw("file:///home/phablet/test.txt")}; |
4244 | - |
4245 | - app->launch(urls); |
4246 | - |
4247 | - len = 0; |
4248 | - calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4249 | - EXPECT_NE(nullptr, calls); |
4250 | - EXPECT_EQ(1u, len); |
4251 | - |
4252 | - env = g_variant_get_child_value(calls->params, 0); |
4253 | - EXPECT_TRUE(check_env(env, "APP_ID", "unity8-package_single_x123")); |
4254 | - EXPECT_TRUE( |
4255 | - check_env(env, "APP_URIS", "'http://ubuntu.com/' 'https://ubuntu.com/' 'file:///home/phablet/test.txt'")); |
4256 | - g_variant_unref(env); |
4257 | - |
4258 | - return; |
4259 | -} |
4260 | - |
4261 | -TEST_F(LibUAL, StartSnapApplicationTest) |
4262 | -{ |
4263 | - SnapdMock snapd{LOCAL_SNAPD_TEST_SOCKET, {u8Package, interfaces, u8Package}}; |
4264 | - registry = std::make_shared<ubuntu::app_launch::Registry>(); |
4265 | - |
4266 | - auto obj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_snap", "com.ubuntu.Upstart0_6.Job", NULL); |
4267 | - |
4268 | - /* Basic make sure we can send the event */ |
4269 | - auto appid = ubuntu::app_launch::AppID::parse("unity8-package_single_x123"); |
4270 | - auto app = ubuntu::app_launch::Application::create(appid, registry); |
4271 | - app->launchTest(); |
4272 | - |
4273 | - guint len = 0; |
4274 | - auto calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4275 | - EXPECT_NE(nullptr, calls); |
4276 | - EXPECT_EQ(1u, len); |
4277 | - |
4278 | - EXPECT_STREQ("Start", calls->name); |
4279 | - EXPECT_EQ(2u, g_variant_n_children(calls->params)); |
4280 | - |
4281 | - GVariant* block = g_variant_get_child_value(calls->params, 1); |
4282 | - EXPECT_TRUE(g_variant_get_boolean(block)); |
4283 | - g_variant_unref(block); |
4284 | - |
4285 | - GVariant* env = g_variant_get_child_value(calls->params, 0); |
4286 | - EXPECT_TRUE(check_env(env, "APP_ID", "unity8-package_single_x123")); |
4287 | - EXPECT_TRUE(check_env(env, "QT_LOAD_TESTABILITY", "1")); |
4288 | - g_variant_unref(env); |
4289 | -} |
4290 | - |
4291 | -TEST_F(LibUAL, StopSnapApplication) |
4292 | -{ |
4293 | - SnapdMock snapd{LOCAL_SNAPD_TEST_SOCKET, {u8Package, interfaces, u8Package}}; |
4294 | - registry = std::make_shared<ubuntu::app_launch::Registry>(); |
4295 | - |
4296 | - auto obj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_snap", "com.ubuntu.Upstart0_6.Job", NULL); |
4297 | - |
4298 | - auto appid = ubuntu::app_launch::AppID::parse("unity8-package_foo_x123"); |
4299 | - auto app = ubuntu::app_launch::Application::create(appid, registry); |
4300 | - |
4301 | - ASSERT_TRUE(app->hasInstances()); |
4302 | - EXPECT_EQ(1, int(app->instances().size())); |
4303 | - |
4304 | - app->instances()[0]->stop(); |
4305 | - |
4306 | - ASSERT_EQ(dbus_test_dbus_mock_object_check_method_call(mock, obj, "Stop", NULL, NULL), 1); |
4307 | -} |
4308 | #endif |
4309 | |
4310 | TEST_F(LibUAL, ApplicationPid) |
4311 | @@ -892,107 +535,6 @@ |
4312 | #endif |
4313 | } |
4314 | |
4315 | -TEST_F(LibUAL, StartStopObserver) |
4316 | -{ |
4317 | - int start_count = 0; |
4318 | - int stop_count = 0; |
4319 | - ubuntu::app_launch::AppID start_appid; |
4320 | - ubuntu::app_launch::AppID stop_appid; |
4321 | - |
4322 | - ubuntu::app_launch::Registry::appStarted(registry).connect( |
4323 | - [&start_count, &start_appid](std::shared_ptr<ubuntu::app_launch::Application> app, |
4324 | - std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { |
4325 | - if (!start_appid.empty() && !(start_appid == app->appId())) |
4326 | - return; |
4327 | - |
4328 | - start_count++; |
4329 | - }); |
4330 | - |
4331 | - ubuntu::app_launch::Registry::appStopped(registry).connect( |
4332 | - [&stop_count, &stop_appid](std::shared_ptr<ubuntu::app_launch::Application> app, |
4333 | - std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { |
4334 | - if (!stop_appid.empty() && !(stop_appid == app->appId())) |
4335 | - return; |
4336 | - |
4337 | - stop_count++; |
4338 | - }); |
4339 | - |
4340 | - DbusTestDbusMockObject* obj = |
4341 | - dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
4342 | - |
4343 | - /* Basic start */ |
4344 | - dbus_test_dbus_mock_object_emit_signal( |
4345 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4346 | - g_variant_new_parsed("('started', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
4347 | - NULL); |
4348 | - |
4349 | - EXPECT_EVENTUALLY_EQ(1, start_count); |
4350 | - |
4351 | - /* Basic stop */ |
4352 | - dbus_test_dbus_mock_object_emit_signal( |
4353 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4354 | - g_variant_new_parsed("('stopped', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
4355 | - NULL); |
4356 | - |
4357 | - EXPECT_EVENTUALLY_EQ(1, stop_count); |
4358 | - |
4359 | - /* Start legacy */ |
4360 | - start_count = 0; |
4361 | - start_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw({}), |
4362 | - ubuntu::app_launch::AppID::AppName::from_raw("multiple"), |
4363 | - ubuntu::app_launch::AppID::Version::from_raw({})}; |
4364 | - |
4365 | - dbus_test_dbus_mock_object_emit_signal( |
4366 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4367 | - g_variant_new_parsed("('started', ['JOB=application-legacy', 'INSTANCE=multiple-234235'])"), NULL); |
4368 | - |
4369 | - EXPECT_EVENTUALLY_EQ(1, start_count); |
4370 | - |
4371 | - /* Legacy stop */ |
4372 | - stop_count = 0; |
4373 | - stop_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw({}), |
4374 | - ubuntu::app_launch::AppID::AppName::from_raw("foo"), |
4375 | - ubuntu::app_launch::AppID::Version::from_raw({})}; |
4376 | - |
4377 | - dbus_test_dbus_mock_object_emit_signal( |
4378 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4379 | - g_variant_new_parsed("('stopped', ['JOB=application-legacy', 'INSTANCE=foo-9344321'])"), NULL); |
4380 | - |
4381 | - EXPECT_EVENTUALLY_EQ(1, stop_count); |
4382 | - |
4383 | - /* Test Noise Start */ |
4384 | - start_count = 0; |
4385 | - start_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw("com.test.good"), |
4386 | - ubuntu::app_launch::AppID::AppName::from_raw("application"), |
4387 | - ubuntu::app_launch::AppID::Version::from_raw("1.2.3")}; |
4388 | - stop_count = 0; |
4389 | - stop_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw("com.test.good"), |
4390 | - ubuntu::app_launch::AppID::AppName::from_raw("application"), |
4391 | - ubuntu::app_launch::AppID::Version::from_raw("1.2.3")}; |
4392 | - |
4393 | - /* A full lifecycle */ |
4394 | - dbus_test_dbus_mock_object_emit_signal( |
4395 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4396 | - g_variant_new_parsed("('starting', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
4397 | - NULL); |
4398 | - dbus_test_dbus_mock_object_emit_signal( |
4399 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4400 | - g_variant_new_parsed("('started', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
4401 | - NULL); |
4402 | - dbus_test_dbus_mock_object_emit_signal( |
4403 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4404 | - g_variant_new_parsed("('stopping', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
4405 | - NULL); |
4406 | - dbus_test_dbus_mock_object_emit_signal( |
4407 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4408 | - g_variant_new_parsed("('stopped', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
4409 | - NULL); |
4410 | - |
4411 | - /* Ensure we just signaled once for each */ |
4412 | - EXPECT_EVENTUALLY_EQ(1, start_count); |
4413 | - EXPECT_EVENTUALLY_EQ(1, stop_count); |
4414 | -} |
4415 | - |
4416 | TEST_F(LibUAL, StartingResponses) |
4417 | { |
4418 | /* Get Bus */ |
4419 | @@ -1195,186 +737,100 @@ |
4420 | |
4421 | TEST_F(LibUAL, LegacySingleInstance) |
4422 | { |
4423 | - DbusTestDbusMockObject* obj = |
4424 | - dbus_test_dbus_mock_get_object(mock, "/com/test/application_legacy", "com.ubuntu.Upstart0_6.Job", NULL); |
4425 | - |
4426 | /* Check for a single-instance app */ |
4427 | auto singleappid = ubuntu::app_launch::AppID::find(registry, "single"); |
4428 | auto singleapp = ubuntu::app_launch::Application::create(singleappid, registry); |
4429 | |
4430 | singleapp->launch(); |
4431 | |
4432 | - guint len = 0; |
4433 | - const DbusTestDbusMockCall* calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4434 | - EXPECT_NE(nullptr, calls); |
4435 | - ASSERT_EQ(1u, len); |
4436 | - |
4437 | - EXPECT_STREQ("Start", calls->name); |
4438 | - EXPECT_EQ(2u, g_variant_n_children(calls->params)); |
4439 | - |
4440 | - GVariant* block = g_variant_get_child_value(calls->params, 1); |
4441 | - EXPECT_TRUE(g_variant_get_boolean(block)); |
4442 | - g_variant_unref(block); |
4443 | - |
4444 | - GVariant* env = g_variant_get_child_value(calls->params, 0); |
4445 | - EXPECT_TRUE(check_env(env, "APP_ID", "single")); |
4446 | - EXPECT_TRUE(check_env(env, "INSTANCE_ID", "")); |
4447 | - g_variant_unref(env); |
4448 | - |
4449 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4450 | + auto singleStart = systemd->unitCalls(); |
4451 | + ASSERT_EQ(1u, singleStart.size()); |
4452 | + EXPECT_EQ(SystemdMock::instanceName({"application-legacy", "single", "", 0, {}}), singleStart.begin()->name); |
4453 | + |
4454 | + systemd->managerClear(); |
4455 | |
4456 | /* Check for a multi-instance app */ |
4457 | auto multipleappid = ubuntu::app_launch::AppID::find(registry, "multiple"); |
4458 | auto multipleapp = ubuntu::app_launch::Application::create(multipleappid, registry); |
4459 | |
4460 | - multipleapp->launch(); |
4461 | - |
4462 | - len = 0; |
4463 | - calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4464 | - EXPECT_NE(nullptr, calls); |
4465 | - ASSERT_EQ(1u, len); |
4466 | - |
4467 | - EXPECT_STREQ("Start", calls->name); |
4468 | - EXPECT_EQ(2u, g_variant_n_children(calls->params)); |
4469 | - |
4470 | - block = g_variant_get_child_value(calls->params, 1); |
4471 | - EXPECT_TRUE(g_variant_get_boolean(block)); |
4472 | - g_variant_unref(block); |
4473 | - |
4474 | - env = g_variant_get_child_value(calls->params, 0); |
4475 | - EXPECT_TRUE(check_env(env, "APP_ID", "multiple")); |
4476 | - EXPECT_FALSE(check_env(env, "INSTANCE_ID", "")); |
4477 | - g_variant_unref(env); |
4478 | -} |
4479 | - |
4480 | -TEST_F(LibUAL, FailingObserver) |
4481 | -{ |
4482 | - ubuntu::app_launch::AppID lastFailedApp; |
4483 | - ubuntu::app_launch::Registry::FailureType lastFailedType; |
4484 | - |
4485 | - ubuntu::app_launch::Registry::appFailed(registry).connect( |
4486 | - [&lastFailedApp, &lastFailedType](std::shared_ptr<ubuntu::app_launch::Application> app, |
4487 | - std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
4488 | - ubuntu::app_launch::Registry::FailureType type) { |
4489 | - lastFailedApp = app->appId(); |
4490 | - lastFailedType = type; |
4491 | - }); |
4492 | - |
4493 | - GDBusConnection* session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
4494 | - |
4495 | - g_dbus_connection_emit_signal( |
4496 | - session, NULL, /* destination */ |
4497 | - "/", /* path */ |
4498 | - "com.canonical.UbuntuAppLaunch", /* interface */ |
4499 | - "ApplicationFailed", /* signal */ |
4500 | - g_variant_new("(sss)", "com.test.good_application_1.2.3", "goodinstance", "crash"), /* params, the same */ |
4501 | - NULL); |
4502 | - |
4503 | - EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), lastFailedApp); |
4504 | - EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::Registry::FailureType::CRASH, lastFailedType); |
4505 | - |
4506 | - lastFailedApp = ubuntu::app_launch::AppID(); |
4507 | - |
4508 | - g_dbus_connection_emit_signal( |
4509 | - session, NULL, /* destination */ |
4510 | - "/", /* path */ |
4511 | - "com.canonical.UbuntuAppLaunch", /* interface */ |
4512 | - "ApplicationFailed", /* signal */ |
4513 | - g_variant_new("(sss)", "com.test.good_application_1.2.3", "goodinstance", "blahblah"), /* params, the same */ |
4514 | - NULL); |
4515 | - |
4516 | - EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), lastFailedApp); |
4517 | - |
4518 | - lastFailedApp = ubuntu::app_launch::AppID(); |
4519 | - |
4520 | - g_dbus_connection_emit_signal(session, NULL, /* destination */ |
4521 | - "/", /* path */ |
4522 | - "com.canonical.UbuntuAppLaunch", /* interface */ |
4523 | - "ApplicationFailed", /* signal */ |
4524 | - g_variant_new("(sss)", "com.test.good_application_1.2.3", "goodinstance", |
4525 | - "start-failure"), /* params, the same */ |
4526 | - NULL); |
4527 | - |
4528 | - EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::Registry::FailureType::START_FAILURE, lastFailedType); |
4529 | - |
4530 | - g_object_unref(session); |
4531 | + auto inst = multipleapp->launch(); |
4532 | + |
4533 | + auto multiStart = systemd->unitCalls(); |
4534 | + ASSERT_EQ(1u, multiStart.size()); |
4535 | + EXPECT_EQ(SystemdMock::instanceName( |
4536 | + {"application-legacy", |
4537 | + "multiple", |
4538 | + std::dynamic_pointer_cast<ubuntu::app_launch::jobs::instance::Base>(inst)->getInstanceId(), |
4539 | + 0, |
4540 | + {}}), |
4541 | + multiStart.begin()->name); |
4542 | } |
4543 | |
4544 | TEST_F(LibUAL, StartHelper) |
4545 | { |
4546 | - DbusTestDbusMockObject* obj = |
4547 | - dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper", "com.ubuntu.Upstart0_6.Job", NULL); |
4548 | - |
4549 | auto untrusted = ubuntu::app_launch::Helper::Type::from_raw("untrusted-type"); |
4550 | |
4551 | /* Basic make sure we can send the event */ |
4552 | auto appid = ubuntu::app_launch::AppID::parse("com.test.multiple_first_1.2.3"); |
4553 | auto helper = ubuntu::app_launch::Helper::create(untrusted, appid, registry); |
4554 | |
4555 | - helper->launch(); |
4556 | - |
4557 | - EXPECT_EQ(1, dbus_test_dbus_mock_object_check_method_call(mock, obj, "Start", NULL, NULL)); |
4558 | - |
4559 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4560 | + auto inst = helper->launch(); |
4561 | + |
4562 | + auto helperStart = systemd->unitCalls(); |
4563 | + |
4564 | + ASSERT_EQ(1u, helperStart.size()); |
4565 | + EXPECT_EQ(SystemdMock::instanceName( |
4566 | + {"untrusted-type", |
4567 | + "com.test.multiple_first_1.2.3", |
4568 | + std::dynamic_pointer_cast<ubuntu::app_launch::jobs::instance::Base>(inst)->getInstanceId(), |
4569 | + 0, |
4570 | + {}}), |
4571 | + helperStart.begin()->name); |
4572 | + |
4573 | + systemd->managerClear(); |
4574 | |
4575 | /* Now check a multi out */ |
4576 | - helper->launch(); |
4577 | - |
4578 | - guint len = 0; |
4579 | - auto calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4580 | - EXPECT_NE(nullptr, calls); |
4581 | - ASSERT_EQ(1u, len); |
4582 | - |
4583 | - EXPECT_STREQ("Start", calls->name); |
4584 | - EXPECT_EQ(2u, g_variant_n_children(calls->params)); |
4585 | - |
4586 | - auto block = g_variant_get_child_value(calls->params, 1); |
4587 | - EXPECT_TRUE(g_variant_get_boolean(block)); |
4588 | - g_variant_unref(block); |
4589 | - |
4590 | - auto env = g_variant_get_child_value(calls->params, 0); |
4591 | - EXPECT_TRUE(check_env(env, "APP_ID", "com.test.multiple_first_1.2.3")); |
4592 | - EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); |
4593 | - g_variant_unref(env); |
4594 | - |
4595 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4596 | + auto inst2 = helper->launch(); |
4597 | + |
4598 | + auto helperStart2 = systemd->unitCalls(); |
4599 | + |
4600 | + ASSERT_EQ(1u, helperStart2.size()); |
4601 | + EXPECT_EQ(SystemdMock::instanceName( |
4602 | + {"untrusted-type", |
4603 | + "com.test.multiple_first_1.2.3", |
4604 | + std::dynamic_pointer_cast<ubuntu::app_launch::jobs::instance::Base>(inst2)->getInstanceId(), |
4605 | + 0, |
4606 | + {}}), |
4607 | + helperStart2.begin()->name); |
4608 | + |
4609 | + systemd->managerClear(); |
4610 | |
4611 | /* Let's pass some URLs */ |
4612 | std::vector<ubuntu::app_launch::Helper::URL> urls = { |
4613 | ubuntu::app_launch::Helper::URL::from_raw("http://ubuntu.com/"), |
4614 | ubuntu::app_launch::Helper::URL::from_raw("https://ubuntu.com/"), |
4615 | ubuntu::app_launch::Helper::URL::from_raw("file:///home/phablet/test.txt")}; |
4616 | - helper->launch(urls); |
4617 | - |
4618 | - len = 0; |
4619 | - calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4620 | - EXPECT_NE(nullptr, calls); |
4621 | - ASSERT_EQ(1u, len); |
4622 | - |
4623 | - env = g_variant_get_child_value(calls->params, 0); |
4624 | - EXPECT_TRUE(check_env(env, "APP_ID", "com.test.multiple_first_1.2.3")); |
4625 | - EXPECT_TRUE( |
4626 | - check_env(env, "APP_URIS", "'http://ubuntu.com/' 'https://ubuntu.com/' 'file:///home/phablet/test.txt'")); |
4627 | - EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); |
4628 | - EXPECT_FALSE(check_env(env, "INSTANCE_ID", NULL)); |
4629 | - g_variant_unref(env); |
4630 | - |
4631 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4632 | - |
4633 | - /* Needed as we still haven't ported second-exec.c to use the registry |
4634 | - thread and inherit its cancellable, we need to ensure all the extra |
4635 | - DBus messages error out before ending the test, or otherwise they'll |
4636 | - keep a reference to the DBus bus object. */ |
4637 | - pause(100); |
4638 | + |
4639 | + auto inst3 = helper->launch(urls); |
4640 | + |
4641 | + auto helperStart3 = systemd->unitCalls(); |
4642 | + |
4643 | + ASSERT_EQ(1u, helperStart3.size()); |
4644 | + EXPECT_EQ(SystemdMock::instanceName( |
4645 | + {"untrusted-type", |
4646 | + "com.test.multiple_first_1.2.3", |
4647 | + std::dynamic_pointer_cast<ubuntu::app_launch::jobs::instance::Base>(inst3)->getInstanceId(), |
4648 | + 0, |
4649 | + {}}), |
4650 | + helperStart3.begin()->name); |
4651 | + |
4652 | + /* TODO: Check URLS in exec */ |
4653 | |
4654 | return; |
4655 | } |
4656 | |
4657 | TEST_F(LibUAL, StopHelper) |
4658 | { |
4659 | - DbusTestDbusMockObject* obj = |
4660 | - dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper", "com.ubuntu.Upstart0_6.Job", NULL); |
4661 | - |
4662 | /* Multi helper */ |
4663 | auto untrusted = ubuntu::app_launch::Helper::Type::from_raw("untrusted-type"); |
4664 | |
4665 | @@ -1389,33 +845,12 @@ |
4666 | |
4667 | instances[0]->stop(); |
4668 | |
4669 | - ASSERT_EQ(dbus_test_dbus_mock_object_check_method_call(mock, obj, "Stop", NULL, NULL), 1); |
4670 | - |
4671 | - guint len = 0; |
4672 | - auto calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Stop", &len, NULL); |
4673 | - EXPECT_NE(nullptr, calls); |
4674 | - ASSERT_EQ(1u, len); |
4675 | - |
4676 | - EXPECT_STREQ("Stop", calls->name); |
4677 | - EXPECT_EQ(2u, g_variant_n_children(calls->params)); |
4678 | - |
4679 | - auto block = g_variant_get_child_value(calls->params, 1); |
4680 | - EXPECT_TRUE(g_variant_get_boolean(block)); |
4681 | - g_variant_unref(block); |
4682 | - |
4683 | - auto env = g_variant_get_child_value(calls->params, 0); |
4684 | - EXPECT_TRUE(check_env(env, "APP_ID", "com.bar_foo_8432.13.1")); |
4685 | - EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); |
4686 | - EXPECT_TRUE(check_env(env, "INSTANCE_ID", "24034582324132")); |
4687 | - g_variant_unref(env); |
4688 | - |
4689 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4690 | - |
4691 | - /* Needed as we still haven't ported second-exec.c to use the registry |
4692 | - thread and inherit its cancellable, we need to ensure all the extra |
4693 | - DBus messages error out before ending the test, or otherwise they'll |
4694 | - keep a reference to the DBus bus object. */ |
4695 | - pause(100); |
4696 | + auto calls = systemd->stopCalls(); |
4697 | + |
4698 | + ASSERT_EQ(1u, calls.size()); |
4699 | + |
4700 | + EXPECT_EQ(SystemdMock::instanceName({"untrusted-type", "com.bar_foo_8432.13.1", "24034582324132", 0, {}}), |
4701 | + *calls.begin()); |
4702 | |
4703 | return; |
4704 | } |
4705 | @@ -1482,23 +917,13 @@ |
4706 | ASSERT_TRUE(ubuntu_app_launch_observer_add_helper_started(helper_observer_cb, "my-type-is-scorpio", &start_data)); |
4707 | ASSERT_TRUE(ubuntu_app_launch_observer_add_helper_stop(helper_observer_cb, "my-type-is-libra", &stop_data)); |
4708 | |
4709 | - DbusTestDbusMockObject* obj = |
4710 | - dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
4711 | - |
4712 | /* Basic start */ |
4713 | - dbus_test_dbus_mock_object_emit_signal( |
4714 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4715 | - g_variant_new_parsed("('started', ['JOB=untrusted-helper', 'INSTANCE=my-type-is-scorpio::com.foo_foo_1.2.3'])"), |
4716 | - NULL); |
4717 | + systemd->managerEmitNew(SystemdMock::instanceName({"my-type-is-scorpio", "com.foo_foo_1.2.3", "", 0, {}}), "/"); |
4718 | |
4719 | EXPECT_EVENTUALLY_EQ(1, start_data.count); |
4720 | |
4721 | /* Basic stop */ |
4722 | - dbus_test_dbus_mock_object_emit_signal( |
4723 | - mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
4724 | - g_variant_new_parsed( |
4725 | - "('stopped', ['JOB=untrusted-helper', 'INSTANCE=my-type-is-libra:1234:com.bar_bar_44.32'])"), |
4726 | - NULL); |
4727 | + systemd->managerEmitRemoved(SystemdMock::instanceName({"my-type-is-scorpio", "com.foo_foo_1.2.3", "", 0, {}}), "/"); |
4728 | |
4729 | EXPECT_EVENTUALLY_EQ(1, stop_data.count); |
4730 | |
4731 | @@ -1516,35 +941,20 @@ |
4732 | /* Setup some spew */ |
4733 | SpewMaster spew; |
4734 | |
4735 | - /* Setup the cgroup */ |
4736 | - g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_NAME", "org.test.cgmock2", TRUE); |
4737 | - DbusTestDbusMock* cgmock2 = dbus_test_dbus_mock_new("org.test.cgmock2"); |
4738 | - DbusTestDbusMockObject* cgobject = dbus_test_dbus_mock_get_object(cgmock2, "/org/linuxcontainers/cgmanager", |
4739 | - "org.linuxcontainers.cgmanager0_0", NULL); |
4740 | - gchar* pypids = g_strdup_printf("ret = [%d]", spew.pid()); |
4741 | - dbus_test_dbus_mock_object_add_method(cgmock, cgobject, "GetTasksRecursive", G_VARIANT_TYPE("(ss)"), |
4742 | - G_VARIANT_TYPE("ai"), pypids, NULL); |
4743 | - g_free(pypids); |
4744 | - |
4745 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(cgmock2)); |
4746 | - dbus_test_task_run(DBUS_TEST_TASK(cgmock2)); |
4747 | - g_object_unref(G_OBJECT(cgmock2)); |
4748 | - |
4749 | /* Setup ZG Mock */ |
4750 | - DbusTestDbusMock* zgmock = dbus_test_dbus_mock_new("org.gnome.zeitgeist.Engine"); |
4751 | - DbusTestDbusMockObject* zgobj = |
4752 | - dbus_test_dbus_mock_get_object(zgmock, "/org/gnome/zeitgeist/log/activity", "org.gnome.zeitgeist.Log", NULL); |
4753 | - |
4754 | - dbus_test_dbus_mock_object_add_method(zgmock, zgobj, "InsertEvents", G_VARIANT_TYPE("a(asaasay)"), |
4755 | - G_VARIANT_TYPE("au"), "ret = [ 0 ]", NULL); |
4756 | - |
4757 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(zgmock)); |
4758 | - dbus_test_task_run(DBUS_TEST_TASK(zgmock)); |
4759 | - g_object_unref(G_OBJECT(zgmock)); |
4760 | + auto zgmock = std::make_shared<ZeitgeistMock>(); |
4761 | + |
4762 | + /* New Systemd Mock */ |
4763 | + dbus_test_service_remove_task(service, *systemd); |
4764 | + systemd.reset(); |
4765 | + auto systemd2 = std::make_shared<SystemdMock>( |
4766 | + std::list<SystemdMock::Instance>{ |
4767 | + {"application-click", "com.test.good_application_1.2.3", {}, spew.pid(), {spew.pid()}}}, |
4768 | + CGROUP_DIR); |
4769 | |
4770 | /* Give things a chance to start */ |
4771 | - EXPECT_EVENTUALLY_FUNC_EQ(DBUS_TEST_TASK_STATE_RUNNING, TASK_STATE(cgmock2)); |
4772 | - EXPECT_EVENTUALLY_FUNC_EQ(DBUS_TEST_TASK_STATE_RUNNING, TASK_STATE(zgmock)); |
4773 | + EXPECT_EVENTUALLY_FUNC_EQ(DBUS_TEST_TASK_STATE_RUNNING, systemd2->stateFunc()); |
4774 | + EXPECT_EVENTUALLY_FUNC_EQ(DBUS_TEST_TASK_STATE_RUNNING, zgmock->stateFunc()); |
4775 | |
4776 | /* Setup signal handling */ |
4777 | guint paused_count = 0; |
4778 | @@ -1592,14 +1002,10 @@ |
4779 | EXPECT_EQ(0u, spew.dataCnt()); |
4780 | |
4781 | /* Check to make sure we sent the event to ZG */ |
4782 | - guint numcalls = 0; |
4783 | - const DbusTestDbusMockCall* calls = |
4784 | - dbus_test_dbus_mock_object_get_method_calls(zgmock, zgobj, "InsertEvents", &numcalls, NULL); |
4785 | - |
4786 | - EXPECT_NE(nullptr, calls); |
4787 | - EXPECT_EQ(1u, numcalls); |
4788 | - |
4789 | - dbus_test_dbus_mock_object_clear_method_calls(zgmock, zgobj, NULL); |
4790 | + auto inserts = zgmock->insertCalls(); |
4791 | + EXPECT_EQ(1u, inserts.size()); |
4792 | + |
4793 | + zgmock->clear(); |
4794 | |
4795 | /* Check to ensure we set the OOM score */ |
4796 | EXPECT_EQ("900", spew.oomScore()); |
4797 | @@ -1613,11 +1019,10 @@ |
4798 | EXPECT_NE(0u, spew.dataCnt()); |
4799 | |
4800 | /* Check to make sure we sent the event to ZG */ |
4801 | - numcalls = 0; |
4802 | - calls = dbus_test_dbus_mock_object_get_method_calls(zgmock, zgobj, "InsertEvents", &numcalls, NULL); |
4803 | + auto inserts2 = zgmock->insertCalls(); |
4804 | + EXPECT_EQ(1u, inserts2.size()); |
4805 | |
4806 | - EXPECT_NE(nullptr, calls); |
4807 | - EXPECT_EQ(1u, numcalls); |
4808 | + zgmock->clear(); |
4809 | |
4810 | /* Check to ensure we set the OOM score */ |
4811 | EXPECT_EQ("100", spew.oomScore()); |
4812 | @@ -1632,41 +1037,22 @@ |
4813 | /* Setup A TON OF spew */ |
4814 | std::array<SpewMaster, 50> spews; |
4815 | |
4816 | - /* Setup the cgroup */ |
4817 | - g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_NAME", "org.test.cgmock2", TRUE); |
4818 | - DbusTestDbusMock* cgmock2 = dbus_test_dbus_mock_new("org.test.cgmock2"); |
4819 | - DbusTestDbusMockObject* cgobject = dbus_test_dbus_mock_get_object(cgmock2, "/org/linuxcontainers/cgmanager", |
4820 | - "org.linuxcontainers.cgmanager0_0", NULL); |
4821 | - |
4822 | - std::string pypids = "ret = [ " + std::accumulate(spews.begin(), spews.end(), std::string{}, |
4823 | - [](const std::string& accum, SpewMaster& spew) { |
4824 | - return accum.empty() ? |
4825 | - std::to_string(spew.pid()) : |
4826 | - accum + ", " + std::to_string(spew.pid()); |
4827 | - }) + |
4828 | - "]"; |
4829 | - dbus_test_dbus_mock_object_add_method(cgmock, cgobject, "GetTasksRecursive", G_VARIANT_TYPE("(ss)"), |
4830 | - G_VARIANT_TYPE("ai"), pypids.c_str(), NULL); |
4831 | - |
4832 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(cgmock2)); |
4833 | - dbus_test_task_run(DBUS_TEST_TASK(cgmock2)); |
4834 | - g_object_unref(G_OBJECT(cgmock2)); |
4835 | - |
4836 | /* Setup ZG Mock */ |
4837 | - DbusTestDbusMock* zgmock = dbus_test_dbus_mock_new("org.gnome.zeitgeist.Engine"); |
4838 | - DbusTestDbusMockObject* zgobj = |
4839 | - dbus_test_dbus_mock_get_object(zgmock, "/org/gnome/zeitgeist/log/activity", "org.gnome.zeitgeist.Log", NULL); |
4840 | - |
4841 | - dbus_test_dbus_mock_object_add_method(zgmock, zgobj, "InsertEvents", G_VARIANT_TYPE("a(asaasay)"), |
4842 | - G_VARIANT_TYPE("au"), "ret = [ 0 ]", NULL); |
4843 | - |
4844 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(zgmock)); |
4845 | - dbus_test_task_run(DBUS_TEST_TASK(zgmock)); |
4846 | - g_object_unref(G_OBJECT(zgmock)); |
4847 | + auto zgmock = std::make_shared<ZeitgeistMock>(); |
4848 | + |
4849 | + /* New Systemd Mock */ |
4850 | + dbus_test_service_remove_task(service, *systemd); |
4851 | + systemd.reset(); |
4852 | + std::vector<pid_t> spewpids; |
4853 | + std::transform(spews.begin(), spews.end(), spewpids.begin(), [](SpewMaster& spew) { return spew.pid(); }); |
4854 | + auto systemd2 = std::make_shared<SystemdMock>( |
4855 | + std::list<SystemdMock::Instance>{ |
4856 | + {"application-click", "com.test.good_application_1.2.3", {}, spews.begin()->pid(), spewpids}}, |
4857 | + CGROUP_DIR); |
4858 | |
4859 | /* Give things a chance to start */ |
4860 | - EXPECT_EVENTUALLY_FUNC_EQ(DBUS_TEST_TASK_STATE_RUNNING, TASK_STATE(cgmock2)); |
4861 | - EXPECT_EVENTUALLY_FUNC_EQ(DBUS_TEST_TASK_STATE_RUNNING, TASK_STATE(zgmock)); |
4862 | + EXPECT_EVENTUALLY_FUNC_EQ(DBUS_TEST_TASK_STATE_RUNNING, systemd2->stateFunc()); |
4863 | + EXPECT_EVENTUALLY_FUNC_EQ(DBUS_TEST_TASK_STATE_RUNNING, zgmock->stateFunc()); |
4864 | |
4865 | /* Setup signal handling */ |
4866 | guint paused_count = 0; |
4867 | @@ -1763,23 +1149,6 @@ |
4868 | g_free(procdir); |
4869 | ASSERT_TRUE(g_file_set_contents(oomadjfile, "0", -1, NULL)); |
4870 | |
4871 | - /* Setup the cgroup */ |
4872 | - g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_NAME", "org.test.cgmock2", TRUE); |
4873 | - DbusTestDbusMock* cgmock2 = dbus_test_dbus_mock_new("org.test.cgmock2"); |
4874 | - DbusTestDbusMockObject* cgobject = dbus_test_dbus_mock_get_object(cgmock2, "/org/linuxcontainers/cgmanager", |
4875 | - "org.linuxcontainers.cgmanager0_0", NULL); |
4876 | - gchar* pypids = g_strdup_printf("ret = [%d]", testpid); |
4877 | - dbus_test_dbus_mock_object_add_method(cgmock, cgobject, "GetTasksRecursive", G_VARIANT_TYPE("(ss)"), |
4878 | - G_VARIANT_TYPE("ai"), pypids, NULL); |
4879 | - g_free(pypids); |
4880 | - |
4881 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(cgmock2)); |
4882 | - dbus_test_task_run(DBUS_TEST_TASK(cgmock2)); |
4883 | - g_object_unref(G_OBJECT(cgmock2)); |
4884 | - |
4885 | - /* Give things a chance to start */ |
4886 | - EXPECT_EVENTUALLY_FUNC_EQ(DBUS_TEST_TASK_STATE_RUNNING, TASK_STATE(cgmock2)); |
4887 | - |
4888 | /* Get our app object */ |
4889 | auto appid = ubuntu::app_launch::AppID::find(registry, "com.test.good_application_1.2.3"); |
4890 | auto app = ubuntu::app_launch::Application::create(appid, registry); |
4891 | @@ -1833,8 +1202,6 @@ |
4892 | |
4893 | TEST_F(LibUAL, StartSessionHelper) |
4894 | { |
4895 | - DbusTestDbusMockObject* obj = |
4896 | - dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper", "com.ubuntu.Upstart0_6.Job", NULL); |
4897 | MirConnection* conn = mir_connect_sync("libual-test", "start-session-helper"); // Mocked, doesn't need cleaning up |
4898 | MirPromptSession* msession = mir_connection_create_prompt_session_sync(conn, 5, nullptr, nullptr); |
4899 | |
4900 | @@ -1851,42 +1218,23 @@ |
4901 | |
4902 | helper->launch(msession); |
4903 | |
4904 | - guint len = 0; |
4905 | - const DbusTestDbusMockCall* calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
4906 | - EXPECT_NE(nullptr, calls); |
4907 | - ASSERT_EQ(1u, len); |
4908 | - |
4909 | - EXPECT_STREQ("Start", calls->name); |
4910 | - EXPECT_EQ(2u, g_variant_n_children(calls->params)); |
4911 | - |
4912 | - GVariant* block = g_variant_get_child_value(calls->params, 1); |
4913 | - EXPECT_TRUE(g_variant_get_boolean(block)); |
4914 | - g_variant_unref(block); |
4915 | + auto calls = systemd->unitCalls(); |
4916 | + ASSERT_EQ(1u, calls.size()); |
4917 | |
4918 | /* Check the environment */ |
4919 | - GVariant* env = g_variant_get_child_value(calls->params, 0); |
4920 | + auto& env = calls.begin()->environment; |
4921 | EXPECT_TRUE(check_env(env, "APP_ID", "com.test.multiple_first_1.2.3")); |
4922 | EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); |
4923 | |
4924 | - GVariant* mnamev = find_env(env, "UBUNTU_APP_LAUNCH_DEMANGLE_NAME"); |
4925 | - ASSERT_NE(nullptr, mnamev); /* Have to assert because, eh, GVariant */ |
4926 | - EXPECT_STREQ(g_dbus_connection_get_unique_name(bus), |
4927 | - g_variant_get_string(mnamev, nullptr) + strlen("UBUNTU_APP_LAUNCH_DEMANGLE_NAME=")); |
4928 | - GVariant* mpathv = find_env(env, "UBUNTU_APP_LAUNCH_DEMANGLE_PATH"); |
4929 | - ASSERT_NE(nullptr, mpathv); /* Have to assert because, eh, GVariant */ |
4930 | - |
4931 | - g_variant_unref(env); |
4932 | + auto demanglename = find_env(env, "UBUNTU_APP_LAUNCH_DEMANGLE_NAME"); |
4933 | + ASSERT_FALSE(demanglename.empty()); |
4934 | + EXPECT_EQ(g_dbus_connection_get_unique_name(bus), split_env(demanglename).second); |
4935 | + auto demanglepath = find_env(env, "UBUNTU_APP_LAUNCH_DEMANGLE_PATH"); |
4936 | + ASSERT_FALSE(demanglepath.empty()); |
4937 | |
4938 | /* Setup environment for call */ |
4939 | - const gchar* mname = g_variant_get_string(mnamev, nullptr); |
4940 | - mname += strlen("UBUNTU_APP_LAUNCH_DEMANGLE_NAME="); |
4941 | - g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME", mname, TRUE); |
4942 | - g_variant_unref(mnamev); |
4943 | - |
4944 | - const gchar* mpath = g_variant_get_string(mpathv, nullptr); |
4945 | - mpath += strlen("UBUNTU_APP_LAUNCH_DEMANGLE_PATH="); |
4946 | - g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_PATH", mpath, TRUE); |
4947 | - g_variant_unref(mpathv); |
4948 | + g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME", split_env(demanglename).second.c_str(), TRUE); |
4949 | + g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_PATH", split_env(demanglepath).second.c_str(), TRUE); |
4950 | |
4951 | /* Exec our tool */ |
4952 | std::promise<std::string> outputpromise; |
4953 | @@ -1919,11 +1267,11 @@ |
4954 | |
4955 | ASSERT_STREQ(filedata, outputfuture.get().c_str()); |
4956 | |
4957 | - ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4958 | - |
4959 | return; |
4960 | } |
4961 | |
4962 | +#if 0 |
4963 | +/* Need to change as helpers change to not use Upstart features */ |
4964 | TEST_F(LibUAL, SetExec) |
4965 | { |
4966 | DbusTestDbusMockObject* obj = |
4967 | @@ -1978,6 +1326,7 @@ |
4968 | |
4969 | ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
4970 | } |
4971 | +#endif |
4972 | |
4973 | TEST_F(LibUAL, AppInfo) |
4974 | { |
4975 | |
4976 | === modified file 'tests/systemd-mock.h' |
4977 | --- tests/systemd-mock.h 2017-02-04 03:53:34 +0000 |
4978 | +++ tests/systemd-mock.h 2017-03-21 03:20:55 +0000 |
4979 | @@ -551,4 +551,9 @@ |
4980 | throw std::runtime_error{"Mock disfunctional"}; |
4981 | } |
4982 | } |
4983 | + |
4984 | + std::function<DbusTestTaskState()> stateFunc() |
4985 | + { |
4986 | + return [this] { return dbus_test_task_get_state(DBUS_TEST_TASK(mock)); }; |
4987 | + } |
4988 | }; |
4989 | |
4990 | === added file 'tests/zg-mock.h' |
4991 | --- tests/zg-mock.h 1970-01-01 00:00:00 +0000 |
4992 | +++ tests/zg-mock.h 2017-03-21 03:20:55 +0000 |
4993 | @@ -0,0 +1,117 @@ |
4994 | +/* |
4995 | + * Copyright © 2017 Canonical Ltd. |
4996 | + * |
4997 | + * This program is free software; you can redistribute it and/or modify |
4998 | + * it under the terms of the GNU General Public License as published by |
4999 | + * the Free Software Foundation; version 3. |
5000 | + * |
FAILED: Continuous integration, rev:295 /jenkins. canonical. com/unity- api-1/job/ lp-ubuntu- app-launch- ci/233/ /jenkins. canonical. com/unity- api-1/job/ build/1705/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/1712 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 1486/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= zesty/1486/ console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 1486/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= zesty/1486/ console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 1486/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= zesty/1486/ console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-ubuntu- app-launch- ci/233/ rebuild
https:/