2011-03-11 13:13:17 +00:00
|
|
|
/* Integration tests for the dbus-daemon
|
|
|
|
|
*
|
|
|
|
|
* Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
|
Translate Python-based tests to C
This simplifies bootstrapping: now you don't have to build dbus,
build dbus-python (with GLib), and use dbus-python to test dbus.
It also avoids test failures when using facilities like
AddressSanitizer. When libdbus is built with AddressSanitizer, but the
system copies of Python and dbus-python were not, dbus-python will exit
the Python interpreter on load, because libasan wasn't already
initialized. The simplest way to avoid this is to not use Python:
the scripts are not *that* hard to translate into C.
Both of these tests happen to be conditionally compiled for Unix only.
test_activation_forking() relies on code in TestSuiteForkingEchoService
that calls fork(), which can only work on Unix; meanwhile,
test_system_signals() tests the system bus configuration, which is
only relevant to Unix because we don't support using dbus-daemon as
a privilege boundary on Windows (and in any case D-Bus is not a Windows
OS feature, so the system bus cannot be used to communicate with OS
services like it can on most Linux systems).
This is also a partial solution to
<https://gitlab.freedesktop.org/dbus/dbus/issues/135>, by reducing the
size of name-test/.
For this to work, we need to build the test-service helper executable
even if embedded tests are disabled.
Signed-off-by: Simon McVittie <smcv@collabora.com>
2018-11-16 18:53:11 +00:00
|
|
|
* Copyright © 2008 Red Hat, Inc.
|
2011-06-10 18:23:52 +01:00
|
|
|
* Copyright © 2010-2011 Nokia Corporation
|
Translate Python-based tests to C
This simplifies bootstrapping: now you don't have to build dbus,
build dbus-python (with GLib), and use dbus-python to test dbus.
It also avoids test failures when using facilities like
AddressSanitizer. When libdbus is built with AddressSanitizer, but the
system copies of Python and dbus-python were not, dbus-python will exit
the Python interpreter on load, because libasan wasn't already
initialized. The simplest way to avoid this is to not use Python:
the scripts are not *that* hard to translate into C.
Both of these tests happen to be conditionally compiled for Unix only.
test_activation_forking() relies on code in TestSuiteForkingEchoService
that calls fork(), which can only work on Unix; meanwhile,
test_system_signals() tests the system bus configuration, which is
only relevant to Unix because we don't support using dbus-daemon as
a privilege boundary on Windows (and in any case D-Bus is not a Windows
OS feature, so the system bus cannot be used to communicate with OS
services like it can on most Linux systems).
This is also a partial solution to
<https://gitlab.freedesktop.org/dbus/dbus/issues/135>, by reducing the
size of name-test/.
For this to work, we need to build the test-service helper executable
even if embedded tests are disabled.
Signed-off-by: Simon McVittie <smcv@collabora.com>
2018-11-16 18:53:11 +00:00
|
|
|
* Copyright © 2015-2018 Collabora Ltd.
|
2011-03-11 13:13:17 +00:00
|
|
|
*
|
|
|
|
|
* 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>
|
|
|
|
|
|
2015-02-05 18:30:36 +00:00
|
|
|
#include <errno.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include <dbus/dbus.h>
|
|
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <glib/gstdio.h>
|
2016-08-16 18:27:43 +01:00
|
|
|
#include <gio/gio.h>
|
2015-02-05 18:30:36 +00:00
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
#include "bus/stats.h"
|
2015-01-26 19:02:59 +00:00
|
|
|
#include "test-utils-glib.h"
|
2011-03-11 13:13:17 +00:00
|
|
|
|
2015-02-11 13:19:43 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
|
2015-01-26 19:02:59 +00:00
|
|
|
#ifdef DBUS_UNIX
|
2018-02-20 11:45:39 +00:00
|
|
|
# include <pwd.h>
|
2011-03-11 13:13:17 +00:00
|
|
|
# include <unistd.h>
|
2019-03-25 23:01:26 +01:00
|
|
|
# include <stdlib.h>
|
|
|
|
|
# include <search.h>
|
2013-08-22 18:21:58 +01:00
|
|
|
# include <sys/types.h>
|
2016-08-16 18:27:43 +01:00
|
|
|
|
|
|
|
|
# ifdef HAVE_GIO_UNIX
|
|
|
|
|
/* The CMake build system doesn't know how to check for this yet */
|
|
|
|
|
# include <gio/gunixfdmessage.h>
|
|
|
|
|
# endif
|
2018-02-20 11:45:39 +00:00
|
|
|
|
|
|
|
|
# ifdef HAVE_SYS_RESOURCE_H
|
|
|
|
|
# include <sys/resource.h>
|
|
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
# ifdef HAVE_SYS_TIME_H
|
|
|
|
|
# include <sys/time.h>
|
|
|
|
|
# endif
|
2011-03-11 13:13:17 +00:00
|
|
|
#endif
|
|
|
|
|
|
2014-09-15 18:04:36 +01:00
|
|
|
/* Platforms where we know that credentials-passing passes both the
|
|
|
|
|
* uid and the pid. Please keep these in alphabetical order.
|
|
|
|
|
*
|
|
|
|
|
* These platforms should #error in _dbus_read_credentials_socket()
|
|
|
|
|
* if we didn't detect their flavour of credentials-passing, since that
|
|
|
|
|
* would be a regression.
|
|
|
|
|
*/
|
|
|
|
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
|
|
|
|
defined(__linux__) || \
|
2014-09-15 18:37:59 +01:00
|
|
|
defined(__NetBSD__) || \
|
2014-09-15 18:04:36 +01:00
|
|
|
defined(__OpenBSD__)
|
|
|
|
|
# define UNIX_USER_SHOULD_WORK
|
|
|
|
|
# define PID_SHOULD_WORK
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Platforms where we know that credentials-passing passes the
|
|
|
|
|
* uid, but not necessarily the pid. Again, alphabetical order please.
|
|
|
|
|
*
|
|
|
|
|
* These platforms should also #error in _dbus_read_credentials_socket()
|
|
|
|
|
* if we didn't detect their flavour of credentials-passing.
|
|
|
|
|
*/
|
2014-09-15 18:37:59 +01:00
|
|
|
#if 0 /* defined(__your_platform_here__) */
|
2014-09-15 18:04:36 +01:00
|
|
|
# define UNIX_USER_SHOULD_WORK
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
typedef struct {
|
2011-03-11 13:24:08 +00:00
|
|
|
gboolean skip;
|
|
|
|
|
|
Tests: allow dbus-glib to be replaced with use of libdbus-internal
We only use dbus-glib for its main loop; within dbus, DBusLoop is
available as an alternative, although it isn't thread-safe and
isn't public API.
For tests that otherwise only use libdbus public API, it's desirable to
be able to avoid DBusLoop, so we can run them against an installed
libdbus as an integration test. However, if we don't have dbus-glib,
we're going to have to use an in-tree main loop, which might as well
be DBusLoop.
The major disadvantage of using dbus-glib is that it isn't safe to
link both dbus-1 and dbus-internal at the same time. This is awkward
for a future test case that wants to use _dbus_getsid() in dbus-daemon.c,
but only on Windows (fd.o #54445). If we use the same API wrapper around
both dbus-glib and DBusLoop, we can compile that test against dbus-glib
or against DBusLoop, depending on the platform.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68852
Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
2013-09-02 16:32:31 +01:00
|
|
|
TestMainContext *ctx;
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
DBusError e;
|
|
|
|
|
GError *ge;
|
|
|
|
|
|
2011-08-05 13:55:09 +01:00
|
|
|
GPid daemon_pid;
|
2016-07-01 12:30:22 +01:00
|
|
|
gchar *address;
|
2011-03-11 13:13:17 +00:00
|
|
|
|
|
|
|
|
DBusConnection *left_conn;
|
|
|
|
|
|
|
|
|
|
DBusConnection *right_conn;
|
2016-07-01 13:02:04 +01:00
|
|
|
GQueue held_messages;
|
2011-03-11 13:13:17 +00:00
|
|
|
gboolean right_conn_echo;
|
2016-07-01 13:02:04 +01:00
|
|
|
gboolean right_conn_hold;
|
2014-10-29 14:10:48 +00:00
|
|
|
gboolean wait_forever_called;
|
Translate Python-based tests to C
This simplifies bootstrapping: now you don't have to build dbus,
build dbus-python (with GLib), and use dbus-python to test dbus.
It also avoids test failures when using facilities like
AddressSanitizer. When libdbus is built with AddressSanitizer, but the
system copies of Python and dbus-python were not, dbus-python will exit
the Python interpreter on load, because libasan wasn't already
initialized. The simplest way to avoid this is to not use Python:
the scripts are not *that* hard to translate into C.
Both of these tests happen to be conditionally compiled for Unix only.
test_activation_forking() relies on code in TestSuiteForkingEchoService
that calls fork(), which can only work on Unix; meanwhile,
test_system_signals() tests the system bus configuration, which is
only relevant to Unix because we don't support using dbus-daemon as
a privilege boundary on Windows (and in any case D-Bus is not a Windows
OS feature, so the system bus cannot be used to communicate with OS
services like it can on most Linux systems).
This is also a partial solution to
<https://gitlab.freedesktop.org/dbus/dbus/issues/135>, by reducing the
size of name-test/.
For this to work, we need to build the test-service helper executable
even if embedded tests are disabled.
Signed-off-by: Simon McVittie <smcv@collabora.com>
2018-11-16 18:53:11 +00:00
|
|
|
guint activation_forking_counter;
|
2015-02-05 18:30:36 +00:00
|
|
|
|
|
|
|
|
gchar *tmp_runtime_dir;
|
|
|
|
|
gchar *saved_runtime_dir;
|
2011-03-11 13:13:17 +00:00
|
|
|
} Fixture;
|
|
|
|
|
|
|
|
|
|
static DBusHandlerResult
|
|
|
|
|
echo_filter (DBusConnection *connection,
|
|
|
|
|
DBusMessage *message,
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
2014-10-29 14:10:48 +00:00
|
|
|
Fixture *f = user_data;
|
2011-03-11 13:13:17 +00:00
|
|
|
DBusMessage *reply;
|
|
|
|
|
|
|
|
|
|
if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
|
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
|
|
2014-10-29 14:10:48 +00:00
|
|
|
/* WaitForever() never replies, emulating a service that has got stuck */
|
|
|
|
|
if (dbus_message_is_method_call (message, "com.example", "WaitForever"))
|
|
|
|
|
{
|
|
|
|
|
f->wait_forever_called = TRUE;
|
|
|
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
reply = dbus_message_new_method_return (message);
|
|
|
|
|
|
|
|
|
|
if (reply == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (!dbus_connection_send (connection, reply, NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&reply);
|
2011-03-11 13:13:17 +00:00
|
|
|
|
|
|
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 13:02:04 +01:00
|
|
|
static DBusHandlerResult
|
|
|
|
|
hold_filter (DBusConnection *connection,
|
|
|
|
|
DBusMessage *message,
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
|
|
|
|
Fixture *f = user_data;
|
|
|
|
|
|
|
|
|
|
if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
|
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
|
|
|
|
|
|
g_queue_push_tail (&f->held_messages, dbus_message_ref (message));
|
|
|
|
|
|
|
|
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-11 13:24:08 +00:00
|
|
|
typedef struct {
|
|
|
|
|
const char *bug_ref;
|
|
|
|
|
guint min_messages;
|
|
|
|
|
const char *config_file;
|
2018-02-20 11:45:39 +00:00
|
|
|
TestUser user;
|
2015-02-05 18:30:36 +00:00
|
|
|
enum { SPECIFY_ADDRESS = 0, RELY_ON_DEFAULT } connect_mode;
|
2011-03-11 13:24:08 +00:00
|
|
|
} Config;
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
static void
|
|
|
|
|
setup (Fixture *f,
|
2011-03-11 13:24:08 +00:00
|
|
|
gconstpointer context)
|
2011-03-11 13:13:17 +00:00
|
|
|
{
|
2011-03-11 13:24:08 +00:00
|
|
|
const Config *config = context;
|
2011-03-11 13:13:17 +00:00
|
|
|
|
2017-09-27 13:14:39 +01:00
|
|
|
/* Some tests are fairly slow, so make the test timeout per-test */
|
2017-11-27 19:14:23 +00:00
|
|
|
test_timeout_reset (1);
|
2017-09-27 13:14:39 +01:00
|
|
|
|
Tests: allow dbus-glib to be replaced with use of libdbus-internal
We only use dbus-glib for its main loop; within dbus, DBusLoop is
available as an alternative, although it isn't thread-safe and
isn't public API.
For tests that otherwise only use libdbus public API, it's desirable to
be able to avoid DBusLoop, so we can run them against an installed
libdbus as an integration test. However, if we don't have dbus-glib,
we're going to have to use an in-tree main loop, which might as well
be DBusLoop.
The major disadvantage of using dbus-glib is that it isn't safe to
link both dbus-1 and dbus-internal at the same time. This is awkward
for a future test case that wants to use _dbus_getsid() in dbus-daemon.c,
but only on Windows (fd.o #54445). If we use the same API wrapper around
both dbus-glib and DBusLoop, we can compile that test against dbus-glib
or against DBusLoop, depending on the platform.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68852
Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
2013-09-02 16:32:31 +01:00
|
|
|
f->ctx = test_main_context_get ();
|
2011-03-11 13:13:17 +00:00
|
|
|
f->ge = NULL;
|
|
|
|
|
dbus_error_init (&f->e);
|
|
|
|
|
|
2015-02-05 18:30:36 +00:00
|
|
|
if (config != NULL && config->connect_mode == RELY_ON_DEFAULT)
|
|
|
|
|
{
|
|
|
|
|
/* this is chosen to be something needing escaping */
|
|
|
|
|
f->tmp_runtime_dir = g_dir_make_tmp ("dbus=daemon=test.XXXXXX", &f->ge);
|
|
|
|
|
g_assert_no_error (f->ge);
|
|
|
|
|
|
|
|
|
|
/* we're relying on being single-threaded for this to be safe */
|
|
|
|
|
f->saved_runtime_dir = g_strdup (g_getenv ("XDG_RUNTIME_DIR"));
|
|
|
|
|
g_setenv ("XDG_RUNTIME_DIR", f->tmp_runtime_dir, TRUE);
|
2017-07-05 15:30:05 +01:00
|
|
|
g_unsetenv ("DBUS_SESSION_BUS_ADDRESS");
|
2015-02-05 18:30:36 +00:00
|
|
|
}
|
|
|
|
|
|
2016-07-01 12:30:22 +01:00
|
|
|
f->address = test_get_dbus_daemon (config ? config->config_file : NULL,
|
2018-02-20 11:45:39 +00:00
|
|
|
config ? config->user : TEST_USER_ME,
|
|
|
|
|
NULL, &f->daemon_pid);
|
2011-03-11 13:24:08 +00:00
|
|
|
|
2016-07-01 12:30:22 +01:00
|
|
|
if (f->address == NULL)
|
2013-09-02 16:36:46 +01:00
|
|
|
{
|
2015-01-26 19:02:59 +00:00
|
|
|
f->skip = TRUE;
|
|
|
|
|
return;
|
2013-09-02 16:36:46 +01:00
|
|
|
}
|
2011-03-11 13:13:17 +00:00
|
|
|
|
2016-07-01 12:30:22 +01:00
|
|
|
f->left_conn = test_connect_to_bus (f->ctx, f->address);
|
2015-02-05 18:30:36 +00:00
|
|
|
|
|
|
|
|
if (config != NULL && config->connect_mode == RELY_ON_DEFAULT)
|
|
|
|
|
{
|
|
|
|
|
/* use the default bus for the echo service ("right"), to check that
|
|
|
|
|
* it ends up on the same bus as the client ("left") */
|
|
|
|
|
f->right_conn = dbus_bus_get_private (DBUS_BUS_SESSION, &f->e);
|
|
|
|
|
test_assert_no_error (&f->e);
|
|
|
|
|
|
2017-11-27 19:26:03 +00:00
|
|
|
test_connection_setup (f->ctx, f->right_conn);
|
2015-02-05 18:30:36 +00:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-07-01 12:30:22 +01:00
|
|
|
f->right_conn = test_connect_to_bus (f->ctx, f->address);
|
2015-02-05 18:30:36 +00:00
|
|
|
}
|
2011-03-11 13:13:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_echo_filter (Fixture *f)
|
|
|
|
|
{
|
2014-10-29 14:10:48 +00:00
|
|
|
if (!dbus_connection_add_filter (f->right_conn, echo_filter, f, NULL))
|
2011-03-11 13:13:17 +00:00
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
f->right_conn_echo = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 13:02:04 +01:00
|
|
|
static void
|
|
|
|
|
add_hold_filter (Fixture *f)
|
|
|
|
|
{
|
|
|
|
|
if (!dbus_connection_add_filter (f->right_conn, hold_filter, f, NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
f->right_conn_hold = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
static void
|
|
|
|
|
pc_count (DBusPendingCall *pc,
|
|
|
|
|
void *data)
|
|
|
|
|
{
|
|
|
|
|
guint *received_p = data;
|
|
|
|
|
|
|
|
|
|
(*received_p)++;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 13:02:04 +01:00
|
|
|
static void
|
|
|
|
|
pc_enqueue (DBusPendingCall *pc,
|
|
|
|
|
void *data)
|
|
|
|
|
{
|
|
|
|
|
GQueue *q = data;
|
|
|
|
|
DBusMessage *m = dbus_pending_call_steal_reply (pc);
|
|
|
|
|
|
|
|
|
|
g_test_message ("message of type %d", dbus_message_get_type (m));
|
|
|
|
|
g_queue_push_tail (q, m);
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
static void
|
|
|
|
|
test_echo (Fixture *f,
|
2011-03-11 13:24:08 +00:00
|
|
|
gconstpointer context)
|
2011-03-11 13:13:17 +00:00
|
|
|
{
|
2011-03-11 13:24:08 +00:00
|
|
|
const Config *config = context;
|
2011-03-11 13:13:17 +00:00
|
|
|
guint count = 2000;
|
|
|
|
|
guint sent;
|
|
|
|
|
guint received = 0;
|
|
|
|
|
double elapsed;
|
|
|
|
|
|
2011-03-11 13:24:08 +00:00
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (config != NULL && config->bug_ref != NULL)
|
|
|
|
|
g_test_bug (config->bug_ref);
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
if (g_test_perf ())
|
|
|
|
|
count = 100000;
|
|
|
|
|
|
2011-03-11 13:24:08 +00:00
|
|
|
if (config != NULL)
|
|
|
|
|
count = MAX (config->min_messages, count);
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
add_echo_filter (f);
|
|
|
|
|
|
|
|
|
|
g_test_timer_start ();
|
|
|
|
|
|
|
|
|
|
for (sent = 0; sent < count; sent++)
|
|
|
|
|
{
|
|
|
|
|
DBusMessage *m = dbus_message_new_method_call (
|
|
|
|
|
dbus_bus_get_unique_name (f->right_conn), "/",
|
|
|
|
|
"com.example", "Spam");
|
|
|
|
|
DBusPendingCall *pc;
|
|
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2011-06-10 17:41:04 +01:00
|
|
|
if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
|
|
|
|
|
DBUS_TIMEOUT_INFINITE) ||
|
|
|
|
|
pc == NULL)
|
2011-03-11 13:13:17 +00:00
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (dbus_pending_call_get_completed (pc))
|
|
|
|
|
pc_count (pc, &received);
|
|
|
|
|
else if (!dbus_pending_call_set_notify (pc, pc_count, &received,
|
|
|
|
|
NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_pending_call (&pc);
|
|
|
|
|
dbus_clear_message (&m);
|
2011-03-11 13:13:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (received < count)
|
Tests: allow dbus-glib to be replaced with use of libdbus-internal
We only use dbus-glib for its main loop; within dbus, DBusLoop is
available as an alternative, although it isn't thread-safe and
isn't public API.
For tests that otherwise only use libdbus public API, it's desirable to
be able to avoid DBusLoop, so we can run them against an installed
libdbus as an integration test. However, if we don't have dbus-glib,
we're going to have to use an in-tree main loop, which might as well
be DBusLoop.
The major disadvantage of using dbus-glib is that it isn't safe to
link both dbus-1 and dbus-internal at the same time. This is awkward
for a future test case that wants to use _dbus_getsid() in dbus-daemon.c,
but only on Windows (fd.o #54445). If we use the same API wrapper around
both dbus-glib and DBusLoop, we can compile that test against dbus-glib
or against DBusLoop, depending on the platform.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68852
Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
2013-09-02 16:32:31 +01:00
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
2011-03-11 13:13:17 +00:00
|
|
|
|
|
|
|
|
elapsed = g_test_timer_elapsed ();
|
|
|
|
|
|
|
|
|
|
g_test_maximized_result (count / elapsed, "%u messages / %f seconds",
|
|
|
|
|
count, elapsed);
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-29 14:10:48 +00:00
|
|
|
static void
|
|
|
|
|
test_no_reply (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
const Config *config = context;
|
|
|
|
|
DBusMessage *m;
|
|
|
|
|
DBusPendingCall *pc;
|
|
|
|
|
DBusMessage *reply = NULL;
|
|
|
|
|
enum { TIMEOUT, DISCONNECT } mode;
|
|
|
|
|
gboolean ok;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_test_bug ("76112");
|
|
|
|
|
|
|
|
|
|
if (config != NULL && config->config_file != NULL)
|
|
|
|
|
mode = TIMEOUT;
|
|
|
|
|
else
|
|
|
|
|
mode = DISCONNECT;
|
|
|
|
|
|
|
|
|
|
m = dbus_message_new_method_call (
|
|
|
|
|
dbus_bus_get_unique_name (f->right_conn), "/",
|
|
|
|
|
"com.example", "WaitForever");
|
|
|
|
|
|
|
|
|
|
add_echo_filter (f);
|
|
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
/* Not using test_main_context_call_and_wait() here because we need to
|
|
|
|
|
* do things with the right connection as a side-effect */
|
2014-10-29 14:10:48 +00:00
|
|
|
if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
|
|
|
|
|
DBUS_TIMEOUT_INFINITE) ||
|
|
|
|
|
pc == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (dbus_pending_call_get_completed (pc))
|
2015-01-26 19:02:59 +00:00
|
|
|
test_pending_call_store_reply (pc, &reply);
|
|
|
|
|
else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
|
|
|
|
|
&reply, NULL))
|
2014-10-29 14:10:48 +00:00
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_pending_call (&pc);
|
|
|
|
|
dbus_clear_message (&m);
|
2014-10-29 14:10:48 +00:00
|
|
|
|
|
|
|
|
if (mode == DISCONNECT)
|
|
|
|
|
{
|
|
|
|
|
while (!f->wait_forever_called)
|
|
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
|
|
|
|
|
|
|
|
|
dbus_connection_remove_filter (f->right_conn, echo_filter, f);
|
2018-07-12 12:51:38 +01:00
|
|
|
test_connection_shutdown (f->ctx, f->right_conn);
|
2014-10-29 14:10:48 +00:00
|
|
|
dbus_connection_close (f->right_conn);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_connection (&f->right_conn);
|
2014-10-29 14:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (reply == NULL)
|
|
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
|
|
|
|
|
|
|
|
|
/* using inefficient string comparison for better assertion message */
|
|
|
|
|
g_assert_cmpstr (
|
|
|
|
|
dbus_message_type_to_string (dbus_message_get_type (reply)), ==,
|
|
|
|
|
dbus_message_type_to_string (DBUS_MESSAGE_TYPE_ERROR));
|
|
|
|
|
ok = dbus_set_error_from_message (&f->e, reply);
|
|
|
|
|
g_assert (ok);
|
|
|
|
|
g_assert_cmpstr (f->e.name, ==, DBUS_ERROR_NO_REPLY);
|
|
|
|
|
|
|
|
|
|
if (mode == DISCONNECT)
|
|
|
|
|
g_assert_cmpstr (f->e.message, ==,
|
|
|
|
|
"Message recipient disconnected from message bus without replying");
|
|
|
|
|
else
|
|
|
|
|
g_assert_cmpstr (f->e.message, ==,
|
|
|
|
|
"Message did not receive a reply (timeout by message bus)");
|
2017-06-02 12:19:18 +01:00
|
|
|
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&reply);
|
2014-10-29 14:10:48 +00:00
|
|
|
}
|
|
|
|
|
|
2019-03-25 23:01:26 +01:00
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
|
static int
|
|
|
|
|
gid_cmp (const void *ap, const void *bp)
|
|
|
|
|
{
|
|
|
|
|
gid_t a = *(const gid_t *)ap;
|
|
|
|
|
gid_t b = *(const gid_t *)bp;
|
|
|
|
|
if (a < b)
|
|
|
|
|
return -1;
|
|
|
|
|
if (a > b)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2013-08-22 18:21:58 +01:00
|
|
|
static void
|
|
|
|
|
test_creds (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
const char *unique = dbus_bus_get_unique_name (f->left_conn);
|
|
|
|
|
DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetConnectionCredentials");
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2013-08-22 18:21:58 +01:00
|
|
|
DBusMessageIter args_iter;
|
|
|
|
|
DBusMessageIter arr_iter;
|
|
|
|
|
DBusMessageIter pair_iter;
|
|
|
|
|
DBusMessageIter var_iter;
|
|
|
|
|
enum {
|
|
|
|
|
SEEN_UNIX_USER = 1,
|
|
|
|
|
SEEN_PID = 2,
|
2015-02-11 13:19:43 +00:00
|
|
|
SEEN_WINDOWS_SID = 4,
|
2019-03-25 23:01:26 +01:00
|
|
|
SEEN_LINUX_SECURITY_LABEL = 8,
|
|
|
|
|
SEEN_UNIX_GROUPS = 16,
|
2013-08-22 18:21:58 +01:00
|
|
|
} seen = 0;
|
|
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &unique,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2013-08-22 18:21:58 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
g_assert_cmpstr (dbus_message_get_signature (reply), ==, "a{sv}");
|
2013-08-22 18:21:58 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_message_iter_init (reply, &args_iter);
|
2013-08-22 18:21:58 +01:00
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&args_iter), ==,
|
|
|
|
|
DBUS_TYPE_ARRAY);
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_element_type (&args_iter), ==,
|
|
|
|
|
DBUS_TYPE_DICT_ENTRY);
|
|
|
|
|
dbus_message_iter_recurse (&args_iter, &arr_iter);
|
|
|
|
|
|
|
|
|
|
while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_recurse (&arr_iter, &pair_iter);
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
|
|
|
|
|
DBUS_TYPE_STRING);
|
|
|
|
|
dbus_message_iter_get_basic (&pair_iter, &name);
|
|
|
|
|
dbus_message_iter_next (&pair_iter);
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
|
|
|
|
|
DBUS_TYPE_VARIANT);
|
|
|
|
|
dbus_message_iter_recurse (&pair_iter, &var_iter);
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 (name, "UnixUserID") == 0)
|
|
|
|
|
{
|
|
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
|
guint32 u32;
|
|
|
|
|
|
|
|
|
|
g_assert (!(seen & SEEN_UNIX_USER));
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
|
|
|
|
|
DBUS_TYPE_UINT32);
|
|
|
|
|
dbus_message_iter_get_basic (&var_iter, &u32);
|
2015-02-26 17:12:22 +00:00
|
|
|
g_test_message ("%s of this process is %u", name, u32);
|
2013-08-22 18:21:58 +01:00
|
|
|
g_assert_cmpuint (u32, ==, geteuid ());
|
|
|
|
|
seen |= SEEN_UNIX_USER;
|
|
|
|
|
#else
|
|
|
|
|
g_assert_not_reached ();
|
2019-03-25 23:01:26 +01:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else if (g_strcmp0 (name, "UnixGroupIDs") == 0)
|
|
|
|
|
{
|
|
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
|
guint32 *groups;
|
|
|
|
|
gid_t egid = getegid();
|
|
|
|
|
gid_t *actual_groups;
|
|
|
|
|
int len, ret, i;
|
|
|
|
|
size_t nmemb;
|
2019-04-17 14:17:41 +01:00
|
|
|
DBusMessageIter array_iter;
|
2019-03-25 23:01:26 +01:00
|
|
|
|
|
|
|
|
g_assert (!(seen & SEEN_UNIX_GROUPS));
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
|
|
|
|
|
DBUS_TYPE_ARRAY);
|
2019-04-17 14:17:41 +01:00
|
|
|
dbus_message_iter_recurse (&var_iter, &array_iter);
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&array_iter), ==,
|
2019-03-25 23:01:26 +01:00
|
|
|
DBUS_TYPE_UINT32);
|
2019-04-17 14:17:41 +01:00
|
|
|
dbus_message_iter_get_fixed_array (&array_iter, &groups, &len);
|
2019-03-25 23:01:26 +01:00
|
|
|
g_test_message ("%s of this process present (%d groups)", name, len);
|
|
|
|
|
g_assert_cmpint (len, >=, 1);
|
|
|
|
|
|
|
|
|
|
actual_groups = g_new0 (gid_t, len+1);
|
|
|
|
|
ret = getgroups (len, actual_groups);
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
g_error ("getgroups: %s", g_strerror (errno));
|
|
|
|
|
nmemb = ret;
|
|
|
|
|
if (!lfind (&egid, actual_groups, &nmemb, sizeof (gid_t), gid_cmp))
|
|
|
|
|
actual_groups[ret++] = egid;
|
|
|
|
|
g_assert_cmpint (ret, ==, len);
|
|
|
|
|
qsort (actual_groups, len, sizeof (gid_t), gid_cmp);
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
g_assert_true (groups[i] == actual_groups[i]);
|
|
|
|
|
g_free (actual_groups);
|
|
|
|
|
|
|
|
|
|
seen |= SEEN_UNIX_GROUPS;
|
|
|
|
|
#else
|
|
|
|
|
g_assert_not_reached ();
|
2015-02-10 15:41:52 +01:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else if (g_strcmp0 (name, "WindowsSID") == 0)
|
|
|
|
|
{
|
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
gchar *sid;
|
|
|
|
|
char *self_sid;
|
|
|
|
|
|
|
|
|
|
g_assert (!(seen & SEEN_WINDOWS_SID));
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
|
|
|
|
|
DBUS_TYPE_STRING);
|
|
|
|
|
dbus_message_iter_get_basic (&var_iter, &sid);
|
2015-02-26 17:12:22 +00:00
|
|
|
g_test_message ("%s of this process is %s", name, sid);
|
2015-02-10 15:41:52 +01:00
|
|
|
if (_dbus_getsid (&self_sid, 0))
|
|
|
|
|
{
|
|
|
|
|
g_assert_cmpstr (self_sid, ==, sid);
|
|
|
|
|
LocalFree(self_sid);
|
|
|
|
|
}
|
|
|
|
|
seen |= SEEN_WINDOWS_SID;
|
|
|
|
|
#else
|
|
|
|
|
g_assert_not_reached ();
|
2013-08-22 18:21:58 +01:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else if (g_strcmp0 (name, "ProcessID") == 0)
|
|
|
|
|
{
|
|
|
|
|
guint32 u32;
|
|
|
|
|
|
|
|
|
|
g_assert (!(seen & SEEN_PID));
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
|
|
|
|
|
DBUS_TYPE_UINT32);
|
|
|
|
|
dbus_message_iter_get_basic (&var_iter, &u32);
|
2015-02-26 17:12:22 +00:00
|
|
|
g_test_message ("%s of this process is %u", name, u32);
|
2013-08-22 18:21:58 +01:00
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
|
g_assert_cmpuint (u32, ==, getpid ());
|
|
|
|
|
#elif defined(G_OS_WIN32)
|
|
|
|
|
g_assert_cmpuint (u32, ==, GetCurrentProcessId ());
|
|
|
|
|
#else
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
#endif
|
|
|
|
|
seen |= SEEN_PID;
|
|
|
|
|
}
|
2015-02-11 13:19:43 +00:00
|
|
|
else if (g_strcmp0 (name, "LinuxSecurityLabel") == 0)
|
|
|
|
|
{
|
|
|
|
|
#ifdef __linux__
|
|
|
|
|
gchar *label;
|
|
|
|
|
int len;
|
|
|
|
|
DBusMessageIter ay_iter;
|
|
|
|
|
|
|
|
|
|
g_assert (!(seen & SEEN_LINUX_SECURITY_LABEL));
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
|
|
|
|
|
DBUS_TYPE_ARRAY);
|
|
|
|
|
dbus_message_iter_recurse (&var_iter, &ay_iter);
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&ay_iter), ==,
|
|
|
|
|
DBUS_TYPE_BYTE);
|
|
|
|
|
dbus_message_iter_get_fixed_array (&ay_iter, &label, &len);
|
2015-02-26 17:12:22 +00:00
|
|
|
g_test_message ("%s of this process is %s", name, label);
|
2015-02-11 13:19:43 +00:00
|
|
|
g_assert_cmpuint (strlen (label) + 1, ==, len);
|
|
|
|
|
seen |= SEEN_LINUX_SECURITY_LABEL;
|
2019-04-17 14:13:42 +01:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* At this point we would like to do something like:
|
|
|
|
|
*
|
|
|
|
|
* g_assert_cmpstr (label, ==, real_security_label);
|
|
|
|
|
*
|
|
|
|
|
* but there is no LSM-agnostic way to find out our real security
|
|
|
|
|
* label in a way that matches SO_PEERSEC. The closest thing
|
|
|
|
|
* available is reading /proc/self/attr/current, but that is only
|
|
|
|
|
* equal to SO_PEERSEC after applying LSM-specific
|
|
|
|
|
* canonicalization (for example for AppArmor you have to remove
|
|
|
|
|
* a trailing newline from /proc/self/attr/current).
|
|
|
|
|
*/
|
2015-02-11 13:19:43 +00:00
|
|
|
#else
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2017-06-09 15:59:44 +01:00
|
|
|
else if (g_str_has_prefix (name, DBUS_INTERFACE_CONTAINERS1 "."))
|
|
|
|
|
{
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
2013-08-22 18:21:58 +01:00
|
|
|
|
|
|
|
|
dbus_message_iter_next (&arr_iter);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-15 18:04:36 +01:00
|
|
|
#ifdef UNIX_USER_SHOULD_WORK
|
2013-08-22 18:21:58 +01:00
|
|
|
g_assert (seen & SEEN_UNIX_USER);
|
2014-09-15 18:04:36 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef PID_SHOULD_WORK
|
2013-08-22 18:21:58 +01:00
|
|
|
g_assert (seen & SEEN_PID);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
|
g_assert (seen & SEEN_WINDOWS_SID);
|
|
|
|
|
#endif
|
2017-06-02 12:19:18 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2013-08-22 18:21:58 +01:00
|
|
|
}
|
|
|
|
|
|
2014-07-29 14:08:20 +01:00
|
|
|
static void
|
|
|
|
|
test_processid (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
const char *unique = dbus_bus_get_unique_name (f->left_conn);
|
|
|
|
|
DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetConnectionUnixProcessID");
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2014-07-29 14:08:20 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
guint32 pid;
|
|
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &unique,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2014-07-29 14:08:20 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (dbus_set_error_from_message (&error, reply))
|
2016-06-23 12:26:45 +00:00
|
|
|
{
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN);
|
|
|
|
|
|
|
|
|
|
#ifdef PID_SHOULD_WORK
|
|
|
|
|
g_error ("Expected pid to be passed, but got %s: %s",
|
|
|
|
|
error.name, error.message);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
}
|
2017-11-21 11:59:20 +00:00
|
|
|
else if (dbus_message_get_args (reply, &error,
|
2014-09-15 18:38:49 +01:00
|
|
|
DBUS_TYPE_UINT32, &pid,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
{
|
2017-11-21 11:59:20 +00:00
|
|
|
g_assert_cmpstr (dbus_message_get_signature (reply), ==, "u");
|
2015-01-26 19:02:59 +00:00
|
|
|
test_assert_no_error (&error);
|
2014-07-29 14:08:20 +01:00
|
|
|
|
2015-02-26 17:12:22 +00:00
|
|
|
g_test_message ("GetConnectionUnixProcessID returned %u", pid);
|
2014-07-29 14:08:20 +01:00
|
|
|
|
|
|
|
|
#ifdef G_OS_UNIX
|
2014-09-15 18:38:49 +01:00
|
|
|
g_assert_cmpuint (pid, ==, getpid ());
|
2014-07-29 14:08:20 +01:00
|
|
|
#elif defined(G_OS_WIN32)
|
2014-09-15 18:38:49 +01:00
|
|
|
g_assert_cmpuint (pid, ==, GetCurrentProcessId ());
|
2014-07-29 14:08:20 +01:00
|
|
|
#else
|
2014-09-15 18:38:49 +01:00
|
|
|
g_assert_not_reached ();
|
2014-07-29 14:08:20 +01:00
|
|
|
#endif
|
2014-09-15 18:38:49 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-06-23 12:26:45 +00:00
|
|
|
g_error ("Unexpected error: %s: %s", error.name, error.message);
|
2014-09-15 18:38:49 +01:00
|
|
|
}
|
2017-06-02 12:19:18 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2014-07-29 14:08:20 +01:00
|
|
|
}
|
|
|
|
|
|
2014-12-19 19:17:14 +00:00
|
|
|
static void
|
|
|
|
|
test_canonical_path_uae (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "UpdateActivationEnvironment");
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2014-12-19 19:17:14 +00:00
|
|
|
DBusMessageIter args_iter;
|
|
|
|
|
DBusMessageIter arr_iter;
|
|
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_init_append (m, &args_iter);
|
|
|
|
|
|
|
|
|
|
/* Append an empty a{ss} (string => string dictionary). */
|
|
|
|
|
if (!dbus_message_iter_open_container (&args_iter, DBUS_TYPE_ARRAY,
|
|
|
|
|
"{ss}", &arr_iter) ||
|
|
|
|
|
!dbus_message_iter_close_container (&args_iter, &arr_iter))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2014-12-19 19:17:14 +00:00
|
|
|
|
|
|
|
|
/* it succeeds */
|
2017-11-21 11:59:20 +00:00
|
|
|
g_assert_cmpint (dbus_message_get_type (reply), ==,
|
2014-12-19 19:17:14 +00:00
|
|
|
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2014-12-19 19:17:14 +00:00
|
|
|
|
|
|
|
|
/* Now try with the wrong object path */
|
|
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
"/com/example/Wrong", DBUS_INTERFACE_DBUS, "UpdateActivationEnvironment");
|
|
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_init_append (m, &args_iter);
|
|
|
|
|
|
|
|
|
|
/* Append an empty a{ss} (string => string dictionary). */
|
|
|
|
|
if (!dbus_message_iter_open_container (&args_iter, DBUS_TYPE_ARRAY,
|
|
|
|
|
"{ss}", &arr_iter) ||
|
|
|
|
|
!dbus_message_iter_close_container (&args_iter, &arr_iter))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2014-12-19 19:17:14 +00:00
|
|
|
|
|
|
|
|
/* it fails, yielding an error message with one string argument */
|
2017-11-21 11:59:20 +00:00
|
|
|
g_assert_cmpint (dbus_message_get_type (reply), ==, DBUS_MESSAGE_TYPE_ERROR);
|
|
|
|
|
g_assert_cmpstr (dbus_message_get_error_name (reply), ==,
|
2014-12-19 19:17:14 +00:00
|
|
|
DBUS_ERROR_ACCESS_DENIED);
|
2017-11-21 11:59:20 +00:00
|
|
|
g_assert_cmpstr (dbus_message_get_signature (reply), ==, "s");
|
2014-12-19 19:17:14 +00:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2014-12-19 19:17:14 +00:00
|
|
|
}
|
|
|
|
|
|
2018-11-29 14:24:00 +00:00
|
|
|
static Config max_connections_per_user_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/max-connections-per-user.conf",
|
|
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
|
|
|
|
};
|
|
|
|
|
|
2016-07-01 12:30:22 +01:00
|
|
|
static void
|
|
|
|
|
test_max_connections (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
DBusConnection *third_conn;
|
|
|
|
|
DBusConnection *failing_conn;
|
2018-11-29 14:24:00 +00:00
|
|
|
#ifdef DBUS_WIN
|
|
|
|
|
const Config *config = context;
|
|
|
|
|
#endif
|
2016-07-01 12:30:22 +01:00
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2018-11-29 14:24:00 +00:00
|
|
|
#ifdef DBUS_WIN
|
|
|
|
|
if (config == &max_connections_per_user_config)
|
|
|
|
|
{
|
|
|
|
|
/* <limit name="max_connections_per_user"/> is currently only
|
|
|
|
|
* implemented in terms of Unix uids. It could be implemented for
|
|
|
|
|
* Windows SIDs too, but there wouldn't be much point, because we
|
|
|
|
|
* don't support use of a multi-user dbus-daemon on Windows, so
|
|
|
|
|
* in practice all connections have the same SID. */
|
|
|
|
|
g_test_skip ("Maximum connections per Windows SID are not "
|
|
|
|
|
"implemented");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-07-01 12:30:22 +01:00
|
|
|
/* We have two connections already */
|
|
|
|
|
g_assert (f->left_conn != NULL);
|
|
|
|
|
g_assert (f->right_conn != NULL);
|
|
|
|
|
|
|
|
|
|
/* Our configuration file sets the limit to 3 connections, either globally
|
|
|
|
|
* or per uid, so this one is the last that will work */
|
|
|
|
|
third_conn = test_connect_to_bus (f->ctx, f->address);
|
|
|
|
|
|
|
|
|
|
/* This one is going to fail. We don't guarantee whether it will fail
|
|
|
|
|
* now, or while registering (implementation detail: it's the latter). */
|
|
|
|
|
failing_conn = dbus_connection_open_private (f->address, &error);
|
|
|
|
|
|
|
|
|
|
if (failing_conn != NULL)
|
|
|
|
|
{
|
|
|
|
|
gboolean ok = dbus_bus_register (failing_conn, &error);
|
|
|
|
|
|
|
|
|
|
g_assert (!ok);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert (dbus_error_is_set (&error));
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
|
|
|
|
|
|
|
|
|
|
if (failing_conn != NULL)
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_connection_close (failing_conn);
|
2016-07-01 12:30:22 +01:00
|
|
|
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_connection (&failing_conn);
|
2018-07-12 12:51:38 +01:00
|
|
|
test_connection_shutdown (f->ctx, third_conn);
|
2016-07-01 12:30:22 +01:00
|
|
|
dbus_connection_close (third_conn);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_connection (&third_conn);
|
2018-07-11 19:55:31 +01:00
|
|
|
dbus_error_free (&error);
|
2016-07-01 12:30:22 +01:00
|
|
|
}
|
|
|
|
|
|
2016-07-01 13:02:04 +01:00
|
|
|
static void
|
|
|
|
|
test_max_replies_per_connection (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
GQueue received = G_QUEUE_INIT;
|
|
|
|
|
GQueue errors = G_QUEUE_INIT;
|
|
|
|
|
DBusMessage *m;
|
|
|
|
|
DBusPendingCall *pc;
|
|
|
|
|
guint i;
|
|
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
add_hold_filter (f);
|
|
|
|
|
|
|
|
|
|
/* The configured limit is 3 replies per connection. */
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
m = dbus_message_new_method_call (
|
|
|
|
|
dbus_bus_get_unique_name (f->right_conn), "/",
|
|
|
|
|
"com.example", "Spam");
|
|
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
|
|
|
|
|
DBUS_TIMEOUT_INFINITE) ||
|
|
|
|
|
pc == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (dbus_pending_call_get_completed (pc))
|
|
|
|
|
pc_enqueue (pc, &received);
|
|
|
|
|
else if (!dbus_pending_call_set_notify (pc, pc_enqueue, &received,
|
|
|
|
|
NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_pending_call_unref (pc);
|
|
|
|
|
dbus_message_unref (m);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (g_queue_get_length (&f->held_messages) < 3)
|
|
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpuint (g_queue_get_length (&received), ==, 0);
|
|
|
|
|
g_assert_cmpuint (g_queue_get_length (&errors), ==, 0);
|
|
|
|
|
|
|
|
|
|
/* Go a couple of messages over the limit. */
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
|
{
|
|
|
|
|
m = dbus_message_new_method_call (
|
|
|
|
|
dbus_bus_get_unique_name (f->right_conn), "/",
|
|
|
|
|
"com.example", "Spam");
|
|
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
|
|
|
|
|
DBUS_TIMEOUT_INFINITE) ||
|
|
|
|
|
pc == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (dbus_pending_call_get_completed (pc))
|
|
|
|
|
pc_enqueue (pc, &errors);
|
|
|
|
|
else if (!dbus_pending_call_set_notify (pc, pc_enqueue, &errors,
|
|
|
|
|
NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_pending_call_unref (pc);
|
|
|
|
|
dbus_message_unref (m);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Reply to the held messages. */
|
|
|
|
|
for (m = g_queue_pop_head (&f->held_messages);
|
|
|
|
|
m != NULL;
|
|
|
|
|
m = g_queue_pop_head (&f->held_messages))
|
|
|
|
|
{
|
|
|
|
|
DBusMessage *reply = dbus_message_new_method_return (m);
|
|
|
|
|
|
|
|
|
|
if (reply == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (!dbus_connection_send (f->right_conn, reply, NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
|
|
|
|
dbus_clear_message (&reply);
|
2016-07-01 13:02:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Wait for all 5 replies to come in. */
|
|
|
|
|
while (g_queue_get_length (&received) + g_queue_get_length (&errors) < 5)
|
|
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
|
|
|
|
|
|
|
|
|
/* The first three succeeded. */
|
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
m = g_queue_pop_head (&received);
|
|
|
|
|
g_assert (m != NULL);
|
|
|
|
|
|
|
|
|
|
if (dbus_set_error_from_message (&error, m))
|
|
|
|
|
g_error ("Unexpected error: %s: %s", error.name, error.message);
|
|
|
|
|
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2016-07-01 13:02:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The last two failed. */
|
|
|
|
|
for (i = 0; i < 2; i++)
|
|
|
|
|
{
|
|
|
|
|
m = g_queue_pop_head (&errors);
|
|
|
|
|
g_assert (m != NULL);
|
|
|
|
|
|
|
|
|
|
if (!dbus_set_error_from_message (&error, m))
|
|
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
|
|
|
|
|
dbus_error_free (&error);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2016-07-01 13:02:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert_cmpuint (g_queue_get_length (&received), ==, 0);
|
|
|
|
|
g_assert_cmpuint (g_queue_get_length (&errors), ==, 0);
|
|
|
|
|
g_queue_clear (&received);
|
|
|
|
|
g_queue_clear (&errors);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 13:07:49 +01:00
|
|
|
static void
|
|
|
|
|
test_max_match_rules_per_connection (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
dbus_bus_add_match (f->left_conn, "sender='com.example.C1'", &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
dbus_bus_add_match (f->left_conn, "sender='com.example.C2'", &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
dbus_bus_add_match (f->left_conn, "sender='com.example.C3'", &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
|
|
|
|
|
dbus_bus_add_match (f->left_conn, "sender='com.example.C4'", &error);
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
|
|
|
|
dbus_bus_remove_match (f->left_conn, "sender='com.example.C3'", &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
|
|
|
|
|
dbus_bus_add_match (f->left_conn, "sender='com.example.C4'", &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 13:17:23 +01:00
|
|
|
static void
|
|
|
|
|
test_max_names_per_connection (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* The limit in the configuration file is set to 4, but we only own 3
|
|
|
|
|
* names here - remember that the unique name is a name too. */
|
|
|
|
|
|
|
|
|
|
ret = dbus_bus_request_name (f->left_conn, "com.example.C1", 0, &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
|
|
|
|
|
|
|
|
|
|
ret = dbus_bus_request_name (f->left_conn, "com.example.C2", 0, &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
|
|
|
|
|
|
|
|
|
|
ret = dbus_bus_request_name (f->left_conn, "com.example.C3", 0, &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
|
|
|
|
|
|
|
|
|
|
ret = dbus_bus_request_name (f->left_conn, "com.example.C4", 0, &error);
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
g_assert_cmpint (ret, ==, -1);
|
|
|
|
|
|
|
|
|
|
ret = dbus_bus_release_name (f->left_conn, "com.example.C3", &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
g_assert_cmpint (ret, ==, DBUS_RELEASE_NAME_REPLY_RELEASED);
|
|
|
|
|
|
|
|
|
|
ret = dbus_bus_request_name (f->left_conn, "com.example.C4", 0, &error);
|
|
|
|
|
test_assert_no_error (&error);
|
|
|
|
|
g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-16 18:27:43 +01:00
|
|
|
#if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) && defined(HAVE_GIO_UNIX)
|
|
|
|
|
|
|
|
|
|
static DBusHandlerResult
|
|
|
|
|
wait_for_disconnected_cb (DBusConnection *client_conn,
|
|
|
|
|
DBusMessage *message,
|
|
|
|
|
void *data)
|
|
|
|
|
{
|
|
|
|
|
gboolean *disconnected = data;
|
|
|
|
|
|
|
|
|
|
if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected"))
|
|
|
|
|
{
|
|
|
|
|
*disconnected = TRUE;
|
|
|
|
|
return DBUS_HANDLER_RESULT_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const guchar partial_message[] =
|
|
|
|
|
{
|
|
|
|
|
DBUS_LITTLE_ENDIAN,
|
|
|
|
|
DBUS_MESSAGE_TYPE_METHOD_CALL,
|
|
|
|
|
0, /* flags */
|
|
|
|
|
1, /* version */
|
|
|
|
|
0xff, 0xff, 0, 0, /* length of body = 65535 bytes */
|
|
|
|
|
1, 2, 3, 4, /* cookie */
|
|
|
|
|
0xff, 0xff, 0, 0, /* length of header fields array = 65535 bytes */
|
|
|
|
|
42 /* pretending to be the beginning of the header fields array */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
send_all_with_fd (GSocket *socket,
|
2016-08-21 21:30:49 +02:00
|
|
|
const guchar *local_partial_message,
|
2016-08-16 18:27:43 +01:00
|
|
|
gsize len,
|
|
|
|
|
int fd)
|
|
|
|
|
{
|
|
|
|
|
GSocketControlMessage *fdm = g_unix_fd_message_new ();
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
gssize sent;
|
2016-08-21 21:30:49 +02:00
|
|
|
GOutputVector vector = { local_partial_message, len };
|
2016-08-16 18:27:43 +01:00
|
|
|
|
|
|
|
|
g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (fdm), fd, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
|
|
|
|
|
sent = g_socket_send_message (socket, NULL, &vector, 1, &fdm, 1,
|
|
|
|
|
G_SOCKET_MSG_NONE, NULL, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert_cmpint (sent, >=, 1);
|
|
|
|
|
g_assert_cmpint (sent, <=, vector.size);
|
|
|
|
|
|
|
|
|
|
while (((gsize) sent) < vector.size)
|
|
|
|
|
{
|
|
|
|
|
vector.size -= sent;
|
|
|
|
|
vector.buffer = ((const guchar *) vector.buffer) + sent;
|
|
|
|
|
sent = g_socket_send_message (socket, NULL, &vector, 1, NULL, 0,
|
|
|
|
|
G_SOCKET_MSG_NONE, NULL, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert_cmpint (sent, >=, 1);
|
|
|
|
|
g_assert_cmpint (sent, <=, vector.size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_object_unref (fdm);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_pending_fd_timeout (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
GError *error = NULL;
|
|
|
|
|
gint64 start;
|
|
|
|
|
int fd;
|
|
|
|
|
GSocket *socket;
|
|
|
|
|
gboolean have_mem;
|
|
|
|
|
gboolean disconnected = FALSE;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2016-11-11 16:40:44 +00:00
|
|
|
if (getuid () == 0)
|
|
|
|
|
{
|
|
|
|
|
g_test_skip ("Cannot test, uid 0 is immune to this limit");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-16 18:27:43 +01:00
|
|
|
have_mem = dbus_connection_add_filter (f->left_conn, wait_for_disconnected_cb,
|
|
|
|
|
&disconnected, NULL);
|
|
|
|
|
g_assert (have_mem);
|
|
|
|
|
|
|
|
|
|
/* This is not API. Never do this. */
|
|
|
|
|
|
|
|
|
|
if (!dbus_connection_get_socket (f->left_conn, &fd))
|
|
|
|
|
g_error ("failed to steal fd from left connection");
|
|
|
|
|
|
|
|
|
|
socket = g_socket_new_from_fd (fd, &error);
|
|
|
|
|
g_assert_no_error (error);
|
|
|
|
|
g_assert (socket != NULL);
|
|
|
|
|
|
|
|
|
|
/* We send part of a message that contains a fd, then stop. */
|
|
|
|
|
start = g_get_monotonic_time ();
|
|
|
|
|
send_all_with_fd (socket, partial_message, G_N_ELEMENTS (partial_message),
|
|
|
|
|
fd);
|
|
|
|
|
|
|
|
|
|
while (!disconnected)
|
|
|
|
|
{
|
|
|
|
|
test_progress ('.');
|
|
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
|
|
|
|
|
2018-10-23 11:43:23 +01:00
|
|
|
/* It should take 0.5s to get disconnected, as configured in
|
|
|
|
|
* valid-config-files/pending-fd-timeout.conf; but this test
|
|
|
|
|
* might get starved by other processes running in parallel
|
|
|
|
|
* (particularly on shared CI systems), so we have to be a lot
|
|
|
|
|
* more generous. Allow up to 10 seconds. */
|
|
|
|
|
g_assert_cmpint (g_get_monotonic_time (), <=,
|
|
|
|
|
start + (10 * G_USEC_PER_SEC));
|
2016-08-16 18:27:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_object_unref (socket);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-19 19:43:09 +01:00
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
const gchar *path;
|
|
|
|
|
guint n_fds;
|
|
|
|
|
gboolean should_work;
|
|
|
|
|
} CountFdsVector;
|
|
|
|
|
|
|
|
|
|
static const CountFdsVector count_fds_vectors[] =
|
|
|
|
|
{
|
|
|
|
|
/* Deny sending if number of fds <= 2 */
|
|
|
|
|
{ "/test/DenySendMax2", 1, FALSE },
|
|
|
|
|
{ "/test/DenySendMax2", 2, FALSE },
|
|
|
|
|
{ "/test/DenySendMax2", 3, TRUE },
|
|
|
|
|
{ "/test/DenySendMax2", 4, TRUE },
|
|
|
|
|
|
|
|
|
|
/* Deny receiving if number of fds <= 3 */
|
|
|
|
|
{ "/test/DenyReceiveMax3", 2, FALSE },
|
|
|
|
|
{ "/test/DenyReceiveMax3", 3, FALSE },
|
|
|
|
|
{ "/test/DenyReceiveMax3", 4, TRUE },
|
|
|
|
|
{ "/test/DenyReceiveMax3", 5, TRUE },
|
|
|
|
|
|
|
|
|
|
/* Deny sending if number of fds >= 4 */
|
|
|
|
|
{ "/test/DenySendMin4", 2, TRUE },
|
|
|
|
|
{ "/test/DenySendMin4", 3, TRUE },
|
|
|
|
|
{ "/test/DenySendMin4", 4, FALSE },
|
|
|
|
|
{ "/test/DenySendMin4", 5, FALSE },
|
|
|
|
|
|
|
|
|
|
/* Deny receiving if number of fds >= 5 */
|
|
|
|
|
{ "/test/DenyReceiveMin5", 3, TRUE },
|
|
|
|
|
{ "/test/DenyReceiveMin5", 4, TRUE },
|
|
|
|
|
{ "/test/DenyReceiveMin5", 5, FALSE },
|
|
|
|
|
{ "/test/DenyReceiveMin5", 6, FALSE },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_count_fds (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
GQueue received = G_QUEUE_INIT;
|
|
|
|
|
DBusMessage *m;
|
|
|
|
|
DBusPendingCall *pc;
|
|
|
|
|
guint i;
|
|
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const int stdin_fd = 0;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
add_hold_filter (f);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (count_fds_vectors); i++)
|
|
|
|
|
{
|
|
|
|
|
const CountFdsVector *vector = &count_fds_vectors[i];
|
|
|
|
|
guint j;
|
|
|
|
|
|
|
|
|
|
m = dbus_message_new_method_call (
|
|
|
|
|
dbus_bus_get_unique_name (f->right_conn), vector->path,
|
|
|
|
|
"com.example", "Spam");
|
|
|
|
|
|
|
|
|
|
if (m == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < vector->n_fds; j++)
|
|
|
|
|
{
|
|
|
|
|
if (!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_UNIX_FD, &stdin_fd,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
|
|
|
|
|
DBUS_TIMEOUT_INFINITE) ||
|
|
|
|
|
pc == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (dbus_pending_call_get_completed (pc))
|
|
|
|
|
pc_enqueue (pc, &received);
|
|
|
|
|
else if (!dbus_pending_call_set_notify (pc, pc_enqueue, &received,
|
|
|
|
|
NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_pending_call_unref (pc);
|
|
|
|
|
dbus_message_unref (m);
|
|
|
|
|
|
|
|
|
|
if (vector->should_work)
|
|
|
|
|
{
|
|
|
|
|
DBusMessage *reply;
|
|
|
|
|
|
|
|
|
|
while (g_queue_get_length (&f->held_messages) < 1)
|
|
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (g_queue_get_length (&f->held_messages), ==, 1);
|
|
|
|
|
|
|
|
|
|
m = g_queue_pop_head (&f->held_messages);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (g_queue_get_length (&f->held_messages), ==, 0);
|
|
|
|
|
|
|
|
|
|
reply = dbus_message_new_method_return (m);
|
|
|
|
|
|
|
|
|
|
if (reply == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
if (!dbus_connection_send (f->right_conn, reply, NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_message_unref (reply);
|
|
|
|
|
dbus_message_unref (m);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (g_queue_get_length (&received) < 1)
|
|
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (g_queue_get_length (&received), ==, 1);
|
|
|
|
|
m = g_queue_pop_head (&received);
|
|
|
|
|
g_assert (m != NULL);
|
|
|
|
|
g_assert_cmpint (g_queue_get_length (&received), ==, 0);
|
|
|
|
|
|
|
|
|
|
if (vector->should_work)
|
|
|
|
|
{
|
|
|
|
|
if (dbus_set_error_from_message (&error, m))
|
|
|
|
|
g_error ("Unexpected error: %s: %s", error.name, error.message);
|
|
|
|
|
|
|
|
|
|
g_test_message ("Sending %u fds to %s was not denied, as expected",
|
|
|
|
|
vector->n_fds, vector->path);
|
|
|
|
|
}
|
|
|
|
|
else if (!dbus_set_error_from_message (&error, m))
|
|
|
|
|
{
|
|
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_ACCESS_DENIED);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
g_test_message ("Sending %u fds to %s was denied, as expected",
|
|
|
|
|
vector->n_fds, vector->path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbus_message_unref (m);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-16 18:27:43 +01:00
|
|
|
#endif
|
|
|
|
|
|
2017-06-02 12:22:59 +01:00
|
|
|
static void
|
|
|
|
|
test_peer_get_machine_id (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-06-07 17:26:03 +01:00
|
|
|
char *what_i_think;
|
2017-06-02 12:22:59 +01:00
|
|
|
const char *what_daemon_thinks;
|
|
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 12:22:59 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-06-07 17:26:03 +01:00
|
|
|
what_i_think = dbus_try_get_local_machine_id (&error);
|
|
|
|
|
|
|
|
|
|
if (what_i_think == NULL)
|
2017-06-02 12:22:59 +01:00
|
|
|
{
|
|
|
|
|
if (g_getenv ("DBUS_TEST_UNINSTALLED") != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* When running unit tests during make check or make installcheck,
|
|
|
|
|
* tolerate this */
|
|
|
|
|
g_test_skip ("Machine UUID not available");
|
2018-07-11 19:54:24 +01:00
|
|
|
dbus_error_free (&error);
|
2017-06-02 12:22:59 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* When running integration tests, don't tolerate it */
|
2017-06-07 17:26:03 +01:00
|
|
|
g_error ("%s", error.message);
|
2017-06-02 12:22:59 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check that the dbus-daemon agrees with us. */
|
|
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS,
|
|
|
|
|
DBUS_INTERFACE_PEER,
|
|
|
|
|
"GetMachineId");
|
|
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
if (m == NULL)
|
|
|
|
|
test_oom ();
|
2017-06-02 12:22:59 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 12:22:59 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_message_get_args (reply, &error,
|
2017-06-02 12:22:59 +01:00
|
|
|
DBUS_TYPE_STRING, &what_daemon_thinks,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
g_error ("%s: %s", error.name, error.message);
|
|
|
|
|
|
2017-06-07 17:26:03 +01:00
|
|
|
g_assert_cmpstr (what_i_think, ==, what_daemon_thinks);
|
2017-06-02 12:22:59 +01:00
|
|
|
g_assert_nonnull (what_daemon_thinks);
|
|
|
|
|
g_assert_cmpuint (strlen (what_daemon_thinks), ==, 32);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-07 17:26:03 +01:00
|
|
|
dbus_free (what_i_think);
|
2017-06-02 12:22:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_peer_ping (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:50:37 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 12:22:59 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PEER, "Ping");
|
|
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
if (m == NULL)
|
|
|
|
|
test_oom ();
|
2017-06-02 12:22:59 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 12:22:59 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_message_get_args (reply, &error, DBUS_TYPE_INVALID))
|
2017-06-02 12:22:59 +01:00
|
|
|
g_error ("%s: %s", error.name, error.message);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 12:22:59 +01:00
|
|
|
}
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
static void
|
|
|
|
|
test_get_invalid_path (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const char *iface = DBUS_INTERFACE_DBUS;
|
|
|
|
|
const char *property = "Interfaces";
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS, "/",
|
|
|
|
|
DBUS_INTERFACE_PROPERTIES, "Get");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
|
|
|
|
DBUS_TYPE_STRING, &property,
|
2017-11-21 16:01:02 +00:00
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_set_error_from_message (&error, reply))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
/* That object path does not have that interface */
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_get_invalid_iface (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const char *iface = "com.example.Nope";
|
|
|
|
|
const char *property = "Whatever";
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
|
|
|
|
DBUS_TYPE_STRING, &property,
|
2017-11-21 16:01:02 +00:00
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_set_error_from_message (&error, reply))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_get_invalid (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const char *iface = DBUS_INTERFACE_DBUS;
|
|
|
|
|
const char *property = "Whatever";
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
|
|
|
|
DBUS_TYPE_STRING, &property,
|
2017-11-21 16:01:02 +00:00
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_set_error_from_message (&error, reply))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_PROPERTY);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_get_all_invalid_iface (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const char *iface = "com.example.Nope";
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "GetAll");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
2017-11-21 16:01:02 +00:00
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_set_error_from_message (&error, reply))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_get_all_invalid_path (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const char *iface = DBUS_INTERFACE_DBUS;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
"/", DBUS_INTERFACE_PROPERTIES, "GetAll");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
2017-11-21 16:01:02 +00:00
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_set_error_from_message (&error, reply))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
/* That object path does not have that interface */
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_set_invalid_iface (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const char *iface = "com.example.Nope";
|
|
|
|
|
const char *property = "Whatever";
|
|
|
|
|
DBusMessageIter args_iter;
|
|
|
|
|
DBusMessageIter var_iter;
|
|
|
|
|
dbus_bool_t b = FALSE;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Set");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
|
|
|
|
DBUS_TYPE_STRING, &property,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_init_append (m, &args_iter);
|
|
|
|
|
|
|
|
|
|
if (!dbus_message_iter_open_container (&args_iter,
|
|
|
|
|
DBUS_TYPE_VARIANT, "b", &var_iter) ||
|
|
|
|
|
!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
|
2017-11-21 16:01:02 +00:00
|
|
|
!dbus_message_iter_close_container (&args_iter, &var_iter))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_set_error_from_message (&error, reply))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_set_invalid_path (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const char *iface = DBUS_INTERFACE_DBUS;
|
|
|
|
|
const char *property = "Interfaces";
|
|
|
|
|
DBusMessageIter args_iter;
|
|
|
|
|
DBusMessageIter var_iter;
|
|
|
|
|
dbus_bool_t b = FALSE;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
"/", DBUS_INTERFACE_PROPERTIES, "Set");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
|
|
|
|
DBUS_TYPE_STRING, &property,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_init_append (m, &args_iter);
|
|
|
|
|
|
|
|
|
|
if (!dbus_message_iter_open_container (&args_iter,
|
|
|
|
|
DBUS_TYPE_VARIANT, "b", &var_iter) ||
|
|
|
|
|
!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
|
2017-11-21 16:01:02 +00:00
|
|
|
!dbus_message_iter_close_container (&args_iter, &var_iter))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_set_error_from_message (&error, reply))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_set_invalid (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const char *iface = DBUS_INTERFACE_DBUS;
|
|
|
|
|
const char *property = "Whatever";
|
|
|
|
|
DBusMessageIter args_iter;
|
|
|
|
|
DBusMessageIter var_iter;
|
|
|
|
|
dbus_bool_t b = FALSE;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Set");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
|
|
|
|
DBUS_TYPE_STRING, &property,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_init_append (m, &args_iter);
|
|
|
|
|
|
|
|
|
|
if (!dbus_message_iter_open_container (&args_iter,
|
|
|
|
|
DBUS_TYPE_VARIANT, "b", &var_iter) ||
|
|
|
|
|
!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
|
2017-11-21 16:01:02 +00:00
|
|
|
!dbus_message_iter_close_container (&args_iter, &var_iter))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_set_error_from_message (&error, reply))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_PROPERTY);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_set (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusError error = DBUS_ERROR_INIT;
|
|
|
|
|
const char *iface = DBUS_INTERFACE_DBUS;
|
|
|
|
|
const char *property = "Features";
|
|
|
|
|
DBusMessageIter args_iter;
|
|
|
|
|
DBusMessageIter var_iter;
|
|
|
|
|
dbus_bool_t b = FALSE;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Set");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
|
|
|
|
DBUS_TYPE_STRING, &property,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_init_append (m, &args_iter);
|
|
|
|
|
|
|
|
|
|
if (!dbus_message_iter_open_container (&args_iter,
|
|
|
|
|
DBUS_TYPE_VARIANT, "b", &var_iter) ||
|
|
|
|
|
!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
|
2017-11-21 16:01:02 +00:00
|
|
|
!dbus_message_iter_close_container (&args_iter, &var_iter))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_set_error_from_message (&error, reply))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Unexpected success");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (error.name, ==, DBUS_ERROR_PROPERTY_READ_ONLY);
|
|
|
|
|
dbus_error_free (&error);
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
check_features (DBusMessageIter *var_iter)
|
|
|
|
|
{
|
|
|
|
|
DBusMessageIter arr_iter;
|
|
|
|
|
gboolean have_systemd_activation = FALSE;
|
2017-12-12 14:05:20 +00:00
|
|
|
gboolean have_header_filtering = FALSE;
|
2017-06-02 13:32:13 +01:00
|
|
|
|
|
|
|
|
g_assert_cmpint (dbus_message_iter_get_arg_type (var_iter), ==,
|
|
|
|
|
DBUS_TYPE_ARRAY);
|
|
|
|
|
g_assert_cmpint (dbus_message_iter_get_element_type (var_iter), ==,
|
|
|
|
|
DBUS_TYPE_STRING);
|
|
|
|
|
dbus_message_iter_recurse (var_iter, &arr_iter);
|
|
|
|
|
|
|
|
|
|
while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
|
|
|
|
|
{
|
|
|
|
|
const char *feature;
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (dbus_message_iter_get_arg_type (&arr_iter), ==,
|
|
|
|
|
DBUS_TYPE_STRING);
|
|
|
|
|
dbus_message_iter_get_basic (&arr_iter, &feature);
|
|
|
|
|
|
|
|
|
|
g_test_message ("Feature: %s", feature);
|
|
|
|
|
|
2017-12-12 14:05:20 +00:00
|
|
|
if (g_strcmp0 (feature, "HeaderFiltering") == 0)
|
|
|
|
|
have_header_filtering = TRUE;
|
|
|
|
|
else if (g_strcmp0 (feature, "SystemdActivation") == 0)
|
2017-06-02 13:32:13 +01:00
|
|
|
have_systemd_activation = TRUE;
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_next (&arr_iter);
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-12 14:05:20 +00:00
|
|
|
g_assert_true (have_header_filtering);
|
2017-06-02 13:32:13 +01:00
|
|
|
/* We pass --systemd-activation to the daemon for this unit test on Unix
|
|
|
|
|
* (it can only work in practice on Linux, but there's nothing
|
|
|
|
|
* inherently Linux-specific about the protocol). */
|
|
|
|
|
#ifdef DBUS_UNIX
|
|
|
|
|
g_assert_true (have_systemd_activation);
|
|
|
|
|
#else
|
|
|
|
|
g_assert_false (have_systemd_activation);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_features (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusMessageIter args_iter;
|
|
|
|
|
DBusMessageIter var_iter;
|
|
|
|
|
const char *iface = DBUS_INTERFACE_DBUS;
|
|
|
|
|
const char *features = "Features";
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
|
|
|
|
DBUS_TYPE_STRING, &features,
|
2017-11-21 16:01:02 +00:00
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_message_iter_init (reply, &args_iter))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Reply has no arguments");
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (dbus_message_iter_get_arg_type (&args_iter), ==,
|
|
|
|
|
DBUS_TYPE_VARIANT);
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_recurse (&args_iter, &var_iter);
|
|
|
|
|
check_features (&var_iter);
|
|
|
|
|
|
|
|
|
|
if (dbus_message_iter_next (&args_iter))
|
|
|
|
|
g_error ("Reply has too many arguments");
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
check_interfaces (DBusMessageIter *var_iter)
|
|
|
|
|
{
|
|
|
|
|
DBusMessageIter arr_iter;
|
|
|
|
|
gboolean have_monitoring = FALSE;
|
|
|
|
|
gboolean have_stats = FALSE;
|
|
|
|
|
gboolean have_verbose = FALSE;
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (dbus_message_iter_get_arg_type (var_iter), ==,
|
|
|
|
|
DBUS_TYPE_ARRAY);
|
|
|
|
|
g_assert_cmpint (dbus_message_iter_get_element_type (var_iter), ==,
|
|
|
|
|
DBUS_TYPE_STRING);
|
|
|
|
|
dbus_message_iter_recurse (var_iter, &arr_iter);
|
|
|
|
|
|
|
|
|
|
while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
|
|
|
|
|
{
|
|
|
|
|
const char *iface;
|
|
|
|
|
|
|
|
|
|
g_assert_cmpint (dbus_message_iter_get_arg_type (&arr_iter), ==,
|
|
|
|
|
DBUS_TYPE_STRING);
|
|
|
|
|
dbus_message_iter_get_basic (&arr_iter, &iface);
|
|
|
|
|
g_test_message ("Interface: %s", iface);
|
|
|
|
|
|
|
|
|
|
g_assert_cmpstr (iface, !=, DBUS_INTERFACE_DBUS);
|
|
|
|
|
g_assert_cmpstr (iface, !=, DBUS_INTERFACE_PROPERTIES);
|
|
|
|
|
g_assert_cmpstr (iface, !=, DBUS_INTERFACE_INTROSPECTABLE);
|
|
|
|
|
g_assert_cmpstr (iface, !=, DBUS_INTERFACE_PEER);
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 (iface, DBUS_INTERFACE_MONITORING) == 0)
|
|
|
|
|
have_monitoring = TRUE;
|
|
|
|
|
else if (g_strcmp0 (iface, BUS_INTERFACE_STATS) == 0)
|
|
|
|
|
have_stats = TRUE;
|
|
|
|
|
else if (g_strcmp0 (iface, DBUS_INTERFACE_VERBOSE) == 0)
|
|
|
|
|
have_verbose = TRUE;
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_next (&arr_iter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert_true (have_monitoring);
|
|
|
|
|
|
|
|
|
|
#ifdef DBUS_ENABLE_STATS
|
|
|
|
|
g_assert_true (have_stats);
|
|
|
|
|
#else
|
|
|
|
|
g_assert_false (have_stats);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef DBUS_ENABLE_VERBOSE_MODE
|
|
|
|
|
g_assert_true (have_verbose);
|
|
|
|
|
#else
|
|
|
|
|
g_assert_false (have_verbose);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_interfaces (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusMessageIter args_iter;
|
|
|
|
|
DBusMessageIter var_iter;
|
|
|
|
|
const char *iface = DBUS_INTERFACE_DBUS;
|
|
|
|
|
const char *ifaces = "Interfaces";
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
|
|
|
|
DBUS_TYPE_STRING, &ifaces,
|
2017-11-21 16:01:02 +00:00
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
if (!dbus_message_iter_init (reply, &args_iter))
|
2017-06-02 13:32:13 +01:00
|
|
|
g_error ("Reply has no arguments");
|
|
|
|
|
|
|
|
|
|
if (dbus_message_iter_get_arg_type (&args_iter) != DBUS_TYPE_VARIANT)
|
|
|
|
|
g_error ("Reply does not have a variant argument");
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_recurse (&args_iter, &var_iter);
|
|
|
|
|
check_interfaces (&var_iter);
|
|
|
|
|
|
|
|
|
|
if (dbus_message_iter_next (&args_iter))
|
|
|
|
|
g_error ("Reply has too many arguments");
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_get_all (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
2017-11-21 10:56:56 +00:00
|
|
|
DBusMessage *m = NULL;
|
2017-11-21 11:59:20 +00:00
|
|
|
DBusMessage *reply = NULL;
|
2017-06-02 13:32:13 +01:00
|
|
|
DBusMessageIter args_iter;
|
|
|
|
|
DBusMessageIter arr_iter;
|
|
|
|
|
DBusMessageIter pair_iter;
|
|
|
|
|
DBusMessageIter var_iter;
|
|
|
|
|
const char *iface = DBUS_INTERFACE_DBUS;
|
|
|
|
|
gboolean have_features = FALSE;
|
|
|
|
|
gboolean have_interfaces = FALSE;
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
2017-11-21 10:56:56 +00:00
|
|
|
m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
|
|
|
|
|
DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "GetAll");
|
|
|
|
|
|
2017-06-02 13:32:13 +01:00
|
|
|
if (m == NULL ||
|
|
|
|
|
!dbus_message_append_args (m,
|
|
|
|
|
DBUS_TYPE_STRING, &iface,
|
2017-11-21 16:01:02 +00:00
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
test_oom ();
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 16:01:02 +00:00
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, m,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
2017-06-02 13:32:13 +01:00
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_message_iter_init (reply, &args_iter);
|
2017-06-02 13:32:13 +01:00
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&args_iter), ==,
|
|
|
|
|
DBUS_TYPE_ARRAY);
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_element_type (&args_iter), ==,
|
|
|
|
|
DBUS_TYPE_DICT_ENTRY);
|
|
|
|
|
dbus_message_iter_recurse (&args_iter, &arr_iter);
|
|
|
|
|
|
|
|
|
|
while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_recurse (&arr_iter, &pair_iter);
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
|
|
|
|
|
DBUS_TYPE_STRING);
|
|
|
|
|
dbus_message_iter_get_basic (&pair_iter, &name);
|
|
|
|
|
dbus_message_iter_next (&pair_iter);
|
|
|
|
|
g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
|
|
|
|
|
DBUS_TYPE_VARIANT);
|
|
|
|
|
dbus_message_iter_recurse (&pair_iter, &var_iter);
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 (name, "Features") == 0)
|
|
|
|
|
{
|
|
|
|
|
check_features (&var_iter);
|
|
|
|
|
have_features = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (g_strcmp0 (name, "Interfaces") == 0)
|
|
|
|
|
{
|
|
|
|
|
check_interfaces (&var_iter);
|
|
|
|
|
have_interfaces = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbus_message_iter_next (&arr_iter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_assert_true (have_features);
|
|
|
|
|
g_assert_true (have_interfaces);
|
|
|
|
|
|
|
|
|
|
if (dbus_message_iter_next (&args_iter))
|
|
|
|
|
g_error ("Reply has too many arguments");
|
|
|
|
|
|
2017-11-21 11:59:20 +00:00
|
|
|
dbus_clear_message (&reply);
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_message (&m);
|
2017-06-02 13:32:13 +01:00
|
|
|
}
|
|
|
|
|
|
2018-02-20 11:45:39 +00:00
|
|
|
#define DESIRED_RLIMIT 65536
|
|
|
|
|
|
|
|
|
|
#ifdef DBUS_UNIX
|
|
|
|
|
static void
|
|
|
|
|
test_fd_limit (Fixture *f,
|
|
|
|
|
gconstpointer context)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_PRLIMIT
|
|
|
|
|
struct rlimit lim;
|
2018-12-04 12:09:26 +00:00
|
|
|
struct rlimit new_limit;
|
2018-02-20 11:45:39 +00:00
|
|
|
const struct passwd *pwd = NULL;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_PRLIMIT
|
|
|
|
|
|
|
|
|
|
if (getuid () != 0)
|
|
|
|
|
{
|
|
|
|
|
g_test_skip ("Cannot test, only uid 0 is expected to raise fd limit");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pwd = getpwnam (DBUS_USER);
|
|
|
|
|
|
|
|
|
|
if (pwd == NULL)
|
|
|
|
|
{
|
|
|
|
|
gchar *message = g_strdup_printf ("user '%s' does not exist",
|
|
|
|
|
DBUS_USER);
|
|
|
|
|
|
|
|
|
|
g_test_skip (message);
|
|
|
|
|
g_free (message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (prlimit (getpid (), RLIMIT_NOFILE, NULL, &lim) < 0)
|
2018-12-04 12:09:26 +00:00
|
|
|
g_error ("get prlimit (self): %s", g_strerror (errno));
|
2018-02-20 11:45:39 +00:00
|
|
|
|
|
|
|
|
g_test_message ("our RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld",
|
|
|
|
|
(long) lim.rlim_cur, (long) lim.rlim_max);
|
|
|
|
|
|
|
|
|
|
if (lim.rlim_cur == RLIM_INFINITY || lim.rlim_cur >= DESIRED_RLIMIT)
|
|
|
|
|
{
|
|
|
|
|
/* The dbus-daemon will have inherited our large rlimit */
|
|
|
|
|
g_test_skip ("Cannot test, our own fd limit was already large");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-04 12:09:26 +00:00
|
|
|
new_limit = lim;
|
|
|
|
|
new_limit.rlim_cur = DESIRED_RLIMIT;
|
|
|
|
|
new_limit.rlim_max = DESIRED_RLIMIT;
|
|
|
|
|
|
|
|
|
|
/* Try to increase the rlimit ourselves. If we're root in an
|
|
|
|
|
* unprivileged Linux container, then we won't have CAP_SYS_RESOURCE
|
|
|
|
|
* and this will fail with EPERM. If so, the dbus-daemon wouldn't be
|
|
|
|
|
* able to increase its rlimit either. */
|
|
|
|
|
if (prlimit (getpid (), RLIMIT_NOFILE, &new_limit, NULL) < 0)
|
|
|
|
|
{
|
|
|
|
|
gchar *message;
|
|
|
|
|
|
|
|
|
|
message = g_strdup_printf ("Cannot test, we cannot change the rlimit so "
|
|
|
|
|
"presumably neither can the dbus-daemon: %s",
|
|
|
|
|
g_strerror (errno));
|
|
|
|
|
g_test_skip (message);
|
|
|
|
|
g_free (message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Immediately put our original limit back so it won't interfere with
|
|
|
|
|
* subsequent tests. This should always succeed. */
|
|
|
|
|
if (prlimit (getpid (), RLIMIT_NOFILE, &lim, NULL) < 0)
|
|
|
|
|
g_error ("Cannot restore our original limits: %s", g_strerror (errno));
|
|
|
|
|
|
2018-02-20 11:45:39 +00:00
|
|
|
if (prlimit (f->daemon_pid, RLIMIT_NOFILE, NULL, &lim) < 0)
|
2018-12-04 12:09:26 +00:00
|
|
|
g_error ("get prlimit (dbus-daemon): %s", g_strerror (errno));
|
2018-02-20 11:45:39 +00:00
|
|
|
|
|
|
|
|
g_test_message ("dbus-daemon's RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld",
|
|
|
|
|
(long) lim.rlim_cur, (long) lim.rlim_max);
|
|
|
|
|
|
|
|
|
|
if (lim.rlim_cur != RLIM_INFINITY)
|
|
|
|
|
g_assert_cmpint (lim.rlim_cur, >=, DESIRED_RLIMIT);
|
|
|
|
|
|
|
|
|
|
#else /* !HAVE_PRLIMIT */
|
|
|
|
|
|
|
|
|
|
g_test_skip ("prlimit() not supported on this platform");
|
|
|
|
|
|
|
|
|
|
#endif /* !HAVE_PRLIMIT */
|
|
|
|
|
}
|
Translate Python-based tests to C
This simplifies bootstrapping: now you don't have to build dbus,
build dbus-python (with GLib), and use dbus-python to test dbus.
It also avoids test failures when using facilities like
AddressSanitizer. When libdbus is built with AddressSanitizer, but the
system copies of Python and dbus-python were not, dbus-python will exit
the Python interpreter on load, because libasan wasn't already
initialized. The simplest way to avoid this is to not use Python:
the scripts are not *that* hard to translate into C.
Both of these tests happen to be conditionally compiled for Unix only.
test_activation_forking() relies on code in TestSuiteForkingEchoService
that calls fork(), which can only work on Unix; meanwhile,
test_system_signals() tests the system bus configuration, which is
only relevant to Unix because we don't support using dbus-daemon as
a privilege boundary on Windows (and in any case D-Bus is not a Windows
OS feature, so the system bus cannot be used to communicate with OS
services like it can on most Linux systems).
This is also a partial solution to
<https://gitlab.freedesktop.org/dbus/dbus/issues/135>, by reducing the
size of name-test/.
For this to work, we need to build the test-service helper executable
even if embedded tests are disabled.
Signed-off-by: Simon McVittie <smcv@collabora.com>
2018-11-16 18:53:11 +00:00
|
|
|
|
|
|
|
|
#define ECHO_SERVICE "org.freedesktop.DBus.TestSuiteEchoService"
|
|
|
|
|
#define FORKING_ECHO_SERVICE "org.freedesktop.DBus.TestSuiteForkingEchoService"
|
|
|
|
|
#define ECHO_SERVICE_PATH "/org/freedesktop/TestSuite"
|
|
|
|
|
#define ECHO_SERVICE_INTERFACE "org.freedesktop.TestSuite"
|
|
|
|
|
|
2019-03-23 22:18:11 +02:00
|
|
|
#ifdef ENABLE_TRADITIONAL_ACTIVATION
|
Translate Python-based tests to C
This simplifies bootstrapping: now you don't have to build dbus,
build dbus-python (with GLib), and use dbus-python to test dbus.
It also avoids test failures when using facilities like
AddressSanitizer. When libdbus is built with AddressSanitizer, but the
system copies of Python and dbus-python were not, dbus-python will exit
the Python interpreter on load, because libasan wasn't already
initialized. The simplest way to avoid this is to not use Python:
the scripts are not *that* hard to translate into C.
Both of these tests happen to be conditionally compiled for Unix only.
test_activation_forking() relies on code in TestSuiteForkingEchoService
that calls fork(), which can only work on Unix; meanwhile,
test_system_signals() tests the system bus configuration, which is
only relevant to Unix because we don't support using dbus-daemon as
a privilege boundary on Windows (and in any case D-Bus is not a Windows
OS feature, so the system bus cannot be used to communicate with OS
services like it can on most Linux systems).
This is also a partial solution to
<https://gitlab.freedesktop.org/dbus/dbus/issues/135>, by reducing the
size of name-test/.
For this to work, we need to build the test-service helper executable
even if embedded tests are disabled.
Signed-off-by: Simon McVittie <smcv@collabora.com>
2018-11-16 18:53:11 +00:00
|
|
|
/*
|
|
|
|
|
* Helper for test_activation_forking: whenever the forking service is
|
|
|
|
|
* activated, start it again.
|
|
|
|
|
*/
|
|
|
|
|
static DBusHandlerResult
|
|
|
|
|
activation_forking_signal_filter (DBusConnection *connection,
|
|
|
|
|
DBusMessage *message,
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
|
|
|
|
Fixture *f = user_data;
|
|
|
|
|
|
|
|
|
|
if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
|
|
|
|
|
"NameOwnerChanged"))
|
|
|
|
|
{
|
|
|
|
|
dbus_bool_t ok;
|
|
|
|
|
const char *name;
|
|
|
|
|
const char *old_owner;
|
|
|
|
|
const char *new_owner;
|
|
|
|
|
|
|
|
|
|
ok = dbus_message_get_args (message, &f->e,
|
|
|
|
|
DBUS_TYPE_STRING, &name,
|
|
|
|
|
DBUS_TYPE_STRING, &old_owner,
|
|
|
|
|
DBUS_TYPE_STRING, &new_owner,
|
|
|
|
|
DBUS_TYPE_INVALID);
|
|
|
|
|
test_assert_no_error (&f->e);
|
|
|
|
|
g_assert_true (ok);
|
|
|
|
|
|
|
|
|
|
g_test_message ("owner of \"%s\": \"%s\" -> \"%s\"",
|
|
|
|
|
name, old_owner, new_owner);
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 (name, FORKING_ECHO_SERVICE) != 0)
|
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
|
|
|
|
|
|
if (f->activation_forking_counter > 10)
|
|
|
|
|
{
|
|
|
|
|
g_test_message ("Activated 10 times OK, TestSuiteForkingEchoService pass");
|
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f->activation_forking_counter++;
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 (new_owner, "") == 0)
|
|
|
|
|
{
|
|
|
|
|
/* Reactivate it, and tell it to exit immediately. */
|
|
|
|
|
DBusMessage *echo_call = NULL;
|
|
|
|
|
DBusMessage *exit_call = NULL;
|
|
|
|
|
gchar *payload = NULL;
|
|
|
|
|
|
|
|
|
|
payload = g_strdup_printf ("counter %u", f->activation_forking_counter);
|
|
|
|
|
echo_call = dbus_message_new_method_call (FORKING_ECHO_SERVICE,
|
|
|
|
|
ECHO_SERVICE_PATH,
|
|
|
|
|
ECHO_SERVICE_INTERFACE,
|
|
|
|
|
"Echo");
|
|
|
|
|
exit_call = dbus_message_new_method_call (FORKING_ECHO_SERVICE,
|
|
|
|
|
ECHO_SERVICE_PATH,
|
|
|
|
|
ECHO_SERVICE_INTERFACE,
|
|
|
|
|
"Exit");
|
|
|
|
|
|
|
|
|
|
if (echo_call == NULL ||
|
|
|
|
|
!dbus_message_append_args (echo_call,
|
|
|
|
|
DBUS_TYPE_STRING, &payload,
|
|
|
|
|
DBUS_TYPE_INVALID) ||
|
|
|
|
|
exit_call == NULL ||
|
|
|
|
|
!dbus_connection_send (connection, echo_call, NULL) ||
|
|
|
|
|
!dbus_connection_send (connection, exit_call, NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_clear_message (&echo_call);
|
|
|
|
|
dbus_clear_message (&exit_call);
|
|
|
|
|
g_free (payload);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Assert that Unix services are allowed to daemonize, and this does not
|
|
|
|
|
* cause us to signal an activation failure.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
test_activation_forking (Fixture *f,
|
|
|
|
|
gconstpointer context G_GNUC_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
DBusMessage *call = NULL;
|
|
|
|
|
DBusMessage *reply = NULL;
|
|
|
|
|
const char *hello = "hello world";
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!dbus_connection_add_filter (f->left_conn,
|
|
|
|
|
activation_forking_signal_filter,
|
|
|
|
|
f, NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
/* Start it up */
|
|
|
|
|
call = dbus_message_new_method_call (FORKING_ECHO_SERVICE,
|
|
|
|
|
ECHO_SERVICE_PATH,
|
|
|
|
|
ECHO_SERVICE_INTERFACE,
|
|
|
|
|
"Echo");
|
|
|
|
|
|
|
|
|
|
if (call == NULL ||
|
|
|
|
|
!dbus_message_append_args (call,
|
|
|
|
|
DBUS_TYPE_STRING, &hello,
|
|
|
|
|
DBUS_TYPE_INVALID))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_bus_add_match (f->left_conn,
|
|
|
|
|
"sender='org.freedesktop.DBus'",
|
|
|
|
|
&f->e);
|
|
|
|
|
test_assert_no_error (&f->e);
|
|
|
|
|
|
|
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, call,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
|
|
|
|
dbus_clear_message (&call);
|
|
|
|
|
g_test_message ("TestSuiteForkingEchoService initial reply OK");
|
|
|
|
|
dbus_clear_message (&reply);
|
|
|
|
|
|
|
|
|
|
/* Now monitor for exits: when that happens, start it up again.
|
|
|
|
|
* The goal here is to try to hit any race conditions in activation. */
|
|
|
|
|
f->activation_forking_counter = 0;
|
|
|
|
|
|
|
|
|
|
call = dbus_message_new_method_call (FORKING_ECHO_SERVICE,
|
|
|
|
|
ECHO_SERVICE_PATH,
|
|
|
|
|
ECHO_SERVICE_INTERFACE,
|
|
|
|
|
"Exit");
|
|
|
|
|
|
|
|
|
|
if (call == NULL || !dbus_connection_send (f->left_conn, call, NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_clear_message (&call);
|
|
|
|
|
|
|
|
|
|
while (f->activation_forking_counter <= 10)
|
|
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
|
|
|
|
|
|
|
|
|
dbus_connection_remove_filter (f->left_conn,
|
|
|
|
|
activation_forking_signal_filter, f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Helper for test_system_signals: Receive Foo signals and add them to
|
|
|
|
|
* the held_messages queue.
|
|
|
|
|
*/
|
|
|
|
|
static DBusHandlerResult
|
|
|
|
|
foo_signal_filter (DBusConnection *connection,
|
|
|
|
|
DBusMessage *message,
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
|
|
|
|
Fixture *f = user_data;
|
|
|
|
|
|
|
|
|
|
if (dbus_message_is_signal (message, ECHO_SERVICE_INTERFACE, "Foo"))
|
|
|
|
|
g_queue_push_tail (&f->held_messages, dbus_message_ref (message));
|
|
|
|
|
|
|
|
|
|
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Assert that the system bus(-like) configuration allows services
|
|
|
|
|
* to emit signals, even if there is no service-specific configuration
|
|
|
|
|
* to allow it.
|
|
|
|
|
*
|
|
|
|
|
* Essentially equivalent to the old test/name-test/test-wait-for-echo.py.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
test_system_signals (Fixture *f,
|
|
|
|
|
gconstpointer context G_GNUC_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
DBusMessage *call = NULL;
|
|
|
|
|
DBusMessage *response = NULL;
|
|
|
|
|
|
|
|
|
|
g_test_bug ("18229");
|
|
|
|
|
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!dbus_connection_add_filter (f->left_conn, foo_signal_filter,
|
|
|
|
|
f, NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_bus_add_match (f->left_conn,
|
|
|
|
|
"interface='" ECHO_SERVICE_INTERFACE "'",
|
|
|
|
|
&f->e);
|
|
|
|
|
test_assert_no_error (&f->e);
|
|
|
|
|
|
|
|
|
|
call = dbus_message_new_method_call (ECHO_SERVICE,
|
|
|
|
|
ECHO_SERVICE_PATH,
|
|
|
|
|
ECHO_SERVICE_INTERFACE,
|
|
|
|
|
"EmitFoo");
|
|
|
|
|
|
|
|
|
|
if (call == NULL || !dbus_connection_send (f->left_conn, call, NULL))
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
dbus_clear_message (&call);
|
|
|
|
|
|
|
|
|
|
while (g_queue_get_length (&f->held_messages) < 1)
|
|
|
|
|
test_main_context_iterate (f->ctx, TRUE);
|
|
|
|
|
|
|
|
|
|
g_test_message ("got signal");
|
|
|
|
|
g_assert_cmpuint (g_queue_get_length (&f->held_messages), ==, 1);
|
|
|
|
|
response = g_queue_pop_head (&f->held_messages);
|
|
|
|
|
g_assert_cmpint (dbus_message_get_type (response), ==,
|
|
|
|
|
DBUS_MESSAGE_TYPE_SIGNAL);
|
|
|
|
|
g_assert_cmpstr (dbus_message_get_interface (response), ==,
|
|
|
|
|
ECHO_SERVICE_INTERFACE);
|
|
|
|
|
g_assert_cmpstr (dbus_message_get_path (response), ==,
|
|
|
|
|
ECHO_SERVICE_PATH);
|
|
|
|
|
g_assert_cmpstr (dbus_message_get_signature (response), ==, "d");
|
|
|
|
|
g_assert_cmpstr (dbus_message_get_member (response), ==, "Foo");
|
|
|
|
|
dbus_clear_message (&response);
|
|
|
|
|
|
|
|
|
|
dbus_connection_remove_filter (f->left_conn, foo_signal_filter, f);
|
|
|
|
|
}
|
2018-02-20 11:45:39 +00:00
|
|
|
#endif
|
2019-03-23 22:18:11 +02:00
|
|
|
#endif
|
2018-02-20 11:45:39 +00:00
|
|
|
|
2019-04-25 09:35:59 +02:00
|
|
|
static void
|
|
|
|
|
take_well_known_name (DBusConnection *conn,
|
|
|
|
|
const char *name,
|
|
|
|
|
DBusError *error,
|
|
|
|
|
int ownership_type)
|
|
|
|
|
{
|
|
|
|
|
int ret = dbus_bus_request_name (conn, name, 0, error);
|
|
|
|
|
test_assert_no_error (error);
|
|
|
|
|
g_assert_cmpint (ret, ==, ownership_type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
drop_well_known_name (DBusConnection *conn,
|
|
|
|
|
const char *name,
|
|
|
|
|
DBusError *error)
|
|
|
|
|
{
|
|
|
|
|
int ret = dbus_bus_release_name (conn, name, error);
|
|
|
|
|
test_assert_no_error (error);
|
|
|
|
|
g_assert_cmpint (ret, ==, DBUS_RELEASE_NAME_REPLY_RELEASED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
helper_send_destination_prefix_check (Fixture *f,
|
|
|
|
|
const char *name,
|
|
|
|
|
const char *interface,
|
|
|
|
|
const char *member,
|
|
|
|
|
dbus_bool_t allowed,
|
|
|
|
|
const char *additional_name,
|
|
|
|
|
int ownership_type)
|
|
|
|
|
{
|
|
|
|
|
DBusMessage *call = NULL;
|
|
|
|
|
DBusMessage *reply = NULL;
|
|
|
|
|
|
|
|
|
|
take_well_known_name (f->right_conn, name, &f->e, ownership_type);
|
|
|
|
|
|
|
|
|
|
if (additional_name)
|
|
|
|
|
take_well_known_name (f->right_conn, additional_name, &f->e, ownership_type);
|
|
|
|
|
|
|
|
|
|
call = dbus_message_new_method_call (dbus_bus_get_unique_name (f->right_conn),
|
|
|
|
|
"/",
|
|
|
|
|
interface,
|
|
|
|
|
member);
|
|
|
|
|
|
|
|
|
|
if (call == NULL)
|
|
|
|
|
g_error ("OOM");
|
|
|
|
|
|
|
|
|
|
reply = test_main_context_call_and_wait (f->ctx, f->left_conn, call,
|
|
|
|
|
DBUS_TIMEOUT_USE_DEFAULT);
|
|
|
|
|
dbus_clear_message (&call);
|
|
|
|
|
g_test_message ("reply from %s(%d):%s OK", name, ownership_type, member);
|
|
|
|
|
if (allowed)
|
|
|
|
|
{
|
|
|
|
|
g_test_message ("checking reply from %s for correct method_return", name);
|
|
|
|
|
g_assert_cmpint (dbus_message_get_type (reply), ==,
|
|
|
|
|
DBUS_MESSAGE_TYPE_METHOD_RETURN);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
g_test_message ("checking reply from %s for correct access_denied", name);
|
|
|
|
|
g_assert_cmpint (dbus_message_get_type (reply), ==,
|
|
|
|
|
DBUS_MESSAGE_TYPE_ERROR);
|
|
|
|
|
g_assert_cmpstr (dbus_message_get_error_name (reply), ==,
|
|
|
|
|
DBUS_ERROR_ACCESS_DENIED);
|
|
|
|
|
}
|
|
|
|
|
dbus_clear_message (&reply);
|
|
|
|
|
|
|
|
|
|
drop_well_known_name (f->right_conn, name, &f->e);
|
|
|
|
|
|
|
|
|
|
if (additional_name)
|
|
|
|
|
drop_well_known_name (f->right_conn, additional_name, &f->e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
helper_send_destination_prefix (Fixture *f,
|
|
|
|
|
const char *name,
|
|
|
|
|
const char *interface,
|
|
|
|
|
const char *member,
|
|
|
|
|
dbus_bool_t allowed,
|
|
|
|
|
const char *additional_name)
|
|
|
|
|
{
|
|
|
|
|
/* check with primary ownership */
|
|
|
|
|
helper_send_destination_prefix_check (f, name, interface, member, allowed, additional_name, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
|
|
|
|
|
|
|
|
|
|
/* check with queued ownership */
|
|
|
|
|
take_well_known_name (f->left_conn, name, &f->e, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
|
|
|
|
|
if (additional_name)
|
|
|
|
|
take_well_known_name (f->left_conn, additional_name, &f->e, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
|
|
|
|
|
|
|
|
|
|
helper_send_destination_prefix_check (f, name, interface, member, allowed, additional_name, DBUS_REQUEST_NAME_REPLY_IN_QUEUE);
|
|
|
|
|
|
|
|
|
|
drop_well_known_name (f->left_conn, name, &f->e);
|
|
|
|
|
if (additional_name)
|
|
|
|
|
drop_well_known_name (f->left_conn, additional_name, &f->e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
test_send_destination_prefix (Fixture *f,
|
|
|
|
|
gconstpointer context G_GNUC_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
if (f->skip)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
add_echo_filter (f);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Names are constructed with prefix foo.bar.test.dest_prefix followed by some of the tokens:
|
|
|
|
|
* - a - allow send_destination for this name
|
|
|
|
|
* - d - deny send_destination for this name
|
|
|
|
|
* - ap - allow send_destination_prefix for this name
|
|
|
|
|
* - dp - deny send_destination_prefix for this name
|
|
|
|
|
* - f, f1, f2, f3 - fillers for generating names down the name hierarchy
|
|
|
|
|
* - apf, dpf, ao, do - just some neighbour names
|
|
|
|
|
* - m - names with 'm' have rules for interface and member
|
|
|
|
|
* - apxdp, dpxap - names that have contradicting rules, e.g. for apxdp there are "allow send_destination_prefix"
|
|
|
|
|
* rules first, followed by "deny send_destination_prefix" rules
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* basic checks - base allow */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.apf", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.apf.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
/* basic checks - base deny */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dpf", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dpf.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
/* With interface and method in the policy:
|
|
|
|
|
* everything is allowed, except foo.bar.a.CallDeny and whole foo.bar.d minus foo.bar.d.CallAllow.*/
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.a", "CallDeny", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.a", "CallAllow", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.a", "NonExistent", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.d", "CallDeny", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.d", "CallAllow", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.d", "NonExistent", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.none", "NonExistent", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.a", "CallDeny", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.a", "CallAllow", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.a", "NonExistent", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.d", "CallDeny", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.d", "CallAllow", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.d", "NonExistent", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.none", "NonExistent", TRUE, NULL);
|
|
|
|
|
/* With interface and method in the policy:
|
|
|
|
|
* everything is denied, except foo.bar.d.CallAllow and whole foo.bar.a minus foo.bar.a.CallDeny */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.a", "CallDeny", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.a", "CallAllow", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.a", "NonExistent", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.d", "CallDeny", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.d", "CallAllow", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.d", "NonExistent", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.none", "NonExistent", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.a", "CallDeny", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.a", "CallAllow", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.a", "NonExistent", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.d", "CallDeny", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.d", "CallAllow", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.d", "NonExistent", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.none", "NonExistent", FALSE, NULL);
|
|
|
|
|
/* multiple names owned - everything is allowed */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.ap.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.ao");
|
|
|
|
|
/* multiple names owned - mixed allow/deny, but denied wins */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.dp.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.do", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.do");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.dp.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ao");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ao.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.dp.f.f");
|
|
|
|
|
/* multiple names owned - mixed allow/deny, but allowed wins */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.ao.ao");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao.ao", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f1.ap.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f");
|
|
|
|
|
/* multiple names owned - everything is denied */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.do.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.do.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.dp.f");
|
|
|
|
|
/* holes in default allow */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.d", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ao");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f");
|
|
|
|
|
/* holes in holes in default allow */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.d.ap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.d.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.ap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.ap.a", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
/* redefinitions in default allow */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap.d", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.a", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap.f.a", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.f.f.f.ap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.f.f.f.ap.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
/* cancelled definitions in default allow */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.ap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.a", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
/* holes in default deny */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.a", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.a.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.do");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.do", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.do.f.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.do.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f.f.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f1.ap.f.f");
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
/* holes in holes in default deny */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.a.dp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.a.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.dp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.d", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.d.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
/* redefinitions in default deny */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.a", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.a.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.d", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.d.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.f.d", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.f.f.f.dp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.f.f.f.dp.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
/* cancelled definitions in default deny */
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.dp", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.d", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.d.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
static void
|
|
|
|
|
teardown (Fixture *f,
|
|
|
|
|
gconstpointer context G_GNUC_UNUSED)
|
|
|
|
|
{
|
|
|
|
|
dbus_error_free (&f->e);
|
|
|
|
|
g_clear_error (&f->ge);
|
|
|
|
|
|
|
|
|
|
if (f->left_conn != NULL)
|
2018-07-12 12:51:38 +01:00
|
|
|
{
|
|
|
|
|
test_connection_shutdown (f->ctx, f->left_conn);
|
|
|
|
|
dbus_connection_close (f->left_conn);
|
|
|
|
|
}
|
2011-03-11 13:13:17 +00:00
|
|
|
|
|
|
|
|
if (f->right_conn != NULL)
|
|
|
|
|
{
|
2018-07-23 18:02:42 +01:00
|
|
|
GList *link;
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
if (f->right_conn_echo)
|
|
|
|
|
{
|
2014-10-29 14:10:48 +00:00
|
|
|
dbus_connection_remove_filter (f->right_conn, echo_filter, f);
|
2011-03-11 13:13:17 +00:00
|
|
|
f->right_conn_echo = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-01 13:02:04 +01:00
|
|
|
if (f->right_conn_hold)
|
|
|
|
|
{
|
|
|
|
|
dbus_connection_remove_filter (f->right_conn, hold_filter, f);
|
|
|
|
|
f->right_conn_hold = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 18:02:42 +01:00
|
|
|
for (link = f->held_messages.head; link != NULL; link = link->next)
|
|
|
|
|
dbus_message_unref (link->data);
|
|
|
|
|
|
2016-07-01 13:02:04 +01:00
|
|
|
g_queue_clear (&f->held_messages);
|
|
|
|
|
|
2018-07-12 12:51:38 +01:00
|
|
|
test_connection_shutdown (f->ctx, f->right_conn);
|
2011-03-11 13:13:17 +00:00
|
|
|
dbus_connection_close (f->right_conn);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 19:15:05 +01:00
|
|
|
dbus_clear_connection (&f->left_conn);
|
|
|
|
|
dbus_clear_connection (&f->right_conn);
|
|
|
|
|
|
2011-03-11 13:24:08 +00:00
|
|
|
if (f->daemon_pid != 0)
|
|
|
|
|
{
|
2015-01-26 19:02:59 +00:00
|
|
|
test_kill_pid (f->daemon_pid);
|
2011-03-11 13:24:08 +00:00
|
|
|
g_spawn_close_pid (f->daemon_pid);
|
|
|
|
|
f->daemon_pid = 0;
|
|
|
|
|
}
|
Tests: allow dbus-glib to be replaced with use of libdbus-internal
We only use dbus-glib for its main loop; within dbus, DBusLoop is
available as an alternative, although it isn't thread-safe and
isn't public API.
For tests that otherwise only use libdbus public API, it's desirable to
be able to avoid DBusLoop, so we can run them against an installed
libdbus as an integration test. However, if we don't have dbus-glib,
we're going to have to use an in-tree main loop, which might as well
be DBusLoop.
The major disadvantage of using dbus-glib is that it isn't safe to
link both dbus-1 and dbus-internal at the same time. This is awkward
for a future test case that wants to use _dbus_getsid() in dbus-daemon.c,
but only on Windows (fd.o #54445). If we use the same API wrapper around
both dbus-glib and DBusLoop, we can compile that test against dbus-glib
or against DBusLoop, depending on the platform.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68852
Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
2013-09-02 16:32:31 +01:00
|
|
|
|
2015-02-05 18:30:36 +00:00
|
|
|
if (f->tmp_runtime_dir != NULL)
|
|
|
|
|
{
|
|
|
|
|
gchar *path;
|
|
|
|
|
|
|
|
|
|
/* the socket may exist */
|
|
|
|
|
path = g_strdup_printf ("%s/bus", f->tmp_runtime_dir);
|
2017-02-14 19:49:46 +00:00
|
|
|
|
|
|
|
|
test_remove_if_exists (path);
|
2015-02-05 18:30:36 +00:00
|
|
|
g_free (path);
|
|
|
|
|
/* there shouldn't be anything else in there */
|
2017-02-14 19:49:46 +00:00
|
|
|
test_rmdir_must_exist (f->tmp_runtime_dir);
|
2015-02-05 18:30:36 +00:00
|
|
|
|
|
|
|
|
/* we're relying on being single-threaded for this to be safe */
|
|
|
|
|
if (f->saved_runtime_dir != NULL)
|
|
|
|
|
g_setenv ("XDG_RUNTIME_DIR", f->saved_runtime_dir, TRUE);
|
|
|
|
|
else
|
|
|
|
|
g_unsetenv ("XDG_RUNTIME_DIR");
|
|
|
|
|
g_free (f->saved_runtime_dir);
|
|
|
|
|
g_free (f->tmp_runtime_dir);
|
|
|
|
|
}
|
|
|
|
|
|
Tests: allow dbus-glib to be replaced with use of libdbus-internal
We only use dbus-glib for its main loop; within dbus, DBusLoop is
available as an alternative, although it isn't thread-safe and
isn't public API.
For tests that otherwise only use libdbus public API, it's desirable to
be able to avoid DBusLoop, so we can run them against an installed
libdbus as an integration test. However, if we don't have dbus-glib,
we're going to have to use an in-tree main loop, which might as well
be DBusLoop.
The major disadvantage of using dbus-glib is that it isn't safe to
link both dbus-1 and dbus-internal at the same time. This is awkward
for a future test case that wants to use _dbus_getsid() in dbus-daemon.c,
but only on Windows (fd.o #54445). If we use the same API wrapper around
both dbus-glib and DBusLoop, we can compile that test against dbus-glib
or against DBusLoop, depending on the platform.
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=68852
Reviewed-by: Ralf Habacker <ralf.habacker@freenet.de>
2013-09-02 16:32:31 +01:00
|
|
|
test_main_context_unref (f->ctx);
|
2016-07-01 12:30:22 +01:00
|
|
|
g_free (f->address);
|
2011-03-11 13:13:17 +00:00
|
|
|
}
|
|
|
|
|
|
2011-03-11 13:24:08 +00:00
|
|
|
static Config limited_config = {
|
2015-02-05 18:30:36 +00:00
|
|
|
"34393", 10000, "valid-config-files/incoming-limit.conf",
|
2018-02-20 11:45:39 +00:00
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
2011-03-11 13:24:08 +00:00
|
|
|
};
|
|
|
|
|
|
2014-10-29 14:10:48 +00:00
|
|
|
static Config finite_timeout_config = {
|
2015-02-05 18:30:36 +00:00
|
|
|
NULL, 1, "valid-config-files/finite-timeout.conf",
|
2018-02-20 11:45:39 +00:00
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
2014-10-29 14:10:48 +00:00
|
|
|
};
|
|
|
|
|
|
2015-02-05 18:30:36 +00:00
|
|
|
#ifdef DBUS_UNIX
|
|
|
|
|
static Config listen_unix_runtime_config = {
|
|
|
|
|
"61303", 1, "valid-config-files/listen-unix-runtime.conf",
|
2018-02-20 11:45:39 +00:00
|
|
|
TEST_USER_ME, RELY_ON_DEFAULT
|
2015-02-05 18:30:36 +00:00
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-07-01 12:30:22 +01:00
|
|
|
static Config max_completed_connections_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/max-completed-connections.conf",
|
2018-02-20 11:45:39 +00:00
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
2016-07-01 12:30:22 +01:00
|
|
|
};
|
|
|
|
|
|
2016-07-01 13:02:04 +01:00
|
|
|
static Config max_replies_per_connection_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/max-replies-per-connection.conf",
|
2018-02-20 11:45:39 +00:00
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
2016-07-01 13:02:04 +01:00
|
|
|
};
|
|
|
|
|
|
2016-07-01 13:07:49 +01:00
|
|
|
static Config max_match_rules_per_connection_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/max-match-rules-per-connection.conf",
|
2018-02-20 11:45:39 +00:00
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
2016-07-01 13:07:49 +01:00
|
|
|
};
|
|
|
|
|
|
2016-07-01 13:17:23 +01:00
|
|
|
static Config max_names_per_connection_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/max-names-per-connection.conf",
|
2018-02-20 11:45:39 +00:00
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
2016-07-01 13:17:23 +01:00
|
|
|
};
|
|
|
|
|
|
2016-08-16 18:27:43 +01:00
|
|
|
#if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) && defined(HAVE_GIO_UNIX)
|
|
|
|
|
static Config pending_fd_timeout_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/pending-fd-timeout.conf",
|
2018-02-20 11:45:39 +00:00
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
2016-08-16 18:27:43 +01:00
|
|
|
};
|
2017-07-19 19:43:09 +01:00
|
|
|
|
|
|
|
|
static Config count_fds_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/count-fds.conf",
|
2018-02-20 11:45:39 +00:00
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(DBUS_UNIX)
|
|
|
|
|
static Config as_another_user_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/as-another-user.conf",
|
|
|
|
|
/* We start the dbus-daemon as root and drop privileges, like the
|
|
|
|
|
* real system bus does */
|
2019-07-02 20:42:54 +01:00
|
|
|
TEST_USER_ROOT_DROP_TO_MESSAGEBUS, SPECIFY_ADDRESS
|
2017-07-19 19:43:09 +01:00
|
|
|
};
|
Translate Python-based tests to C
This simplifies bootstrapping: now you don't have to build dbus,
build dbus-python (with GLib), and use dbus-python to test dbus.
It also avoids test failures when using facilities like
AddressSanitizer. When libdbus is built with AddressSanitizer, but the
system copies of Python and dbus-python were not, dbus-python will exit
the Python interpreter on load, because libasan wasn't already
initialized. The simplest way to avoid this is to not use Python:
the scripts are not *that* hard to translate into C.
Both of these tests happen to be conditionally compiled for Unix only.
test_activation_forking() relies on code in TestSuiteForkingEchoService
that calls fork(), which can only work on Unix; meanwhile,
test_system_signals() tests the system bus configuration, which is
only relevant to Unix because we don't support using dbus-daemon as
a privilege boundary on Windows (and in any case D-Bus is not a Windows
OS feature, so the system bus cannot be used to communicate with OS
services like it can on most Linux systems).
This is also a partial solution to
<https://gitlab.freedesktop.org/dbus/dbus/issues/135>, by reducing the
size of name-test/.
For this to work, we need to build the test-service helper executable
even if embedded tests are disabled.
Signed-off-by: Simon McVittie <smcv@collabora.com>
2018-11-16 18:53:11 +00:00
|
|
|
|
2019-03-23 22:18:11 +02:00
|
|
|
#ifdef ENABLE_TRADITIONAL_ACTIVATION
|
Translate Python-based tests to C
This simplifies bootstrapping: now you don't have to build dbus,
build dbus-python (with GLib), and use dbus-python to test dbus.
It also avoids test failures when using facilities like
AddressSanitizer. When libdbus is built with AddressSanitizer, but the
system copies of Python and dbus-python were not, dbus-python will exit
the Python interpreter on load, because libasan wasn't already
initialized. The simplest way to avoid this is to not use Python:
the scripts are not *that* hard to translate into C.
Both of these tests happen to be conditionally compiled for Unix only.
test_activation_forking() relies on code in TestSuiteForkingEchoService
that calls fork(), which can only work on Unix; meanwhile,
test_system_signals() tests the system bus configuration, which is
only relevant to Unix because we don't support using dbus-daemon as
a privilege boundary on Windows (and in any case D-Bus is not a Windows
OS feature, so the system bus cannot be used to communicate with OS
services like it can on most Linux systems).
This is also a partial solution to
<https://gitlab.freedesktop.org/dbus/dbus/issues/135>, by reducing the
size of name-test/.
For this to work, we need to build the test-service helper executable
even if embedded tests are disabled.
Signed-off-by: Simon McVittie <smcv@collabora.com>
2018-11-16 18:53:11 +00:00
|
|
|
static Config tmp_session_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/tmp-session.conf",
|
|
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static Config nearly_system_config = {
|
|
|
|
|
NULL, 1, "valid-config-files-system/tmp-session-like-system.conf",
|
|
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
|
|
|
|
};
|
2016-08-16 18:27:43 +01:00
|
|
|
#endif
|
2019-03-23 22:18:11 +02:00
|
|
|
#endif
|
2016-08-16 18:27:43 +01:00
|
|
|
|
2019-04-25 09:35:59 +02:00
|
|
|
static Config send_destination_prefix_config = {
|
|
|
|
|
NULL, 1, "valid-config-files/send-destination-prefix-rules.conf",
|
|
|
|
|
TEST_USER_ME, SPECIFY_ADDRESS
|
|
|
|
|
};
|
|
|
|
|
|
2011-03-11 13:13:17 +00:00
|
|
|
int
|
|
|
|
|
main (int argc,
|
|
|
|
|
char **argv)
|
|
|
|
|
{
|
2018-07-11 16:40:12 +01:00
|
|
|
int ret;
|
|
|
|
|
|
2015-02-03 14:45:35 +00:00
|
|
|
test_init (&argc, &argv);
|
2011-03-11 13:13:17 +00:00
|
|
|
|
|
|
|
|
g_test_add ("/echo/session", Fixture, NULL, setup, test_echo, teardown);
|
2011-03-11 13:24:08 +00:00
|
|
|
g_test_add ("/echo/limited", Fixture, &limited_config,
|
|
|
|
|
setup, test_echo, teardown);
|
2014-10-29 14:10:48 +00:00
|
|
|
g_test_add ("/no-reply/disconnect", Fixture, NULL,
|
|
|
|
|
setup, test_no_reply, teardown);
|
|
|
|
|
g_test_add ("/no-reply/timeout", Fixture, &finite_timeout_config,
|
|
|
|
|
setup, test_no_reply, teardown);
|
2013-08-22 18:21:58 +01:00
|
|
|
g_test_add ("/creds", Fixture, NULL, setup, test_creds, teardown);
|
2014-07-29 14:08:20 +01:00
|
|
|
g_test_add ("/processid", Fixture, NULL, setup, test_processid, teardown);
|
2014-12-19 19:17:14 +00:00
|
|
|
g_test_add ("/canonical-path/uae", Fixture, NULL,
|
|
|
|
|
setup, test_canonical_path_uae, teardown);
|
2016-07-01 12:30:22 +01:00
|
|
|
g_test_add ("/limits/max-completed-connections", Fixture,
|
|
|
|
|
&max_completed_connections_config,
|
|
|
|
|
setup, test_max_connections, teardown);
|
|
|
|
|
g_test_add ("/limits/max-connections-per-user", Fixture,
|
|
|
|
|
&max_connections_per_user_config,
|
|
|
|
|
setup, test_max_connections, teardown);
|
2016-07-01 13:02:04 +01:00
|
|
|
g_test_add ("/limits/max-replies-per-connection", Fixture,
|
|
|
|
|
&max_replies_per_connection_config,
|
|
|
|
|
setup, test_max_replies_per_connection, teardown);
|
2016-07-01 13:07:49 +01:00
|
|
|
g_test_add ("/limits/max-match-rules-per-connection", Fixture,
|
|
|
|
|
&max_match_rules_per_connection_config,
|
|
|
|
|
setup, test_max_match_rules_per_connection, teardown);
|
2016-07-01 13:17:23 +01:00
|
|
|
g_test_add ("/limits/max-names-per-connection", Fixture,
|
|
|
|
|
&max_names_per_connection_config,
|
|
|
|
|
setup, test_max_names_per_connection, teardown);
|
2017-06-02 12:22:59 +01:00
|
|
|
g_test_add ("/peer/ping", Fixture, NULL, setup, test_peer_ping, teardown);
|
|
|
|
|
g_test_add ("/peer/get-machine-id", Fixture, NULL,
|
|
|
|
|
setup, test_peer_get_machine_id, teardown);
|
2017-06-02 13:32:13 +01:00
|
|
|
g_test_add ("/properties/get-invalid-iface", Fixture, NULL,
|
|
|
|
|
setup, test_get_invalid_iface, teardown);
|
|
|
|
|
g_test_add ("/properties/get-invalid-path", Fixture, NULL,
|
|
|
|
|
setup, test_get_invalid_path, teardown);
|
|
|
|
|
g_test_add ("/properties/get-invalid", Fixture, NULL,
|
|
|
|
|
setup, test_get_invalid, teardown);
|
|
|
|
|
g_test_add ("/properties/get-all-invalid-iface", Fixture, NULL, setup,
|
|
|
|
|
test_get_all_invalid_iface, teardown);
|
|
|
|
|
g_test_add ("/properties/get-all-invalid-path", Fixture, NULL, setup,
|
|
|
|
|
test_get_all_invalid_path, teardown);
|
|
|
|
|
g_test_add ("/properties/set-invalid-iface", Fixture, NULL,
|
|
|
|
|
setup, test_set_invalid_iface, teardown);
|
|
|
|
|
g_test_add ("/properties/set-invalid-path", Fixture, NULL,
|
|
|
|
|
setup, test_set_invalid_path, teardown);
|
|
|
|
|
g_test_add ("/properties/set-invalid", Fixture, NULL,
|
|
|
|
|
setup, test_set_invalid, teardown);
|
|
|
|
|
g_test_add ("/properties/set", Fixture, NULL,
|
|
|
|
|
setup, test_set, teardown);
|
|
|
|
|
g_test_add ("/properties/features", Fixture, NULL,
|
|
|
|
|
setup, test_features, teardown);
|
|
|
|
|
g_test_add ("/properties/interfaces", Fixture, NULL, setup,
|
|
|
|
|
test_interfaces, teardown);
|
|
|
|
|
g_test_add ("/properties/get-all", Fixture, NULL, setup,
|
|
|
|
|
test_get_all, teardown);
|
2016-08-16 18:27:43 +01:00
|
|
|
|
|
|
|
|
#if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) && defined(HAVE_GIO_UNIX)
|
|
|
|
|
g_test_add ("/limits/pending-fd-timeout", Fixture,
|
|
|
|
|
&pending_fd_timeout_config,
|
|
|
|
|
setup, test_pending_fd_timeout, teardown);
|
2017-07-19 19:43:09 +01:00
|
|
|
g_test_add ("/policy/count-fds", Fixture, &count_fds_config,
|
|
|
|
|
setup, test_count_fds, teardown);
|
2016-08-16 18:27:43 +01:00
|
|
|
#endif
|
|
|
|
|
|
2015-02-05 18:30:36 +00:00
|
|
|
#ifdef DBUS_UNIX
|
|
|
|
|
/* We can't test this in loopback.c with the rest of unix:runtime=yes,
|
|
|
|
|
* because dbus_bus_get[_private] is the only way to use the default,
|
|
|
|
|
* and that blocks on a round-trip to the dbus-daemon */
|
|
|
|
|
g_test_add ("/unix-runtime-is-default", Fixture, &listen_unix_runtime_config,
|
|
|
|
|
setup, test_echo, teardown);
|
2018-02-20 11:45:39 +00:00
|
|
|
|
|
|
|
|
g_test_add ("/fd-limit/session", Fixture, NULL,
|
|
|
|
|
setup, test_fd_limit, teardown);
|
|
|
|
|
g_test_add ("/fd-limit/system", Fixture, &as_another_user_config,
|
|
|
|
|
setup, test_fd_limit, teardown);
|
Translate Python-based tests to C
This simplifies bootstrapping: now you don't have to build dbus,
build dbus-python (with GLib), and use dbus-python to test dbus.
It also avoids test failures when using facilities like
AddressSanitizer. When libdbus is built with AddressSanitizer, but the
system copies of Python and dbus-python were not, dbus-python will exit
the Python interpreter on load, because libasan wasn't already
initialized. The simplest way to avoid this is to not use Python:
the scripts are not *that* hard to translate into C.
Both of these tests happen to be conditionally compiled for Unix only.
test_activation_forking() relies on code in TestSuiteForkingEchoService
that calls fork(), which can only work on Unix; meanwhile,
test_system_signals() tests the system bus configuration, which is
only relevant to Unix because we don't support using dbus-daemon as
a privilege boundary on Windows (and in any case D-Bus is not a Windows
OS feature, so the system bus cannot be used to communicate with OS
services like it can on most Linux systems).
This is also a partial solution to
<https://gitlab.freedesktop.org/dbus/dbus/issues/135>, by reducing the
size of name-test/.
For this to work, we need to build the test-service helper executable
even if embedded tests are disabled.
Signed-off-by: Simon McVittie <smcv@collabora.com>
2018-11-16 18:53:11 +00:00
|
|
|
|
2019-03-23 22:18:11 +02:00
|
|
|
#ifdef ENABLE_TRADITIONAL_ACTIVATION
|
Translate Python-based tests to C
This simplifies bootstrapping: now you don't have to build dbus,
build dbus-python (with GLib), and use dbus-python to test dbus.
It also avoids test failures when using facilities like
AddressSanitizer. When libdbus is built with AddressSanitizer, but the
system copies of Python and dbus-python were not, dbus-python will exit
the Python interpreter on load, because libasan wasn't already
initialized. The simplest way to avoid this is to not use Python:
the scripts are not *that* hard to translate into C.
Both of these tests happen to be conditionally compiled for Unix only.
test_activation_forking() relies on code in TestSuiteForkingEchoService
that calls fork(), which can only work on Unix; meanwhile,
test_system_signals() tests the system bus configuration, which is
only relevant to Unix because we don't support using dbus-daemon as
a privilege boundary on Windows (and in any case D-Bus is not a Windows
OS feature, so the system bus cannot be used to communicate with OS
services like it can on most Linux systems).
This is also a partial solution to
<https://gitlab.freedesktop.org/dbus/dbus/issues/135>, by reducing the
size of name-test/.
For this to work, we need to build the test-service helper executable
even if embedded tests are disabled.
Signed-off-by: Simon McVittie <smcv@collabora.com>
2018-11-16 18:53:11 +00:00
|
|
|
g_test_add ("/activation/forking", Fixture, &tmp_session_config,
|
|
|
|
|
setup, test_activation_forking, teardown);
|
|
|
|
|
g_test_add ("/system-policy/allow-signals", Fixture, &nearly_system_config,
|
|
|
|
|
setup, test_system_signals, teardown);
|
2019-03-23 22:18:11 +02:00
|
|
|
#endif
|
2015-02-05 18:30:36 +00:00
|
|
|
#endif
|
2011-03-11 13:13:17 +00:00
|
|
|
|
2019-04-25 09:35:59 +02:00
|
|
|
g_test_add ("/system-policy/send-destination/prefix", Fixture, &send_destination_prefix_config,
|
|
|
|
|
setup, test_send_destination_prefix, teardown);
|
|
|
|
|
|
2018-07-11 16:40:12 +01:00
|
|
|
ret = g_test_run ();
|
|
|
|
|
dbus_shutdown ();
|
|
|
|
|
return ret;
|
2011-03-11 13:13:17 +00:00
|
|
|
}
|