diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 7ae28fb6ac..77de16227f 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -82,6 +82,8 @@ struct QTestState GString *rx; QTestTransportOps ops; GList *pending_events; + QTestQMPEventCallback eventCB; + void *eventData; }; static GHookList abrt_hooks; @@ -703,8 +705,13 @@ QDict *qtest_qmp_receive(QTestState *s) if (!qdict_get_try_str(response, "event")) { return response; } - /* Stash the event for a later consumption */ - s->pending_events = g_list_append(s->pending_events, response); + + if (!s->eventCB || + !s->eventCB(s, qdict_get_str(response, "event"), + response, s->eventData)) { + /* Stash the event for a later consumption */ + s->pending_events = g_list_append(s->pending_events, response); + } } } @@ -808,6 +815,13 @@ void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...) va_end(ap); } +void qtest_qmp_set_event_callback(QTestState *s, + QTestQMPEventCallback cb, void *opaque) +{ + s->eventCB = cb; + s->eventData = opaque; +} + QDict *qtest_qmp_event_ref(QTestState *s, const char *event) { while (s->pending_events) { diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h index d310eba7fb..a12acf7fa9 100644 --- a/tests/qtest/libqtest.h +++ b/tests/qtest/libqtest.h @@ -238,17 +238,52 @@ QDict *qtest_qmp_receive_dict(QTestState *s); * @s: #QTestState instance to operate on. * * Reads a QMP message from QEMU and returns the response. - * Buffers all the events received meanwhile, until a - * call to qtest_qmp_eventwait + * + * If a callback is registered with qtest_qmp_set_event_callback, + * it will be invoked for every event seen, otherwise events + * will be buffered until a call to one of the qtest_qmp_eventwait + * family of functions. */ QDict *qtest_qmp_receive(QTestState *s); +/* + * QTestQMPEventCallback: + * @s: #QTestState instance event was received on + * @name: name of the event type + * @event: #QDict for the event details + * @opaque: opaque data from time of callback registration + * + * This callback will be invoked whenever an event is received. + * If the callback returns true the event will be consumed, + * otherwise it will be put on the list of pending events. + * Pending events can be later handled by calling either + * qtest_qmp_eventwait or qtest_qmp_eventwait_ref. + * + * Return: true to consume the event, false to let it be queued + */ +typedef bool (*QTestQMPEventCallback)(QTestState *s, const char *name, + QDict *event, void *opaque); + +/** + * qtest_qmp_set_event_callback: + * @s: #QTestSTate instance to operate on + * @cb: callback to invoke for events + * @opaque: data to pass to @cb + * + * Register a callback to be invoked whenever an event arrives + */ +void qtest_qmp_set_event_callback(QTestState *s, + QTestQMPEventCallback cb, void *opaque); + /** * qtest_qmp_eventwait: * @s: #QTestState instance to operate on. * @event: event to wait for. * * Continuously polls for QMP responses until it receives the desired event. + * + * Any callback registered with qtest_qmp_set_event_callback will + * be invoked for every event seen. */ void qtest_qmp_eventwait(QTestState *s, const char *event); @@ -258,6 +293,10 @@ void qtest_qmp_eventwait(QTestState *s, const char *event); * @event: event to wait for. * * Continuously polls for QMP responses until it receives the desired event. + * + * Any callback registered with qtest_qmp_set_event_callback will + * be invoked for every event seen. + * * Returns a copy of the event for further investigation. */ QDict *qtest_qmp_eventwait_ref(QTestState *s, const char *event);