Add missing libxml2-tools dependency
[archive/platform/upstream/libvirt.git] / tests / qemucapabilitiestest.c
1 /*
2  * Copyright (C) 2011-2013 Red Hat, Inc.
3  *
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.
8  *
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.
13  *
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/>.
17  *
18  */
19
20 #include <config.h>
21
22 #include "testutils.h"
23 #include "testutilsqemu.h"
24 #include "qemumonitortestutils.h"
25
26
27 #define VIR_FROM_THIS VIR_FROM_NONE
28
29 typedef struct _testQemuData testQemuData;
30 typedef testQemuData *testQemuDataPtr;
31 struct _testQemuData {
32     virDomainXMLOptionPtr xmlopt;
33     const char *base;
34     bool fips;
35 };
36
37 static qemuMonitorTestPtr
38 testQemuFeedMonitor(char *replies,
39                     virDomainXMLOptionPtr xmlopt)
40 {
41     qemuMonitorTestPtr test = NULL;
42     char *tmp = replies;
43     char *singleReply = tmp;
44
45     /* Our JSON parser expects replies to be separated by a newline character.
46      * Hence we must preprocess the file a bit. */
47     while ((tmp = strchr(tmp, '\n'))) {
48         /* It is safe to touch tmp[1] since all strings ends with '\0'. */
49         bool eof = !tmp[1];
50
51         if (*(tmp + 1) != '\n') {
52             *tmp = ' ';
53             tmp++;
54         } else {
55             /* Cut off a single reply. */
56             *(tmp + 1) = '\0';
57
58             if (test) {
59                 if (qemuMonitorTestAddItem(test, NULL, singleReply) < 0)
60                     goto error;
61             } else {
62                 /* Create new mocked monitor with our greeting */
63                 if (!(test = qemuMonitorTestNew(true, xmlopt, NULL, NULL, singleReply)))
64                     goto error;
65             }
66
67             if (!eof) {
68                 /* Move the @tmp and @singleReply. */
69                 tmp += 2;
70                 singleReply = tmp;
71             }
72         }
73
74         if (eof)
75             break;
76     }
77
78     if (test && qemuMonitorTestAddItem(test, NULL, singleReply) < 0)
79         goto error;
80
81     return test;
82
83  error:
84     qemuMonitorTestFree(test);
85     return NULL;
86 }
87
88 static virQEMUCapsPtr
89 testQemuGetCaps(char *caps)
90 {
91     virQEMUCapsPtr qemuCaps = NULL;
92     xmlDocPtr xml;
93     xmlXPathContextPtr ctxt = NULL;
94     ssize_t i, n;
95     xmlNodePtr *nodes = NULL;
96
97     if (!(xml = virXMLParseStringCtxt(caps, "(test caps)", &ctxt)))
98         goto error;
99
100     if ((n = virXPathNodeSet("/qemuCaps/flag", ctxt, &nodes)) < 0) {
101         fprintf(stderr, "failed to parse qemu capabilities flags");
102         goto error;
103     }
104
105     if (n > 0) {
106         if (!(qemuCaps = virQEMUCapsNew()))
107             goto error;
108
109         for (i = 0; i < n; i++) {
110             char *str = virXMLPropString(nodes[i], "name");
111             if (str) {
112                 int flag = virQEMUCapsTypeFromString(str);
113                 if (flag < 0) {
114                     fprintf(stderr, "Unknown qemu capabilities flag %s", str);
115                     VIR_FREE(str);
116                     goto error;
117                 }
118                 VIR_FREE(str);
119                 virQEMUCapsSet(qemuCaps, flag);
120             }
121         }
122     }
123
124     VIR_FREE(nodes);
125     xmlFreeDoc(xml);
126     xmlXPathFreeContext(ctxt);
127     return qemuCaps;
128
129  error:
130     VIR_FREE(nodes);
131     virObjectUnref(qemuCaps);
132     xmlFreeDoc(xml);
133     xmlXPathFreeContext(ctxt);
134     return NULL;
135 }
136
137 static int
138 testQemuCapsCompare(virQEMUCapsPtr capsProvided,
139                     virQEMUCapsPtr capsComputed)
140 {
141     int ret = 0;
142     size_t i;
143
144     for (i = 0; i < QEMU_CAPS_LAST; i++) {
145         if (virQEMUCapsGet(capsProvided, i) &&
146             !virQEMUCapsGet(capsComputed, i)) {
147             fprintf(stderr, "Caps mismatch: capsComputed is missing %s\n",
148                     virQEMUCapsTypeToString(i));
149             ret = -1;
150         }
151
152         if (virQEMUCapsGet(capsComputed, i) &&
153             !virQEMUCapsGet(capsProvided, i)) {
154             fprintf(stderr, "Caps mismatch: capsProvided is missing %s\n",
155                     virQEMUCapsTypeToString(i));
156             ret = -1;
157         }
158     }
159
160     return ret;
161 }
162
163 static int
164 testQemuCaps(const void *opaque)
165 {
166     int ret = -1;
167     const testQemuData *data = opaque;
168     char *repliesFile = NULL, *capsFile = NULL;
169     char *replies = NULL, *caps = NULL;
170     qemuMonitorTestPtr mon = NULL;
171     virQEMUCapsPtr capsProvided = NULL, capsComputed = NULL;
172
173     if (virAsprintf(&repliesFile, "%s/qemucapabilitiesdata/%s.replies",
174                     abs_srcdir, data->base) < 0 ||
175         virAsprintf(&capsFile, "%s/qemucapabilitiesdata/%s.caps",
176                     abs_srcdir, data->base) < 0)
177         goto cleanup;
178
179     if (virtTestLoadFile(repliesFile, &replies) < 0 ||
180         virtTestLoadFile(capsFile, &caps) < 0)
181         goto cleanup;
182
183     if (!(mon = testQemuFeedMonitor(replies, data->xmlopt)))
184         goto cleanup;
185
186     if (!(capsProvided = testQemuGetCaps(caps)))
187         goto cleanup;
188
189     if (!(capsComputed = virQEMUCapsNew()))
190         goto cleanup;
191
192     if (virQEMUCapsInitQMPMonitor(capsComputed,
193                                   qemuMonitorTestGetMonitor(mon)) < 0)
194         goto cleanup;
195
196     /* So that our test does not depend on the contents of /proc, we
197      * hoisted the setting of ENABLE_FIPS to virQEMUCapsInitQMP.  But
198      * we do want to test the effect of that flag.  */
199     if (data->fips)
200         virQEMUCapsSet(capsComputed, QEMU_CAPS_ENABLE_FIPS);
201
202     if (testQemuCapsCompare(capsProvided, capsComputed) < 0)
203         goto cleanup;
204
205     ret = 0;
206  cleanup:
207     VIR_FREE(repliesFile);
208     VIR_FREE(capsFile);
209     VIR_FREE(replies);
210     VIR_FREE(caps);
211     qemuMonitorTestFree(mon);
212     virObjectUnref(capsProvided);
213     virObjectUnref(capsComputed);
214     return ret;
215 }
216
217 static int
218 mymain(void)
219 {
220     int ret = 0;
221     virDomainXMLOptionPtr xmlopt;
222     testQemuData data;
223
224 #if !WITH_YAJL
225     fputs("libvirt not compiled with yajl, skipping this test\n", stderr);
226     return EXIT_AM_SKIP;
227 #endif
228
229     if (virThreadInitialize() < 0 ||
230         !(xmlopt = virQEMUDriverCreateXMLConf(NULL)))
231         return EXIT_FAILURE;
232
233     virEventRegisterDefaultImpl();
234
235     data.xmlopt = xmlopt;
236
237 #define DO_TEST_FULL(name, use_fips)                 \
238     data.base = name;                                \
239     data.fips = use_fips;                            \
240     if (virtTestRun(name, testQemuCaps, &data) < 0)  \
241         ret = -1
242
243 #define DO_TEST(name) DO_TEST_FULL(name, false)
244
245     DO_TEST_FULL("caps_1.2.2-1", true);
246     DO_TEST("caps_1.3.1-1");
247     DO_TEST("caps_1.4.2-1");
248     DO_TEST("caps_1.5.3-1");
249     DO_TEST_FULL("caps_1.6.0-1", true);
250     DO_TEST("caps_1.6.50-1");
251
252     virObjectUnref(xmlopt);
253     return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
254 }
255
256 VIRT_TEST_MAIN(mymain)