2014-06-25 15:24:53 +04:00
/*
* Copyright ( C ) Red Hat , Inc . 2014
*
* 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/>.
*
* Authors :
* Michal Privoznik < mprivozn @ redhat . com >
*/
# include <config.h>
# include <stdlib.h>
# include "testutils.h"
# include "domain_capabilities.h"
# define VIR_FROM_THIS VIR_FROM_NONE
2014-09-17 13:33:35 +04:00
typedef int ( * virDomainCapsFill ) ( virDomainCapsPtr domCaps ,
void * opaque ) ;
2014-06-25 15:24:53 +04:00
# define SET_ALL_BITS(x) \
memset ( & ( x . values ) , 0xff , sizeof ( x . values ) )
2014-09-17 03:52:54 +04:00
static int ATTRIBUTE_SENTINEL
fillStringValues ( virDomainCapsStringValuesPtr values , . . . )
{
int ret = 0 ;
va_list list ;
const char * str ;
va_start ( list , values ) ;
while ( ( str = va_arg ( list , const char * ) ) ) {
if ( VIR_REALLOC_N ( values - > values , values - > nvalues + 1 ) < 0 | |
VIR_STRDUP ( values - > values [ values - > nvalues ] , str ) < 0 ) {
ret = - 1 ;
break ;
}
values - > nvalues + + ;
}
va_end ( list ) ;
return ret ;
}
2014-09-17 13:33:35 +04:00
static int
2016-04-25 15:20:58 +03:00
fillAllCaps ( virDomainCapsPtr domCaps )
2014-06-25 15:24:53 +04:00
{
2014-09-16 16:47:47 +04:00
virDomainCapsOSPtr os = & domCaps - > os ;
virDomainCapsLoaderPtr loader = & os - > loader ;
2014-06-25 15:24:53 +04:00
virDomainCapsDeviceDiskPtr disk = & domCaps - > disk ;
virDomainCapsDeviceHostdevPtr hostdev = & domCaps - > hostdev ;
domCaps - > maxvcpus = 255 ;
2016-03-10 21:52:52 +03:00
os - > supported = true ;
2014-09-16 16:47:47 +04:00
2016-03-10 21:52:52 +03:00
loader - > supported = true ;
2014-09-16 16:47:47 +04:00
SET_ALL_BITS ( loader - > type ) ;
SET_ALL_BITS ( loader - > readonly ) ;
2014-09-17 03:52:54 +04:00
if ( fillStringValues ( & loader - > values ,
" /foo/bar " ,
" /tmp/my_path " ,
NULL ) < 0 )
return - 1 ;
2014-09-16 16:47:47 +04:00
2016-03-10 21:52:52 +03:00
disk - > supported = true ;
2014-06-25 15:24:53 +04:00
SET_ALL_BITS ( disk - > diskDevice ) ;
SET_ALL_BITS ( disk - > bus ) ;
2016-03-10 21:52:52 +03:00
hostdev - > supported = true ;
2014-06-25 15:24:53 +04:00
SET_ALL_BITS ( hostdev - > mode ) ;
SET_ALL_BITS ( hostdev - > startupPolicy ) ;
SET_ALL_BITS ( hostdev - > subsysType ) ;
SET_ALL_BITS ( hostdev - > capsType ) ;
SET_ALL_BITS ( hostdev - > pciBackend ) ;
2014-09-17 13:33:35 +04:00
return 0 ;
2014-06-25 15:24:53 +04:00
}
2014-06-25 20:39:29 +04:00
2016-04-25 15:20:58 +03:00
# if WITH_QEMU
2014-06-25 20:39:29 +04:00
# include "testutilsqemu.h"
2014-09-17 03:52:54 +04:00
2014-09-17 13:33:35 +04:00
static int
2014-06-25 20:39:29 +04:00
fillQemuCaps ( virDomainCapsPtr domCaps ,
2016-04-25 15:20:58 +03:00
const char * name ,
2016-04-25 15:19:49 +03:00
virArch arch ,
2016-04-25 15:20:58 +03:00
virQEMUDriverConfigPtr cfg )
2014-06-25 20:39:29 +04:00
{
2016-04-25 15:20:58 +03:00
int ret = - 1 ;
char * path = NULL ;
virQEMUCapsPtr qemuCaps = NULL ;
2015-01-21 21:38:57 +03:00
virDomainCapsLoaderPtr loader = & domCaps - > os . loader ;
2014-06-25 20:39:29 +04:00
2016-04-28 18:45:41 +03:00
if ( virAsprintf ( & path , " %s/qemucapabilitiesdata/%s.%s.xml " ,
2016-04-25 15:19:49 +03:00
abs_srcdir , name , virArchToString ( arch ) ) < 0 | |
2016-04-25 15:20:58 +03:00
! ( qemuCaps = qemuTestParseCapabilities ( path ) ) )
goto cleanup ;
2014-09-18 10:30:40 +04:00
if ( virQEMUCapsFillDomainCaps ( domCaps , qemuCaps ,
cfg - > loader , cfg - > nloader ) < 0 )
2016-04-25 15:20:58 +03:00
goto cleanup ;
2014-06-25 20:39:29 +04:00
/* The function above tries to query host's KVM & VFIO capabilities by
* calling qemuHostdevHostSupportsPassthroughLegacy ( ) and
* qemuHostdevHostSupportsPassthroughVFIO ( ) which , however , can ' t be
* successfully mocked as they are not exposed as internal APIs . Therefore ,
* instead of mocking set the expected values here by hand . */
VIR_DOMAIN_CAPS_ENUM_SET ( domCaps - > hostdev . pciBackend ,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT ,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM ,
VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO ) ;
2014-09-17 19:17:03 +04:00
2016-04-25 15:20:58 +03:00
/* As of f05b6a918e28 we are expecting to see OVMF_CODE.fd file which
* may not exists everywhere . */
2015-01-21 21:38:57 +03:00
while ( loader - > values . nvalues )
VIR_FREE ( loader - > values . values [ - - loader - > values . nvalues ] ) ;
if ( fillStringValues ( & loader - > values ,
2015-01-21 21:44:43 +03:00
" /usr/share/AAVMF/AAVMF_CODE.fd " ,
2015-01-21 21:38:57 +03:00
" /usr/share/OVMF/OVMF_CODE.fd " ,
NULL ) < 0 )
2014-06-25 15:24:53 +04:00
goto cleanup ;
2016-04-25 15:20:58 +03:00
ret = 0 ;
2014-06-25 15:24:53 +04:00
cleanup :
2016-04-25 15:20:58 +03:00
virObjectUnref ( qemuCaps ) ;
VIR_FREE ( path ) ;
2014-09-17 03:52:54 +04:00
return ret ;
2014-06-25 15:24:53 +04:00
}
2016-04-25 15:20:58 +03:00
# endif /* WITH_QEMU */
enum testCapsType {
CAPS_NONE ,
CAPS_ALL ,
CAPS_QEMU ,
} ;
2014-06-25 15:24:53 +04:00
2016-04-25 15:20:58 +03:00
struct testData {
const char * name ;
const char * emulator ;
2014-06-25 15:24:53 +04:00
const char * machine ;
virArch arch ;
virDomainVirtType type ;
2016-04-25 15:20:58 +03:00
enum testCapsType capsType ;
const char * capsName ;
void * capsOpaque ;
2014-06-25 15:24:53 +04:00
} ;
static int
test_virDomainCapsFormat ( const void * opaque )
{
2016-04-25 15:20:58 +03:00
const struct testData * data = opaque ;
2014-06-25 15:24:53 +04:00
virDomainCapsPtr domCaps = NULL ;
char * path = NULL ;
char * domCapsXML = NULL ;
int ret = - 1 ;
if ( virAsprintf ( & path , " %s/domaincapsschemadata/domaincaps-%s.xml " ,
2016-04-25 15:20:58 +03:00
abs_srcdir , data - > name ) < 0 )
2014-06-25 15:24:53 +04:00
goto cleanup ;
2016-04-25 15:20:58 +03:00
if ( ! ( domCaps = virDomainCapsNew ( data - > emulator , data - > machine , data - > arch ,
data - > type ) ) )
2014-06-25 15:24:53 +04:00
goto cleanup ;
2016-04-25 15:20:58 +03:00
switch ( data - > capsType ) {
case CAPS_NONE :
break ;
case CAPS_ALL :
if ( fillAllCaps ( domCaps ) < 0 )
goto cleanup ;
break ;
case CAPS_QEMU :
# if WITH_QEMU
2016-04-25 15:19:49 +03:00
if ( fillQemuCaps ( domCaps , data - > capsName , data - > arch ,
data - > capsOpaque ) < 0 )
2016-04-25 15:20:58 +03:00
goto cleanup ;
# endif
break ;
}
2014-06-25 15:24:53 +04:00
if ( ! ( domCapsXML = virDomainCapsFormat ( domCaps ) ) )
goto cleanup ;
2015-04-23 18:14:26 +03:00
if ( virtTestCompareToFile ( domCapsXML , path ) < 0 )
2014-06-25 15:24:53 +04:00
goto cleanup ;
ret = 0 ;
cleanup :
VIR_FREE ( domCapsXML ) ;
VIR_FREE ( path ) ;
virObjectUnref ( domCaps ) ;
return ret ;
}
static int
mymain ( void )
{
int ret = 0 ;
2016-04-25 15:20:58 +03:00
# if WITH_QEMU
2014-09-17 03:52:54 +04:00
virQEMUDriverConfigPtr cfg = virQEMUDriverConfigNew ( false ) ;
2015-01-26 19:09:36 +03:00
if ( ! cfg )
return EXIT_FAILURE ;
2016-04-25 15:20:58 +03:00
# endif
# define DO_TEST(Name, Emulator, Machine, Arch, Type, CapsType) \
do { \
struct testData data = { \
. name = Name , \
. emulator = Emulator , \
. machine = Machine , \
. arch = Arch , \
. type = Type , \
. capsType = CapsType , \
} ; \
if ( virtTestRun ( Name , test_virDomainCapsFormat , & data ) < 0 ) \
ret = - 1 ; \
} while ( 0 )
2015-01-26 19:09:36 +03:00
2016-04-25 15:20:58 +03:00
# define DO_TEST_QEMU(Name, CapsName, Emulator, Machine, Arch, Type) \
do { \
struct testData data = { \
. name = Name , \
. emulator = Emulator , \
. machine = Machine , \
. arch = Arch , \
. type = Type , \
. capsType = CAPS_QEMU , \
. capsName = CapsName , \
. capsOpaque = cfg , \
} ; \
if ( virtTestRun ( Name , test_virDomainCapsFormat , & data ) < 0 ) \
ret = - 1 ; \
2014-06-25 20:39:29 +04:00
} while ( 0 )
2016-04-25 15:20:58 +03:00
DO_TEST ( " basic " , " /bin/emulatorbin " , " my-machine-type " ,
VIR_ARCH_X86_64 , VIR_DOMAIN_VIRT_UML , CAPS_NONE ) ;
DO_TEST ( " full " , " /bin/emulatorbin " , " my-machine-type " ,
VIR_ARCH_X86_64 , VIR_DOMAIN_VIRT_KVM , CAPS_ALL ) ;
# if WITH_QEMU
DO_TEST_QEMU ( " qemu_1.6.50-1 " , " caps_1.6.50-1 " ,
" /usr/bin/qemu-system-x86_64 " , " pc-1.2 " , VIR_ARCH_X86_64 ,
VIR_DOMAIN_VIRT_KVM ) ;
2014-06-25 20:39:29 +04:00
# endif /* WITH_QEMU */
2014-06-25 15:24:53 +04:00
return ret ;
}
VIRT_TEST_MAIN ( mymain )