qemumonitortestutils: Refactor the test helpers to allow reuse

Refactor the test helpers to allow adding callbacks to verify the
monitor responses instead of simple command name checking and clean up
various parts to prepare for adding guest agent tests.
This commit is contained in:
Peter Krempa 2013-07-25 11:48:11 +02:00
parent 3383480430
commit 5467cbef4b
2 changed files with 149 additions and 105 deletions

View File

@ -36,12 +36,10 @@
#define VIR_FROM_THIS VIR_FROM_NONE
typedef struct _qemuMonitorTestItem qemuMonitorTestItem;
typedef qemuMonitorTestItem *qemuMonitorTestItemPtr;
struct _qemuMonitorTestItem {
char *command_name;
char *response;
qemuMonitorTestResponseCallback cb;
void *opaque;
virFreeCallback freecb;
};
struct _qemuMonitorTest {
@ -74,13 +72,23 @@ struct _qemuMonitorTest {
};
static void qemuMonitorTestItemFree(qemuMonitorTestItemPtr item);
static void
qemuMonitorTestItemFree(qemuMonitorTestItemPtr item)
{
if (!item)
return;
if (item->freecb)
(item->freecb)(item->opaque);
VIR_FREE(item);
}
/*
* Appends data for a reply to the outgoing buffer
*/
static int
int
qemuMonitorTestAddReponse(qemuMonitorTestPtr test,
const char *response)
{
@ -101,81 +109,17 @@ qemuMonitorTestAddReponse(qemuMonitorTestPtr test,
}
/*
* Processes a single line, looking for a matching expected
* item to reply with, else replies with an error
*/
static int
qemuMonitorTestProcessCommandJSON(qemuMonitorTestPtr test,
const char *cmdstr)
qemuMonitorTestAddUnexpectedErrorResponse(qemuMonitorTestPtr test)
{
virJSONValuePtr val;
const char *cmdname;
int ret = -1;
if (!(val = virJSONValueFromString(cmdstr)))
return -1;
if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Missing command name in %s", cmdstr);
goto cleanup;
}
if (test->nitems == 0 ||
STRNEQ(test->items[0]->command_name, cmdname)) {
ret = qemuMonitorTestAddReponse(test,
"{ \"error\": "
" { \"desc\": \"Unexpected command\", "
" \"class\": \"UnexpectedCommand\" } }");
if (test->json) {
return qemuMonitorTestAddReponse(test,
"{ \"error\": "
" { \"desc\": \"Unexpected command\", "
" \"class\": \"UnexpectedCommand\" } }");
} else {
ret = qemuMonitorTestAddReponse(test, test->items[0]->response);
qemuMonitorTestItemFree(test->items[0]);
if (VIR_DELETE_ELEMENT(test->items, 0, test->nitems) < 0) {
ret = -1;
goto cleanup;
}
return qemuMonitorTestAddReponse(test, "unexpected command");
}
cleanup:
virJSONValueFree(val);
return ret;
}
static int
qemuMonitorTestProcessCommandText(qemuMonitorTestPtr test,
const char *cmdstr)
{
char *tmp;
char *cmdname;
int ret = -1;
if (VIR_STRDUP(cmdname, cmdstr) < 0)
return -1;
if (!(tmp = strchr(cmdname, ' '))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Cannot find command name in '%s'", cmdstr);
goto cleanup;
}
*tmp = '\0';
if (test->nitems == 0 ||
STRNEQ(test->items[0]->command_name, cmdname)) {
ret = qemuMonitorTestAddReponse(test,
"unexpected command");
} else {
ret = qemuMonitorTestAddReponse(test, test->items[0]->response);
qemuMonitorTestItemFree(test->items[0]);
if (VIR_DELETE_ELEMENT(test->items, 0, test->nitems) < 0) {
ret = -1;
goto cleanup;
}
}
cleanup:
VIR_FREE(cmdname);
return ret;
}
@ -183,10 +127,19 @@ static int
qemuMonitorTestProcessCommand(qemuMonitorTestPtr test,
const char *cmdstr)
{
if (test->json)
return qemuMonitorTestProcessCommandJSON(test ,cmdstr);
else
return qemuMonitorTestProcessCommandText(test ,cmdstr);
int ret;
if (test->nitems == 0) {
return qemuMonitorTestAddUnexpectedErrorResponse(test);
} else {
qemuMonitorTestItemPtr item = test->items[0];
ret = (item->cb)(test, item, cmdstr);
qemuMonitorTestItemFree(item);
if (VIR_DELETE_ELEMENT(test->items, 0, test->nitems) < 0)
return -1;
}
return ret;
}
@ -316,19 +269,6 @@ qemuMonitorTestWorker(void *opaque)
}
static void
qemuMonitorTestItemFree(qemuMonitorTestItemPtr item)
{
if (!item)
return;
VIR_FREE(item->command_name);
VIR_FREE(item->response);
VIR_FREE(item);
}
static void
qemuMonitorTestFreeTimer(int timer ATTRIBUTE_UNUSED,
void *opaque ATTRIBUTE_UNUSED)
@ -392,18 +332,19 @@ qemuMonitorTestFree(qemuMonitorTestPtr test)
int
qemuMonitorTestAddItem(qemuMonitorTestPtr test,
const char *command_name,
const char *response)
qemuMonitorTestAddHandler(qemuMonitorTestPtr test,
qemuMonitorTestResponseCallback cb,
void *opaque,
virFreeCallback freecb)
{
qemuMonitorTestItemPtr item;
if (VIR_ALLOC(item) < 0)
goto error;
if (VIR_STRDUP(item->command_name, command_name) < 0 ||
VIR_STRDUP(item->response, response) < 0)
goto error;
item->cb = cb;
item->freecb = freecb;
item->opaque = opaque;
virMutexLock(&test->lock);
if (VIR_APPEND_ELEMENT(test->items, test->nitems, item) < 0) {
@ -415,10 +356,91 @@ qemuMonitorTestAddItem(qemuMonitorTestPtr test,
return 0;
error:
qemuMonitorTestItemFree(item);
if (freecb)
(freecb)(opaque);
VIR_FREE(item);
return -1;
}
void *
qemuMonitorTestItemGetPrivateData(qemuMonitorTestItemPtr item)
{
return item ? item->opaque : NULL;
}
struct qemuMonitorTestDefaultHandlerData {
const char *command_name;
const char *response;
};
static int
qemuMonitorTestProcessCommandDefault(qemuMonitorTestPtr test,
qemuMonitorTestItemPtr item,
const char *cmdstr)
{
struct qemuMonitorTestDefaultHandlerData *data = item->opaque;
virJSONValuePtr val = NULL;
char *cmdcopy = NULL;
const char *cmdname;
char *tmp;
int ret = -1;
if (test->json) {
if (!(val = virJSONValueFromString(cmdstr)))
return -1;
if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Missing command name in %s", cmdstr);
goto cleanup;
}
} else {
if (VIR_STRDUP(cmdcopy, cmdstr) < 0)
return -1;
cmdname = cmdcopy;
if (!(tmp = strchr(cmdcopy, ' '))) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"Cannot find command name in '%s'", cmdstr);
goto cleanup;
}
*tmp = '\0';
}
if (STRNEQ(data->command_name, cmdname))
ret = qemuMonitorTestAddUnexpectedErrorResponse(test);
else
ret = qemuMonitorTestAddReponse(test, data->response);
cleanup:
VIR_FREE(cmdcopy);
virJSONValueFree(val);
return ret;
}
int
qemuMonitorTestAddItem(qemuMonitorTestPtr test,
const char *command_name,
const char *response)
{
struct qemuMonitorTestDefaultHandlerData *data;
if (VIR_ALLOC(data) < 0)
return -1;
data->command_name = command_name;
data->response = response;
return qemuMonitorTestAddHandler(test,
qemuMonitorTestProcessCommandDefault,
data,
free);
}
static void
qemuMonitorTestEOFNotify(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
@ -434,7 +456,7 @@ qemuMonitorTestErrorNotify(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
}
static qemuMonitorCallbacks qemuCallbacks = {
static qemuMonitorCallbacks qemuMonitorTestCallbacks = {
.eofNotify = qemuMonitorTestEOFNotify,
.errorNotify = qemuMonitorTestErrorNotify,
};
@ -502,6 +524,8 @@ error:
static int
qemuMonitorCommonTestInit(qemuMonitorTestPtr test)
{
int events = VIR_EVENT_HANDLE_READABLE;
if (!test)
return -1;
@ -511,8 +535,11 @@ qemuMonitorCommonTestInit(qemuMonitorTestPtr test)
if (!test->client)
goto error;
if (test->outgoingLength > 0)
events = VIR_EVENT_HANDLE_WRITABLE;
if (virNetSocketAddIOCallback(test->client,
VIR_EVENT_HANDLE_WRITABLE,
events,
qemuMonitorTestIO,
test,
NULL) < 0)
@ -566,7 +593,7 @@ qemuMonitorTestNew(bool json, virDomainXMLOptionPtr xmlopt)
if (!(test->mon = qemuMonitorOpen(test->vm,
&src,
json,
&qemuCallbacks)))
&qemuMonitorTestCallbacks)))
goto error;
virObjectLock(test->mon);

View File

@ -26,6 +26,23 @@
typedef struct _qemuMonitorTest qemuMonitorTest;
typedef qemuMonitorTest *qemuMonitorTestPtr;
typedef struct _qemuMonitorTestItem qemuMonitorTestItem;
typedef qemuMonitorTestItem *qemuMonitorTestItemPtr;
typedef int (*qemuMonitorTestResponseCallback)(qemuMonitorTestPtr test,
qemuMonitorTestItemPtr item,
const char *message);
int qemuMonitorTestAddHandler(qemuMonitorTestPtr test,
qemuMonitorTestResponseCallback cb,
void *opaque,
virFreeCallback freecb);
int qemuMonitorTestAddReponse(qemuMonitorTestPtr test,
const char *response);
void *qemuMonitorTestItemGetPrivateData(qemuMonitorTestItemPtr item);
int qemuMonitorTestAddItem(qemuMonitorTestPtr test,
const char *command_name,
const char *response);