backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / qemumonitorjsontest.c
blob522ff5a3d55bd81f8e96c311dd022be7e6b9dfa0
1 /*
2 * Copyright (C) 2011-2014 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/>.
20 #include <config.h>
22 #include "testutils.h"
23 #include "testutilsqemu.h"
24 #include "testutilsqemuschema.h"
25 #include "qemumonitortestutils.h"
26 #include "qemu/qemu_domain.h"
27 #include "qemu/qemu_block.h"
28 #include "qemu/qemu_monitor_json.h"
29 #include "qemu/qemu_qapi.h"
30 #include "virthread.h"
31 #include "virerror.h"
32 #include "virstring.h"
33 #include "cpu/cpu.h"
34 #include "qemu/qemu_monitor.h"
35 #include "qemu/qemu_migration_params.h"
36 #define LIBVIRT_QEMU_MIGRATION_PARAMSPRIV_H_ALLOW
37 #include "qemu/qemu_migration_paramspriv.h"
39 #define VIR_FROM_THIS VIR_FROM_NONE
41 typedef struct _testQemuMonitorJSONSimpleFuncData testQemuMonitorJSONSimpleFuncData;
42 typedef testQemuMonitorJSONSimpleFuncData *testQemuMonitorJSONSimpleFuncDataPtr;
43 struct _testQemuMonitorJSONSimpleFuncData {
44 const char *cmd;
45 int (* func) (qemuMonitorPtr mon);
46 virDomainXMLOptionPtr xmlopt;
47 const char *reply;
48 virHashTablePtr schema;
51 typedef struct _testGenericData testGenericData;
52 struct _testGenericData {
53 virDomainXMLOptionPtr xmlopt;
54 virHashTablePtr schema;
57 const char *queryBlockReply =
58 "{"
59 " \"return\": ["
60 " {"
61 " \"io-status\": \"ok\","
62 " \"device\": \"drive-virtio-disk0\","
63 " \"locked\": false,"
64 " \"removable\": false,"
65 " \"inserted\": {"
66 " \"iops_rd\": 5,"
67 " \"iops_wr\": 6,"
68 " \"ro\": false,"
69 " \"backing_file_depth\": 0,"
70 " \"drv\": \"qcow2\","
71 " \"iops\": 4,"
72 " \"bps_wr\": 3,"
73 " \"encrypted\": false,"
74 " \"bps\": 1,"
75 " \"bps_rd\": 2,"
76 " \"bps_max\": 7,"
77 " \"iops_max\": 10,"
78 " \"bps_rd_max\": 8,"
79 " \"bps_wr_max\": 9,"
80 " \"iops_rd_max\": 11,"
81 " \"iops_wr_max\": 12,"
82 " \"iops_size\": 13,"
83 " \"group\": \"group14\","
84 " \"bps_max_length\": 15,"
85 " \"bps_rd_max_length\": 16,"
86 " \"bps_wr_max_length\": 17,"
87 " \"iops_max_length\": 18,"
88 " \"iops_rd_max_length\": 19,"
89 " \"iops_wr_max_length\": 20,"
90 " \"file\": \"/home/zippy/work/tmp/gentoo.qcow2\","
91 " \"encryption_key_missing\": false"
92 " },"
93 " \"type\": \"unknown\""
94 " },"
95 " {"
96 " \"io-status\": \"ok\","
97 " \"device\": \"drive-virtio-disk1\","
98 " \"locked\": false,"
99 " \"removable\": false,"
100 " \"inserted\": {"
101 " \"iops_rd\": 0,"
102 " \"iops_wr\": 0,"
103 " \"ro\": false,"
104 " \"backing_file_depth\": 0,"
105 " \"drv\": \"raw\","
106 " \"iops\": 0,"
107 " \"bps_wr\": 0,"
108 " \"encrypted\": false,"
109 " \"bps\": 0,"
110 " \"bps_rd\": 0,"
111 " \"file\": \"/home/zippy/test.bin\","
112 " \"encryption_key_missing\": false"
113 " },"
114 " \"type\": \"unknown\""
115 " },"
116 " {"
117 " \"io-status\": \"ok\","
118 " \"device\": \"drive-ide0-1-0\","
119 " \"locked\": true,"
120 " \"removable\": true,"
121 " \"inserted\": {"
122 " \"iops_rd\": 0,"
123 " \"iops_wr\": 0,"
124 " \"ro\": true,"
125 " \"backing_file_depth\": 0,"
126 " \"drv\": \"raw\","
127 " \"iops\": 0,"
128 " \"bps_wr\": 0,"
129 " \"encrypted\": false,"
130 " \"bps\": 0,"
131 " \"bps_rd\": 0,"
132 " \"file\": \"/home/zippy/tmp/install-amd64-minimal-20121210.iso\","
133 " \"encryption_key_missing\": false"
134 " },"
135 " \"tray_open\": false,"
136 " \"type\": \"unknown\""
137 " },"
138 " {"
139 " \"io-status\": \"ok\","
140 " \"device\": \"drive-ide0-1-1\","
141 " \"locked\": false,"
142 " \"removable\": true,"
143 " \"tray_open\": false,"
144 " \"type\": \"unknown\""
145 " }"
146 " ],"
147 " \"id\": \"libvirt-10\""
148 "}";
150 static int
151 testQemuMonitorJSONGetStatus(const void *opaque)
153 const testGenericData *data = opaque;
154 virDomainXMLOptionPtr xmlopt = data->xmlopt;
155 bool running = false;
156 virDomainPausedReason reason = 0;
157 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
159 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
160 return -1;
162 if (qemuMonitorTestAddItem(test, "query-status",
163 "{ "
164 " \"return\": { "
165 " \"status\": \"running\", "
166 " \"singlestep\": false, "
167 " \"running\": true "
168 " } "
169 "}") < 0)
170 return -1;
171 if (qemuMonitorTestAddItem(test, "query-status",
172 "{ "
173 " \"return\": { "
174 " \"singlestep\": false, "
175 " \"running\": false "
176 " } "
177 "}") < 0)
178 return -1;
179 if (qemuMonitorTestAddItem(test, "query-status",
180 "{ "
181 " \"return\": { "
182 " \"status\": \"inmigrate\", "
183 " \"singlestep\": false, "
184 " \"running\": false "
185 " } "
186 "}") < 0)
187 return -1;
189 if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
190 &running, &reason) < 0)
191 return -1;
193 if (!running) {
194 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
195 "Running was not true");
196 return -1;
199 if (reason != VIR_DOMAIN_PAUSED_UNKNOWN) {
200 virReportError(VIR_ERR_INTERNAL_ERROR,
201 "Reason was unexpectedly set to %d", reason);
202 return -1;
205 if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
206 &running, &reason) < 0)
207 return -1;
209 if (running) {
210 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
211 "Running was not false");
212 return -1;
215 if (reason != VIR_DOMAIN_PAUSED_UNKNOWN) {
216 virReportError(VIR_ERR_INTERNAL_ERROR,
217 "Reason was unexpectedly set to %d", reason);
218 return -1;
221 if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
222 &running, &reason) < 0)
223 return -1;
225 if (running) {
226 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
227 "Running was not false");
228 return -1;
231 if (reason != VIR_DOMAIN_PAUSED_MIGRATION) {
232 virReportError(VIR_ERR_INTERNAL_ERROR,
233 "Reason was unexpectedly set to %d", reason);
234 return -1;
237 return 0;
240 static int
241 testQemuMonitorJSONGetVersion(const void *opaque)
243 const testGenericData *data = opaque;
244 virDomainXMLOptionPtr xmlopt = data->xmlopt;
245 int ret = -1;
246 int major;
247 int minor;
248 int micro;
249 char *package = NULL;
250 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
252 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
253 return -1;
255 if (qemuMonitorTestAddItem(test, "query-version",
256 "{ "
257 " \"return\":{ "
258 " \"qemu\":{ "
259 " \"major\":1, "
260 " \"minor\":2, "
261 " \"micro\":3 "
262 " },"
263 " \"package\":\"\""
264 " }"
265 "}") < 0)
266 goto cleanup;
268 if (qemuMonitorTestAddItem(test, "query-version",
269 "{ "
270 " \"return\":{ "
271 " \"qemu\":{ "
272 " \"major\":0, "
273 " \"minor\":11, "
274 " \"micro\":6 "
275 " },"
276 " \"package\":\"2.283.el6\""
277 " }"
278 "}") < 0)
279 goto cleanup;
281 if (qemuMonitorGetVersion(qemuMonitorTestGetMonitor(test),
282 &major, &minor, &micro,
283 &package) < 0)
284 goto cleanup;
286 if (major != 1) {
287 virReportError(VIR_ERR_INTERNAL_ERROR,
288 "Major %d was not 1", major);
289 goto cleanup;
291 if (minor != 2) {
292 virReportError(VIR_ERR_INTERNAL_ERROR,
293 "Minor %d was not 2", major);
294 goto cleanup;
296 if (micro != 3) {
297 virReportError(VIR_ERR_INTERNAL_ERROR,
298 "Micro %d was not 3", major);
299 goto cleanup;
302 if (STRNEQ(package, "")) {
303 virReportError(VIR_ERR_INTERNAL_ERROR,
304 "Package %s was not ''", package);
305 goto cleanup;
307 VIR_FREE(package);
309 if (qemuMonitorGetVersion(qemuMonitorTestGetMonitor(test),
310 &major, &minor, &micro,
311 &package) < 0)
312 goto cleanup;
314 if (major != 0) {
315 virReportError(VIR_ERR_INTERNAL_ERROR,
316 "Major %d was not 0", major);
317 goto cleanup;
319 if (minor != 11) {
320 virReportError(VIR_ERR_INTERNAL_ERROR,
321 "Minor %d was not 11", major);
322 goto cleanup;
324 if (micro != 6) {
325 virReportError(VIR_ERR_INTERNAL_ERROR,
326 "Micro %d was not 6", major);
327 goto cleanup;
330 if (STRNEQ(package, "2.283.el6")) {
331 virReportError(VIR_ERR_INTERNAL_ERROR,
332 "Package %s was not '2.283.el6'", package);
333 goto cleanup;
336 ret = 0;
338 cleanup:
339 VIR_FREE(package);
340 return ret;
343 static int
344 testQemuMonitorJSONGetMachines(const void *opaque)
346 const testGenericData *data = opaque;
347 virDomainXMLOptionPtr xmlopt = data->xmlopt;
348 int ret = -1;
349 qemuMonitorMachineInfoPtr *info;
350 int ninfo = 0;
351 const char *null = NULL;
352 size_t i;
354 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
356 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
357 return -1;
359 if (qemuMonitorTestAddItem(test, "query-machines",
360 "{ "
361 " \"return\": [ "
362 " { "
363 " \"name\": \"pc-1.0\" "
364 " }, "
365 " { "
366 " \"name\": \"pc-1.1\" "
367 " }, "
368 " { "
369 " \"name\": \"pc-1.2\", "
370 " \"is-default\": true, "
371 " \"alias\": \"pc\" "
372 " } "
373 " ]"
374 "}") < 0)
375 goto cleanup;
377 if ((ninfo = qemuMonitorGetMachines(qemuMonitorTestGetMonitor(test),
378 &info)) < 0)
379 goto cleanup;
381 if (ninfo != 3) {
382 virReportError(VIR_ERR_INTERNAL_ERROR,
383 "ninfo %d is not 3", ninfo);
384 goto cleanup;
387 #define CHECK(i, wantname, wantisDefault, wantalias) \
388 do { \
389 if (STRNEQ(info[i]->name, (wantname))) { \
390 virReportError(VIR_ERR_INTERNAL_ERROR, \
391 "name %s is not %s", \
392 info[i]->name, (wantname)); \
393 goto cleanup; \
395 if (info[i]->isDefault != (wantisDefault)) { \
396 virReportError(VIR_ERR_INTERNAL_ERROR, \
397 "isDefault %d is not %d", \
398 info[i]->isDefault, (wantisDefault)); \
399 goto cleanup; \
401 if (STRNEQ_NULLABLE(info[i]->alias, (wantalias))) { \
402 virReportError(VIR_ERR_INTERNAL_ERROR, \
403 "alias %s is not %s", \
404 info[i]->alias, NULLSTR(wantalias)); \
405 goto cleanup; \
407 } while (0)
409 CHECK(0, "pc-1.0", false, null);
410 CHECK(1, "pc-1.1", false, null);
411 CHECK(2, "pc-1.2", true, "pc");
413 #undef CHECK
415 ret = 0;
417 cleanup:
418 for (i = 0; i < ninfo; i++)
419 qemuMonitorMachineInfoFree(info[i]);
420 VIR_FREE(info);
422 return ret;
426 static int
427 testQemuMonitorJSONGetCPUDefinitions(const void *opaque)
429 const testGenericData *data = opaque;
430 virDomainXMLOptionPtr xmlopt = data->xmlopt;
431 int ret = -1;
432 qemuMonitorCPUDefInfoPtr *cpus = NULL;
433 int ncpus = 0;
434 size_t i;
435 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
437 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
438 return -1;
440 if (qemuMonitorTestAddItem(test, "query-cpu-definitions",
441 "{ "
442 " \"return\": [ "
443 " { "
444 " \"name\": \"qemu64\" "
445 " }, "
446 " { "
447 " \"name\": \"Opteron_G4\", "
448 " \"unavailable-features\": [\"vme\"]"
449 " }, "
450 " { "
451 " \"name\": \"Westmere\", "
452 " \"unavailable-features\": []"
453 " } "
454 " ]"
455 "}") < 0)
456 goto cleanup;
458 if ((ncpus = qemuMonitorGetCPUDefinitions(qemuMonitorTestGetMonitor(test),
459 &cpus)) < 0)
460 goto cleanup;
462 if (ncpus != 3) {
463 virReportError(VIR_ERR_INTERNAL_ERROR,
464 "ncpus %d is not 3", ncpus);
465 goto cleanup;
468 #define CHECK_FULL(i, wantname, Usable) \
469 do { \
470 if (STRNEQ(cpus[i]->name, (wantname))) { \
471 virReportError(VIR_ERR_INTERNAL_ERROR, \
472 "name %s is not %s", \
473 cpus[i]->name, (wantname)); \
474 goto cleanup; \
476 if (cpus[i]->usable != (Usable)) { \
477 virReportError(VIR_ERR_INTERNAL_ERROR, \
478 "%s: expecting usable flag %d, got %d", \
479 cpus[i]->name, Usable, cpus[i]->usable); \
480 goto cleanup; \
482 } while (0)
484 #define CHECK(i, wantname) \
485 CHECK_FULL(i, wantname, VIR_TRISTATE_BOOL_ABSENT)
487 #define CHECK_USABLE(i, wantname, usable) \
488 CHECK_FULL(i, wantname, \
489 usable ? VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO)
491 CHECK(0, "qemu64");
492 CHECK_USABLE(1, "Opteron_G4", false);
493 CHECK_USABLE(2, "Westmere", true);
495 #undef CHECK
496 #undef CHECK_USABLE
497 #undef CHECK_FULL
499 ret = 0;
501 cleanup:
502 for (i = 0; i < ncpus; i++)
503 qemuMonitorCPUDefInfoFree(cpus[i]);
504 VIR_FREE(cpus);
505 return ret;
509 static int
510 testQemuMonitorJSONGetCommands(const void *opaque)
512 const testGenericData *data = opaque;
513 virDomainXMLOptionPtr xmlopt = data->xmlopt;
514 int ret = -1;
515 char **commands = NULL;
516 int ncommands = 0;
517 size_t i;
518 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
520 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
521 return -1;
523 if (qemuMonitorTestAddItem(test, "query-commands",
524 "{ "
525 " \"return\": [ "
526 " { "
527 " \"name\": \"system_wakeup\" "
528 " }, "
529 " { "
530 " \"name\": \"cont\" "
531 " }, "
532 " { "
533 " \"name\": \"quit\" "
534 " } "
535 " ]"
536 "}") < 0)
537 goto cleanup;
539 if ((ncommands = qemuMonitorGetCommands(qemuMonitorTestGetMonitor(test),
540 &commands)) < 0)
541 goto cleanup;
543 if (ncommands != 3) {
544 virReportError(VIR_ERR_INTERNAL_ERROR,
545 "ncommands %d is not 3", ncommands);
546 goto cleanup;
549 #define CHECK(i, wantname) \
550 do { \
551 if (STRNEQ(commands[i], (wantname))) { \
552 virReportError(VIR_ERR_INTERNAL_ERROR, \
553 "name %s is not %s", \
554 commands[i], (wantname)); \
555 goto cleanup; \
557 } while (0)
559 CHECK(0, "system_wakeup");
560 CHECK(1, "cont");
561 CHECK(2, "quit");
563 #undef CHECK
564 ret = 0;
566 cleanup:
567 for (i = 0; i < ncommands; i++)
568 VIR_FREE(commands[i]);
569 VIR_FREE(commands);
570 return ret;
574 static int
575 testQemuMonitorJSONGetTPMModels(const void *opaque)
577 const testGenericData *data = opaque;
578 virDomainXMLOptionPtr xmlopt = data->xmlopt;
579 int ret = -1;
580 char **tpmmodels = NULL;
581 int ntpmmodels = 0;
582 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
584 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
585 return -1;
587 if (qemuMonitorTestAddItem(test, "query-tpm-models",
588 "{ "
589 " \"return\": [ "
590 " \"passthrough\""
591 " ]"
592 "}") < 0)
593 goto cleanup;
595 if ((ntpmmodels = qemuMonitorGetTPMModels(qemuMonitorTestGetMonitor(test),
596 &tpmmodels)) < 0)
597 goto cleanup;
599 if (ntpmmodels != 1) {
600 virReportError(VIR_ERR_INTERNAL_ERROR,
601 "ntpmmodels %d is not 1", ntpmmodels);
602 goto cleanup;
605 #define CHECK(i, wantname) \
606 do { \
607 if (STRNEQ(tpmmodels[i], (wantname))) { \
608 virReportError(VIR_ERR_INTERNAL_ERROR, \
609 "name %s is not %s", \
610 tpmmodels[i], (wantname)); \
611 goto cleanup; \
613 } while (0)
615 CHECK(0, "passthrough");
617 #undef CHECK
619 ret = 0;
621 cleanup:
622 virStringListFree(tpmmodels);
623 return ret;
627 static int
628 testQemuMonitorJSONGetCommandLineOptionParameters(const void *opaque)
630 const testGenericData *data = opaque;
631 virDomainXMLOptionPtr xmlopt = data->xmlopt;
632 int ret = -1;
633 char **params = NULL;
634 int nparams = 0;
635 bool found = false;
636 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
638 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
639 return -1;
641 if (qemuMonitorTestAddItem(test, "query-command-line-options",
642 "{ "
643 " \"return\": [ "
644 " {\"parameters\": [], \"option\": \"acpi\" },"
645 " {\"parameters\": ["
646 " {\"name\": \"romfile\", "
647 " \"type\": \"string\"}, "
648 " {\"name\": \"bootindex\", "
649 " \"type\": \"number\"}], "
650 " \"option\": \"option-rom\"}"
651 " ]"
652 "}") < 0)
653 goto cleanup;
655 /* present with params */
656 if ((nparams = qemuMonitorGetCommandLineOptionParameters(qemuMonitorTestGetMonitor(test),
657 "option-rom",
658 &params,
659 NULL)) < 0)
660 goto cleanup;
662 if (nparams != 2) {
663 virReportError(VIR_ERR_INTERNAL_ERROR,
664 "nparams was %d, expected 2", nparams);
665 goto cleanup;
668 #define CHECK(i, wantname) \
669 do { \
670 if (STRNEQ(params[i], (wantname))) { \
671 virReportError(VIR_ERR_INTERNAL_ERROR, \
672 "name was %s, expected %s", \
673 params[i], (wantname)); \
674 goto cleanup; \
676 } while (0)
678 CHECK(0, "romfile");
679 CHECK(1, "bootindex");
681 #undef CHECK
683 virStringListFree(params);
684 params = NULL;
686 /* present but empty */
687 if ((nparams = qemuMonitorGetCommandLineOptionParameters(qemuMonitorTestGetMonitor(test),
688 "acpi",
689 &params,
690 &found)) < 0)
691 goto cleanup;
693 if (nparams != 0) {
694 virReportError(VIR_ERR_INTERNAL_ERROR,
695 "nparams was %d, expected 0", nparams);
696 goto cleanup;
698 if (!found) {
699 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
700 "found was false, expected true");
701 goto cleanup;
703 if (params && params[0]) {
704 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
705 "unexpected array contents");
706 goto cleanup;
709 virStringListFree(params);
710 params = NULL;
712 /* no such option */
713 if ((nparams = qemuMonitorGetCommandLineOptionParameters(qemuMonitorTestGetMonitor(test),
714 "foobar",
715 &params,
716 &found)) < 0)
717 goto cleanup;
719 if (nparams != 0) {
720 virReportError(VIR_ERR_INTERNAL_ERROR,
721 "nparams was %d, expected 0", nparams);
722 goto cleanup;
724 if (found) {
725 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
726 "found was true, expected false");
727 goto cleanup;
729 if (params && params[0]) {
730 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
731 "unexpected array contents");
732 goto cleanup;
735 ret = 0;
737 cleanup:
738 virStringListFree(params);
739 return ret;
743 struct qemuMonitorJSONTestAttachChardevData {
744 qemuMonitorTestPtr test;
745 virDomainChrSourceDefPtr chr;
746 const char *expectPty;
747 bool fail;
750 static int
751 testQemuMonitorJSONAttachChardev(const void *opaque)
753 const struct qemuMonitorJSONTestAttachChardevData *data = opaque;
754 int rc;
756 if ((rc = qemuMonitorAttachCharDev(qemuMonitorTestGetMonitor(data->test),
757 "alias", data->chr)) < 0)
758 goto cleanup;
760 if (data->chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
761 if (STRNEQ_NULLABLE(data->expectPty, data->chr->data.file.path)) {
762 virReportError(VIR_ERR_INTERNAL_ERROR,
763 "expected PTY path: %s got: %s",
764 NULLSTR(data->expectPty),
765 NULLSTR(data->chr->data.file.path));
766 rc = -1;
769 VIR_FREE(data->chr->data.file.path);
772 cleanup:
773 if ((rc != 0) != data->fail)
774 return -1;
775 else
776 return 0;
780 static int
781 qemuMonitorJSONTestAttachOneChardev(virDomainXMLOptionPtr xmlopt,
782 virHashTablePtr schema,
783 const char *label,
784 virDomainChrSourceDefPtr chr,
785 const char *expectargs,
786 const char *reply,
787 const char *expectPty,
788 bool fail)
791 struct qemuMonitorJSONTestAttachChardevData data = {0};
792 char *jsonreply = NULL;
793 char *fulllabel = NULL;
794 int ret = -1;
796 if (!reply)
797 reply = "";
799 if (virAsprintf(&jsonreply, "{\"return\": {%s}}", reply) < 0)
800 goto cleanup;
802 if (virAsprintf(&fulllabel, "qemuMonitorJSONTestAttachChardev(%s)", label) < 0)
803 goto cleanup;
805 data.chr = chr;
806 data.fail = fail;
807 data.expectPty = expectPty;
808 if (!(data.test = qemuMonitorTestNewSchema(xmlopt, schema)))
809 goto cleanup;
811 if (qemuMonitorTestAddItemExpect(data.test, "chardev-add",
812 expectargs, true, jsonreply) < 0)
813 goto cleanup;
815 if (virTestRun(fulllabel, &testQemuMonitorJSONAttachChardev, &data) < 0)
816 goto cleanup;
818 ret = 0;
820 cleanup:
821 qemuMonitorTestFree(data.test);
822 VIR_FREE(jsonreply);
823 VIR_FREE(fulllabel);
824 return ret;
827 static int
828 qemuMonitorJSONTestAttachChardev(virDomainXMLOptionPtr xmlopt,
829 virHashTablePtr schema)
831 virDomainChrSourceDef chr;
832 int ret = 0;
834 #define CHECK(label, fail, expectargs) \
835 if (qemuMonitorJSONTestAttachOneChardev(xmlopt, schema, label, &chr, \
836 expectargs, NULL, NULL, fail) < 0) \
837 ret = -1
839 chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_NULL };
840 CHECK("null", false,
841 "{'id':'alias','backend':{'type':'null','data':{}}}");
843 chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_VC };
844 CHECK("vc", false,
845 "{'id':'alias','backend':{'type':'null','data':{}}}");
847 chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_PTY };
848 if (qemuMonitorJSONTestAttachOneChardev(xmlopt, schema, "pty", &chr,
849 "{'id':'alias',"
850 "'backend':{'type':'pty',"
851 "'data':{}}}",
852 "\"pty\" : \"/dev/pts/0\"",
853 "/dev/pts/0", false) < 0)
854 ret = -1;
856 chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_PTY };
857 CHECK("pty missing path", true,
858 "{'id':'alias','backend':{'type':'pty','data':{}}}");
860 memset(&chr, 0, sizeof(chr));
861 chr.type = VIR_DOMAIN_CHR_TYPE_FILE;
862 chr.data.file.path = (char *) "/test/path";
863 CHECK("file", false,
864 "{'id':'alias','backend':{'type':'file','data':{'out':'/test/path'}}}");
866 memset(&chr, 0, sizeof(chr));
867 chr.type = VIR_DOMAIN_CHR_TYPE_DEV;
868 chr.data.file.path = (char *) "/test/path";
869 CHECK("device", false,
870 "{'id':'alias','backend':{'type':'serial','data':{'device':'/test/path'}}}");
872 memset(&chr, 0, sizeof(chr));
873 chr.type = VIR_DOMAIN_CHR_TYPE_TCP;
874 chr.data.tcp.host = (char *) "example.com";
875 chr.data.tcp.service = (char *) "1234";
876 CHECK("tcp", false,
877 "{'id':'alias',"
878 "'backend':{'type':'socket',"
879 "'data':{'addr':{'type':'inet',"
880 "'data':{'host':'example.com',"
881 "'port':'1234'}},"
882 "'telnet':false,"
883 "'server':false}}}");
885 memset(&chr, 0, sizeof(chr));
886 chr.type = VIR_DOMAIN_CHR_TYPE_UDP;
887 chr.data.udp.connectHost = (char *) "example.com";
888 chr.data.udp.connectService = (char *) "1234";
889 CHECK("udp", false,
890 "{'id':'alias',"
891 "'backend':{'type':'udp',"
892 "'data':{'remote':{'type':'inet',"
893 "'data':{'host':'example.com',"
894 "'port':'1234'}}}}}");
896 chr.data.udp.bindHost = (char *) "localhost";
897 chr.data.udp.bindService = (char *) "4321";
898 CHECK("udp", false,
899 "{'id':'alias',"
900 "'backend':{'type':'udp',"
901 "'data':{'remote':{'type':'inet',"
902 "'data':{'host':'example.com',"
903 "'port':'1234'}},"
904 "'local':{'type':'inet',"
905 "'data':{'host':'localhost',"
906 "'port':'4321'}}}}}");
908 chr.data.udp.bindHost = NULL;
909 chr.data.udp.bindService = (char *) "4321";
910 CHECK("udp", false,
911 "{'id':'alias',"
912 "'backend':{'type':'udp',"
913 "'data':{'remote':{'type':'inet',"
914 "'data':{'host':'example.com',"
915 "'port':'1234'}},"
916 "'local':{'type':'inet',"
917 "'data':{'host':'',"
918 "'port':'4321'}}}}}");
919 memset(&chr, 0, sizeof(chr));
920 chr.type = VIR_DOMAIN_CHR_TYPE_UNIX;
921 chr.data.nix.path = (char *) "/path/to/socket";
922 CHECK("unix", false,
923 "{'id':'alias',"
924 "'backend':{'type':'socket',"
925 "'data':{'addr':{'type':'unix',"
926 "'data':{'path':'/path/to/socket'}},"
927 "'server':false}}}");
929 chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_SPICEVMC };
930 CHECK("spicevmc", false,
931 "{'id':'alias','backend':{'type':'spicevmc','"
932 "data':{'type':'vdagent'}}}");
934 chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_PIPE };
935 CHECK("pipe", true, "");
937 chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_STDIO };
938 CHECK("stdio", true, "");
939 #undef CHECK
941 return ret;
945 static int
946 testQemuMonitorJSONDetachChardev(const void *opaque)
948 const testGenericData *data = opaque;
949 virDomainXMLOptionPtr xmlopt = data->xmlopt;
950 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
952 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
953 return -1;
955 if (qemuMonitorTestAddItem(test, "chardev-remove", "{\"return\": {}}") < 0)
956 return -1;
958 if (qemuMonitorDetachCharDev(qemuMonitorTestGetMonitor(test),
959 "dummy_chrID") < 0)
960 return -1;
962 return 0;
966 * This test will request to return a list of paths for "/". It should be
967 * a simple list of 1 real element that being the "machine". The following
968 * is the execution and expected return:
970 * {"execute":"qom-list", "arguments": { "path": "/"}}"
971 * {"return": [{"name": "machine", "type": "child<container>"}, \
972 * {"name": "type", "type": "string"}]}
974 static int
975 testQemuMonitorJSONGetListPaths(const void *opaque)
977 const testGenericData *data = opaque;
978 virDomainXMLOptionPtr xmlopt = data->xmlopt;
979 int ret = -1;
980 qemuMonitorJSONListPathPtr *paths;
981 int npaths = 0;
982 size_t i;
983 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
985 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
986 return -1;
988 if (qemuMonitorTestAddItem(test, "qom-list",
989 "{ "
990 " \"return\": [ "
991 " {\"name\": \"machine\", "
992 " \"type\": \"child<container>\"}, "
993 " {\"name\": \"type\", "
994 " \"type\": \"string\"} "
995 " ]"
996 "}") < 0)
997 goto cleanup;
999 /* present with path */
1000 if ((npaths = qemuMonitorJSONGetObjectListPaths(
1001 qemuMonitorTestGetMonitor(test),
1002 "/",
1003 &paths)) < 0)
1004 goto cleanup;
1006 if (npaths != 2) {
1007 virReportError(VIR_ERR_INTERNAL_ERROR,
1008 "npaths was %d, expected 1", npaths);
1009 goto cleanup;
1012 #define CHECK(i, wantname, wanttype) \
1013 do { \
1014 if (STRNEQ(paths[i]->name, (wantname))) { \
1015 virReportError(VIR_ERR_INTERNAL_ERROR, \
1016 "name was %s, expected %s", \
1017 paths[i]->name, (wantname)); \
1018 goto cleanup; \
1020 if (STRNEQ_NULLABLE(paths[i]->type, (wanttype))) { \
1021 virReportError(VIR_ERR_INTERNAL_ERROR, \
1022 "type was %s, expected %s", \
1023 NULLSTR(paths[i]->type), (wanttype)); \
1024 goto cleanup; \
1026 } while (0)
1028 CHECK(0, "machine", "child<container>");
1030 #undef CHECK
1032 ret = 0;
1034 cleanup:
1035 for (i = 0; i < npaths; i++)
1036 qemuMonitorJSONListPathFree(paths[i]);
1037 VIR_FREE(paths);
1038 return ret;
1043 * This test will use a path to /machine/i440fx which should exist in order
1044 * to ensure that the qom-get property fetch works properly. The following
1045 * is the execution and expected return:
1048 * { "execute": "qom-get","arguments": \
1049 * { "path": "/machine/i440fx","property": "realized"}}
1050 * {"return": true}
1052 static int
1053 testQemuMonitorJSONGetObjectProperty(const void *opaque)
1055 const testGenericData *data = opaque;
1056 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1057 qemuMonitorJSONObjectProperty prop;
1058 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1060 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1061 return -1;
1063 if (qemuMonitorTestAddItem(test, "qom-get",
1064 "{ \"return\": true }") < 0)
1065 return -1;
1067 /* Present with path and property */
1068 memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty));
1069 prop.type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN;
1070 if (qemuMonitorJSONGetObjectProperty(qemuMonitorTestGetMonitor(test),
1071 "/machine/i440fx",
1072 "realized",
1073 &prop) < 0)
1074 return -1;
1076 if (!prop.val.b) {
1077 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1078 "expected true, but false returned");
1079 return -1;
1082 return 0;
1087 * This test will use a path to /machine/i440fx which should exist in order
1088 * to ensure that the qom-set property set works properly. The test will
1089 * set a true property to true just as a proof of concept. Setting it to
1090 * false is not a good idea...
1092 static int
1093 testQemuMonitorJSONSetObjectProperty(const void *opaque)
1095 const testGenericData *data = opaque;
1096 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1097 qemuMonitorJSONObjectProperty prop;
1098 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1100 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1101 return -1;
1103 if (qemuMonitorTestAddItem(test, "qom-set",
1104 "{ \"return\": {} }") < 0)
1105 return -1;
1106 if (qemuMonitorTestAddItem(test, "qom-get",
1107 "{ \"return\": true }") < 0)
1108 return -1;
1110 /* Let's attempt the setting */
1111 memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty));
1112 prop.type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN;
1113 prop.val.b = true;
1114 if (qemuMonitorJSONSetObjectProperty(qemuMonitorTestGetMonitor(test),
1115 "/machine/i440fx",
1116 "realized",
1117 &prop) < 0)
1118 return -1;
1120 /* To make sure it worked, fetch the property - if this succeeds then
1121 * we didn't hose things
1123 memset(&prop, 0, sizeof(qemuMonitorJSONObjectProperty));
1124 prop.type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN;
1125 if (qemuMonitorJSONGetObjectProperty(qemuMonitorTestGetMonitor(test),
1126 "/machine/i440fx",
1127 "realized",
1128 &prop) < 0)
1129 return -1;
1131 if (!prop.val.b) {
1132 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1133 "expected true, but false returned");
1134 return -1;
1137 return 0;
1141 static int
1142 testQemuMonitorJSONGetDeviceAliases(const void *opaque)
1144 const testGenericData *data = opaque;
1145 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1146 int ret = -1;
1147 char **aliases = NULL;
1148 const char **alias;
1149 const char *expected[] = {
1150 "virtio-disk25", "video0", "serial0", "ide0-0-0", "usb", NULL };
1151 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1153 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1154 return -1;
1156 if (qemuMonitorTestAddItem(test,
1157 "qom-list",
1158 "{\"return\": ["
1159 " {\"name\": \"virtio-disk25\","
1160 " \"type\": \"child<virtio-blk-pci>\"},"
1161 " {\"name\": \"video0\","
1162 " \"type\": \"child<VGA>\"},"
1163 " {\"name\": \"serial0\","
1164 " \"type\": \"child<isa-serial>\"},"
1165 " {\"name\": \"ide0-0-0\","
1166 " \"type\": \"child<ide-cd>\"},"
1167 " {\"name\": \"usb\","
1168 " \"type\": \"child<piix3-usb-uhci>\"},"
1169 " {\"name\": \"type\", \"type\": \"string\"}"
1170 "]}") < 0)
1171 goto cleanup;
1173 if (qemuMonitorJSONGetDeviceAliases(qemuMonitorTestGetMonitor(test),
1174 &aliases) < 0)
1175 goto cleanup;
1177 if (!aliases) {
1178 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", "no aliases returned");
1179 goto cleanup;
1182 ret = 0;
1183 for (alias = (const char **) aliases; *alias; alias++) {
1184 if (!virStringListHasString(expected, *alias)) {
1185 fprintf(stderr, "got unexpected device alias '%s'\n", *alias);
1186 ret = -1;
1189 for (alias = expected; *alias; alias++) {
1190 if (!virStringListHasString((const char **) aliases, *alias)) {
1191 fprintf(stderr, "missing expected alias '%s'\n", *alias);
1192 ret = -1;
1196 cleanup:
1197 virStringListFree(aliases);
1198 return ret;
1201 static int
1202 testQemuMonitorJSONCPU(const void *opaque)
1204 const testGenericData *data = opaque;
1205 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1206 bool running = false;
1207 virDomainPausedReason reason = 0;
1208 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1210 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1211 return -1;
1213 if (qemuMonitorTestAddItem(test, "stop", "{\"return\": {}}") < 0 ||
1214 qemuMonitorTestAddItem(test, "query-status",
1215 "{\"return\": {"
1216 " \"status\": \"paused\","
1217 " \"singlestep\": false,"
1218 " \"running\": false}}") < 0 ||
1219 qemuMonitorTestAddItem(test, "cont", "{\"return\": {}}") < 0 ||
1220 qemuMonitorTestAddItem(test, "query-status",
1221 "{\"return\": {"
1222 " \"status\": \"running\","
1223 " \"singlestep\": false,"
1224 " \"running\": true}}") < 0)
1225 return -1;
1227 if (qemuMonitorJSONStopCPUs(qemuMonitorTestGetMonitor(test)) < 0)
1228 return -1;
1230 if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
1231 &running, &reason) < 0)
1232 return -1;
1234 if (running) {
1235 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1236 "Running was not false");
1237 return -1;
1240 if (qemuMonitorJSONStartCPUs(qemuMonitorTestGetMonitor(test)) < 0)
1241 return -1;
1243 if (qemuMonitorGetStatus(qemuMonitorTestGetMonitor(test),
1244 &running, &reason) < 0)
1245 return -1;
1247 if (!running) {
1248 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1249 "Running was not true");
1250 return -1;
1253 return 0;
1256 static int
1257 testQemuMonitorJSONSimpleFunc(const void *opaque)
1259 testQemuMonitorJSONSimpleFuncDataPtr data =
1260 (testQemuMonitorJSONSimpleFuncDataPtr) opaque;
1261 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1262 const char *reply = data->reply;
1263 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1265 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1266 return -1;
1268 if (!reply)
1269 reply = "{\"return\":{}}";
1271 if (qemuMonitorTestAddItem(test, data->cmd, reply) < 0)
1272 return -1;
1274 if (data->func(qemuMonitorTestGetMonitor(test)) < 0)
1275 return -1;
1277 return 0;
1280 #define GEN_TEST_FUNC(funcName, ...) \
1281 static int \
1282 testQemuMonitorJSON ## funcName(const void *opaque) \
1284 const testQemuMonitorJSONSimpleFuncData *data = opaque; \
1285 virDomainXMLOptionPtr xmlopt = data->xmlopt; \
1286 const char *reply = data->reply; \
1287 VIR_AUTOPTR(qemuMonitorTest) test = NULL; \
1289 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema))) \
1290 return -1; \
1292 if (!reply) \
1293 reply = "{\"return\":{}}"; \
1295 if (qemuMonitorTestAddItem(test, data->cmd, reply) < 0) \
1296 return -1; \
1298 if (funcName(qemuMonitorTestGetMonitor(test), __VA_ARGS__) < 0) \
1299 return -1; \
1301 return 0; \
1304 GEN_TEST_FUNC(qemuMonitorJSONSetLink, "vnet0", VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN)
1305 GEN_TEST_FUNC(qemuMonitorJSONBlockResize, "vda", "asdf", 123456)
1306 GEN_TEST_FUNC(qemuMonitorJSONSetPassword, "spice", "secret_password", "disconnect")
1307 GEN_TEST_FUNC(qemuMonitorJSONExpirePassword, "spice", "123456")
1308 GEN_TEST_FUNC(qemuMonitorJSONSetBalloon, 1024)
1309 GEN_TEST_FUNC(qemuMonitorJSONSetCPU, 1, true)
1310 GEN_TEST_FUNC(qemuMonitorJSONEjectMedia, "hdc", true)
1311 GEN_TEST_FUNC(qemuMonitorJSONChangeMedia, "hdc", "/foo/bar", "formatstr")
1312 GEN_TEST_FUNC(qemuMonitorJSONSaveVirtualMemory, 0, 1024, "/foo/bar")
1313 GEN_TEST_FUNC(qemuMonitorJSONSavePhysicalMemory, 0, 1024, "/foo/bar")
1314 GEN_TEST_FUNC(qemuMonitorJSONSetMigrationSpeed, 1024)
1315 GEN_TEST_FUNC(qemuMonitorJSONSetMigrationDowntime, 1)
1316 GEN_TEST_FUNC(qemuMonitorJSONMigrate, QEMU_MONITOR_MIGRATE_BACKGROUND |
1317 QEMU_MONITOR_MIGRATE_NON_SHARED_DISK |
1318 QEMU_MONITOR_MIGRATE_NON_SHARED_INC, "tcp:localhost:12345")
1319 GEN_TEST_FUNC(qemuMonitorJSONDump, "dummy_protocol", "elf",
1320 true)
1321 GEN_TEST_FUNC(qemuMonitorJSONGraphicsRelocate, VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
1322 "localhost", 12345, 12346, "certsubjectval")
1323 GEN_TEST_FUNC(qemuMonitorJSONAddNetdev, "id=net0,type=test")
1324 GEN_TEST_FUNC(qemuMonitorJSONRemoveNetdev, "net0")
1325 GEN_TEST_FUNC(qemuMonitorJSONDelDevice, "ide0")
1326 GEN_TEST_FUNC(qemuMonitorJSONAddDevice, "some_dummy_devicestr")
1327 GEN_TEST_FUNC(qemuMonitorJSONDriveMirror, "vdb", "/foo/bar", "formatstr", 1024, 1234, 31234, true, true)
1328 GEN_TEST_FUNC(qemuMonitorJSONBlockdevMirror, "jobname", true, "vdb", "targetnode", 1024, 1234, 31234, true)
1329 GEN_TEST_FUNC(qemuMonitorJSONBlockStream, "vdb", "jobname", true, "/foo/bar1", "backingnode", "backingfilename", 1024)
1330 GEN_TEST_FUNC(qemuMonitorJSONBlockCommit, "vdb", "jobname", true, "/foo/bar1", "topnode", "/foo/bar2", "basenode", "backingfilename", 1024)
1331 GEN_TEST_FUNC(qemuMonitorJSONDrivePivot, "vdb")
1332 GEN_TEST_FUNC(qemuMonitorJSONScreendump, "devicename", 1, "/foo/bar")
1333 GEN_TEST_FUNC(qemuMonitorJSONOpenGraphics, "spice", "spicefd", false)
1334 GEN_TEST_FUNC(qemuMonitorJSONNBDServerAdd, "vda", "export", true, "bitmap")
1335 GEN_TEST_FUNC(qemuMonitorJSONDetachCharDev, "serial1")
1336 GEN_TEST_FUNC(qemuMonitorJSONBlockdevTrayOpen, "foodev", true)
1337 GEN_TEST_FUNC(qemuMonitorJSONBlockdevTrayClose, "foodev")
1338 GEN_TEST_FUNC(qemuMonitorJSONBlockdevMediumRemove, "foodev")
1339 GEN_TEST_FUNC(qemuMonitorJSONBlockdevMediumInsert, "foodev", "newnode")
1340 GEN_TEST_FUNC(qemuMonitorJSONAddBitmap, "node", "bitmap", true)
1341 GEN_TEST_FUNC(qemuMonitorJSONEnableBitmap, "node", "bitmap")
1342 GEN_TEST_FUNC(qemuMonitorJSONDeleteBitmap, "node", "bitmap")
1343 GEN_TEST_FUNC(qemuMonitorJSONJobDismiss, "jobname")
1344 GEN_TEST_FUNC(qemuMonitorJSONJobCancel, "jobname", false)
1345 GEN_TEST_FUNC(qemuMonitorJSONJobComplete, "jobname")
1347 static int
1348 testQemuMonitorJSONqemuMonitorJSONNBDServerStart(const void *opaque)
1350 const testGenericData *data = opaque;
1351 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1352 virStorageNetHostDef server_tcp = {
1353 .name = (char *)"localhost",
1354 .port = 12345,
1355 .transport = VIR_STORAGE_NET_HOST_TRANS_TCP,
1357 virStorageNetHostDef server_unix = {
1358 .socket = (char *)"/tmp/sock",
1359 .transport = VIR_STORAGE_NET_HOST_TRANS_UNIX,
1361 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1363 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1364 return -1;
1366 if (qemuMonitorTestAddItem(test, "nbd-server-start",
1367 "{\"return\":{}}") < 0)
1368 return -1;
1370 if (qemuMonitorTestAddItem(test, "nbd-server-start",
1371 "{\"return\":{}}") < 0)
1372 return -1;
1374 if (qemuMonitorJSONNBDServerStart(qemuMonitorTestGetMonitor(test),
1375 &server_tcp, "test-alias") < 0)
1376 return -1;
1378 if (qemuMonitorJSONNBDServerStart(qemuMonitorTestGetMonitor(test),
1379 &server_unix, "test-alias") < 0)
1380 return -1;
1382 return 0;
1385 static int
1386 testQemuMonitorJSONqemuMonitorJSONMergeBitmaps(const void *opaque)
1388 const testGenericData *data = opaque;
1389 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1390 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1391 VIR_AUTOPTR(virJSONValue) arr = NULL;
1393 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1394 return -1;
1396 if (!(arr = virJSONValueNewArray()))
1397 return -1;
1399 if (virJSONValueArrayAppendString(arr, "b1") < 0 ||
1400 virJSONValueArrayAppendString(arr, "b2") < 0)
1401 return -1;
1403 if (qemuMonitorTestAddItem(test, "block-dirty-bitmap-merge",
1404 "{\"return\":{}}") < 0)
1405 return -1;
1407 if (qemuMonitorJSONMergeBitmaps(qemuMonitorTestGetMonitor(test),
1408 "node", "dst", &arr) < 0)
1409 return -1;
1411 if (arr) {
1412 VIR_TEST_VERBOSE("arr should have been cleared");
1413 return -1;
1416 return 0;
1419 static bool
1420 testQemuMonitorJSONqemuMonitorJSONQueryCPUsEqual(struct qemuMonitorQueryCpusEntry *a,
1421 struct qemuMonitorQueryCpusEntry *b)
1423 if (a->tid != b->tid ||
1424 STRNEQ_NULLABLE(a->qom_path, b->qom_path))
1425 return false;
1427 return true;
1431 static int
1432 testQEMUMonitorJSONqemuMonitorJSONQueryCPUsHelper(qemuMonitorTestPtr test,
1433 struct qemuMonitorQueryCpusEntry *expect,
1434 bool fast,
1435 size_t num)
1437 struct qemuMonitorQueryCpusEntry *cpudata = NULL;
1438 size_t ncpudata = 0;
1439 size_t i;
1440 int ret = -1;
1442 if (qemuMonitorJSONQueryCPUs(qemuMonitorTestGetMonitor(test),
1443 &cpudata, &ncpudata, true, fast) < 0)
1444 goto cleanup;
1446 if (ncpudata != num) {
1447 virReportError(VIR_ERR_INTERNAL_ERROR,
1448 "Expecting ncpupids = %zu but got %zu", num, ncpudata);
1449 goto cleanup;
1452 for (i = 0; i < ncpudata; i++) {
1453 if (!testQemuMonitorJSONqemuMonitorJSONQueryCPUsEqual(cpudata + i,
1454 expect + i)) {
1455 virReportError(VIR_ERR_INTERNAL_ERROR,
1456 "vcpu entry %zu does not match expected data", i);
1457 goto cleanup;
1461 ret = 0;
1463 cleanup:
1464 qemuMonitorQueryCpusFree(cpudata, ncpudata);
1465 return ret;
1469 static int
1470 testQemuMonitorJSONqemuMonitorJSONQueryCPUs(const void *opaque)
1472 const testGenericData *data = opaque;
1473 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1474 struct qemuMonitorQueryCpusEntry expect_slow[] = {
1475 {0, 17622, (char *) "/machine/unattached/device[0]", true},
1476 {1, 17624, (char *) "/machine/unattached/device[1]", true},
1477 {2, 17626, (char *) "/machine/unattached/device[2]", true},
1478 {3, 17628, NULL, true},
1480 struct qemuMonitorQueryCpusEntry expect_fast[] = {
1481 {0, 17629, (char *) "/machine/unattached/device[0]", false},
1482 {1, 17630, (char *) "/machine/unattached/device[1]", false},
1484 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1486 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1487 return -1;
1489 if (qemuMonitorTestAddItem(test, "query-cpus",
1491 " \"return\": ["
1492 " {"
1493 " \"current\": true,"
1494 " \"CPU\": 0,"
1495 " \"qom_path\": \"/machine/unattached/device[0]\","
1496 " \"pc\": -2130530478,"
1497 " \"halted\": true,"
1498 " \"thread_id\": 17622"
1499 " },"
1500 " {"
1501 " \"current\": false,"
1502 " \"CPU\": 1,"
1503 " \"qom_path\": \"/machine/unattached/device[1]\","
1504 " \"pc\": -2130530478,"
1505 " \"halted\": true,"
1506 " \"thread_id\": 17624"
1507 " },"
1508 " {"
1509 " \"current\": false,"
1510 " \"CPU\": 2,"
1511 " \"qom_path\": \"/machine/unattached/device[2]\","
1512 " \"pc\": -2130530478,"
1513 " \"halted\": true,"
1514 " \"thread_id\": 17626"
1515 " },"
1516 " {"
1517 " \"current\": false,"
1518 " \"CPU\": 3,"
1519 " \"pc\": -2130530478,"
1520 " \"halted\": true,"
1521 " \"thread_id\": 17628"
1522 " }"
1523 " ],"
1524 " \"id\": \"libvirt-7\""
1525 "}") < 0)
1526 return -1;
1528 if (qemuMonitorTestAddItem(test, "query-cpus-fast",
1530 " \"return\": ["
1531 " {"
1532 " \"cpu-index\": 0,"
1533 " \"qom-path\": \"/machine/unattached/device[0]\","
1534 " \"thread-id\": 17629"
1535 " },"
1536 " {"
1537 " \"cpu-index\": 1,"
1538 " \"qom-path\": \"/machine/unattached/device[1]\","
1539 " \"thread-id\": 17630"
1540 " }"
1541 " ],"
1542 " \"id\": \"libvirt-8\""
1543 "}") < 0)
1544 return -1;
1546 /* query-cpus */
1547 if (testQEMUMonitorJSONqemuMonitorJSONQueryCPUsHelper(test, expect_slow,
1548 false, 4))
1549 return -1;
1551 /* query-cpus-fast */
1552 if (testQEMUMonitorJSONqemuMonitorJSONQueryCPUsHelper(test, expect_fast,
1553 true, 2))
1554 return -1;
1556 return 0;
1559 static int
1560 testQemuMonitorJSONqemuMonitorJSONGetBalloonInfo(const void *opaque)
1562 const testGenericData *data = opaque;
1563 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1564 unsigned long long currmem;
1565 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1567 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1568 return -1;
1570 if (qemuMonitorTestAddItem(test, "query-balloon",
1572 " \"return\": {"
1573 " \"actual\": 18446744073709551615"
1574 " },"
1575 " \"id\": \"libvirt-9\""
1576 "}") < 0)
1577 return -1;
1579 if (qemuMonitorJSONGetBalloonInfo(qemuMonitorTestGetMonitor(test), &currmem) < 0)
1580 return -1;
1582 if (currmem != (18446744073709551615ULL/1024)) {
1583 virReportError(VIR_ERR_INTERNAL_ERROR,
1584 "Unexpected currmem value: %llu", currmem);
1585 return -1;
1588 return 0;
1591 static int
1592 testQemuMonitorJSONqemuMonitorJSONGetVirtType(const void *opaque)
1594 const testGenericData *data = opaque;
1595 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1596 virDomainVirtType virtType;
1597 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1599 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1600 return -1;
1602 if (qemuMonitorTestAddItem(test, "query-kvm",
1604 " \"return\": {"
1605 " \"enabled\": true,"
1606 " \"present\": true"
1607 " },"
1608 " \"id\": \"libvirt-8\""
1609 "}") < 0 ||
1610 qemuMonitorTestAddItem(test, "query-kvm",
1612 " \"return\": {"
1613 " \"enabled\": false,"
1614 " \"present\": true"
1615 " },"
1616 " \"id\": \"libvirt-7\""
1617 "}") < 0)
1618 return -1;
1620 if (qemuMonitorJSONGetVirtType(qemuMonitorTestGetMonitor(test), &virtType) < 0)
1621 return -1;
1623 if (virtType != VIR_DOMAIN_VIRT_KVM) {
1624 virReportError(VIR_ERR_INTERNAL_ERROR,
1625 "Unexpected virt type: %d, expecting %d", virtType, VIR_DOMAIN_VIRT_KVM);
1626 return -1;
1629 if (qemuMonitorJSONGetVirtType(qemuMonitorTestGetMonitor(test), &virtType) < 0)
1630 return -1;
1632 if (virtType != VIR_DOMAIN_VIRT_QEMU) {
1633 virReportError(VIR_ERR_INTERNAL_ERROR,
1634 "Unexpected virt type: %d, expecting %d", virtType, VIR_DOMAIN_VIRT_QEMU);
1635 return -1;
1638 return 0;
1642 static void
1643 testQemuMonitorJSONGetBlockInfoPrint(const struct qemuDomainDiskInfo *d)
1645 VIR_TEST_VERBOSE("removable: %d, tray: %d, tray_open: %d, empty: %d, "
1646 "io_status: %d, nodename: '%s'\n",
1647 d->removable, d->tray, d->tray_open, d->empty,
1648 d->io_status, NULLSTR(d->nodename));
1652 static int
1653 testHashEqualQemuDomainDiskInfo(const void *value1, const void *value2)
1655 const struct qemuDomainDiskInfo *info1 = value1, *info2 = value2;
1656 int ret;
1658 if ((ret = memcmp(info1, info2, sizeof(*info1))) != 0) {
1659 testQemuMonitorJSONGetBlockInfoPrint(info1);
1660 testQemuMonitorJSONGetBlockInfoPrint(info2);
1663 return ret;
1666 static int
1667 testQemuMonitorJSONqemuMonitorJSONGetBlockInfo(const void *opaque)
1669 const testGenericData *data = opaque;
1670 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1671 int ret = -1;
1672 virHashTablePtr blockDevices = NULL, expectedBlockDevices = NULL;
1673 struct qemuDomainDiskInfo *info;
1674 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1676 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1677 return -1;
1679 if (!(blockDevices = virHashCreate(32, virHashValueFree)) ||
1680 !(expectedBlockDevices = virHashCreate(32, virHashValueFree)))
1681 goto cleanup;
1683 if (VIR_ALLOC(info) < 0)
1684 goto cleanup;
1686 if (virHashAddEntry(expectedBlockDevices, "virtio-disk0", info) < 0) {
1687 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1688 "Unable to create expectedBlockDevices hash table");
1689 goto cleanup;
1692 if (VIR_ALLOC(info) < 0)
1693 goto cleanup;
1695 if (virHashAddEntry(expectedBlockDevices, "virtio-disk1", info) < 0) {
1696 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1697 "Unable to create expectedBlockDevices hash table");
1698 goto cleanup;
1701 if (VIR_ALLOC(info) < 0)
1702 goto cleanup;
1704 info->removable = true;
1705 info->tray = true;
1707 if (virHashAddEntry(expectedBlockDevices, "ide0-1-0", info) < 0) {
1708 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1709 "Unable to create expectedBlockDevices hash table");
1710 goto cleanup;
1713 if (VIR_ALLOC(info) < 0)
1714 goto cleanup;
1716 info->removable = true;
1717 info->tray = true;
1718 info->empty = true;
1720 if (virHashAddEntry(expectedBlockDevices, "ide0-1-1", info) < 0) {
1721 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1722 "Unable to create expectedBlockDevices hash table");
1723 goto cleanup;
1726 if (qemuMonitorTestAddItem(test, "query-block", queryBlockReply) < 0)
1727 goto cleanup;
1729 if (qemuMonitorJSONGetBlockInfo(qemuMonitorTestGetMonitor(test), blockDevices) < 0)
1730 goto cleanup;
1732 if (!virHashEqual(blockDevices, expectedBlockDevices, testHashEqualQemuDomainDiskInfo)) {
1733 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1734 "Hashtable is different to the expected one");
1735 goto cleanup;
1738 ret = 0;
1739 cleanup:
1740 virHashFree(blockDevices);
1741 virHashFree(expectedBlockDevices);
1742 return ret;
1745 static int
1746 testQemuMonitorJSONqemuMonitorJSONGetAllBlockStatsInfo(const void *opaque)
1748 const testGenericData *data = opaque;
1749 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1750 virHashTablePtr blockstats = NULL;
1751 qemuBlockStatsPtr stats;
1752 int ret = -1;
1753 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1755 const char *reply =
1757 " \"return\": ["
1758 " {"
1759 " \"device\": \"drive-virtio-disk0\","
1760 " \"parent\": {"
1761 " \"stats\": {"
1762 " \"flush_total_time_ns\": 0,"
1763 " \"wr_highest_offset\": 5256018944,"
1764 " \"wr_total_time_ns\": 0,"
1765 " \"wr_bytes\": 0,"
1766 " \"rd_total_time_ns\": 0,"
1767 " \"flush_operations\": 0,"
1768 " \"wr_operations\": 0,"
1769 " \"rd_bytes\": 0,"
1770 " \"rd_operations\": 0"
1771 " }"
1772 " },"
1773 " \"stats\": {"
1774 " \"flush_total_time_ns\": 0,"
1775 " \"wr_highest_offset\": 10406001664,"
1776 " \"wr_total_time_ns\": 530699221,"
1777 " \"wr_bytes\": 2845696,"
1778 " \"rd_total_time_ns\": 640616474,"
1779 " \"flush_operations\": 0,"
1780 " \"wr_operations\": 174,"
1781 " \"rd_bytes\": 28505088,"
1782 " \"rd_operations\": 1279"
1783 " }"
1784 " },"
1785 " {"
1786 " \"device\": \"drive-virtio-disk1\","
1787 " \"parent\": {"
1788 " \"stats\": {"
1789 " \"flush_total_time_ns\": 0,"
1790 " \"wr_highest_offset\": 0,"
1791 " \"wr_total_time_ns\": 0,"
1792 " \"wr_bytes\": 0,"
1793 " \"rd_total_time_ns\": 0,"
1794 " \"flush_operations\": 0,"
1795 " \"wr_operations\": 0,"
1796 " \"rd_bytes\": 0,"
1797 " \"rd_operations\": 0"
1798 " }"
1799 " },"
1800 " \"stats\": {"
1801 " \"flush_total_time_ns\": 0,"
1802 " \"wr_highest_offset\": 0,"
1803 " \"wr_total_time_ns\": 0,"
1804 " \"wr_bytes\": 0,"
1805 " \"rd_total_time_ns\": 8232156,"
1806 " \"flush_operations\": 0,"
1807 " \"wr_operations\": 0,"
1808 " \"rd_bytes\": 348160,"
1809 " \"rd_operations\": 85"
1810 " }"
1811 " },"
1812 " {"
1813 " \"device\": \"drive-ide0-1-0\","
1814 " \"parent\": {"
1815 " \"stats\": {"
1816 " \"flush_total_time_ns\": 0,"
1817 " \"wr_total_time_ns\": 0,"
1818 " \"wr_bytes\": 0,"
1819 " \"rd_total_time_ns\": 0,"
1820 " \"flush_operations\": 0,"
1821 " \"wr_operations\": 0,"
1822 " \"rd_bytes\": 0,"
1823 " \"rd_operations\": 0"
1824 " }"
1825 " },"
1826 " \"stats\": {"
1827 " \"flush_total_time_ns\": 0,"
1828 " \"wr_highest_offset\": 0,"
1829 " \"wr_total_time_ns\": 0,"
1830 " \"wr_bytes\": 0,"
1831 " \"rd_total_time_ns\": 1004952,"
1832 " \"flush_operations\": 0,"
1833 " \"wr_operations\": 0,"
1834 " \"rd_bytes\": 49250,"
1835 " \"rd_operations\": 16"
1836 " }"
1837 " }"
1838 " ],"
1839 " \"id\": \"libvirt-11\""
1840 "}";
1842 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1843 return -1;
1845 if (!(blockstats = virHashCreate(10, virHashValueFree)))
1846 goto cleanup;
1848 if (qemuMonitorTestAddItem(test, "query-blockstats", reply) < 0)
1849 goto cleanup;
1851 #define CHECK0FULL(var, value, varformat, valformat) \
1852 if (stats->var != value) { \
1853 virReportError(VIR_ERR_INTERNAL_ERROR, \
1854 "Invalid " #var " value: " varformat \
1855 ", expected " valformat, \
1856 stats->var, value); \
1857 goto cleanup; \
1860 #define CHECK0(var, value) CHECK0FULL(var, value, "%lld", "%d")
1862 #define CHECK(NAME, RD_REQ, RD_BYTES, RD_TOTAL_TIMES, WR_REQ, WR_BYTES, \
1863 WR_TOTAL_TIMES, FLUSH_REQ, FLUSH_TOTAL_TIMES, \
1864 WR_HIGHEST_OFFSET, WR_HIGHEST_OFFSET_VALID) \
1865 if (!(stats = virHashLookup(blockstats, NAME))) { \
1866 virReportError(VIR_ERR_INTERNAL_ERROR, \
1867 "block stats for device '%s' is missing", NAME); \
1868 goto cleanup; \
1870 CHECK0(rd_req, RD_REQ) \
1871 CHECK0(rd_bytes, RD_BYTES) \
1872 CHECK0(rd_total_times, RD_TOTAL_TIMES) \
1873 CHECK0(wr_req, WR_REQ) \
1874 CHECK0(wr_bytes, WR_BYTES) \
1875 CHECK0(wr_total_times, WR_TOTAL_TIMES) \
1876 CHECK0(flush_req, FLUSH_REQ) \
1877 CHECK0(flush_total_times, FLUSH_TOTAL_TIMES) \
1878 CHECK0FULL(wr_highest_offset, WR_HIGHEST_OFFSET, "%llu", "%llu") \
1879 CHECK0FULL(wr_highest_offset_valid, WR_HIGHEST_OFFSET_VALID, "%d", "%d")
1881 if (qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorTestGetMonitor(test),
1882 blockstats, false) < 0)
1883 goto cleanup;
1885 if (!blockstats) {
1886 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1887 "qemuMonitorJSONGetAllBlockStatsInfo didn't return stats");
1888 goto cleanup;
1891 CHECK("virtio-disk0", 1279, 28505088, 640616474, 174, 2845696, 530699221, 0, 0, 5256018944ULL, true)
1892 CHECK("virtio-disk1", 85, 348160, 8232156, 0, 0, 0, 0, 0, 0ULL, true)
1893 CHECK("ide0-1-0", 16, 49250, 1004952, 0, 0, 0, 0, 0, 0ULL, false)
1895 ret = 0;
1897 #undef CHECK
1898 #undef CHECK0
1899 #undef CHECK0FULL
1901 cleanup:
1902 virHashFree(blockstats);
1903 return ret;
1907 static int
1908 testQemuMonitorJSONqemuMonitorJSONGetMigrationCacheSize(const void *opaque)
1910 const testGenericData *data = opaque;
1911 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1912 unsigned long long cacheSize;
1913 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1915 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1916 return -1;
1918 if (qemuMonitorTestAddItem(test, "query-migrate-cache-size",
1920 " \"return\": 67108864,"
1921 " \"id\": \"libvirt-12\""
1922 "}") < 0)
1923 return -1;
1925 if (qemuMonitorJSONGetMigrationCacheSize(qemuMonitorTestGetMonitor(test),
1926 &cacheSize) < 0)
1927 return -1;
1929 if (cacheSize != 67108864) {
1930 virReportError(VIR_ERR_INTERNAL_ERROR,
1931 "Invalid cacheSize: %llu, expected 67108864",
1932 cacheSize);
1933 return -1;
1936 return 0;
1939 static int
1940 testQemuMonitorJSONqemuMonitorJSONGetMigrationStats(const void *opaque)
1942 const testGenericData *data = opaque;
1943 virDomainXMLOptionPtr xmlopt = data->xmlopt;
1944 int ret = -1;
1945 qemuMonitorMigrationStats stats, expectedStats;
1946 char *error = NULL;
1947 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
1949 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
1950 return -1;
1952 memset(&expectedStats, 0, sizeof(expectedStats));
1954 expectedStats.status = QEMU_MONITOR_MIGRATION_STATUS_ACTIVE;
1955 expectedStats.total_time = 47;
1956 expectedStats.ram_total = 1611038720;
1957 expectedStats.ram_remaining = 1605013504;
1958 expectedStats.ram_transferred = 3625548;
1960 if (qemuMonitorTestAddItem(test, "query-migrate",
1962 " \"return\": {"
1963 " \"status\": \"active\","
1964 " \"total-time\": 47,"
1965 " \"ram\": {"
1966 " \"total\": 1611038720,"
1967 " \"remaining\": 1605013504,"
1968 " \"transferred\": 3625548"
1969 " }"
1970 " },"
1971 " \"id\": \"libvirt-13\""
1972 "}") < 0 ||
1973 qemuMonitorTestAddItem(test, "query-migrate",
1975 " \"return\": {"
1976 " \"status\": \"failed\","
1977 " \"error-desc\": \"It's broken\""
1978 " },"
1979 " \"id\": \"libvirt-14\""
1980 "}") < 0)
1981 goto cleanup;
1983 if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test),
1984 &stats, &error) < 0)
1985 goto cleanup;
1987 if (memcmp(&stats, &expectedStats, sizeof(stats)) != 0 || error) {
1988 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1989 "Invalid migration statistics");
1990 goto cleanup;
1993 memset(&stats, 0, sizeof(stats));
1994 if (qemuMonitorJSONGetMigrationStats(qemuMonitorTestGetMonitor(test),
1995 &stats, &error) < 0)
1996 goto cleanup;
1998 if (stats.status != QEMU_MONITOR_MIGRATION_STATUS_ERROR ||
1999 STRNEQ_NULLABLE(error, "It's broken")) {
2000 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2001 "Invalid failed migration status");
2002 goto cleanup;
2005 ret = 0;
2006 cleanup:
2007 VIR_FREE(error);
2008 return ret;
2011 static int
2012 testHashEqualChardevInfo(const void *value1, const void *value2)
2014 const qemuMonitorChardevInfo *info1 = value1;
2015 const qemuMonitorChardevInfo *info2 = value2;
2017 if (info1->state != info2->state)
2018 goto error;
2020 if (STRNEQ_NULLABLE(info1->ptyPath, info2->ptyPath))
2021 goto error;
2023 return 0;
2025 error:
2026 fprintf(stderr, "\n"
2027 "info1->state: %d info2->state: %d\n"
2028 "info1->ptyPath: %s info2->ptyPath: %s\n",
2029 info1->state, info2->state, info1->ptyPath, info2->ptyPath);
2030 return -1;
2034 static int
2035 testQemuMonitorJSONqemuMonitorJSONGetChardevInfo(const void *opaque)
2037 const testGenericData *data = opaque;
2038 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2039 int ret = -1;
2040 virHashTablePtr info = NULL, expectedInfo = NULL;
2041 qemuMonitorChardevInfo info0 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
2042 qemuMonitorChardevInfo info1 = { (char *) "/dev/pts/21", VIR_DOMAIN_CHR_DEVICE_STATE_CONNECTED };
2043 qemuMonitorChardevInfo info2 = { (char *) "/dev/pts/20", VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT };
2044 qemuMonitorChardevInfo info3 = { NULL, VIR_DOMAIN_CHR_DEVICE_STATE_DISCONNECTED };
2045 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2047 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2048 return -1;
2050 if (!(info = virHashCreate(32, qemuMonitorChardevInfoFree)) ||
2051 !(expectedInfo = virHashCreate(32, NULL)))
2052 goto cleanup;
2054 if (virHashAddEntry(expectedInfo, "charserial1", &info1) < 0 ||
2055 virHashAddEntry(expectedInfo, "charserial0", &info2) < 0 ||
2056 virHashAddEntry(expectedInfo, "charmonitor", &info0) < 0 ||
2057 virHashAddEntry(expectedInfo, "charserial2", &info3) < 0) {
2058 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2059 "Unable to create expectedInfo hash table");
2060 goto cleanup;
2063 if (qemuMonitorTestAddItem(test, "query-chardev",
2065 " \"return\": ["
2066 " {"
2067 " \"filename\": \"pty:/dev/pts/21\","
2068 " \"label\": \"charserial1\","
2069 " \"frontend-open\": true"
2070 " },"
2071 " {"
2072 " \"filename\": \"pty:/dev/pts/20\","
2073 " \"label\": \"charserial0\""
2074 " },"
2075 " {"
2076 " \"filename\": \"unix:/var/lib/libvirt/qemu/gentoo.monitor,server\","
2077 " \"label\": \"charmonitor\""
2078 " },"
2079 " {"
2080 " \"filename\": \"unix:/path/to/socket,server\","
2081 " \"label\": \"charserial2\","
2082 " \"frontend-open\": false"
2083 " }"
2084 " ],"
2085 " \"id\": \"libvirt-15\""
2086 "}") < 0)
2087 goto cleanup;
2089 if (qemuMonitorJSONGetChardevInfo(qemuMonitorTestGetMonitor(test),
2090 info) < 0)
2091 goto cleanup;
2093 if (!virHashEqual(info, expectedInfo, testHashEqualChardevInfo)) {
2094 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2095 "Hashtable is different to the expected one");
2096 goto cleanup;
2099 ret = 0;
2100 cleanup:
2101 virHashFree(info);
2102 virHashFree(expectedInfo);
2103 return ret;
2107 static int
2108 testValidateGetBlockIoThrottle(const virDomainBlockIoTuneInfo *info,
2109 const virDomainBlockIoTuneInfo *expectedInfo)
2111 #define VALIDATE_IOTUNE(field) \
2112 if (info->field != expectedInfo->field) { \
2113 virReportError(VIR_ERR_INTERNAL_ERROR, \
2114 "info->%s=%llu != expected=%llu", \
2115 #field, info->field, expectedInfo->field); \
2116 return -1; \
2118 if (info->field##_max != expectedInfo->field##_max) { \
2119 virReportError(VIR_ERR_INTERNAL_ERROR, \
2120 "info->%s_max=%llu != expected=%llu", \
2121 #field, info->field##_max, expectedInfo->field##_max); \
2122 return -1; \
2124 if (info->field##_max_length != expectedInfo->field##_max_length) { \
2125 virReportError(VIR_ERR_INTERNAL_ERROR, \
2126 "info->%s_max_length=%llu != expected=%llu", \
2127 #field, info->field##_max_length, \
2128 expectedInfo->field##_max_length); \
2129 return -1; \
2131 VALIDATE_IOTUNE(total_bytes_sec);
2132 VALIDATE_IOTUNE(read_bytes_sec);
2133 VALIDATE_IOTUNE(write_bytes_sec);
2134 VALIDATE_IOTUNE(total_iops_sec);
2135 VALIDATE_IOTUNE(read_iops_sec);
2136 VALIDATE_IOTUNE(write_iops_sec);
2137 if (info->size_iops_sec != expectedInfo->size_iops_sec) {
2138 virReportError(VIR_ERR_INTERNAL_ERROR,
2139 "info->size_iops_sec=%llu != expected=%llu",
2140 info->size_iops_sec, expectedInfo->size_iops_sec);
2141 return -1;
2143 if (STRNEQ(info->group_name, expectedInfo->group_name)) {
2144 virReportError(VIR_ERR_INTERNAL_ERROR,
2145 "info->group_name=%s != expected=%s",
2146 info->group_name, expectedInfo->group_name);
2147 return -1;
2149 #undef VALIDATE_IOTUNE
2151 return 0;
2155 static int
2156 testQemuMonitorJSONqemuMonitorJSONSetBlockIoThrottle(const void *opaque)
2158 const testGenericData *data = opaque;
2159 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2160 int ret = -1;
2161 virDomainBlockIoTuneInfo info, expectedInfo;
2162 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2164 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2165 return -1;
2167 expectedInfo = (virDomainBlockIoTuneInfo) {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, NULL, 15, 16, 17, 18, 19, 20};
2168 if (VIR_STRDUP(expectedInfo.group_name, "group14") < 0)
2169 return -1;
2171 if (qemuMonitorTestAddItem(test, "query-block", queryBlockReply) < 0 ||
2172 qemuMonitorTestAddItemParams(test, "block_set_io_throttle",
2173 "{\"return\":{}}",
2174 "device", "\"drive-virtio-disk1\"",
2175 "bps", "1", "bps_rd", "2", "bps_wr", "3",
2176 "iops", "4", "iops_rd", "5", "iops_wr", "6",
2177 "bps_max", "7", "bps_rd_max", "8",
2178 "bps_wr_max", "9",
2179 "iops_max", "10", "iops_rd_max", "11",
2180 "iops_wr_max", "12", "iops_size", "13",
2181 "group", "\"group14\"",
2182 "bps_max_length", "15",
2183 "bps_rd_max_length", "16",
2184 "bps_wr_max_length", "17",
2185 "iops_max_length", "18",
2186 "iops_rd_max_length", "19",
2187 "iops_wr_max_length", "20",
2188 NULL, NULL) < 0)
2189 goto cleanup;
2191 if (qemuMonitorJSONGetBlockIoThrottle(qemuMonitorTestGetMonitor(test),
2192 "drive-virtio-disk0", NULL, &info) < 0)
2193 goto cleanup;
2195 if (testValidateGetBlockIoThrottle(&info, &expectedInfo) < 0)
2196 goto cleanup;
2198 if (qemuMonitorJSONSetBlockIoThrottle(qemuMonitorTestGetMonitor(test),
2199 "drive-virtio-disk1", NULL, &info, true,
2200 true, true) < 0)
2201 goto cleanup;
2203 ret = 0;
2204 cleanup:
2205 VIR_FREE(info.group_name);
2206 VIR_FREE(expectedInfo.group_name);
2207 return ret;
2210 static int
2211 testQemuMonitorJSONqemuMonitorJSONGetTargetArch(const void *opaque)
2213 const testGenericData *data = opaque;
2214 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2215 int ret = -1;
2216 char *arch;
2217 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2219 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2220 return -1;
2222 if (qemuMonitorTestAddItem(test, "query-target",
2224 " \"return\": {"
2225 " \"arch\": \"x86_64\""
2226 " },"
2227 " \"id\": \"libvirt-21\""
2228 "}") < 0)
2229 goto cleanup;
2231 if (!(arch = qemuMonitorJSONGetTargetArch(qemuMonitorTestGetMonitor(test))))
2232 goto cleanup;
2234 if (STRNEQ(arch, "x86_64")) {
2235 virReportError(VIR_ERR_INTERNAL_ERROR,
2236 "Unexpected architecture %s, expecting x86_64",
2237 arch);
2238 goto cleanup;
2241 ret = 0;
2242 cleanup:
2243 VIR_FREE(arch);
2244 return ret;
2247 static int
2248 testQemuMonitorJSONqemuMonitorJSONGetMigrationCapabilities(const void *opaque)
2250 const testGenericData *data = opaque;
2251 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2252 int ret = -1;
2253 const char *cap;
2254 char **caps = NULL;
2255 virBitmapPtr bitmap = NULL;
2256 virJSONValuePtr json = NULL;
2257 const char *reply =
2259 " \"return\": ["
2260 " {"
2261 " \"state\": false,"
2262 " \"capability\": \"xbzrle\""
2263 " }"
2264 " ],"
2265 " \"id\": \"libvirt-22\""
2266 "}";
2267 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2269 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2270 return -1;
2272 if (qemuMonitorTestAddItem(test, "query-migrate-capabilities", reply) < 0 ||
2273 qemuMonitorTestAddItem(test, "migrate-set-capabilities",
2274 "{\"return\":{}}") < 0)
2275 goto cleanup;
2277 if (qemuMonitorGetMigrationCapabilities(qemuMonitorTestGetMonitor(test),
2278 &caps) < 0)
2279 goto cleanup;
2281 cap = qemuMigrationCapabilityTypeToString(QEMU_MIGRATION_CAP_XBZRLE);
2282 if (!virStringListHasString((const char **) caps, cap)) {
2283 virReportError(VIR_ERR_INTERNAL_ERROR,
2284 "Expected capability %s is missing", cap);
2285 goto cleanup;
2288 bitmap = virBitmapNew(QEMU_MIGRATION_CAP_LAST);
2289 if (!bitmap)
2290 goto cleanup;
2292 ignore_value(virBitmapSetBit(bitmap, QEMU_MIGRATION_CAP_XBZRLE));
2293 if (!(json = qemuMigrationCapsToJSON(bitmap, bitmap)))
2294 goto cleanup;
2296 ret = qemuMonitorJSONSetMigrationCapabilities(qemuMonitorTestGetMonitor(test),
2297 json);
2298 json = NULL;
2300 cleanup:
2301 virJSONValueFree(json);
2302 virStringListFree(caps);
2303 virBitmapFree(bitmap);
2304 return ret;
2307 static int
2308 testQemuMonitorJSONqemuMonitorJSONSendKey(const void *opaque)
2310 const testGenericData *data = opaque;
2311 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2312 unsigned int keycodes[] = {43, 26, 46, 32};
2313 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2315 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2316 return -1;
2318 if (qemuMonitorTestAddItem(test, "send-key",
2319 "{\"return\": {}, \"id\": \"libvirt-16\"}") < 0)
2320 return -1;
2322 if (qemuMonitorJSONSendKey(qemuMonitorTestGetMonitor(test),
2323 0, keycodes, ARRAY_CARDINALITY(keycodes)) < 0)
2324 return -1;
2326 return 0;
2329 static int
2330 testQemuMonitorJSONqemuMonitorJSONSendKeyHoldtime(const void *opaque)
2332 const testGenericData *data = opaque;
2333 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2334 unsigned int keycodes[] = {43, 26, 46, 32};
2335 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2337 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2338 return -1;
2340 if (qemuMonitorTestAddItemParams(test, "send-key",
2341 "{\"return\":{}}",
2342 "hold-time", "31337",
2343 "keys", "[{\"type\":\"number\",\"data\":43},"
2344 "{\"type\":\"number\",\"data\":26},"
2345 "{\"type\":\"number\",\"data\":46},"
2346 "{\"type\":\"number\",\"data\":32}]",
2347 NULL, NULL) < 0)
2348 return -1;
2350 if (qemuMonitorJSONSendKey(qemuMonitorTestGetMonitor(test),
2351 31337, keycodes,
2352 ARRAY_CARDINALITY(keycodes)) < 0)
2353 return -1;
2355 return 0;
2358 static int
2359 testQemuMonitorJSONqemuMonitorSupportsActiveCommit(const void *opaque)
2361 const testGenericData *data = opaque;
2362 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2363 const char *error1 =
2365 " \"error\": {"
2366 " \"class\": \"DeviceNotFound\","
2367 " \"desc\": \"Device 'bogus' not found\""
2368 " }"
2369 "}";
2370 const char *error2 =
2372 " \"error\": {"
2373 " \"class\": \"GenericError\","
2374 " \"desc\": \"Parameter 'top' is missing\""
2375 " }"
2376 "}";
2377 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2379 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2380 return -1;
2382 if (qemuMonitorTestAddItemParams(test, "block-commit", error1,
2383 "device", "\"bogus\"",
2384 NULL, NULL) < 0)
2385 return -1;
2387 if (!qemuMonitorSupportsActiveCommit(qemuMonitorTestGetMonitor(test)))
2388 return -1;
2390 if (qemuMonitorTestAddItemParams(test, "block-commit", error2,
2391 "device", "\"bogus\"",
2392 NULL, NULL) < 0)
2393 return -1;
2395 if (qemuMonitorSupportsActiveCommit(qemuMonitorTestGetMonitor(test)))
2396 return -1;
2398 return 0;
2401 static int
2402 testQemuMonitorJSONqemuMonitorJSONGetDumpGuestMemoryCapability(const void *opaque)
2404 const testGenericData *data = opaque;
2405 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2406 int cap;
2407 const char *reply =
2409 " \"return\": {"
2410 " \"formats\": ["
2411 " \"elf\","
2412 " \"kdump-zlib\","
2413 " \"kdump-lzo\","
2414 " \"kdump-snappy\""
2415 " ]"
2416 " },"
2417 " \"id\": \"libvirt-9\""
2418 "}";
2419 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2421 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2422 return -1;
2424 if (qemuMonitorTestAddItem(test, "query-dump-guest-memory-capability",
2425 reply) < 0)
2426 return -1;
2428 cap = qemuMonitorJSONGetDumpGuestMemoryCapability(
2429 qemuMonitorTestGetMonitor(test), "elf");
2431 if (cap != 1) {
2432 virReportError(VIR_ERR_INTERNAL_ERROR,
2433 "Unexpected capability: %d, expecting 1",
2434 cap);
2435 return -1;
2438 return 0;
2441 struct testCPUData {
2442 const char *name;
2443 virDomainXMLOptionPtr xmlopt;
2444 virHashTablePtr schema;
2448 static int
2449 testQemuMonitorJSONGetCPUData(const void *opaque)
2451 const struct testCPUData *data = opaque;
2452 virCPUDataPtr cpuData = NULL;
2453 char *jsonFile = NULL;
2454 char *dataFile = NULL;
2455 char *jsonStr = NULL;
2456 char *actual = NULL;
2457 int ret = -1;
2458 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2460 if (!(test = qemuMonitorTestNewSchema(data->xmlopt, data->schema)))
2461 return -1;
2463 if (virAsprintf(&jsonFile,
2464 "%s/qemumonitorjsondata/qemumonitorjson-getcpu-%s.json",
2465 abs_srcdir, data->name) < 0 ||
2466 virAsprintf(&dataFile,
2467 "%s/qemumonitorjsondata/qemumonitorjson-getcpu-%s.data",
2468 abs_srcdir, data->name) < 0)
2469 goto cleanup;
2471 if (virTestLoadFile(jsonFile, &jsonStr) < 0)
2472 goto cleanup;
2474 if (qemuMonitorTestAddItem(test, "qom-list",
2476 " \"return\": ["
2477 " {"
2478 " \"name\": \"filtered-features\","
2479 " \"type\": \"X86CPUFeatureWordInfo\""
2480 " },"
2481 " {"
2482 " \"name\": \"feature-words\","
2483 " \"type\": \"X86CPUFeatureWordInfo\""
2484 " }"
2485 " ],"
2486 " \"id\": \"libvirt-19\""
2487 "}") < 0)
2488 goto cleanup;
2490 if (qemuMonitorTestAddItem(test, "qom-get", jsonStr) < 0)
2491 goto cleanup;
2493 if (qemuMonitorJSONGetGuestCPUx86(qemuMonitorTestGetMonitor(test),
2494 &cpuData, NULL) < 0)
2495 goto cleanup;
2497 if (!(actual = virCPUDataFormat(cpuData)))
2498 goto cleanup;
2500 if (virTestCompareToFile(actual, dataFile) < 0)
2501 goto cleanup;
2503 ret = 0;
2504 cleanup:
2505 VIR_FREE(jsonFile);
2506 VIR_FREE(dataFile);
2507 VIR_FREE(jsonStr);
2508 VIR_FREE(actual);
2509 virCPUDataFree(cpuData);
2510 return ret;
2513 static int
2514 testQemuMonitorJSONGetNonExistingCPUData(const void *opaque)
2516 const testGenericData *data = opaque;
2517 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2518 virCPUDataPtr cpuData = NULL;
2519 int rv, ret = -1;
2520 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2522 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2523 return -1;
2525 if (qemuMonitorTestAddItem(test, "qom-list",
2527 " \"id\": \"libvirt-7\","
2528 " \"error\": {"
2529 " \"class\": \"CommandNotFound\","
2530 " \"desc\": \"The command qom-list has not been found\""
2531 " }"
2532 "}") < 0)
2533 goto cleanup;
2535 rv = qemuMonitorJSONGetGuestCPUx86(qemuMonitorTestGetMonitor(test),
2536 &cpuData, NULL);
2537 if (rv != -2) {
2538 virReportError(VIR_ERR_INTERNAL_ERROR,
2539 "Unexpected return value %d, expecting -2", rv);
2540 goto cleanup;
2543 if (cpuData) {
2544 virReportError(VIR_ERR_INTERNAL_ERROR,
2545 "Unexpected allocation of data = %p, expecting NULL",
2546 cpuData);
2547 goto cleanup;
2550 ret = 0;
2551 cleanup:
2552 virCPUDataFree(cpuData);
2553 return ret;
2556 static int
2557 testQemuMonitorJSONGetIOThreads(const void *opaque)
2559 const testGenericData *data = opaque;
2560 virDomainXMLOptionPtr xmlopt = data->xmlopt;
2561 qemuMonitorIOThreadInfoPtr *info;
2562 int ninfo = 0;
2563 int ret = -1;
2564 size_t i;
2565 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2567 if (!(test = qemuMonitorTestNewSchema(xmlopt, data->schema)))
2568 return -1;
2570 if (qemuMonitorTestAddItem(test, "query-iothreads",
2571 "{ "
2572 " \"return\": [ "
2573 " { "
2574 " \"id\": \"iothread1\", "
2575 " \"thread-id\": 30992 "
2576 " }, "
2577 " { "
2578 " \"id\": \"iothread2\", "
2579 " \"thread-id\": 30993 "
2580 " } "
2581 " ]"
2582 "}") < 0)
2583 goto cleanup;
2585 if ((ninfo = qemuMonitorGetIOThreads(qemuMonitorTestGetMonitor(test),
2586 &info)) < 0)
2587 goto cleanup;
2589 if (ninfo != 2) {
2590 virReportError(VIR_ERR_INTERNAL_ERROR,
2591 "ninfo %d is not 2", ninfo);
2592 goto cleanup;
2595 #define CHECK(i, wantiothread_id, wantthread_id) \
2596 do { \
2597 if (info[i]->iothread_id != (wantiothread_id)) { \
2598 virReportError(VIR_ERR_INTERNAL_ERROR, \
2599 "iothread_id %u is not %u", \
2600 info[i]->iothread_id, (wantiothread_id)); \
2601 goto cleanup; \
2603 if (info[i]->thread_id != (wantthread_id)) { \
2604 virReportError(VIR_ERR_INTERNAL_ERROR, \
2605 "thread_id %d is not %d", \
2606 info[i]->thread_id, (wantthread_id)); \
2607 goto cleanup; \
2609 } while (0)
2611 CHECK(0, 1, 30992);
2612 CHECK(1, 2, 30993);
2614 #undef CHECK
2616 ret = 0;
2618 cleanup:
2619 for (i = 0; i < ninfo; i++)
2620 VIR_FREE(info[i]);
2621 VIR_FREE(info);
2623 return ret;
2626 struct testCPUInfoData {
2627 const char *name;
2628 size_t maxvcpus;
2629 virDomainXMLOptionPtr xmlopt;
2630 bool fast;
2631 virHashTablePtr schema;
2635 static char *
2636 testQemuMonitorCPUInfoFormat(qemuMonitorCPUInfoPtr vcpus,
2637 size_t nvcpus)
2639 virBuffer buf = VIR_BUFFER_INITIALIZER;
2640 qemuMonitorCPUInfoPtr vcpu;
2641 size_t i;
2643 for (i = 0; i < nvcpus; i++) {
2644 vcpu = vcpus + i;
2646 virBufferAsprintf(&buf, "[vcpu libvirt-id='%zu']\n", i);
2647 virBufferAdjustIndent(&buf, 4);
2649 virBufferAsprintf(&buf, "online=%s\n", vcpu->online ? "yes" : "no");
2650 virBufferAsprintf(&buf, "hotpluggable=%s\n", vcpu->hotpluggable ? "yes" : "no");
2652 if (vcpu->tid)
2653 virBufferAsprintf(&buf, "thread-id='%llu'\n",
2654 (unsigned long long) vcpu->tid);
2656 if (vcpu->id != 0)
2657 virBufferAsprintf(&buf, "enable-id='%d'\n", vcpu->id);
2659 if (vcpu->qemu_id != -1)
2660 virBufferAsprintf(&buf, "query-cpus-id='%d'\n", vcpu->qemu_id);
2662 if (vcpu->type)
2663 virBufferAsprintf(&buf, "type='%s'\n", vcpu->type);
2665 if (vcpu->alias)
2666 virBufferAsprintf(&buf, "alias='%s'\n", vcpu->alias);
2667 if (vcpu->qom_path)
2668 virBufferAsprintf(&buf, "qom_path='%s'\n", vcpu->qom_path);
2670 if (vcpu->socket_id != -1 || vcpu->core_id != -1 ||
2671 vcpu->thread_id != -1 || vcpu->vcpus != 0) {
2672 virBufferAddLit(&buf, "topology:");
2673 if (vcpu->socket_id != -1)
2674 virBufferAsprintf(&buf, " socket='%d'", vcpu->socket_id);
2675 if (vcpu->core_id != -1)
2676 virBufferAsprintf(&buf, " core='%d'", vcpu->core_id);
2677 if (vcpu->thread_id != -1)
2678 virBufferAsprintf(&buf, " thread='%d'", vcpu->thread_id);
2679 if (vcpu->node_id != -1)
2680 virBufferAsprintf(&buf, " node='%d'", vcpu->node_id);
2681 if (vcpu->vcpus != 0)
2682 virBufferAsprintf(&buf, " vcpus='%u'", vcpu->vcpus);
2683 virBufferAddLit(&buf, "\n");
2686 if (vcpu->halted)
2687 virBufferAddLit(&buf, "halted\n");
2689 virBufferAdjustIndent(&buf, -4);
2692 return virBufferContentAndReset(&buf);
2696 static int
2697 testQemuMonitorCPUInfo(const void *opaque)
2699 const struct testCPUInfoData *data = opaque;
2700 virDomainObjPtr vm = NULL;
2701 char *queryCpusFile = NULL;
2702 char *queryHotpluggableFile = NULL;
2703 char *dataFile = NULL;
2704 char *queryCpusStr = NULL;
2705 char *queryHotpluggableStr = NULL;
2706 char *actual = NULL;
2707 const char *queryCpusFunction;
2708 qemuMonitorCPUInfoPtr vcpus = NULL;
2709 int rc;
2710 int ret = -1;
2711 VIR_AUTOPTR(qemuMonitorTest) test = NULL;
2713 if (!(test = qemuMonitorTestNewSchema(data->xmlopt, data->schema)))
2714 return -1;
2716 if (virAsprintf(&queryCpusFile,
2717 "%s/qemumonitorjsondata/qemumonitorjson-cpuinfo-%s-cpus.json",
2718 abs_srcdir, data->name) < 0 ||
2719 virAsprintf(&queryHotpluggableFile,
2720 "%s/qemumonitorjsondata/qemumonitorjson-cpuinfo-%s-hotplug.json",
2721 abs_srcdir, data->name) < 0 ||
2722 virAsprintf(&dataFile,
2723 "%s/qemumonitorjsondata/qemumonitorjson-cpuinfo-%s.data",
2724 abs_srcdir, data->name) < 0)
2725 goto cleanup;
2727 if (virTestLoadFile(queryCpusFile, &queryCpusStr) < 0)
2728 goto cleanup;
2730 if (virTestLoadFile(queryHotpluggableFile, &queryHotpluggableStr) < 0)
2731 goto cleanup;
2733 if (qemuMonitorTestAddItem(test, "query-hotpluggable-cpus",
2734 queryHotpluggableStr) < 0)
2735 goto cleanup;
2737 if (data->fast)
2738 queryCpusFunction = "query-cpus-fast";
2739 else
2740 queryCpusFunction = "query-cpus";
2742 if (qemuMonitorTestAddItem(test, queryCpusFunction, queryCpusStr) < 0)
2743 goto cleanup;
2745 vm = qemuMonitorTestGetDomainObj(test);
2746 if (!vm)
2747 goto cleanup;
2749 rc = qemuMonitorGetCPUInfo(qemuMonitorTestGetMonitor(test),
2750 &vcpus, data->maxvcpus, true, data->fast);
2752 if (rc < 0)
2753 goto cleanup;
2755 actual = testQemuMonitorCPUInfoFormat(vcpus, data->maxvcpus);
2757 if (virTestCompareToFile(actual, dataFile) < 0)
2758 goto cleanup;
2760 ret = 0;
2761 cleanup:
2762 VIR_FREE(queryCpusFile);
2763 VIR_FREE(queryHotpluggableFile);
2764 VIR_FREE(dataFile);
2765 VIR_FREE(queryCpusStr);
2766 VIR_FREE(queryHotpluggableStr);
2767 VIR_FREE(actual);
2768 qemuMonitorCPUInfoFree(vcpus, data->maxvcpus);
2769 return ret;
2773 static int
2774 testBlockNodeNameDetectFormat(void *payload,
2775 const void *name,
2776 void *opaque)
2778 qemuBlockNodeNameBackingChainDataPtr entry = payload;
2779 const char *diskalias = name;
2780 virBufferPtr buf = opaque;
2782 virBufferSetIndent(buf, 0);
2784 virBufferAdd(buf, diskalias, -1);
2785 virBufferAddLit(buf, "\n");
2787 while (entry) {
2788 virBufferAsprintf(buf, "filename : '%s'\n", entry->qemufilename);
2789 virBufferAsprintf(buf, "format node : '%s'\n",
2790 NULLSTR(entry->nodeformat));
2791 virBufferAsprintf(buf, "format drv : '%s'\n", NULLSTR(entry->drvformat));
2792 virBufferAsprintf(buf, "storage node: '%s'\n",
2793 NULLSTR(entry->nodestorage));
2794 virBufferAsprintf(buf, "storage drv : '%s'\n", NULLSTR(entry->drvstorage));
2796 virBufferAdjustIndent(buf, 2);
2798 entry = entry->backing;
2801 virBufferSetIndent(buf, 0);
2802 virBufferAddLit(buf, "\n");
2803 return 0;
2807 static int
2808 testBlockNodeNameDetect(const void *opaque)
2810 const char *testname = opaque;
2811 const char *pathprefix = "qemumonitorjsondata/qemumonitorjson-nodename-";
2812 char *resultFile = NULL;
2813 char *actual = NULL;
2814 virJSONValuePtr namedNodesJson = NULL;
2815 virJSONValuePtr blockstatsJson = NULL;
2816 virHashTablePtr nodedata = NULL;
2817 virBuffer buf = VIR_BUFFER_INITIALIZER;
2818 int ret = -1;
2820 if (virAsprintf(&resultFile, "%s/%s%s.result",
2821 abs_srcdir, pathprefix, testname) < 0)
2822 goto cleanup;
2824 if (!(namedNodesJson = virTestLoadFileJSON(pathprefix, testname,
2825 "-named-nodes.json", NULL)))
2826 goto cleanup;
2828 if (!(blockstatsJson = virTestLoadFileJSON(pathprefix, testname,
2829 "-blockstats.json", NULL)))
2830 goto cleanup;
2832 if (!(nodedata = qemuBlockNodeNameGetBackingChain(namedNodesJson,
2833 blockstatsJson)))
2834 goto cleanup;
2836 virHashForEach(nodedata, testBlockNodeNameDetectFormat, &buf);
2838 virBufferTrim(&buf, "\n", -1);
2840 if (virBufferCheckError(&buf) < 0)
2841 goto cleanup;
2843 actual = virBufferContentAndReset(&buf);
2845 if (virTestCompareToFile(actual, resultFile) < 0)
2846 goto cleanup;
2848 ret = 0;
2850 cleanup:
2851 VIR_FREE(resultFile);
2852 VIR_FREE(actual);
2853 virHashFree(nodedata);
2854 virJSONValueFree(namedNodesJson);
2855 virJSONValueFree(blockstatsJson);
2857 return ret;
2861 struct testQAPISchemaData {
2862 virHashTablePtr schema;
2863 const char *name;
2864 const char *query;
2865 const char *json;
2866 bool success;
2867 int rc;
2868 bool replyobj;
2872 static int
2873 testQAPISchemaQuery(const void *opaque)
2875 const struct testQAPISchemaData *data = opaque;
2876 virJSONValuePtr replyobj = NULL;
2877 int rc;
2879 rc = virQEMUQAPISchemaPathGet(data->query, data->schema, &replyobj);
2881 if (data->rc != rc || data->replyobj != !!replyobj) {
2882 VIR_TEST_VERBOSE("\n success: expected '%d' got '%d', replyobj: expected '%d' got '%d'",
2883 data->rc, rc, data->replyobj, !!replyobj);
2884 return -1;
2887 return 0;
2891 static int
2892 testQAPISchemaValidate(const void *opaque)
2894 const struct testQAPISchemaData *data = opaque;
2895 virBuffer debug = VIR_BUFFER_INITIALIZER;
2896 virJSONValuePtr schemaroot;
2897 virJSONValuePtr json = NULL;
2898 int ret = -1;
2900 if (virQEMUQAPISchemaPathGet(data->query, data->schema, &schemaroot) < 0)
2901 goto cleanup;
2903 if (!(json = virJSONValueFromString(data->json)))
2904 goto cleanup;
2906 if ((testQEMUSchemaValidate(json, schemaroot, data->schema, &debug) == 0) != data->success) {
2907 if (!data->success)
2908 VIR_TEST_VERBOSE("\nschema validation should have failed\n");
2909 } else {
2910 ret = 0;
2913 if (virTestGetDebug() >= 3 ||
2914 (ret < 0 && virTestGetVerbose())) {
2915 char *debugstr = virBufferContentAndReset(&debug);
2916 fprintf(stderr, "\n%s\n", debugstr);
2917 VIR_FREE(debugstr);
2921 cleanup:
2922 virBufferFreeAndReset(&debug);
2923 virJSONValueFree(json);
2924 return ret;
2928 static void
2929 testQueryJobsPrintJob(virBufferPtr buf,
2930 qemuMonitorJobInfoPtr job)
2932 virBufferAddLit(buf, "[job]\n");
2933 virBufferAsprintf(buf, "id=%s\n", NULLSTR(job->id));
2934 virBufferAsprintf(buf, "type=%s\n", NULLSTR(qemuMonitorJobTypeToString(job->type)));
2935 virBufferAsprintf(buf, "status=%s\n", NULLSTR(qemuMonitorJobStatusTypeToString(job->status)));
2936 virBufferAsprintf(buf, "error=%s\n", NULLSTR(job->error));
2937 virBufferAddLit(buf, "\n");
2941 struct testQueryJobsData {
2942 const char *name;
2943 virDomainXMLOptionPtr xmlopt;
2947 static int
2948 testQueryJobs(const void *opaque)
2950 const struct testQueryJobsData *data = opaque;
2951 qemuMonitorTestPtr test = qemuMonitorTestNewSimple(data->xmlopt);
2952 VIR_AUTOFREE(char *) filenameJSON = NULL;
2953 VIR_AUTOFREE(char *) fileJSON = NULL;
2954 VIR_AUTOFREE(char *) filenameResult = NULL;
2955 VIR_AUTOFREE(char *) actual = NULL;
2956 qemuMonitorJobInfoPtr *jobs = NULL;
2957 virBuffer buf = VIR_BUFFER_INITIALIZER;
2958 size_t njobs = 0;
2959 size_t i;
2960 int ret = -1;
2962 if (!test)
2963 return -1;
2965 if (virAsprintf(&filenameJSON,
2966 abs_srcdir "/qemumonitorjsondata/query-jobs-%s.json",
2967 data->name) < 0 ||
2968 virAsprintf(&filenameResult,
2969 abs_srcdir "/qemumonitorjsondata/query-jobs-%s.result",
2970 data->name) < 0)
2971 goto cleanup;
2973 if (virTestLoadFile(filenameJSON, &fileJSON) < 0)
2974 goto cleanup;
2976 if (qemuMonitorTestAddItem(test, "query-jobs", fileJSON) < 0)
2977 goto cleanup;
2979 if (qemuMonitorJSONGetJobInfo(qemuMonitorTestGetMonitor(test),
2980 &jobs, &njobs) < 0)
2981 goto cleanup;
2983 for (i = 0; i < njobs; i++)
2984 testQueryJobsPrintJob(&buf, jobs[i]);
2986 virBufferTrim(&buf, "\n", -1);
2988 if (virBufferCheckError(&buf) < 0)
2989 goto cleanup;
2991 actual = virBufferContentAndReset(&buf);
2993 if (virTestCompareToFile(actual, filenameResult) < 0)
2994 goto cleanup;
2996 ret = 0;
2998 cleanup:
2999 for (i = 0; i < njobs; i++)
3000 qemuMonitorJobInfoFree(jobs[i]);
3001 VIR_FREE(jobs);
3002 qemuMonitorTestFree(test);
3003 return ret;
3007 static int
3008 mymain(void)
3010 int ret = 0;
3011 virQEMUDriver driver;
3012 testQemuMonitorJSONSimpleFuncData simpleFunc;
3013 struct testQAPISchemaData qapiData;
3014 virJSONValuePtr metaschema = NULL;
3015 char *metaschemastr = NULL;
3017 #if !WITH_YAJL
3018 fputs("libvirt not compiled with JSON support, skipping this test\n", stderr);
3019 return EXIT_AM_SKIP;
3020 #endif
3022 if (virThreadInitialize() < 0 ||
3023 qemuTestDriverInit(&driver) < 0)
3024 return EXIT_FAILURE;
3026 virEventRegisterDefaultImpl();
3028 if (!(qapiData.schema = testQEMUSchemaLoad())) {
3029 VIR_TEST_VERBOSE("failed to load qapi schema\n");
3030 ret = -1;
3031 goto cleanup;
3034 #define DO_TEST(name) \
3035 do { \
3036 testGenericData data = { driver.xmlopt, qapiData.schema }; \
3037 if (virTestRun(# name, testQemuMonitorJSON ## name, &data) < 0) \
3038 ret = -1; \
3039 } while (0)
3041 #define DO_TEST_SIMPLE(CMD, FNC, ...) \
3042 simpleFunc = (testQemuMonitorJSONSimpleFuncData) {.cmd = CMD, .func = FNC, \
3043 .xmlopt = driver.xmlopt, \
3044 .schema = qapiData.schema, \
3045 __VA_ARGS__ }; \
3046 if (virTestRun(# FNC, testQemuMonitorJSONSimpleFunc, &simpleFunc) < 0) \
3047 ret = -1
3049 #define DO_TEST_GEN(name, ...) \
3050 simpleFunc = (testQemuMonitorJSONSimpleFuncData) {.xmlopt = driver.xmlopt, \
3051 .schema = qapiData.schema \
3052 __VA_ARGS__ }; \
3053 if (virTestRun(# name, testQemuMonitorJSON ## name, &simpleFunc) < 0) \
3054 ret = -1
3056 #define DO_TEST_CPU_DATA(name) \
3057 do { \
3058 struct testCPUData data = { name, driver.xmlopt, qapiData.schema }; \
3059 const char *label = "GetCPUData(" name ")"; \
3060 if (virTestRun(label, testQemuMonitorJSONGetCPUData, &data) < 0) \
3061 ret = -1; \
3062 } while (0)
3064 #define DO_TEST_CPU_INFO(name, maxvcpus) \
3065 do { \
3066 struct testCPUInfoData data = {name, maxvcpus, driver.xmlopt, false, \
3067 qapiData.schema}; \
3068 if (virTestRun("GetCPUInfo(" name ")", testQemuMonitorCPUInfo, \
3069 &data) < 0) \
3070 ret = -1; \
3071 } while (0)
3073 #define DO_TEST_CPU_INFO_FAST(name, maxvcpus) \
3074 do { \
3075 struct testCPUInfoData data = {name, maxvcpus, driver.xmlopt, true, \
3076 qapiData.schema }; \
3077 if (virTestRun("GetCPUInfo(" name ")", testQemuMonitorCPUInfo, \
3078 &data) < 0) \
3079 ret = -1; \
3080 } while (0)
3082 DO_TEST(GetStatus);
3083 DO_TEST(GetVersion);
3084 DO_TEST(GetMachines);
3085 DO_TEST(GetCPUDefinitions);
3086 DO_TEST(GetCommands);
3087 DO_TEST(GetTPMModels);
3088 DO_TEST(GetCommandLineOptionParameters);
3089 if (qemuMonitorJSONTestAttachChardev(driver.xmlopt, qapiData.schema) < 0)
3090 ret = -1;
3091 DO_TEST(DetachChardev);
3092 DO_TEST(GetListPaths);
3093 DO_TEST(GetObjectProperty);
3094 DO_TEST(SetObjectProperty);
3095 DO_TEST(GetDeviceAliases);
3096 DO_TEST(CPU);
3097 DO_TEST(GetNonExistingCPUData);
3098 DO_TEST(GetIOThreads);
3099 DO_TEST_SIMPLE("qmp_capabilities", qemuMonitorJSONSetCapabilities);
3100 DO_TEST_SIMPLE("system_powerdown", qemuMonitorJSONSystemPowerdown);
3101 DO_TEST_SIMPLE("system_reset", qemuMonitorJSONSystemReset);
3102 DO_TEST_SIMPLE("migrate_cancel", qemuMonitorJSONMigrateCancel);
3103 DO_TEST_SIMPLE("inject-nmi", qemuMonitorJSONInjectNMI);
3104 DO_TEST_SIMPLE("system_wakeup", qemuMonitorJSONSystemWakeup);
3105 DO_TEST_SIMPLE("nbd-server-stop", qemuMonitorJSONNBDServerStop);
3106 DO_TEST_SIMPLE("rtc-reset-reinjection", qemuMonitorJSONRTCResetReinjection);
3107 DO_TEST_GEN(qemuMonitorJSONSetLink);
3108 DO_TEST_GEN(qemuMonitorJSONBlockResize);
3109 DO_TEST_GEN(qemuMonitorJSONSetPassword);
3110 DO_TEST_GEN(qemuMonitorJSONExpirePassword);
3111 DO_TEST_GEN(qemuMonitorJSONSetBalloon);
3112 DO_TEST_GEN(qemuMonitorJSONSetCPU);
3113 DO_TEST_GEN(qemuMonitorJSONEjectMedia);
3114 DO_TEST_GEN(qemuMonitorJSONChangeMedia);
3115 DO_TEST_GEN(qemuMonitorJSONSaveVirtualMemory);
3116 DO_TEST_GEN(qemuMonitorJSONSavePhysicalMemory);
3117 DO_TEST_GEN(qemuMonitorJSONSetMigrationSpeed);
3118 DO_TEST_GEN(qemuMonitorJSONSetMigrationDowntime);
3119 DO_TEST_GEN(qemuMonitorJSONMigrate);
3120 DO_TEST_GEN(qemuMonitorJSONDump);
3121 DO_TEST_GEN(qemuMonitorJSONGraphicsRelocate);
3122 DO_TEST_GEN(qemuMonitorJSONAddNetdev);
3123 DO_TEST_GEN(qemuMonitorJSONRemoveNetdev);
3124 DO_TEST_GEN(qemuMonitorJSONDelDevice);
3125 DO_TEST_GEN(qemuMonitorJSONAddDevice);
3126 DO_TEST_GEN(qemuMonitorJSONDriveMirror);
3127 DO_TEST_GEN(qemuMonitorJSONBlockdevMirror);
3128 DO_TEST_GEN(qemuMonitorJSONBlockStream);
3129 DO_TEST_GEN(qemuMonitorJSONBlockCommit);
3130 DO_TEST_GEN(qemuMonitorJSONDrivePivot);
3131 DO_TEST_GEN(qemuMonitorJSONScreendump);
3132 DO_TEST_GEN(qemuMonitorJSONOpenGraphics);
3133 DO_TEST_GEN(qemuMonitorJSONNBDServerAdd);
3134 DO_TEST_GEN(qemuMonitorJSONDetachCharDev);
3135 DO_TEST_GEN(qemuMonitorJSONBlockdevTrayOpen);
3136 DO_TEST_GEN(qemuMonitorJSONBlockdevTrayClose);
3137 DO_TEST_GEN(qemuMonitorJSONBlockdevMediumRemove);
3138 DO_TEST_GEN(qemuMonitorJSONBlockdevMediumInsert);
3139 DO_TEST_GEN(qemuMonitorJSONAddBitmap);
3140 DO_TEST_GEN(qemuMonitorJSONEnableBitmap);
3141 DO_TEST_GEN(qemuMonitorJSONDeleteBitmap);
3142 DO_TEST_GEN(qemuMonitorJSONJobDismiss);
3143 DO_TEST_GEN(qemuMonitorJSONJobCancel);
3144 DO_TEST_GEN(qemuMonitorJSONJobComplete);
3145 DO_TEST(qemuMonitorJSONGetBalloonInfo);
3146 DO_TEST(qemuMonitorJSONGetBlockInfo);
3147 DO_TEST(qemuMonitorJSONGetAllBlockStatsInfo);
3148 DO_TEST(qemuMonitorJSONGetMigrationCacheSize);
3149 DO_TEST(qemuMonitorJSONGetMigrationStats);
3150 DO_TEST(qemuMonitorJSONGetChardevInfo);
3151 DO_TEST(qemuMonitorJSONSetBlockIoThrottle);
3152 DO_TEST(qemuMonitorJSONGetTargetArch);
3153 DO_TEST(qemuMonitorJSONGetMigrationCapabilities);
3154 DO_TEST(qemuMonitorJSONQueryCPUs);
3155 DO_TEST(qemuMonitorJSONGetVirtType);
3156 DO_TEST(qemuMonitorJSONSendKey);
3157 DO_TEST(qemuMonitorJSONGetDumpGuestMemoryCapability);
3158 DO_TEST(qemuMonitorJSONSendKeyHoldtime);
3159 DO_TEST(qemuMonitorSupportsActiveCommit);
3160 DO_TEST(qemuMonitorJSONNBDServerStart);
3161 DO_TEST(qemuMonitorJSONMergeBitmaps);
3163 DO_TEST_CPU_DATA("host");
3164 DO_TEST_CPU_DATA("full");
3165 DO_TEST_CPU_DATA("ecx");
3167 DO_TEST_CPU_INFO("x86-basic-pluggable", 8);
3168 DO_TEST_CPU_INFO("x86-full", 11);
3169 DO_TEST_CPU_INFO("x86-node-full", 8);
3170 DO_TEST_CPU_INFO_FAST("x86-full-fast", 11);
3172 DO_TEST_CPU_INFO("ppc64-basic", 24);
3173 DO_TEST_CPU_INFO("ppc64-hotplug-1", 24);
3174 DO_TEST_CPU_INFO("ppc64-hotplug-2", 24);
3175 DO_TEST_CPU_INFO("ppc64-hotplug-4", 24);
3176 DO_TEST_CPU_INFO("ppc64-no-threads", 16);
3178 DO_TEST_CPU_INFO_FAST("s390-fast", 2);
3180 #define DO_TEST_BLOCK_NODE_DETECT(testname) \
3181 do { \
3182 if (virTestRun("node-name-detect(" testname ")", \
3183 testBlockNodeNameDetect, testname) < 0) \
3184 ret = -1; \
3185 } while (0)
3187 DO_TEST_BLOCK_NODE_DETECT("basic");
3188 DO_TEST_BLOCK_NODE_DETECT("same-backing");
3189 DO_TEST_BLOCK_NODE_DETECT("relative");
3190 DO_TEST_BLOCK_NODE_DETECT("gluster");
3191 DO_TEST_BLOCK_NODE_DETECT("blockjob");
3192 DO_TEST_BLOCK_NODE_DETECT("luks");
3193 DO_TEST_BLOCK_NODE_DETECT("iscsi");
3194 DO_TEST_BLOCK_NODE_DETECT("old");
3195 DO_TEST_BLOCK_NODE_DETECT("empty");
3197 #undef DO_TEST_BLOCK_NODE_DETECT
3199 #define DO_TEST_QAPI_QUERY(nme, qry, scc, rplobj) \
3200 do { \
3201 qapiData.name = nme; \
3202 qapiData.query = qry; \
3203 qapiData.rc = scc; \
3204 qapiData.replyobj = rplobj; \
3205 if (virTestRun("qapi schema query" nme, testQAPISchemaQuery, &qapiData) < 0)\
3206 ret = -1; \
3207 } while (0)
3209 DO_TEST_QAPI_QUERY("command", "blockdev-add", 1, true);
3210 DO_TEST_QAPI_QUERY("event", "RTC_CHANGE", 1, true);
3211 DO_TEST_QAPI_QUERY("object property", "screendump/arg-type/device", 1, true);
3212 DO_TEST_QAPI_QUERY("optional property", "block-commit/arg-type/*top", 1, true);
3213 DO_TEST_QAPI_QUERY("variant", "blockdev-add/arg-type/+file", 1, true);
3214 DO_TEST_QAPI_QUERY("variant property", "blockdev-add/arg-type/+file/filename", 1, true);
3215 DO_TEST_QAPI_QUERY("enum value", "query-status/ret-type/status/^debug", 1, false);
3216 DO_TEST_QAPI_QUERY("builtin type", "query-qmp-schema/ret-type/name/!string", 1, false);
3217 DO_TEST_QAPI_QUERY("alternate variant 1", "blockdev-add/arg-type/+qcow2/backing/!null", 1, false);
3218 DO_TEST_QAPI_QUERY("alternate variant 2", "blockdev-add/arg-type/+qcow2/backing/!string", 1, false);
3219 DO_TEST_QAPI_QUERY("alternate variant 3", "blockdev-add/arg-type/+qcow2/backing/+file/filename", 1, true);
3221 DO_TEST_QAPI_QUERY("nonexistent command", "nonexistent", 0, false);
3222 DO_TEST_QAPI_QUERY("nonexistent attr", "screendump/arg-type/nonexistent", 0, false);
3223 DO_TEST_QAPI_QUERY("nonexistent variant", "blockdev-add/arg-type/+nonexistent", 0, false);
3224 DO_TEST_QAPI_QUERY("nonexistent enum value", "query-status/ret-type/status/^nonexistentdebug", 0, false);
3225 DO_TEST_QAPI_QUERY("broken query for enum value", "query-status/ret-type/status/^debug/test", -1, false);
3226 DO_TEST_QAPI_QUERY("builtin type", "query-qmp-schema/ret-type/name/!number", 0, false);
3228 #undef DO_TEST_QAPI_QUERY
3231 #define DO_TEST_QAPI_VALIDATE(nme, rootquery, scc, jsonstr) \
3232 do { \
3233 qapiData.name = nme; \
3234 qapiData.query = rootquery; \
3235 qapiData.success = scc; \
3236 qapiData.json = jsonstr; \
3237 if (virTestRun("qapi schema validate" nme, testQAPISchemaValidate, &qapiData) < 0)\
3238 ret = -1; \
3239 } while (0)
3242 DO_TEST_QAPI_VALIDATE("string", "trace-event-get-state/arg-type", true,
3243 "{\"name\":\"test\"}");
3244 DO_TEST_QAPI_VALIDATE("all attrs", "trace-event-get-state/arg-type", true,
3245 "{\"name\":\"test\", \"vcpu\":123}");
3246 DO_TEST_QAPI_VALIDATE("attr type mismatch", "trace-event-get-state/arg-type", false,
3247 "{\"name\":123}");
3248 DO_TEST_QAPI_VALIDATE("missing mandatory attr", "trace-event-get-state/arg-type", false,
3249 "{\"vcpu\":123}");
3250 DO_TEST_QAPI_VALIDATE("attr name not present", "trace-event-get-state/arg-type", false,
3251 "{\"name\":\"test\", \"blah\":123}");
3252 DO_TEST_QAPI_VALIDATE("variant", "blockdev-add/arg-type", true,
3253 "{\"driver\":\"file\", \"filename\":\"ble\"}");
3254 DO_TEST_QAPI_VALIDATE("variant wrong", "blockdev-add/arg-type", false,
3255 "{\"driver\":\"filefilefilefile\", \"filename\":\"ble\"}");
3256 DO_TEST_QAPI_VALIDATE("variant missing mandatory", "blockdev-add/arg-type", false,
3257 "{\"driver\":\"file\", \"pr-manager\":\"ble\"}");
3258 DO_TEST_QAPI_VALIDATE("variant missing discriminator", "blockdev-add/arg-type", false,
3259 "{\"node-name\":\"dfgfdg\"}");
3260 DO_TEST_QAPI_VALIDATE("alternate 1", "blockdev-add/arg-type", true,
3261 "{\"driver\":\"qcow2\","
3262 "\"file\": { \"driver\":\"file\", \"filename\":\"ble\"}}");
3263 DO_TEST_QAPI_VALIDATE("alternate 2", "blockdev-add/arg-type", true,
3264 "{\"driver\":\"qcow2\",\"file\": \"somepath\"}");
3265 DO_TEST_QAPI_VALIDATE("alternate 2", "blockdev-add/arg-type", false,
3266 "{\"driver\":\"qcow2\",\"file\": 1234}");
3268 if (!(metaschema = testQEMUSchemaGetLatest()) ||
3269 !(metaschemastr = virJSONValueToString(metaschema, false))) {
3270 VIR_TEST_VERBOSE("failed to load latest qapi schema\n");
3271 ret = -1;
3272 goto cleanup;
3275 DO_TEST_QAPI_VALIDATE("schema-meta", "query-qmp-schema/ret-type", true,
3276 metaschemastr);
3279 #undef DO_TEST_QAPI_VALIDATE
3281 #define DO_TEST_QUERY_JOBS(name) \
3282 do { \
3283 struct testQueryJobsData data = { name, driver.xmlopt}; \
3284 if (virTestRun("query-jobs-" name, testQueryJobs, &data) < 0) \
3285 ret = -1; \
3286 } while (0)
3288 DO_TEST_QUERY_JOBS("empty");
3289 DO_TEST_QUERY_JOBS("create");
3291 #undef DO_TEST_QUERY_JOBS
3293 cleanup:
3294 VIR_FREE(metaschemastr);
3295 virJSONValueFree(metaschema);
3296 virHashFree(qapiData.schema);
3297 qemuTestDriverFree(&driver);
3298 return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
3301 VIR_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virdeterministichashmock.so")