[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [PATCH 04/12] qtest: add interface to save/restore
From: |
Anthony Liguori |
Subject: |
[Qemu-ppc] [PATCH 04/12] qtest: add interface to save/restore |
Date: |
Wed, 19 Jun 2013 15:40:27 -0500 |
The idea here is pretty simple. We have a synchronous interface
that when called, does a migration to a file, kills the QEMU
instance, and spawns a new one using the saved file state.
We an then sprinkle calls to qtest_save_restore() thorough test
cases to validate that we are properly saving and restoring state.
Signed-off-by: Anthony Liguori <address@hidden>
---
tests/libqtest.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/libqtest.h | 46 +++++++++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+)
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 235ec62..bc2e84e 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -44,6 +44,7 @@ struct QTestState
gchar *pid_file; /* QEMU PID file */
int child_pid; /* Child process created to execute QEMU */
char *socket_path, *qmp_socket_path;
+ char *extra_args;
};
#define g_assert_no_errno(ret) do { \
@@ -104,6 +105,14 @@ static pid_t qtest_qemu_pid(QTestState *s)
return pid;
}
+void qtest_qmp_wait_event(QTestState *s, const char *event)
+{
+ char *d;
+ /* This is cheating */
+ d = qtest_qmp(s, "");
+ g_free(d);
+}
+
QTestState *qtest_init(const char *extra_args)
{
QTestState *s;
@@ -118,6 +127,7 @@ QTestState *qtest_init(const char *extra_args)
s = g_malloc(sizeof(*s));
+ s->extra_args = g_strdup(extra_args);
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());
@@ -177,6 +187,61 @@ void qtest_quit(QTestState *s)
g_free(s->pid_file);
g_free(s->socket_path);
g_free(s->qmp_socket_path);
+ g_free(s->extra_args);
+}
+
+QTestState *qtest_save_restore(QTestState *s)
+{
+ char *filename;
+ char *d, *p, *extra_args;
+ char *n;
+
+ filename = g_strdup_printf("/tmp/qtest-%d.savevm", getpid());
+
+ /* Start migration to a temporary file */
+ d = qtest_qmp(s,
+ "{ 'execute': 'migrate', "
+ " 'arguments': { 'uri': 'exec:dd of=%s 2>/dev/null' } }",
+ filename);
+ g_free(d);
+
+ /* Wait for critical section to be entered */
+ qtest_qmp_wait_event(s, "STOP");
+
+ /* Not strictly needed as we can't possibly respond to this command until
+ * we've completed migration by virtue of the fact that STOP has been sent
+ * but it's good to be rigorious. */
+ do {
+ d = qtest_qmp(s, "{ 'execute': 'query-migrate' }");
+ p = strstr(d, "\"status\": \"completed\",");
+ g_free(d);
+ if (!p) {
+ g_usleep(100);
+ }
+ } while (p == NULL);
+
+ /* Save arguments to this qtest instance */
+ extra_args = s->extra_args;
+ s->extra_args = NULL;
+
+ /* Quit src instance */
+ qtest_quit(s);
+
+ /* Spawn destination */
+ n = g_strdup_printf("%s -incoming exec:\"dd if=%s 2>/dev/null\"",
+ extra_args, filename);
+ s = qtest_init(n);
+
+ /* Wait for incoming migration to complete */
+ qtest_qmp_wait_event(s, "RESUME");
+
+ /* Fixup extra arg so we can call repeatedly */
+ g_free(s->extra_args);
+ s->extra_args = extra_args;
+
+ g_free(filename);
+
+ return s;
}
static void socket_sendf(int fd, const char *fmt, va_list ap)
diff --git a/tests/libqtest.h b/tests/libqtest.h
index 5cdcae7..f2c6e52 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -67,6 +67,15 @@ char *qtest_qmp(QTestState *s, const char *fmt, ...);
char *qtest_qmpv(QTestState *s, const char *fmt, va_list ap);
/**
+ * qtest_qmp_wait_event:
+ * @s: #QTestState instance to operate on.
+ * @event: the event to wait for.
+ *
+ * Waits for a specific QMP event to occur.
+ */
+void qtest_qmp_wait_event(QTestState *s, const char *event);
+
+/**
* qtest_get_irq:
* @s: #QTestState instance to operate on.
* @num: Interrupt to observe.
@@ -291,6 +300,19 @@ int64_t qtest_clock_step(QTestState *s, int64_t step);
int64_t qtest_clock_set(QTestState *s, int64_t val);
/**
+ * qtest_save_restore:
+ * @s: QTest instance to operate on.
+ *
+ * This function will save and restore the state of the running QEMU
+ * instance. If the savevm code is implemented correctly for a device,
+ * this function should behave like a nop. If a test case fails because
+ * this function is called, the savevm code for the device is broken.
+ *
+ * Returns: the new QTest instance
+ */
+QTestState *qtest_save_restore(QTestState *s);
+
+/**
* qtest_spapr_hcall9:
* @s: QTestState instance to operate on.
* @nr: The hypercall index
@@ -337,6 +359,17 @@ static inline QTestState *qtest_start(const char *args)
}
/**
+ * qmp_wait_event:
+ * @event: the event to wait for.
+ *
+ * Waits for a specific QMP event to occur.
+ */
+static inline void qmp_wait_event(const char *event)
+{
+ qtest_qmp_wait_event(global_qtest, event);
+}
+
+/**
* qmp:
* @fmt...: QMP message to send to qemu
*
@@ -628,6 +661,19 @@ static inline int64_t clock_set(int64_t val)
return qtest_clock_set(global_qtest, val);
}
+/**
+ * save_restore:
+ *
+ * This function will save and restore the state of the running QEMU
+ * instance. If the savevm code is implemented correctly for a device,
+ * this function should behave like a nop. If a test case fails because
+ * this function is called, the savevm code for the device is broken.
+ */
+static inline void save_restore(void)
+{
+ global_qtest = qtest_save_restore(global_qtest);
+}
+
static inline uint64_t spapr_hcall0(uint64_t nr)
{
return qtest_spapr_hcall9(global_qtest, nr, 0, 0, 0, 0, 0, 0, 0, 0, 0);
--
1.8.0
[Qemu-ppc] [PATCH 08/12] spapr-rtas: use hypercall interface and remove special vty interfaces, Anthony Liguori, 2013/06/19
[Qemu-ppc] [PATCH 12/12] spapr-vty: remove unfixable FIXME, Anthony Liguori, 2013/06/19
[Qemu-ppc] [PATCH 10/12] spapr-vty: refactor the code to improve consistency, Anthony Liguori, 2013/06/19
[Qemu-ppc] [PATCH 04/12] qtest: add interface to save/restore,
Anthony Liguori <=
[Qemu-ppc] [PATCH 07/12] spapr-rtas: add CPU argument to RTAS calls, Anthony Liguori, 2013/06/19
[Qemu-ppc] [PATCH 11/12] spapr-vio: pass type to spapr_vio_find_by_reg(), Anthony Liguori, 2013/06/19
[Qemu-ppc] [PATCH 05/12] spapr-vty: add qtest test case, Anthony Liguori, 2013/06/19