1 #include "qemu/osdep.h"
2 #include <glib/gstdio.h>
5 #include "dbus-vmstate1.h"
6 #include "migration-helpers.h"
10 typedef struct TestServerId
{
16 static const TestServerId idA
= {
17 "idA", "I'am\0idA!", sizeof("I'am\0idA!")
20 static const TestServerId idB
= {
21 "idB", "I'am\0idB!", sizeof("I'am\0idB!")
24 typedef struct TestServer
{
25 const TestServerId
*id
;
43 vmstate_load(VMState1
*object
, GDBusMethodInvocation
*invocation
,
44 const gchar
*arg_data
, gpointer user_data
)
46 TestServer
*h
= user_data
;
47 g_autoptr(GVariant
) var
= NULL
;
52 args
= g_dbus_method_invocation_get_parameters(invocation
);
53 var
= g_variant_get_child_value(args
, 0);
54 data
= g_variant_get_fixed_array(var
, &size
, sizeof(char));
55 g_assert_cmpuint(size
, ==, h
->id
->size
);
56 g_assert(!memcmp(data
, h
->id
->data
, h
->id
->size
));
57 h
->load_called
= true;
59 g_dbus_method_invocation_return_value(invocation
, g_variant_new("()"));
64 vmstate_save(VMState1
*object
, GDBusMethodInvocation
*invocation
,
67 TestServer
*h
= user_data
;
70 var
= g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE
,
71 h
->id
->data
, h
->id
->size
, sizeof(char));
72 g_dbus_method_invocation_return_value(invocation
,
73 g_variant_new("(@ay)", var
));
74 h
->save_called
= true;
79 typedef struct WaitNamed
{
85 named_cb(GDBusConnection
*connection
,
89 WaitNamed
*t
= user_data
;
92 g_main_loop_quit(t
->loop
);
95 static GDBusConnection
*
96 get_connection(Test
*test
, guint
*ownid
)
98 g_autofree gchar
*addr
= NULL
;
103 wait
= g_new0(WaitNamed
, 1);
104 wait
->loop
= test
->loop
;
105 addr
= g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SESSION
, NULL
, &err
);
106 g_assert_no_error(err
);
108 c
= g_dbus_connection_new_for_address_sync(
110 G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION
|
111 G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT
,
113 g_assert_no_error(err
);
114 *ownid
= g_bus_own_name_on_connection(c
, "org.qemu.VMState1",
115 G_BUS_NAME_OWNER_FLAGS_NONE
,
116 named_cb
, named_cb
, wait
, g_free
);
118 g_main_loop_run(wait
->loop
);
124 static GDBusObjectManagerServer
*
125 get_server(GDBusConnection
*conn
, TestServer
*s
, const TestServerId
*id
)
127 g_autoptr(GDBusObjectSkeleton
) sk
= NULL
;
128 g_autoptr(VMState1Skeleton
) v
= NULL
;
129 GDBusObjectManagerServer
*os
;
132 os
= g_dbus_object_manager_server_new("/org/qemu");
133 sk
= g_dbus_object_skeleton_new("/org/qemu/VMState1");
135 v
= VMSTATE1_SKELETON(vmstate1_skeleton_new());
136 g_object_set(v
, "id", id
->name
, NULL
);
138 g_signal_connect(v
, "handle-load", G_CALLBACK(vmstate_load
), s
);
139 g_signal_connect(v
, "handle-save", G_CALLBACK(vmstate_save
), s
);
141 g_dbus_object_skeleton_add_interface(sk
, G_DBUS_INTERFACE_SKELETON(v
));
142 g_dbus_object_manager_server_export(os
, sk
);
143 g_dbus_object_manager_server_set_connection(os
, conn
);
149 set_id_list(Test
*test
, QTestState
*s
)
151 if (!test
->id_list
) {
155 g_assert(!qmp_rsp_is_err(qtest_qmp(s
,
156 "{ 'execute': 'qom-set', 'arguments': "
157 "{ 'path': '/objects/dv', 'property': 'id-list', 'value': %s } }",
162 dbus_vmstate_thread(gpointer data
)
164 GMainLoop
*loop
= data
;
166 g_main_loop_run(loop
);
172 test_dbus_vmstate(Test
*test
)
174 g_autofree
char *src_qemu_args
= NULL
;
175 g_autofree
char *dst_qemu_args
= NULL
;
176 g_autoptr(GTestDBus
) srcbus
= NULL
;
177 g_autoptr(GTestDBus
) dstbus
= NULL
;
178 g_autoptr(GDBusConnection
) srcconnA
= NULL
;
179 g_autoptr(GDBusConnection
) srcconnB
= NULL
;
180 g_autoptr(GDBusConnection
) dstconnA
= NULL
;
181 g_autoptr(GDBusConnection
) dstconnB
= NULL
;
182 g_autoptr(GDBusObjectManagerServer
) srcserverA
= NULL
;
183 g_autoptr(GDBusObjectManagerServer
) srcserverB
= NULL
;
184 g_autoptr(GDBusObjectManagerServer
) dstserverA
= NULL
;
185 g_autoptr(GDBusObjectManagerServer
) dstserverB
= NULL
;
186 g_auto(GStrv
) srcaddr
= NULL
;
187 g_auto(GStrv
) dstaddr
= NULL
;
188 g_autoptr(GThread
) thread
= NULL
;
189 g_autoptr(GMainLoop
) loop
= NULL
;
190 g_autofree
char *uri
= NULL
;
191 QTestState
*src_qemu
= NULL
, *dst_qemu
= NULL
;
192 guint ownsrcA
, ownsrcB
, owndstA
, owndstB
;
194 uri
= g_strdup_printf("unix:%s/migsocket", workdir
);
196 loop
= g_main_loop_new(NULL
, FALSE
);
199 srcbus
= g_test_dbus_new(G_TEST_DBUS_NONE
);
200 g_test_dbus_up(srcbus
);
201 srcconnA
= get_connection(test
, &ownsrcA
);
202 srcserverA
= get_server(srcconnA
, &test
->srcA
, &idA
);
203 srcconnB
= get_connection(test
, &ownsrcB
);
204 srcserverB
= get_server(srcconnB
, &test
->srcB
, &idB
);
206 /* remove ,guid=foo part */
207 srcaddr
= g_strsplit(g_test_dbus_get_bus_address(srcbus
), ",", 2);
209 g_strdup_printf("-object dbus-vmstate,id=dv,addr=%s", srcaddr
[0]);
211 dstbus
= g_test_dbus_new(G_TEST_DBUS_NONE
);
212 g_test_dbus_up(dstbus
);
213 dstconnA
= get_connection(test
, &owndstA
);
214 dstserverA
= get_server(dstconnA
, &test
->dstA
, &idA
);
215 if (!test
->without_dst_b
) {
216 dstconnB
= get_connection(test
, &owndstB
);
217 dstserverB
= get_server(dstconnB
, &test
->dstB
, &idB
);
220 dstaddr
= g_strsplit(g_test_dbus_get_bus_address(dstbus
), ",", 2);
222 g_strdup_printf("-object dbus-vmstate,id=dv,addr=%s -incoming %s",
225 src_qemu
= qtest_init(src_qemu_args
);
226 dst_qemu
= qtest_init(dst_qemu_args
);
227 set_id_list(test
, src_qemu
);
228 set_id_list(test
, dst_qemu
);
230 thread
= g_thread_new("dbus-vmstate-thread", dbus_vmstate_thread
, loop
);
232 migrate_qmp(src_qemu
, uri
, "{}");
233 test
->src_qemu
= src_qemu
;
234 if (test
->migrate_fail
) {
235 wait_for_migration_fail(src_qemu
, true);
236 qtest_set_expected_status(dst_qemu
, EXIT_FAILURE
);
238 wait_for_migration_complete(src_qemu
);
241 qtest_quit(dst_qemu
);
242 qtest_quit(src_qemu
);
243 g_bus_unown_name(ownsrcA
);
244 g_bus_unown_name(ownsrcB
);
245 g_bus_unown_name(owndstA
);
246 if (!test
->without_dst_b
) {
247 g_bus_unown_name(owndstB
);
250 g_main_loop_quit(test
->loop
);
254 check_not_migrated(TestServer
*s
, TestServer
*d
)
256 assert(!s
->save_called
);
257 assert(!s
->load_called
);
258 assert(!d
->save_called
);
259 assert(!d
->load_called
);
263 check_migrated(TestServer
*s
, TestServer
*d
)
265 assert(s
->save_called
);
266 assert(!s
->load_called
);
267 assert(!d
->save_called
);
268 assert(d
->load_called
);
272 test_dbus_vmstate_without_list(void)
276 test_dbus_vmstate(&test
);
278 check_migrated(&test
.srcA
, &test
.dstA
);
279 check_migrated(&test
.srcB
, &test
.dstB
);
283 test_dbus_vmstate_with_list(void)
285 Test test
= { .id_list
= "idA,idB" };
287 test_dbus_vmstate(&test
);
289 check_migrated(&test
.srcA
, &test
.dstA
);
290 check_migrated(&test
.srcB
, &test
.dstB
);
294 test_dbus_vmstate_only_a(void)
296 Test test
= { .id_list
= "idA" };
298 test_dbus_vmstate(&test
);
300 check_migrated(&test
.srcA
, &test
.dstA
);
301 check_not_migrated(&test
.srcB
, &test
.dstB
);
305 test_dbus_vmstate_missing_src(void)
307 Test test
= { .id_list
= "idA,idC", .migrate_fail
= true };
309 /* run in subprocess to silence QEMU error reporting */
310 if (g_test_subprocess()) {
311 test_dbus_vmstate(&test
);
312 check_not_migrated(&test
.srcA
, &test
.dstA
);
313 check_not_migrated(&test
.srcB
, &test
.dstB
);
317 g_test_trap_subprocess(NULL
, 0, 0);
318 g_test_trap_assert_passed();
322 test_dbus_vmstate_missing_dst(void)
324 Test test
= { .id_list
= "idA,idB",
325 .without_dst_b
= true,
326 .migrate_fail
= true };
328 /* run in subprocess to silence QEMU error reporting */
329 if (g_test_subprocess()) {
330 test_dbus_vmstate(&test
);
331 assert(test
.srcA
.save_called
);
332 assert(test
.srcB
.save_called
);
333 assert(!test
.dstB
.save_called
);
337 g_test_trap_subprocess(NULL
, 0, 0);
338 g_test_trap_assert_passed();
342 main(int argc
, char **argv
)
345 g_autofree
char *dbus_daemon
= NULL
;
348 dbus_daemon
= g_build_filename(G_STRINGIFY(SRCDIR
),
350 "dbus-vmstate-daemon.sh",
352 g_setenv("G_TEST_DBUS_DAEMON", dbus_daemon
, true);
354 g_test_init(&argc
, &argv
, NULL
);
356 workdir
= g_dir_make_tmp("dbus-vmstate-test-XXXXXX", &err
);
358 g_error("Unable to create temporary dir: %s\n", err
->message
);
362 g_setenv("DBUS_VMSTATE_TEST_TMPDIR", workdir
, true);
364 qtest_add_func("/dbus-vmstate/without-list",
365 test_dbus_vmstate_without_list
);
366 qtest_add_func("/dbus-vmstate/with-list",
367 test_dbus_vmstate_with_list
);
368 qtest_add_func("/dbus-vmstate/only-a",
369 test_dbus_vmstate_only_a
);
370 qtest_add_func("/dbus-vmstate/missing-src",
371 test_dbus_vmstate_missing_src
);
372 qtest_add_func("/dbus-vmstate/missing-dst",
373 test_dbus_vmstate_missing_dst
);