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 on 2017-03-21 |
| 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) | 2017-02-22 | Approve on 2017-03-21 | |
| unity-api-1-bot | continuous-integration | Needs Fixing on 2017-03-21 | |
|
Review via email:
|
|||
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 : | # |
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:/
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:/