[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 28/36] tests: start dbus-display-test
From: |
marcandre . lureau |
Subject: |
[PULL 28/36] tests: start dbus-display-test |
Date: |
Fri, 17 Dec 2021 18:37:48 +0400 |
From: Marc-André Lureau <marcandre.lureau@redhat.com>
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>
---
tests/qtest/dbus-display-test.c | 257 ++++++++++++++++++++++++++++++++
tests/qtest/meson.build | 8 +
2 files changed, 265 insertions(+)
create mode 100644 tests/qtest/dbus-display-test.c
diff --git a/tests/qtest/dbus-display-test.c b/tests/qtest/dbus-display-test.c
new file mode 100644
index 000000000000..43c77aff045c
--- /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 913e987409d5..1b2bde666037 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')
--
2.34.1.8.g35151cf07204
- [PULL 18/36] console: save current scanout details, (continued)
- [PULL 18/36] console: save current scanout details, marcandre . lureau, 2021/12/17
- [PULL 19/36] scripts: teach modinfo to skip non-C sources, marcandre . lureau, 2021/12/17
- [PULL 20/36] docs/sphinx: add sphinx modules to include D-Bus documentation, marcandre . lureau, 2021/12/17
- [PULL 21/36] backends: move dbus-vmstate1.xml to backends/, marcandre . lureau, 2021/12/17
- [PULL 22/36] docs: move D-Bus VMState documentation to source XML, marcandre . lureau, 2021/12/17
- [PULL 23/36] docs: add dbus-display documentation, marcandre . lureau, 2021/12/17
- [PULL 24/36] build-sys: set glib dependency version, marcandre . lureau, 2021/12/17
- [PULL 25/36] ui: add a D-Bus display backend, marcandre . lureau, 2021/12/17
- [PULL 26/36] ui/dbus: add p2p=on/off option, marcandre . lureau, 2021/12/17
- [PULL 27/36] tests/qtests: add qtest_qmp_add_client(), marcandre . lureau, 2021/12/17
- [PULL 28/36] tests: start dbus-display-test,
marcandre . lureau <=
- [PULL 29/36] audio: add "dbus" audio backend, marcandre . lureau, 2021/12/17
- [PULL 30/36] ui/dbus: add clipboard interface, marcandre . lureau, 2021/12/17
- [PULL 31/36] chardev: teach socket to accept no addresses, marcandre . lureau, 2021/12/17
- [PULL 32/36] chardev: make socket derivable, marcandre . lureau, 2021/12/17
- [PULL 33/36] option: add g_auto for QemuOpts, marcandre . lureau, 2021/12/17
- [PULL 34/36] ui/dbus: add chardev backend & interface, marcandre . lureau, 2021/12/17
- [PULL 35/36] ui/dbus: register D-Bus VC handler, marcandre . lureau, 2021/12/17
- [PULL 36/36] MAINTAINERS: update D-Bus section, marcandre . lureau, 2021/12/17