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