aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2021-10-07 01:08:15 +0400
committerMarc-André Lureau <marcandre.lureau@redhat.com>2021-12-21 10:50:22 +0400
commitb4dd5b6a60eb525437c8d315d0d59dc25d4e4cb1 (patch)
treed789f5760f199996866721d316ea6fa837af7a2e
parent2c7294d72c4086fc89935514430bd2bfb5ae5011 (diff)
tests: start dbus-display-test
Cover basic display interface usage. More cases to be added to cover disconnections, multiple connections, corner cases. At this point, they would be better written in Rust or Python though. The proxy also covers reading the properties, since they are automatically loaded at creation. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com>
-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')