11e8a1faeSThomas Huth #include "qemu/osdep.h"
21e8a1faeSThomas Huth #include <glib/gstdio.h>
31e8a1faeSThomas Huth #include <gio/gio.h>
4907b5105SMarc-André Lureau #include "libqtest.h"
51e8a1faeSThomas Huth #include "dbus-vmstate1.h"
61e8a1faeSThomas Huth #include "migration-helpers.h"
71e8a1faeSThomas Huth 
81e8a1faeSThomas Huth static char *workdir;
91e8a1faeSThomas Huth 
101e8a1faeSThomas Huth typedef struct TestServerId {
111e8a1faeSThomas Huth     const char *name;
121e8a1faeSThomas Huth     const char *data;
131e8a1faeSThomas Huth     size_t size;
141e8a1faeSThomas Huth } TestServerId;
151e8a1faeSThomas Huth 
161e8a1faeSThomas Huth static const TestServerId idA = {
171e8a1faeSThomas Huth     "idA", "I'am\0idA!", sizeof("I'am\0idA!")
181e8a1faeSThomas Huth };
191e8a1faeSThomas Huth 
201e8a1faeSThomas Huth static const TestServerId idB = {
211e8a1faeSThomas Huth     "idB", "I'am\0idB!", sizeof("I'am\0idB!")
221e8a1faeSThomas Huth };
231e8a1faeSThomas Huth 
241e8a1faeSThomas Huth typedef struct TestServer {
251e8a1faeSThomas Huth     const TestServerId *id;
261e8a1faeSThomas Huth     bool save_called;
271e8a1faeSThomas Huth     bool load_called;
281e8a1faeSThomas Huth } TestServer;
291e8a1faeSThomas Huth 
301e8a1faeSThomas Huth typedef struct Test {
311e8a1faeSThomas Huth     const char *id_list;
321e8a1faeSThomas Huth     bool migrate_fail;
331e8a1faeSThomas Huth     bool without_dst_b;
341e8a1faeSThomas Huth     TestServer srcA;
351e8a1faeSThomas Huth     TestServer dstA;
361e8a1faeSThomas Huth     TestServer srcB;
371e8a1faeSThomas Huth     TestServer dstB;
381e8a1faeSThomas Huth     GMainLoop *loop;
391e8a1faeSThomas Huth     QTestState *src_qemu;
401e8a1faeSThomas Huth } Test;
411e8a1faeSThomas Huth 
421e8a1faeSThomas Huth static gboolean
vmstate_load(VMState1 * object,GDBusMethodInvocation * invocation,const gchar * arg_data,gpointer user_data)431e8a1faeSThomas Huth vmstate_load(VMState1 *object, GDBusMethodInvocation *invocation,
441e8a1faeSThomas Huth              const gchar *arg_data, gpointer user_data)
451e8a1faeSThomas Huth {
461e8a1faeSThomas Huth     TestServer *h = user_data;
471e8a1faeSThomas Huth     g_autoptr(GVariant) var = NULL;
481e8a1faeSThomas Huth     GVariant *args;
491e8a1faeSThomas Huth     const uint8_t *data;
501e8a1faeSThomas Huth     size_t size;
511e8a1faeSThomas Huth 
521e8a1faeSThomas Huth     args = g_dbus_method_invocation_get_parameters(invocation);
531e8a1faeSThomas Huth     var = g_variant_get_child_value(args, 0);
541e8a1faeSThomas Huth     data = g_variant_get_fixed_array(var, &size, sizeof(char));
551e8a1faeSThomas Huth     g_assert_cmpuint(size, ==, h->id->size);
561e8a1faeSThomas Huth     g_assert(!memcmp(data, h->id->data, h->id->size));
571e8a1faeSThomas Huth     h->load_called = true;
581e8a1faeSThomas Huth 
591e8a1faeSThomas Huth     g_dbus_method_invocation_return_value(invocation, g_variant_new("()"));
601e8a1faeSThomas Huth     return TRUE;
611e8a1faeSThomas Huth }
621e8a1faeSThomas Huth 
631e8a1faeSThomas Huth static gboolean
vmstate_save(VMState1 * object,GDBusMethodInvocation * invocation,gpointer user_data)641e8a1faeSThomas Huth vmstate_save(VMState1 *object, GDBusMethodInvocation *invocation,
651e8a1faeSThomas Huth              gpointer user_data)
661e8a1faeSThomas Huth {
671e8a1faeSThomas Huth     TestServer *h = user_data;
681e8a1faeSThomas Huth     GVariant *var;
691e8a1faeSThomas Huth 
701e8a1faeSThomas Huth     var = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
711e8a1faeSThomas Huth                                     h->id->data, h->id->size, sizeof(char));
721e8a1faeSThomas Huth     g_dbus_method_invocation_return_value(invocation,
731e8a1faeSThomas Huth                                           g_variant_new("(@ay)", var));
741e8a1faeSThomas Huth     h->save_called = true;
751e8a1faeSThomas Huth 
761e8a1faeSThomas Huth     return TRUE;
771e8a1faeSThomas Huth }
781e8a1faeSThomas Huth 
791e8a1faeSThomas Huth typedef struct WaitNamed {
801e8a1faeSThomas Huth     GMainLoop *loop;
811e8a1faeSThomas Huth     bool named;
821e8a1faeSThomas Huth } WaitNamed;
831e8a1faeSThomas Huth 
841e8a1faeSThomas Huth static void
named_cb(GDBusConnection * connection,const gchar * name,gpointer user_data)851e8a1faeSThomas Huth named_cb(GDBusConnection *connection,
861e8a1faeSThomas Huth          const gchar *name,
871e8a1faeSThomas Huth          gpointer user_data)
881e8a1faeSThomas Huth {
891e8a1faeSThomas Huth     WaitNamed *t = user_data;
901e8a1faeSThomas Huth 
911e8a1faeSThomas Huth     t->named = true;
921e8a1faeSThomas Huth     g_main_loop_quit(t->loop);
931e8a1faeSThomas Huth }
941e8a1faeSThomas Huth 
951e8a1faeSThomas Huth static GDBusConnection *
get_connection(Test * test,guint * ownid)961e8a1faeSThomas Huth get_connection(Test *test, guint *ownid)
971e8a1faeSThomas Huth {
981e8a1faeSThomas Huth     g_autofree gchar *addr = NULL;
991e8a1faeSThomas Huth     WaitNamed *wait;
1001e8a1faeSThomas Huth     GError *err = NULL;
1011e8a1faeSThomas Huth     GDBusConnection *c;
1021e8a1faeSThomas Huth 
1031e8a1faeSThomas Huth     wait = g_new0(WaitNamed, 1);
1041e8a1faeSThomas Huth     wait->loop = test->loop;
1051e8a1faeSThomas Huth     addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SESSION, NULL, &err);
1061e8a1faeSThomas Huth     g_assert_no_error(err);
1071e8a1faeSThomas Huth 
1081e8a1faeSThomas Huth     c = g_dbus_connection_new_for_address_sync(
1091e8a1faeSThomas Huth         addr,
1101e8a1faeSThomas Huth         G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION |
1111e8a1faeSThomas Huth         G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
1121e8a1faeSThomas Huth         NULL, NULL, &err);
1131e8a1faeSThomas Huth     g_assert_no_error(err);
1141e8a1faeSThomas Huth     *ownid = g_bus_own_name_on_connection(c, "org.qemu.VMState1",
1151e8a1faeSThomas Huth                                           G_BUS_NAME_OWNER_FLAGS_NONE,
1161e8a1faeSThomas Huth                                           named_cb, named_cb, wait, g_free);
1171e8a1faeSThomas Huth     if (!wait->named) {
1181e8a1faeSThomas Huth         g_main_loop_run(wait->loop);
1191e8a1faeSThomas Huth     }
1201e8a1faeSThomas Huth 
1211e8a1faeSThomas Huth     return c;
1221e8a1faeSThomas Huth }
1231e8a1faeSThomas Huth 
1241e8a1faeSThomas Huth static GDBusObjectManagerServer *
get_server(GDBusConnection * conn,TestServer * s,const TestServerId * id)1251e8a1faeSThomas Huth get_server(GDBusConnection *conn, TestServer *s, const TestServerId *id)
1261e8a1faeSThomas Huth {
1271e8a1faeSThomas Huth     g_autoptr(GDBusObjectSkeleton) sk = NULL;
1281e8a1faeSThomas Huth     g_autoptr(VMState1Skeleton) v = NULL;
1291e8a1faeSThomas Huth     GDBusObjectManagerServer *os;
1301e8a1faeSThomas Huth 
1311e8a1faeSThomas Huth     s->id = id;
1321e8a1faeSThomas Huth     os = g_dbus_object_manager_server_new("/org/qemu");
1331e8a1faeSThomas Huth     sk = g_dbus_object_skeleton_new("/org/qemu/VMState1");
1341e8a1faeSThomas Huth 
1351e8a1faeSThomas Huth     v = VMSTATE1_SKELETON(vmstate1_skeleton_new());
1361e8a1faeSThomas Huth     g_object_set(v, "id", id->name, NULL);
1371e8a1faeSThomas Huth 
1381e8a1faeSThomas Huth     g_signal_connect(v, "handle-load", G_CALLBACK(vmstate_load), s);
1391e8a1faeSThomas Huth     g_signal_connect(v, "handle-save", G_CALLBACK(vmstate_save), s);
1401e8a1faeSThomas Huth 
1411e8a1faeSThomas Huth     g_dbus_object_skeleton_add_interface(sk, G_DBUS_INTERFACE_SKELETON(v));
1421e8a1faeSThomas Huth     g_dbus_object_manager_server_export(os, sk);
1431e8a1faeSThomas Huth     g_dbus_object_manager_server_set_connection(os, conn);
1441e8a1faeSThomas Huth 
1451e8a1faeSThomas Huth     return os;
1461e8a1faeSThomas Huth }
1471e8a1faeSThomas Huth 
1481e8a1faeSThomas Huth static void
set_id_list(Test * test,QTestState * s)1491e8a1faeSThomas Huth set_id_list(Test *test, QTestState *s)
1501e8a1faeSThomas Huth {
1511e8a1faeSThomas Huth     if (!test->id_list) {
1521e8a1faeSThomas Huth         return;
1531e8a1faeSThomas Huth     }
1541e8a1faeSThomas Huth 
1551e8a1faeSThomas Huth     g_assert(!qmp_rsp_is_err(qtest_qmp(s,
1561e8a1faeSThomas Huth         "{ 'execute': 'qom-set', 'arguments': "
1571e8a1faeSThomas Huth         "{ 'path': '/objects/dv', 'property': 'id-list', 'value': %s } }",
1581e8a1faeSThomas Huth         test->id_list)));
1591e8a1faeSThomas Huth }
1601e8a1faeSThomas Huth 
1611e8a1faeSThomas Huth static gpointer
dbus_vmstate_thread(gpointer data)1621e8a1faeSThomas Huth dbus_vmstate_thread(gpointer data)
1631e8a1faeSThomas Huth {
1641e8a1faeSThomas Huth     GMainLoop *loop = data;
1651e8a1faeSThomas Huth 
1661e8a1faeSThomas Huth     g_main_loop_run(loop);
1671e8a1faeSThomas Huth 
1681e8a1faeSThomas Huth     return NULL;
1691e8a1faeSThomas Huth }
1701e8a1faeSThomas Huth 
1711e8a1faeSThomas Huth static void
test_dbus_vmstate(Test * test)1721e8a1faeSThomas Huth test_dbus_vmstate(Test *test)
1731e8a1faeSThomas Huth {
1741e8a1faeSThomas Huth     g_autofree char *src_qemu_args = NULL;
1751e8a1faeSThomas Huth     g_autofree char *dst_qemu_args = NULL;
1761e8a1faeSThomas Huth     g_autoptr(GTestDBus) srcbus = NULL;
1771e8a1faeSThomas Huth     g_autoptr(GTestDBus) dstbus = NULL;
1781e8a1faeSThomas Huth     g_autoptr(GDBusConnection) srcconnA = NULL;
1791e8a1faeSThomas Huth     g_autoptr(GDBusConnection) srcconnB = NULL;
1801e8a1faeSThomas Huth     g_autoptr(GDBusConnection) dstconnA = NULL;
1811e8a1faeSThomas Huth     g_autoptr(GDBusConnection) dstconnB = NULL;
1821e8a1faeSThomas Huth     g_autoptr(GDBusObjectManagerServer) srcserverA = NULL;
1831e8a1faeSThomas Huth     g_autoptr(GDBusObjectManagerServer) srcserverB = NULL;
1841e8a1faeSThomas Huth     g_autoptr(GDBusObjectManagerServer) dstserverA = NULL;
1851e8a1faeSThomas Huth     g_autoptr(GDBusObjectManagerServer) dstserverB = NULL;
1861e8a1faeSThomas Huth     g_auto(GStrv) srcaddr = NULL;
1871e8a1faeSThomas Huth     g_auto(GStrv) dstaddr = NULL;
1881e8a1faeSThomas Huth     g_autoptr(GThread) thread = NULL;
1891e8a1faeSThomas Huth     g_autoptr(GMainLoop) loop = NULL;
1901e8a1faeSThomas Huth     g_autofree char *uri = NULL;
1911e8a1faeSThomas Huth     QTestState *src_qemu = NULL, *dst_qemu = NULL;
1921e8a1faeSThomas Huth     guint ownsrcA, ownsrcB, owndstA, owndstB;
1931e8a1faeSThomas Huth 
1941e8a1faeSThomas Huth     uri = g_strdup_printf("unix:%s/migsocket", workdir);
1951e8a1faeSThomas Huth 
1961e8a1faeSThomas Huth     loop = g_main_loop_new(NULL, FALSE);
1971e8a1faeSThomas Huth     test->loop = loop;
1981e8a1faeSThomas Huth 
1991e8a1faeSThomas Huth     srcbus = g_test_dbus_new(G_TEST_DBUS_NONE);
2001e8a1faeSThomas Huth     g_test_dbus_up(srcbus);
2011e8a1faeSThomas Huth     srcconnA = get_connection(test, &ownsrcA);
2021e8a1faeSThomas Huth     srcserverA = get_server(srcconnA, &test->srcA, &idA);
2031e8a1faeSThomas Huth     srcconnB = get_connection(test, &ownsrcB);
2041e8a1faeSThomas Huth     srcserverB = get_server(srcconnB, &test->srcB, &idB);
2051e8a1faeSThomas Huth 
2061e8a1faeSThomas Huth     /* remove ,guid=foo part */
2071e8a1faeSThomas Huth     srcaddr = g_strsplit(g_test_dbus_get_bus_address(srcbus), ",", 2);
2081e8a1faeSThomas Huth     src_qemu_args =
2091e8a1faeSThomas Huth         g_strdup_printf("-object dbus-vmstate,id=dv,addr=%s", srcaddr[0]);
2101e8a1faeSThomas Huth 
2111e8a1faeSThomas Huth     dstbus = g_test_dbus_new(G_TEST_DBUS_NONE);
2121e8a1faeSThomas Huth     g_test_dbus_up(dstbus);
2131e8a1faeSThomas Huth     dstconnA = get_connection(test, &owndstA);
2141e8a1faeSThomas Huth     dstserverA = get_server(dstconnA, &test->dstA, &idA);
2151e8a1faeSThomas Huth     if (!test->without_dst_b) {
2161e8a1faeSThomas Huth         dstconnB = get_connection(test, &owndstB);
2171e8a1faeSThomas Huth         dstserverB = get_server(dstconnB, &test->dstB, &idB);
2181e8a1faeSThomas Huth     }
2191e8a1faeSThomas Huth 
2201e8a1faeSThomas Huth     dstaddr = g_strsplit(g_test_dbus_get_bus_address(dstbus), ",", 2);
2211e8a1faeSThomas Huth     dst_qemu_args =
2221e8a1faeSThomas Huth         g_strdup_printf("-object dbus-vmstate,id=dv,addr=%s -incoming %s",
2231e8a1faeSThomas Huth                         dstaddr[0], uri);
2241e8a1faeSThomas Huth 
2251e8a1faeSThomas Huth     src_qemu = qtest_init(src_qemu_args);
2261e8a1faeSThomas Huth     dst_qemu = qtest_init(dst_qemu_args);
2271e8a1faeSThomas Huth     set_id_list(test, src_qemu);
2281e8a1faeSThomas Huth     set_id_list(test, dst_qemu);
2291e8a1faeSThomas Huth 
2301e8a1faeSThomas Huth     thread = g_thread_new("dbus-vmstate-thread", dbus_vmstate_thread, loop);
2311e8a1faeSThomas Huth 
2321e8a1faeSThomas Huth     migrate_qmp(src_qemu, uri, "{}");
2331e8a1faeSThomas Huth     test->src_qemu = src_qemu;
2341e8a1faeSThomas Huth     if (test->migrate_fail) {
2351e8a1faeSThomas Huth         wait_for_migration_fail(src_qemu, true);
236*1b0f1b14SBin Meng         qtest_set_expected_status(dst_qemu, EXIT_FAILURE);
2371e8a1faeSThomas Huth     } else {
2381e8a1faeSThomas Huth         wait_for_migration_complete(src_qemu);
2391e8a1faeSThomas Huth     }
2401e8a1faeSThomas Huth 
2411e8a1faeSThomas Huth     qtest_quit(dst_qemu);
2421e8a1faeSThomas Huth     qtest_quit(src_qemu);
2431e8a1faeSThomas Huth     g_bus_unown_name(ownsrcA);
2441e8a1faeSThomas Huth     g_bus_unown_name(ownsrcB);
2451e8a1faeSThomas Huth     g_bus_unown_name(owndstA);
2461e8a1faeSThomas Huth     if (!test->without_dst_b) {
2471e8a1faeSThomas Huth         g_bus_unown_name(owndstB);
2481e8a1faeSThomas Huth     }
2491e8a1faeSThomas Huth 
2501e8a1faeSThomas Huth     g_main_loop_quit(test->loop);
2511e8a1faeSThomas Huth }
2521e8a1faeSThomas Huth 
2531e8a1faeSThomas Huth static void
check_not_migrated(TestServer * s,TestServer * d)2541e8a1faeSThomas Huth check_not_migrated(TestServer *s, TestServer *d)
2551e8a1faeSThomas Huth {
2561e8a1faeSThomas Huth     assert(!s->save_called);
2571e8a1faeSThomas Huth     assert(!s->load_called);
2581e8a1faeSThomas Huth     assert(!d->save_called);
2591e8a1faeSThomas Huth     assert(!d->load_called);
2601e8a1faeSThomas Huth }
2611e8a1faeSThomas Huth 
2621e8a1faeSThomas Huth static void
check_migrated(TestServer * s,TestServer * d)2631e8a1faeSThomas Huth check_migrated(TestServer *s, TestServer *d)
2641e8a1faeSThomas Huth {
2651e8a1faeSThomas Huth     assert(s->save_called);
2661e8a1faeSThomas Huth     assert(!s->load_called);
2671e8a1faeSThomas Huth     assert(!d->save_called);
2681e8a1faeSThomas Huth     assert(d->load_called);
2691e8a1faeSThomas Huth }
2701e8a1faeSThomas Huth 
2711e8a1faeSThomas Huth static void
test_dbus_vmstate_without_list(void)2721e8a1faeSThomas Huth test_dbus_vmstate_without_list(void)
2731e8a1faeSThomas Huth {
2741e8a1faeSThomas Huth     Test test = { 0, };
2751e8a1faeSThomas Huth 
2761e8a1faeSThomas Huth     test_dbus_vmstate(&test);
2771e8a1faeSThomas Huth 
2781e8a1faeSThomas Huth     check_migrated(&test.srcA, &test.dstA);
2791e8a1faeSThomas Huth     check_migrated(&test.srcB, &test.dstB);
2801e8a1faeSThomas Huth }
2811e8a1faeSThomas Huth 
2821e8a1faeSThomas Huth static void
test_dbus_vmstate_with_list(void)2831e8a1faeSThomas Huth test_dbus_vmstate_with_list(void)
2841e8a1faeSThomas Huth {
2851e8a1faeSThomas Huth     Test test = { .id_list = "idA,idB" };
2861e8a1faeSThomas Huth 
2871e8a1faeSThomas Huth     test_dbus_vmstate(&test);
2881e8a1faeSThomas Huth 
2891e8a1faeSThomas Huth     check_migrated(&test.srcA, &test.dstA);
2901e8a1faeSThomas Huth     check_migrated(&test.srcB, &test.dstB);
2911e8a1faeSThomas Huth }
2921e8a1faeSThomas Huth 
2931e8a1faeSThomas Huth static void
test_dbus_vmstate_only_a(void)2941e8a1faeSThomas Huth test_dbus_vmstate_only_a(void)
2951e8a1faeSThomas Huth {
2961e8a1faeSThomas Huth     Test test = { .id_list = "idA" };
2971e8a1faeSThomas Huth 
2981e8a1faeSThomas Huth     test_dbus_vmstate(&test);
2991e8a1faeSThomas Huth 
3001e8a1faeSThomas Huth     check_migrated(&test.srcA, &test.dstA);
3011e8a1faeSThomas Huth     check_not_migrated(&test.srcB, &test.dstB);
3021e8a1faeSThomas Huth }
3031e8a1faeSThomas Huth 
3041e8a1faeSThomas Huth static void
test_dbus_vmstate_missing_src(void)3051e8a1faeSThomas Huth test_dbus_vmstate_missing_src(void)
3061e8a1faeSThomas Huth {
3071e8a1faeSThomas Huth     Test test = { .id_list = "idA,idC", .migrate_fail = true };
3081e8a1faeSThomas Huth 
3091e8a1faeSThomas Huth     /* run in subprocess to silence QEMU error reporting */
3101e8a1faeSThomas Huth     if (g_test_subprocess()) {
3111e8a1faeSThomas Huth         test_dbus_vmstate(&test);
3121e8a1faeSThomas Huth         check_not_migrated(&test.srcA, &test.dstA);
3131e8a1faeSThomas Huth         check_not_migrated(&test.srcB, &test.dstB);
3141e8a1faeSThomas Huth         return;
3151e8a1faeSThomas Huth     }
3161e8a1faeSThomas Huth 
3171e8a1faeSThomas Huth     g_test_trap_subprocess(NULL, 0, 0);
3181e8a1faeSThomas Huth     g_test_trap_assert_passed();
3191e8a1faeSThomas Huth }
3201e8a1faeSThomas Huth 
3211e8a1faeSThomas Huth static void
test_dbus_vmstate_missing_dst(void)3221e8a1faeSThomas Huth test_dbus_vmstate_missing_dst(void)
3231e8a1faeSThomas Huth {
3241e8a1faeSThomas Huth     Test test = { .id_list = "idA,idB",
3251e8a1faeSThomas Huth                   .without_dst_b = true,
3261e8a1faeSThomas Huth                   .migrate_fail = true };
3271e8a1faeSThomas Huth 
3281e8a1faeSThomas Huth     /* run in subprocess to silence QEMU error reporting */
3291e8a1faeSThomas Huth     if (g_test_subprocess()) {
3301e8a1faeSThomas Huth         test_dbus_vmstate(&test);
3311e8a1faeSThomas Huth         assert(test.srcA.save_called);
3321e8a1faeSThomas Huth         assert(test.srcB.save_called);
3331e8a1faeSThomas Huth         assert(!test.dstB.save_called);
3341e8a1faeSThomas Huth         return;
3351e8a1faeSThomas Huth     }
3361e8a1faeSThomas Huth 
3371e8a1faeSThomas Huth     g_test_trap_subprocess(NULL, 0, 0);
3381e8a1faeSThomas Huth     g_test_trap_assert_passed();
3391e8a1faeSThomas Huth }
3401e8a1faeSThomas Huth 
3411e8a1faeSThomas Huth int
main(int argc,char ** argv)3421e8a1faeSThomas Huth main(int argc, char **argv)
3431e8a1faeSThomas Huth {
3441e8a1faeSThomas Huth     GError *err = NULL;
3451e8a1faeSThomas Huth     g_autofree char *dbus_daemon = NULL;
3461e8a1faeSThomas Huth     int ret;
3471e8a1faeSThomas Huth 
3481e8a1faeSThomas Huth     dbus_daemon = g_build_filename(G_STRINGIFY(SRCDIR),
3491e8a1faeSThomas Huth                                    "tests",
3501e8a1faeSThomas Huth                                    "dbus-vmstate-daemon.sh",
3511e8a1faeSThomas Huth                                    NULL);
3521e8a1faeSThomas Huth     g_setenv("G_TEST_DBUS_DAEMON", dbus_daemon, true);
3531e8a1faeSThomas Huth 
3541e8a1faeSThomas Huth     g_test_init(&argc, &argv, NULL);
3551e8a1faeSThomas Huth 
3561e8a1faeSThomas Huth     workdir = g_dir_make_tmp("dbus-vmstate-test-XXXXXX", &err);
3571e8a1faeSThomas Huth     if (!workdir) {
3581e8a1faeSThomas Huth         g_error("Unable to create temporary dir: %s\n", err->message);
3591e8a1faeSThomas Huth         exit(1);
3601e8a1faeSThomas Huth     }
3611e8a1faeSThomas Huth 
3621e8a1faeSThomas Huth     g_setenv("DBUS_VMSTATE_TEST_TMPDIR", workdir, true);
3631e8a1faeSThomas Huth 
3641e8a1faeSThomas Huth     qtest_add_func("/dbus-vmstate/without-list",
3651e8a1faeSThomas Huth                    test_dbus_vmstate_without_list);
3661e8a1faeSThomas Huth     qtest_add_func("/dbus-vmstate/with-list",
3671e8a1faeSThomas Huth                    test_dbus_vmstate_with_list);
3681e8a1faeSThomas Huth     qtest_add_func("/dbus-vmstate/only-a",
3691e8a1faeSThomas Huth                    test_dbus_vmstate_only_a);
3701e8a1faeSThomas Huth     qtest_add_func("/dbus-vmstate/missing-src",
3711e8a1faeSThomas Huth                    test_dbus_vmstate_missing_src);
3721e8a1faeSThomas Huth     qtest_add_func("/dbus-vmstate/missing-dst",
3731e8a1faeSThomas Huth                    test_dbus_vmstate_missing_dst);
3741e8a1faeSThomas Huth 
3751e8a1faeSThomas Huth     ret = g_test_run();
3761e8a1faeSThomas Huth 
3771e8a1faeSThomas Huth     rmdir(workdir);
3781e8a1faeSThomas Huth     g_free(workdir);
3791e8a1faeSThomas Huth 
3801e8a1faeSThomas Huth     return ret;
3811e8a1faeSThomas Huth }
382