2016-06-07 19:54:43 +03:00
/*
* 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 " ) ;
2020-10-07 11:26:56 +03:00
struct testSchemaEntry {
const char * dir ;
2020-10-06 18:25:52 +03:00
/* if dirRegex is non-NULL the provided regular expression is used to match
* the file names in a directory ( without path prefixed ) and only matching
* files are validated */
const char * dirRegex ;
2020-10-07 11:26:56 +03:00
const char * file ;
} ;
2016-06-07 19:54:43 +03:00
struct testSchemaData {
2021-03-11 10:16:13 +03:00
virXMLValidator * validator ;
2016-06-07 19:54:43 +03:00
const char * xml_path ;
} ;
static int
2020-10-07 11:26:56 +03:00
testSchemaValidateXML ( const void * args )
2016-06-07 19:54:43 +03:00
{
const struct testSchemaData * data = args ;
2019-03-07 11:40:54 +03:00
bool shouldFail = virStringHasSuffix ( data - > xml_path , " -invalid.xml " ) ;
2020-10-07 11:26:56 +03:00
g_autoptr ( xmlDoc ) xml = NULL ;
2016-06-07 19:54:43 +03:00
if ( ! ( xml = virXMLParseFile ( data - > xml_path ) ) )
return - 1 ;
2020-10-07 11:26:56 +03:00
if ( ( virXMLValidatorValidate ( data - > validator , xml ) < 0 ) ! = shouldFail )
return - 1 ;
2016-06-07 19:54:43 +03:00
2020-10-07 11:26:56 +03:00
return 0 ;
}
static int
testSchemaFile ( const char * schema ,
2021-03-11 10:16:13 +03:00
virXMLValidator * validator ,
2020-10-07 11:26:56 +03:00
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 ) ;
2016-06-07 19:54:43 +03:00
}
static int
testSchemaDir ( const char * schema ,
2021-03-11 10:16:13 +03:00
virXMLValidator * validator ,
2020-10-06 18:25:52 +03:00
const char * dir_path ,
const char * filterstr )
2016-06-07 19:54:43 +03:00
{
2020-10-26 00:50:51 +03:00
g_autoptr ( DIR ) dir = NULL ;
2016-06-07 19:54:43 +03:00
struct dirent * ent ;
int ret = 0 ;
int rc ;
2020-10-06 18:25:52 +03:00
g_autoptr ( GRegex ) filter = NULL ;
2016-06-07 19:54:43 +03:00
2019-11-19 13:55:05 +03:00
if ( virDirOpen ( & dir , dir_path ) < 0 ) {
virTestPropagateLibvirtError ( ) ;
2016-06-07 19:54:43 +03:00
return - 1 ;
2019-11-19 13:55:05 +03:00
}
2016-06-07 19:54:43 +03:00
2020-10-06 18:25:52 +03:00
if ( filterstr ) {
g_autoptr ( GError ) err = NULL ;
if ( ! ( filter = g_regex_new ( filterstr , 0 , 0 , & err ) ) ) {
VIR_TEST_VERBOSE ( " \n failed to compile regex '%s': %s " , filterstr , err - > message ) ;
return - 1 ;
}
}
2016-06-07 19:54:43 +03:00
while ( ( rc = virDirRead ( dir , & ent , dir_path ) ) > 0 ) {
2019-11-19 13:16:34 +03:00
g_autofree char * xml_path = NULL ;
2019-03-07 11:40:54 +03:00
if ( ! virStringHasSuffix ( ent - > d_name , " .xml " ) )
2016-06-07 19:54:43 +03:00
continue ;
2018-12-17 16:17:26 +03:00
if ( ent - > d_name [ 0 ] = = ' . ' )
continue ;
2020-10-06 18:25:52 +03:00
if ( filter & &
! g_regex_match ( filter , ent - > d_name , 0 , NULL ) )
continue ;
2016-06-07 19:54:43 +03:00
2019-10-22 16:26:14 +03:00
xml_path = g_strdup_printf ( " %s/%s " , dir_path , ent - > d_name ) ;
2016-06-07 19:54:43 +03:00
2020-10-07 11:26:56 +03:00
if ( testSchemaFile ( schema , validator , xml_path ) < 0 )
2016-06-07 19:54:43 +03:00
ret = - 1 ;
}
2019-11-19 13:55:05 +03:00
if ( rc < 0 ) {
virTestPropagateLibvirtError ( ) ;
2016-06-07 19:54:43 +03:00
ret = - 1 ;
2019-11-19 13:55:05 +03:00
}
2016-06-07 19:54:43 +03:00
return ret ;
}
2020-10-07 11:26:56 +03:00
/**
* 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 .
*/
2016-06-07 19:54:43 +03:00
static int
2020-10-07 11:26:56 +03:00
testSchemaGrammarReport ( const void * opaque )
2016-06-07 19:54:43 +03:00
{
2020-10-07 11:26:56 +03:00
const virXMLValidator * validator = opaque ;
2016-06-07 19:54:43 +03:00
2020-10-07 11:26:56 +03:00
if ( ! validator )
return - 1 ;
2016-06-07 19:54:43 +03:00
2020-10-07 11:26:56 +03:00
return 0 ;
}
2021-03-11 10:16:13 +03:00
static virXMLValidator *
2020-10-07 11:26:56 +03:00
testSchemaGrammarLoad ( const char * schema )
{
g_autofree char * schema_path = NULL ;
g_autofree char * testname = NULL ;
2021-03-11 10:16:13 +03:00
virXMLValidator * ret ;
2020-10-07 11:26:56 +03:00
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 ) ) ;
2016-06-07 19:54:43 +03:00
return ret ;
}
2016-08-02 10:11:33 +03:00
static int
2020-10-07 11:26:56 +03:00
testSchemaEntries ( const char * schema ,
const struct testSchemaEntry * entries ,
size_t nentries )
2016-08-02 10:11:33 +03:00
{
2020-10-07 11:26:56 +03:00
g_autoptr ( virXMLValidator ) validator = NULL ;
size_t i ;
int ret = 0 ;
2016-08-02 10:11:33 +03:00
2020-10-07 11:26:56 +03:00
if ( ! ( validator = testSchemaGrammarLoad ( schema ) ) )
2019-11-19 13:16:34 +03:00
return - 1 ;
2016-08-02 10:11:33 +03:00
2020-10-07 11:26:56 +03:00
for ( i = 0 ; i < nentries ; i + + ) {
const struct testSchemaEntry * entry = entries + i ;
if ( ! entry - > file = = ! entry - > dir ) {
VIR_TEST_VERBOSE ( " \n must 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 ) ;
2020-10-06 18:25:52 +03:00
if ( testSchemaDir ( schema , validator , path , entry - > dirRegex ) < 0 )
2020-10-07 11:26:56 +03:00
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 ;
2016-08-02 10:11:33 +03:00
}
2020-10-07 11:26:56 +03:00
static const struct testSchemaEntry schemaCapability [ ] = {
{ . dir = " tests/capabilityschemadata " } ,
{ . dir = " tests/vircaps2xmldata " } ,
2020-10-07 14:58:24 +03:00
{ . dir = " tests/qemucaps2xmloutdata " } ,
2020-10-07 11:26:56 +03:00
} ;
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 " } ,
2020-10-06 18:28:44 +03:00
{ . dir = " examples/xml/test/ " ,
. dirRegex = " testdom.* " } ,
2020-10-07 12:40:39 +03:00
{ . dir = " tests/qemuhotplugtestcpus " } ,
{ . dir = " tests/securityselinuxlabeldata " } ,
{ . dir = " tests/domainconfdata " } ,
{ . dir = " tests/lxcconf2xmldata " } ,
{ . dir = " tests/qemumemlockdata " } ,
{ . dir = " tests/vmx2xmldata " } ,
{ . dir = " tests/xml2vmxdata " } ,
{ . dir = " tests/bhyveargv2xmldata " } ,
{ . dir = " tests/qemuagentdata " } ,
2020-10-07 11:26:56 +03:00
} ;
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 " } ,
2020-10-06 18:28:44 +03:00
{ . dir = " examples/xml/test/ " ,
. dirRegex = " testnet.* " } ,
2020-10-07 14:58:24 +03:00
{ . dir = " tests/networkxml2xmlupdateout " } ,
{ . dir = " tests/networkxml2firewalldata " } ,
2020-10-07 11:26:56 +03:00
} ;
static const struct testSchemaEntry schemaNetworkport [ ] = {
{ . dir = " tests/virnetworkportxml2xmldata " } ,
} ;
static const struct testSchemaEntry schemaNodedev [ ] = {
{ . dir = " tests/nodedevschemadata " } ,
2020-10-06 18:28:44 +03:00
{ . file = " examples/xml/test/testdev.xml " } ,
2020-10-07 11:26:56 +03:00
} ;
static const struct testSchemaEntry schemaNwfilter [ ] = {
{ . dir = " tests/nwfilterxml2xmlout " } ,
2020-10-07 12:33:30 +03:00
{ . dir = " src/nwfilter/xml " } ,
2020-10-07 14:58:24 +03:00
{ . dir = " tests/nwfilterxml2xmlin " } ,
{ . dir = " tests/nwfilterxml2firewalldata " } ,
2020-10-07 11:26:56 +03:00
} ;
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 " } ,
2020-10-06 18:28:44 +03:00
{ . dir = " examples/xml/storage " ,
. dirRegex = " pool-.* " } ,
2020-10-06 18:28:44 +03:00
{ . file = " examples/xml/test/testpool.xml " } ,
2020-10-07 11:26:56 +03:00
} ;
static const struct testSchemaEntry schemaStorageVol [ ] = {
{ . dir = " tests/storagevolxml2xmlin " } ,
{ . dir = " tests/storagevolxml2xmlout " } ,
{ . dir = " tests/storagevolschemadata " } ,
2020-10-06 18:28:44 +03:00
{ . dir = " examples/xml/storage " ,
. dirRegex = " vol-.* " } ,
2020-10-06 18:28:44 +03:00
{ . file = " examples/xml/test/testvol.xml " } ,
2020-10-07 11:26:56 +03:00
} ;
2020-10-07 17:52:14 +03:00
static const struct testSchemaEntry schemaCpu [ ] = {
{ . dir = " tests/cputestdata " ,
. dirRegex = " ^[^-]+-cpuid-.*(-host|-guest|-json) \\ .xml$ " } ,
{ . dir = " tests/cputestdata " ,
. dirRegex = " ^[^-]+-baseline-.*-result \\ .xml$ " } ,
{ . dir = " tests/cputestdata " ,
. dirRegex = " ^[^-]+-(?!cpuid|baseline).*$ " } ,
} ;
2020-10-07 11:26:56 +03:00
2016-06-07 19:54:43 +03:00
static int
mymain ( void )
{
int ret = 0 ;
2020-10-07 11:26:56 +03:00
# 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 ) ;
2020-10-07 17:52:14 +03:00
DO_TEST ( " docs/schemas/cpu.rng " , schemaCpu ) ;
2016-06-07 19:54:43 +03:00
return ret = = 0 ? EXIT_SUCCESS : EXIT_FAILURE ;
}
2017-03-29 17:45:42 +03:00
VIR_TEST_MAIN ( mymain )