docs: Reword virDomainGetEmulatorPinInfo description
[libvirt.git] / tests / virschematest.c
blobe08ae2173893d3d393b8f611e8da7169dfacb2f6
1 /*
2 * Copyright (C) 2016 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/>.
19 #include <config.h>
22 #include "testutils.h"
24 #include "virlog.h"
25 #include "virxml.h"
27 #define VIR_FROM_THIS VIR_FROM_NONE
29 VIR_LOG_INIT("tests.schematest");
31 struct testSchemaEntry {
32 const char *dir;
33 /* if dirRegex is non-NULL the provided regular expression is used to match
34 * the file names in a directory (without path prefixed) and only matching
35 * files are validated */
36 const char **exceptions; /* optional NULL terminated list of filenames inside
37 directory where the expected validation result is
38 inverted */
39 const char **skip; /* optional NULL terminated list of files to skip altogether */
40 const char *dirRegex;
41 const char *file;
45 struct testSchemaData {
46 virXMLValidator *validator;
47 bool exception;
48 const char *xml_path;
52 static int
53 testSchemaValidateXML(const void *args)
55 const struct testSchemaData *data = args;
56 /* invalid XMLs have a '-invalid.' suffix, but not necessarily at the end
57 * of the file name e.g. in case of qemuxmlconftest with real capabilities */
58 bool shouldFail = !!strstr(data->xml_path, "-invalid.");
59 g_autoptr(xmlDoc) xml = NULL;
61 if (data->exception)
62 shouldFail = !shouldFail;
64 if (!(xml = virXMLParseFileCtxt(data->xml_path, NULL)))
65 return -1;
67 if ((virXMLValidatorValidate(data->validator, xml) < 0) != shouldFail)
68 return -1;
70 return 0;
74 static int
75 testSchemaFile(const char *schema,
76 virXMLValidator *validator,
77 const char *path,
78 bool exception)
80 g_autofree char *test_name = NULL;
81 struct testSchemaData data = {
82 .validator = validator,
83 .xml_path = path,
84 .exception = exception,
87 test_name = g_strdup_printf("Checking %s against %s", path, schema);
89 return virTestRun(test_name, testSchemaValidateXML, &data);
93 static int
94 testSchemaDir(const char *schema,
95 virXMLValidator *validator,
96 const char *dir_path,
97 const struct testSchemaEntry *entry)
99 g_autoptr(DIR) dir = NULL;
100 struct dirent *ent;
101 int ret = 0;
102 int rc;
103 g_autoptr(GRegex) filter = NULL;
105 if (virDirOpen(&dir, dir_path) < 0) {
106 virTestPropagateLibvirtError();
107 return -1;
110 if (entry->dirRegex) {
111 g_autoptr(GError) err = NULL;
113 if (!(filter = g_regex_new(entry->dirRegex, 0, 0, &err))) {
114 VIR_TEST_VERBOSE("\nfailed to compile regex '%s': %s", entry->dirRegex, err->message);
115 return -1;
119 while ((rc = virDirRead(dir, &ent, dir_path)) > 0) {
120 g_autofree char *xml_path = NULL;
121 bool exception = false;
123 if (!virStringHasSuffix(ent->d_name, ".xml"))
124 continue;
125 if (ent->d_name[0] == '.')
126 continue;
127 if (filter &&
128 !g_regex_match(filter, ent->d_name, 0, NULL))
129 continue;
131 if (entry->skip &&
132 g_strv_contains(entry->skip, ent->d_name))
133 continue;
135 xml_path = g_strdup_printf("%s/%s", dir_path, ent->d_name);
137 if (virFileIsLink(xml_path) == 1)
138 continue;
140 if (entry->exceptions)
141 exception = g_strv_contains(entry->exceptions, ent->d_name);
143 if (testSchemaFile(schema, validator, xml_path, exception) < 0)
144 ret = -1;
147 if (rc < 0) {
148 virTestPropagateLibvirtError();
149 ret = -1;
152 return ret;
157 * testSchemaGrammarReport:
159 * We need to parse the schema regardless since it's necessary also when tests
160 * are skipped using VIR_TEST_RANGE so this function merely reports whether the
161 * schema was parsed successfully via virTestRun.
163 static int
164 testSchemaGrammarReport(const void *opaque)
166 const virXMLValidator *validator = opaque;
168 if (!validator)
169 return -1;
171 return 0;
174 static virXMLValidator *
175 testSchemaGrammarLoad(const char *schema)
177 g_autofree char *testname = NULL;
178 virXMLValidator *ret;
180 ret = virXMLValidatorInit(schema);
182 testname = g_strdup_printf("test schema grammar file: '%s'", schema);
184 ignore_value(virTestRun(testname, testSchemaGrammarReport, ret));
186 return ret;
190 static int
191 testSchemaEntries(const char *schema,
192 const struct testSchemaEntry *entries,
193 size_t nentries)
195 g_autoptr(virXMLValidator) validator = NULL;
196 size_t i;
197 int ret = 0;
199 if (!(validator = testSchemaGrammarLoad(schema)))
200 return -1;
202 for (i = 0; i < nentries; i++) {
203 const struct testSchemaEntry *entry = entries + i;
205 if (!entry->file == !entry->dir) {
206 VIR_TEST_VERBOSE("\nmust specify exactly one of 'dir' and 'file' for struct testSchemaEntry\n");
207 ret = -1;
208 continue;
211 if (entry->dir) {
212 g_autofree char *path = g_strdup_printf("%s/%s", abs_top_srcdir, entry->dir);
214 if (testSchemaDir(schema, validator, path, entry) < 0)
215 ret = -1;
218 if (entry->file) {
219 g_autofree char *path = g_strdup_printf("%s/%s", abs_top_srcdir, entry->file);
221 if (testSchemaFile(schema, validator, path, false) < 0)
222 ret = -1;
226 return ret;
230 static const struct testSchemaEntry schemaCapability[] = {
231 { .dir = "tests/capabilityschemadata" },
232 { .dir = "tests/vircaps2xmldata" },
233 { .dir = "tests/qemucaps2xmloutdata" },
237 /* give exceptions for output files of invalid input XMLs */
238 static const char *exceptions_qemuxmlconfdata[] = {
239 "disk-cdrom-empty-network-invalid.x86_64-latest.xml",
240 "numatune-auto-nodeset-invalid.x86_64-latest.xml",
241 NULL
244 /* skip tests with completely broken XML */
245 static const char *skip_qemuxmlconfdata[] = {
246 "broken-xml-invalid.xml",
247 NULL
250 static const struct testSchemaEntry schemaDomain[] = {
251 { .dir = "tests/domainschemadata" },
252 { .dir = "tests/qemuxmlconfdata",
253 .exceptions = exceptions_qemuxmlconfdata,
254 .skip = skip_qemuxmlconfdata,
256 { .dir = "tests/xmconfigdata" },
257 { .dir = "tests/lxcxml2xmldata" },
258 { .dir = "tests/lxcxml2xmloutdata" },
259 { .dir = "tests/bhyvexml2argvdata" },
260 { .dir = "tests/bhyvexml2xmloutdata" },
261 { .dir = "tests/genericxml2xmlindata" },
262 { .dir = "tests/genericxml2xmloutdata" },
263 { .dir = "tests/xlconfigdata" },
264 { .dir = "tests/libxlxml2domconfigdata" },
265 { .dir = "tests/qemuhotplugtestdomains" },
266 { .dir = "examples/xml/test/",
267 .dirRegex = "testdom.*" },
268 { .dir = "tests/qemuhotplugtestcpus" },
269 { .dir = "tests/securityselinuxlabeldata" },
270 { .dir = "tests/domainconfdata" },
271 { .dir = "tests/lxcconf2xmldata" },
272 { .dir = "tests/qemumemlockdata" },
273 { .dir = "tests/vmx2xmldata" },
274 { .dir = "tests/xml2vmxdata" },
275 { .dir = "tests/bhyveargv2xmldata" },
276 { .dir = "tests/qemuagentdata" },
277 { .dir = "tests/chxml2xmlin" },
278 { .dir = "tests/chxml2xmlout" },
281 static const struct testSchemaEntry schemaDomainCaps[] = {
282 { .dir = "tests/domaincapsdata" },
285 static const struct testSchemaEntry schemaDomainBackup[] = {
286 { .dir = "tests/domainbackupxml2xmlin" },
287 { .dir = "tests/domainbackupxml2xmlout" },
290 static const struct testSchemaEntry schemaDomainCheckpoint[] = {
291 { .dir = "tests/qemudomaincheckpointxml2xmlin" },
292 { .dir = "tests/qemudomaincheckpointxml2xmlout" },
295 static const struct testSchemaEntry schemaDomainSnapshot[] = {
296 { .dir = "tests/qemudomainsnapshotxml2xmlin" },
297 { .dir = "tests/qemudomainsnapshotxml2xmlout" },
300 static const struct testSchemaEntry schemaInterface[] = {
301 { .dir = "tests/interfaceschemadata" },
304 static const struct testSchemaEntry schemaNetwork[] = {
305 { .dir = "src/network" },
306 { .dir = "tests/networkxml2xmlin" },
307 { .dir = "tests/networkxml2xmlout" },
308 { .dir = "tests/networkxml2confdata" },
309 { .dir = "examples/xml/test/",
310 .dirRegex = "testnet.*" },
311 { .dir = "tests/networkxml2xmlupdateout" },
312 { .dir = "tests/networkxml2firewalldata" },
315 static const struct testSchemaEntry schemaNetworkport[] = {
316 { .dir = "tests/virnetworkportxml2xmldata" },
319 static const struct testSchemaEntry schemaNodedev[] = {
320 { .dir = "tests/nodedevschemadata" },
321 { .dir = "tests/nodedevxml2xmlout" },
322 { .file = "examples/xml/test/testdev.xml" },
325 static const struct testSchemaEntry schemaNwfilter[] = {
326 { .dir = "tests/nwfilterxml2xmlout" },
327 { .dir = "src/nwfilter/xml" },
328 { .dir = "tests/nwfilterxml2xmlin" },
329 { .dir = "tests/nwfilterxml2firewalldata" },
332 static const struct testSchemaEntry schemaNwfilterbinding[] = {
333 { .dir = "tests/virnwfilterbindingxml2xmldata" },
336 static const struct testSchemaEntry schemaSecret[] = {
337 { .dir = "tests/secretxml2xmlin" },
340 static const struct testSchemaEntry schemaStoragepoolcaps[] = {
341 { .dir = "tests/storagepoolcapsschemadata" },
344 static const struct testSchemaEntry schemaStoragePool[] = {
345 { .dir = "tests/storagepoolxml2xmlin" },
346 { .dir = "tests/storagepoolxml2xmlout" },
347 { .dir = "tests/storagepoolschemadata" },
348 { .dir = "examples/xml/storage",
349 .dirRegex = "pool-.*" },
350 { .file = "examples/xml/test/testpool.xml" },
353 static const struct testSchemaEntry schemaStorageVol[] = {
354 { .dir = "tests/storagevolxml2xmlin" },
355 { .dir = "tests/storagevolxml2xmlout" },
356 { .dir = "tests/storagevolschemadata" },
357 { .dir = "examples/xml/storage",
358 .dirRegex = "vol-.*" },
359 { .file = "examples/xml/test/testvol.xml" },
362 static const struct testSchemaEntry testsCpuBaseline[] = {
363 { . dir = "tests/cputestdata" },
366 static const struct testSchemaEntry testDevice[] = {
367 { .dir = "tests/qemuhotplugtestdevices" },
368 { .dir = "tests/qemublocktestdata/imagecreate" },
369 { .dir = "tests/qemublocktestdata/xml2json" },
372 static int
373 mymain(void)
375 int ret = 0;
377 #define SCHEMAS_PATH abs_top_srcdir "/src/conf/schemas/"
378 #define INTERNAL_SCHEMAS_PATH abs_builddir "/schemas/"
380 #define DO_TEST(sch, ent) \
381 if (testSchemaEntries((sch), (ent), G_N_ELEMENTS(ent)) < 0) \
382 ret = -1;
384 DO_TEST(SCHEMAS_PATH "capability.rng", schemaCapability);
385 DO_TEST(SCHEMAS_PATH "domain.rng", schemaDomain);
386 DO_TEST(SCHEMAS_PATH "domaincaps.rng", schemaDomainCaps);
387 DO_TEST(SCHEMAS_PATH "domainbackup.rng", schemaDomainBackup);
388 DO_TEST(SCHEMAS_PATH "domaincheckpoint.rng", schemaDomainCheckpoint);
389 DO_TEST(SCHEMAS_PATH "domainsnapshot.rng", schemaDomainSnapshot);
390 DO_TEST(SCHEMAS_PATH "interface.rng", schemaInterface);
391 DO_TEST(SCHEMAS_PATH "network.rng", schemaNetwork);
392 DO_TEST(SCHEMAS_PATH "networkport.rng", schemaNetworkport);
393 DO_TEST(SCHEMAS_PATH "nodedev.rng", schemaNodedev);
394 DO_TEST(SCHEMAS_PATH "nwfilter.rng", schemaNwfilter);
395 DO_TEST(SCHEMAS_PATH "nwfilterbinding.rng", schemaNwfilterbinding);
396 DO_TEST(SCHEMAS_PATH "secret.rng", schemaSecret);
397 DO_TEST(SCHEMAS_PATH "storagepoolcaps.rng", schemaStoragepoolcaps);
398 DO_TEST(SCHEMAS_PATH "storagepool.rng", schemaStoragePool);
399 DO_TEST(SCHEMAS_PATH "storagevol.rng", schemaStorageVol);
401 DO_TEST(INTERNAL_SCHEMAS_PATH "cpu-baseline.rng", testsCpuBaseline);
402 DO_TEST(INTERNAL_SCHEMAS_PATH "device.rng", testDevice);
404 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
407 VIR_TEST_MAIN(mymain)