aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/qtest/dbus-display-test.c257
-rw-r--r--tests/qtest/meson.build8
2 files changed, 265 insertions, 0 deletions
diff --git a/tests/qtest/dbus-display-test.c b/tests/qtest/dbus-display-test.c
new file mode 100644
index 0000000000..43c77aff04
--- /dev/null
+++ b/tests/qtest/dbus-display-test.c
@@ -0,0 +1,257 @@
+#include "qemu/osdep.h"
+#include "qemu/dbus.h"
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+#include "libqos/libqtest.h"
+#include "qemu-common.h"
+#include "dbus-display1.h"
+
+static GDBusConnection*
+test_dbus_p2p_from_fd(int fd)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GSocket) socket = NULL;
+ g_autoptr(GSocketConnection) socketc = NULL;
+ GDBusConnection *conn;
+
+ socket = g_socket_new_from_fd(fd, &err);
+ g_assert_no_error(err);
+
+ socketc = g_socket_connection_factory_create_connection(socket);
+ g_assert(socketc != NULL);
+
+ conn = g_dbus_connection_new_sync(
+ G_IO_STREAM(socketc), NULL,
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+ G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING,
+ NULL, NULL, &err);
+ g_assert_no_error(err);
+
+ return conn;
+}
+
+static void
+test_setup(QTestState **qts, GDBusConnection **conn)
+{
+ int pair[2];
+
+ *qts = qtest_init("-display dbus,p2p=yes -name dbus-test");
+
+ g_assert_cmpint(socketpair(AF_UNIX, SOCK_STREAM, 0, pair), ==, 0);
+
+ qtest_qmp_add_client(*qts, "@dbus-display", pair[1]);
+
+ *conn = test_dbus_p2p_from_fd(pair[0]);
+ g_dbus_connection_start_message_processing(*conn);
+}
+
+static void
+test_dbus_display_vm(void)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GDBusConnection) conn = NULL;
+ g_autoptr(QemuDBusDisplay1VMProxy) vm = NULL;
+ QTestState *qts = NULL;
+
+ test_setup(&qts, &conn);
+
+ vm = QEMU_DBUS_DISPLAY1_VM_PROXY(
+ qemu_dbus_display1_vm_proxy_new_sync(
+ conn,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ DBUS_DISPLAY1_ROOT "/VM",
+ NULL,
+ &err));
+ g_assert_no_error(err);
+
+ g_assert_cmpstr(
+ qemu_dbus_display1_vm_get_name(QEMU_DBUS_DISPLAY1_VM(vm)),
+ ==,
+ "dbus-test");
+ qtest_quit(qts);
+}
+
+typedef struct TestDBusConsoleRegister {
+ GMainLoop *loop;
+ GThread *thread;
+ GDBusConnection *listener_conn;
+ GDBusObjectManagerServer *server;
+} TestDBusConsoleRegister;
+
+static gboolean listener_handle_scanout(
+ QemuDBusDisplay1Listener *object,
+ GDBusMethodInvocation *invocation,
+ guint arg_width,
+ guint arg_height,
+ guint arg_stride,
+ guint arg_pixman_format,
+ GVariant *arg_data,
+ TestDBusConsoleRegister *test)
+{
+ g_main_loop_quit(test->loop);
+
+ return DBUS_METHOD_INVOCATION_HANDLED;
+}
+
+static void
+test_dbus_console_setup_listener(TestDBusConsoleRegister *test)
+{
+ g_autoptr(GDBusObjectSkeleton) listener = NULL;
+ g_autoptr(QemuDBusDisplay1ListenerSkeleton) iface = NULL;
+
+ test->server = g_dbus_object_manager_server_new(DBUS_DISPLAY1_ROOT);
+ listener = g_dbus_object_skeleton_new(DBUS_DISPLAY1_ROOT "/Listener");
+ iface = QEMU_DBUS_DISPLAY1_LISTENER_SKELETON(
+ qemu_dbus_display1_listener_skeleton_new());
+ g_object_connect(iface,
+ "signal::handle-scanout", listener_handle_scanout, test,
+ NULL);
+ g_dbus_object_skeleton_add_interface(listener,
+ G_DBUS_INTERFACE_SKELETON(iface));
+ g_dbus_object_manager_server_export(test->server, listener);
+ g_dbus_object_manager_server_set_connection(test->server,
+ test->listener_conn);
+
+ g_dbus_connection_start_message_processing(test->listener_conn);
+}
+
+static void
+test_dbus_console_registered(GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ TestDBusConsoleRegister *test = user_data;
+ g_autoptr(GError) err = NULL;
+
+ qemu_dbus_display1_console_call_register_listener_finish(
+ QEMU_DBUS_DISPLAY1_CONSOLE(source_object),
+ NULL, res, &err);
+ g_assert_no_error(err);
+
+ test->listener_conn = g_thread_join(test->thread);
+ test_dbus_console_setup_listener(test);
+}
+
+static gpointer
+test_dbus_p2p_server_setup_thread(gpointer data)
+{
+ return test_dbus_p2p_from_fd(GPOINTER_TO_INT(data));
+}
+
+static void
+test_dbus_display_console(void)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GDBusConnection) conn = NULL;
+ g_autoptr(QemuDBusDisplay1ConsoleProxy) console = NULL;
+ g_autoptr(GUnixFDList) fd_list = NULL;
+ g_autoptr(GMainLoop) loop = NULL;
+ QTestState *qts = NULL;
+ int pair[2], idx;
+ TestDBusConsoleRegister test;
+
+ test_setup(&qts, &conn);
+
+ g_assert_cmpint(socketpair(AF_UNIX, SOCK_STREAM, 0, pair), ==, 0);
+ fd_list = g_unix_fd_list_new();
+ idx = g_unix_fd_list_append(fd_list, pair[1], NULL);
+
+ console = QEMU_DBUS_DISPLAY1_CONSOLE_PROXY(
+ qemu_dbus_display1_console_proxy_new_sync(
+ conn,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "/org/qemu/Display1/Console_0",
+ NULL,
+ &err));
+ g_assert_no_error(err);
+
+ test.loop = loop = g_main_loop_new(NULL, FALSE);
+ test.thread = g_thread_new(NULL, test_dbus_p2p_server_setup_thread,
+ GINT_TO_POINTER(pair[0]));
+
+ qemu_dbus_display1_console_call_register_listener(
+ QEMU_DBUS_DISPLAY1_CONSOLE(console),
+ g_variant_new_handle(idx),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ fd_list,
+ NULL,
+ test_dbus_console_registered,
+ &test);
+
+ g_main_loop_run(loop);
+
+ g_clear_object(&test.server);
+ g_clear_object(&test.listener_conn);
+ qtest_quit(qts);
+}
+
+static void
+test_dbus_display_keyboard(void)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GDBusConnection) conn = NULL;
+ g_autoptr(QemuDBusDisplay1KeyboardProxy) keyboard = NULL;
+ QTestState *qts = NULL;
+
+ test_setup(&qts, &conn);
+
+ keyboard = QEMU_DBUS_DISPLAY1_KEYBOARD_PROXY(
+ qemu_dbus_display1_keyboard_proxy_new_sync(
+ conn,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ "/org/qemu/Display1/Console_0",
+ NULL,
+ &err));
+ g_assert_no_error(err);
+
+
+ g_assert_cmpint(qtest_inb(qts, 0x64) & 0x1, ==, 0);
+ g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0);
+
+ qemu_dbus_display1_keyboard_call_press_sync(
+ QEMU_DBUS_DISPLAY1_KEYBOARD(keyboard),
+ 0x1C, /* qnum enter */
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err);
+ g_assert_no_error(err);
+
+ /* may be should wait for interrupt? */
+ g_assert_cmpint(qtest_inb(qts, 0x64) & 0x1, ==, 1);
+ g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0x5A); /* scan code 2 enter */
+
+ qemu_dbus_display1_keyboard_call_release_sync(
+ QEMU_DBUS_DISPLAY1_KEYBOARD(keyboard),
+ 0x1C, /* qnum enter */
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &err);
+ g_assert_no_error(err);
+
+ g_assert_cmpint(qtest_inb(qts, 0x64) & 0x1, ==, 1);
+ g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0xF0); /* scan code 2 release */
+ g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0x5A); /* scan code 2 enter */
+
+ g_assert_cmpint(qemu_dbus_display1_keyboard_get_modifiers(
+ QEMU_DBUS_DISPLAY1_KEYBOARD(keyboard)), ==, 0);
+
+ qtest_quit(qts);
+}
+
+int
+main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_func("/dbus-display/vm", test_dbus_display_vm);
+ qtest_add_func("/dbus-display/console", test_dbus_display_console);
+ qtest_add_func("/dbus-display/keyboard", test_dbus_display_keyboard);
+
+ return g_test_run();
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 913e987409..1b2bde6660 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -92,6 +92,10 @@ qtests_i386 = \
'test-x86-cpuid-compat',
'numa-test']
+if dbus_display
+ qtests_i386 += ['dbus-display-test']
+endif
+
dbus_daemon = find_program('dbus-daemon', required: false)
if dbus_daemon.found() and config_host.has_key('GDBUS_CODEGEN')
# Temporarily disabled due to Patchew failures:
@@ -265,6 +269,10 @@ qtests = {
'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
}
+if dbus_display
+qtests += {'dbus-display-test': [dbus_display1, gio]}
+endif
+
qtest_executables = {}
foreach dir : target_dirs
if not dir.endswith('-softmmu')