qemumonitortestutils: Make test monitor failures more prominent

Until now we've tried to report errors from the test monitor code by
passing them back as failures from the qemu we simulate. This doesn't
work well in cases when the monitor logic does not detect failures or
has fallback code. Additionally there isn't much use for continuing the
test execution after first failure as in most cases the test data will
be misaligned and all other calls will fail as well.

To make the errors more obvious this patch moves away from reporting
them via the simulated monitor to reporting them to stderr and
exit()ing afterwards. While this might be less convenient
when developing tests it actually makes failures in the test suite
really obvious and doesn't require any opt-in from the tests themselves.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
Peter Krempa 2020-04-23 11:57:14 +02:00
parent 1f3ce96e70
commit 84a20fe8e3
2 changed files with 59 additions and 61 deletions

View File

@ -900,6 +900,7 @@ sc_flake8:
sc_prohibit_exit_in_tests: sc_prohibit_exit_in_tests:
@prohibit='\<exit *\(' \ @prohibit='\<exit *\(' \
in_vc_files='tests/.*\.c$$' \ in_vc_files='tests/.*\.c$$' \
exclude='exempt from syntax-check' \
halt='use return, not exit(), in tests' \ halt='use return, not exit(), in tests' \
$(_sc_search_regexp) $(_sc_search_regexp)

View File

