2013-09-19 15:44:41 +04:00
/*
* Copyright ( C ) 2011 - 2013 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 "testutilsqemu.h"
# include "qemumonitortestutils.h"
# define VIR_FROM_THIS VIR_FROM_NONE
typedef struct _testQemuData testQemuData ;
typedef testQemuData * testQemuDataPtr ;
struct _testQemuData {
virDomainXMLOptionPtr xmlopt ;
const char * base ;
} ;
static qemuMonitorTestPtr
testQemuFeedMonitor ( char * replies ,
virDomainXMLOptionPtr xmlopt )
{
qemuMonitorTestPtr test = NULL ;
char * tmp = replies ;
char * singleReply = tmp ;
/* Our JSON parser expects replies to be separated by a newline character.
* Hence we must preprocess the file a bit . */
while ( ( tmp = strchr ( tmp , ' \n ' ) ) ) {
/* It is safe to touch tmp[1] since all strings ends with '\0'. */
bool eof = ! tmp [ 1 ] ;
if ( * ( tmp + 1 ) ! = ' \n ' ) {
* tmp = ' ' ;
tmp + + ;
} else {
/* Cut off a single reply. */
* ( tmp + 1 ) = ' \0 ' ;
if ( test ) {
if ( qemuMonitorTestAddItem ( test , NULL , singleReply ) < 0 )
goto error ;
} else {
/* Create new mocked monitor with our greeting */
if ( ! ( test = qemuMonitorTestNew ( true , xmlopt , NULL , NULL , singleReply ) ) )
goto error ;
}
if ( ! eof ) {
/* Move the @tmp and @singleReply. */
tmp + = 2 ;
singleReply = tmp ;
}
}
if ( eof )
break ;
}
if ( test & & qemuMonitorTestAddItem ( test , NULL , singleReply ) < 0 )
goto error ;
return test ;
error :
qemuMonitorTestFree ( test ) ;
return NULL ;
}
static virQEMUCapsPtr
testQemuGetCaps ( char * caps )
{
virQEMUCapsPtr qemuCaps = NULL ;
xmlDocPtr xml ;
xmlXPathContextPtr ctxt = NULL ;
ssize_t i , n ;
xmlNodePtr * nodes = NULL ;
if ( ! ( xml = virXMLParseStringCtxt ( caps , " (test caps) " , & ctxt ) ) )
goto error ;
if ( ( n = virXPathNodeSet ( " /qemuCaps/flag " , ctxt , & nodes ) ) < 0 ) {
fprintf ( stderr , " failed to parse qemu capabilities flags " ) ;
goto error ;
}
if ( n > 0 ) {
if ( ! ( qemuCaps = virQEMUCapsNew ( ) ) )
goto error ;
for ( i = 0 ; i < n ; i + + ) {
char * str = virXMLPropString ( nodes [ i ] , " name " ) ;
if ( str ) {
int flag = virQEMUCapsTypeFromString ( str ) ;
if ( flag < 0 ) {
fprintf ( stderr , " Unknown qemu capabilities flag %s " , str ) ;
VIR_FREE ( str ) ;
goto error ;
}
VIR_FREE ( str ) ;
virQEMUCapsSet ( qemuCaps , flag ) ;
}
}
}
VIR_FREE ( nodes ) ;
xmlFreeDoc ( xml ) ;
xmlXPathFreeContext ( ctxt ) ;
return qemuCaps ;
error :
VIR_FREE ( nodes ) ;
virObjectUnref ( qemuCaps ) ;
xmlFreeDoc ( xml ) ;
xmlXPathFreeContext ( ctxt ) ;
return NULL ;
}
static int
testQemuCapsCompare ( virQEMUCapsPtr capsProvided ,
virQEMUCapsPtr capsComputed )
{
int ret = 0 ;
size_t i ;
for ( i = 0 ; i < QEMU_CAPS_LAST ; i + + ) {
if ( virQEMUCapsGet ( capsProvided , i ) & &
! virQEMUCapsGet ( capsComputed , i ) ) {
fprintf ( stderr , " Caps mismatch: capsComputed is missing %s \n " ,
virQEMUCapsTypeToString ( i ) ) ;
ret = - 1 ;
}
if ( virQEMUCapsGet ( capsComputed , i ) & &
! virQEMUCapsGet ( capsProvided , i ) ) {
fprintf ( stderr , " Caps mismatch: capsProvided is missing %s \n " ,
virQEMUCapsTypeToString ( i ) ) ;
ret = - 1 ;
}
}
return ret ;
}
static int
testQemuCaps ( const void * opaque )
{
int ret = - 1 ;
2013-10-05 05:40:19 +04:00
const testQemuData * data = opaque ;
2013-09-19 15:44:41 +04:00
char * repliesFile = NULL , * capsFile = NULL ;
char * replies = NULL , * caps = NULL ;
qemuMonitorTestPtr mon = NULL ;
virQEMUCapsPtr capsProvided = NULL , capsComputed = NULL ;
if ( virAsprintf ( & repliesFile , " %s/qemucapabilitiesdata/%s.replies " ,
abs_srcdir , data - > base ) < 0 | |
virAsprintf ( & capsFile , " %s/qemucapabilitiesdata/%s.caps " ,
abs_srcdir , data - > base ) < 0 )
goto cleanup ;
if ( virtTestLoadFile ( repliesFile , & replies ) < 0 | |
virtTestLoadFile ( capsFile , & caps ) < 0 )
goto cleanup ;
if ( ! ( mon = testQemuFeedMonitor ( replies , data - > xmlopt ) ) )
goto cleanup ;
if ( ! ( capsProvided = testQemuGetCaps ( caps ) ) )
goto cleanup ;
if ( ! ( capsComputed = virQEMUCapsNew ( ) ) )
goto cleanup ;
if ( virQEMUCapsInitQMPMonitor ( capsComputed ,
qemuMonitorTestGetMonitor ( mon ) ) < 0 )
goto cleanup ;
if ( testQemuCapsCompare ( capsProvided , capsComputed ) < 0 )
goto cleanup ;
ret = 0 ;
cleanup :
VIR_FREE ( repliesFile ) ;
VIR_FREE ( capsFile ) ;
VIR_FREE ( replies ) ;
VIR_FREE ( caps ) ;
qemuMonitorTestFree ( mon ) ;
virObjectUnref ( capsProvided ) ;
virObjectUnref ( capsComputed ) ;
return ret ;
}
static int
mymain ( void )
{
int ret = 0 ;
virDomainXMLOptionPtr xmlopt ;
testQemuData data ;
# if !WITH_YAJL
fputs ( " libvirt not compiled with yajl, skipping this test \n " , stderr ) ;
return EXIT_AM_SKIP ;
# endif
if ( virThreadInitialize ( ) < 0 | |
! ( xmlopt = virQEMUDriverCreateXMLConf ( NULL ) ) )
return EXIT_FAILURE ;
virEventRegisterDefaultImpl ( ) ;
data . xmlopt = xmlopt ;
# define DO_TEST(name) \
data . base = name ; \
2013-09-20 22:13:35 +04:00
if ( virtTestRun ( name , testQemuCaps , & data ) < 0 ) \
2013-09-19 15:44:41 +04:00
ret = - 1
2013-10-03 16:30:26 +04:00
DO_TEST ( " caps_1.2.2-1 " ) ;
2013-10-03 16:16:32 +04:00
DO_TEST ( " caps_1.3.1-1 " ) ;
2013-10-03 16:00:57 +04:00
DO_TEST ( " caps_1.4.2-1 " ) ;
2013-09-19 15:44:41 +04:00
DO_TEST ( " caps_1.5.3-1 " ) ;
2013-10-03 17:02:02 +04:00
DO_TEST ( " caps_1.6.0-1 " ) ;
2013-10-03 15:27:45 +04:00
DO_TEST ( " caps_1.6.50-1 " ) ;
2013-09-19 15:44:41 +04:00
virObjectUnref ( xmlopt ) ;
return ( ret = = 0 ) ? EXIT_SUCCESS : EXIT_FAILURE ;
}
VIRT_TEST_MAIN ( mymain )