2 * Copyright (C) 2011-2013 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
24 #include "testutils.h"
25 #include "testutilsqemuschema.h"
26 #include "qemumonitortestutils.h"
28 #include "virthread.h"
29 #define LIBVIRT_QEMU_PROCESSPRIV_H_ALLOW
30 #include "qemu/qemu_processpriv.h"
31 #include "qemu/qemu_monitor.h"
32 #include "qemu/qemu_agent.h"
33 #include "qemu/qemu_qapi.h"
34 #include "rpc/virnetsocket.h"
38 #include "virstring.h"
40 #define VIR_FROM_THIS VIR_FROM_NONE
42 VIR_LOG_INIT("tests.qemumonitortestutils");
44 struct _qemuMonitorTestItem
{
45 qemuMonitorTestResponseCallback cb
;
47 virFreeCallback freecb
;
50 struct _qemuMonitorTest
{
59 size_t incomingLength
;
60 size_t incomingCapacity
;
63 size_t outgoingLength
;
64 size_t outgoingCapacity
;
66 virNetSocketPtr server
;
67 virNetSocketPtr client
;
75 qemuMonitorTestItemPtr
*items
;
78 virHashTablePtr qapischema
;
83 qemuMonitorTestItemFree(qemuMonitorTestItemPtr item
)
89 (item
->freecb
)(item
->opaque
);
96 * Appends data for a reply to the outgoing buffer
99 qemuMonitorTestAddResponse(qemuMonitorTestPtr test
,
100 const char *response
)
102 size_t want
= strlen(response
) + 2;
103 size_t have
= test
->outgoingCapacity
- test
->outgoingLength
;
105 VIR_DEBUG("Adding response to monitor command: '%s", response
);
108 size_t need
= want
- have
;
109 if (VIR_EXPAND_N(test
->outgoing
, test
->outgoingCapacity
, need
) < 0)
114 memcpy(test
->outgoing
+ test
->outgoingLength
, response
, want
);
115 memcpy(test
->outgoing
+ test
->outgoingLength
+ want
, "\r\n", 2);
116 test
->outgoingLength
+= want
+ 2;
122 qemuMonitorTestAddErrorResponse(qemuMonitorTestPtr test
,
125 virBuffer buf
= VIR_BUFFER_INITIALIZER
;
126 VIR_AUTOFREE(char *) escapemsg
= NULL
;
127 VIR_AUTOFREE(char *) jsonmsg
= NULL
;
131 usermsg
= "unexpected command";
133 virBufferEscape(&buf
, '\\', "\"", "%s", usermsg
);
134 if (virBufferCheckError(&buf
) < 0)
136 escapemsg
= virBufferContentAndReset(&buf
);
138 /* replace newline/carriage return with space */
141 if (*tmp
== '\r' || *tmp
== '\n')
147 /* format the JSON error message */
148 if (virAsprintf(&jsonmsg
, "{ \"error\": "
149 " { \"desc\": \"%s\", "
150 " \"class\": \"UnexpectedCommand\" } }",
154 return qemuMonitorTestAddResponse(test
, jsonmsg
);
159 qemuMonitorTestAddUnexpectedErrorResponse(qemuMonitorTestPtr test
,
162 VIR_AUTOFREE(char *) msg
= NULL
;
164 if (virAsprintf(&msg
, "unexpected command: '%s'", command
) < 0)
167 return qemuMonitorTestAddErrorResponse(test
, msg
);
172 qemuMonitorTestAddInvalidCommandResponse(qemuMonitorTestPtr test
,
173 const char *expectedcommand
,
174 const char *actualcommand
)
176 VIR_AUTOFREE(char *) msg
= NULL
;
178 if (virAsprintf(&msg
, "expected command '%s' got '%s'",
179 expectedcommand
, actualcommand
) < 0)
182 return qemuMonitorTestAddErrorResponse(test
, msg
);
186 int ATTRIBUTE_FMT_PRINTF(2, 3)
187 qemuMonitorReportError(qemuMonitorTestPtr test
, const char *errmsg
, ...)
190 VIR_AUTOFREE(char *) tmp
= NULL
;
191 VIR_AUTOFREE(char *) msg
= NULL
;
192 VIR_AUTOFREE(char *) jsonmsg
= NULL
;
195 va_start(msgargs
, errmsg
);
197 if (virVasprintf(&msg
, errmsg
, msgargs
) < 0)
200 if (!(tmp
= qemuMonitorEscapeArg(msg
)))
203 if (virAsprintf(&jsonmsg
, "{ \"error\": "
204 " { \"desc\": \"%s\", "
205 " \"class\": \"UnexpectedCommand\" } }",
209 ret
= qemuMonitorTestAddResponse(test
, jsonmsg
);
218 qemuMonitorTestProcessCommand(qemuMonitorTestPtr test
,
223 VIR_DEBUG("Processing string from monitor handler: '%s", cmdstr
);
225 if (test
->nitems
== 0) {
226 return qemuMonitorTestAddUnexpectedErrorResponse(test
, cmdstr
);
228 qemuMonitorTestItemPtr item
= test
->items
[0];
229 ret
= (item
->cb
)(test
, item
, cmdstr
);
230 qemuMonitorTestItemFree(item
);
231 if (VIR_DELETE_ELEMENT(test
->items
, 0, test
->nitems
) < 0)
240 * Handles read/write of monitor data on the monitor server side
243 qemuMonitorTestIO(virNetSocketPtr sock
,
247 qemuMonitorTestPtr test
= opaque
;
250 virMutexLock(&test
->lock
);
252 virMutexUnlock(&test
->lock
);
255 if (events
& VIR_EVENT_HANDLE_WRITABLE
) {
257 if ((ret
= virNetSocketWrite(sock
,
259 test
->outgoingLength
)) < 0) {
264 memmove(test
->outgoing
,
265 test
->outgoing
+ ret
,
266 test
->outgoingLength
- ret
);
267 test
->outgoingLength
-= ret
;
269 if ((test
->outgoingCapacity
- test
->outgoingLength
) > 1024)
270 VIR_SHRINK_N(test
->outgoing
, test
->outgoingCapacity
, 1024);
273 if (events
& VIR_EVENT_HANDLE_READABLE
) {
277 if ((test
->incomingCapacity
- test
->incomingLength
) < 1024) {
278 if (VIR_EXPAND_N(test
->incoming
, test
->incomingCapacity
, 1024) < 0) {
284 if ((ret
= virNetSocketRead(sock
,
285 test
->incoming
+ test
->incomingLength
,
286 (test
->incomingCapacity
- test
->incomingLength
) - 1)) < 0) {
290 test
->incomingLength
+= ret
;
291 test
->incoming
[test
->incomingLength
] = '\0';
293 /* Look to see if we've got a complete line, and
294 * if so, handle that command
297 while ((t2
= strstr(t1
, "\n")) ||
298 (test
->agent
&& (t2
= strstr(t1
, "\r")))) {
301 if (qemuMonitorTestProcessCommand(test
, t1
) < 0) {
308 used
= t1
- test
->incoming
;
309 memmove(test
->incoming
, t1
, test
->incomingLength
- used
);
310 test
->incomingLength
-= used
;
311 if ((test
->incomingCapacity
- test
->incomingLength
) > 1024) {
312 VIR_SHRINK_N(test
->incoming
,
313 test
->incomingCapacity
,
318 if (events
& (VIR_EVENT_HANDLE_HANGUP
|
319 VIR_EVENT_HANDLE_ERROR
))
324 virNetSocketRemoveIOCallback(sock
);
325 virNetSocketClose(sock
);
326 virObjectUnref(test
->client
);
329 events
= VIR_EVENT_HANDLE_READABLE
;
331 if (test
->outgoingLength
)
332 events
|= VIR_EVENT_HANDLE_WRITABLE
;
334 virNetSocketUpdateIOCallback(sock
, events
);
336 virMutexUnlock(&test
->lock
);
341 qemuMonitorTestWorker(void *opaque
)
343 qemuMonitorTestPtr test
= opaque
;
345 virMutexLock(&test
->lock
);
347 while (!test
->quit
) {
348 virMutexUnlock(&test
->lock
);
350 if (virEventRunDefaultImpl() < 0) {
351 virMutexLock(&test
->lock
);
356 virMutexLock(&test
->lock
);
359 test
->running
= false;
361 virMutexUnlock(&test
->lock
);
367 qemuMonitorTestFreeTimer(int timer ATTRIBUTE_UNUSED
,
368 void *opaque ATTRIBUTE_UNUSED
)
370 /* nothing to be done here */
375 qemuMonitorTestFree(qemuMonitorTestPtr test
)
383 virMutexLock(&test
->lock
);
386 /* HACK: Add a dummy timeout to break event loop */
387 timer
= virEventAddTimeout(0, qemuMonitorTestFreeTimer
, NULL
, NULL
);
389 virMutexUnlock(&test
->lock
);
392 virNetSocketRemoveIOCallback(test
->client
);
393 virNetSocketClose(test
->client
);
394 virObjectUnref(test
->client
);
397 virObjectUnref(test
->server
);
399 virObjectUnlock(test
->mon
);
400 qemuMonitorClose(test
->mon
);
404 virObjectUnlock(test
->agent
);
405 qemuAgentClose(test
->agent
);
408 virObjectUnref(test
->vm
);
411 virThreadJoin(&test
->thread
);
414 virEventRemoveTimeout(timer
);
416 VIR_FREE(test
->incoming
);
417 VIR_FREE(test
->outgoing
);
419 for (i
= 0; i
< test
->nitems
; i
++)
420 qemuMonitorTestItemFree(test
->items
[i
]);
421 VIR_FREE(test
->items
);
423 if (test
->tmpdir
&& rmdir(test
->tmpdir
) < 0)
424 VIR_WARN("Failed to remove tempdir: %s", strerror(errno
));
426 VIR_FREE(test
->tmpdir
);
428 virMutexDestroy(&test
->lock
);
434 qemuMonitorTestAddHandler(qemuMonitorTestPtr test
,
435 qemuMonitorTestResponseCallback cb
,
437 virFreeCallback freecb
)
439 qemuMonitorTestItemPtr item
;
441 if (VIR_ALLOC(item
) < 0)
445 item
->freecb
= freecb
;
446 item
->opaque
= opaque
;
448 virMutexLock(&test
->lock
);
449 if (VIR_APPEND_ELEMENT(test
->items
, test
->nitems
, item
) < 0) {
450 virMutexUnlock(&test
->lock
);
453 virMutexUnlock(&test
->lock
);
465 qemuMonitorTestItemGetPrivateData(qemuMonitorTestItemPtr item
)
467 return item
? item
->opaque
: NULL
;
471 typedef struct _qemuMonitorTestCommandArgs qemuMonitorTestCommandArgs
;
472 typedef qemuMonitorTestCommandArgs
*qemuMonitorTestCommandArgsPtr
;
473 struct _qemuMonitorTestCommandArgs
{
479 struct qemuMonitorTestHandlerData
{
484 qemuMonitorTestCommandArgsPtr args
;
489 qemuMonitorTestHandlerDataFree(void *opaque
)
491 struct qemuMonitorTestHandlerData
*data
= opaque
;
497 for (i
= 0; i
< data
->nargs
; i
++) {
498 VIR_FREE(data
->args
[i
].argname
);
499 VIR_FREE(data
->args
[i
].argval
);
502 VIR_FREE(data
->command_name
);
503 VIR_FREE(data
->cmderr
);
504 VIR_FREE(data
->response
);
505 VIR_FREE(data
->args
);
506 VIR_FREE(data
->expectArgs
);
511 /* Returns -1 on error, 0 if validation was successful/not necessary, 1 if
512 * the validation has failed, and the reply was properly constructed */
514 qemuMonitorTestProcessCommandDefaultValidate(qemuMonitorTestPtr test
,
516 virJSONValuePtr args
)
518 VIR_AUTOCLEAN(virBuffer
) debug
= VIR_BUFFER_INITIALIZER
;
519 virJSONValuePtr schemaroot
;
520 VIR_AUTOPTR(virJSONValue
) emptyargs
= NULL
;
521 VIR_AUTOFREE(char *) schemapath
= NULL
;
523 if (!test
->qapischema
)
527 virReportError(VIR_ERR_INTERNAL_ERROR
, "%s",
528 "Command validation testing is not "
529 "implemented for the guest agent");
533 /* 'device_add' needs to be skipped as it does not have fully defined schema */
534 if (STREQ(cmdname
, "device_add"))
537 if (virAsprintf(&schemapath
, "%s/arg-type", cmdname
) < 0)
540 if (virQEMUQAPISchemaPathGet(schemapath
, test
->qapischema
, &schemaroot
) < 0 ||
542 if (qemuMonitorReportError(test
,
543 "command '%s' not found in QAPI schema",
550 if (!(emptyargs
= virJSONValueNewObject()))
556 if (testQEMUSchemaValidate(args
, schemaroot
, test
->qapischema
, &debug
) < 0) {
557 if (qemuMonitorReportError(test
,
558 "failed to validate arguments of '%s' "
559 "against QAPI schema: %s",
560 cmdname
, virBufferCurrentContent(&debug
)) == 0)
570 qemuMonitorTestProcessCommandDefault(qemuMonitorTestPtr test
,
571 qemuMonitorTestItemPtr item
,
574 struct qemuMonitorTestHandlerData
*data
= item
->opaque
;
575 VIR_AUTOPTR(virJSONValue
) val
= NULL
;
576 virJSONValuePtr cmdargs
= NULL
;
580 if (!(val
= virJSONValueFromString(cmdstr
)))
583 if (!(cmdname
= virJSONValueObjectGetString(val
, "execute")))
584 return qemuMonitorReportError(test
, "Missing command name in %s", cmdstr
);
586 cmdargs
= virJSONValueObjectGet(val
, "arguments");
587 if ((rc
= qemuMonitorTestProcessCommandDefaultValidate(test
, cmdname
, cmdargs
)) < 0)
592 if (data
->command_name
&& STRNEQ(data
->command_name
, cmdname
)) {
593 return qemuMonitorTestAddInvalidCommandResponse(test
, data
->command_name
,
596 return qemuMonitorTestAddResponse(test
, data
->response
);
602 qemuMonitorTestAddItem(qemuMonitorTestPtr test
,
603 const char *command_name
,
604 const char *response
)
606 struct qemuMonitorTestHandlerData
*data
;
608 if (VIR_ALLOC(data
) < 0)
611 if (VIR_STRDUP(data
->command_name
, command_name
) < 0 ||
612 VIR_STRDUP(data
->response
, response
) < 0) {
613 qemuMonitorTestHandlerDataFree(data
);
617 return qemuMonitorTestAddHandler(test
,
618 qemuMonitorTestProcessCommandDefault
,
619 data
, qemuMonitorTestHandlerDataFree
);
624 qemuMonitorTestProcessCommandVerbatim(qemuMonitorTestPtr test
,
625 qemuMonitorTestItemPtr item
,
628 struct qemuMonitorTestHandlerData
*data
= item
->opaque
;
629 VIR_AUTOFREE(char *) reformatted
= NULL
;
630 VIR_AUTOFREE(char *) errmsg
= NULL
;
631 VIR_AUTOPTR(virJSONValue
) json
= NULL
;
632 virJSONValuePtr cmdargs
;
637 /* JSON strings will be reformatted to simplify checking */
638 if (!(json
= virJSONValueFromString(cmdstr
)) ||
639 !(reformatted
= virJSONValueToString(json
, false)))
642 cmdstr
= reformatted
;
644 /* in this case we do a best-effort schema check if we can find the command */
645 if ((cmdname
= virJSONValueObjectGetString(json
, "execute"))) {
646 cmdargs
= virJSONValueObjectGet(json
, "arguments");
648 if ((rc
= qemuMonitorTestProcessCommandDefaultValidate(test
, cmdname
, cmdargs
)) < 0)
655 if (STREQ(data
->command_name
, cmdstr
)) {
656 ret
= qemuMonitorTestAddResponse(test
, data
->response
);
659 if (virAsprintf(&errmsg
, "%s: %s", data
->cmderr
, cmdstr
) < 0)
662 ret
= qemuMonitorTestAddErrorResponse(test
, errmsg
);
664 ret
= qemuMonitorTestAddInvalidCommandResponse(test
,
675 * qemuMonitorTestAddItemVerbatim:
676 * @test: monitor test object
677 * @command: full expected command syntax
678 * @cmderr: possible explanation of expected command (may be NULL)
679 * @response: full reply of @command
681 * Adds a test command for the simulated monitor. The full syntax is checked
682 * as specified in @command. For JSON monitor tests formatting/whitespace is
683 * ignored. If the command on the monitor is not as expected an error containing
684 * @cmderr is returned. Otherwise @response is put as-is on the monitor.
686 * Returns 0 when command was successfully added, -1 on error.
689 qemuMonitorTestAddItemVerbatim(qemuMonitorTestPtr test
,
692 const char *response
)
694 struct qemuMonitorTestHandlerData
*data
;
696 if (VIR_ALLOC(data
) < 0)
699 if (VIR_STRDUP(data
->response
, response
) < 0 ||
700 VIR_STRDUP(data
->cmderr
, cmderr
) < 0)
703 data
->command_name
= virJSONStringReformat(command
, false);
704 if (!data
->command_name
)
707 return qemuMonitorTestAddHandler(test
,
708 qemuMonitorTestProcessCommandVerbatim
,
709 data
, qemuMonitorTestHandlerDataFree
);
712 qemuMonitorTestHandlerDataFree(data
);
718 qemuMonitorTestProcessGuestAgentSync(qemuMonitorTestPtr test
,
719 qemuMonitorTestItemPtr item ATTRIBUTE_UNUSED
,
722 virJSONValuePtr val
= NULL
;
723 virJSONValuePtr args
;
724 unsigned long long id
;
729 if (!(val
= virJSONValueFromString(cmdstr
)))
732 if (!(cmdname
= virJSONValueObjectGetString(val
, "execute"))) {
733 ret
= qemuMonitorReportError(test
, "Missing guest-sync command name");
737 if (STRNEQ(cmdname
, "guest-sync")) {
738 ret
= qemuMonitorTestAddInvalidCommandResponse(test
, "guest-sync", cmdname
);
742 if (!(args
= virJSONValueObjectGet(val
, "arguments"))) {
743 ret
= qemuMonitorReportError(test
, "Missing arguments for guest-sync");
747 if (virJSONValueObjectGetNumberUlong(args
, "id", &id
)) {
748 ret
= qemuMonitorReportError(test
, "Missing id for guest sync");
752 if (virAsprintf(&retmsg
, "{\"return\":%llu}", id
) < 0)
756 ret
= qemuMonitorTestAddResponse(test
, retmsg
);
759 virJSONValueFree(val
);
766 qemuMonitorTestAddAgentSyncResponse(qemuMonitorTestPtr test
)
769 virReportError(VIR_ERR_INTERNAL_ERROR
, "%s",
770 "This test is not an agent test");
774 return qemuMonitorTestAddHandler(test
,
775 qemuMonitorTestProcessGuestAgentSync
,
781 qemuMonitorTestProcessCommandWithArgs(qemuMonitorTestPtr test
,
782 qemuMonitorTestItemPtr item
,
785 struct qemuMonitorTestHandlerData
*data
= item
->opaque
;
786 virJSONValuePtr val
= NULL
;
787 virJSONValuePtr args
;
788 virJSONValuePtr argobj
;
794 if (!(val
= virJSONValueFromString(cmdstr
)))
797 if (!(cmdname
= virJSONValueObjectGetString(val
, "execute"))) {
798 ret
= qemuMonitorReportError(test
, "Missing command name in %s", cmdstr
);
802 if (data
->command_name
&&
803 STRNEQ(data
->command_name
, cmdname
)) {
804 ret
= qemuMonitorTestAddInvalidCommandResponse(test
, data
->command_name
,
809 if (!(args
= virJSONValueObjectGet(val
, "arguments"))) {
810 ret
= qemuMonitorReportError(test
,
811 "Missing arguments section for command '%s'",
812 NULLSTR(data
->command_name
));
816 /* validate the args */
817 for (i
= 0; i
< data
->nargs
; i
++) {
818 qemuMonitorTestCommandArgsPtr arg
= &data
->args
[i
];
819 if (!(argobj
= virJSONValueObjectGet(args
, arg
->argname
))) {
820 ret
= qemuMonitorReportError(test
,
821 "Missing argument '%s' for command '%s'",
823 NULLSTR(data
->command_name
));
827 /* convert the argument to string */
828 if (!(argstr
= virJSONValueToString(argobj
, false)))
831 /* verify that the argument value is expected */
832 if (STRNEQ(argstr
, arg
->argval
)) {
833 ret
= qemuMonitorReportError(test
,
834 "Invalid value of argument '%s' "
836 "expected '%s' got '%s'",
838 NULLSTR(data
->command_name
),
839 arg
->argval
, argstr
);
846 /* arguments checked out, return the response */
847 ret
= qemuMonitorTestAddResponse(test
, data
->response
);
851 virJSONValueFree(val
);
857 /* this allows to add a responder that is able to check
858 * a (shallow) structure of arguments for a command */
860 qemuMonitorTestAddItemParams(qemuMonitorTestPtr test
,
862 const char *response
,
865 struct qemuMonitorTestHandlerData
*data
;
870 va_start(args
, response
);
872 if (VIR_ALLOC(data
) < 0)
875 if (VIR_STRDUP(data
->command_name
, cmdname
) < 0 ||
876 VIR_STRDUP(data
->response
, response
) < 0)
879 while ((argname
= va_arg(args
, char *))) {
881 if (!(argval
= va_arg(args
, char *))) {
882 virReportError(VIR_ERR_INTERNAL_ERROR
,
883 "Missing argument value for argument '%s'",
889 if (VIR_EXPAND_N(data
->args
, data
->nargs
, 1))
892 if (VIR_STRDUP(data
->args
[i
].argname
, argname
) < 0 ||
893 VIR_STRDUP(data
->args
[i
].argval
, argval
) < 0)
899 return qemuMonitorTestAddHandler(test
,
900 qemuMonitorTestProcessCommandWithArgs
,
901 data
, qemuMonitorTestHandlerDataFree
);
905 qemuMonitorTestHandlerDataFree(data
);
911 qemuMonitorTestProcessCommandWithArgStr(qemuMonitorTestPtr test
,
912 qemuMonitorTestItemPtr item
,
915 struct qemuMonitorTestHandlerData
*data
= item
->opaque
;
916 virJSONValuePtr val
= NULL
;
917 virJSONValuePtr args
;
922 if (!(val
= virJSONValueFromString(cmdstr
)))
925 if (!(cmdname
= virJSONValueObjectGetString(val
, "execute"))) {
926 ret
= qemuMonitorReportError(test
, "Missing command name in %s", cmdstr
);
930 if (STRNEQ(data
->command_name
, cmdname
)) {
931 ret
= qemuMonitorTestAddInvalidCommandResponse(test
, data
->command_name
,
936 if (!(args
= virJSONValueObjectGet(val
, "arguments"))) {
937 ret
= qemuMonitorReportError(test
,
938 "Missing arguments section for command '%s'",
943 /* convert the arguments to string */
944 if (!(argstr
= virJSONValueToString(args
, false)))
947 /* verify that the argument value is expected */
948 if (STRNEQ(argstr
, data
->expectArgs
)) {
949 ret
= qemuMonitorReportError(test
,
950 "%s: expected arguments: '%s', got: '%s'",
952 data
->expectArgs
, argstr
);
956 /* arguments checked out, return the response */
957 ret
= qemuMonitorTestAddResponse(test
, data
->response
);
961 virJSONValueFree(val
);
967 * qemuMonitorTestAddItemExpect:
969 * @test: test monitor object
970 * @cmdname: command name
971 * @cmdargs: expected arguments of the command
972 * @apostrophe: convert apostrophes (') in @cmdargs to quotes (")
973 * @response: simulated response of the command
975 * Simulates a qemu monitor command. Checks that the 'arguments' of the qmp
976 * command are expected. If @apostrophe is true apostrophes are converted to
977 * quotes for simplification of writing the strings into code.
980 qemuMonitorTestAddItemExpect(qemuMonitorTestPtr test
,
984 const char *response
)
986 struct qemuMonitorTestHandlerData
*data
;
988 if (VIR_ALLOC(data
) < 0)
991 if (VIR_STRDUP(data
->command_name
, cmdname
) < 0 ||
992 VIR_STRDUP(data
->response
, response
) < 0 ||
993 VIR_STRDUP(data
->expectArgs
, cmdargs
) < 0)
997 char *tmp
= data
->expectArgs
;
999 while (*tmp
!= '\0') {
1007 return qemuMonitorTestAddHandler(test
,
1008 qemuMonitorTestProcessCommandWithArgStr
,
1009 data
, qemuMonitorTestHandlerDataFree
);
1012 qemuMonitorTestHandlerDataFree(data
);
1018 qemuMonitorTestEOFNotify(qemuMonitorPtr mon ATTRIBUTE_UNUSED
,
1019 virDomainObjPtr vm ATTRIBUTE_UNUSED
,
1020 void *opaque ATTRIBUTE_UNUSED
)
1026 qemuMonitorTestErrorNotify(qemuMonitorPtr mon ATTRIBUTE_UNUSED
,
1027 virDomainObjPtr vm ATTRIBUTE_UNUSED
,
1028 void *opaque ATTRIBUTE_UNUSED
)
1033 static qemuMonitorCallbacks qemuMonitorTestCallbacks
= {
1034 .eofNotify
= qemuMonitorTestEOFNotify
,
1035 .errorNotify
= qemuMonitorTestErrorNotify
,
1036 .domainDeviceDeleted
= qemuProcessHandleDeviceDeleted
,
1041 qemuMonitorTestAgentNotify(qemuAgentPtr agent ATTRIBUTE_UNUSED
,
1042 virDomainObjPtr vm ATTRIBUTE_UNUSED
)
1047 static qemuAgentCallbacks qemuMonitorTestAgentCallbacks
= {
1048 .eofNotify
= qemuMonitorTestAgentNotify
,
1049 .errorNotify
= qemuMonitorTestAgentNotify
,
1053 static qemuMonitorTestPtr
1054 qemuMonitorCommonTestNew(virDomainXMLOptionPtr xmlopt
,
1056 virDomainChrSourceDefPtr src
)
1058 qemuMonitorTestPtr test
= NULL
;
1060 char *tmpdir_template
= NULL
;
1062 if (VIR_ALLOC(test
) < 0)
1065 if (virMutexInit(&test
->lock
) < 0) {
1066 virReportError(VIR_ERR_INTERNAL_ERROR
, "%s",
1067 "Cannot initialize mutex");
1072 if (VIR_STRDUP(tmpdir_template
, "/tmp/libvirt_XXXXXX") < 0)
1075 if (!(test
->tmpdir
= mkdtemp(tmpdir_template
))) {
1076 virReportSystemError(errno
, "%s",
1077 "Failed to create temporary directory");
1081 tmpdir_template
= NULL
;
1083 if (virAsprintf(&path
, "%s/qemumonitorjsontest.sock", test
->tmpdir
) < 0)
1087 test
->vm
= virObjectRef(vm
);
1089 test
->vm
= virDomainObjNew(xmlopt
);
1094 if (virNetSocketNewListenUNIX(path
, 0700, geteuid(), getegid(),
1098 memset(src
, 0, sizeof(*src
));
1099 src
->type
= VIR_DOMAIN_CHR_TYPE_UNIX
;
1100 src
->data
.nix
.path
= (char *)path
;
1101 src
->data
.nix
.listen
= false;
1104 if (virNetSocketListen(test
->server
, 1) < 0)
1112 VIR_FREE(tmpdir_template
);
1113 qemuMonitorTestFree(test
);
1121 qemuMonitorCommonTestInit(qemuMonitorTestPtr test
)
1123 int events
= VIR_EVENT_HANDLE_READABLE
;
1128 if (virNetSocketAccept(test
->server
, &test
->client
) < 0)
1134 if (test
->outgoingLength
> 0)
1135 events
= VIR_EVENT_HANDLE_WRITABLE
;
1137 if (virNetSocketAddIOCallback(test
->client
,
1144 virMutexLock(&test
->lock
);
1145 if (virThreadCreate(&test
->thread
,
1147 qemuMonitorTestWorker
,
1149 virMutexUnlock(&test
->lock
);
1152 test
->started
= test
->running
= true;
1153 virMutexUnlock(&test
->lock
);
1162 #define QEMU_JSON_GREETING "{\"QMP\":"\
1169 " \"package\": \"(qemu-kvm-1.0.1)"\
1171 " \"capabilities\": []"\
1174 /* We skip the normal handshake reply of "{\"execute\":\"qmp_capabilities\"}" */
1177 qemuMonitorTestNew(virDomainXMLOptionPtr xmlopt
,
1179 virQEMUDriverPtr driver
,
1180 const char *greeting
,
1181 virHashTablePtr schema
)
1183 qemuMonitorTestPtr test
= NULL
;
1184 virDomainChrSourceDef src
;
1186 memset(&src
, 0, sizeof(src
));
1188 if (!(test
= qemuMonitorCommonTestNew(xmlopt
, vm
, &src
)))
1191 test
->qapischema
= schema
;
1192 if (!(test
->mon
= qemuMonitorOpen(test
->vm
,
1196 &qemuMonitorTestCallbacks
,
1200 virObjectLock(test
->mon
);
1203 greeting
= QEMU_JSON_GREETING
;
1205 if (qemuMonitorTestAddResponse(test
, greeting
) < 0)
1208 if (qemuMonitorCommonTestInit(test
) < 0)
1211 virDomainChrSourceDefClear(&src
);
1216 virDomainChrSourceDefClear(&src
);
1217 qemuMonitorTestFree(test
);
1223 * qemuMonitorTestNewFromFile:
1224 * @fileName: File name to load monitor replies from
1225 * @xmlopt: XML parser configuration object
1226 * @simple: see below
1228 * Create a JSON test monitor simulator object and fill it with replies
1229 * specified in @fileName. The file contains JSON reply objects separated by
1230 * empty lines. If @simple is true a generic QMP greeting is automatically
1231 * added as the first reply, otherwise the first entry in the file is used.
1233 * Returns the monitor object on success; NULL on error.
1236 qemuMonitorTestNewFromFile(const char *fileName
,
1237 virDomainXMLOptionPtr xmlopt
,
1240 qemuMonitorTestPtr test
= NULL
;
1245 if (virTestLoadFile(fileName
, &json
) < 0)
1248 if (simple
&& !(test
= qemuMonitorTestNewSimple(xmlopt
)))
1251 /* Our JSON parser expects replies to be separated by a newline character.
1252 * Hence we must preprocess the file a bit. */
1253 tmp
= singleReply
= json
;
1254 while ((tmp
= strchr(tmp
, '\n'))) {
1255 /* It is safe to touch tmp[1] since all strings ends with '\0'. */
1258 if (*(tmp
+ 1) != '\n') {
1262 /* Cut off a single reply. */
1266 if (qemuMonitorTestAddItem(test
, NULL
, singleReply
) < 0)
1269 /* Create new mocked monitor with our greeting */
1270 if (!(test
= qemuMonitorTestNew(xmlopt
, NULL
, NULL
,
1271 singleReply
, NULL
)))
1276 /* Move the @tmp and @singleReply. */
1286 if (test
&& qemuMonitorTestAddItem(test
, NULL
, singleReply
) < 0)
1294 qemuMonitorTestFree(test
);
1301 qemuMonitorTestFullAddItem(qemuMonitorTestPtr test
,
1302 const char *filename
,
1303 const char *command
,
1304 const char *response
,
1310 if (virAsprintf(&cmderr
, "wrong expected command in %s:%zu: ",
1311 filename
, line
) < 0)
1314 ret
= qemuMonitorTestAddItemVerbatim(test
, command
, cmderr
, response
);
1322 * qemuMonitorTestNewFromFileFull:
1323 * @fileName: File name to load monitor replies from
1324 * @driver: qemu driver object
1325 * @vm: domain object (may be null if it's not needed by the test)
1326 * @qmpschema: QMP schema data hash table if QMP checking is required
1328 * Create a JSON test monitor simulator object and fill it with expected command
1329 * sequence and replies specified in @fileName.
1331 * The file contains a sequence of JSON commands and reply objects separated by
1332 * empty lines. A command is followed by a reply. The QMP greeting is added
1335 * Returns the monitor object on success; NULL on error.
1338 qemuMonitorTestNewFromFileFull(const char *fileName
,
1339 virQEMUDriverPtr driver
,
1341 virHashTablePtr qmpschema
)
1343 qemuMonitorTestPtr ret
= NULL
;
1344 char *jsonstr
= NULL
;
1348 char *command
= NULL
;
1349 char *response
= NULL
;
1350 size_t commandln
= 0;
1352 if (virTestLoadFile(fileName
, &jsonstr
) < 0)
1355 if (!(ret
= qemuMonitorTestNew(driver
->xmlopt
, vm
, driver
, NULL
,
1361 while ((tmp
= strchr(tmp
, '\n'))) {
1368 /* concatenate block which was broken up for readability */
1369 if (*(tmp
+ 1) != '\n') {
1375 /* Cut off a single reply. */
1379 if (qemuMonitorTestFullAddItem(ret
, fileName
, command
,
1380 response
, commandln
) < 0)
1386 /* Move the @tmp and @singleReply. */
1399 virReportError(VIR_ERR_INTERNAL_ERROR
, "missing response for command "
1400 "on line '%zu' in '%s'", commandln
, fileName
);
1404 if (qemuMonitorTestFullAddItem(ret
, fileName
, command
,
1405 response
, commandln
) < 0)
1414 qemuMonitorTestFree(ret
);
1421 qemuMonitorTestNewAgent(virDomainXMLOptionPtr xmlopt
)
1423 qemuMonitorTestPtr test
= NULL
;
1424 virDomainChrSourceDef src
;
1426 memset(&src
, 0, sizeof(src
));
1428 if (!(test
= qemuMonitorCommonTestNew(xmlopt
, NULL
, &src
)))
1431 if (!(test
->agent
= qemuAgentOpen(test
->vm
,
1433 &qemuMonitorTestAgentCallbacks
)))
1436 virObjectLock(test
->agent
);
1438 if (qemuMonitorCommonTestInit(test
) < 0)
1441 virDomainChrSourceDefClear(&src
);
1446 virDomainChrSourceDefClear(&src
);
1447 qemuMonitorTestFree(test
);
1453 qemuMonitorTestGetMonitor(qemuMonitorTestPtr test
)
1460 qemuMonitorTestGetAgent(qemuMonitorTestPtr test
)
1467 qemuMonitorTestGetDomainObj(qemuMonitorTestPtr test
)