Commit 3cd46d42 authored by Markus Armbruster's avatar Markus Armbruster
Browse files

tests: New helper qtest_qmp_receive_success()



Commit b21373d0 copied wait_command() from tests/migration-test.c
to tests/tpm-util.c.  Replace both copies by new libqtest helper
qtest_qmp_receive_success().  Also use it to simplify
qtest_qmp_device_del().

Bonus: gets rid of a non-literal format string.  A step towards
compile-time format string checking without triggering
-Wformat-nonliteral.

Cc: Thomas Huth <thuth@redhat.com>
Cc: Juan Quintela <quintela@redhat.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: Stefan Berger <stefanb@linux.vnet.ibm.com>
Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
Reviewed-by: default avatarJuan Quintela <quintela@redhat.com>
Reviewed-by: default avatarStefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
Message-Id: <20180806065344.7103-17-armbru@redhat.com>
parent e1454165
Loading
Loading
Loading
Loading
+50 −19
Original line number Diff line number Diff line
@@ -1004,6 +1004,35 @@ void qtest_cb_for_every_machine(void (*cb)(const char *machine))
    qobject_unref(response);
}

QDict *qtest_qmp_receive_success(QTestState *s,
                                 void (*event_cb)(void *opaque,
                                                  const char *event,
                                                  QDict *data),
                                 void *opaque)
{
    QDict *response, *ret, *data;
    const char *event;

    for (;;) {
        response = qtest_qmp_receive(s);
        g_assert(!qdict_haskey(response, "error"));
        ret = qdict_get_qdict(response, "return");
        if (ret) {
            break;
        }
        event = qdict_get_str(response, "event");
        data = qdict_get_qdict(response, "data");
        if (event_cb) {
            event_cb(opaque, event, data);
        }
        qobject_unref(response);
    }

    qobject_ref(ret);
    qobject_unref(response);
    return ret;
}

/*
 * Generic hot-plugging test via the device_add QMP command.
 */
@@ -1028,6 +1057,14 @@ void qtest_qmp_device_add(const char *driver, const char *id,
    qobject_unref(response);
}

static void device_deleted_cb(void *opaque, const char *name, QDict *data)
{
    bool *got_event = opaque;

    g_assert_cmpstr(name, ==, "DEVICE_DELETED");
    *got_event = true;
}

/*
 * Generic hot-unplugging test via the device_del QMP command.
 * Device deletion will get one response and one event. For example:
@@ -1048,27 +1085,21 @@ void qtest_qmp_device_add(const char *driver, const char *id,
 */
void qtest_qmp_device_del(const char *id)
{
    QDict *response1, *response2, *event = NULL;
    bool got_event = false;
    QDict *rsp;

    response1 = qmp("{'execute': 'device_del', 'arguments': {'id': %s}}",
    qtest_qmp_send(global_qtest,
                   "{'execute': 'device_del', 'arguments': {'id': %s}}",
                   id);
    g_assert(response1);
    g_assert(!qdict_haskey(response1, "error"));

    response2 = qmp_receive();
    g_assert(response2);
    g_assert(!qdict_haskey(response2, "error"));

    if (qdict_haskey(response1, "event")) {
        event = response1;
    } else if (qdict_haskey(response2, "event")) {
        event = response2;
    rsp = qtest_qmp_receive_success(global_qtest, device_deleted_cb,
                                    &got_event);
    qobject_unref(rsp);
    if (!got_event) {
        rsp = qmp_receive();
        g_assert_cmpstr(qdict_get_try_str(rsp, "event"),
                        ==, "DEVICE_DELETED");
        qobject_unref(rsp);
    }
    g_assert(event);
    g_assert_cmpstr(qdict_get_str(event, "event"), ==, "DEVICE_DELETED");

    qobject_unref(response1);
    qobject_unref(response2);
}

bool qmp_rsp_is_err(QDict *rsp)
+17 −0
Original line number Diff line number Diff line
@@ -146,6 +146,23 @@ void qtest_qmp_eventwait(QTestState *s, const char *event);
 */
QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event);

/**
 * qtest_qmp_receive_success:
 * @s: #QTestState instance to operate on
 * @event_cb: Event callback
 * @opaque: Argument for @event_cb
 *
 * Poll QMP messages until a command success response is received.
 * If @event_cb, call it for each event received, passing @opaque,
 * the event's name and data.
 * Return the success response's "return" member.
 */
QDict *qtest_qmp_receive_success(QTestState *s,
                                 void (*event_cb)(void *opaque,
                                                  const char *name,
                                                  QDict *data),
                                 void *opaque);

/**
 * qtest_hmp:
 * @s: #QTestState instance to operate on.
+9 −20
Original line number Diff line number Diff line
@@ -149,31 +149,20 @@ static void wait_for_serial(const char *side)
    } while (true);
}

/*
 * Events can get in the way of responses we are actually waiting for.
 */
static QDict *wait_command(QTestState *who, const char *command)
static void stop_cb(void *opaque, const char *name, QDict *data)
{
    const char *event_string;
    QDict *response, *ret;

    response = qtest_qmp(who, command);

    while (qdict_haskey(response, "event")) {
        /* OK, it was an event */
        event_string = qdict_get_str(response, "event");
        if (!strcmp(event_string, "STOP")) {
    if (!strcmp(name, "STOP")) {
        got_stop = true;
    }
        qobject_unref(response);
        response = qtest_qmp_receive(who);
}

    ret = qdict_get_qdict(response, "return");
    g_assert(ret);
    qobject_ref(ret);
    qobject_unref(response);
    return ret;
/*
 * Events can get in the way of responses we are actually waiting for.
 */
static QDict *wait_command(QTestState *who, const char *command)
{
    qtest_qmp_send(who, command);
    return qtest_qmp_receive_success(who, stop_cb, NULL);
}

/*
+4 −28
Original line number Diff line number Diff line
@@ -22,8 +22,6 @@
#define TIS_REG(LOCTY, REG) \
    (TPM_TIS_ADDR_BASE + ((LOCTY) << 12) + REG)

static bool got_stop;

void tpm_util_crb_transfer(QTestState *s,
                           const unsigned char *req, size_t req_size,
                           unsigned char *rsp, size_t rsp_size)
@@ -247,41 +245,19 @@ void tpm_util_migrate(QTestState *who, const char *uri)
    qobject_unref(rsp);
}

/*
 * Events can get in the way of responses we are actually waiting for.
 */
static QDict *tpm_util_wait_command(QTestState *who, const char *command)
{
    const char *event_string;
    QDict *response;

    response = qtest_qmp(who, command);

    while (qdict_haskey(response, "event")) {
        /* OK, it was an event */
        event_string = qdict_get_str(response, "event");
        if (!strcmp(event_string, "STOP")) {
            got_stop = true;
        }
        qobject_unref(response);
        response = qtest_qmp_receive(who);
    }
    return response;
}

void tpm_util_wait_for_migration_complete(QTestState *who)
{
    while (true) {
        QDict *rsp, *rsp_return;
        QDict *rsp_return;
        bool completed;
        const char *status;

        rsp = tpm_util_wait_command(who, "{ 'execute': 'query-migrate' }");
        rsp_return = qdict_get_qdict(rsp, "return");
        qtest_qmp_send(who, "{ 'execute': 'query-migrate' }");
        rsp_return = qtest_qmp_receive_success(who, NULL, NULL);
        status = qdict_get_str(rsp_return, "status");
        completed = strcmp(status, "completed") == 0;
        g_assert_cmpstr(status, !=,  "failed");
        qobject_unref(rsp);
        qobject_unref(rsp_return);
        if (completed) {
            return;
        }