tests/qtest: migration: Add support for negative testing of qmp_migrate
There is currently no way to write a test for errors that happened in qmp_migrate before the migration has started. Add a version of qmp_migrate that ensures an error happens. To make use of it a test needs to set MigrateCommon.result as MIG_TEST_QMP_ERROR. Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Signed-off-by: Fabiano Rosas <farosas@suse.de> Signed-off-by: Juan Quintela <quintela@redhat.com> Message-ID: <20230712190742.22294-6-farosas@suse.de>
This commit is contained in:
parent
4111a732e8
commit
5274274c26
|
@ -1259,6 +1259,28 @@ void qtest_memset(QTestState *s, uint64_t addr, uint8_t pattern, size_t size)
|
|||
qtest_rsp(s);
|
||||
}
|
||||
|
||||
QDict *qtest_vqmp_assert_failure_ref(QTestState *qts,
|
||||
const char *fmt, va_list args)
|
||||
{
|
||||
QDict *response;
|
||||
QDict *ret;
|
||||
|
||||
response = qtest_vqmp(qts, fmt, args);
|
||||
|
||||
g_assert(response);
|
||||
if (!qdict_haskey(response, "error")) {
|
||||
g_autoptr(GString) s = qobject_to_json_pretty(QOBJECT(response), true);
|
||||
g_test_message("%s", s->str);
|
||||
}
|
||||
g_assert(qdict_haskey(response, "error"));
|
||||
g_assert(!qdict_haskey(response, "return"));
|
||||
ret = qdict_get_qdict(response, "error");
|
||||
qobject_ref(ret);
|
||||
qobject_unref(response);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QDict *qtest_vqmp_assert_success_ref(QTestState *qts,
|
||||
const char *fmt, va_list args)
|
||||
{
|
||||
|
@ -1321,6 +1343,17 @@ void qtest_vqmp_fds_assert_success(QTestState *qts, int *fds, size_t nfds,
|
|||
}
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
QDict *qtest_qmp_assert_failure_ref(QTestState *qts, const char *fmt, ...)
|
||||
{
|
||||
QDict *response;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
response = qtest_vqmp_assert_failure_ref(qts, fmt, ap);
|
||||
va_end(ap);
|
||||
return response;
|
||||
}
|
||||
|
||||
QDict *qtest_qmp_assert_success_ref(QTestState *qts, const char *fmt, ...)
|
||||
{
|
||||
QDict *response;
|
||||
|
|
|
@ -810,6 +810,34 @@ void qtest_vqmp_fds_assert_success(QTestState *qts, int *fds, size_t nfds,
|
|||
G_GNUC_PRINTF(4, 0);
|
||||
#endif /* !_WIN32 */
|
||||
|
||||
/**
|
||||
* qtest_qmp_assert_failure_ref:
|
||||
* @qts: QTestState instance to operate on
|
||||
* @fmt: QMP message to send to qemu, formatted like
|
||||
* qobject_from_jsonf_nofail(). See parse_interpolation() for what's
|
||||
* supported after '%'.
|
||||
*
|
||||
* Sends a QMP message to QEMU, asserts that an 'error' key is present in
|
||||
* the response, and returns the response.
|
||||
*/
|
||||
QDict *qtest_qmp_assert_failure_ref(QTestState *qts, const char *fmt, ...)
|
||||
G_GNUC_PRINTF(2, 3);
|
||||
|
||||
/**
|
||||
* qtest_vqmp_assert_failure_ref:
|
||||
* @qts: QTestState instance to operate on
|
||||
* @fmt: QMP message to send to qemu, formatted like
|
||||
* qobject_from_jsonf_nofail(). See parse_interpolation() for what's
|
||||
* supported after '%'.
|
||||
* @args: variable arguments for @fmt
|
||||
*
|
||||
* Sends a QMP message to QEMU, asserts that an 'error' key is present in
|
||||
* the response, and returns the response.
|
||||
*/
|
||||
QDict *qtest_vqmp_assert_failure_ref(QTestState *qts,
|
||||
const char *fmt, va_list args)
|
||||
G_GNUC_PRINTF(2, 0);
|
||||
|
||||
/**
|
||||
* qtest_qmp_assert_success_ref:
|
||||
* @qts: QTestState instance to operate on
|
||||
|
|
|
@ -49,6 +49,26 @@ bool migrate_watch_for_resume(QTestState *who, const char *name,
|
|||
return false;
|
||||
}
|
||||
|
||||
void migrate_qmp_fail(QTestState *who, const char *uri, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
QDict *args, *err;
|
||||
|
||||
va_start(ap, fmt);
|
||||
args = qdict_from_vjsonf_nofail(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
g_assert(!qdict_haskey(args, "uri"));
|
||||
qdict_put_str(args, "uri", uri);
|
||||
|
||||
err = qtest_qmp_assert_failure_ref(
|
||||
who, "{ 'execute': 'migrate', 'arguments': %p}", args);
|
||||
|
||||
g_assert(qdict_haskey(err, "desc"));
|
||||
|
||||
qobject_unref(err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send QMP command "migrate".
|
||||
* Arguments are built from @fmt... (formatted like
|
||||
|
|
|
@ -27,6 +27,9 @@ G_GNUC_PRINTF(3, 4)
|
|||
void migrate_incoming_qmp(QTestState *who, const char *uri,
|
||||
const char *fmt, ...);
|
||||
|
||||
G_GNUC_PRINTF(3, 4)
|
||||
void migrate_qmp_fail(QTestState *who, const char *uri, const char *fmt, ...);
|
||||
|
||||
void migrate_set_capability(QTestState *who, const char *capability,
|
||||
bool value);
|
||||
|
||||
|
|
|
@ -697,6 +697,8 @@ typedef struct {
|
|||
MIG_TEST_FAIL,
|
||||
/* This test should fail, dest qemu should fail with abnormal status */
|
||||
MIG_TEST_FAIL_DEST_QUIT_ERR,
|
||||
/* The QMP command for this migration should fail with an error */
|
||||
MIG_TEST_QMP_ERROR,
|
||||
} result;
|
||||
|
||||
/*
|
||||
|
@ -1503,6 +1505,7 @@ static void test_precopy_common(MigrateCommon *args)
|
|||
{
|
||||
QTestState *from, *to;
|
||||
void *data_hook = NULL;
|
||||
g_autofree char *connect_uri = NULL;
|
||||
|
||||
if (test_migrate_start(&from, &to, args->listen_uri, &args->start)) {
|
||||
return;
|
||||
|
@ -1537,13 +1540,17 @@ static void test_precopy_common(MigrateCommon *args)
|
|||
}
|
||||
|
||||
if (!args->connect_uri) {
|
||||
g_autofree char *local_connect_uri =
|
||||
migrate_get_socket_address(to, "socket-address");
|
||||
migrate_qmp(from, local_connect_uri, "{}");
|
||||
connect_uri = migrate_get_socket_address(to, "socket-address");
|
||||
} else {
|
||||
migrate_qmp(from, args->connect_uri, "{}");
|
||||
connect_uri = g_strdup(args->connect_uri);
|
||||
}
|
||||
|
||||
if (args->result == MIG_TEST_QMP_ERROR) {
|
||||
migrate_qmp_fail(from, connect_uri, "{}");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
migrate_qmp(from, connect_uri, "{}");
|
||||
|
||||
if (args->result != MIG_TEST_SUCCEED) {
|
||||
bool allow_active = args->result == MIG_TEST_FAIL;
|
||||
|
@ -1595,6 +1602,7 @@ static void test_precopy_common(MigrateCommon *args)
|
|||
wait_for_serial("dest_serial");
|
||||
}
|
||||
|
||||
finish:
|
||||
if (args->finish_hook) {
|
||||
args->finish_hook(from, to, data_hook);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue