tests: New helper qtest_qmp_receive_success()
Commit b21373d0713 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: Markus Armbruster <armbru@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20180806065344.7103-17-armbru@redhat.com>
This commit is contained in:
		
							parent
							
								
									e145416524
								
							
						
					
					
						commit
						3cd46d42fe
					
				| @ -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}}", | ||||
|                     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; | ||||
|     qtest_qmp_send(global_qtest, | ||||
|                    "{'execute': 'device_del', 'arguments': {'id': %s}}", | ||||
|                    id); | ||||
|     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) | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
| @ -149,31 +149,20 @@ static void wait_for_serial(const char *side) | ||||
|     } while (true); | ||||
| } | ||||
| 
 | ||||
| static void stop_cb(void *opaque, const char *name, QDict *data) | ||||
| { | ||||
|     if (!strcmp(name, "STOP")) { | ||||
|         got_stop = true; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Events can get in the way of responses we are actually waiting for. | ||||
|  */ | ||||
| static QDict *wait_command(QTestState *who, const char *command) | ||||
| { | ||||
|     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")) { | ||||
|             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; | ||||
|     qtest_qmp_send(who, command); | ||||
|     return qtest_qmp_receive_success(who, stop_cb, NULL); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
| @ -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; | ||||
|         } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Markus Armbruster
						Markus Armbruster