From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: marcandre.lureau@redhat.com, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 2/2] tests: add a local test for guest agent
Date: Wed, 09 Sep 2015 16:53:19 -0500 [thread overview]
Message-ID: <20150909215319.3885.37547@loki> (raw)
In-Reply-To: <1440672727-20231-2-git-send-email-marcandre.lureau@redhat.com>
Quoting marcandre.lureau@redhat.com (2015-08-27 05:52:07)
> From: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> Add some local guest agent tests (as it is better than nothing).
>
> They can be run inside or outside a VM, when run inside a VM, they will
> do a bit more side effects, such as freezing/thawing the FS or changing
> the time.
>
> A better test would involve a managed VM (or container), but it might be
> better to leave that off to autotest/avocado.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> tests/Makefile | 3 +
> tests/test-qga.c | 686 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 689 insertions(+)
> create mode 100644 tests/test-qga.c
>
> diff --git a/tests/Makefile b/tests/Makefile
> index 5271123..35671a1 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile
> @@ -76,6 +76,7 @@ check-unit-y += tests/test-write-threshold$(EXESUF)
> gcov-files-test-write-threshold-y = block/write-threshold.c
> check-unit-$(CONFIG_GNUTLS_HASH) += tests/test-crypto-hash$(EXESUF)
> check-unit-y += tests/test-crypto-cipher$(EXESUF)
> +check-unit-y += tests/test-qga$(EXESUF)
>
> check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
>
> @@ -425,6 +426,8 @@ endif
> qtest-obj-y = tests/libqtest.o libqemuutil.a libqemustub.a
> $(check-qtest-y): $(qtest-obj-y)
>
> +tests/test-qga: tests/test-qga.o $(qtest-obj-y)
> +
> .PHONY: check-help
> check-help:
> @echo "Regression testing targets:"
> diff --git a/tests/test-qga.c b/tests/test-qga.c
> new file mode 100644
> index 0000000..1fb58ec
> --- /dev/null
> +++ b/tests/test-qga.c
> @@ -0,0 +1,686 @@
> +#include <locale.h>
> +#include <glib.h>
> +#include <glib/gstdio.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <sys/un.h>
> +#include <unistd.h>
> +
> +#include "libqtest.h"
> +#include "config-host.h"
> +
> +typedef struct {
> + char *test_dir;
> + GMainLoop *loop;
> + int fd;
> + GPid pid;
> +} TestFixture;
> +
> +static int connect_qga(char *path)
> +{
> + int s, ret, len;
> + struct sockaddr_un remote;
> +
> + s = socket(AF_UNIX, SOCK_STREAM, 0);
> + g_assert(s != -1);
> +
> + remote.sun_family = AF_UNIX;
> + do {
> + strcpy(remote.sun_path, path);
> + len = strlen(remote.sun_path) + sizeof(remote.sun_family);
> + ret = connect(s, (struct sockaddr *)&remote, len);
> + if (ret == -1) {
> + g_usleep(G_USEC_PER_SEC);
> + }
> + } while (ret == -1);
I think we should loop on ECONNREFUSED (or whatever corresponds to
the socket not yet being created/bound), and the usual suspects
like EINTR. If it's anything else I don't think we'd want this to
loop indefinitely.
> +
> + return s;
> +}
> +
> +static void qga_watch(GPid pid, gint status, gpointer user_data)
> +{
> + TestFixture *fixture = user_data;
> +
> + g_assert_cmpint(status, ==, 0);
> + g_main_loop_quit(fixture->loop);
> +}
> +
> +static void
> +fixture_setup(TestFixture *fixture, gconstpointer data)
> +{
> + const gchar *extra_arg = data;
> + GError *error = NULL;
> + gchar *cwd, *path, *cmd, **argv = NULL;
> +
> + fixture->loop = g_main_loop_new(NULL, FALSE);
> +
> + fixture->test_dir = g_strdup("/tmp/qgatest.XXXXXX");
> + g_assert_nonnull(g_mkdtemp(fixture->test_dir));
> +
> + path = g_build_filename(fixture->test_dir, "sock", NULL);
> + cwd = g_get_current_dir();
> + cmd = g_strdup_printf("%s%cqemu-ga -m unix-listen -t %s -p %s %s %s",
Would be nice if we could also run qemu-ga.exe for a w32 build with
binfmt set up like some of the other tests, but no idea how we'd get
at it through wine. I guess it would have to be a serial connection
or something...
Probably too environment-specific for a useful unit test. I guess in
the future we could plumb in custom qemu-ga invocation/script that
does some extra setup on the backend (VM/container/wine) and exposes
that via a local socket like we'd get via -chardev.
> + cwd, G_DIR_SEPARATOR,
> + fixture->test_dir, path,
> + getenv("QTEST_LOG") ? "-v" : "",
> + extra_arg ?: "");
> + g_shell_parse_argv(cmd, NULL, &argv, &error);
> + g_assert_no_error(error);
> +
> + g_spawn_async(fixture->test_dir, argv, NULL,
> + G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD,
> + NULL, NULL, &fixture->pid, &error);
> + g_assert_no_error(error);
> +
> + g_child_watch_add(fixture->pid, qga_watch, fixture);
> +
> + fixture->fd = connect_qga(path);
> +
> + g_strfreev(argv);
> + g_free(cmd);
> + g_free(cwd);
> + g_free(path);
> +}
> +
> +static void
> +fixture_tear_down(TestFixture *fixture, gconstpointer data)
> +{
> + gchar *tmp;
> +
> + kill(fixture->pid, SIGTERM);
> +
> + g_main_loop_run(fixture->loop);
> + g_main_loop_unref(fixture->loop);
> +
> + g_spawn_close_pid(fixture->pid);
> +
> + tmp = g_build_filename(fixture->test_dir, "foo", NULL);
> + g_unlink(tmp);
> + g_free(tmp);
Shouldn't the individual unit tests clean these up? I think a flag
determining whether or not we're running locally (set by default
obviously) would be useful for determining whether it makes sense
for us to clean them up or not.
> +
> + tmp = g_build_filename(fixture->test_dir, "qga.state", NULL);
> + g_unlink(tmp);
> + g_free(tmp);
> +
> + tmp = g_build_filename(fixture->test_dir, "sock", NULL);
> + g_unlink(tmp);
> + g_free(tmp);
> +
> + g_rmdir(fixture->test_dir);
> + g_free(fixture->test_dir);
> +}
> +
> +static void qmp_assertion_message_error(const char *domain,
> + const char *file,
> + int line,
> + const char *func,
> + const char *expr,
> + QDict *dict)
> +{
> + const char *class, *desc;
> + char *s;
> + QDict *error;
> +
> + error = qdict_get_qdict(dict, "error");
> + class = qdict_get_try_str(error, "class");
> + desc = qdict_get_try_str(error, "desc");
> +
> + s = g_strdup_printf("assertion failed %s: %s %s", expr, class, desc);
> + g_assertion_message(domain, file, line, func, s);
> + g_free(s);
> +}
> +
> +#define qmp_assert_no_error(err) do { \
> + if (qdict_haskey(err, "error")) { \
> + qmp_assertion_message_error(G_LOG_DOMAIN, __FILE__, __LINE__, \
> + G_STRFUNC, #err, err); \
> + } \
> +} while (0)
> +
> +static void test_qga_sync_delimited(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + guint32 v, r = g_random_int();
> + unsigned char c;
> + QDict *ret;
> + gchar *cmd;
> +
> + cmd = g_strdup_printf("%c{'execute': 'guest-sync-delimited',"
> + " 'arguments': {'id': %u } }", 0xff, r);
> + qmp_fd_send(fixture->fd, cmd);
> + g_free(cmd);
> +
> + v = read(fixture->fd, &c, 1);
> + g_assert_cmpint(v, ==, 1);
> + g_assert_cmpint(c, ==, 0xff);
> +
> + ret = qmp_fd_receive(fixture->fd);
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + v = qdict_get_int(ret, "return");
> + g_assert_cmpint(r, ==, v);
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_sync(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + guint32 v, r = g_random_int();
> + QDict *ret;
> + gchar *cmd;
> +
> + cmd = g_strdup_printf("%c{'execute': 'guest-sync',"
> + " 'arguments': {'id': %u } }", 0xff, r);
> + ret = qmp_fd(fixture->fd, cmd);
> + g_free(cmd);
> +
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + v = qdict_get_int(ret, "return");
> + g_assert_cmpint(r, ==, v);
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_ping(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-ping'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_invalid_cmd(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret, *error;
> + const gchar *class, *desc;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-invalid-cmd'}");
> + g_assert_nonnull(ret);
> +
> + error = qdict_get_qdict(ret, "error");
> + class = qdict_get_try_str(error, "class");
> + desc = qdict_get_try_str(error, "desc");
> +
> + g_assert_cmpstr(class, ==, "CommandNotFound");
> + g_assert_cmpint(strlen(desc), >, 0);
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_info(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret, *val;
> + const gchar *version;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-info'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + val = qdict_get_qdict(ret, "return");
> + version = qdict_get_try_str(val, "version");
> + g_assert_cmpstr(version, ==, QEMU_VERSION);
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_get_vcpus(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> + QList *list;
> + const QListEntry *entry;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-vcpus'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + /* check there is at least a cpu */
> + list = qdict_get_qlist(ret, "return");
> + entry = qlist_first(list);
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "logical-id"));
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_get_fsinfo(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> + QList *list;
> + const QListEntry *entry;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-fsinfo'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + /* check there is at least a fs */
> + list = qdict_get_qlist(ret, "return");
> + entry = qlist_first(list);
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "mountpoint"));
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "type"));
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "disk"));
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_get_memory_block_info(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret, *val;
> + int64_t size;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-block-info'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + /* check there is at least some memory */
> + val = qdict_get_qdict(ret, "return");
> + size = qdict_get_int(val, "size");
> + g_assert_cmpint(size, >, 0);
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_get_memory_blocks(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> + QList *list;
> + const QListEntry *entry;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-memory-blocks'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + list = qdict_get_qlist(ret, "return");
> + entry = qlist_first(list);
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "phys-index"));
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"));
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_network_get_interfaces(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> + QList *list;
> + const QListEntry *entry;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-network-get-interfaces'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + /* check there is at least a cpu */
copy/paste artifact
> + list = qdict_get_qlist(ret, "return");
> + entry = qlist_first(list);
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name"));
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_file_ops(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + gchar *cmd, *path;
> + const gchar *b64;
> + QDict *ret, *val;
> + int64_t id, count, eof;
> + FILE *f;
> + char tmp[100];
> +
> + /* open */
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
> + " 'arguments': { 'path': 'foo', 'mode': 'w+' } }");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + id = qdict_get_int(ret, "return");
> + QDECREF(ret);
> +
> + /* write */
> + cmd = g_strdup_printf("{'execute': 'guest-file-write',"
> + " 'arguments': { 'handle': %" G_GINT64_FORMAT ","
> + " 'buf-b64': 'aGVsbG8gd29ybGQK' } }", id);
> + ret = qmp_fd(fixture->fd, cmd);
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + val = qdict_get_qdict(ret, "return");
> + count = qdict_get_int(val, "count");
> + eof = qdict_get_bool(val, "eof");
> + g_assert_cmpint(count, ==, 12);
> + g_assert_cmpint(eof, ==, 0);
> + QDECREF(ret);
> + g_free(cmd);
> +
> + /* flush */
> + cmd = g_strdup_printf("{'execute': 'guest-file-flush',"
> + " 'arguments': {'handle': %" G_GINT64_FORMAT "} }",
> + id);
> + ret = qmp_fd(fixture->fd, cmd);
> + QDECREF(ret);
> + g_free(cmd);
> +
> + /* close */
> + cmd = g_strdup_printf("{'execute': 'guest-file-close',"
> + " 'arguments': {'handle': %" G_GINT64_FORMAT "} }",
> + id);
> + ret = qmp_fd(fixture->fd, cmd);
> + QDECREF(ret);
> + g_free(cmd);
> +
> + /* check content */
> + path = g_build_filename(fixture->test_dir, "foo", NULL);
> + f = fopen(path, "r");
> + g_assert_nonnull(f);
> + count = fread(tmp, 1, sizeof(tmp), f);
> + g_assert_cmpint(count, ==, 12);
> + tmp[count] = 0;
> + g_assert_cmpstr(tmp, ==, "hello world\n");
> + fclose(f);
> +
> + /* open */
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-file-open',"
> + " 'arguments': { 'path': 'foo', 'mode': 'r' } }");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + id = qdict_get_int(ret, "return");
> + QDECREF(ret);
> +
> + /* read */
> + cmd = g_strdup_printf("{'execute': 'guest-file-read',"
> + " 'arguments': { 'handle': %" G_GINT64_FORMAT "} }",
> + id);
> + ret = qmp_fd(fixture->fd, cmd);
> + val = qdict_get_qdict(ret, "return");
> + count = qdict_get_int(val, "count");
> + eof = qdict_get_bool(val, "eof");
> + b64 = qdict_get_str(val, "buf-b64");
> + g_assert_cmpint(count, ==, 12);
> + g_assert(eof);
> + g_assert_cmpstr(b64, ==, "aGVsbG8gd29ybGQK");
> +
> + QDECREF(ret);
> + g_free(cmd);
> +
> + /* read eof */
> + cmd = g_strdup_printf("{'execute': 'guest-file-read',"
> + " 'arguments': { 'handle': %" G_GINT64_FORMAT "} }",
> + id);
> + ret = qmp_fd(fixture->fd, cmd);
> + val = qdict_get_qdict(ret, "return");
> + count = qdict_get_int(val, "count");
> + eof = qdict_get_bool(val, "eof");
> + b64 = qdict_get_str(val, "buf-b64");
> + g_assert_cmpint(count, ==, 0);
> + g_assert(eof);
> + g_assert_cmpstr(b64, ==, "");
> + QDECREF(ret);
> + g_free(cmd);
> +
> + /* seek */
> + cmd = g_strdup_printf("{'execute': 'guest-file-seek',"
> + " 'arguments': { 'handle': %" G_GINT64_FORMAT ", "
> + " 'offset': %d, 'whence': %d } }",
> + id, 6, SEEK_SET);
> + ret = qmp_fd(fixture->fd, cmd);
> + qmp_assert_no_error(ret);
> + val = qdict_get_qdict(ret, "return");
> + count = qdict_get_int(val, "position");
> + eof = qdict_get_bool(val, "eof");
> + g_assert_cmpint(count, ==, 6);
> + g_assert(!eof);
> + QDECREF(ret);
> + g_free(cmd);
> +
> + /* partial read */
> + cmd = g_strdup_printf("{'execute': 'guest-file-read',"
> + " 'arguments': { 'handle': %" G_GINT64_FORMAT "} }",
> + id);
> + ret = qmp_fd(fixture->fd, cmd);
> + val = qdict_get_qdict(ret, "return");
> + count = qdict_get_int(val, "count");
> + eof = qdict_get_bool(val, "eof");
> + b64 = qdict_get_str(val, "buf-b64");
> + g_assert_cmpint(count, ==, 6);
> + g_assert(eof);
> + g_assert_cmpstr(b64, ==, "d29ybGQK");
> +
> + QDECREF(ret);
> + g_free(cmd);
> +
> + /* close */
> + cmd = g_strdup_printf("{'execute': 'guest-file-close',"
> + " 'arguments': {'handle': %" G_GINT64_FORMAT "} }",
> + id);
> + ret = qmp_fd(fixture->fd, cmd);
I like having a complex test to make sure all the guest-file-* commands
interact properly, but would be good if we could preceed this with
simpler guest-file-* tests that test each command more granularly.
That could be added as a follow-up though, since this is still a good
test to have.
> + QDECREF(ret);
> + g_free(cmd);
> +}
> +
> +static void test_qga_get_time(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> + int64_t time;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + time = qdict_get_int(ret, "return");
> + g_assert_cmpint(time, >, 0);
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_set_time(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> + int64_t current, time;
> + gchar *cmd;
> +
> + /* get current time */
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + current = qdict_get_int(ret, "return");
> + g_assert_cmpint(current, >, 0);
> + QDECREF(ret);
> +
> + /* set some old time */
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-set-time',"
> + " 'arguments': { 'time': 1000 } }");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + QDECREF(ret);
> +
> + /* check old time */
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-get-time'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + time = qdict_get_int(ret, "return");
> + g_assert_cmpint(time / 1000, <, G_USEC_PER_SEC * 10);
> + QDECREF(ret);
> +
> + /* set back current time */
> + cmd = g_strdup_printf("{'execute': 'guest-set-time',"
> + " 'arguments': { 'time': %" G_GINT64_FORMAT " } }",
> + current + time * 1000);
> + ret = qmp_fd(fixture->fd, cmd);
Little concerned about playing with host time in our unit tests. Maybe
this sort of test should only be enabled if a flag is set, and turned
of by default?
Ah, I see that's where running_in_virt() comes into play. Nice :)
> + g_free(cmd);
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + QDECREF(ret);
> +}
> +
> +static void test_qga_fstrim(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> + QList *list;
> + const QListEntry *entry;
> +
> + /* get current time */
copy/paste artifact
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-fstrim',"
> + " arguments: { minimum: 4194304 } }");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + list = qdict_get_qlist(ret, "return");
> + entry = qlist_first(list);
> + g_assert(qdict_haskey(qobject_to_qdict(entry->value), "paths"));
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_blacklist(gconstpointer data)
> +{
> + TestFixture fix;
> + QDict *ret, *error;
> + const gchar *class, *desc;
> +
> + fixture_setup(&fix, "-b guest-ping,guest-get-time");
> +
> + /* check blacklist */
> + ret = qmp_fd(fix.fd, "{'execute': 'guest-ping'}");
> + g_assert_nonnull(ret);
> + error = qdict_get_qdict(ret, "error");
> + class = qdict_get_try_str(error, "class");
> + desc = qdict_get_try_str(error, "desc");
> + g_assert_cmpstr(class, ==, "GenericError");
> + g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
> + QDECREF(ret);
> +
> + ret = qmp_fd(fix.fd, "{'execute': 'guest-get-time'}");
> + g_assert_nonnull(ret);
> + error = qdict_get_qdict(ret, "error");
> + class = qdict_get_try_str(error, "class");
> + desc = qdict_get_try_str(error, "desc");
> + g_assert_cmpstr(class, ==, "GenericError");
> + g_assert_nonnull(g_strstr_len(desc, -1, "has been disabled"));
> + QDECREF(ret);
> +
> + /* check something work */
> + ret = qmp_fd(fix.fd, "{'execute': 'guest-get-fsinfo'}");
> + qmp_assert_no_error(ret);
> + QDECREF(ret);
> +
> + fixture_tear_down(&fix, NULL);
> +}
> +
> +static void test_qga_fsfreeze_status(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> + const gchar *status;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> +
> + status = qdict_get_try_str(ret, "return");
> + g_assert_cmpstr(status, ==, "thawed");
> +
> + QDECREF(ret);
> +}
> +
> +static void test_qga_fsfreeze_and_thaw(gconstpointer fix)
> +{
> + const TestFixture *fixture = fix;
> + QDict *ret;
> + const gchar *status;
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-freeze'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + QDECREF(ret);
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-status'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + status = qdict_get_try_str(ret, "return");
> + g_assert_cmpstr(status, ==, "frozen");
> + QDECREF(ret);
> +
> + ret = qmp_fd(fixture->fd, "{'execute': 'guest-fsfreeze-thaw'}");
> + g_assert_nonnull(ret);
> + qmp_assert_no_error(ret);
> + QDECREF(ret);
> +}
> +
> +static gboolean running_in_virt(const gchar *virt)
> +{
> + gchar *virt_what = NULL;
> + gint status;
> + gboolean success;
> +
> + success = g_spawn_command_line_sync("virt-what", &virt_what, NULL,
> + &status, NULL);
> +
> + success = success && status == 0 && g_strcmp0(virt_what, virt);
> +
> + g_free(virt_what);
> +
> + return success;
> +}
> +int main(int argc, char **argv)
> +{
> + TestFixture fix;
> + int ret;
> +
> + setlocale (LC_ALL, "");
> + g_test_init(&argc, &argv, NULL);
> + fixture_setup(&fix, NULL);
> +
> + g_test_add_data_func("/qga/sync-delimited", &fix, test_qga_sync_delimited);
> + g_test_add_data_func("/qga/sync", &fix, test_qga_sync);
> + g_test_add_data_func("/qga/ping", &fix, test_qga_ping);
> + g_test_add_data_func("/qga/info", &fix, test_qga_info);
> + g_test_add_data_func("/qga/network-get-interfaces", &fix,
> + test_qga_network_get_interfaces);
> + g_test_add_data_func("/qga/get-vcpus", &fix, test_qga_get_vcpus);
> + g_test_add_data_func("/qga/get-fsinfo", &fix, test_qga_get_fsinfo);
> + g_test_add_data_func("/qga/get-memory-block-info", &fix,
> + test_qga_get_memory_block_info);
> + g_test_add_data_func("/qga/get-memory-blocks", &fix,
> + test_qga_get_memory_blocks);
> + g_test_add_data_func("/qga/file-ops", &fix, test_qga_file_ops);
> + g_test_add_data_func("/qga/get-time", &fix, test_qga_get_time);
> + g_test_add_data_func("/qga/invalid-cmd", &fix, test_qga_invalid_cmd);
> + g_test_add_data_func("/qga/fsfreeze-status", &fix,
> + test_qga_fsfreeze_status);
> +
> + g_test_add_data_func("/qga/blacklist", NULL, test_qga_blacklist);
> +
> + if (running_in_virt("kvm")) {
> + g_test_add_data_func("/qga/fsfreeze-and-thaw", &fix,
> + test_qga_fsfreeze_and_thaw);
> + g_test_add_data_func("/qga/set-time", &fix, test_qga_set_time);
> + if (g_test_thorough()) {
> + g_test_add_data_func("/qga/fstrim", &fix, test_qga_fstrim);
> + }
> + }
> +
> + ret = g_test_run();
> +
> + fixture_tear_down(&fix, NULL);
> +
> + return ret;
> +}
> --
> 2.4.3
>
next prev parent reply other threads:[~2015-09-09 21:53 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-27 10:52 [Qemu-devel] [PATCH 1/2] qtest: add a few fd-level qmp helpers marcandre.lureau
2015-08-27 10:52 ` [Qemu-devel] [PATCH 2/2] tests: add a local test for guest agent marcandre.lureau
2015-08-27 11:36 ` Marc-André Lureau
2015-09-09 17:36 ` Michael Roth
2015-09-09 21:53 ` Michael Roth [this message]
2015-09-11 17:46 ` Marc-André Lureau
2015-09-09 20:05 ` [Qemu-devel] [PATCH 1/2] qtest: add a few fd-level qmp helpers Michael Roth
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=20150909215319.3885.37547@loki \
--to=mdroth@linux.vnet.ibm.com \
--cc=marcandre.lureau@redhat.com \
--cc=qemu-devel@nongnu.org \
/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.