qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

dbus-display-test.c (7334B)


      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 "ui/dbus-display1.h"
      7 
      8 static GDBusConnection*
      9 test_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 
     32 static void
     33 test_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 
     47 static void
     48 test_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 
     74 typedef struct TestDBusConsoleRegister {
     75     GMainLoop *loop;
     76     GThread *thread;
     77     GDBusConnection *listener_conn;
     78     GDBusObjectManagerServer *server;
     79 } TestDBusConsoleRegister;
     80 
     81 static 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 
     96 static void
     97 test_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 
    118 static void
    119 test_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 
    135 static gpointer
    136 test_dbus_p2p_server_setup_thread(gpointer data)
    137 {
    138     return test_dbus_p2p_from_fd(GPOINTER_TO_INT(data));
    139 }
    140 
    141 static void
    142 test_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 
    190 static void
    191 test_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 
    246 int
    247 main(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 }