2 * Copyright (C) 2013, 2014 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
21 #include "testutils.h"
23 #if defined(WITH_DBUS) && defined(__linux__)
25 # include <dbus/dbus.h>
27 # define LIBVIRT_VIRSYSTEMDPRIV_H_ALLOW
28 # include "virsystemdpriv.h"
30 # include "virsystemd.h"
34 # define VIR_FROM_THIS VIR_FROM_NONE
36 VIR_LOG_INIT("tests.systemdtest");
38 VIR_MOCK_WRAP_RET_ARGS(dbus_connection_send_with_reply_and_block
,
40 DBusConnection
*, connection
,
41 DBusMessage
*, message
,
42 int, timeout_milliseconds
,
45 DBusMessage
*reply
= NULL
;
46 const char *service
= dbus_message_get_destination(message
);
47 const char *member
= dbus_message_get_member(message
);
49 VIR_MOCK_REAL_INIT(dbus_connection_send_with_reply_and_block
);
51 if (STREQ(service
, "org.freedesktop.machine1")) {
52 if (getenv("FAIL_BAD_SERVICE")) {
53 dbus_set_error_const(error
,
54 "org.freedesktop.systemd.badthing",
55 "Something went wrong creating the machine");
57 reply
= dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN
);
59 if (STREQ(member
, "GetMachineByPID")) {
60 const char *object_path
= "/org/freedesktop/machine1/machine/qemu_2ddemo";
63 dbus_message_iter_init_append(reply
, &iter
);
64 if (!dbus_message_iter_append_basic(&iter
,
65 DBUS_TYPE_OBJECT_PATH
,
68 } else if (STREQ(member
, "Get")) {
69 const char *name
= "qemu-demo";
73 dbus_message_iter_init_append(reply
, &iter
);
74 dbus_message_iter_open_container(&iter
, DBUS_TYPE_VARIANT
,
77 if (!dbus_message_iter_append_basic(&sub
,
81 dbus_message_iter_close_container(&iter
, &sub
);
84 } else if (STREQ(service
, "org.freedesktop.login1")) {
85 char *supported
= getenv("RESULT_SUPPORT");
87 reply
= dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN
);
88 dbus_message_iter_init_append(reply
, &iter
);
90 if (!dbus_message_iter_append_basic(&iter
,
94 } else if (STREQ(service
, "org.freedesktop.DBus") &&
95 STREQ(member
, "ListActivatableNames")) {
96 const char *svc1
= "org.foo.bar.wizz";
97 const char *svc2
= "org.freedesktop.machine1";
98 const char *svc3
= "org.freedesktop.login1";
101 reply
= dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN
);
102 dbus_message_iter_init_append(reply
, &iter
);
103 dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
,
106 if (!dbus_message_iter_append_basic(&sub
,
110 if (!getenv("FAIL_NO_SERVICE") &&
111 !dbus_message_iter_append_basic(&sub
,
115 if (!getenv("FAIL_NO_SERVICE") &&
116 !dbus_message_iter_append_basic(&sub
,
120 dbus_message_iter_close_container(&iter
, &sub
);
121 } else if (STREQ(service
, "org.freedesktop.DBus") &&
122 STREQ(member
, "ListNames")) {
123 const char *svc1
= "org.foo.bar.wizz";
124 const char *svc2
= "org.freedesktop.systemd1";
125 const char *svc3
= "org.freedesktop.login1";
126 DBusMessageIter iter
;
128 reply
= dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN
);
129 dbus_message_iter_init_append(reply
, &iter
);
130 dbus_message_iter_open_container(&iter
, DBUS_TYPE_ARRAY
,
133 if (!dbus_message_iter_append_basic(&sub
,
137 if ((!getenv("FAIL_NO_SERVICE") && !getenv("FAIL_NOT_REGISTERED")) &&
138 !dbus_message_iter_append_basic(&sub
,
142 if ((!getenv("FAIL_NO_SERVICE") && !getenv("FAIL_NOT_REGISTERED")) &&
143 !dbus_message_iter_append_basic(&sub
,
147 dbus_message_iter_close_container(&iter
, &sub
);
149 reply
= dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN
);
155 virDBusMessageUnref(reply
);
160 static int testCreateContainer(const void *opaque ATTRIBUTE_UNUSED
)
162 unsigned char uuid
[VIR_UUID_BUFLEN
] = {
168 if (virSystemdCreateMachine("demo",
175 "highpriority.slice") < 0) {
176 fprintf(stderr
, "%s", "Failed to create LXC machine\n");
183 static int testTerminateContainer(const void *opaque ATTRIBUTE_UNUSED
)
185 if (virSystemdTerminateMachine("lxc-demo") < 0) {
186 fprintf(stderr
, "%s", "Failed to terminate LXC machine\n");
193 static int testCreateMachine(const void *opaque ATTRIBUTE_UNUSED
)
195 unsigned char uuid
[VIR_UUID_BUFLEN
] = {
201 if (virSystemdCreateMachine("demo",
209 fprintf(stderr
, "%s", "Failed to create KVM machine\n");
216 static int testTerminateMachine(const void *opaque ATTRIBUTE_UNUSED
)
218 if (virSystemdTerminateMachine("test-qemu-demo") < 0) {
219 fprintf(stderr
, "%s", "Failed to terminate KVM machine\n");
226 static int testCreateNoSystemd(const void *opaque ATTRIBUTE_UNUSED
)
228 unsigned char uuid
[VIR_UUID_BUFLEN
] = {
236 setenv("FAIL_NO_SERVICE", "1", 1);
238 if ((rv
= virSystemdCreateMachine("demo",
246 unsetenv("FAIL_NO_SERVICE");
247 fprintf(stderr
, "%s", "Unexpected create machine success\n");
250 unsetenv("FAIL_NO_SERVICE");
253 fprintf(stderr
, "%s", "Unexpected create machine error\n");
260 static int testCreateSystemdNotRunning(const void *opaque ATTRIBUTE_UNUSED
)
262 unsigned char uuid
[VIR_UUID_BUFLEN
] = {
270 setenv("FAIL_NOT_REGISTERED", "1", 1);
272 if ((rv
= virSystemdCreateMachine("demo",
280 unsetenv("FAIL_NOT_REGISTERED");
281 fprintf(stderr
, "%s", "Unexpected create machine success\n");
284 unsetenv("FAIL_NOT_REGISTERED");
287 fprintf(stderr
, "%s", "Unexpected create machine error\n");
294 static int testCreateBadSystemd(const void *opaque ATTRIBUTE_UNUSED
)
296 unsigned char uuid
[VIR_UUID_BUFLEN
] = {
304 setenv("FAIL_BAD_SERVICE", "1", 1);
306 if ((rv
= virSystemdCreateMachine("demo",
314 unsetenv("FAIL_BAD_SERVICE");
315 fprintf(stderr
, "%s", "Unexpected create machine success\n");
318 unsetenv("FAIL_BAD_SERVICE");
321 fprintf(stderr
, "%s", "Unexpected create machine error\n");
329 static int testCreateNetwork(const void *opaque ATTRIBUTE_UNUSED
)
331 unsigned char uuid
[VIR_UUID_BUFLEN
] = {
340 size_t nnicindexes
= ARRAY_CARDINALITY(nicindexes
);
341 if (virSystemdCreateMachine("demo",
347 nnicindexes
, nicindexes
,
348 "highpriority.slice") < 0) {
349 fprintf(stderr
, "%s", "Failed to create LXC machine\n");
358 testGetMachineName(const void *opaque ATTRIBUTE_UNUSED
)
360 char *tmp
= virSystemdGetMachineNameByPID(1234);
364 fprintf(stderr
, "%s", "Failed to create LXC machine\n");
368 if (STREQ(tmp
, "qemu-demo"))
376 struct testNameData
{
378 const char *expected
;
384 testScopeName(const void *opaque
)
386 const struct testNameData
*data
= opaque
;
390 if (!(actual
= virSystemdMakeScopeName(data
->name
, "lxc", data
->legacy
)))
393 if (STRNEQ(actual
, data
->expected
)) {
394 fprintf(stderr
, "Expected '%s' but got '%s'\n",
395 data
->expected
, actual
);
407 testMachineName(const void *opaque
)
409 const struct testNameData
*data
= opaque
;
413 if (!(actual
= virDomainGenerateMachineName("qemu", data
->id
,
417 if (STRNEQ(actual
, data
->expected
)) {
418 fprintf(stderr
, "Expected '%s' but got '%s'\n",
419 data
->expected
, actual
);
430 typedef int (*virSystemdCanHelper
)(bool * result
);
431 struct testPMSupportData
{
432 virSystemdCanHelper tested
;
435 static int testPMSupportHelper(const void *opaque
)
440 const char *results
[4] = {"yes", "no", "na", "challenge"};
441 int expected
[4] = {1, 0, 0, 1};
442 const struct testPMSupportData
*data
= opaque
;
444 for (i
= 0; i
< 4; i
++) {
445 setenv("RESULT_SUPPORT", results
[i
], 1);
446 if ((rv
= data
->tested(&result
)) < 0) {
447 fprintf(stderr
, "%s", "Unexpected canSuspend error\n");
451 if (result
!= expected
[i
]) {
452 fprintf(stderr
, "Unexpected result for answer '%s'\n", results
[i
]);
455 unsetenv("RESULT_SUPPORT");
460 unsetenv("RESULT_SUPPORT");
464 static int testPMSupportHelperNoSystemd(const void *opaque
)
468 const struct testPMSupportData
*data
= opaque
;
470 setenv("FAIL_NO_SERVICE", "1", 1);
472 if ((rv
= data
->tested(&result
)) == 0) {
473 unsetenv("FAIL_NO_SERVICE");
474 fprintf(stderr
, "%s", "Unexpected canSuspend success\n");
477 unsetenv("FAIL_NO_SERVICE");
480 fprintf(stderr
, "%s", "Unexpected canSuspend error\n");
487 static int testPMSupportSystemdNotRunning(const void *opaque
)
491 const struct testPMSupportData
*data
= opaque
;
493 setenv("FAIL_NOT_REGISTERED", "1", 1);
495 if ((rv
= data
->tested(&result
)) == 0) {
496 unsetenv("FAIL_NOT_REGISTERED");
497 fprintf(stderr
, "%s", "Unexpected canSuspend success\n");
500 unsetenv("FAIL_NOT_REGISTERED");
503 fprintf(stderr
, "%s", "Unexpected canSuspend error\n");
515 unsigned char uuid
[VIR_UUID_BUFLEN
];
517 /* The one we use in tests quite often */
518 if (virUUIDParse("c7a5fdbd-edaf-9455-926a-d65c16db1809", uuid
) < 0)
521 # define DO_TEST(_name, func) \
523 if (virTestRun(_name, func, NULL) < 0) \
525 if (virTestRun(_name "again ", func, NULL) < 0) \
527 virSystemdHasMachinedResetCachedValue(); \
530 DO_TEST("Test create container ", testCreateContainer
);
531 DO_TEST("Test terminate container ", testTerminateContainer
);
532 DO_TEST("Test create machine ", testCreateMachine
);
533 DO_TEST("Test terminate machine ", testTerminateMachine
);
534 DO_TEST("Test create no systemd ", testCreateNoSystemd
);
535 DO_TEST("Test create systemd not running ", testCreateSystemdNotRunning
);
536 DO_TEST("Test create bad systemd ", testCreateBadSystemd
);
537 DO_TEST("Test create with network ", testCreateNetwork
);
538 DO_TEST("Test getting machine name ", testGetMachineName
);
540 # define TEST_SCOPE(_name, unitname, _legacy) \
542 struct testNameData data = { \
543 .name = _name, .expected = unitname, .legacy = _legacy, \
545 if (virTestRun("Test scopename", testScopeName, &data) < 0) \
549 # define TEST_SCOPE_OLD(name, unitname) \
550 TEST_SCOPE(name, unitname, true)
551 # define TEST_SCOPE_NEW(name, unitname) \
552 TEST_SCOPE(name, unitname, false)
554 TEST_SCOPE_OLD("demo", "machine-lxc\\x2ddemo.scope");
555 TEST_SCOPE_OLD("demo-name", "machine-lxc\\x2ddemo\\x2dname.scope");
556 TEST_SCOPE_OLD("demo!name", "machine-lxc\\x2ddemo\\x21name.scope");
557 TEST_SCOPE_OLD(".demo", "machine-lxc\\x2d\\x2edemo.scope");
558 TEST_SCOPE_OLD("bull💩", "machine-lxc\\x2dbull\\xf0\\x9f\\x92\\xa9.scope");
560 TEST_SCOPE_NEW("qemu-3-demo", "machine-qemu\\x2d3\\x2ddemo.scope");
562 # define TEST_MACHINE(_name, _id, machinename) \
564 struct testNameData data = { \
565 .name = _name, .expected = machinename, .id = _id, \
567 if (virTestRun("Test scopename", testMachineName, &data) < 0) \
571 TEST_MACHINE("demo", 1, "qemu-1-demo");
572 TEST_MACHINE("demo-name", 2, "qemu-2-demo-name");
573 TEST_MACHINE("demo!name", 3, "qemu-3-demoname");
574 TEST_MACHINE(".demo", 4, "qemu-4-.demo");
575 TEST_MACHINE("bull\U0001f4a9", 5, "qemu-5-bull");
576 TEST_MACHINE("demo..name", 6, "qemu-6-demo.name");
577 TEST_MACHINE("12345678901234567890123456789012345678901234567890123456789", 7,
578 "qemu-7-123456789012345678901234567890123456789012345678901234567");
579 TEST_MACHINE("123456789012345678901234567890123456789012345678901234567890", 8,
580 "qemu-8-123456789012345678901234567890123456789012345678901234567");
582 # define TESTS_PM_SUPPORT_HELPER(name, function) \
584 struct testPMSupportData data = { \
587 if (virTestRun("Test " name " ", testPMSupportHelper, &data) < 0) \
589 if (virTestRun("Test " name " no systemd ", \
590 testPMSupportHelperNoSystemd, &data) < 0) \
592 if (virTestRun("Test systemd " name " not running ", \
593 testPMSupportSystemdNotRunning, &data) < 0) \
597 TESTS_PM_SUPPORT_HELPER("canSuspend", &virSystemdCanSuspend
);
598 TESTS_PM_SUPPORT_HELPER("canHibernate", &virSystemdCanHibernate
);
599 TESTS_PM_SUPPORT_HELPER("canHybridSleep", &virSystemdCanHybridSleep
);
601 return ret
== 0 ? EXIT_SUCCESS
: EXIT_FAILURE
;
604 VIR_TEST_MAIN_PRELOAD(mymain
, abs_builddir
"/.libs/virdbusmock.so")
606 #else /* ! (WITH_DBUS && __linux__) */
612 #endif /* ! WITH_DBUS */