tests/qtest: defer connection
Add an option to defer making the connecting to the monitor and qtest sockets when calling qtest_init_with_env. The client makes the connection later by calling qtest_connect and qtest_qmp_handshake. Signed-off-by: Steve Sistare <steven.sistare@oracle.com> Reviewed-by: Peter Xu <peterx@redhat.com> Link: https://lore.kernel.org/r/1736967650-129648-20-git-send-email-steven.sistare@oracle.com [plumb capabilities list into qtest_qmp_handshake] Signed-off-by: Fabiano Rosas <farosas@suse.de>
This commit is contained in:
parent
903a65120d
commit
5357ef823a
@ -75,6 +75,8 @@ struct QTestState
|
|||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int qmp_fd;
|
int qmp_fd;
|
||||||
|
int sock;
|
||||||
|
int qmpsock;
|
||||||
pid_t qemu_pid; /* our child QEMU process */
|
pid_t qemu_pid; /* our child QEMU process */
|
||||||
int wstatus;
|
int wstatus;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -458,18 +460,19 @@ static QTestState *G_GNUC_PRINTF(2, 3) qtest_spawn_qemu(const char *qemu_bin,
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *qtest_socket_path(const char *suffix)
|
||||||
|
{
|
||||||
|
return g_strdup_printf("%s/qtest-%d.%s", g_get_tmp_dir(), getpid(), suffix);
|
||||||
|
}
|
||||||
|
|
||||||
static QTestState *qtest_init_internal(const char *qemu_bin,
|
static QTestState *qtest_init_internal(const char *qemu_bin,
|
||||||
const char *extra_args)
|
const char *extra_args,
|
||||||
|
bool do_connect)
|
||||||
{
|
{
|
||||||
QTestState *s;
|
QTestState *s;
|
||||||
int sock, qmpsock, i;
|
int sock, qmpsock, i;
|
||||||
gchar *socket_path;
|
g_autofree gchar *socket_path = qtest_socket_path("sock");
|
||||||
gchar *qmp_socket_path;
|
g_autofree gchar *qmp_socket_path = qtest_socket_path("qmp");
|
||||||
|
|
||||||
socket_path = g_strdup_printf("%s/qtest-%d.sock",
|
|
||||||
g_get_tmp_dir(), getpid());
|
|
||||||
qmp_socket_path = g_strdup_printf("%s/qtest-%d.qmp",
|
|
||||||
g_get_tmp_dir(), getpid());
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It's possible that if an earlier test run crashed it might
|
* It's possible that if an earlier test run crashed it might
|
||||||
@ -501,22 +504,19 @@ static QTestState *qtest_init_internal(const char *qemu_bin,
|
|||||||
qtest_client_set_rx_handler(s, qtest_client_socket_recv_line);
|
qtest_client_set_rx_handler(s, qtest_client_socket_recv_line);
|
||||||
qtest_client_set_tx_handler(s, qtest_client_socket_send);
|
qtest_client_set_tx_handler(s, qtest_client_socket_send);
|
||||||
|
|
||||||
s->fd = socket_accept(sock);
|
|
||||||
if (s->fd >= 0) {
|
|
||||||
s->qmp_fd = socket_accept(qmpsock);
|
|
||||||
}
|
|
||||||
unlink(socket_path);
|
|
||||||
unlink(qmp_socket_path);
|
|
||||||
g_free(socket_path);
|
|
||||||
g_free(qmp_socket_path);
|
|
||||||
|
|
||||||
g_assert(s->fd >= 0 && s->qmp_fd >= 0);
|
|
||||||
|
|
||||||
s->rx = g_string_new("");
|
s->rx = g_string_new("");
|
||||||
for (i = 0; i < MAX_IRQ; i++) {
|
for (i = 0; i < MAX_IRQ; i++) {
|
||||||
s->irq_level[i] = false;
|
s->irq_level[i] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->fd = -1;
|
||||||
|
s->qmp_fd = -1;
|
||||||
|
s->sock = sock;
|
||||||
|
s->qmpsock = qmpsock;
|
||||||
|
if (do_connect) {
|
||||||
|
qtest_connect(s);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stopping QEMU for debugging is not supported on Windows.
|
* Stopping QEMU for debugging is not supported on Windows.
|
||||||
*
|
*
|
||||||
@ -531,28 +531,38 @@ static QTestState *qtest_init_internal(const char *qemu_bin,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ask endianness of the target */
|
|
||||||
|
|
||||||
s->big_endian = qtest_query_target_endianness(s);
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qtest_connect(QTestState *s)
|
||||||
|
{
|
||||||
|
g_autofree gchar *socket_path = qtest_socket_path("sock");
|
||||||
|
g_autofree gchar *qmp_socket_path = qtest_socket_path("qmp");
|
||||||
|
|
||||||
|
g_assert(s->sock >= 0 && s->qmpsock >= 0);
|
||||||
|
s->fd = socket_accept(s->sock);
|
||||||
|
if (s->fd >= 0) {
|
||||||
|
s->qmp_fd = socket_accept(s->qmpsock);
|
||||||
|
}
|
||||||
|
unlink(socket_path);
|
||||||
|
unlink(qmp_socket_path);
|
||||||
|
g_assert(s->fd >= 0 && s->qmp_fd >= 0);
|
||||||
|
s->sock = s->qmpsock = -1;
|
||||||
|
/* ask endianness of the target */
|
||||||
|
s->big_endian = qtest_query_target_endianness(s);
|
||||||
|
}
|
||||||
|
|
||||||
QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
|
QTestState *qtest_init_without_qmp_handshake(const char *extra_args)
|
||||||
{
|
{
|
||||||
return qtest_init_internal(qtest_qemu_binary(NULL), extra_args);
|
return qtest_init_internal(qtest_qemu_binary(NULL), extra_args, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTestState *qtest_init_with_env_and_capabilities(const char *var,
|
void qtest_qmp_handshake(QTestState *s, QList *capabilities)
|
||||||
const char *extra_args,
|
|
||||||
QList *capabilities)
|
|
||||||
{
|
{
|
||||||
QTestState *s = qtest_init_internal(qtest_qemu_binary(var), extra_args);
|
|
||||||
QDict *greeting;
|
|
||||||
|
|
||||||
/* Read the QMP greeting and then do the handshake */
|
/* Read the QMP greeting and then do the handshake */
|
||||||
greeting = qtest_qmp_receive(s);
|
QDict *greeting = qtest_qmp_receive(s);
|
||||||
qobject_unref(greeting);
|
qobject_unref(greeting);
|
||||||
|
|
||||||
if (capabilities) {
|
if (capabilities) {
|
||||||
qtest_qmp_assert_success(s,
|
qtest_qmp_assert_success(s,
|
||||||
"{ 'execute': 'qmp_capabilities', "
|
"{ 'execute': 'qmp_capabilities', "
|
||||||
@ -561,18 +571,37 @@ QTestState *qtest_init_with_env_and_capabilities(const char *var,
|
|||||||
} else {
|
} else {
|
||||||
qtest_qmp_assert_success(s, "{ 'execute': 'qmp_capabilities' }");
|
qtest_qmp_assert_success(s, "{ 'execute': 'qmp_capabilities' }");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTestState *qtest_init_with_env_and_capabilities(const char *var,
|
||||||
|
const char *extra_args,
|
||||||
|
QList *capabilities,
|
||||||
|
bool do_connect)
|
||||||
|
{
|
||||||
|
QTestState *s = qtest_init_internal(qtest_qemu_binary(var), extra_args,
|
||||||
|
do_connect);
|
||||||
|
|
||||||
|
if (do_connect) {
|
||||||
|
qtest_qmp_handshake(s, capabilities);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If the connection is delayed, the capabilities must be set
|
||||||
|
* at that moment.
|
||||||
|
*/
|
||||||
|
assert(!capabilities);
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTestState *qtest_init_with_env(const char *var, const char *extra_args)
|
QTestState *qtest_init_with_env(const char *var, const char *extra_args,
|
||||||
|
bool do_connect)
|
||||||
{
|
{
|
||||||
return qtest_init_with_env_and_capabilities(var, extra_args, NULL);
|
return qtest_init_with_env_and_capabilities(var, extra_args, NULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTestState *qtest_init(const char *extra_args)
|
QTestState *qtest_init(const char *extra_args)
|
||||||
{
|
{
|
||||||
return qtest_init_with_env(NULL, extra_args);
|
return qtest_init_with_env(NULL, extra_args, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTestState *qtest_vinitf(const char *fmt, va_list ap)
|
QTestState *qtest_vinitf(const char *fmt, va_list ap)
|
||||||
@ -1580,7 +1609,7 @@ static struct MachInfo *qtest_get_machines(const char *var)
|
|||||||
|
|
||||||
silence_spawn_log = !g_test_verbose();
|
silence_spawn_log = !g_test_verbose();
|
||||||
|
|
||||||
qts = qtest_init_with_env(qemu_var, "-machine none");
|
qts = qtest_init_with_env(qemu_var, "-machine none", true);
|
||||||
response = qtest_qmp(qts, "{ 'execute': 'query-machines' }");
|
response = qtest_qmp(qts, "{ 'execute': 'query-machines' }");
|
||||||
g_assert(response);
|
g_assert(response);
|
||||||
list = qdict_get_qlist(response, "return");
|
list = qdict_get_qlist(response, "return");
|
||||||
@ -1635,7 +1664,7 @@ static struct CpuModel *qtest_get_cpu_models(void)
|
|||||||
|
|
||||||
silence_spawn_log = !g_test_verbose();
|
silence_spawn_log = !g_test_verbose();
|
||||||
|
|
||||||
qts = qtest_init_with_env(NULL, "-machine none");
|
qts = qtest_init_with_env(NULL, "-machine none", true);
|
||||||
response = qtest_qmp(qts, "{ 'execute': 'query-cpu-definitions' }");
|
response = qtest_qmp(qts, "{ 'execute': 'query-cpu-definitions' }");
|
||||||
g_assert(response);
|
g_assert(response);
|
||||||
list = qdict_get_qlist(response, "return");
|
list = qdict_get_qlist(response, "return");
|
||||||
|
@ -61,13 +61,15 @@ QTestState *qtest_init(const char *extra_args);
|
|||||||
* @var: Environment variable from where to take the QEMU binary
|
* @var: Environment variable from where to take the QEMU binary
|
||||||
* @extra_args: Other arguments to pass to QEMU. CAUTION: these
|
* @extra_args: Other arguments to pass to QEMU. CAUTION: these
|
||||||
* arguments are subject to word splitting and shell evaluation.
|
* arguments are subject to word splitting and shell evaluation.
|
||||||
|
* @do_connect: connect to qemu monitor and qtest socket.
|
||||||
*
|
*
|
||||||
* Like qtest_init(), but use a different environment variable for the
|
* Like qtest_init(), but use a different environment variable for the
|
||||||
* QEMU binary.
|
* QEMU binary.
|
||||||
*
|
*
|
||||||
* Returns: #QTestState instance.
|
* Returns: #QTestState instance.
|
||||||
*/
|
*/
|
||||||
QTestState *qtest_init_with_env(const char *var, const char *extra_args);
|
QTestState *qtest_init_with_env(const char *var, const char *extra_args,
|
||||||
|
bool do_connect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qtest_init_with_env_and_capabilities:
|
* qtest_init_with_env_and_capabilities:
|
||||||
@ -75,6 +77,7 @@ QTestState *qtest_init_with_env(const char *var, const char *extra_args);
|
|||||||
* @extra_args: Other arguments to pass to QEMU. CAUTION: these
|
* @extra_args: Other arguments to pass to QEMU. CAUTION: these
|
||||||
* arguments are subject to word splitting and shell evaluation.
|
* arguments are subject to word splitting and shell evaluation.
|
||||||
* @capabilities: list of QMP capabilities (strings) to enable
|
* @capabilities: list of QMP capabilities (strings) to enable
|
||||||
|
* @do_connect: connect to qemu monitor and qtest socket.
|
||||||
*
|
*
|
||||||
* Like qtest_init_with_env(), but enable specified capabilities during
|
* Like qtest_init_with_env(), but enable specified capabilities during
|
||||||
* hadshake.
|
* hadshake.
|
||||||
@ -83,7 +86,8 @@ QTestState *qtest_init_with_env(const char *var, const char *extra_args);
|
|||||||
*/
|
*/
|
||||||
QTestState *qtest_init_with_env_and_capabilities(const char *var,
|
QTestState *qtest_init_with_env_and_capabilities(const char *var,
|
||||||
const char *extra_args,
|
const char *extra_args,
|
||||||
QList *capabilities);
|
QList *capabilities,
|
||||||
|
bool do_connect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qtest_init_without_qmp_handshake:
|
* qtest_init_without_qmp_handshake:
|
||||||
@ -94,6 +98,22 @@ QTestState *qtest_init_with_env_and_capabilities(const char *var,
|
|||||||
*/
|
*/
|
||||||
QTestState *qtest_init_without_qmp_handshake(const char *extra_args);
|
QTestState *qtest_init_without_qmp_handshake(const char *extra_args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qtest_connect
|
||||||
|
* @s: #QTestState instance to connect
|
||||||
|
* Connect to qemu monitor and qtest socket, after skipping them in
|
||||||
|
* qtest_init_with_env. Does not handshake with the monitor.
|
||||||
|
*/
|
||||||
|
void qtest_connect(QTestState *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qtest_qmp_handshake:
|
||||||
|
* @s: #QTestState instance to operate on.
|
||||||
|
* @capabilities: list of QMP capabilities (strings) to enable
|
||||||
|
* Perform handshake after connecting to qemu monitor.
|
||||||
|
*/
|
||||||
|
void qtest_qmp_handshake(QTestState *s, QList *capabilities);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qtest_init_with_serial:
|
* qtest_init_with_serial:
|
||||||
* @extra_args: other arguments to pass to QEMU. CAUTION: these
|
* @extra_args: other arguments to pass to QEMU. CAUTION: these
|
||||||
|
@ -196,9 +196,10 @@ static void cleanup(const char *filename)
|
|||||||
|
|
||||||
static QList *migrate_start_get_qmp_capabilities(const MigrateStart *args)
|
static QList *migrate_start_get_qmp_capabilities(const MigrateStart *args)
|
||||||
{
|
{
|
||||||
QList *capabilities = qlist_new();
|
QList *capabilities = NULL;
|
||||||
|
|
||||||
if (args->oob) {
|
if (args->oob) {
|
||||||
|
capabilities = qlist_new();
|
||||||
qlist_append_str(capabilities, "oob");
|
qlist_append_str(capabilities, "oob");
|
||||||
}
|
}
|
||||||
return capabilities;
|
return capabilities;
|
||||||
@ -333,7 +334,7 @@ int migrate_start(QTestState **from, QTestState **to, const char *uri,
|
|||||||
ignore_stderr);
|
ignore_stderr);
|
||||||
if (!args->only_target) {
|
if (!args->only_target) {
|
||||||
*from = qtest_init_with_env_and_capabilities(QEMU_ENV_SRC, cmd_source,
|
*from = qtest_init_with_env_and_capabilities(QEMU_ENV_SRC, cmd_source,
|
||||||
capabilities);
|
capabilities, true);
|
||||||
qtest_qmp_set_event_callback(*from,
|
qtest_qmp_set_event_callback(*from,
|
||||||
migrate_watch_for_events,
|
migrate_watch_for_events,
|
||||||
&src_state);
|
&src_state);
|
||||||
@ -354,7 +355,7 @@ int migrate_start(QTestState **from, QTestState **to, const char *uri,
|
|||||||
args->opts_target ? args->opts_target : "",
|
args->opts_target ? args->opts_target : "",
|
||||||
ignore_stderr);
|
ignore_stderr);
|
||||||
*to = qtest_init_with_env_and_capabilities(QEMU_ENV_DST, cmd_target,
|
*to = qtest_init_with_env_and_capabilities(QEMU_ENV_DST, cmd_target,
|
||||||
capabilities);
|
capabilities, true);
|
||||||
qtest_qmp_set_event_callback(*to,
|
qtest_qmp_set_event_callback(*to,
|
||||||
migrate_watch_for_events,
|
migrate_watch_for_events,
|
||||||
&dst_state);
|
&dst_state);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user