2008-08-08 14:09:19 +04:00
# include <string.h>
# include <libxml/parser.h>
# include <libxml/dict.h>
/* #define WITH_PRINT */
2008-08-08 16:03:22 +04:00
static const char * seeds1 [ ] = {
2008-08-08 14:09:19 +04:00
" a " , " b " , " c " ,
" d " , " e " , " f " ,
" g " , " h " , " i " ,
" j " , " k " , " l " ,
NULL
} ;
2008-08-08 16:03:22 +04:00
static const char * seeds2 [ ] = {
" m " , " n " , " o " ,
" p " , " q " , " r " ,
" s " , " t " , " u " ,
" v " , " w " , " x " ,
NULL
} ;
2008-08-08 14:09:19 +04:00
# define NB_STRINGS_NS 100
# define NB_STRINGS_MAX 10000
# define NB_STRINGS_MIN 10
2008-08-08 16:03:22 +04:00
static xmlChar * strings1 [ NB_STRINGS_MAX ] ;
static xmlChar * strings2 [ NB_STRINGS_MAX ] ;
2008-08-08 14:09:19 +04:00
static const xmlChar * test1 [ NB_STRINGS_MAX ] ;
2008-08-08 16:03:22 +04:00
static const xmlChar * test2 [ NB_STRINGS_MAX ] ;
static int nbErrors = 0 ;
2008-08-08 14:09:19 +04:00
static void fill_strings ( void ) {
int i , j , k ;
/*
* That ' s a bit nasty but the output is fine and it doesn ' t take hours
* there is a small but sufficient number of duplicates , and we have
* " :xxx " and full QNames in the last NB_STRINGS_NS values
*/
2008-08-08 16:03:22 +04:00
for ( i = 0 ; seeds1 [ i ] ! = NULL ; i + + ) {
strings1 [ i ] = xmlStrdup ( ( const xmlChar * ) seeds1 [ i ] ) ;
if ( strings1 [ i ] = = NULL ) {
fprintf ( stderr , " Out of memory while generating strings1 \n " ) ;
2008-08-08 14:09:19 +04:00
exit ( 1 ) ;
}
}
for ( j = 0 , k = 0 ; i < NB_STRINGS_MAX - NB_STRINGS_NS ; i + + , j + + ) {
2008-08-08 16:03:22 +04:00
strings1 [ i ] = xmlStrncatNew ( strings1 [ j ] , strings1 [ k ] , - 1 ) ;
if ( strings1 [ i ] = = NULL ) {
fprintf ( stderr , " Out of memory while generating strings1 \n " ) ;
2008-08-08 14:09:19 +04:00
exit ( 1 ) ;
}
if ( j > = 50 ) {
j = 0 ;
k + + ;
}
}
for ( j = 0 ; ( j < 50 ) & & ( i < NB_STRINGS_MAX ) ; i + + , j + = 2 ) {
2008-08-08 16:03:22 +04:00
strings1 [ i ] = xmlStrncatNew ( strings1 [ j ] , ( const xmlChar * ) " : " , - 1 ) ;
if ( strings1 [ i ] = = NULL ) {
fprintf ( stderr , " Out of memory while generating strings1 \n " ) ;
2008-08-08 14:09:19 +04:00
exit ( 1 ) ;
}
}
for ( j = NB_STRINGS_MAX - NB_STRINGS_NS , k = 0 ;
i < NB_STRINGS_MAX ; i + + , j + + ) {
2008-08-08 16:03:22 +04:00
strings1 [ i ] = xmlStrncatNew ( strings1 [ j ] , strings1 [ k ] , - 1 ) ;
if ( strings1 [ i ] = = NULL ) {
fprintf ( stderr , " Out of memory while generating strings1 \n " ) ;
2008-08-08 14:09:19 +04:00
exit ( 1 ) ;
}
k + = 3 ;
if ( k > = 50 ) k = 0 ;
}
2008-08-08 16:03:22 +04:00
/*
* Now do the same with the second pool of strings
*/
for ( i = 0 ; seeds2 [ i ] ! = NULL ; i + + ) {
strings2 [ i ] = xmlStrdup ( ( const xmlChar * ) seeds2 [ i ] ) ;
if ( strings2 [ i ] = = NULL ) {
fprintf ( stderr , " Out of memory while generating strings2 \n " ) ;
exit ( 1 ) ;
}
}
for ( j = 0 , k = 0 ; i < NB_STRINGS_MAX - NB_STRINGS_NS ; i + + , j + + ) {
strings2 [ i ] = xmlStrncatNew ( strings2 [ j ] , strings2 [ k ] , - 1 ) ;
if ( strings2 [ i ] = = NULL ) {
fprintf ( stderr , " Out of memory while generating strings2 \n " ) ;
exit ( 1 ) ;
}
if ( j > = 50 ) {
j = 0 ;
k + + ;
}
}
for ( j = 0 ; ( j < 50 ) & & ( i < NB_STRINGS_MAX ) ; i + + , j + = 2 ) {
strings2 [ i ] = xmlStrncatNew ( strings2 [ j ] , ( const xmlChar * ) " : " , - 1 ) ;
if ( strings2 [ i ] = = NULL ) {
fprintf ( stderr , " Out of memory while generating strings2 \n " ) ;
exit ( 1 ) ;
}
}
for ( j = NB_STRINGS_MAX - NB_STRINGS_NS , k = 0 ;
i < NB_STRINGS_MAX ; i + + , j + + ) {
strings2 [ i ] = xmlStrncatNew ( strings2 [ j ] , strings2 [ k ] , - 1 ) ;
if ( strings2 [ i ] = = NULL ) {
fprintf ( stderr , " Out of memory while generating strings2 \n " ) ;
exit ( 1 ) ;
}
k + = 3 ;
if ( k > = 50 ) k = 0 ;
}
2008-08-08 14:09:19 +04:00
}
# ifdef WITH_PRINT
static void print_strings ( void ) {
int i ;
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
2008-08-08 16:03:22 +04:00
printf ( " %s \n " , strings1 [ i ] ) ;
}
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
printf ( " %s \n " , strings2 [ i ] ) ;
2008-08-08 14:09:19 +04:00
}
}
# endif
static void clean_strings ( void ) {
int i ;
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
2008-08-08 16:03:22 +04:00
if ( strings1 [ i ] ! = NULL ) /* really should not happen */
xmlFree ( strings1 [ i ] ) ;
}
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
if ( strings2 [ i ] ! = NULL ) /* really should not happen */
xmlFree ( strings2 [ i ] ) ;
2008-08-08 14:09:19 +04:00
}
}
2008-08-08 16:03:22 +04:00
/*
* This tests the sub - dictionary support
*/
static int run_test2 ( xmlDictPtr parent ) {
int i , j ;
xmlDictPtr dict ;
int ret = 0 ;
xmlChar prefix [ 40 ] ;
xmlChar * cur , * pref ;
const xmlChar * tmp ;
dict = xmlDictCreateSub ( parent ) ;
if ( dict = = NULL ) {
fprintf ( stderr , " Out of memory while creating sub-dictionary \n " ) ;
exit ( 1 ) ;
}
memset ( test2 , 0 , sizeof ( test2 ) ) ;
/*
* Fill in NB_STRINGS_MIN , at this point the dictionary should not grow
* and we allocate all those doing the fast key computations
* All the strings are based on a different seeds subset so we know
* they are allocated in the main dictionary , not coming from the parent
*/
for ( i = 0 ; i < NB_STRINGS_MIN ; i + + ) {
test2 [ i ] = xmlDictLookup ( dict , strings2 [ i ] , - 1 ) ;
if ( test2 [ i ] = = NULL ) {
fprintf ( stderr , " Failed lookup for '%s' \n " , strings2 [ i ] ) ;
ret = 1 ;
nbErrors + + ;
}
}
j = NB_STRINGS_MAX - NB_STRINGS_NS ;
/* ":foo" like strings2 */
for ( i = 0 ; i < NB_STRINGS_MIN ; i + + , j + + ) {
test2 [ j ] = xmlDictLookup ( dict , strings2 [ j ] , xmlStrlen ( strings2 [ j ] ) ) ;
if ( test2 [ j ] = = NULL ) {
fprintf ( stderr , " Failed lookup for '%s' \n " , strings2 [ j ] ) ;
ret = 1 ;
nbErrors + + ;
}
}
/* "a:foo" like strings2 */
j = NB_STRINGS_MAX - NB_STRINGS_MIN ;
for ( i = 0 ; i < NB_STRINGS_MIN ; i + + , j + + ) {
test2 [ j ] = xmlDictLookup ( dict , strings2 [ j ] , xmlStrlen ( strings2 [ j ] ) ) ;
if ( test2 [ j ] = = NULL ) {
fprintf ( stderr , " Failed lookup for '%s' \n " , strings2 [ j ] ) ;
ret = 1 ;
nbErrors + + ;
}
}
/*
* At this point allocate all the strings
* the dictionary will grow in the process , reallocate more string tables
* and switch to the better key generator
*/
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
if ( test2 [ i ] ! = NULL )
continue ;
test2 [ i ] = xmlDictLookup ( dict , strings2 [ i ] , - 1 ) ;
if ( test2 [ i ] = = NULL ) {
fprintf ( stderr , " Failed lookup for '%s' \n " , strings2 [ i ] ) ;
ret = 1 ;
nbErrors + + ;
}
}
/*
* Now we can start to test things , first that all strings2 belongs to
* the dict , and that none of them was actually allocated in the parent
*/
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
if ( ! xmlDictOwns ( dict , test2 [ i ] ) ) {
fprintf ( stderr , " Failed ownership failure for '%s' \n " ,
strings2 [ i ] ) ;
ret = 1 ;
nbErrors + + ;
}
if ( xmlDictOwns ( parent , test2 [ i ] ) ) {
fprintf ( stderr , " Failed parent ownership failure for '%s' \n " ,
strings2 [ i ] ) ;
ret = 1 ;
nbErrors + + ;
}
}
/*
* Also verify that all strings from the parent are seen from the subdict
*/
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
if ( ! xmlDictOwns ( dict , test1 [ i ] ) ) {
fprintf ( stderr , " Failed sub-ownership failure for '%s' \n " ,
strings1 [ i ] ) ;
ret = 1 ;
nbErrors + + ;
}
}
/*
* Then that another lookup to the string in sub will return the same
*/
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
if ( xmlDictLookup ( dict , strings2 [ i ] , - 1 ) ! = test2 [ i ] ) {
fprintf ( stderr , " Failed re-lookup check for %d, '%s' \n " ,
i , strings2 [ i ] ) ;
ret = 1 ;
nbErrors + + ;
}
}
/*
* But also that any lookup for a string in the parent will be provided
* as in the parent
*/
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
if ( xmlDictLookup ( dict , strings1 [ i ] , - 1 ) ! = test1 [ i ] ) {
fprintf ( stderr , " Failed parent string lookup check for %d, '%s' \n " ,
i , strings1 [ i ] ) ;
ret = 1 ;
nbErrors + + ;
}
}
/*
* check the QName lookups
*/
for ( i = NB_STRINGS_MAX - NB_STRINGS_NS ; i < NB_STRINGS_MAX ; i + + ) {
cur = strings2 [ i ] ;
pref = & prefix [ 0 ] ;
while ( * cur ! = ' : ' ) * pref + + = * cur + + ;
cur + + ;
* pref = 0 ;
tmp = xmlDictQLookup ( dict , & prefix [ 0 ] , cur ) ;
if ( xmlDictQLookup ( dict , & prefix [ 0 ] , cur ) ! = test2 [ i ] ) {
fprintf ( stderr , " Failed lookup check for '%s':'%s' \n " ,
& prefix [ 0 ] , cur ) ;
ret = 1 ;
nbErrors + + ;
}
}
/*
* check the QName lookups for strings from the parent
*/
for ( i = NB_STRINGS_MAX - NB_STRINGS_NS ; i < NB_STRINGS_MAX ; i + + ) {
cur = strings1 [ i ] ;
pref = & prefix [ 0 ] ;
while ( * cur ! = ' : ' ) * pref + + = * cur + + ;
cur + + ;
* pref = 0 ;
tmp = xmlDictQLookup ( dict , & prefix [ 0 ] , cur ) ;
if ( xmlDictQLookup ( dict , & prefix [ 0 ] , cur ) ! = test1 [ i ] ) {
fprintf ( stderr , " Failed parent lookup check for '%s':'%s' \n " ,
& prefix [ 0 ] , cur ) ;
ret = 1 ;
nbErrors + + ;
}
}
xmlDictFree ( dict ) ;
return ( ret ) ;
}
/*
* Test a single dictionary
*/
2008-08-08 14:09:19 +04:00
static int run_test1 ( void ) {
int i , j ;
xmlDictPtr dict ;
int ret = 0 ;
xmlChar prefix [ 40 ] ;
2008-08-08 16:03:22 +04:00
xmlChar * cur , * pref ;
const xmlChar * tmp ;
2008-08-08 14:09:19 +04:00
dict = xmlDictCreate ( ) ;
if ( dict = = NULL ) {
fprintf ( stderr , " Out of memory while creating dictionary \n " ) ;
exit ( 1 ) ;
}
memset ( test1 , 0 , sizeof ( test1 ) ) ;
/*
* Fill in NB_STRINGS_MIN , at this point the dictionary should not grow
* and we allocate all those doing the fast key computations
*/
for ( i = 0 ; i < NB_STRINGS_MIN ; i + + ) {
2008-08-08 16:03:22 +04:00
test1 [ i ] = xmlDictLookup ( dict , strings1 [ i ] , - 1 ) ;
2008-08-08 14:09:19 +04:00
if ( test1 [ i ] = = NULL ) {
2008-08-08 16:03:22 +04:00
fprintf ( stderr , " Failed lookup for '%s' \n " , strings1 [ i ] ) ;
2008-08-08 14:09:19 +04:00
ret = 1 ;
2008-08-08 16:03:22 +04:00
nbErrors + + ;
2008-08-08 14:09:19 +04:00
}
}
j = NB_STRINGS_MAX - NB_STRINGS_NS ;
2008-08-08 16:03:22 +04:00
/* ":foo" like strings1 */
2008-08-08 14:09:19 +04:00
for ( i = 0 ; i < NB_STRINGS_MIN ; i + + , j + + ) {
2008-08-08 16:03:22 +04:00
test1 [ j ] = xmlDictLookup ( dict , strings1 [ j ] , xmlStrlen ( strings1 [ j ] ) ) ;
2008-08-08 14:09:19 +04:00
if ( test1 [ j ] = = NULL ) {
2008-08-08 16:03:22 +04:00
fprintf ( stderr , " Failed lookup for '%s' \n " , strings1 [ j ] ) ;
2008-08-08 14:09:19 +04:00
ret = 1 ;
2008-08-08 16:03:22 +04:00
nbErrors + + ;
2008-08-08 14:09:19 +04:00
}
}
2008-08-08 16:03:22 +04:00
/* "a:foo" like strings1 */
2008-08-08 14:09:19 +04:00
j = NB_STRINGS_MAX - NB_STRINGS_MIN ;
for ( i = 0 ; i < NB_STRINGS_MIN ; i + + , j + + ) {
2008-08-08 16:03:22 +04:00
test1 [ j ] = xmlDictLookup ( dict , strings1 [ j ] , xmlStrlen ( strings1 [ j ] ) ) ;
2008-08-08 14:09:19 +04:00
if ( test1 [ j ] = = NULL ) {
2008-08-08 16:03:22 +04:00
fprintf ( stderr , " Failed lookup for '%s' \n " , strings1 [ j ] ) ;
2008-08-08 14:09:19 +04:00
ret = 1 ;
2008-08-08 16:03:22 +04:00
nbErrors + + ;
2008-08-08 14:09:19 +04:00
}
}
/*
* At this point allocate all the strings
* the dictionary will grow in the process , reallocate more string tables
* and switch to the better key generator
*/
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
if ( test1 [ i ] ! = NULL )
continue ;
2008-08-08 16:03:22 +04:00
test1 [ i ] = xmlDictLookup ( dict , strings1 [ i ] , - 1 ) ;
2008-08-08 14:09:19 +04:00
if ( test1 [ i ] = = NULL ) {
2008-08-08 16:03:22 +04:00
fprintf ( stderr , " Failed lookup for '%s' \n " , strings1 [ i ] ) ;
2008-08-08 14:09:19 +04:00
ret = 1 ;
2008-08-08 16:03:22 +04:00
nbErrors + + ;
2008-08-08 14:09:19 +04:00
}
}
/*
2008-08-08 16:03:22 +04:00
* Now we can start to test things , first that all strings1 belongs to
2008-08-08 14:09:19 +04:00
* the dict
*/
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
if ( ! xmlDictOwns ( dict , test1 [ i ] ) ) {
fprintf ( stderr , " Failed ownership failure for '%s' \n " ,
2008-08-08 16:03:22 +04:00
strings1 [ i ] ) ;
2008-08-08 14:09:19 +04:00
ret = 1 ;
2008-08-08 16:03:22 +04:00
nbErrors + + ;
2008-08-08 14:09:19 +04:00
}
}
/*
* Then that another lookup to the string will return the same
*/
for ( i = 0 ; i < NB_STRINGS_MAX ; i + + ) {
2008-08-08 16:03:22 +04:00
if ( xmlDictLookup ( dict , strings1 [ i ] , - 1 ) ! = test1 [ i ] ) {
2008-08-08 14:09:19 +04:00
fprintf ( stderr , " Failed re-lookup check for %d, '%s' \n " ,
2008-08-08 16:03:22 +04:00
i , strings1 [ i ] ) ;
2008-08-08 14:09:19 +04:00
ret = 1 ;
2008-08-08 16:03:22 +04:00
nbErrors + + ;
2008-08-08 14:09:19 +04:00
}
}
/*
* More complex , check the QName lookups
*/
for ( i = NB_STRINGS_MAX - NB_STRINGS_NS ; i < NB_STRINGS_MAX ; i + + ) {
2008-08-08 16:03:22 +04:00
cur = strings1 [ i ] ;
2008-08-08 14:09:19 +04:00
pref = & prefix [ 0 ] ;
while ( * cur ! = ' : ' ) * pref + + = * cur + + ;
cur + + ;
* pref = 0 ;
tmp = xmlDictQLookup ( dict , & prefix [ 0 ] , cur ) ;
if ( xmlDictQLookup ( dict , & prefix [ 0 ] , cur ) ! = test1 [ i ] ) {
fprintf ( stderr , " Failed lookup check for '%s':'%s' \n " ,
& prefix [ 0 ] , cur ) ;
ret = 1 ;
2008-08-08 16:03:22 +04:00
nbErrors + + ;
2008-08-08 14:09:19 +04:00
}
}
2008-08-08 16:03:22 +04:00
run_test2 ( dict ) ;
2008-08-08 14:09:19 +04:00
xmlDictFree ( dict ) ;
2008-08-08 16:03:22 +04:00
return ( ret ) ;
2008-08-08 14:09:19 +04:00
}
int main ( void )
{
int ret ;
LIBXML_TEST_VERSION
fill_strings ( ) ;
# ifdef WITH_PRINT
print_strings ( ) ;
# endif
ret = run_test1 ( ) ;
2008-08-08 16:03:22 +04:00
if ( ret = = 0 ) {
printf ( " dictionary tests succeeded %d strings \n " , 2 * NB_STRINGS_MAX ) ;
} else {
printf ( " dictionary tests failed with %d errors \n " , nbErrors ) ;
}
2008-08-08 14:09:19 +04:00
clean_strings ( ) ;
xmlCleanupParser ( ) ;
xmlMemoryDump ( ) ;
return ( ret ) ;
}