2011-04-15 15:15:37 +04:00
# include <config.h>
2011-04-15 23:17:11 +04:00
# include <time.h>
2011-04-15 15:15:37 +04:00
# include "internal.h"
2012-01-25 20:13:59 +04:00
# include "virhash.h"
# include "virhashdata.h"
2011-04-15 15:15:37 +04:00
# include "testutils.h"
2012-12-12 22:06:53 +04:00
# include "viralloc.h"
2012-12-12 21:59:27 +04:00
# include "virlog.h"
2013-04-03 14:36:23 +04:00
# include "virstring.h"
2011-04-15 15:15:37 +04:00
2013-06-07 19:10:28 +04:00
# define VIR_FROM_THIS VIR_FROM_NONE
2014-02-28 16:16:17 +04:00
VIR_LOG_INIT ( " tests.hashtest " ) ;
2011-04-15 15:15:37 +04:00
static virHashTablePtr
testHashInit ( int size )
{
virHashTablePtr hash ;
2012-01-25 19:55:00 +04:00
ssize_t i ;
2011-04-15 15:15:37 +04:00
if ( ! ( hash = virHashCreate ( size , NULL ) ) )
return NULL ;
2018-12-04 20:08:14 +03:00
/* entries are added in reverse order so that they will be linked in
2011-04-15 15:15:37 +04:00
* collision list in the same order as in the uuids array
*/
2019-10-15 14:55:26 +03:00
for ( i = G_N_ELEMENTS ( uuids ) - 1 ; i > = 0 ; i - - ) {
2012-01-25 19:55:00 +04:00
ssize_t oldsize = virHashTableSize ( hash ) ;
2011-04-15 15:15:37 +04:00
if ( virHashAddEntry ( hash , uuids [ i ] , ( void * ) uuids [ i ] ) < 0 ) {
virHashFree ( hash ) ;
return NULL ;
}
2011-04-15 23:17:11 +04:00
2015-04-23 20:38:00 +03:00
if ( virHashTableSize ( hash ) ! = oldsize ) {
VIR_TEST_DEBUG ( " hash grown from %zd to %zd " ,
2012-03-29 13:41:37 +04:00
( size_t ) oldsize , ( size_t ) virHashTableSize ( hash ) ) ;
2011-04-15 23:17:11 +04:00
}
}
2019-10-15 14:55:26 +03:00
for ( i = 0 ; i < G_N_ELEMENTS ( uuids ) ; i + + ) {
2011-04-15 23:17:11 +04:00
if ( ! virHashLookup ( hash , uuids [ i ] ) ) {
2019-05-03 11:45:58 +03:00
VIR_TEST_VERBOSE ( " \n entry \" %s \" could not be found " , uuids [ i ] ) ;
2011-04-15 23:17:11 +04:00
virHashFree ( hash ) ;
return NULL ;
}
2011-04-15 15:15:37 +04:00
}
return hash ;
}
2016-02-12 12:03:50 +03:00
static int
2019-10-14 15:45:03 +03:00
testHashCheckForEachCount ( void * payload G_GNUC_UNUSED ,
const void * name G_GNUC_UNUSED ,
void * data G_GNUC_UNUSED )
2011-04-29 23:49:36 +04:00
{
2016-02-12 12:15:57 +03:00
size_t * count = data ;
* count + = 1 ;
2016-02-12 12:03:50 +03:00
return 0 ;
2011-04-29 23:49:36 +04:00
}
2011-04-15 15:15:37 +04:00
static int
2012-01-25 19:55:00 +04:00
testHashCheckCount ( virHashTablePtr hash , size_t count )
2011-04-15 15:15:37 +04:00
{
2016-02-12 12:15:57 +03:00
size_t iter_count = 0 ;
2011-04-29 23:49:36 +04:00
2011-04-15 15:15:37 +04:00
if ( virHashSize ( hash ) ! = count ) {
2019-05-03 11:45:58 +03:00
VIR_TEST_VERBOSE ( " \n hash contains %zd instead of %zu elements " ,
2016-02-12 12:15:57 +03:00
virHashSize ( hash ) , count ) ;
2011-04-15 15:15:37 +04:00
return - 1 ;
}
2016-02-12 12:15:57 +03:00
virHashForEach ( hash , testHashCheckForEachCount , & iter_count ) ;
2011-04-29 23:49:36 +04:00
if ( count ! = iter_count ) {
2016-02-12 12:15:57 +03:00
VIR_TEST_VERBOSE ( " \n hash claims to have %zu elements but iteration "
2019-05-03 11:45:58 +03:00
" finds %zu " , count , iter_count ) ;
2011-04-29 23:49:36 +04:00
return - 1 ;
}
2011-04-15 15:15:37 +04:00
return 0 ;
}
struct testInfo {
void * data ;
2012-01-25 19:55:00 +04:00
size_t count ;
2011-04-15 15:15:37 +04:00
} ;
2011-04-15 23:17:11 +04:00
static int
testHashGrow ( const void * data )
{
const struct testInfo * info = data ;
virHashTablePtr hash ;
int ret = - 1 ;
if ( ! ( hash = testHashInit ( info - > count ) ) )
return - 1 ;
2019-10-15 14:55:26 +03:00
if ( testHashCheckCount ( hash , G_N_ELEMENTS ( uuids ) ) < 0 )
2011-04-15 23:17:11 +04:00
goto cleanup ;
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2011-04-15 23:17:11 +04:00
virHashFree ( hash ) ;
return ret ;
}
static int
2019-10-14 15:45:03 +03:00
testHashUpdate ( const void * data G_GNUC_UNUSED )
2011-04-15 23:17:11 +04:00
{
2019-10-15 14:55:26 +03:00
int count = G_N_ELEMENTS ( uuids ) + G_N_ELEMENTS ( uuids_new ) ;
2011-04-15 23:17:11 +04:00
virHashTablePtr hash ;
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t i ;
2011-04-15 23:17:11 +04:00
int ret = - 1 ;
if ( ! ( hash = testHashInit ( 0 ) ) )
return - 1 ;
2019-10-15 14:55:26 +03:00
for ( i = 0 ; i < G_N_ELEMENTS ( uuids_subset ) ; i + + ) {
2011-04-15 23:17:11 +04:00
if ( virHashUpdateEntry ( hash , uuids_subset [ i ] , ( void * ) 1 ) < 0 ) {
2019-05-03 11:45:58 +03:00
VIR_TEST_VERBOSE ( " \n entry \" %s \" could not be updated " ,
2015-04-23 20:38:00 +03:00
uuids_subset [ i ] ) ;
2011-04-15 23:17:11 +04:00
goto cleanup ;
}
}
2019-10-15 14:55:26 +03:00
for ( i = 0 ; i < G_N_ELEMENTS ( uuids_new ) ; i + + ) {
2011-04-15 23:17:11 +04:00
if ( virHashUpdateEntry ( hash , uuids_new [ i ] , ( void * ) 1 ) < 0 ) {
2019-05-03 11:45:58 +03:00
VIR_TEST_VERBOSE ( " \n new entry \" %s \" could not be updated " ,
2015-04-23 20:38:00 +03:00
uuids_new [ i ] ) ;
2011-04-15 23:17:11 +04:00
goto cleanup ;
}
}
if ( testHashCheckCount ( hash , count ) < 0 )
goto cleanup ;
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2011-04-15 23:17:11 +04:00
virHashFree ( hash ) ;
return ret ;
}
static int
2019-10-14 15:45:03 +03:00
testHashRemove ( const void * data G_GNUC_UNUSED )
2011-04-15 23:17:11 +04:00
{
2019-10-15 14:55:26 +03:00
int count = G_N_ELEMENTS ( uuids ) - G_N_ELEMENTS ( uuids_subset ) ;
2011-04-15 23:17:11 +04:00
virHashTablePtr hash ;
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t i ;
2011-04-15 23:17:11 +04:00
int ret = - 1 ;
if ( ! ( hash = testHashInit ( 0 ) ) )
return - 1 ;
2019-10-15 14:55:26 +03:00
for ( i = 0 ; i < G_N_ELEMENTS ( uuids_subset ) ; i + + ) {
2011-04-15 23:17:11 +04:00
if ( virHashRemoveEntry ( hash , uuids_subset [ i ] ) < 0 ) {
2019-05-03 11:45:58 +03:00
VIR_TEST_VERBOSE ( " \n entry \" %s \" could not be removed " ,
2015-04-23 20:38:00 +03:00
uuids_subset [ i ] ) ;
2011-04-15 23:17:11 +04:00
goto cleanup ;
}
}
if ( testHashCheckCount ( hash , count ) < 0 )
goto cleanup ;
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2011-04-15 23:17:11 +04:00
virHashFree ( hash ) ;
return ret ;
}
2011-04-15 15:15:37 +04:00
const int testHashCountRemoveForEachSome =
2019-10-15 14:55:26 +03:00
G_N_ELEMENTS ( uuids ) - G_N_ELEMENTS ( uuids_subset ) ;
2011-04-15 15:15:37 +04:00
2016-02-12 12:03:50 +03:00
static int
2019-10-14 15:45:03 +03:00
testHashRemoveForEachSome ( void * payload G_GNUC_UNUSED ,
2011-04-15 15:15:37 +04:00
const void * name ,
void * data )
{
virHashTablePtr hash = data ;
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t i ;
2011-04-15 15:15:37 +04:00
2019-10-15 14:55:26 +03:00
for ( i = 0 ; i < G_N_ELEMENTS ( uuids_subset ) ; i + + ) {
2011-04-15 15:15:37 +04:00
if ( STREQ ( uuids_subset [ i ] , name ) ) {
2015-04-23 20:38:00 +03:00
if ( virHashRemoveEntry ( hash , name ) < 0 ) {
VIR_TEST_VERBOSE ( " \n entry \" %s \" could not be removed " ,
2011-04-15 15:15:37 +04:00
uuids_subset [ i ] ) ;
}
break ;
}
}
2016-02-12 12:03:50 +03:00
return 0 ;
2011-04-15 15:15:37 +04:00
}
const int testHashCountRemoveForEachAll = 0 ;
2016-02-12 12:03:50 +03:00
static int
2019-10-14 15:45:03 +03:00
testHashRemoveForEachAll ( void * payload G_GNUC_UNUSED ,
2011-04-15 15:15:37 +04:00
const void * name ,
void * data )
{
virHashTablePtr hash = data ;
virHashRemoveEntry ( hash , name ) ;
2016-02-12 12:03:50 +03:00
return 0 ;
2011-04-15 15:15:37 +04:00
}
static int
testHashRemoveForEach ( const void * data )
{
const struct testInfo * info = data ;
virHashTablePtr hash ;
int ret = - 1 ;
if ( ! ( hash = testHashInit ( 0 ) ) )
return - 1 ;
2016-02-12 12:15:57 +03:00
if ( virHashForEach ( hash , ( virHashIterator ) info - > data , hash ) ) {
VIR_TEST_VERBOSE ( " \n virHashForEach didn't go through all entries " ) ;
2011-04-15 15:15:37 +04:00
goto cleanup ;
}
if ( testHashCheckCount ( hash , info - > count ) < 0 )
goto cleanup ;
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2011-04-15 15:15:37 +04:00
virHashFree ( hash ) ;
return ret ;
}
2011-04-15 23:17:11 +04:00
static int
2019-10-14 15:45:03 +03:00
testHashSteal ( const void * data G_GNUC_UNUSED )
2011-04-15 23:17:11 +04:00
{
2019-10-15 14:55:26 +03:00
int count = G_N_ELEMENTS ( uuids ) - G_N_ELEMENTS ( uuids_subset ) ;
2011-04-15 23:17:11 +04:00
virHashTablePtr hash ;
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t i ;
2011-04-15 23:17:11 +04:00
int ret = - 1 ;
if ( ! ( hash = testHashInit ( 0 ) ) )
return - 1 ;
2019-10-15 14:55:26 +03:00
for ( i = 0 ; i < G_N_ELEMENTS ( uuids_subset ) ; i + + ) {
2011-04-15 23:17:11 +04:00
if ( ! virHashSteal ( hash , uuids_subset [ i ] ) ) {
2019-05-03 11:45:58 +03:00
VIR_TEST_VERBOSE ( " \n entry \" %s \" could not be stolen " ,
2015-04-23 20:38:00 +03:00
uuids_subset [ i ] ) ;
2011-04-15 23:17:11 +04:00
goto cleanup ;
}
}
if ( testHashCheckCount ( hash , count ) < 0 )
goto cleanup ;
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2011-04-15 23:17:11 +04:00
virHashFree ( hash ) ;
return ret ;
}
static int
2019-10-14 15:45:03 +03:00
testHashRemoveSetIter ( const void * payload G_GNUC_UNUSED ,
2011-04-15 23:17:11 +04:00
const void * name ,
const void * data )
{
int * count = ( int * ) data ;
bool rem = false ;
Convert 'int i' to 'size_t i' in tests/ files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 18:09:33 +04:00
size_t i ;
2011-04-15 23:17:11 +04:00
2019-10-15 14:55:26 +03:00
for ( i = 0 ; i < G_N_ELEMENTS ( uuids_subset ) ; i + + ) {
2011-04-15 23:17:11 +04:00
if ( STREQ ( uuids_subset [ i ] , name ) ) {
rem = true ;
break ;
}
}
if ( rem | | rand ( ) % 2 ) {
( * count ) + + ;
return 1 ;
} else {
return 0 ;
}
}
static int
2019-10-14 15:45:03 +03:00
testHashRemoveSet ( const void * data G_GNUC_UNUSED )
2011-04-15 23:17:11 +04:00
{
virHashTablePtr hash ;
int count = 0 ;
int rcount ;
int ret = - 1 ;
if ( ! ( hash = testHashInit ( 0 ) ) )
return - 1 ;
/* seed the generator so that rand() provides reproducible sequence */
srand ( 9000 ) ;
rcount = virHashRemoveSet ( hash , testHashRemoveSetIter , & count ) ;
if ( count ! = rcount ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n virHashRemoveSet didn't remove expected number of "
2019-05-03 11:45:58 +03:00
" entries, %d != %u " ,
2015-04-23 20:38:00 +03:00
rcount , count ) ;
2011-04-15 23:17:11 +04:00
goto cleanup ;
}
2019-10-15 14:55:26 +03:00
if ( testHashCheckCount ( hash , G_N_ELEMENTS ( uuids ) - count ) < 0 )
2011-04-15 23:17:11 +04:00
goto cleanup ;
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2011-04-15 23:17:11 +04:00
virHashFree ( hash ) ;
return ret ;
}
2019-10-15 14:55:26 +03:00
const int testSearchIndex = G_N_ELEMENTS ( uuids_subset ) / 2 ;
2011-04-15 23:17:11 +04:00
static int
2019-10-14 15:45:03 +03:00
testHashSearchIter ( const void * payload G_GNUC_UNUSED ,
2011-04-15 23:17:11 +04:00
const void * name ,
2019-10-14 15:45:03 +03:00
const void * data G_GNUC_UNUSED )
2011-04-15 23:17:11 +04:00
{
return STREQ ( uuids_subset [ testSearchIndex ] , name ) ;
}
static int
2019-10-14 15:45:03 +03:00
testHashSearch ( const void * data G_GNUC_UNUSED )
2011-04-15 23:17:11 +04:00
{
virHashTablePtr hash ;
void * entry ;
int ret = - 1 ;
if ( ! ( hash = testHashInit ( 0 ) ) )
return - 1 ;
2017-06-13 16:56:14 +03:00
entry = virHashSearch ( hash , testHashSearchIter , NULL , NULL ) ;
2011-04-15 23:17:11 +04:00
if ( ! entry | | STRNEQ ( uuids_subset [ testSearchIndex ] , entry ) ) {
2019-05-03 11:45:58 +03:00
VIR_TEST_VERBOSE ( " \n virHashSearch didn't find entry '%s' " ,
2015-04-23 20:38:00 +03:00
uuids_subset [ testSearchIndex ] ) ;
2011-04-15 23:17:11 +04:00
goto cleanup ;
}
2019-10-15 14:55:26 +03:00
if ( testHashCheckCount ( hash , G_N_ELEMENTS ( uuids ) ) < 0 )
2011-04-15 23:17:11 +04:00
goto cleanup ;
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2011-04-15 23:17:11 +04:00
virHashFree ( hash ) ;
return ret ;
}
2011-11-18 02:04:17 +04:00
static int
maint: avoid 'const fooPtr' in hashes
'const fooPtr' is the same as 'foo * const' (the pointer won't
change, but it's contents can). But in general, if an interface
is trying to be const-correct, it should be using 'const foo *'
(the pointer is to data that can't be changed).
Fix up virhash to provide a const-correct interface: all actions
that don't modify the table take a const table. Note that in
one case (virHashSearch), we actually strip const away - we aren't
modifying the contents of the table, so much as associated data
for ensuring that the code uses the table correctly (if this were
C++, it would be a case for the 'mutable' keyword).
* src/util/virhash.h (virHashKeyComparator, virHashEqual): Use
intended type.
(virHashSize, virHashTableSize, virHashLookup, virHashSearch):
Make const-correct.
* src/util/virhash.c (virHashEqualData, virHashEqual)
(virHashLookup, virHashSize, virHashTableSize, virHashSearch)
(virHashComputeKey): Fix fallout.
* src/conf/nwfilter_params.c
(virNWFilterFormatParameterNameSorter): Likewise.
* src/nwfilter/nwfilter_ebiptables_driver.c
(ebiptablesFilterOrderSort): Likewise.
* tests/virhashtest.c (testHashGetItemsCompKey)
(testHashGetItemsCompValue): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-10-05 06:30:35 +04:00
testHashGetItemsCompKey ( const virHashKeyValuePair * a ,
const virHashKeyValuePair * b )
2011-11-18 02:04:17 +04:00
{
2012-10-17 13:23:12 +04:00
return strcmp ( a - > key , b - > key ) ;
2011-11-18 02:04:17 +04:00
}
static int
maint: avoid 'const fooPtr' in hashes
'const fooPtr' is the same as 'foo * const' (the pointer won't
change, but it's contents can). But in general, if an interface
is trying to be const-correct, it should be using 'const foo *'
(the pointer is to data that can't be changed).
Fix up virhash to provide a const-correct interface: all actions
that don't modify the table take a const table. Note that in
one case (virHashSearch), we actually strip const away - we aren't
modifying the contents of the table, so much as associated data
for ensuring that the code uses the table correctly (if this were
C++, it would be a case for the 'mutable' keyword).
* src/util/virhash.h (virHashKeyComparator, virHashEqual): Use
intended type.
(virHashSize, virHashTableSize, virHashLookup, virHashSearch):
Make const-correct.
* src/util/virhash.c (virHashEqualData, virHashEqual)
(virHashLookup, virHashSize, virHashTableSize, virHashSearch)
(virHashComputeKey): Fix fallout.
* src/conf/nwfilter_params.c
(virNWFilterFormatParameterNameSorter): Likewise.
* src/nwfilter/nwfilter_ebiptables_driver.c
(ebiptablesFilterOrderSort): Likewise.
* tests/virhashtest.c (testHashGetItemsCompKey)
(testHashGetItemsCompValue): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-10-05 06:30:35 +04:00
testHashGetItemsCompValue ( const virHashKeyValuePair * a ,
const virHashKeyValuePair * b )
2011-11-18 02:04:17 +04:00
{
2012-10-17 13:23:12 +04:00
return strcmp ( a - > value , b - > value ) ;
2011-11-18 02:04:17 +04:00
}
static int
2019-10-14 15:45:03 +03:00
testHashGetItems ( const void * data G_GNUC_UNUSED )
2011-11-18 02:04:17 +04:00
{
virHashTablePtr hash ;
virHashKeyValuePairPtr array = NULL ;
int ret = - 1 ;
char keya [ ] = " a " ;
char keyb [ ] = " b " ;
char keyc [ ] = " c " ;
char value1 [ ] = " 1 " ;
char value2 [ ] = " 2 " ;
char value3 [ ] = " 3 " ;
if ( ! ( hash = virHashCreate ( 0 , NULL ) ) | |
virHashAddEntry ( hash , keya , value3 ) < 0 | |
virHashAddEntry ( hash , keyc , value1 ) < 0 | |
virHashAddEntry ( hash , keyb , value2 ) < 0 ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed to create hash " ) ;
2011-11-18 02:04:17 +04:00
goto cleanup ;
}
if ( ! ( array = virHashGetItems ( hash , NULL ) ) | |
array [ 3 ] . key | | array [ 3 ] . value ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed to get items with NULL sort " ) ;
2011-11-18 02:04:17 +04:00
goto cleanup ;
}
VIR_FREE ( array ) ;
if ( ! ( array = virHashGetItems ( hash , testHashGetItemsCompKey ) ) | |
STRNEQ ( array [ 0 ] . key , " a " ) | |
STRNEQ ( array [ 0 ] . value , " 3 " ) | |
STRNEQ ( array [ 1 ] . key , " b " ) | |
STRNEQ ( array [ 1 ] . value , " 2 " ) | |
STRNEQ ( array [ 2 ] . key , " c " ) | |
STRNEQ ( array [ 2 ] . value , " 1 " ) | |
array [ 3 ] . key | | array [ 3 ] . value ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed to get items with key sort " ) ;
2011-11-18 02:04:17 +04:00
goto cleanup ;
}
VIR_FREE ( array ) ;
if ( ! ( array = virHashGetItems ( hash , testHashGetItemsCompValue ) ) | |
STRNEQ ( array [ 0 ] . key , " c " ) | |
STRNEQ ( array [ 0 ] . value , " 1 " ) | |
STRNEQ ( array [ 1 ] . key , " b " ) | |
STRNEQ ( array [ 1 ] . value , " 2 " ) | |
STRNEQ ( array [ 2 ] . key , " a " ) | |
STRNEQ ( array [ 2 ] . value , " 3 " ) | |
array [ 3 ] . key | | array [ 3 ] . value ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed to get items with value sort " ) ;
2011-11-18 02:04:17 +04:00
goto cleanup ;
}
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2011-11-18 02:04:17 +04:00
VIR_FREE ( array ) ;
virHashFree ( hash ) ;
return ret ;
}
2012-01-24 00:35:54 +04:00
static int
testHashEqualCompValue ( const void * value1 , const void * value2 )
{
return c_strcasecmp ( value1 , value2 ) ;
}
static int
2019-10-14 15:45:03 +03:00
testHashEqual ( const void * data G_GNUC_UNUSED )
2012-01-24 00:35:54 +04:00
{
2012-01-24 15:09:42 +04:00
virHashTablePtr hash1 , hash2 = NULL ;
2012-01-24 00:35:54 +04:00
int ret = - 1 ;
char keya [ ] = " a " ;
char keyb [ ] = " b " ;
char keyc [ ] = " c " ;
char value1_l [ ] = " m " ;
char value2_l [ ] = " n " ;
char value3_l [ ] = " o " ;
char value1_u [ ] = " M " ;
char value2_u [ ] = " N " ;
char value3_u [ ] = " O " ;
char value4_u [ ] = " P " ;
if ( ! ( hash1 = virHashCreate ( 0 , NULL ) ) | |
! ( hash2 = virHashCreate ( 0 , NULL ) ) | |
virHashAddEntry ( hash1 , keya , value1_l ) < 0 | |
virHashAddEntry ( hash1 , keyb , value2_l ) < 0 | |
virHashAddEntry ( hash1 , keyc , value3_l ) < 0 | |
virHashAddEntry ( hash2 , keya , value1_u ) < 0 | |
virHashAddEntry ( hash2 , keyb , value2_u ) < 0 ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed to create hashes " ) ;
2012-01-24 00:35:54 +04:00
goto cleanup ;
}
if ( virHashEqual ( hash1 , hash2 , testHashEqualCompValue ) ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed equal test for different number of elements " ) ;
2012-01-24 00:35:54 +04:00
goto cleanup ;
}
if ( virHashAddEntry ( hash2 , keyc , value4_u ) < 0 ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed to add element to hash2 " ) ;
2012-01-24 00:35:54 +04:00
goto cleanup ;
}
if ( virHashEqual ( hash1 , hash2 , testHashEqualCompValue ) ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed equal test for same number of elements " ) ;
2012-01-24 00:35:54 +04:00
goto cleanup ;
}
if ( virHashUpdateEntry ( hash2 , keyc , value3_u ) < 0 ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed to update element in hash2 " ) ;
2012-01-24 00:35:54 +04:00
goto cleanup ;
}
if ( ! virHashEqual ( hash1 , hash2 , testHashEqualCompValue ) ) {
2015-04-23 20:38:00 +03:00
VIR_TEST_VERBOSE ( " \n failed equal test for equal hash tables " ) ;
2012-01-24 00:35:54 +04:00
goto cleanup ;
}
ret = 0 ;
2014-03-25 10:53:44 +04:00
cleanup :
2012-01-24 00:35:54 +04:00
virHashFree ( hash1 ) ;
virHashFree ( hash2 ) ;
return ret ;
}
2011-11-18 02:04:17 +04:00
2011-04-15 15:15:37 +04:00
static int
2011-04-29 20:21:20 +04:00
mymain ( void )
2011-04-15 15:15:37 +04:00
{
int ret = 0 ;
2017-11-03 15:09:47 +03:00
# define DO_TEST_FULL(name, cmd, data, count) \
do { \
struct testInfo info = { data , count } ; \
if ( virTestRun ( name , testHash # # cmd , & info ) < 0 ) \
ret = - 1 ; \
2011-04-15 15:15:37 +04:00
} while ( 0 )
2017-11-03 15:09:47 +03:00
# define DO_TEST_DATA(name, cmd, data) \
DO_TEST_FULL ( name " ( " # data " ) " , \
cmd , \
testHash # # cmd # # data , \
2011-04-15 15:15:37 +04:00
testHashCount # # cmd # # data )
2017-11-03 15:09:47 +03:00
# define DO_TEST_COUNT(name, cmd, count) \
2011-04-15 23:17:11 +04:00
DO_TEST_FULL ( name " ( " # count " ) " , cmd , NULL , count )
2017-11-03 15:09:47 +03:00
# define DO_TEST(name, cmd) \
2011-04-15 23:17:11 +04:00
DO_TEST_FULL ( name , cmd , NULL , - 1 )
DO_TEST_COUNT ( " Grow " , Grow , 1 ) ;
DO_TEST_COUNT ( " Grow " , Grow , 10 ) ;
DO_TEST_COUNT ( " Grow " , Grow , 42 ) ;
DO_TEST ( " Update " , Update ) ;
DO_TEST ( " Remove " , Remove ) ;
2011-04-15 15:15:37 +04:00
DO_TEST_DATA ( " Remove in ForEach " , RemoveForEach , Some ) ;
DO_TEST_DATA ( " Remove in ForEach " , RemoveForEach , All ) ;
2011-04-15 23:17:11 +04:00
DO_TEST ( " Steal " , Steal ) ;
DO_TEST ( " RemoveSet " , RemoveSet ) ;
DO_TEST ( " Search " , Search ) ;
2011-11-18 02:04:17 +04:00
DO_TEST ( " GetItems " , GetItems ) ;
2012-01-24 00:35:54 +04:00
DO_TEST ( " Equal " , Equal ) ;
2011-04-15 15:15:37 +04:00
return ( ret = = 0 ) ? EXIT_SUCCESS : EXIT_FAILURE ;
}
2017-03-29 17:45:42 +03:00
VIR_TEST_MAIN ( mymain )