qemu/tests/qtest/dbus-display-test.c
<<
>>
Prefs
   1#include "qemu/osdep.h"
   2#include "qemu/dbus.h"
   3#include <gio/gio.h>
   4#include <gio/gunixfdlist.h>
   5#include "libqos/libqtest.h"
   6#include "qemu-common.h"
   7#include "dbus-display1.h"
   8
   9static GDBusConnection*
  10test_dbus_p2p_from_fd(int fd)
  11{
  12    g_autoptr(GError) err = NULL;
  13    g_autoptr(GSocket) socket = NULL;
  14    g_autoptr(GSocketConnection) socketc = NULL;
  15    GDBusConnection *conn;
  16
  17    socket = g_socket_new_from_fd(fd, &err);
  18    g_assert_no_error(err);
  19
  20    socketc = g_socket_connection_factory_create_connection(socket);
  21    g_assert(socketc != NULL);
  22
  23    conn = g_dbus_connection_new_sync(
  24        G_IO_STREAM(socketc), NULL,
  25        G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
  26        G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING,
  27        NULL, NULL, &err);
  28    g_assert_no_error(err);
  29
  30    return conn;
  31}
  32
  33static void
  34test_setup(QTestState **qts, GDBusConnection **conn)
  35{
  36    int pair[2];
  37
  38    *qts = qtest_init("-display dbus,p2p=yes -name dbus-test");
  39
  40    g_assert_cmpint(socketpair(AF_UNIX, SOCK_STREAM, 0, pair), ==, 0);
  41
  42    qtest_qmp_add_client(*qts, "@dbus-display", pair[1]);
  43
  44    *conn = test_dbus_p2p_from_fd(pair[0]);
  45    g_dbus_connection_start_message_processing(*conn);
  46}
  47
  48static void
  49test_dbus_display_vm(void)
  50{
  51    g_autoptr(GError) err = NULL;
  52    g_autoptr(GDBusConnection) conn = NULL;
  53    g_autoptr(QemuDBusDisplay1VMProxy) vm = NULL;
  54    QTestState *qts = NULL;
  55
  56    test_setup(&qts, &conn);
  57
  58    vm = QEMU_DBUS_DISPLAY1_VM_PROXY(
  59        qemu_dbus_display1_vm_proxy_new_sync(
  60            conn,
  61            G_DBUS_PROXY_FLAGS_NONE,
  62            NULL,
  63            DBUS_DISPLAY1_ROOT "/VM",
  64            NULL,
  65            &err));
  66    g_assert_no_error(err);
  67
  68    g_assert_cmpstr(
  69        qemu_dbus_display1_vm_get_name(QEMU_DBUS_DISPLAY1_VM(vm)),
  70        ==,
  71        "dbus-test");
  72    qtest_quit(qts);
  73}
  74
  75typedef struct TestDBusConsoleRegister {
  76    GMainLoop *loop;
  77    GThread *thread;
  78    GDBusConnection *listener_conn;
  79    GDBusObjectManagerServer *server;
  80} TestDBusConsoleRegister;
  81
  82static gboolean listener_handle_scanout(
  83    QemuDBusDisplay1Listener *object,
  84    GDBusMethodInvocation *invocation,
  85    guint arg_width,
  86    guint arg_height,
  87    guint arg_stride,
  88    guint arg_pixman_format,
  89    GVariant *arg_data,
  90    TestDBusConsoleRegister *test)
  91{
  92    g_main_loop_quit(test->loop);
  93
  94    return DBUS_METHOD_INVOCATION_HANDLED;
  95}
  96
  97static void
  98test_dbus_console_setup_listener(TestDBusConsoleRegister *test)
  99{
 100    g_autoptr(GDBusObjectSkeleton) listener = NULL;
 101    g_autoptr(QemuDBusDisplay1ListenerSkeleton) iface = NULL;
 102
 103    test->server = g_dbus_object_manager_server_new(DBUS_DISPLAY1_ROOT);
 104    listener = g_dbus_object_skeleton_new(DBUS_DISPLAY1_ROOT "/Listener");
 105    iface = QEMU_DBUS_DISPLAY1_LISTENER_SKELETON(
 106        qemu_dbus_display1_listener_skeleton_new());
 107    g_object_connect(iface,
 108                     "signal::handle-scanout", listener_handle_scanout, test,
 109                     NULL);
 110    g_dbus_object_skeleton_add_interface(listener,
 111                                         G_DBUS_INTERFACE_SKELETON(iface));
 112    g_dbus_object_manager_server_export(test->server, listener);
 113    g_dbus_object_manager_server_set_connection(test->server,
 114                                                test->listener_conn);
 115
 116    g_dbus_connection_start_message_processing(test->listener_conn);
 117}
 118
 119static void
 120test_dbus_console_registered(GObject *source_object,
 121                             GAsyncResult *res,
 122                             gpointer user_data)
 123{
 124    TestDBusConsoleRegister *test = user_data;
 125    g_autoptr(GError) err = NULL;
 126
 127    qemu_dbus_display1_console_call_register_listener_finish(
 128        QEMU_DBUS_DISPLAY1_CONSOLE(source_object),
 129        NULL, res, &err);
 130    g_assert_no_error(err);
 131
 132    test->listener_conn = g_thread_join(test->thread);
 133    test_dbus_console_setup_listener(test);
 134}
 135
 136static gpointer
 137test_dbus_p2p_server_setup_thread(gpointer data)
 138{
 139    return test_dbus_p2p_from_fd(GPOINTER_TO_INT(data));
 140}
 141
 142static void
 143test_dbus_display_console(void)
 144{
 145    g_autoptr(GError) err = NULL;
 146    g_autoptr(GDBusConnection) conn = NULL;
 147    g_autoptr(QemuDBusDisplay1ConsoleProxy) console = NULL;
 148    g_autoptr(GUnixFDList) fd_list = NULL;
 149    g_autoptr(GMainLoop) loop = NULL;
 150    QTestState *qts = NULL;
 151    int pair[2], idx;
 152    TestDBusConsoleRegister test;
 153
 154    test_setup(&qts, &conn);
 155
 156    g_assert_cmpint(socketpair(AF_UNIX, SOCK_STREAM, 0, pair), ==, 0);
 157    fd_list = g_unix_fd_list_new();
 158    idx = g_unix_fd_list_append(fd_list, pair[1], NULL);
 159
 160    console = QEMU_DBUS_DISPLAY1_CONSOLE_PROXY(
 161        qemu_dbus_display1_console_proxy_new_sync(
 162            conn,
 163            G_DBUS_PROXY_FLAGS_NONE,
 164            NULL,
 165            "/org/qemu/Display1/Console_0",
 166            NULL,
 167            &err));
 168    g_assert_no_error(err);
 169
 170    test.loop = loop = g_main_loop_new(NULL, FALSE);
 171    test.thread = g_thread_new(NULL, test_dbus_p2p_server_setup_thread,
 172                               GINT_TO_POINTER(pair[0]));
 173
 174    qemu_dbus_display1_console_call_register_listener(
 175        QEMU_DBUS_DISPLAY1_CONSOLE(console),
 176        g_variant_new_handle(idx),
 177        G_DBUS_CALL_FLAGS_NONE,
 178        -1,
 179        fd_list,
 180        NULL,
 181        test_dbus_console_registered,
 182        &test);
 183
 184    g_main_loop_run(loop);
 185
 186    g_clear_object(&test.server);
 187    g_clear_object(&test.listener_conn);
 188    qtest_quit(qts);
 189}
 190
 191static void
 192test_dbus_display_keyboard(void)
 193{
 194    g_autoptr(GError) err = NULL;
 195    g_autoptr(GDBusConnection) conn = NULL;
 196    g_autoptr(QemuDBusDisplay1KeyboardProxy) keyboard = NULL;
 197    QTestState *qts = NULL;
 198
 199    test_setup(&qts, &conn);
 200
 201    keyboard = QEMU_DBUS_DISPLAY1_KEYBOARD_PROXY(
 202        qemu_dbus_display1_keyboard_proxy_new_sync(
 203            conn,
 204            G_DBUS_PROXY_FLAGS_NONE,
 205            NULL,
 206            "/org/qemu/Display1/Console_0",
 207            NULL,
 208            &err));
 209    g_assert_no_error(err);
 210
 211
 212    g_assert_cmpint(qtest_inb(qts, 0x64) & 0x1, ==, 0);
 213    g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0);
 214
 215    qemu_dbus_display1_keyboard_call_press_sync(
 216        QEMU_DBUS_DISPLAY1_KEYBOARD(keyboard),
 217        0x1C, /* qnum enter */
 218        G_DBUS_CALL_FLAGS_NONE,
 219        -1,
 220        NULL,
 221        &err);
 222    g_assert_no_error(err);
 223
 224    /* may be should wait for interrupt? */
 225    g_assert_cmpint(qtest_inb(qts, 0x64) & 0x1, ==, 1);
 226    g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0x5A); /* scan code 2 enter */
 227
 228    qemu_dbus_display1_keyboard_call_release_sync(
 229        QEMU_DBUS_DISPLAY1_KEYBOARD(keyboard),
 230        0x1C, /* qnum enter */
 231        G_DBUS_CALL_FLAGS_NONE,
 232        -1,
 233        NULL,
 234        &err);
 235    g_assert_no_error(err);
 236
 237    g_assert_cmpint(qtest_inb(qts, 0x64) & 0x1, ==, 1);
 238    g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0xF0); /* scan code 2 release */
 239    g_assert_cmpint(qtest_inb(qts, 0x60), ==, 0x5A); /* scan code 2 enter */
 240
 241    g_assert_cmpint(qemu_dbus_display1_keyboard_get_modifiers(
 242                        QEMU_DBUS_DISPLAY1_KEYBOARD(keyboard)), ==, 0);
 243
 244    qtest_quit(qts);
 245}
 246
 247int
 248main(int argc, char **argv)
 249{
 250    g_test_init(&argc, &argv, NULL);
 251
 252    qtest_add_func("/dbus-display/vm", test_dbus_display_vm);
 253    qtest_add_func("/dbus-display/console", test_dbus_display_console);
 254    qtest_add_func("/dbus-display/keyboard", test_dbus_display_keyboard);
 255
 256    return g_test_run();
 257}
 258