mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-07-12 12:55:46 +00:00
To allow greater variablitity of XML schema validation tests without needlessly reparsing the schema we need to refactor the internals to pass in structs rather than just paths to directory. This allows to directly implement testing of single files and will simplify further additions such as filtering of the list of XML files in a directory. The list of tested paths is directly ported for now and will be improved in follow-up patches. Signed-off-by: Peter Krempa <pkrempa@redhat.com> Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
314 lines
8.5 KiB
C
314 lines
8.5 KiB
C
/*
|
|
* Copyright (C) 2016 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
|
|
#include "testutils.h"
|
|
|
|
#include "virerror.h"
|
|
#include "viralloc.h"
|
|
#include "virlog.h"
|
|
#include "virxml.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
VIR_LOG_INIT("tests.schematest");
|
|
|
|
struct testSchemaEntry {
|
|
const char *dir;
|
|
const char *file;
|
|
};
|
|
|
|
|
|
struct testSchemaData {
|
|
virXMLValidatorPtr validator;
|
|
const char *xml_path;
|
|
};
|
|
|
|
|
|
static int
|
|
testSchemaValidateXML(const void *args)
|
|
{
|
|
const struct testSchemaData *data = args;
|
|
bool shouldFail = virStringHasSuffix(data->xml_path, "-invalid.xml");
|
|
g_autoptr(xmlDoc) xml = NULL;
|
|
|
|
if (!(xml = virXMLParseFile(data->xml_path)))
|
|
return -1;
|
|
|
|
if ((virXMLValidatorValidate(data->validator, xml) < 0) != shouldFail)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
testSchemaFile(const char *schema,
|
|
virXMLValidatorPtr validator,
|
|
const char *path)
|
|
{
|
|
g_autofree char *test_name = NULL;
|
|
struct testSchemaData data = {
|
|
.validator = validator,
|
|
.xml_path = path,
|
|
};
|
|
|
|
test_name = g_strdup_printf("Checking %s against %s", path, schema);
|
|
|
|
return virTestRun(test_name, testSchemaValidateXML, &data);
|
|
}
|
|
|
|
|
|
static int
|
|
testSchemaDir(const char *schema,
|
|
virXMLValidatorPtr validator,
|
|
const char *dir_path)
|
|
{
|
|
DIR *dir = NULL;
|
|
struct dirent *ent;
|
|
int ret = 0;
|
|
int rc;
|
|
|
|
if (virDirOpen(&dir, dir_path) < 0) {
|
|
virTestPropagateLibvirtError();
|
|
return -1;
|
|
}
|
|
|
|
while ((rc = virDirRead(dir, &ent, dir_path)) > 0) {
|
|
g_autofree char *xml_path = NULL;
|
|
|
|
if (!virStringHasSuffix(ent->d_name, ".xml"))
|
|
continue;
|
|
if (ent->d_name[0] == '.')
|
|
continue;
|
|
|
|
xml_path = g_strdup_printf("%s/%s", dir_path, ent->d_name);
|
|
|
|
if (testSchemaFile(schema, validator, xml_path) < 0)
|
|
ret = -1;
|
|
}
|
|
|
|
if (rc < 0) {
|
|
virTestPropagateLibvirtError();
|
|
ret = -1;
|
|
}
|
|
|
|
VIR_DIR_CLOSE(dir);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
* testSchemaGrammarReport:
|
|
*
|
|
* We need to parse the schema regardless since it's necessary also when tests
|
|
* are skipped using VIR_TEST_RANGE so this function merely reports whether the
|
|
* schema was parsed successfully via virTestRun.
|
|
*/
|
|
static int
|
|
testSchemaGrammarReport(const void *opaque)
|
|
{
|
|
const virXMLValidator *validator = opaque;
|
|
|
|
if (!validator)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static virXMLValidatorPtr
|
|
testSchemaGrammarLoad(const char *schema)
|
|
{
|
|
g_autofree char *schema_path = NULL;
|
|
g_autofree char *testname = NULL;
|
|
virXMLValidatorPtr ret;
|
|
|
|
schema_path = g_strdup_printf("%s/%s", abs_top_srcdir, schema);
|
|
|
|
ret = virXMLValidatorInit(schema_path);
|
|
|
|
testname = g_strdup_printf("test schema grammar file: '%s'", schema);
|
|
|
|
ignore_value(virTestRun(testname, testSchemaGrammarReport, ret));
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int
|
|
testSchemaEntries(const char *schema,
|
|
const struct testSchemaEntry *entries,
|
|
size_t nentries)
|
|
{
|
|
g_autoptr(virXMLValidator) validator = NULL;
|
|
size_t i;
|
|
int ret = 0;
|
|
|
|
if (!(validator = testSchemaGrammarLoad(schema)))
|
|
return -1;
|
|
|
|
for (i = 0; i < nentries; i++) {
|
|
const struct testSchemaEntry *entry = entries + i;
|
|
|
|
if (!entry->file == !entry->dir) {
|
|
VIR_TEST_VERBOSE("\nmust specify exactly one of 'dir' and 'file' for struct testSchemaEntry\n");
|
|
ret = -1;
|
|
continue;
|
|
}
|
|
|
|
if (entry->dir) {
|
|
g_autofree char *path = g_strdup_printf("%s/%s", abs_top_srcdir, entry->dir);
|
|
|
|
if (testSchemaDir(schema, validator, path) < 0)
|
|
ret = -1;
|
|
}
|
|
|
|
if (entry->file) {
|
|
g_autofree char *path = g_strdup_printf("%s/%s", abs_top_srcdir, entry->file);
|
|
|
|
if (testSchemaFile(schema, validator, path) < 0)
|
|
ret = -1;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static const struct testSchemaEntry schemaCapability[] = {
|
|
{ .dir = "tests/capabilityschemadata" },
|
|
{ .dir = "tests/vircaps2xmldata" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaDomain[] = {
|
|
{ .dir = "tests/domainschemadata" },
|
|
{ .dir = "tests/qemuxml2argvdata" },
|
|
{ .dir = "tests/xmconfigdata" },
|
|
{ .dir = "tests/qemuxml2xmloutdata" },
|
|
{ .dir = "tests/lxcxml2xmldata" },
|
|
{ .dir = "tests/lxcxml2xmloutdata" },
|
|
{ .dir = "tests/bhyvexml2argvdata" },
|
|
{ .dir = "tests/bhyvexml2xmloutdata" },
|
|
{ .dir = "tests/genericxml2xmlindata" },
|
|
{ .dir = "tests/genericxml2xmloutdata" },
|
|
{ .dir = "tests/xlconfigdata" },
|
|
{ .dir = "tests/libxlxml2domconfigdata" },
|
|
{ .dir = "tests/qemuhotplugtestdomains" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaDomainCaps[] = {
|
|
{ .dir = "tests/domaincapsdata" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaDomainBackup[] = {
|
|
{ .dir = "tests/domainbackupxml2xmlin" },
|
|
{ .dir = "tests/domainbackupxml2xmlout" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaDomainCheckpoint[] = {
|
|
{ .dir = "tests/qemudomaincheckpointxml2xmlin" },
|
|
{ .dir = "tests/qemudomaincheckpointxml2xmlout" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaDomainSnapshot[] = {
|
|
{ .dir = "tests/qemudomainsnapshotxml2xmlin" },
|
|
{ .dir = "tests/qemudomainsnapshotxml2xmlout" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaInterface[] = {
|
|
{ .dir = "tests/interfaceschemadata" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaNetwork[] = {
|
|
{ .dir = "src/network" },
|
|
{ .dir = "tests/networkxml2xmlin" },
|
|
{ .dir = "tests/networkxml2xmlout" },
|
|
{ .dir = "tests/networkxml2confdata" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaNetworkport[] = {
|
|
{ .dir = "tests/virnetworkportxml2xmldata" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaNodedev[] = {
|
|
{ .dir = "tests/nodedevschemadata" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaNwfilter[] = {
|
|
{ .dir = "tests/nwfilterxml2xmlout" },
|
|
{ .dir = "src/nwfilter" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaNwfilterbinding[] = {
|
|
{ .dir = "tests/virnwfilterbindingxml2xmldata" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaSecret[] = {
|
|
{ .dir = "tests/secretxml2xmlin" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaStoragepoolcaps[] = {
|
|
{ .dir = "tests/storagepoolcapsschemadata" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaStoragePool[] = {
|
|
{ .dir = "tests/storagepoolxml2xmlin" },
|
|
{ .dir = "tests/storagepoolxml2xmlout" },
|
|
{ .dir = "tests/storagepoolschemadata" },
|
|
};
|
|
|
|
static const struct testSchemaEntry schemaStorageVol[] = {
|
|
{ .dir = "tests/storagevolxml2xmlin" },
|
|
{ .dir = "tests/storagevolxml2xmlout" },
|
|
{ .dir = "tests/storagevolschemadata" },
|
|
};
|
|
|
|
|
|
static int
|
|
mymain(void)
|
|
{
|
|
int ret = 0;
|
|
|
|
#define DO_TEST(sch, ent) \
|
|
if (testSchemaEntries((sch), (ent), G_N_ELEMENTS(ent)) < 0) \
|
|
ret = -1;
|
|
|
|
DO_TEST("docs/schemas/capability.rng", schemaCapability);
|
|
DO_TEST("docs/schemas/domain.rng", schemaDomain);
|
|
DO_TEST("docs/schemas/domaincaps.rng", schemaDomainCaps);
|
|
DO_TEST("docs/schemas/domainbackup.rng", schemaDomainBackup);
|
|
DO_TEST("docs/schemas/domaincheckpoint.rng", schemaDomainCheckpoint);
|
|
DO_TEST("docs/schemas/domainsnapshot.rng", schemaDomainSnapshot);
|
|
DO_TEST("docs/schemas/interface.rng", schemaInterface);
|
|
DO_TEST("docs/schemas/network.rng", schemaNetwork);
|
|
DO_TEST("docs/schemas/networkport.rng", schemaNetworkport);
|
|
DO_TEST("docs/schemas/nodedev.rng", schemaNodedev);
|
|
DO_TEST("docs/schemas/nwfilter.rng", schemaNwfilter);
|
|
DO_TEST("docs/schemas/nwfilterbinding.rng", schemaNwfilterbinding);
|
|
DO_TEST("docs/schemas/secret.rng", schemaSecret);
|
|
DO_TEST("docs/schemas/storagepoolcaps.rng", schemaStoragepoolcaps);
|
|
DO_TEST("docs/schemas/storagepool.rng", schemaStoragePool);
|
|
DO_TEST("docs/schemas/storagevol.rng", schemaStorageVol);
|
|
|
|
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
|
}
|
|
|
|
VIR_TEST_MAIN(mymain)
|