2011-09-23 00:29:00 +04:00
# include <config.h>
# include <unistd.h>
# include <sys/types.h>
# include <fcntl.h>
2013-12-04 17:53:24 +04:00
# include <regex.h>
2013-04-16 17:41:44 +04:00
# include "testutils.h"
2011-09-23 00:29:00 +04:00
# ifdef WITH_QEMU
# include "internal.h"
# include "qemu / qemu_conf.h"
# include "qemu / qemu_domain.h"
# include "testutilsqemu.h"
2013-04-03 14:36:23 +04:00
# include "virstring.h"
2011-09-23 00:29:00 +04:00
2013-06-07 19:10:28 +04:00
# define VIR_FROM_THIS VIR_FROM_NONE
2012-11-28 20:43:10 +04:00
static virQEMUDriver driver ;
2011-09-23 00:29:00 +04:00
2013-12-04 17:53:24 +04:00
/* This regex will skip the following XML constructs in test files
* that are dynamically generated and thus problematic to test :
* < name > 1234352345 < / name > if the snapshot has no name ,
* < creationTime > 23523452345 < / creationTime > ,
* < state > nostate < / state > as the backend code doesn ' t fill this
*/
static const char * testSnapshotXMLVariableLineRegexStr =
" (<(name|creationTime)>[0-9]+</(name|creationTime)>| "
" <state>nostate</state>) " ;
regex_t * testSnapshotXMLVariableLineRegex = NULL ;
2019-04-15 22:49:30 +03:00
enum {
TEST_INTERNAL = 1 < < 0 , /* Test use of INTERNAL parse/format flag */
TEST_REDEFINE = 1 < < 1 , /* Test use of REDEFINE parse flag */
} ;
2013-12-04 17:53:24 +04:00
static char *
testFilterXML ( char * xml )
{
virBuffer buf = VIR_BUFFER_INITIALIZER ;
char * * xmlLines = NULL ;
char * * xmlLine ;
char * ret = NULL ;
if ( ! ( xmlLines = virStringSplit ( xml , " \n " , 0 ) ) ) {
VIR_FREE ( xml ) ;
goto cleanup ;
}
VIR_FREE ( xml ) ;
for ( xmlLine = xmlLines ; * xmlLine ; xmlLine + + ) {
if ( regexec ( testSnapshotXMLVariableLineRegex ,
* xmlLine , 0 , NULL , 0 ) = = 0 )
continue ;
virBufferStrcat ( & buf , * xmlLine , " \n " , NULL ) ;
}
2014-06-27 12:40:15 +04:00
if ( virBufferCheckError ( & buf ) < 0 )
2013-12-04 17:53:24 +04:00
goto cleanup ;
ret = virBufferContentAndReset ( & buf ) ;
2014-03-25 10:53:44 +04:00
cleanup :
2013-12-04 17:53:24 +04:00
virBufferFreeAndReset ( & buf ) ;
2016-11-25 11:18:35 +03:00
virStringListFree ( xmlLines ) ;
2013-12-04 17:53:24 +04:00
return ret ;
}
2011-09-23 00:29:00 +04:00
static int
2013-12-04 17:53:24 +04:00
testCompareXMLToXMLFiles ( const char * inxml ,
const char * outxml ,
const char * uuid ,
2019-04-15 22:49:30 +03:00
unsigned int flags )
2011-09-23 00:29:00 +04:00
{
char * inXmlData = NULL ;
2013-12-04 17:53:24 +04:00
char * outXmlData = NULL ;
2011-09-23 00:29:00 +04:00
char * actual = NULL ;
int ret = - 1 ;
virDomainSnapshotDefPtr def = NULL ;
2019-02-15 23:43:43 +03:00
unsigned int parseflags = VIR_DOMAIN_SNAPSHOT_PARSE_DISKS ;
unsigned int formatflags = VIR_DOMAIN_SNAPSHOT_FORMAT_SECURE ;
2019-04-15 22:49:30 +03:00
bool cur = false ;
2013-12-04 17:53:24 +04:00
2019-04-15 22:49:30 +03:00
if ( flags & TEST_INTERNAL ) {
2019-02-15 23:43:43 +03:00
parseflags | = VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL ;
formatflags | = VIR_DOMAIN_SNAPSHOT_FORMAT_INTERNAL ;
}
2013-12-04 17:53:24 +04:00
2019-04-15 22:49:30 +03:00
if ( flags & TEST_REDEFINE )
2019-02-15 23:43:43 +03:00
parseflags | = VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE ;
2011-09-23 00:29:00 +04:00
2016-05-26 18:01:52 +03:00
if ( virTestLoadFile ( inxml , & inXmlData ) < 0 )
2013-12-04 16:49:40 +04:00
goto cleanup ;
2011-09-23 00:29:00 +04:00
2016-05-26 18:01:52 +03:00
if ( virTestLoadFile ( outxml , & outXmlData ) < 0 )
2013-12-04 17:53:24 +04:00
goto cleanup ;
2011-09-23 00:29:00 +04:00
if ( ! ( def = virDomainSnapshotDefParseString ( inXmlData , driver . caps ,
snapshot: Drop virDomainSnapshotDef.current
The only use for the 'current' member of virDomainSnapshotDef was with
the PARSE/FORMAT_INTERNAL flag for controlling an internal-use
<active> element marking whether a particular snapshot definition was
current, and even then, only by the qemu driver on output, and by qemu
and test driver on input. But this duplicates vm->snapshot_current,
and gets in the way of potential simplifications to have qemu store a
single file for all snapshots rather than one file per snapshot. Get
rid of the member by adding a bool* parameter during parse (ignored if
the PARSE_INTERNAL flag is not set), and by adding a new flag during
format (if FORMAT_INTERNAL is set, the value printed in <active>
depends on the new FORMAT_CURRENT).
Then update the qemu driver accordingly, which involves hoisting
assignments to vm->current_snapshot to occur prior to any point where
a snapshot XML file is written (although qemu kept
vm->current_snapshot and snapshot->def_current in sync by the end of
the function, they were not always identical in the middle of
functions, so the shuffling gets a bit interesting). Later patches
will clean up some of that confusing churn to vm->current_snapshot.
Note: even if later patches refactor qemu to no longer use
FORMAT_INTERNAL for output (by storing bulk snapshot XML instead), we
will always need PARSE_INTERNAL for input (because on upgrade, a new
libvirt still has to parse XML left from a previous libvirt).
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
2019-03-19 06:56:19 +03:00
driver . xmlopt , & cur ,
2019-02-15 23:43:43 +03:00
parseflags ) ) )
2013-12-04 16:49:40 +04:00
goto cleanup ;
2019-04-15 22:49:30 +03:00
if ( cur ) {
if ( ! ( flags & TEST_INTERNAL ) )
goto cleanup ;
snapshot: Drop virDomainSnapshotDef.current
The only use for the 'current' member of virDomainSnapshotDef was with
the PARSE/FORMAT_INTERNAL flag for controlling an internal-use
<active> element marking whether a particular snapshot definition was
current, and even then, only by the qemu driver on output, and by qemu
and test driver on input. But this duplicates vm->snapshot_current,
and gets in the way of potential simplifications to have qemu store a
single file for all snapshots rather than one file per snapshot. Get
rid of the member by adding a bool* parameter during parse (ignored if
the PARSE_INTERNAL flag is not set), and by adding a new flag during
format (if FORMAT_INTERNAL is set, the value printed in <active>
depends on the new FORMAT_CURRENT).
Then update the qemu driver accordingly, which involves hoisting
assignments to vm->current_snapshot to occur prior to any point where
a snapshot XML file is written (although qemu kept
vm->current_snapshot and snapshot->def_current in sync by the end of
the function, they were not always identical in the middle of
functions, so the shuffling gets a bit interesting). Later patches
will clean up some of that confusing churn to vm->current_snapshot.
Note: even if later patches refactor qemu to no longer use
FORMAT_INTERNAL for output (by storing bulk snapshot XML instead), we
will always need PARSE_INTERNAL for input (because on upgrade, a new
libvirt still has to parse XML left from a previous libvirt).
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
2019-03-19 06:56:19 +03:00
formatflags | = VIR_DOMAIN_SNAPSHOT_FORMAT_CURRENT ;
2019-04-15 22:49:30 +03:00
}
2011-09-23 00:29:00 +04:00
2016-02-05 01:55:05 +03:00
if ( ! ( actual = virDomainSnapshotDefFormat ( uuid , def , driver . caps ,
2017-06-02 01:27:33 +03:00
driver . xmlopt ,
2019-02-15 23:43:43 +03:00
formatflags ) ) )
2013-12-04 16:49:40 +04:00
goto cleanup ;
2011-09-23 00:29:00 +04:00
2019-04-15 22:49:30 +03:00
if ( ! ( flags & TEST_REDEFINE ) ) {
2013-12-04 17:53:24 +04:00
if ( ! ( actual = testFilterXML ( actual ) ) )
goto cleanup ;
if ( ! ( outXmlData = testFilterXML ( outXmlData ) ) )
goto cleanup ;
}
2011-09-23 00:29:00 +04:00
2013-12-04 17:53:24 +04:00
if ( STRNEQ ( outXmlData , actual ) ) {
2016-05-26 18:01:54 +03:00
virTestDifferenceFull ( stderr , outXmlData , outxml , actual , inxml ) ;
2013-12-04 16:49:40 +04:00
goto cleanup ;
2011-09-23 00:29:00 +04:00
}
ret = 0 ;
2013-12-04 16:49:40 +04:00
2014-03-25 10:53:44 +04:00
cleanup :
2012-02-03 03:16:43 +04:00
VIR_FREE ( inXmlData ) ;
2013-12-04 17:53:24 +04:00
VIR_FREE ( outXmlData ) ;
2012-02-03 03:16:43 +04:00
VIR_FREE ( actual ) ;
2011-09-23 00:29:00 +04:00
virDomainSnapshotDefFree ( def ) ;
return ret ;
}
struct testInfo {
2013-12-04 17:53:24 +04:00
const char * inxml ;
const char * outxml ;
2011-09-23 00:29:00 +04:00
const char * uuid ;
2019-04-15 22:49:30 +03:00
unsigned int flags ;
2011-09-23 00:29:00 +04:00
} ;
2013-12-04 16:49:40 +04:00
2011-09-23 00:29:00 +04:00
static int
testCompareXMLToXMLHelper ( const void * data )
{
const struct testInfo * info = data ;
2013-12-04 17:53:24 +04:00
return testCompareXMLToXMLFiles ( info - > inxml , info - > outxml , info - > uuid ,
2019-04-15 22:49:30 +03:00
info - > flags ) ;
2011-09-23 00:29:00 +04:00
}
static int
mymain ( void )
{
int ret = 0 ;
2015-09-15 09:16:02 +03:00
if ( qemuTestDriverInit ( & driver ) < 0 )
2012-03-22 15:33:35 +04:00
return EXIT_FAILURE ;
2011-09-23 00:29:00 +04:00
2013-12-04 17:53:24 +04:00
if ( VIR_ALLOC ( testSnapshotXMLVariableLineRegex ) < 0 )
goto cleanup ;
if ( regcomp ( testSnapshotXMLVariableLineRegex ,
testSnapshotXMLVariableLineRegexStr ,
REG_EXTENDED | REG_NOSUB ) ! = 0 ) {
virReportError ( VIR_ERR_INTERNAL_ERROR , " %s " ,
" failed to compile test regex " ) ;
goto cleanup ;
}
2019-04-15 22:49:30 +03:00
# define DO_TEST(prefix, name, inpath, outpath, uuid, flags) \
2017-11-03 15:09:47 +03:00
do { \
const struct testInfo info = { abs_srcdir " / " inpath " / " name " .xml " , \
2013-12-04 17:53:24 +04:00
abs_srcdir " / " outpath " / " name " .xml " , \
2019-04-15 22:49:30 +03:00
uuid , flags } ; \
2017-11-03 15:09:47 +03:00
if ( virTestRun ( " SNAPSHOT XML-2-XML " prefix " " name , \
testCompareXMLToXMLHelper , & info ) < 0 ) \
ret = - 1 ; \
2011-09-23 00:29:00 +04:00
} while ( 0 )
2013-12-04 17:53:24 +04:00
# define DO_TEST_IN(name, uuid) DO_TEST("in->in", name,\
" domainsnapshotxml2xmlin " , \
" domainsnapshotxml2xmlin " , \
2019-04-15 22:49:30 +03:00
uuid , 0 )
2013-12-04 17:53:24 +04:00
# define DO_TEST_OUT(name, uuid, internal) DO_TEST("out->out", name,\
" domainsnapshotxml2xmlout " , \
" domainsnapshotxml2xmlout " , \
2019-04-15 22:49:30 +03:00
uuid , \
internal | TEST_REDEFINE )
2013-12-04 17:53:24 +04:00
2019-04-15 22:49:30 +03:00
# define DO_TEST_INOUT(name, uuid, flags) \
2013-12-04 17:53:24 +04:00
DO_TEST ( " in->out " , name , \
" domainsnapshotxml2xmlin " , \
" domainsnapshotxml2xmlout " , \
2019-04-15 22:49:30 +03:00
uuid , flags )
2013-12-04 17:53:24 +04:00
2011-09-23 00:29:00 +04:00
/* Unset or set all envvars here that are copied in qemudBuildCommandLine
* using ADD_ENV_COPY , otherwise these tests may fail due to unexpected
* values for these envvars */
setenv ( " PATH " , " /bin " , 1 ) ;
2019-04-15 22:49:30 +03:00
DO_TEST_OUT ( " all_parameters " , " 9d37b878-a7cc-9f9a-b78f-49b3abad25a8 " ,
TEST_INTERNAL ) ;
DO_TEST_OUT ( " disk_snapshot_redefine " , " c7a5fdbd-edaf-9455-926a-d65c16db1809 " ,
TEST_INTERNAL ) ;
DO_TEST_OUT ( " full_domain " , " c7a5fdbd-edaf-9455-926a-d65c16db1809 " ,
TEST_INTERNAL ) ;
DO_TEST_OUT ( " noparent_nodescription_noactive " , NULL , 0 ) ;
DO_TEST_OUT ( " noparent_nodescription " , NULL , TEST_INTERNAL ) ;
DO_TEST_OUT ( " noparent " , " 9d37b878-a7cc-9f9a-b78f-49b3abad25a8 " , 0 ) ;
DO_TEST_OUT ( " metadata " , " c7a5fdbd-edaf-9455-926a-d65c16db1809 " , 0 ) ;
DO_TEST_OUT ( " external_vm_redefine " , " c7a5fdbd-edaf-9455-926a-d65c16db1809 " ,
0 ) ;
DO_TEST_INOUT ( " empty " , " 9d37b878-a7cc-9f9a-b78f-49b3abad25a8 " , 0 ) ;
DO_TEST_INOUT ( " noparent " , " 9d37b878-a7cc-9f9a-b78f-49b3abad25a8 " , 0 ) ;
DO_TEST_INOUT ( " external_vm " , NULL , 0 ) ;
DO_TEST_INOUT ( " disk_snapshot " , NULL , 0 ) ;
DO_TEST_INOUT ( " disk_driver_name_null " , NULL , 0 ) ;
2013-12-04 21:31:39 +04:00
DO_TEST_IN ( " name_and_description " , NULL ) ;
DO_TEST_IN ( " description_only " , NULL ) ;
DO_TEST_IN ( " name_only " , NULL ) ;
2014-03-25 10:53:44 +04:00
cleanup :
2013-12-04 17:53:24 +04:00
if ( testSnapshotXMLVariableLineRegex )
regfree ( testSnapshotXMLVariableLineRegex ) ;
VIR_FREE ( testSnapshotXMLVariableLineRegex ) ;
2015-09-15 09:16:02 +03:00
qemuTestDriverFree ( & driver ) ;
2011-09-23 00:29:00 +04:00
2014-03-17 13:38:38 +04:00
return ret = = 0 ? EXIT_SUCCESS : EXIT_FAILURE ;
2011-09-23 00:29:00 +04:00
}
2017-03-29 17:45:42 +03:00
VIR_TEST_MAIN ( mymain )
2011-09-23 00:29:00 +04:00
# else
int
main ( void )
{
return EXIT_AM_SKIP ;
}
# endif /* WITH_QEMU */