* [Qemu-devel] [PATCH v2 1/3] qtest: Enable creation of multiple qemu instances
2012-12-20 17:14 [Qemu-devel] [PATCH v2 0/3] qtest: add migration testing Jason Baron
@ 2012-12-20 17:14 ` Jason Baron
2012-12-20 20:07 ` Blue Swirl
2012-12-20 17:14 ` [Qemu-devel] [PATCH v2 3/3] qtest: add migrate-test Jason Baron
2012-12-20 17:14 ` [Qemu-devel] [PATCH v2 2/3] qtest: extend qtest_qmp() to fill in the reply Jason Baron
2 siblings, 1 reply; 10+ messages in thread
From: Jason Baron @ 2012-12-20 17:14 UTC (permalink / raw)
To: qemu-devel
Cc: kwolf, aliguori, quintela, blauwirbel, andreas.faerber, pbonzini
From: Jason Baron <jbaron@redhat.com>
Currently, the qtest harness can only spawn 1 qemu instance at a time because
the parent pid is used to create the socket files. Use 'mkdtemp()' in
combination with the parent pid to avoid conflicts.
Signed-off-by: Jason Baron <jbaron@redhat.com>
---
tests/libqtest.c | 15 +++++++++------
1 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 71b84c1..57665c9 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -41,6 +41,7 @@ struct QTestState
GString *rx;
gchar *pid_file;
char *socket_path, *qmp_socket_path;
+ char *tmp_dir;
};
#define g_assert_no_errno(ret) do { \
@@ -105,7 +106,6 @@ QTestState *qtest_init(const char *extra_args)
{
QTestState *s;
int sock, qmpsock, ret, i;
- gchar *pid_file;
gchar *command;
const char *qemu_binary;
pid_t pid;
@@ -115,9 +115,11 @@ QTestState *qtest_init(const char *extra_args)
s = g_malloc(sizeof(*s));
- s->socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
- s->qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
- pid_file = g_strdup_printf("/tmp/qtest-%d.pid", getpid());
+ s->tmp_dir = g_strdup_printf("/tmp/qtest-%d-XXXXXX", getpid());
+ g_assert(mkdtemp(s->tmp_dir) != NULL);
+ s->socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "sock");
+ s->qmp_socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "qmp");
+ s->pid_file = g_strdup_printf("%s/%s", s->tmp_dir, "pid");
sock = init_socket(s->socket_path);
qmpsock = init_socket(s->qmp_socket_path);
@@ -131,7 +133,7 @@ QTestState *qtest_init(const char *extra_args)
"-pidfile %s "
"-machine accel=qtest "
"%s", qemu_binary, s->socket_path,
- s->qmp_socket_path, pid_file,
+ s->qmp_socket_path, s->pid_file,
extra_args ?: "");
ret = system(command);
@@ -143,7 +145,6 @@ QTestState *qtest_init(const char *extra_args)
s->qmp_fd = socket_accept(qmpsock);
s->rx = g_string_new("");
- s->pid_file = pid_file;
for (i = 0; i < MAX_IRQ; i++) {
s->irq_level[i] = false;
}
@@ -172,9 +173,11 @@ void qtest_quit(QTestState *s)
unlink(s->pid_file);
unlink(s->socket_path);
unlink(s->qmp_socket_path);
+ unlink(s->tmp_dir);
g_free(s->pid_file);
g_free(s->socket_path);
g_free(s->qmp_socket_path);
+ g_free(s->tmp_dir);
}
static void socket_sendf(int fd, const char *fmt, va_list ap)
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/3] qtest: Enable creation of multiple qemu instances
2012-12-20 17:14 ` [Qemu-devel] [PATCH v2 1/3] qtest: Enable creation of multiple qemu instances Jason Baron
@ 2012-12-20 20:07 ` Blue Swirl
2012-12-20 20:26 ` Jason Baron
0 siblings, 1 reply; 10+ messages in thread
From: Blue Swirl @ 2012-12-20 20:07 UTC (permalink / raw)
To: Jason Baron
Cc: kwolf, aliguori, quintela, qemu-devel, andreas.faerber, pbonzini
On Thu, Dec 20, 2012 at 5:14 PM, Jason Baron <jbaron@redhat.com> wrote:
> From: Jason Baron <jbaron@redhat.com>
>
> Currently, the qtest harness can only spawn 1 qemu instance at a time because
> the parent pid is used to create the socket files. Use 'mkdtemp()' in
But mkdtemp() is not available on Win32.
> combination with the parent pid to avoid conflicts.
>
> Signed-off-by: Jason Baron <jbaron@redhat.com>
> ---
> tests/libqtest.c | 15 +++++++++------
> 1 files changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/tests/libqtest.c b/tests/libqtest.c
> index 71b84c1..57665c9 100644
> --- a/tests/libqtest.c
> +++ b/tests/libqtest.c
> @@ -41,6 +41,7 @@ struct QTestState
> GString *rx;
> gchar *pid_file;
> char *socket_path, *qmp_socket_path;
> + char *tmp_dir;
> };
>
> #define g_assert_no_errno(ret) do { \
> @@ -105,7 +106,6 @@ QTestState *qtest_init(const char *extra_args)
> {
> QTestState *s;
> int sock, qmpsock, ret, i;
> - gchar *pid_file;
> gchar *command;
> const char *qemu_binary;
> pid_t pid;
> @@ -115,9 +115,11 @@ QTestState *qtest_init(const char *extra_args)
>
> s = g_malloc(sizeof(*s));
>
> - s->socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
> - s->qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
> - pid_file = g_strdup_printf("/tmp/qtest-%d.pid", getpid());
> + s->tmp_dir = g_strdup_printf("/tmp/qtest-%d-XXXXXX", getpid());
> + g_assert(mkdtemp(s->tmp_dir) != NULL);
> + s->socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "sock");
> + s->qmp_socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "qmp");
> + s->pid_file = g_strdup_printf("%s/%s", s->tmp_dir, "pid");
>
> sock = init_socket(s->socket_path);
> qmpsock = init_socket(s->qmp_socket_path);
> @@ -131,7 +133,7 @@ QTestState *qtest_init(const char *extra_args)
> "-pidfile %s "
> "-machine accel=qtest "
> "%s", qemu_binary, s->socket_path,
> - s->qmp_socket_path, pid_file,
> + s->qmp_socket_path, s->pid_file,
> extra_args ?: "");
>
> ret = system(command);
> @@ -143,7 +145,6 @@ QTestState *qtest_init(const char *extra_args)
> s->qmp_fd = socket_accept(qmpsock);
>
> s->rx = g_string_new("");
> - s->pid_file = pid_file;
> for (i = 0; i < MAX_IRQ; i++) {
> s->irq_level[i] = false;
> }
> @@ -172,9 +173,11 @@ void qtest_quit(QTestState *s)
> unlink(s->pid_file);
> unlink(s->socket_path);
> unlink(s->qmp_socket_path);
> + unlink(s->tmp_dir);
-EISDIR, rmdir() would be needed instead.
> g_free(s->pid_file);
> g_free(s->socket_path);
> g_free(s->qmp_socket_path);
> + g_free(s->tmp_dir);
> }
>
> static void socket_sendf(int fd, const char *fmt, va_list ap)
> --
> 1.7.1
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/3] qtest: Enable creation of multiple qemu instances
2012-12-20 20:07 ` Blue Swirl
@ 2012-12-20 20:26 ` Jason Baron
2012-12-20 20:38 ` Blue Swirl
2012-12-21 7:47 ` Markus Armbruster
0 siblings, 2 replies; 10+ messages in thread
From: Jason Baron @ 2012-12-20 20:26 UTC (permalink / raw)
To: Blue Swirl
Cc: kwolf, aliguori, quintela, qemu-devel, andreas.faerber, pbonzini
On Thu, Dec 20, 2012 at 08:07:02PM +0000, Blue Swirl wrote:
> On Thu, Dec 20, 2012 at 5:14 PM, Jason Baron <jbaron@redhat.com> wrote:
> > From: Jason Baron <jbaron@redhat.com>
> >
> > Currently, the qtest harness can only spawn 1 qemu instance at a time because
> > the parent pid is used to create the socket files. Use 'mkdtemp()' in
>
> But mkdtemp() is not available on Win32.
So this case important even for qtest?
>
> > combination with the parent pid to avoid conflicts.
> >
> > Signed-off-by: Jason Baron <jbaron@redhat.com>
> > ---
> > tests/libqtest.c | 15 +++++++++------
> > 1 files changed, 9 insertions(+), 6 deletions(-)
> >
> > diff --git a/tests/libqtest.c b/tests/libqtest.c
> > index 71b84c1..57665c9 100644
> > --- a/tests/libqtest.c
> > +++ b/tests/libqtest.c
> > @@ -41,6 +41,7 @@ struct QTestState
> > GString *rx;
> > gchar *pid_file;
> > char *socket_path, *qmp_socket_path;
> > + char *tmp_dir;
> > };
> >
> > #define g_assert_no_errno(ret) do { \
> > @@ -105,7 +106,6 @@ QTestState *qtest_init(const char *extra_args)
> > {
> > QTestState *s;
> > int sock, qmpsock, ret, i;
> > - gchar *pid_file;
> > gchar *command;
> > const char *qemu_binary;
> > pid_t pid;
> > @@ -115,9 +115,11 @@ QTestState *qtest_init(const char *extra_args)
> >
> > s = g_malloc(sizeof(*s));
> >
> > - s->socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
> > - s->qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
> > - pid_file = g_strdup_printf("/tmp/qtest-%d.pid", getpid());
> > + s->tmp_dir = g_strdup_printf("/tmp/qtest-%d-XXXXXX", getpid());
> > + g_assert(mkdtemp(s->tmp_dir) != NULL);
> > + s->socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "sock");
> > + s->qmp_socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "qmp");
> > + s->pid_file = g_strdup_printf("%s/%s", s->tmp_dir, "pid");
> >
> > sock = init_socket(s->socket_path);
> > qmpsock = init_socket(s->qmp_socket_path);
> > @@ -131,7 +133,7 @@ QTestState *qtest_init(const char *extra_args)
> > "-pidfile %s "
> > "-machine accel=qtest "
> > "%s", qemu_binary, s->socket_path,
> > - s->qmp_socket_path, pid_file,
> > + s->qmp_socket_path, s->pid_file,
> > extra_args ?: "");
> >
> > ret = system(command);
> > @@ -143,7 +145,6 @@ QTestState *qtest_init(const char *extra_args)
> > s->qmp_fd = socket_accept(qmpsock);
> >
> > s->rx = g_string_new("");
> > - s->pid_file = pid_file;
> > for (i = 0; i < MAX_IRQ; i++) {
> > s->irq_level[i] = false;
> > }
> > @@ -172,9 +173,11 @@ void qtest_quit(QTestState *s)
> > unlink(s->pid_file);
> > unlink(s->socket_path);
> > unlink(s->qmp_socket_path);
> > + unlink(s->tmp_dir);
>
> -EISDIR, rmdir() would be needed instead.
>
'unlink()' tested fine on Linux. But yes, it might not be as portable.
I looked at tempnam() and mktemp(), but they both generate linker warnings.
'mkstemp()' could be used but its awkward to delete the file right after
its created so that bind() can create it. Plus, it could be a greater
security risk in that the filename is easier to determine.
We could write our own random file string generator then, if mkdtemp(),
isn't ok.
> > g_free(s->pid_file);
> > g_free(s->socket_path);
> > g_free(s->qmp_socket_path);
> > + g_free(s->tmp_dir);
> > }
> >
> > static void socket_sendf(int fd, const char *fmt, va_list ap)
> > --
> > 1.7.1
> >
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/3] qtest: Enable creation of multiple qemu instances
2012-12-20 20:26 ` Jason Baron
@ 2012-12-20 20:38 ` Blue Swirl
2012-12-21 7:47 ` Markus Armbruster
1 sibling, 0 replies; 10+ messages in thread
From: Blue Swirl @ 2012-12-20 20:38 UTC (permalink / raw)
To: Jason Baron
Cc: kwolf, aliguori, quintela, qemu-devel, andreas.faerber, pbonzini
On Thu, Dec 20, 2012 at 8:26 PM, Jason Baron <jbaron@redhat.com> wrote:
> On Thu, Dec 20, 2012 at 08:07:02PM +0000, Blue Swirl wrote:
>> On Thu, Dec 20, 2012 at 5:14 PM, Jason Baron <jbaron@redhat.com> wrote:
>> > From: Jason Baron <jbaron@redhat.com>
>> >
>> > Currently, the qtest harness can only spawn 1 qemu instance at a time because
>> > the parent pid is used to create the socket files. Use 'mkdtemp()' in
>>
>> But mkdtemp() is not available on Win32.
>
> So this case important even for qtest?
Well, there's $(EXESUF) handling for qtest also. But it does not seem
to build now:
LINK tests/test-thread-pool.exe
tests/test-thread-pool.o: In function `test_cancel':
/src/qemu/tests/test-thread-pool.c:177: undefined reference to
`___sync_val_compare_and_swap_4'
tests/test-thread-pool.o: In function `worker_cb':
/src/qemu/tests/test-thread-pool.c:18: undefined reference to
`___sync_fetch_and_add_4'
>
>>
>> > combination with the parent pid to avoid conflicts.
>> >
>> > Signed-off-by: Jason Baron <jbaron@redhat.com>
>> > ---
>> > tests/libqtest.c | 15 +++++++++------
>> > 1 files changed, 9 insertions(+), 6 deletions(-)
>> >
>> > diff --git a/tests/libqtest.c b/tests/libqtest.c
>> > index 71b84c1..57665c9 100644
>> > --- a/tests/libqtest.c
>> > +++ b/tests/libqtest.c
>> > @@ -41,6 +41,7 @@ struct QTestState
>> > GString *rx;
>> > gchar *pid_file;
>> > char *socket_path, *qmp_socket_path;
>> > + char *tmp_dir;
>> > };
>> >
>> > #define g_assert_no_errno(ret) do { \
>> > @@ -105,7 +106,6 @@ QTestState *qtest_init(const char *extra_args)
>> > {
>> > QTestState *s;
>> > int sock, qmpsock, ret, i;
>> > - gchar *pid_file;
>> > gchar *command;
>> > const char *qemu_binary;
>> > pid_t pid;
>> > @@ -115,9 +115,11 @@ QTestState *qtest_init(const char *extra_args)
>> >
>> > s = g_malloc(sizeof(*s));
>> >
>> > - s->socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid());
>> > - s->qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid());
>> > - pid_file = g_strdup_printf("/tmp/qtest-%d.pid", getpid());
>> > + s->tmp_dir = g_strdup_printf("/tmp/qtest-%d-XXXXXX", getpid());
>> > + g_assert(mkdtemp(s->tmp_dir) != NULL);
>> > + s->socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "sock");
>> > + s->qmp_socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "qmp");
>> > + s->pid_file = g_strdup_printf("%s/%s", s->tmp_dir, "pid");
>> >
>> > sock = init_socket(s->socket_path);
>> > qmpsock = init_socket(s->qmp_socket_path);
>> > @@ -131,7 +133,7 @@ QTestState *qtest_init(const char *extra_args)
>> > "-pidfile %s "
>> > "-machine accel=qtest "
>> > "%s", qemu_binary, s->socket_path,
>> > - s->qmp_socket_path, pid_file,
>> > + s->qmp_socket_path, s->pid_file,
>> > extra_args ?: "");
>> >
>> > ret = system(command);
>> > @@ -143,7 +145,6 @@ QTestState *qtest_init(const char *extra_args)
>> > s->qmp_fd = socket_accept(qmpsock);
>> >
>> > s->rx = g_string_new("");
>> > - s->pid_file = pid_file;
>> > for (i = 0; i < MAX_IRQ; i++) {
>> > s->irq_level[i] = false;
>> > }
>> > @@ -172,9 +173,11 @@ void qtest_quit(QTestState *s)
>> > unlink(s->pid_file);
>> > unlink(s->socket_path);
>> > unlink(s->qmp_socket_path);
>> > + unlink(s->tmp_dir);
>>
>> -EISDIR, rmdir() would be needed instead.
>>
>
> 'unlink()' tested fine on Linux. But yes, it might not be as portable.
>
> I looked at tempnam() and mktemp(), but they both generate linker warnings.
> 'mkstemp()' could be used but its awkward to delete the file right after
> its created so that bind() can create it. Plus, it could be a greater
> security risk in that the filename is easier to determine.
>
> We could write our own random file string generator then, if mkdtemp(),
> isn't ok.
Or introduce qemu_mkdtemp() which resolves either to mkdtemp() or to a
custom implementation:
http://stackoverflow.com/questions/278439/creating-a-temporary-directory-in-windows
>
>> > g_free(s->pid_file);
>> > g_free(s->socket_path);
>> > g_free(s->qmp_socket_path);
>> > + g_free(s->tmp_dir);
>> > }
>> >
>> > static void socket_sendf(int fd, const char *fmt, va_list ap)
>> > --
>> > 1.7.1
>> >
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v2 1/3] qtest: Enable creation of multiple qemu instances
2012-12-20 20:26 ` Jason Baron
2012-12-20 20:38 ` Blue Swirl
@ 2012-12-21 7:47 ` Markus Armbruster
1 sibling, 0 replies; 10+ messages in thread
From: Markus Armbruster @ 2012-12-21 7:47 UTC (permalink / raw)
To: Jason Baron
Cc: kwolf, aliguori, quintela, qemu-devel, Blue Swirl,
andreas.faerber, pbonzini
Jason Baron <jbaron@redhat.com> writes:
> On Thu, Dec 20, 2012 at 08:07:02PM +0000, Blue Swirl wrote:
>> On Thu, Dec 20, 2012 at 5:14 PM, Jason Baron <jbaron@redhat.com> wrote:
>> > From: Jason Baron <jbaron@redhat.com>
[...]
>> > @@ -172,9 +173,11 @@ void qtest_quit(QTestState *s)
>> > unlink(s->pid_file);
>> > unlink(s->socket_path);
>> > unlink(s->qmp_socket_path);
>> > + unlink(s->tmp_dir);
>>
>> -EISDIR, rmdir() would be needed instead.
>>
>
> 'unlink()' tested fine on Linux. But yes, it might not be as portable.
s/might not be as/isn't/
SUSv7:
[EPERM]
The file named by path is a directory, and either the calling
process does not have appropriate privileges, or the implementation
prohibits using unlink() on directories.
[...]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v2 3/3] qtest: add migrate-test
2012-12-20 17:14 [Qemu-devel] [PATCH v2 0/3] qtest: add migration testing Jason Baron
2012-12-20 17:14 ` [Qemu-devel] [PATCH v2 1/3] qtest: Enable creation of multiple qemu instances Jason Baron
@ 2012-12-20 17:14 ` Jason Baron
2012-12-20 20:17 ` Blue Swirl
2012-12-20 17:14 ` [Qemu-devel] [PATCH v2 2/3] qtest: extend qtest_qmp() to fill in the reply Jason Baron
2 siblings, 1 reply; 10+ messages in thread
From: Jason Baron @ 2012-12-20 17:14 UTC (permalink / raw)
To: qemu-devel
Cc: kwolf, aliguori, quintela, blauwirbel, andreas.faerber, pbonzini
From: Jason Baron <jbaron@redhat.com>
Tests a single 'pc' machine migration on the same host.
Would be nice to extend the test matrix to various machine versions, but that
requires building multiple qemu binaries, which is a bit awkward in the
context of qtest. Testing migration between different machine versions with the
same binary doesn't seem too useful.
Signed-off-by: Jason Baron <jbaron@redhat.com>
---
tests/Makefile | 2 +
tests/libqtest.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++-
tests/libqtest.h | 15 +++++++-
tests/migrate-test.c | 68 ++++++++++++++++++++++++++++++++++
4 files changed, 179 insertions(+), 4 deletions(-)
create mode 100644 tests/migrate-test.c
diff --git a/tests/Makefile b/tests/Makefile
index 1756b47..3f0c5a2 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -25,6 +25,7 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
check-qtest-i386-y = tests/fdc-test$(EXESUF)
check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
check-qtest-i386-y += tests/rtc-test$(EXESUF)
+check-qtest-i386-y += tests/migrate-test$(EXESUF)
check-qtest-x86_64-y = $(check-qtest-i386-y)
check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
check-qtest-sparc64-y = tests/m48t59-test$(EXESUF)
@@ -78,6 +79,7 @@ tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o $(trace-obj-y)
tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o tests/libqtest.o $(trace-obj-y)
+tests/migrate-test$(EXESUF): tests/migrate-test.o
# QTest rules
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 994cd2f..28cbea9 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -28,6 +28,9 @@
#include "compiler.h"
#include "osdep.h"
+#include "qjson.h"
+#include "qdict.h"
+#include "qbool.h"
#define MAX_IRQ 256
@@ -42,6 +45,8 @@ struct QTestState
gchar *pid_file;
char *socket_path, *qmp_socket_path;
char *tmp_dir;
+ /* uri to use for incoming migration */
+ char *incoming_uri;
};
#define g_assert_no_errno(ret) do { \
@@ -102,7 +107,7 @@ static pid_t qtest_qemu_pid(QTestState *s)
return pid;
}
-QTestState *qtest_init(const char *extra_args)
+QTestState *qtest_init(const char *extra_args, const char *incoming_uri)
{
QTestState *s;
int sock, qmpsock, ret, i;
@@ -113,13 +118,14 @@ QTestState *qtest_init(const char *extra_args)
qemu_binary = getenv("QTEST_QEMU_BINARY");
g_assert(qemu_binary != NULL);
- s = g_malloc(sizeof(*s));
+ s = g_malloc0(sizeof(*s));
s->tmp_dir = g_strdup_printf("/tmp/qtest-%d-XXXXXX", getpid());
g_assert(mkdtemp(s->tmp_dir) != NULL);
s->socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "sock");
s->qmp_socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "qmp");
s->pid_file = g_strdup_printf("%s/%s", s->tmp_dir, "pid");
+ s->incoming_uri = g_strdup(incoming_uri);
sock = init_socket(s->socket_path);
qmpsock = init_socket(s->qmp_socket_path);
@@ -178,6 +184,7 @@ void qtest_quit(QTestState *s)
g_free(s->socket_path);
g_free(s->qmp_socket_path);
g_free(s->tmp_dir);
+ g_free(s->incoming_uri);
}
static void socket_sendf(int fd, const char *fmt, va_list ap)
@@ -482,3 +489,90 @@ void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size)
qtest_sendf(s, "\n");
qtest_rsp(s, 0);
}
+
+/**
+ * is_running:
+ * @mch: QTestState instance to check.
+ *
+ * Returns 1, if mch is running, 0 if its not running. -1 means retry.
+ */
+static int is_running(QTestState *mch)
+{
+ QString *resp = qstring_new();
+ QObject *resp_obj;
+ QObject *ret_obj;
+ QObject *run_obj;
+ int ret;
+
+ resp = qstring_new();
+ qtest_qmp_resp(mch, resp, "{ 'execute': 'query-status' }", NULL);
+
+ resp_obj = qobject_from_json(qstring_get_str(resp));
+ if ((!resp_obj) || (qobject_type(resp_obj) != QTYPE_QDICT)) {
+ ret = -1;
+ goto out;
+ }
+
+ ret_obj = qdict_get(qobject_to_qdict(resp_obj), "return");
+ if ((!ret_obj) || (qobject_type(ret_obj) != QTYPE_QDICT)) {
+ ret = -1;
+ goto out;
+ }
+
+ run_obj = qdict_get(qobject_to_qdict(ret_obj), "running");
+ if ((!run_obj) || (qobject_type(run_obj) != QTYPE_QBOOL)) {
+ ret = -1;
+ goto out;
+ }
+ ret = qbool_get_int(qobject_to_qbool(run_obj));
+
+out:
+ qobject_decref(resp_obj);
+ QDECREF(resp);
+ return ret;
+}
+
+#define SLEEP_INTERVAL 2
+/* Abort after 2 minutes */
+#define SLEEP_MAX (60 * 2)
+
+int test_migrate(QTestState *mach_src, QTestState *mach_dst)
+{
+ int src_run = 0;
+ int dst_run = 0;
+ int iter = 0;
+ gchar *migrate_str;
+
+ if (!mach_dst->incoming_uri) {
+ fprintf(stderr, "do_migrate: Error: mach_dst->incoming_uri not set\n");
+ return -1;
+ }
+
+ /* is running on mach_src ? */
+ if (is_running(mach_src) != 1) {
+ fprintf(stderr, "do_migrate: Error: not running on src\n");
+ return -1;
+ }
+
+ /* do migrate */
+ migrate_str = g_strdup_printf("{ 'execute': 'migrate',"
+ "'arguments': { 'uri': '%s' } }",
+ mach_dst->incoming_uri);
+ qtest_qmp(mach_src, migrate_str, NULL);
+ g_free(migrate_str);
+
+ while (iter < SLEEP_MAX) {
+ src_run = is_running(mach_src);
+ dst_run = is_running(mach_dst);
+ if ((src_run == 0) && (dst_run == 1)) {
+ break;
+ }
+ sleep(SLEEP_INTERVAL);
+ iter += SLEEP_INTERVAL;
+ }
+ if ((src_run != 0) || (dst_run != 1)) {
+ fprintf(stderr, "do_migrate: Error: migration failed\n");
+ return -1;
+ }
+ return 0;
+}
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 972ba5d..47d189b 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -27,8 +27,9 @@ extern QTestState *global_qtest;
/**
* qtest_init:
* @extra_args: other arguments to pass to QEMU.
+ * @incoming_uri: used for incoming migration.
*/
-QTestState *qtest_init(const char *extra_args);
+QTestState *qtest_init(const char *extra_args, const char *incoming_uri);
/**
* qtest_quit:
@@ -207,6 +208,16 @@ const char *qtest_get_arch(void);
void qtest_add_func(const char *str, void (*fn));
/**
+ * test_migrate:
+ * @mach_src: QTestState source.
+ * @mach_dst: QTestState destination.
+ *
+ * Migrate a VM from mach_src to mach_dst.
+ * Returns 0 on success, -1 on failure.
+ */
+int test_migrate(QTestState *mach_src, QTestState *mach_dst);
+
+/**
* qtest_start:
* @args: other arguments to pass to QEMU
*
@@ -214,7 +225,7 @@ void qtest_add_func(const char *str, void (*fn));
* The global variable is used by "shortcut" macros documented below.
*/
#define qtest_start(args) ( \
- global_qtest = qtest_init((args)) \
+ global_qtest = qtest_init((args), NULL) \
)
/**
diff --git a/tests/migrate-test.c b/tests/migrate-test.c
new file mode 100644
index 0000000..80ef815
--- /dev/null
+++ b/tests/migrate-test.c
@@ -0,0 +1,68 @@
+/*
+ * Migration tests
+ *
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Authors:
+ * Jason Baron <jbaron@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+#include "libqtest.h"
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static QTestState *mach_src;
+static QTestState *mach_dst;
+
+static void migrate_cleanup(void)
+{
+ if (mach_src) {
+ qtest_quit(mach_src);
+ }
+ if (mach_dst) {
+ qtest_quit(mach_dst);
+ }
+}
+
+static void test_migration(void)
+{
+ int ret;
+
+ ret = test_migrate(mach_src, mach_dst);
+ if (ret) {
+ migrate_cleanup();
+ g_assert(false);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ gchar *src_cmdline;
+ gchar *dst_cmdline;
+ const char *dst_uri = "tcp:0:4444";
+
+ g_test_init(&argc, &argv, NULL);
+
+ src_cmdline = g_strdup("-display none -machine pc");
+ mach_src = qtest_init(src_cmdline, NULL);
+
+ dst_cmdline = g_strdup_printf("%s -incoming %s", src_cmdline, dst_uri);
+ mach_dst = qtest_init(dst_cmdline, dst_uri);
+
+ g_free(src_cmdline);
+ g_free(dst_cmdline);
+
+ qtest_add_func("/migrate/src-to-dst", test_migration);
+ ret = g_test_run();
+
+ migrate_cleanup();
+ return ret;
+}
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v2 3/3] qtest: add migrate-test
2012-12-20 17:14 ` [Qemu-devel] [PATCH v2 3/3] qtest: add migrate-test Jason Baron
@ 2012-12-20 20:17 ` Blue Swirl
0 siblings, 0 replies; 10+ messages in thread
From: Blue Swirl @ 2012-12-20 20:17 UTC (permalink / raw)
To: Jason Baron
Cc: kwolf, aliguori, quintela, qemu-devel, andreas.faerber, pbonzini
On Thu, Dec 20, 2012 at 5:14 PM, Jason Baron <jbaron@redhat.com> wrote:
> From: Jason Baron <jbaron@redhat.com>
>
> Tests a single 'pc' machine migration on the same host.
>
> Would be nice to extend the test matrix to various machine versions, but that
> requires building multiple qemu binaries, which is a bit awkward in the
> context of qtest. Testing migration between different machine versions with the
> same binary doesn't seem too useful.
We could test migration between TCG, Xen and KVM if two of those are available.
>
> Signed-off-by: Jason Baron <jbaron@redhat.com>
> ---
> tests/Makefile | 2 +
> tests/libqtest.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++-
> tests/libqtest.h | 15 +++++++-
> tests/migrate-test.c | 68 ++++++++++++++++++++++++++++++++++
> 4 files changed, 179 insertions(+), 4 deletions(-)
> create mode 100644 tests/migrate-test.c
>
> diff --git a/tests/Makefile b/tests/Makefile
> index 1756b47..3f0c5a2 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile
> @@ -25,6 +25,7 @@ check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
> check-qtest-i386-y = tests/fdc-test$(EXESUF)
> check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
> check-qtest-i386-y += tests/rtc-test$(EXESUF)
> +check-qtest-i386-y += tests/migrate-test$(EXESUF)
> check-qtest-x86_64-y = $(check-qtest-i386-y)
> check-qtest-sparc-y = tests/m48t59-test$(EXESUF)
> check-qtest-sparc64-y = tests/m48t59-test$(EXESUF)
> @@ -78,6 +79,7 @@ tests/rtc-test$(EXESUF): tests/rtc-test.o $(trace-obj-y)
> tests/m48t59-test$(EXESUF): tests/m48t59-test.o $(trace-obj-y)
> tests/fdc-test$(EXESUF): tests/fdc-test.o tests/libqtest.o $(trace-obj-y)
> tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o tests/libqtest.o $(trace-obj-y)
> +tests/migrate-test$(EXESUF): tests/migrate-test.o
>
> # QTest rules
>
> diff --git a/tests/libqtest.c b/tests/libqtest.c
> index 994cd2f..28cbea9 100644
> --- a/tests/libqtest.c
> +++ b/tests/libqtest.c
> @@ -28,6 +28,9 @@
>
> #include "compiler.h"
> #include "osdep.h"
> +#include "qjson.h"
> +#include "qdict.h"
> +#include "qbool.h"
>
> #define MAX_IRQ 256
>
> @@ -42,6 +45,8 @@ struct QTestState
> gchar *pid_file;
> char *socket_path, *qmp_socket_path;
> char *tmp_dir;
> + /* uri to use for incoming migration */
> + char *incoming_uri;
> };
>
> #define g_assert_no_errno(ret) do { \
> @@ -102,7 +107,7 @@ static pid_t qtest_qemu_pid(QTestState *s)
> return pid;
> }
>
> -QTestState *qtest_init(const char *extra_args)
> +QTestState *qtest_init(const char *extra_args, const char *incoming_uri)
> {
> QTestState *s;
> int sock, qmpsock, ret, i;
> @@ -113,13 +118,14 @@ QTestState *qtest_init(const char *extra_args)
> qemu_binary = getenv("QTEST_QEMU_BINARY");
> g_assert(qemu_binary != NULL);
>
> - s = g_malloc(sizeof(*s));
> + s = g_malloc0(sizeof(*s));
>
> s->tmp_dir = g_strdup_printf("/tmp/qtest-%d-XXXXXX", getpid());
> g_assert(mkdtemp(s->tmp_dir) != NULL);
> s->socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "sock");
> s->qmp_socket_path = g_strdup_printf("%s/%s", s->tmp_dir, "qmp");
> s->pid_file = g_strdup_printf("%s/%s", s->tmp_dir, "pid");
> + s->incoming_uri = g_strdup(incoming_uri);
>
> sock = init_socket(s->socket_path);
> qmpsock = init_socket(s->qmp_socket_path);
> @@ -178,6 +184,7 @@ void qtest_quit(QTestState *s)
> g_free(s->socket_path);
> g_free(s->qmp_socket_path);
> g_free(s->tmp_dir);
> + g_free(s->incoming_uri);
> }
>
> static void socket_sendf(int fd, const char *fmt, va_list ap)
> @@ -482,3 +489,90 @@ void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size)
> qtest_sendf(s, "\n");
> qtest_rsp(s, 0);
> }
> +
> +/**
> + * is_running:
> + * @mch: QTestState instance to check.
> + *
> + * Returns 1, if mch is running, 0 if its not running. -1 means retry.
> + */
> +static int is_running(QTestState *mch)
> +{
> + QString *resp = qstring_new();
> + QObject *resp_obj;
> + QObject *ret_obj;
> + QObject *run_obj;
> + int ret;
> +
> + resp = qstring_new();
> + qtest_qmp_resp(mch, resp, "{ 'execute': 'query-status' }", NULL);
> +
> + resp_obj = qobject_from_json(qstring_get_str(resp));
> + if ((!resp_obj) || (qobject_type(resp_obj) != QTYPE_QDICT)) {
> + ret = -1;
> + goto out;
> + }
> +
> + ret_obj = qdict_get(qobject_to_qdict(resp_obj), "return");
> + if ((!ret_obj) || (qobject_type(ret_obj) != QTYPE_QDICT)) {
> + ret = -1;
> + goto out;
> + }
> +
> + run_obj = qdict_get(qobject_to_qdict(ret_obj), "running");
> + if ((!run_obj) || (qobject_type(run_obj) != QTYPE_QBOOL)) {
> + ret = -1;
> + goto out;
> + }
> + ret = qbool_get_int(qobject_to_qbool(run_obj));
> +
> +out:
> + qobject_decref(resp_obj);
> + QDECREF(resp);
> + return ret;
> +}
> +
> +#define SLEEP_INTERVAL 2
> +/* Abort after 2 minutes */
> +#define SLEEP_MAX (60 * 2)
> +
> +int test_migrate(QTestState *mach_src, QTestState *mach_dst)
> +{
> + int src_run = 0;
> + int dst_run = 0;
> + int iter = 0;
> + gchar *migrate_str;
> +
> + if (!mach_dst->incoming_uri) {
> + fprintf(stderr, "do_migrate: Error: mach_dst->incoming_uri not set\n");
> + return -1;
> + }
> +
> + /* is running on mach_src ? */
> + if (is_running(mach_src) != 1) {
> + fprintf(stderr, "do_migrate: Error: not running on src\n");
> + return -1;
> + }
> +
> + /* do migrate */
> + migrate_str = g_strdup_printf("{ 'execute': 'migrate',"
> + "'arguments': { 'uri': '%s' } }",
> + mach_dst->incoming_uri);
> + qtest_qmp(mach_src, migrate_str, NULL);
> + g_free(migrate_str);
> +
> + while (iter < SLEEP_MAX) {
> + src_run = is_running(mach_src);
> + dst_run = is_running(mach_dst);
> + if ((src_run == 0) && (dst_run == 1)) {
> + break;
> + }
> + sleep(SLEEP_INTERVAL);
> + iter += SLEEP_INTERVAL;
> + }
> + if ((src_run != 0) || (dst_run != 1)) {
> + fprintf(stderr, "do_migrate: Error: migration failed\n");
> + return -1;
> + }
> + return 0;
> +}
> diff --git a/tests/libqtest.h b/tests/libqtest.h
> index 972ba5d..47d189b 100644
> --- a/tests/libqtest.h
> +++ b/tests/libqtest.h
> @@ -27,8 +27,9 @@ extern QTestState *global_qtest;
> /**
> * qtest_init:
> * @extra_args: other arguments to pass to QEMU.
> + * @incoming_uri: used for incoming migration.
> */
> -QTestState *qtest_init(const char *extra_args);
> +QTestState *qtest_init(const char *extra_args, const char *incoming_uri);
>
> /**
> * qtest_quit:
> @@ -207,6 +208,16 @@ const char *qtest_get_arch(void);
> void qtest_add_func(const char *str, void (*fn));
>
> /**
> + * test_migrate:
> + * @mach_src: QTestState source.
> + * @mach_dst: QTestState destination.
> + *
> + * Migrate a VM from mach_src to mach_dst.
> + * Returns 0 on success, -1 on failure.
> + */
> +int test_migrate(QTestState *mach_src, QTestState *mach_dst);
> +
> +/**
> * qtest_start:
> * @args: other arguments to pass to QEMU
> *
> @@ -214,7 +225,7 @@ void qtest_add_func(const char *str, void (*fn));
> * The global variable is used by "shortcut" macros documented below.
> */
> #define qtest_start(args) ( \
> - global_qtest = qtest_init((args)) \
> + global_qtest = qtest_init((args), NULL) \
> )
>
> /**
> diff --git a/tests/migrate-test.c b/tests/migrate-test.c
> new file mode 100644
> index 0000000..80ef815
> --- /dev/null
> +++ b/tests/migrate-test.c
> @@ -0,0 +1,68 @@
> +/*
> + * Migration tests
> + *
> + * Copyright Red Hat, Inc. 2012
> + *
> + * Authors:
> + * Jason Baron <jbaron@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + */
> +#include "libqtest.h"
> +
> +#include <glib.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +
> +static QTestState *mach_src;
> +static QTestState *mach_dst;
> +
> +static void migrate_cleanup(void)
> +{
> + if (mach_src) {
> + qtest_quit(mach_src);
> + }
> + if (mach_dst) {
> + qtest_quit(mach_dst);
> + }
> +}
> +
> +static void test_migration(void)
> +{
> + int ret;
> +
> + ret = test_migrate(mach_src, mach_dst);
> + if (ret) {
> + migrate_cleanup();
> + g_assert(false);
> + }
> +}
> +
> +int main(int argc, char **argv)
> +{
> + int ret;
> + gchar *src_cmdline;
> + gchar *dst_cmdline;
> + const char *dst_uri = "tcp:0:4444";
Maybe use a random port and localhost.
> +
> + g_test_init(&argc, &argv, NULL);
> +
> + src_cmdline = g_strdup("-display none -machine pc");
> + mach_src = qtest_init(src_cmdline, NULL);
> +
> + dst_cmdline = g_strdup_printf("%s -incoming %s", src_cmdline, dst_uri);
> + mach_dst = qtest_init(dst_cmdline, dst_uri);
> +
> + g_free(src_cmdline);
> + g_free(dst_cmdline);
> +
> + qtest_add_func("/migrate/src-to-dst", test_migration);
> + ret = g_test_run();
> +
> + migrate_cleanup();
> + return ret;
> +}
> --
> 1.7.1
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH v2 2/3] qtest: extend qtest_qmp() to fill in the reply
2012-12-20 17:14 [Qemu-devel] [PATCH v2 0/3] qtest: add migration testing Jason Baron
2012-12-20 17:14 ` [Qemu-devel] [PATCH v2 1/3] qtest: Enable creation of multiple qemu instances Jason Baron
2012-12-20 17:14 ` [Qemu-devel] [PATCH v2 3/3] qtest: add migrate-test Jason Baron
@ 2012-12-20 17:14 ` Jason Baron
2013-01-07 20:04 ` Anthony Liguori
2 siblings, 1 reply; 10+ messages in thread
From: Jason Baron @ 2012-12-20 17:14 UTC (permalink / raw)
To: qemu-devel
Cc: kwolf, aliguori, quintela, blauwirbel, andreas.faerber, pbonzini
From: Jason Baron <jbaron@redhat.com>
Introduce:
Add void qtest_qmp_resp(QTestState *s, QString *resp, const char *fmt, ...)
which allows a response string to be filled in.
Signed-off-by: Jason Baron <jbaron@redhat.com>
---
tests/Makefile | 2 +-
tests/libqtest.c | 17 ++++++++++-------
tests/libqtest.h | 15 +++++++++++++--
3 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/tests/Makefile b/tests/Makefile
index b60f0fb..1756b47 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -85,7 +85,7 @@ TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TARGET),))
check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
-qtest-obj-y = tests/libqtest.o $(oslib-obj-y) libqemustub.a
+qtest-obj-y = tests/libqtest.o $(oslib-obj-y) libqemustub.a $(test-qapi-obj-y) $(qom-obj-y)
$(check-qtest-y): $(qtest-obj-y)
.PHONY: check-help
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 57665c9..994cd2f 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -288,7 +288,7 @@ redo:
return words;
}
-void qtest_qmp(QTestState *s, const char *fmt, ...)
+void qtest_qmp_resp(QTestState *s, QString *resp, const char *fmt, ...)
{
va_list ap;
bool has_reply = false;
@@ -313,16 +313,19 @@ void qtest_qmp(QTestState *s, const char *fmt, ...)
fprintf(stderr, "Broken pipe\n");
exit(1);
}
-
- switch (c) {
- case '{':
+ if (c == '{') {
nesting++;
has_reply = true;
- break;
- case '}':
+ }
+ if (c == '}') {
nesting--;
- break;
}
+ if (has_reply && resp) {
+ qstring_append_chr(resp, c);
+ }
+ }
+ if (has_reply && resp) {
+ qstring_append_chr(resp, '\0');
}
}
diff --git a/tests/libqtest.h b/tests/libqtest.h
index c8ade85..972ba5d 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -18,6 +18,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <sys/types.h>
+#include "qstring.h"
typedef struct QTestState QTestState;
@@ -38,13 +39,14 @@ QTestState *qtest_init(const char *extra_args);
void qtest_quit(QTestState *s);
/**
- * qtest_qmp:
+ * qtest_qmp_resp:
* @s: QTestState instance to operate on.
+ * @resp: Fills in response string if provided
* @fmt...: QMP message to send to qemu
*
* Sends a QMP message to QEMU
*/
-void qtest_qmp(QTestState *s, const char *fmt, ...);
+void qtest_qmp_resp(QTestState *s, QString *resp, const char *fmt, ...);
/**
* qtest_get_irq:
@@ -349,4 +351,13 @@ void qtest_add_func(const char *str, void (*fn));
*/
#define clock_set(val) qtest_clock_set(global_qtest, val)
+/**
+ * qtest_qmp:
+ * @s: QTestState instance to operate on.
+ * @fmt...: QMP message to send to qemu
+ *
+ * Sends a QMP message to QEMU
+ */
+#define qtest_qmp(s, fmt, ...) qtest_qmp_resp(s, NULL, fmt, ## __VA_ARGS__)
+
#endif
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH v2 2/3] qtest: extend qtest_qmp() to fill in the reply
2012-12-20 17:14 ` [Qemu-devel] [PATCH v2 2/3] qtest: extend qtest_qmp() to fill in the reply Jason Baron
@ 2013-01-07 20:04 ` Anthony Liguori
0 siblings, 0 replies; 10+ messages in thread
From: Anthony Liguori @ 2013-01-07 20:04 UTC (permalink / raw)
To: Jason Baron, qemu-devel
Cc: kwolf, pbonzini, andreas.faerber, blauwirbel, quintela
Jason Baron <jbaron@redhat.com> writes:
> From: Jason Baron <jbaron@redhat.com>
>
> Introduce:
>
> Add void qtest_qmp_resp(QTestState *s, QString *resp, const char *fmt,
> ...)
Any reason to not just return a QString?
Also, why not do the parsing in this function and just return a QObject
of the result?
Regards,
Anthony Liguori
>
> which allows a response string to be filled in.
>
> Signed-off-by: Jason Baron <jbaron@redhat.com>
> ---
> tests/Makefile | 2 +-
> tests/libqtest.c | 17 ++++++++++-------
> tests/libqtest.h | 15 +++++++++++++--
> 3 files changed, 24 insertions(+), 10 deletions(-)
>
> diff --git a/tests/Makefile b/tests/Makefile
> index b60f0fb..1756b47 100644
> --- a/tests/Makefile
> +++ b/tests/Makefile
> @@ -85,7 +85,7 @@ TARGETS=$(patsubst %-softmmu,%, $(filter %-softmmu,$(TARGET_DIRS)))
> QTEST_TARGETS=$(foreach TARGET,$(TARGETS), $(if $(check-qtest-$(TARGET)-y), $(TARGET),))
> check-qtest-$(CONFIG_POSIX)=$(foreach TARGET,$(TARGETS), $(check-qtest-$(TARGET)-y))
>
> -qtest-obj-y = tests/libqtest.o $(oslib-obj-y) libqemustub.a
> +qtest-obj-y = tests/libqtest.o $(oslib-obj-y) libqemustub.a $(test-qapi-obj-y) $(qom-obj-y)
> $(check-qtest-y): $(qtest-obj-y)
>
> .PHONY: check-help
> diff --git a/tests/libqtest.c b/tests/libqtest.c
> index 57665c9..994cd2f 100644
> --- a/tests/libqtest.c
> +++ b/tests/libqtest.c
> @@ -288,7 +288,7 @@ redo:
> return words;
> }
>
> -void qtest_qmp(QTestState *s, const char *fmt, ...)
> +void qtest_qmp_resp(QTestState *s, QString *resp, const char *fmt, ...)
> {
> va_list ap;
> bool has_reply = false;
> @@ -313,16 +313,19 @@ void qtest_qmp(QTestState *s, const char *fmt, ...)
> fprintf(stderr, "Broken pipe\n");
> exit(1);
> }
> -
> - switch (c) {
> - case '{':
> + if (c == '{') {
> nesting++;
> has_reply = true;
> - break;
> - case '}':
> + }
> + if (c == '}') {
> nesting--;
> - break;
> }
> + if (has_reply && resp) {
> + qstring_append_chr(resp, c);
> + }
> + }
> + if (has_reply && resp) {
> + qstring_append_chr(resp, '\0');
> }
> }
>
> diff --git a/tests/libqtest.h b/tests/libqtest.h
> index c8ade85..972ba5d 100644
> --- a/tests/libqtest.h
> +++ b/tests/libqtest.h
> @@ -18,6 +18,7 @@
> #include <stdint.h>
> #include <stdbool.h>
> #include <sys/types.h>
> +#include "qstring.h"
>
> typedef struct QTestState QTestState;
>
> @@ -38,13 +39,14 @@ QTestState *qtest_init(const char *extra_args);
> void qtest_quit(QTestState *s);
>
> /**
> - * qtest_qmp:
> + * qtest_qmp_resp:
> * @s: QTestState instance to operate on.
> + * @resp: Fills in response string if provided
> * @fmt...: QMP message to send to qemu
> *
> * Sends a QMP message to QEMU
> */
> -void qtest_qmp(QTestState *s, const char *fmt, ...);
> +void qtest_qmp_resp(QTestState *s, QString *resp, const char *fmt, ...);
>
> /**
> * qtest_get_irq:
> @@ -349,4 +351,13 @@ void qtest_add_func(const char *str, void (*fn));
> */
> #define clock_set(val) qtest_clock_set(global_qtest, val)
>
> +/**
> + * qtest_qmp:
> + * @s: QTestState instance to operate on.
> + * @fmt...: QMP message to send to qemu
> + *
> + * Sends a QMP message to QEMU
> + */
> +#define qtest_qmp(s, fmt, ...) qtest_qmp_resp(s, NULL, fmt, ## __VA_ARGS__)
> +
> #endif
> --
> 1.7.1
^ permalink raw reply [flat|nested] 10+ messages in thread