From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
To: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Cc: mprivozn@redhat.com, pbonzini@redhat.com, berrange@redhat.com,
qemu-devel@nongnu.org, quintela@redhat.com
Subject: Re: [PATCH v6 8/8] tests: add dbus-vmstate-test
Date: Fri, 13 Dec 2019 18:20:15 +0000 [thread overview]
Message-ID: <20191213182015.GR3713@work-vm> (raw)
In-Reply-To: <20191211134506.1803403-9-marcandre.lureau@redhat.com>
* Marc-André Lureau (marcandre.lureau@redhat.com) wrote:
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> +static gboolean
> +vmstate_save(VMState1 *object, GDBusMethodInvocation *invocation,
> + gpointer user_data)
> +{
> + TestServer *h = user_data;
> + GVariant *var;
> +
> + var = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
> + h->id->data, h->id->size, sizeof(char));
> + g_dbus_method_invocation_return_value(invocation,
> + g_variant_new("(@ay)", var));
> + h->save_called = true;
> +
> + return TRUE;
> +}
> +
> +static gboolean
> +wait_for_migration_complete(gpointer user_data)
It's a shame we don't have a way to share this with migration-test.c;
we occasionally add more debug/cases in there.
Dave
> +{
> + Test *test = user_data;
> + QDict *rsp_return;
> + bool stop = false;
> + const char *status;
> +
> + qtest_qmp_send(test->src_qemu, "{ 'execute': 'query-migrate' }");
> + rsp_return = qtest_qmp_receive_success(test->src_qemu, NULL, NULL);
> + status = qdict_get_str(rsp_return, "status");
> + if (g_str_equal(status, "completed") || g_str_equal(status, "failed")) {
> + stop = true;
> + g_assert_cmpstr(status, ==,
> + test->migrate_fail ? "failed" : "completed");
> + }
> + qobject_unref(rsp_return);
> +
> + if (stop) {
> + g_main_loop_quit(test->loop);
> + }
> + return stop ? G_SOURCE_REMOVE : G_SOURCE_CONTINUE;
> +}
> +
> +static void migrate(QTestState *who, const char *uri)
> +{
> + QDict *args, *rsp;
> +
> + args = qdict_new();
> + qdict_put_str(args, "uri", uri);
> +
> + rsp = qtest_qmp(who, "{ 'execute': 'migrate', 'arguments': %p }", args);
> +
> + g_assert(qdict_haskey(rsp, "return"));
> + qobject_unref(rsp);
> +}
> +
> +typedef struct WaitNamed {
> + GMainLoop *loop;
> + bool named;
> +} WaitNamed;
> +
> +static void
> +named_cb(GDBusConnection *connection,
> + const gchar *name,
> + gpointer user_data)
> +{
> + WaitNamed *t = user_data;
> +
> + t->named = true;
> + g_main_loop_quit(t->loop);
> +}
> +
> +static GDBusConnection *
> +get_connection(Test *test, guint *ownid)
> +{
> + g_autofree gchar *addr = NULL;
> + WaitNamed *wait;
> + GError *err = NULL;
> + GDBusConnection *c;
> +
> + wait = g_new0(WaitNamed, 1);
> + wait->loop = test->loop;
> + addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SESSION, NULL, &err);
> + g_assert_no_error(err);
> +
> + c = g_dbus_connection_new_for_address_sync(
> + addr,
> + G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION |
> + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
> + NULL, NULL, &err);
> + g_assert_no_error(err);
> + *ownid = g_bus_own_name_on_connection(c, "org.qemu.VMState1",
> + G_BUS_NAME_OWNER_FLAGS_NONE,
> + named_cb, named_cb, wait, g_free);
> + if (!wait->named) {
> + g_main_loop_run(wait->loop);
> + }
> +
> + return c;
> +}
> +
> +static GDBusObjectManagerServer *
> +get_server(GDBusConnection *conn, TestServer *s, const TestServerId *id)
> +{
> + g_autoptr(GDBusObjectSkeleton) sk = NULL;
> + g_autoptr(VMState1Skeleton) v = NULL;
> + GDBusObjectManagerServer *os;
> +
> + s->id = id;
> + os = g_dbus_object_manager_server_new("/org/qemu");
> + sk = g_dbus_object_skeleton_new("/org/qemu/VMState1");
> +
> + v = VMSTATE1_SKELETON(vmstate1_skeleton_new());
> + g_object_set(v, "id", id->name, NULL);
> +
> + g_signal_connect(v, "handle-load", G_CALLBACK(vmstate_load), s);
> + g_signal_connect(v, "handle-save", G_CALLBACK(vmstate_save), s);
> +
> + g_dbus_object_skeleton_add_interface(sk, G_DBUS_INTERFACE_SKELETON(v));
> + g_dbus_object_manager_server_export(os, sk);
> + g_dbus_object_manager_server_set_connection(os, conn);
> +
> + return os;
> +}
> +
> +static void
> +set_id_list(Test *test, QTestState *s)
> +{
> + if (!test->id_list) {
> + return;
> + }
> +
> + g_assert(!qmp_rsp_is_err(qtest_qmp(s,
> + "{ 'execute': 'qom-set', 'arguments': "
> + "{ 'path': '/objects/dv', 'property': 'id-list', 'value': %s } }",
> + test->id_list)));
> +}
> +static void
> +test_dbus_vmstate(Test *test)
> +{
> + g_autofree char *src_qemu_args = NULL;
> + g_autofree char *dst_qemu_args = NULL;
> + g_autoptr(GTestDBus) srcbus = NULL;
> + g_autoptr(GTestDBus) dstbus = NULL;
> + g_autoptr(GDBusConnection) srcconnA = NULL;
> + g_autoptr(GDBusConnection) srcconnB = NULL;
> + g_autoptr(GDBusConnection) dstconnA = NULL;
> + g_autoptr(GDBusConnection) dstconnB = NULL;
> + g_autoptr(GDBusObjectManagerServer) srcserverA = NULL;
> + g_autoptr(GDBusObjectManagerServer) srcserverB = NULL;
> + g_autoptr(GDBusObjectManagerServer) dstserverA = NULL;
> + g_autoptr(GDBusObjectManagerServer) dstserverB = NULL;
> + g_auto(GStrv) srcaddr = NULL;
> + g_auto(GStrv) dstaddr = NULL;
> + g_autofree char *uri = NULL;
> + QTestState *src_qemu = NULL, *dst_qemu = NULL;
> + guint ownsrcA, ownsrcB, owndstA, owndstB;
> +
> + uri = g_strdup_printf("unix:%s/migsocket", workdir);
> +
> + test->loop = g_main_loop_new(NULL, TRUE);
> +
> + srcbus = g_test_dbus_new(G_TEST_DBUS_NONE);
> + g_test_dbus_up(srcbus);
> + srcconnA = get_connection(test, &ownsrcA);
> + srcserverA = get_server(srcconnA, &test->srcA, &idA);
> + srcconnB = get_connection(test, &ownsrcB);
> + srcserverB = get_server(srcconnB, &test->srcB, &idB);
> +
> + /* remove ,guid=foo part */
> + srcaddr = g_strsplit(g_test_dbus_get_bus_address(srcbus), ",", 2);
> + src_qemu_args =
> + g_strdup_printf("-object dbus-vmstate,id=dv,addr=%s", srcaddr[0]);
> +
> + dstbus = g_test_dbus_new(G_TEST_DBUS_NONE);
> + g_test_dbus_up(dstbus);
> + dstconnA = get_connection(test, &owndstA);
> + dstserverA = get_server(dstconnA, &test->dstA, &idA);
> + if (!test->without_dst_b) {
> + dstconnB = get_connection(test, &owndstB);
> + dstserverB = get_server(dstconnB, &test->dstB, &idB);
> + }
> +
> + dstaddr = g_strsplit(g_test_dbus_get_bus_address(dstbus), ",", 2);
> + dst_qemu_args =
> + g_strdup_printf("-object dbus-vmstate,id=dv,addr=%s -incoming %s",
> + dstaddr[0], uri);
> +
> + src_qemu = qtest_init(src_qemu_args);
> + dst_qemu = qtest_init(dst_qemu_args);
> + set_id_list(test, src_qemu);
> + set_id_list(test, dst_qemu);
> +
> + migrate(src_qemu, uri);
> + test->src_qemu = src_qemu;
> + g_timeout_add_seconds(1, wait_for_migration_complete, test);
> +
> + g_main_loop_run(test->loop);
> + g_main_loop_unref(test->loop);
> +
> + if (test->migrate_fail) {
> + qtest_set_expected_status(dst_qemu, 1);
> + }
> + qtest_quit(dst_qemu);
> + qtest_quit(src_qemu);
> + g_bus_unown_name(ownsrcA);
> + g_bus_unown_name(ownsrcB);
> + g_bus_unown_name(owndstA);
> + if (!test->without_dst_b) {
> + g_bus_unown_name(owndstB);
> + }
> +}
> +
> +static void
> +check_not_migrated(TestServer *s, TestServer *d)
> +{
> + assert(!s->save_called);
> + assert(!s->load_called);
> + assert(!d->save_called);
> + assert(!d->load_called);
> +}
> +
> +static void
> +check_migrated(TestServer *s, TestServer *d)
> +{
> + assert(s->save_called);
> + assert(!s->load_called);
> + assert(!d->save_called);
> + assert(d->load_called);
> +}
> +
> +static void
> +test_dbus_vmstate_without_list(void)
> +{
> + Test test = { 0, };
> +
> + test_dbus_vmstate(&test);
> +
> + check_migrated(&test.srcA, &test.dstA);
> + check_migrated(&test.srcB, &test.dstB);
> +}
> +
> +static void
> +test_dbus_vmstate_with_list(void)
> +{
> + Test test = { .id_list = "idA,idB" };
> +
> + test_dbus_vmstate(&test);
> +
> + check_migrated(&test.srcA, &test.dstA);
> + check_migrated(&test.srcB, &test.dstB);
> +}
> +
> +static void
> +test_dbus_vmstate_only_a(void)
> +{
> + Test test = { .id_list = "idA" };
> +
> + test_dbus_vmstate(&test);
> +
> + check_migrated(&test.srcA, &test.dstA);
> + check_not_migrated(&test.srcB, &test.dstB);
> +}
> +
> +static void
> +test_dbus_vmstate_missing_src(void)
> +{
> + Test test = { .id_list = "idA,idC", .migrate_fail = true };
> +
> + /* run in subprocess to silence QEMU error reporting */
> + if (g_test_subprocess()) {
> + test_dbus_vmstate(&test);
> + check_not_migrated(&test.srcA, &test.dstA);
> + check_not_migrated(&test.srcB, &test.dstB);
> + return;
> + }
> +
> + g_test_trap_subprocess(NULL, 0, 0);
> + g_test_trap_assert_passed();
> +}
> +
> +static void
> +test_dbus_vmstate_missing_dst(void)
> +{
> + Test test = { .id_list = "idA,idB",
> + .without_dst_b = true,
> + .migrate_fail = true };
> +
> + /* run in subprocess to silence QEMU error reporting */
> + if (g_test_subprocess()) {
> + test_dbus_vmstate(&test);
> + assert(test.srcA.save_called);
> + assert(test.srcB.save_called);
> + assert(!test.dstB.save_called);
> + return;
> + }
> +
> + g_test_trap_subprocess(NULL, 0, 0);
> + g_test_trap_assert_passed();
> +}
> +
> +int
> +main(int argc, char **argv)
> +{
> + GError *err = NULL;
> + g_autofree char *dbus_daemon = NULL;
> + int ret;
> +
> + dbus_daemon = g_build_filename(G_STRINGIFY(SRCDIR),
> + "tests",
> + "dbus-vmstate-daemon.sh",
> + NULL);
> + g_setenv("G_TEST_DBUS_DAEMON", dbus_daemon, true);
> +
> + g_test_init(&argc, &argv, NULL);
> +
> + workdir = g_dir_make_tmp("dbus-vmstate-test-XXXXXX", &err);
> + if (!workdir) {
> + g_error("Unable to create temporary dir: %s\n", err->message);
> + exit(1);
> + }
> +
> + qtest_add_func("/dbus-vmstate/without-list",
> + test_dbus_vmstate_without_list);
> + qtest_add_func("/dbus-vmstate/with-list",
> + test_dbus_vmstate_with_list);
> + qtest_add_func("/dbus-vmstate/only-a",
> + test_dbus_vmstate_only_a);
> + qtest_add_func("/dbus-vmstate/missing-src",
> + test_dbus_vmstate_missing_src);
> + qtest_add_func("/dbus-vmstate/missing-dst",
> + test_dbus_vmstate_missing_dst);
> +
> + ret = g_test_run();
> +
> + rmdir(workdir);
> + g_free(workdir);
> +
> + return ret;
> +}
> diff --git a/tests/dbus-vmstate1.xml b/tests/dbus-vmstate1.xml
> new file mode 100644
> index 0000000000..cc8563be4c
> --- /dev/null
> +++ b/tests/dbus-vmstate1.xml
> @@ -0,0 +1,12 @@
> +<?xml version="1.0"?>
> +<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
> + <interface name="org.qemu.VMState1">
> + <property name="Id" type="s" access="read"/>
> + <method name="Load">
> + <arg type="ay" name="data" direction="in"/>
> + </method>
> + <method name="Save">
> + <arg type="ay" name="data" direction="out"/>
> + </method>
> + </interface>
> +</node>
> --
> 2.24.0.308.g228f53135a
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
next prev parent reply other threads:[~2019-12-13 21:24 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-11 13:44 [PATCH v6 0/8] Add dbus-vmstate Marc-André Lureau
2019-12-11 13:44 ` [PATCH v6 1/8] vmstate: add qom interface to get id Marc-André Lureau
2019-12-11 13:45 ` [PATCH v6 2/8] vmstate: replace DeviceState with VMStateIf Marc-André Lureau
2019-12-11 13:45 ` [PATCH v6 3/8] docs: start a document to describe D-Bus usage Marc-André Lureau
2019-12-12 11:36 ` Daniel P. Berrangé
2019-12-11 13:45 ` [PATCH v6 4/8] util: add dbus helper unit Marc-André Lureau
2019-12-12 11:38 ` Daniel P. Berrangé
2019-12-11 13:45 ` [PATCH v6 5/8] Add dbus-vmstate object Marc-André Lureau
2019-12-12 12:03 ` Daniel P. Berrangé
2019-12-16 7:44 ` Marc-André Lureau
2019-12-13 16:32 ` Dr. David Alan Gilbert
2019-12-11 13:45 ` [PATCH v6 6/8] configure: add GDBUS_CODEGEN Marc-André Lureau
2019-12-12 12:05 ` Daniel P. Berrangé
2019-12-19 12:54 ` Marc-André Lureau
2019-12-11 13:45 ` [PATCH v6 7/8] dockerfiles: add dbus-daemon to some of latest distributions Marc-André Lureau
2019-12-12 12:06 ` Daniel P. Berrangé
2019-12-19 12:23 ` Marc-André Lureau
2019-12-19 12:30 ` Daniel P. Berrangé
2019-12-11 13:45 ` [PATCH v6 8/8] tests: add dbus-vmstate-test Marc-André Lureau
2019-12-12 12:11 ` Daniel P. Berrangé
2019-12-13 18:20 ` Dr. David Alan Gilbert [this message]
2019-12-16 9:58 ` Daniel P. Berrangé
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191213182015.GR3713@work-vm \
--to=dgilbert@redhat.com \
--cc=berrange@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=mprivozn@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.