Merge lp:~ted/url-dispatcher/de-upstart into lp:url-dispatcher
- de-upstart
- Merge into trunk.17.04
Status: | Merged |
---|---|
Approved by: | dobey |
Approved revision: | 114 |
Merged at revision: | 115 |
Proposed branch: | lp:~ted/url-dispatcher/de-upstart |
Merge into: | lp:url-dispatcher |
Diff against target: |
783 lines (+606/-72) 4 files modified
tests/CMakeLists.txt (+1/-1) tests/service-test.cc (+28/-71) tests/systemd-mock.h (+576/-0) tests/xdg-data/applications/foo-bar.desktop (+1/-0) |
To merge this branch: | bzr merge lp:~ted/url-dispatcher/de-upstart |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
dobey (community) | Approve | ||
unity-api-1-bot | continuous-integration | Needs Fixing | |
Review via email: mp+320123@code.launchpad.net |
Commit message
Remove Upstart from the test suite and replace it with systemd
Description of the change
unity-api-1-bot (unity-api-1-bot) wrote : | # |
dobey (dobey) wrote : | # |
21:59:22 /<<BUILDDIR>
21:59:22 /<<BUILDDIR>
21:59:22 /<<BUILDDIR>
21:59:25 /<<BUILDDIR>
21:59:25 /<<BUILDDIR>
21:58:57 /<<BUILDDIR>
21:59:15 /<<BUILDDIR>
21:59:22 /usr/src/
dobey (dobey) wrote : | # |
Never mind about the signed compares. They aren't from this branch, and seem to already exist in the last build.
Preview Diff
1 | === modified file 'tests/CMakeLists.txt' |
2 | --- tests/CMakeLists.txt 2017-03-14 14:31:35 +0000 |
3 | +++ tests/CMakeLists.txt 2017-03-16 21:55:16 +0000 |
4 | @@ -73,7 +73,7 @@ |
5 | # service test |
6 | ########################### |
7 | |
8 | -add_executable (service-test service-test.cc) |
9 | +add_executable (service-test service-test.cc ${CMAKE_SOURCE_DIR}/service/glib-thread.cpp) |
10 | target_link_libraries (service-test |
11 | url-db-lib |
12 | dispatcher |
13 | |
14 | === modified file 'tests/service-test.cc' |
15 | --- tests/service-test.cc 2015-06-26 13:27:22 +0000 |
16 | +++ tests/service-test.cc 2017-03-16 21:55:16 +0000 |
17 | @@ -23,20 +23,24 @@ |
18 | #include <libdbustest/dbus-test.h> |
19 | |
20 | #include "url-db.h" |
21 | +#include "systemd-mock.h" |
22 | + |
23 | +#define CGROUP_DIR (CMAKE_BINARY_DIR "/systemd-service-test-cgroups") |
24 | |
25 | class ServiceTest : public ::testing::Test |
26 | { |
27 | protected: |
28 | DbusTestService * service = nullptr; |
29 | - DbusTestDbusMock * mock = nullptr; |
30 | DbusTestDbusMock * dashmock = nullptr; |
31 | - DbusTestDbusMockObject * obj = nullptr; |
32 | - DbusTestDbusMockObject * jobobj = nullptr; |
33 | DbusTestProcess * dispatcher = nullptr; |
34 | + std::shared_ptr<SystemdMock> systemd; |
35 | GDBusConnection * bus = nullptr; |
36 | |
37 | virtual void SetUp() { |
38 | g_setenv("UBUNTU_APP_LAUNCH_USE_SESSION", "1", TRUE); |
39 | + g_setenv("UBUNTU_APP_LAUNCH_SYSTEMD_CGROUP_ROOT", CGROUP_DIR, TRUE); |
40 | + g_setenv("UBUNTU_APP_LAUNCH_SYSTEMD_PATH", "/this/should/not/exist", TRUE); |
41 | + |
42 | g_setenv("URL_DISPATCHER_DISABLE_RECOVERABLE_ERROR", "1", TRUE); |
43 | g_setenv("URL_DISPATCHER_DISABLE_SCOPE_CHECKING", "1", TRUE); |
44 | g_setenv("XDG_DATA_DIRS", XDG_DATA_DIRS, TRUE); |
45 | @@ -50,28 +54,12 @@ |
46 | dbus_test_task_set_name(DBUS_TEST_TASK(dispatcher), "Dispatcher"); |
47 | dbus_test_service_add_task(service, DBUS_TEST_TASK(dispatcher)); |
48 | |
49 | - /* Upstart Mock */ |
50 | - mock = dbus_test_dbus_mock_new("com.ubuntu.Upstart"); |
51 | - obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", nullptr); |
52 | - |
53 | - dbus_test_dbus_mock_object_add_method(mock, obj, |
54 | - "GetJobByName", |
55 | - G_VARIANT_TYPE_STRING, |
56 | - G_VARIANT_TYPE_OBJECT_PATH, /* out */ |
57 | - "ret = dbus.ObjectPath('/job')", /* python */ |
58 | - nullptr); /* error */ |
59 | - |
60 | - jobobj = dbus_test_dbus_mock_get_object(mock, "/job", "com.ubuntu.Upstart0_6.Job", nullptr); |
61 | - |
62 | - dbus_test_dbus_mock_object_add_method(mock, jobobj, |
63 | - "Start", |
64 | - G_VARIANT_TYPE("(asb)"), |
65 | - G_VARIANT_TYPE_OBJECT_PATH, /* out */ |
66 | - "ret = dbus.ObjectPath('/instance')", /* python */ |
67 | - nullptr); /* error */ |
68 | - |
69 | - dbus_test_task_set_name(DBUS_TEST_TASK(mock), "Upstart"); |
70 | - dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); |
71 | + /* Systemd Mock */ |
72 | + systemd = std::make_shared<SystemdMock>( |
73 | + std::list<SystemdMock::Instance>{ |
74 | + {"application-legacy", "single", {}, getpid(), {getpid()}}, |
75 | + }, CGROUP_DIR); |
76 | + dbus_test_service_add_task(service, *systemd); |
77 | |
78 | /* Dash Mock */ |
79 | dashmock = dbus_test_dbus_mock_new("com.canonical.UnityDash"); |
80 | @@ -96,12 +84,10 @@ |
81 | } |
82 | |
83 | virtual void TearDown() { |
84 | - gchar * cmdline = g_strdup_printf("kill -TERM %d", dbus_test_process_get_pid(dispatcher)); |
85 | - g_spawn_command_line_sync(cmdline, nullptr, nullptr, nullptr, nullptr); |
86 | - g_free(cmdline); |
87 | + kill(dbus_test_process_get_pid(dispatcher), SIGTERM); |
88 | |
89 | + systemd.reset(); |
90 | g_clear_object(&dispatcher); |
91 | - g_clear_object(&mock); |
92 | g_clear_object(&dashmock); |
93 | g_clear_object(&service); |
94 | |
95 | @@ -165,10 +151,8 @@ |
96 | g_main_loop_run(main); |
97 | g_main_loop_unref(main); |
98 | |
99 | - guint callslen = 0; |
100 | - dbus_test_dbus_mock_object_get_method_calls(mock, jobobj, "Start", &callslen, nullptr); |
101 | - |
102 | - ASSERT_EQ(callslen, 0); |
103 | + auto calls = systemd->unitCalls(); |
104 | + ASSERT_EQ(0u, calls.size()); |
105 | } |
106 | |
107 | TEST_F(ServiceTest, ApplicationTest) { |
108 | @@ -181,30 +165,10 @@ |
109 | g_main_loop_run(main); |
110 | g_main_loop_unref(main); |
111 | |
112 | - guint callslen = 0; |
113 | - const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, jobobj, "Start", &callslen, nullptr); |
114 | - |
115 | - ASSERT_EQ(callslen, 1); |
116 | - |
117 | - /* Making sure the APP_ID is here. We're not testing more to |
118 | - make it so the tests break less, that should be tested in |
119 | - Upstart App Launch, we don't need to retest */ |
120 | - GVariant * env = g_variant_get_child_value(calls->params, 0); |
121 | - GVariantIter iter; |
122 | - bool found_appid = false; |
123 | - g_variant_iter_init(&iter, env); |
124 | - gchar * var = nullptr; |
125 | - |
126 | - while (g_variant_iter_loop(&iter, "s", &var)) { |
127 | - if (g_strcmp0(var, "APP_ID=foo-bar") == 0) { |
128 | - ASSERT_FALSE(found_appid); |
129 | - found_appid = true; |
130 | - } |
131 | - } |
132 | - |
133 | - g_variant_unref(env); |
134 | - |
135 | - ASSERT_TRUE(found_appid); |
136 | + /* Check to see it called systemd */ |
137 | + auto calls = systemd->unitCalls(); |
138 | + ASSERT_EQ(1u, calls.size()); |
139 | + EXPECT_EQ(SystemdMock::instanceName({"application-legacy", "foo-bar", "", 0, {}}), calls.begin()->name); |
140 | } |
141 | |
142 | TEST_F(ServiceTest, TestURLTest) { |
143 | @@ -215,7 +179,7 @@ |
144 | }; |
145 | |
146 | gchar ** appids = url_dispatch_url_appid(testurls); |
147 | - ASSERT_EQ(1, g_strv_length(appids)); |
148 | + ASSERT_EQ(1u, g_strv_length(appids)); |
149 | |
150 | EXPECT_STREQ("foo-bar", appids[0]); |
151 | |
152 | @@ -229,7 +193,7 @@ |
153 | }; |
154 | |
155 | gchar ** multiappids = url_dispatch_url_appid(multiurls); |
156 | - ASSERT_EQ(2, g_strv_length(multiappids)); |
157 | + ASSERT_EQ(2u, g_strv_length(multiappids)); |
158 | |
159 | EXPECT_STREQ("bar-foo", multiappids[0]); |
160 | EXPECT_STREQ("foo-bar", multiappids[1]); |
161 | @@ -243,7 +207,7 @@ |
162 | }; |
163 | |
164 | gchar ** errorappids = url_dispatch_url_appid(errorurls); |
165 | - ASSERT_EQ(0, g_strv_length(errorappids)); |
166 | + ASSERT_EQ(0u, g_strv_length(errorappids)); |
167 | |
168 | g_strfreev(errorappids); |
169 | } |
170 | @@ -283,19 +247,12 @@ |
171 | g_main_loop_unref(main); |
172 | |
173 | guint callslen = 0; |
174 | - const DbusTestDbusMockCall * calls = nullptr; |
175 | - calls = dbus_test_dbus_mock_object_get_method_calls(mock, jobobj, "Start", &callslen, nullptr); |
176 | - |
177 | - EXPECT_NE(calls, nullptr); |
178 | - EXPECT_EQ(0, callslen); |
179 | - |
180 | - callslen = 0; |
181 | - calls = dbus_test_dbus_mock_object_get_method_calls(dashmock, fdoobj, "Open", &callslen, nullptr); |
182 | - |
183 | - EXPECT_EQ(1, callslen); |
184 | + auto calls = dbus_test_dbus_mock_object_get_method_calls(dashmock, fdoobj, "Open", &callslen, nullptr); |
185 | + |
186 | + EXPECT_EQ(1u, callslen); |
187 | EXPECT_TRUE(g_variant_equal(calls[0].params, g_variant_new_parsed("(['scopeish://foo-bar'], @a{sv} {})"))); |
188 | |
189 | - EXPECT_EQ(1, focus_count); |
190 | + EXPECT_EQ(1u, focus_count); |
191 | |
192 | g_dbus_connection_signal_unsubscribe(bus, focus_signal); |
193 | g_clear_object(&bus); |
194 | |
195 | === added file 'tests/systemd-mock.h' |
196 | --- tests/systemd-mock.h 1970-01-01 00:00:00 +0000 |
197 | +++ tests/systemd-mock.h 2017-03-16 21:55:16 +0000 |
198 | @@ -0,0 +1,576 @@ |
199 | +/* |
200 | + * Copyright © 2017 Canonical Ltd. |
201 | + * |
202 | + * This program is free software; you can redistribute it and/or modify |
203 | + * it under the terms of the GNU General Public License as published by |
204 | + * the Free Software Foundation; version 3. |
205 | + * |
206 | + * This program is distributed in the hope that it will be useful, |
207 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
208 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
209 | + * GNU General Public License for more details. |
210 | + * |
211 | + * You should have received a copy of the GNU General Public License |
212 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
213 | + * |
214 | + * Authors: |
215 | + * Ted Gould <ted@canonical.com> |
216 | + */ |
217 | + |
218 | +#include <algorithm> |
219 | +#include <future> |
220 | +#include <list> |
221 | +#include <map> |
222 | +#include <memory> |
223 | +#include <numeric> |
224 | +#include <type_traits> |
225 | + |
226 | +#include <gio/gio.h> |
227 | + |
228 | +#include <libdbustest/dbus-test.h> |
229 | + |
230 | +#include "glib-thread.h" |
231 | + |
232 | +class SystemdMock |
233 | +{ |
234 | +public: |
235 | + struct Instance |
236 | + { |
237 | + std::string job; |
238 | + std::string appid; |
239 | + std::string instanceid; |
240 | + pid_t primaryPid; |
241 | + std::vector<pid_t> pids; |
242 | + }; |
243 | + |
244 | +private: |
245 | + DbusTestDbusMock* mock = nullptr; |
246 | + DbusTestDbusMockObject* managerobj = nullptr; |
247 | + GLib::ContextThread thread; |
248 | + std::list<std::pair<Instance, DbusTestDbusMockObject*>> insts; |
249 | + |
250 | + void throwError(GError* error) |
251 | + { |
252 | + if (error == nullptr) |
253 | + { |
254 | + return; |
255 | + } |
256 | + |
257 | + auto message = std::string{"Error in systemd mock: "} + error->message; |
258 | + g_error_free(error); |
259 | + throw std::runtime_error{message}; |
260 | + } |
261 | + |
262 | +public: |
263 | + SystemdMock(const std::list<Instance>& instances, const std::string& controlGroupPath) |
264 | + { |
265 | + GError* error = nullptr; |
266 | + mock = dbus_test_dbus_mock_new("org.freedesktop.systemd1"); |
267 | + dbus_test_task_set_bus(DBUS_TEST_TASK(mock), DBUS_TEST_SERVICE_BUS_SESSION); |
268 | + dbus_test_task_set_name(DBUS_TEST_TASK(mock), "systemd"); |
269 | + |
270 | + managerobj = dbus_test_dbus_mock_get_object(mock, "/org/freedesktop/systemd1", |
271 | + "org.freedesktop.systemd1.Manager", nullptr); |
272 | + |
273 | + dbus_test_dbus_mock_object_add_method(mock, managerobj, "Subscribe", nullptr, nullptr, "", nullptr); |
274 | + dbus_test_dbus_mock_object_add_method( |
275 | + mock, managerobj, "ListUnits", nullptr, G_VARIANT_TYPE("(a(ssssssouso))"), /* ret type */ |
276 | + ("ret = [ " + std::accumulate(instances.begin(), instances.end(), std::string{}, |
277 | + [](const std::string accum, const Instance& inst) { |
278 | + std::string retval = accum; |
279 | + |
280 | + if (!retval.empty()) |
281 | + { |
282 | + retval += ", "; |
283 | + } |
284 | + |
285 | + retval += std::string{"("} + /* start tuple */ |
286 | + "'" + instanceName(inst) + "', " + /* id */ |
287 | + "'unused', " + /* description */ |
288 | + "'unused', " + /* load state */ |
289 | + "'unused', " + /* active state */ |
290 | + "'unused', " + /* substate */ |
291 | + "'unused', " + /* following */ |
292 | + "'/unused', " + /* path */ |
293 | + "5, " + /* jobId */ |
294 | + "'unused', " + /* jobType */ |
295 | + "'" + instancePath(inst) + "'" + /* jobPath */ |
296 | + ")"; /* finish tuple */ |
297 | + |
298 | + return retval; |
299 | + }) + |
300 | + "]") |
301 | + .c_str(), |
302 | + &error); |
303 | + throwError(error); |
304 | + |
305 | + dbus_test_dbus_mock_object_add_method( |
306 | + mock, managerobj, "GetUnit", G_VARIANT_TYPE_STRING, G_VARIANT_TYPE_OBJECT_PATH, /* ret type */ |
307 | + ("ret = '/'\n" + std::accumulate(instances.begin(), instances.end(), std::string{}, |
308 | + [](const std::string accum, const Instance& inst) { |
309 | + std::string retval = accum; |
310 | + |
311 | + retval += "if args[0] == '" + instanceName(inst) + "':\n"; |
312 | + retval += "\tret = '" + instancePath(inst) + "'\n"; |
313 | + |
314 | + return retval; |
315 | + })) |
316 | + .c_str(), |
317 | + &error); |
318 | + throwError(error); |
319 | + |
320 | + dbus_test_dbus_mock_object_add_method( |
321 | + mock, managerobj, "StopUnit", G_VARIANT_TYPE("(ss)"), G_VARIANT_TYPE_OBJECT_PATH, /* ret type */ |
322 | + std::accumulate(instances.begin(), instances.end(), std::string{}, |
323 | + [](const std::string accum, const Instance& inst) { |
324 | + std::string retval = accum; |
325 | + |
326 | + retval += "if args[0] == '" + instanceName(inst) + "':\n"; |
327 | + retval += "\tret = '" + instancePath(inst) + "'\n"; |
328 | + |
329 | + return retval; |
330 | + }) |
331 | + .c_str(), |
332 | + &error); |
333 | + throwError(error); |
334 | + |
335 | + dbus_test_dbus_mock_object_add_method( |
336 | + mock, managerobj, "StartTransientUnit", G_VARIANT_TYPE("(ssa(sv)a(sa(sv)))"), |
337 | + G_VARIANT_TYPE_OBJECT_PATH, /* ret type */ |
338 | + std::accumulate(instances.begin(), instances.end(), std::string{"ret = '/'\n"}, |
339 | + [](const std::string accum, const Instance& inst) { |
340 | + std::string retval = accum; |
341 | + |
342 | + retval += "if args[0] == '" + instanceName(inst) + "':\n"; |
343 | + retval += "\traise dbus.exceptions.DBusException('Already running app" + |
344 | + instanceName(inst) + "', name='org.freedesktop.systemd1.UnitExists')\n"; |
345 | + |
346 | + return retval; |
347 | + }) |
348 | + .c_str(), |
349 | + &error); |
350 | + throwError(error); |
351 | + |
352 | + dbus_test_dbus_mock_object_add_method(mock, managerobj, "ResetFailedUnit", G_VARIANT_TYPE_STRING, |
353 | + nullptr, /* ret type */ |
354 | + "", &error); |
355 | + throwError(error); |
356 | + |
357 | + for (auto& instance : instances) |
358 | + { |
359 | + auto obj = dbus_test_dbus_mock_get_object(mock, instancePath(instance).c_str(), |
360 | + "org.freedesktop.systemd1.Service", &error); |
361 | + throwError(error); |
362 | + dbus_test_dbus_mock_object_add_property(mock, obj, "MainPID", G_VARIANT_TYPE_UINT32, |
363 | + g_variant_new_uint32(instance.primaryPid), &error); |
364 | + throwError(error); |
365 | + dbus_test_dbus_mock_object_add_property(mock, obj, "Result", G_VARIANT_TYPE_STRING, |
366 | + g_variant_new_string("success"), &error); |
367 | + throwError(error); |
368 | + |
369 | + /* Control Group */ |
370 | + auto dir = g_build_filename(controlGroupPath.c_str(), instancePath(instance).c_str(), nullptr); |
371 | + auto tasks = g_build_filename(dir, "tasks", nullptr); |
372 | + |
373 | + g_mkdir_with_parents(dir, 0777); |
374 | + |
375 | + g_file_set_contents(tasks, |
376 | + std::accumulate(instance.pids.begin(), instance.pids.end(), std::string{}, |
377 | + [](const std::string& accum, pid_t pid) { |
378 | + if (accum.empty()) |
379 | + { |
380 | + return std::to_string(pid); |
381 | + } |
382 | + else |
383 | + { |
384 | + return accum + "\n" + std::to_string(pid); |
385 | + } |
386 | + }) |
387 | + .c_str(), |
388 | + -1, &error); |
389 | + throwError(error); |
390 | + |
391 | + g_free(tasks); |
392 | + g_free(dir); |
393 | + |
394 | + dbus_test_dbus_mock_object_add_property(mock, obj, "ControlGroup", G_VARIANT_TYPE_STRING, |
395 | + g_variant_new_string(instancePath(instance).c_str()), nullptr); |
396 | + |
397 | + insts.emplace_back(std::make_pair(instance, obj)); |
398 | + } |
399 | + } |
400 | + |
401 | + ~SystemdMock() |
402 | + { |
403 | + g_debug("Destroying the Systemd Mock"); |
404 | + g_clear_object(&mock); |
405 | + } |
406 | + |
407 | + static std::string dbusSafe(const std::string& input) |
408 | + { |
409 | + std::string output = input; |
410 | + std::transform(output.begin(), output.end(), output.begin(), [](char in) { |
411 | + if (std::isalpha(in) || std::isdigit(in)) |
412 | + { |
413 | + return in; |
414 | + } |
415 | + else |
416 | + { |
417 | + return '_'; |
418 | + } |
419 | + |
420 | + }); |
421 | + return output; |
422 | + } |
423 | + |
424 | + static std::string instancePath(const Instance& inst) |
425 | + { |
426 | + std::string retval = std::string{"/"} + dbusSafe(inst.job) + "/" + dbusSafe(inst.appid); |
427 | + |
428 | + if (!inst.instanceid.empty()) |
429 | + { |
430 | + retval += "/" + dbusSafe(inst.instanceid); |
431 | + } |
432 | + |
433 | + return retval; |
434 | + } |
435 | + |
436 | + static std::string instanceName(const Instance& inst) |
437 | + { |
438 | + return std::string{"ubuntu-app-launch--"} + inst.job + "--" + inst.appid + "--" + inst.instanceid + ".service"; |
439 | + } |
440 | + |
441 | + operator std::shared_ptr<DbusTestTask>() |
442 | + { |
443 | + std::shared_ptr<DbusTestTask> retval(DBUS_TEST_TASK(g_object_ref(mock)), |
444 | + [](DbusTestTask* task) { g_clear_object(&task); }); |
445 | + return retval; |
446 | + } |
447 | + |
448 | + operator DbusTestTask*() |
449 | + { |
450 | + return DBUS_TEST_TASK(mock); |
451 | + } |
452 | + |
453 | + operator DbusTestProcess*() |
454 | + { |
455 | + return DBUS_TEST_PROCESS(mock); |
456 | + } |
457 | + |
458 | + operator DbusTestDbusMock*() |
459 | + { |
460 | + return mock; |
461 | + } |
462 | + |
463 | + unsigned int subscribeCallsCnt() |
464 | + { |
465 | + guint len = 0; |
466 | + GError* error = nullptr; |
467 | + |
468 | + dbus_test_dbus_mock_object_get_method_calls(mock, /* mock */ |
469 | + managerobj, /* manager */ |
470 | + "Subscribe", /* function */ |
471 | + &len, /* number */ |
472 | + &error /* error */ |
473 | + ); |
474 | + |
475 | + if (error != nullptr) |
476 | + { |
477 | + g_warning("Unable to get 'Subscribe' calls from systemd mock: %s", error->message); |
478 | + g_error_free(error); |
479 | + throw std::runtime_error{"Mock disfunctional"}; |
480 | + } |
481 | + |
482 | + return len; |
483 | + } |
484 | + |
485 | + unsigned int listCallsCnt() |
486 | + { |
487 | + guint len = 0; |
488 | + GError* error = nullptr; |
489 | + |
490 | + dbus_test_dbus_mock_object_get_method_calls(mock, /* mock */ |
491 | + managerobj, /* manager */ |
492 | + "ListUnits", /* function */ |
493 | + &len, /* number */ |
494 | + &error /* error */ |
495 | + ); |
496 | + |
497 | + if (error != nullptr) |
498 | + { |
499 | + g_warning("Unable to get 'Subscribe' calls from systemd mock: %s", error->message); |
500 | + g_error_free(error); |
501 | + throw std::runtime_error{"Mock disfunctional"}; |
502 | + } |
503 | + |
504 | + return len; |
505 | + } |
506 | + |
507 | + std::list<std::string> stopCalls() |
508 | + { |
509 | + guint len = 0; |
510 | + GError* error = nullptr; |
511 | + |
512 | + auto calls = dbus_test_dbus_mock_object_get_method_calls(mock, /* mock */ |
513 | + managerobj, /* manager */ |
514 | + "StopUnit", /* function */ |
515 | + &len, /* number */ |
516 | + &error /* error */ |
517 | + ); |
518 | + |
519 | + if (error != nullptr) |
520 | + { |
521 | + g_warning("Unable to get 'StopUnit' calls from systemd mock: %s", error->message); |
522 | + g_error_free(error); |
523 | + throw std::runtime_error{"Mock disfunctional"}; |
524 | + } |
525 | + |
526 | + std::list<std::string> retval; |
527 | + |
528 | + for (unsigned int i = 0; i < len; i++) |
529 | + { |
530 | + auto& call = calls[i]; |
531 | + gchar* name = nullptr; |
532 | + gchar* inst = nullptr; |
533 | + |
534 | + g_variant_get(call.params, "(&s&s)", &name, &inst); |
535 | + |
536 | + if (name == nullptr) |
537 | + { |
538 | + g_warning("Invalid 'name' on 'StopUnit' call"); |
539 | + continue; |
540 | + } |
541 | + |
542 | + retval.emplace_back(name); |
543 | + } |
544 | + |
545 | + return retval; |
546 | + } |
547 | + |
548 | + struct TransientUnit |
549 | + { |
550 | + std::string name; |
551 | + std::set<std::string> environment; |
552 | + std::string execpath; |
553 | + std::list<std::string> execline; |
554 | + }; |
555 | + |
556 | + std::list<TransientUnit> unitCalls() |
557 | + { |
558 | + guint len = 0; |
559 | + GError* error = nullptr; |
560 | + |
561 | + auto calls = dbus_test_dbus_mock_object_get_method_calls(mock, /* mock */ |
562 | + managerobj, /* manager */ |
563 | + "StartTransientUnit", /* function */ |
564 | + &len, /* number */ |
565 | + &error /* error */ |
566 | + ); |
567 | + |
568 | + if (error != nullptr) |
569 | + { |
570 | + g_warning("Unable to get 'StartTransientUnit' calls from systemd mock: %s", error->message); |
571 | + g_error_free(error); |
572 | + throw std::runtime_error{"Mock disfunctional"}; |
573 | + } |
574 | + |
575 | + std::list<TransientUnit> retval; |
576 | + |
577 | + for (unsigned int i = 0; i < len; i++) |
578 | + { |
579 | + auto& call = calls[i]; |
580 | + gchar* name = nullptr; |
581 | + |
582 | + g_variant_get_child(call.params, 0, "&s", &name); |
583 | + |
584 | + if (name == nullptr) |
585 | + { |
586 | + g_warning("Invalid 'name' on 'StartTransientUnit' call"); |
587 | + continue; |
588 | + } |
589 | + |
590 | + TransientUnit unit; |
591 | + unit.name = name; |
592 | + |
593 | + auto paramarray = g_variant_get_child_value(call.params, 2); |
594 | + gchar* ckey; |
595 | + GVariant* var; |
596 | + GVariantIter iter; |
597 | + g_variant_iter_init(&iter, paramarray); |
598 | + while (g_variant_iter_loop(&iter, "(sv)", &ckey, &var)) |
599 | + { |
600 | + g_debug("Looking at parameter: %s", ckey); |
601 | + std::string key{ckey}; |
602 | + |
603 | + if (key == "Environment") |
604 | + { |
605 | + GVariantIter array; |
606 | + gchar* envvar; |
607 | + g_variant_iter_init(&array, var); |
608 | + |
609 | + while (g_variant_iter_loop(&array, "&s", &envvar)) |
610 | + { |
611 | + unit.environment.emplace(envvar); |
612 | + } |
613 | + } |
614 | + else if (key == "ExecStart") |
615 | + { |
616 | + /* a(sasb) */ |
617 | + if (g_variant_n_children(var) > 1) |
618 | + { |
619 | + g_warning("'ExecStart' has more than one entry, only processing the first"); |
620 | + } |
621 | + |
622 | + auto tuple = g_variant_get_child_value(var, 0); |
623 | + |
624 | + const gchar* cpath = nullptr; |
625 | + g_variant_get_child(tuple, 0, "&s", &cpath); |
626 | + |
627 | + if (cpath != nullptr) |
628 | + { |
629 | + unit.execpath = cpath; |
630 | + } |
631 | + else |
632 | + { |
633 | + g_warning("'ExecStart[0][0]' isn't a string?"); |
634 | + } |
635 | + |
636 | + auto vexecarray = g_variant_get_child_value(tuple, 1); |
637 | + GVariantIter execarray; |
638 | + g_variant_iter_init(&execarray, vexecarray); |
639 | + const gchar* execentry; |
640 | + |
641 | + while (g_variant_iter_loop(&execarray, "&s", &execentry)) |
642 | + { |
643 | + unit.execline.emplace_back(execentry); |
644 | + } |
645 | + |
646 | + g_clear_pointer(&vexecarray, g_variant_unref); |
647 | + g_clear_pointer(&tuple, g_variant_unref); |
648 | + } |
649 | + } |
650 | + g_variant_unref(paramarray); |
651 | + |
652 | + retval.emplace_back(unit); |
653 | + } |
654 | + |
655 | + return retval; |
656 | + } |
657 | + |
658 | + std::list<std::string> resetCalls() |
659 | + { |
660 | + guint len = 0; |
661 | + GError* error = nullptr; |
662 | + |
663 | + auto calls = dbus_test_dbus_mock_object_get_method_calls(mock, /* mock */ |
664 | + managerobj, /* manager */ |
665 | + "ResetFailedUnit", /* function */ |
666 | + &len, /* number */ |
667 | + &error /* error */ |
668 | + ); |
669 | + |
670 | + if (error != nullptr) |
671 | + { |
672 | + g_warning("Unable to get 'ResetFailedUnit' calls from systemd mock: %s", error->message); |
673 | + g_error_free(error); |
674 | + throw std::runtime_error{"Mock disfunctional"}; |
675 | + } |
676 | + |
677 | + std::list<std::string> retval; |
678 | + |
679 | + for (unsigned int i = 0; i < len; i++) |
680 | + { |
681 | + auto& call = calls[i]; |
682 | + gchar* name = nullptr; |
683 | + |
684 | + g_variant_get(call.params, "(&s)", &name); |
685 | + |
686 | + if (name == nullptr) |
687 | + { |
688 | + g_warning("Invalid 'name' on 'ResetFailedUnit' call"); |
689 | + continue; |
690 | + } |
691 | + |
692 | + retval.emplace_back(name); |
693 | + } |
694 | + |
695 | + return retval; |
696 | + } |
697 | + |
698 | + void managerClear() |
699 | + { |
700 | + GError* error = nullptr; |
701 | + |
702 | + dbus_test_dbus_mock_object_clear_method_calls(mock, /* mock */ |
703 | + managerobj, /* manager */ |
704 | + &error /* error */ |
705 | + ); |
706 | + |
707 | + if (error != nullptr) |
708 | + { |
709 | + g_warning("Unable to clear manager calls: %s", error->message); |
710 | + g_error_free(error); |
711 | + throw std::runtime_error{"Mock disfunctional"}; |
712 | + } |
713 | + } |
714 | + |
715 | + void managerEmitNew(const std::string& name, const std::string& path) |
716 | + { |
717 | + GError* error = nullptr; |
718 | + |
719 | + dbus_test_dbus_mock_object_emit_signal(mock, managerobj, "UnitNew", G_VARIANT_TYPE("(so)"), |
720 | + g_variant_new("(so)", name.c_str(), path.c_str()), &error); |
721 | + |
722 | + if (error != nullptr) |
723 | + { |
724 | + g_warning("Unable to emit 'UnitNew': %s", error->message); |
725 | + g_error_free(error); |
726 | + throw std::runtime_error{"Mock disfunctional"}; |
727 | + } |
728 | + } |
729 | + |
730 | + void managerEmitRemoved(const std::string& name, const std::string& path) |
731 | + { |
732 | + GError* error = nullptr; |
733 | + |
734 | + dbus_test_dbus_mock_object_emit_signal(mock, managerobj, "UnitRemoved", G_VARIANT_TYPE("(so)"), |
735 | + g_variant_new("(so)", name.c_str(), path.c_str()), &error); |
736 | + |
737 | + if (error != nullptr) |
738 | + { |
739 | + g_warning("Unable to emit 'UnitRemoved': %s", error->message); |
740 | + g_error_free(error); |
741 | + throw std::runtime_error{"Mock disfunctional"}; |
742 | + } |
743 | + } |
744 | + |
745 | + void managerEmitFailed(const Instance& inst, const std::string& reason = "fail") |
746 | + { |
747 | + auto instobj = |
748 | + std::find_if(insts.begin(), insts.end(), [inst](const std::pair<Instance, DbusTestDbusMockObject*>& item) { |
749 | + return item.first.job == inst.job && item.first.appid == inst.appid && |
750 | + item.first.instanceid == inst.instanceid; |
751 | + }); |
752 | + |
753 | + if (instobj == insts.end()) |
754 | + { |
755 | + throw std::runtime_error{"Unable to find instance"}; |
756 | + } |
757 | + |
758 | + GError* error = nullptr; |
759 | + dbus_test_dbus_mock_object_update_property(mock, instobj->second, "Result", |
760 | + g_variant_new_string(reason.c_str()), &error); |
761 | + |
762 | + if (error != nullptr) |
763 | + { |
764 | + g_warning("Unable to set result to 'fail': %s", error->message); |
765 | + g_error_free(error); |
766 | + throw std::runtime_error{"Mock disfunctional"}; |
767 | + } |
768 | + } |
769 | + |
770 | + std::function<DbusTestTaskState()> stateFunc() |
771 | + { |
772 | + return [this] { return dbus_test_task_get_state(DBUS_TEST_TASK(mock)); }; |
773 | + } |
774 | +}; |
775 | |
776 | === modified file 'tests/xdg-data/applications/foo-bar.desktop' |
777 | --- tests/xdg-data/applications/foo-bar.desktop 2016-08-15 16:56:02 +0000 |
778 | +++ tests/xdg-data/applications/foo-bar.desktop 2017-03-16 21:55:16 +0000 |
779 | @@ -3,3 +3,4 @@ |
780 | Exec=foo-bar |
781 | Type=Application |
782 | Icon=foo-bar.png |
783 | +X-Ubuntu-Single-Instance=true |
FAILED: Continuous integration, rev:114 /jenkins. canonical. com/unity- api-1/job/ lp-url- dispatcher- ci/53/ /jenkins. canonical. com/unity- api-1/job/ build/1798/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/1805 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 1581/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= zesty/1581/ console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 1581/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= zesty/1581/ console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 1581/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= zesty/1581/ 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-url- dispatcher- ci/53/rebuild
https:/