@ -153,18 +153,6 @@ qemuMonitorTestAddErrorResponseInternal(qemuMonitorTestPtr test,
} }
static int
qemuMonitorTestAddUnexpectedErrorResponse(qemuMonitorTestPtr test,
const char *command)
{
g_autofree char *msg = NULL;
msg = g_strdup_printf("unexpected command: '%s'", command);
return qemuMonitorTestAddErrorResponseInternal(test, msg);
}
int int
qemuMonitorTestAddInvalidCommandResponse(qemuMonitorTestPtr test, qemuMonitorTestAddInvalidCommandResponse(qemuMonitorTestPtr test,
const char *expectedcommand, const char *expectedcommand,
@ -201,6 +189,31 @@ qemuMonitorTestAddErrorResponse(qemuMonitorTestPtr test, const char *errmsg, ...
} }
static void G_GNUC_NORETURN G_GNUC_PRINTF(1, 2)
qemuMonitorTestError(const char *errmsg,
...)
{
va_list msgargs;
va_start(msgargs, errmsg);
g_fprintf(stderr, "\n");
g_vfprintf(stderr, errmsg, msgargs);
g_fprintf(stderr, "\n");
exit(EXIT_FAILURE); /* exempt from syntax-check */
}
static void G_GNUC_NORETURN
qemuMonitorTestErrorInvalidCommand(const char *expectedcommand,
const char *actualcommand)
{
qemuMonitorTestError("expected command '%s' got '%s'",
expectedcommand, actualcommand);
}
static int static int
qemuMonitorTestProcessCommand(qemuMonitorTestPtr test, qemuMonitorTestProcessCommand(qemuMonitorTestPtr test,
const char *cmdstr) const char *cmdstr)
@ -210,7 +223,7 @@ qemuMonitorTestProcessCommand(qemuMonitorTestPtr test,
VIR_DEBUG("Processing string from monitor handler: '%s", cmdstr); VIR_DEBUG("Processing string from monitor handler: '%s", cmdstr);
if (test->nitems == 0) { if (test->nitems == 0) {
return qemuMonitorTestAddUnexpectedErrorResponse(test, cmdstr); qemuMonitorTestError("unexpected command: '%s'", cmdstr);
} else { } else {
qemuMonitorTestItemPtr item = test->items[0]; qemuMonitorTestItemPtr item = test->items[0];
ret = (item->cb)(test, item, cmdstr); ret = (item->cb)(test, item, cmdstr);
@ -527,10 +540,7 @@ qemuMonitorTestProcessCommandDefaultValidate(qemuMonitorTestPtr test,
if (virQEMUQAPISchemaPathGet(schemapath, test->qapischema, &schemaroot) < 0 || if (virQEMUQAPISchemaPathGet(schemapath, test->qapischema, &schemaroot) < 0 ||
!schemaroot) { !schemaroot) {
if (qemuMonitorTestAddErrorResponse(test, qemuMonitorTestError("command '%s' not found in QAPI schema", cmdname);
"command '%s' not found in QAPI schema",
cmdname) == 0)
return 1;
return -1; return -1;
} }
@ -546,12 +556,10 @@ qemuMonitorTestProcessCommandDefaultValidate(qemuMonitorTestPtr test,
cmdname, NULLSTR(argstr), virBufferCurrentContent(&debug)); cmdname, NULLSTR(argstr), virBufferCurrentContent(&debug));
} }
if (qemuMonitorTestAddErrorResponse(test, qemuMonitorTestError("failed to validate arguments of '%s' "
"failed to validate arguments of '%s' " "against QAPI schema "
"against QAPI schema " "(to see debug output use VIR_TEST_DEBUG=2)",
"(to see debug output use VIR_TEST_DEBUG=2)", cmdname);
cmdname) == 0)
return 1;
return -1; return -1;
} }
@ -573,8 +581,10 @@ qemuMonitorTestProcessCommandDefault(qemuMonitorTestPtr test,
if (!(val = virJSONValueFromString(cmdstr))) if (!(val = virJSONValueFromString(cmdstr)))
return -1; return -1;
if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) {
return qemuMonitorTestAddErrorResponse(test, "Missing command name in %s", cmdstr); qemuMonitorTestError("Missing command name in %s", cmdstr);
return -1;
}
cmdargs = virJSONValueObjectGet(val, "arguments"); cmdargs = virJSONValueObjectGet(val, "arguments");
if ((rc = qemuMonitorTestProcessCommandDefaultValidate(test, cmdname, cmdargs)) < 0) if ((rc = qemuMonitorTestProcessCommandDefaultValidate(test, cmdname, cmdargs)) < 0)
@ -583,8 +593,8 @@ qemuMonitorTestProcessCommandDefault(qemuMonitorTestPtr test,
return 0; return 0;
if (data->command_name && STRNEQ(data->command_name, cmdname)) { if (data->command_name && STRNEQ(data->command_name, cmdname)) {
return qemuMonitorTestAddInvalidCommandResponse(test, data->command_name, qemuMonitorTestErrorInvalidCommand(data->command_name, cmdname);
cmdname); return -1;
} else { } else {
return qemuMonitorTestAddResponse(test, data->response); return qemuMonitorTestAddResponse(test, data->response);
} }
@ -617,7 +627,6 @@ qemuMonitorTestProcessCommandVerbatim(qemuMonitorTestPtr test,
{ {
struct qemuMonitorTestHandlerData *data = item->opaque; struct qemuMonitorTestHandlerData *data = item->opaque;
g_autofree char *reformatted = NULL; g_autofree char *reformatted = NULL;
g_autofree char *errmsg = NULL;
g_autoptr(virJSONValue) json = NULL; g_autoptr(virJSONValue) json = NULL;
virJSONValuePtr cmdargs; virJSONValuePtr cmdargs;
const char *cmdname; const char *cmdname;
@ -646,13 +655,9 @@ qemuMonitorTestProcessCommandVerbatim(qemuMonitorTestPtr test,
ret = qemuMonitorTestAddResponse(test, data->response); ret = qemuMonitorTestAddResponse(test, data->response);
} else { } else {
if (data->cmderr) { if (data->cmderr) {
errmsg = g_strdup_printf("%s: %s", data->cmderr, cmdstr); qemuMonitorTestError("%s: %s", data->cmderr, cmdstr);
ret = qemuMonitorTestAddErrorResponseInternal(test, errmsg);
} else { } else {
ret = qemuMonitorTestAddInvalidCommandResponse(test, qemuMonitorTestErrorInvalidCommand(data->command_name, cmdstr);
data->command_name,
cmdstr);
} }
} }
@ -782,21 +787,19 @@ qemuMonitorTestProcessCommandWithArgs(qemuMonitorTestPtr test,
return -1; return -1;
if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) { if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) {
ret = qemuMonitorTestAddErrorResponse(test, "Missing command name in %s", cmdstr); qemuMonitorTestError("Missing command name in %s", cmdstr);
goto cleanup; goto cleanup;
} }
if (data->command_name && if (data->command_name &&
STRNEQ(data->command_name, cmdname)) { STRNEQ(data->command_name, cmdname)) {
ret = qemuMonitorTestAddInvalidCommandResponse(test, data->command_name, qemuMonitorTestErrorInvalidCommand(data->command_name, cmdname);
cmdname);
goto cleanup; goto cleanup;
} }
if (!(args = virJSONValueObjectGet(val, "arguments"))) { if (!(args = virJSONValueObjectGet(val, "arguments"))) {
ret = qemuMonitorTestAddErrorResponse(test, qemuMonitorTestError("Missing arguments section for command '%s'",
"Missing arguments section for command '%s'", NULLSTR(data->command_name));
NULLSTR(data->command_name));
goto cleanup; goto cleanup;
} }
@ -804,10 +807,9 @@ qemuMonitorTestProcessCommandWithArgs(qemuMonitorTestPtr test,
for (i = 0; i < data->nargs; i++) { for (i = 0; i < data->nargs; i++) {
qemuMonitorTestCommandArgsPtr arg = &data->args[i]; qemuMonitorTestCommandArgsPtr arg = &data->args[i];
if (!(argobj = virJSONValueObjectGet(args, arg->argname))) { if (!(argobj = virJSONValueObjectGet(args, arg->argname))) {
ret = qemuMonitorTestAddErrorResponse(test, qemuMonitorTestError("Missing argument '%s' for command '%s'",
"Missing argument '%s' for command '%s'", arg->argname,
arg->argname, NULLSTR(data->command_name));
NULLSTR(data->command_name));
goto cleanup; goto cleanup;
} }
@ -817,13 +819,11 @@ qemuMonitorTestProcessCommandWithArgs(qemuMonitorTestPtr test,
/* verify that the argument value is expected */ /* verify that the argument value is expected */
if (STRNEQ(argstr, arg->argval)) { if (STRNEQ(argstr, arg->argval)) {
ret = qemuMonitorTestAddErrorResponse(test, qemuMonitorTestError("Invalid value of argument '%s' of command '%s': "
"Invalid value of argument '%s' " "expected '%s' got '%s'",
"of command '%s': " arg->argname,
"expected '%s' got '%s'", NULLSTR(data->command_name),
arg->argname, arg->argval, argstr);
NULLSTR(data->command_name),
arg->argval, argstr);
goto cleanup; goto cleanup;
} }
@ -908,20 +908,18 @@ qemuMonitorTestProcessCommandWithArgStr(qemuMonitorTestPtr test,
return -1; return -1;
if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) { if (!(cmdname = virJSONValueObjectGetString(val, "execute"))) {
ret = qemuMonitorTestAddErrorResponse(test, "Missing command name in %s", cmdstr); qemuMonitorTestError("Missing command name in %s", cmdstr);
goto cleanup; goto cleanup;
} }
if (STRNEQ(data->command_name, cmdname)) { if (STRNEQ(data->command_name, cmdname)) {
ret = qemuMonitorTestAddInvalidCommandResponse(test, data->command_name, qemuMonitorTestErrorInvalidCommand(data->command_name, cmdname);
cmdname);
goto cleanup; goto cleanup;
} }
if (!(args = virJSONValueObjectGet(val, "arguments"))) { if (!(args = virJSONValueObjectGet(val, "arguments"))) {
ret = qemuMonitorTestAddErrorResponse(test, qemuMonitorTestError("Missing arguments section for command '%s'",
"Missing arguments section for command '%s'", data->command_name);
data->command_name);
goto cleanup; goto cleanup;
} }
@ -931,10 +929,9 @@ qemuMonitorTestProcessCommandWithArgStr(qemuMonitorTestPtr test,
/* verify that the argument value is expected */ /* verify that the argument value is expected */
if (STRNEQ(argstr, data->expectArgs)) { if (STRNEQ(argstr, data->expectArgs)) {
ret = qemuMonitorTestAddErrorResponse(test, qemuMonitorTestError("%s: expected arguments: '%s', got: '%s'",
"%s: expected arguments: '%s', got: '%s'", data->command_name,
data->command_name, data->expectArgs, argstr);
data->expectArgs, argstr);
goto cleanup; goto cleanup;
} }