aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-09-13 14:37:48 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-09-13 14:37:48 +0100
commit85182c96de61f0b600bbe834d5a23e713162e892 (patch)
tree2ea876bece94357492df2be92be5b2413d7ad7cf /tests
parent3d9442ee1d78f7f138dcd6c85c7acad0153d2f11 (diff)
parent268dcd46ae6d608a4ce93b191b51a318504bf1fb (diff)
downloadqemu-85182c96de61f0b600bbe834d5a23e713162e892.zip
qemu-85182c96de61f0b600bbe834d5a23e713162e892.tar.gz
qemu-85182c96de61f0b600bbe834d5a23e713162e892.tar.bz2
Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20190912a' into staging
Migration pull 2019-09-12 New feature: UUID validation check from Yury Kotov plus a bunch of fixes. # gpg: Signature made Thu 12 Sep 2019 14:48:28 BST # gpg: using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7 # gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full] # Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A 9FA9 0516 331E BC5B FDE7 * remotes/dgilbert/tags/pull-migration-20190912a: migration: fix one typo in comment of function migration_total_bytes() migration/qemu-file: fix potential buf waste for extra buf_index adjustment migration/qemu-file: remove check on writev_buffer in qemu_put_compression_data migration: Fix postcopy bw for recovery tests/migration: Add a test for validate-uuid capability tests/libqtest: Allow setting expected exit status migration: Add validate-uuid capability qemu-file: Rework old qemu_fflush comment migration: register_savevm_live doesn't need dev hw/net/vmxnet3: Fix leftover unregister_savevm migration: cleanup check on ops in savevm.handlers iterations migration: multifd_send_thread always post p->sem_sync when error happen Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/libqtest.c36
-rw-r--r--tests/libqtest.h9
-rw-r--r--tests/migration-test.c140
3 files changed, 140 insertions, 45 deletions
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 0a6b917..4a75564 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -41,6 +41,7 @@ struct QTestState
int qmp_fd;
pid_t qemu_pid; /* our child QEMU process */
int wstatus;
+ int expected_status;
bool big_endian;
bool irq_level[MAX_IRQ];
GString *rx;
@@ -111,6 +112,11 @@ bool qtest_probe_child(QTestState *s)
return false;
}
+void qtest_set_expected_status(QTestState *s, int status)
+{
+ s->expected_status = status;
+}
+
static void kill_qemu(QTestState *s)
{
pid_t pid = s->qemu_pid;
@@ -124,24 +130,23 @@ static void kill_qemu(QTestState *s)
}
/*
- * We expect qemu to exit with status 0; anything else is
+ * Check whether qemu exited with expected exit status; anything else is
* fishy and should be logged with as much detail as possible.
*/
wstatus = s->wstatus;
- if (wstatus) {
- if (WIFEXITED(wstatus)) {
- fprintf(stderr, "%s:%d: kill_qemu() tried to terminate QEMU "
- "process but encountered exit status %d\n",
- __FILE__, __LINE__, WEXITSTATUS(wstatus));
- } else if (WIFSIGNALED(wstatus)) {
- int sig = WTERMSIG(wstatus);
- const char *signame = strsignal(sig) ?: "unknown ???";
- const char *dump = WCOREDUMP(wstatus) ? " (core dumped)" : "";
-
- fprintf(stderr, "%s:%d: kill_qemu() detected QEMU death "
- "from signal %d (%s)%s\n",
- __FILE__, __LINE__, sig, signame, dump);
- }
+ if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != s->expected_status) {
+ fprintf(stderr, "%s:%d: kill_qemu() tried to terminate QEMU "
+ "process but encountered exit status %d (expected %d)\n",
+ __FILE__, __LINE__, WEXITSTATUS(wstatus), s->expected_status);
+ abort();
+ } else if (WIFSIGNALED(wstatus)) {
+ int sig = WTERMSIG(wstatus);
+ const char *signame = strsignal(sig) ?: "unknown ???";
+ const char *dump = WCOREDUMP(wstatus) ? " (core dumped)" : "";
+
+ fprintf(stderr, "%s:%d: kill_qemu() detected QEMU death "
+ "from signal %d (%s)%s\n",
+ __FILE__, __LINE__, sig, signame, dump);
abort();
}
}
@@ -246,6 +251,7 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
g_test_message("starting QEMU: %s", command);
s->wstatus = 0;
+ s->expected_status = 0;
s->qemu_pid = fork();
if (s->qemu_pid == 0) {
setenv("QEMU_AUDIO_DRV", "none", true);
diff --git a/tests/libqtest.h b/tests/libqtest.h
index c8cffe5..a177e50 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -708,4 +708,13 @@ void qmp_assert_error_class(QDict *rsp, const char *class);
*/
bool qtest_probe_child(QTestState *s);
+/**
+ * qtest_set_expected_status:
+ * @s: QTestState instance to operate on.
+ * @status: an expected exit status.
+ *
+ * Set expected exit status of the child.
+ */
+void qtest_set_expected_status(QTestState *s, int status);
+
#endif
diff --git a/tests/migration-test.c b/tests/migration-test.c
index a9f81cc..258aa06 100644
--- a/tests/migration-test.c
+++ b/tests/migration-test.c
@@ -512,7 +512,8 @@ static void migrate_postcopy_start(QTestState *from, QTestState *to)
static int test_migrate_start(QTestState **from, QTestState **to,
const char *uri, bool hide_stderr,
- bool use_shmem)
+ bool use_shmem, const char *opts_src,
+ const char *opts_dst)
{
gchar *cmd_src, *cmd_dst;
char *bootpath = NULL;
@@ -521,6 +522,9 @@ static int test_migrate_start(QTestState **from, QTestState **to,
const char *arch = qtest_get_arch();
const char *accel = "kvm:tcg";
+ opts_src = opts_src ? opts_src : "";
+ opts_dst = opts_dst ? opts_dst : "";
+
if (use_shmem) {
if (!g_file_test("/dev/shm", G_FILE_TEST_IS_DIR)) {
g_test_skip("/dev/shm is not supported");
@@ -539,16 +543,16 @@ static int test_migrate_start(QTestState **from, QTestState **to,
cmd_src = g_strdup_printf("-machine accel=%s -m 150M"
" -name source,debug-threads=on"
" -serial file:%s/src_serial"
- " -drive file=%s,format=raw %s",
+ " -drive file=%s,format=raw %s %s",
accel, tmpfs, bootpath,
- extra_opts ? extra_opts : "");
+ extra_opts ? extra_opts : "", opts_src);
cmd_dst = g_strdup_printf("-machine accel=%s -m 150M"
" -name target,debug-threads=on"
" -serial file:%s/dest_serial"
" -drive file=%s,format=raw"
- " -incoming %s %s",
+ " -incoming %s %s %s",
accel, tmpfs, bootpath, uri,
- extra_opts ? extra_opts : "");
+ extra_opts ? extra_opts : "", opts_dst);
start_address = X86_TEST_MEM_START;
end_address = X86_TEST_MEM_END;
} else if (g_str_equal(arch, "s390x")) {
@@ -556,15 +560,15 @@ static int test_migrate_start(QTestState **from, QTestState **to,
extra_opts = use_shmem ? get_shmem_opts("128M", shmem_path) : NULL;
cmd_src = g_strdup_printf("-machine accel=%s -m 128M"
" -name source,debug-threads=on"
- " -serial file:%s/src_serial -bios %s %s",
+ " -serial file:%s/src_serial -bios %s %s %s",
accel, tmpfs, bootpath,
- extra_opts ? extra_opts : "");
+ extra_opts ? extra_opts : "", opts_src);
cmd_dst = g_strdup_printf("-machine accel=%s -m 128M"
" -name target,debug-threads=on"
" -serial file:%s/dest_serial -bios %s"
- " -incoming %s %s",
+ " -incoming %s %s %s",
accel, tmpfs, bootpath, uri,
- extra_opts ? extra_opts : "");
+ extra_opts ? extra_opts : "", opts_dst);
start_address = S390_TEST_MEM_START;
end_address = S390_TEST_MEM_END;
} else if (strcmp(arch, "ppc64") == 0) {
@@ -575,14 +579,15 @@ static int test_migrate_start(QTestState **from, QTestState **to,
" -prom-env 'use-nvramrc?=true' -prom-env "
"'nvramrc=hex .\" _\" begin %x %x "
"do i c@ 1 + i c! 1000 +loop .\" B\" 0 "
- "until' %s", accel, tmpfs, end_address,
- start_address, extra_opts ? extra_opts : "");
+ "until' %s %s", accel, tmpfs, end_address,
+ start_address, extra_opts ? extra_opts : "",
+ opts_src);
cmd_dst = g_strdup_printf("-machine accel=%s -m 256M"
" -name target,debug-threads=on"
" -serial file:%s/dest_serial"
- " -incoming %s %s",
+ " -incoming %s %s %s",
accel, tmpfs, uri,
- extra_opts ? extra_opts : "");
+ extra_opts ? extra_opts : "", opts_dst);
start_address = PPC_TEST_MEM_START;
end_address = PPC_TEST_MEM_END;
@@ -592,16 +597,16 @@ static int test_migrate_start(QTestState **from, QTestState **to,
cmd_src = g_strdup_printf("-machine virt,accel=%s,gic-version=max "
"-name vmsource,debug-threads=on -cpu max "
"-m 150M -serial file:%s/src_serial "
- "-kernel %s %s",
+ "-kernel %s %s %s",
accel, tmpfs, bootpath,
- extra_opts ? extra_opts : "");
+ extra_opts ? extra_opts : "", opts_src);
cmd_dst = g_strdup_printf("-machine virt,accel=%s,gic-version=max "
"-name vmdest,debug-threads=on -cpu max "
"-m 150M -serial file:%s/dest_serial "
"-kernel %s "
- "-incoming %s %s",
+ "-incoming %s %s %s",
accel, tmpfs, bootpath, uri,
- extra_opts ? extra_opts : "");
+ extra_opts ? extra_opts : "", opts_dst);
start_address = ARM_TEST_MEM_START;
end_address = ARM_TEST_MEM_END;
@@ -731,7 +736,7 @@ static int migrate_postcopy_prepare(QTestState **from_ptr,
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
- if (test_migrate_start(&from, &to, uri, hide_error, false)) {
+ if (test_migrate_start(&from, &to, uri, hide_error, false, NULL, NULL)) {
return -1;
}
@@ -841,20 +846,16 @@ static void test_postcopy_recovery(void)
migrate_postcopy_complete(from, to);
}
-static void test_baddest(void)
+static void wait_for_migration_fail(QTestState *from, bool allow_active)
{
- QTestState *from, *to;
QDict *rsp_return;
char *status;
bool failed;
- if (test_migrate_start(&from, &to, "tcp:0:0", true, false)) {
- return;
- }
- migrate(from, "tcp:0:0", "{}");
do {
status = migrate_query_status(from);
- g_assert(!strcmp(status, "setup") || !(strcmp(status, "failed")));
+ g_assert(!strcmp(status, "setup") || !strcmp(status, "failed") ||
+ (allow_active && !strcmp(status, "active")));
failed = !strcmp(status, "failed");
g_free(status);
} while (!failed);
@@ -864,7 +865,17 @@ static void test_baddest(void)
g_assert(qdict_haskey(rsp_return, "running"));
g_assert(qdict_get_bool(rsp_return, "running"));
qobject_unref(rsp_return);
+}
+
+static void test_baddest(void)
+{
+ QTestState *from, *to;
+ if (test_migrate_start(&from, &to, "tcp:0:0", true, false, NULL, NULL)) {
+ return;
+ }
+ migrate(from, "tcp:0:0", "{}");
+ wait_for_migration_fail(from, false);
test_migrate_end(from, to, false);
}
@@ -873,7 +884,7 @@ static void test_precopy_unix(void)
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
- if (test_migrate_start(&from, &to, uri, false, false)) {
+ if (test_migrate_start(&from, &to, uri, false, false, NULL, NULL)) {
return;
}
@@ -916,7 +927,7 @@ static void test_ignore_shared(void)
char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
- if (test_migrate_start(&from, &to, uri, false, true)) {
+ if (test_migrate_start(&from, &to, uri, false, true, NULL, NULL)) {
return;
}
@@ -951,7 +962,7 @@ static void test_xbzrle(const char *uri)
{
QTestState *from, *to;
- if (test_migrate_start(&from, &to, uri, false, false)) {
+ if (test_migrate_start(&from, &to, uri, false, false, NULL, NULL)) {
return;
}
@@ -1003,7 +1014,8 @@ static void test_precopy_tcp(void)
char *uri;
QTestState *from, *to;
- if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", false, false)) {
+ if (test_migrate_start(&from, &to, "tcp:127.0.0.1:0", false, false,
+ NULL, NULL)) {
return;
}
@@ -1049,7 +1061,7 @@ static void test_migrate_fd_proto(void)
QDict *rsp;
const char *error_desc;
- if (test_migrate_start(&from, &to, "defer", false, false)) {
+ if (test_migrate_start(&from, &to, "defer", false, false, NULL, NULL)) {
return;
}
@@ -1125,6 +1137,68 @@ static void test_migrate_fd_proto(void)
test_migrate_end(from, to, true);
}
+static void do_test_validate_uuid(const char *uuid_arg_src,
+ const char *uuid_arg_dst,
+ bool should_fail, bool hide_stderr)
+{
+ char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
+ QTestState *from, *to;
+
+ if (test_migrate_start(&from, &to, uri, hide_stderr, false,
+ uuid_arg_src, uuid_arg_dst)) {
+ return;
+ }
+
+ /*
+ * UUID validation is at the begin of migration. So, the main process of
+ * migration is not interesting for us here. Thus, set huge downtime for
+ * very fast migration.
+ */
+ migrate_set_parameter_int(from, "downtime-limit", 1000000);
+ migrate_set_capability(from, "validate-uuid", true);
+
+ /* Wait for the first serial output from the source */
+ wait_for_serial("src_serial");
+
+ migrate(from, uri, "{}");
+
+ if (should_fail) {
+ qtest_set_expected_status(to, 1);
+ wait_for_migration_fail(from, true);
+ } else {
+ wait_for_migration_complete(from);
+ }
+
+ test_migrate_end(from, to, false);
+ g_free(uri);
+}
+
+static void test_validate_uuid(void)
+{
+ do_test_validate_uuid("-uuid 11111111-1111-1111-1111-111111111111",
+ "-uuid 11111111-1111-1111-1111-111111111111",
+ false, false);
+}
+
+static void test_validate_uuid_error(void)
+{
+ do_test_validate_uuid("-uuid 11111111-1111-1111-1111-111111111111",
+ "-uuid 22222222-2222-2222-2222-222222222222",
+ true, true);
+}
+
+static void test_validate_uuid_src_not_set(void)
+{
+ do_test_validate_uuid(NULL, "-uuid 11111111-1111-1111-1111-111111111111",
+ false, true);
+}
+
+static void test_validate_uuid_dst_not_set(void)
+{
+ do_test_validate_uuid("-uuid 11111111-1111-1111-1111-111111111111", NULL,
+ false, true);
+}
+
int main(int argc, char **argv)
{
char template[] = "/tmp/migration-test-XXXXXX";
@@ -1180,6 +1254,12 @@ int main(int argc, char **argv)
/* qtest_add_func("/migration/ignore_shared", test_ignore_shared); */
qtest_add_func("/migration/xbzrle/unix", test_xbzrle_unix);
qtest_add_func("/migration/fd_proto", test_migrate_fd_proto);
+ qtest_add_func("/migration/validate_uuid", test_validate_uuid);
+ qtest_add_func("/migration/validate_uuid_error", test_validate_uuid_error);
+ qtest_add_func("/migration/validate_uuid_src_not_set",
+ test_validate_uuid_src_not_set);
+ qtest_add_func("/migration/validate_uuid_dst_not_set",
+ test_validate_uuid_dst_not_set);
ret = g_test_run();