summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2015-01-26 20:10:39 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2015-02-03 16:20:01 +0000
commitcf35dad25ab0a3819454d4acb3ac8b10109bb840 (patch)
tree0dcc62ba0085462ed3919f049e98040913fc7031 /test
parent652a324fb6a1030b3525f8395bf5bc05ab50d3d7 (diff)
downloaddbus-cf35dad25ab0a3819454d4acb3ac8b10109bb840.tar.gz
Add a regression test for systemd activation
4.5 years after it was implemented, here is the regression test. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=57952 Reviewed-by: Philip Withnall
Diffstat (limited to 'test')
-rw-r--r--test/Makefile.am15
-rw-r--r--test/data/systemd-activation/com.example.SystemdActivatable1.service4
-rw-r--r--test/data/systemd-activation/com.example.SystemdActivatable2.service4
-rw-r--r--test/data/systemd-activation/com.example.SystemdActivatable3.service4
-rw-r--r--test/data/systemd-activation/org.freedesktop.systemd1.service3
-rw-r--r--test/data/valid-config-files/systemd-activation.conf.in11
-rw-r--r--test/sd-activation.c319
-rw-r--r--test/test-utils-glib.c3
8 files changed, 363 insertions, 0 deletions
diff --git a/test/Makefile.am b/test/Makefile.am
index 75e70d29..8b84c7d2 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -160,6 +160,7 @@ installable_tests += \
test-marshal \
test-refs \
test-relay \
+ test-sd-activation \
test-syntax \
test-syslog \
test-uid-permissions \
@@ -229,6 +230,15 @@ test_dbus_daemon_eavesdrop_LDADD = \
$(GLIB_LIBS) \
$(NULL)
+test_sd_activation_SOURCES = \
+ sd-activation.c \
+ $(NULL)
+test_sd_activation_CPPFLAGS = $(testutils_shared_if_possible_cppflags)
+test_sd_activation_LDADD = \
+ $(testutils_shared_if_possible_libs) \
+ $(GLIB_LIBS) \
+ $(NULL)
+
test_marshal_SOURCES = marshal.c
test_marshal_LDADD = \
$(top_builddir)/dbus/libdbus-1.la \
@@ -287,6 +297,7 @@ in_data = \
data/valid-config-files/finite-timeout.conf.in \
data/valid-config-files/incoming-limit.conf.in \
data/valid-config-files/multi-user.conf.in \
+ data/valid-config-files/systemd-activation.conf.in \
data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in \
data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.in \
data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoUser.service.in \
@@ -355,6 +366,10 @@ static_data = \
data/sha-1/bit-messages.sha1 \
data/sha-1/byte-hashes.sha1 \
data/sha-1/byte-messages.sha1 \
+ data/systemd-activation/com.example.SystemdActivatable1.service \
+ data/systemd-activation/com.example.SystemdActivatable2.service \
+ data/systemd-activation/com.example.SystemdActivatable3.service \
+ data/systemd-activation/org.freedesktop.systemd1.service \
data/valid-config-files/basic.conf \
data/valid-config-files/basic.d/basic.conf \
data/valid-config-files/entities.conf \
diff --git a/test/data/systemd-activation/com.example.SystemdActivatable1.service b/test/data/systemd-activation/com.example.SystemdActivatable1.service
new file mode 100644
index 00000000..f15f0386
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SystemdActivatable1.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=com.example.SystemdActivatable1
+Exec=/bin/false 1
+SystemdService=dbus-com.example.SystemdActivatable1.service
diff --git a/test/data/systemd-activation/com.example.SystemdActivatable2.service b/test/data/systemd-activation/com.example.SystemdActivatable2.service
new file mode 100644
index 00000000..dcedd734
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SystemdActivatable2.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=com.example.SystemdActivatable2
+Exec=/bin/false 2
+SystemdService=dbus-com.example.SystemdActivatable2.service
diff --git a/test/data/systemd-activation/com.example.SystemdActivatable3.service b/test/data/systemd-activation/com.example.SystemdActivatable3.service
new file mode 100644
index 00000000..f6f0559c
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SystemdActivatable3.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=com.example.SystemdActivatable3
+Exec=/bin/false 3
+SystemdService=dbus-com.example.SystemdActivatable3.service
diff --git a/test/data/systemd-activation/org.freedesktop.systemd1.service b/test/data/systemd-activation/org.freedesktop.systemd1.service
new file mode 100644
index 00000000..aea93113
--- /dev/null
+++ b/test/data/systemd-activation/org.freedesktop.systemd1.service
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.freedesktop.systemd1
+Exec=/bin/false
diff --git a/test/data/valid-config-files/systemd-activation.conf.in b/test/data/valid-config-files/systemd-activation.conf.in
new file mode 100644
index 00000000..bcd6416c
--- /dev/null
+++ b/test/data/valid-config-files/systemd-activation.conf.in
@@ -0,0 +1,11 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <listen>@TEST_LISTEN@</listen>
+ <servicedir>@DBUS_TEST_DATA@/systemd-activation</servicedir>
+ <policy context="default">
+ <allow send_destination="*"/>
+ <allow receive_sender="*"/>
+ <allow own="*"/>
+ </policy>
+</busconfig>
diff --git a/test/sd-activation.c b/test/sd-activation.c
new file mode 100644
index 00000000..14e4ae80
--- /dev/null
+++ b/test/sd-activation.c
@@ -0,0 +1,319 @@
+/* Unit tests for systemd activation.
+ *
+ * Copyright © 2010-2011 Nokia Corporation
+ * Copyright © 2015 Collabora Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "test-utils-glib.h"
+
+typedef struct {
+ TestMainContext *ctx;
+ DBusError e;
+ GError *ge;
+
+ gchar *address;
+ GPid daemon_pid;
+
+ DBusConnection *caller;
+ const char *caller_name;
+ DBusConnection *systemd;
+ const char *systemd_name;
+ DBusMessage *systemd_message;
+ DBusConnection *activated;
+ const char *activated_name;
+ DBusMessage *activated_message;
+} Fixture;
+
+/* this is a macro so it gets the right line number */
+#define assert_signal(m, \
+ sender, path, iface, member, signature, \
+ destination) \
+do { \
+ g_assert_cmpstr (dbus_message_type_to_string (dbus_message_get_type (m)), \
+ ==, dbus_message_type_to_string (DBUS_MESSAGE_TYPE_SIGNAL)); \
+ g_assert_cmpstr (dbus_message_get_sender (m), ==, sender); \
+ g_assert_cmpstr (dbus_message_get_destination (m), ==, destination); \
+ g_assert_cmpstr (dbus_message_get_path (m), ==, path); \
+ g_assert_cmpstr (dbus_message_get_interface (m), ==, iface); \
+ g_assert_cmpstr (dbus_message_get_member (m), ==, member); \
+ g_assert_cmpstr (dbus_message_get_signature (m), ==, signature); \
+ g_assert_cmpint (dbus_message_get_serial (m), !=, 0); \
+ g_assert_cmpint (dbus_message_get_reply_serial (m), ==, 0); \
+} while (0)
+
+static DBusHandlerResult
+systemd_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ Fixture *f = user_data;
+
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+ "NameAcquired") ||
+ dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+ "NameLost"))
+ {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ g_assert (f->systemd_message == NULL);
+ f->systemd_message = dbus_message_ref (message);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult
+activated_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ Fixture *f = user_data;
+
+ if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+ "NameAcquired") ||
+ dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+ "NameLost"))
+ {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ g_assert (f->activated_message == NULL);
+ f->activated_message = dbus_message_ref (message);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+setup (Fixture *f,
+ gconstpointer context G_GNUC_UNUSED)
+{
+ f->ctx = test_main_context_get ();
+
+ f->ge = NULL;
+ dbus_error_init (&f->e);
+
+ f->address = test_get_dbus_daemon (
+ "valid-config-files/systemd-activation.conf",
+ TEST_USER_ME, &f->daemon_pid);
+
+ if (f->address == NULL)
+ return;
+
+ f->caller = test_connect_to_bus (f->ctx, f->address);
+ f->caller_name = dbus_bus_get_unique_name (f->caller);
+}
+
+static void
+take_well_known_name (Fixture *f,
+ DBusConnection *connection,
+ const char *name)
+{
+ int ret;
+
+ ret = dbus_bus_request_name (connection, name,
+ DBUS_NAME_FLAG_DO_NOT_QUEUE, &f->e);
+ test_assert_no_error (&f->e);
+ g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+}
+
+static void
+test_activation (Fixture *f,
+ gconstpointer context)
+{
+ DBusMessage *m;
+
+ if (f->address == NULL)
+ return;
+
+ /* The sender sends a message to an activatable service. */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal1");
+ if (!dbus_message_set_destination (m, "com.example.SystemdActivatable1"))
+ g_error ("OOM");
+ dbus_connection_send (f->caller, m, NULL);
+ dbus_message_unref (m);
+
+ /* The fake systemd connects to the bus. */
+ f->systemd = test_connect_to_bus (f->ctx, f->address);
+ if (!dbus_connection_add_filter (f->systemd, systemd_filter, f, NULL))
+ g_error ("OOM");
+ f->systemd_name = dbus_bus_get_unique_name (f->systemd);
+ take_well_known_name (f, f->systemd, "org.freedesktop.systemd1");
+
+ /* It gets its activation request. */
+ while (f->systemd_message == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = f->systemd_message;
+ f->systemd_message = NULL;
+ assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
+ "org.freedesktop.systemd1.Activator", "ActivationRequest", "s",
+ "org.freedesktop.systemd1");
+ dbus_message_unref (m);
+
+ /* systemd starts the activatable service. */
+ f->activated = test_connect_to_bus (f->ctx, f->address);
+ if (!dbus_connection_add_filter (f->activated, activated_filter,
+ f, NULL))
+ g_error ("OOM");
+ f->activated_name = dbus_bus_get_unique_name (f->activated);
+ take_well_known_name (f, f->activated, "com.example.SystemdActivatable1");
+
+ /* The message is delivered to the activatable service. */
+ while (f->activated_message == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = f->activated_message;
+ f->activated_message = NULL;
+ assert_signal (m, f->caller_name, "/foo",
+ "com.example.bar", "UnicastSignal1", "",
+ "com.example.SystemdActivatable1");
+ dbus_message_unref (m);
+
+ /* The sender sends a message to a different activatable service. */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal2");
+ if (!dbus_message_set_destination (m, "com.example.SystemdActivatable2"))
+ g_error ("OOM");
+ dbus_connection_send (f->caller, m, NULL);
+ dbus_message_unref (m);
+
+ /* This time systemd is already ready for it. */
+ while (f->systemd_message == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = f->systemd_message;
+ f->systemd_message = NULL;
+ assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
+ "org.freedesktop.systemd1.Activator", "ActivationRequest", "s",
+ "org.freedesktop.systemd1");
+ dbus_message_unref (m);
+
+ /* The activatable service takes its name. Here I'm faking it by using
+ * an existing connection; in real life it would be yet another
+ * connection. */
+ take_well_known_name (f, f->activated, "com.example.SystemdActivatable2");
+
+ /* The message is delivered to the activatable service. */
+ while (f->activated_message == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = f->activated_message;
+ f->activated_message = NULL;
+ assert_signal (m, f->caller_name, "/foo",
+ "com.example.bar", "UnicastSignal2", "",
+ "com.example.SystemdActivatable2");
+ dbus_message_unref (m);
+
+ /* A third activation. */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal3");
+ if (!dbus_message_set_destination (m, "com.example.SystemdActivatable3"))
+ g_error ("OOM");
+ dbus_connection_send (f->caller, m, NULL);
+ dbus_message_unref (m);
+
+ while (f->systemd_message == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = f->systemd_message;
+ f->systemd_message = NULL;
+ assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
+ "org.freedesktop.systemd1.Activator", "ActivationRequest", "s",
+ "org.freedesktop.systemd1");
+ dbus_message_unref (m);
+
+ /* This time activation fails */
+ m = dbus_message_new_signal ("/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Activator", "ActivationFailure");
+
+ do
+ {
+ const char *unit = "dbus-com.example.SystemdActivatable3.service";
+ const char *error_name = "com.example.Nope";
+ const char *error_message = "Computer says no";
+
+ if (!dbus_message_append_args (m,
+ DBUS_TYPE_STRING, &unit,
+ DBUS_TYPE_STRING, &error_name,
+ DBUS_TYPE_STRING, &error_message,
+ DBUS_TYPE_INVALID))
+ g_error ("OOM");
+ }
+ while (0);
+
+ if (!dbus_message_set_destination (m, "org.freedesktop.DBus"))
+ g_error ("OOM");
+ dbus_connection_send (f->systemd, m, NULL);
+ dbus_message_unref (m);
+}
+
+static void
+teardown (Fixture *f,
+ gconstpointer context G_GNUC_UNUSED)
+{
+ dbus_error_free (&f->e);
+ g_clear_error (&f->ge);
+
+ if (f->caller != NULL)
+ {
+ dbus_connection_close (f->caller);
+ dbus_connection_unref (f->caller);
+ f->caller = NULL;
+ }
+
+ if (f->systemd != NULL)
+ {
+ dbus_connection_remove_filter (f->systemd, systemd_filter, f);
+ dbus_connection_close (f->systemd);
+ dbus_connection_unref (f->systemd);
+ f->systemd = NULL;
+ }
+
+ if (f->activated != NULL)
+ {
+ dbus_connection_remove_filter (f->activated, activated_filter, f);
+ dbus_connection_close (f->activated);
+ dbus_connection_unref (f->activated);
+ f->activated = NULL;
+ }
+
+ test_kill_pid (f->daemon_pid);
+ g_spawn_close_pid (f->daemon_pid);
+ test_main_context_unref (f->ctx);
+ g_free (f->address);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+ g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
+
+ g_test_add ("/sd-activation", Fixture, NULL,
+ setup, test_activation, teardown);
+
+ return g_test_run ();
+}
diff --git a/test/test-utils-glib.c b/test/test-utils-glib.c
index e2ad5791..c9fb5c8a 100644
--- a/test/test-utils-glib.c
+++ b/test/test-utils-glib.c
@@ -100,6 +100,9 @@ spawn_dbus_daemon (const gchar *binary,
configuration,
"--nofork",
"--print-address=1", /* stdout */
+#ifdef DBUS_UNIX
+ "--systemd-activation",
+#endif
NULL
};
#ifdef DBUS_UNIX